@@ -27,32 +27,28 @@ import { ToolRegistry } from "../../tool/registry"
2727
2828const log = Log . create ( { service : "server" } )
2929
30- /** Walk parent session messages backwards to find the model used in the last user message. */
31- async function resolveModel ( sessionID : SessionID ) {
32- const msgs = await Session . messages ( { sessionID } )
33- for ( let i = msgs . length - 1 ; i >= 0 ; i -- ) {
34- const info = msgs [ i ] . info
35- if ( info . role === "user" && info . model ) return info . model
36- }
37- }
38-
3930/** Create an emitter for external ToolPart updates (no-op when messageID is absent). */
4031function emitter ( opts : { sessionID : SessionID ; messageID ?: string ; tool : string } ) {
4132 const mid = opts . messageID ? MessageID . make ( opts . messageID ) : undefined
4233 const pid = mid ? PartID . ascending ( ) : undefined
43- const fn = ( state : z . infer < typeof MessageV2 . ToolState > ) =>
44- mid && pid
45- ? Session . updatePart ( {
46- id : pid ,
47- messageID : mid ,
48- sessionID : opts . sessionID ,
49- type : "tool" as const ,
50- tool : opts . tool ,
51- callID : pid ,
52- external : true ,
53- state,
54- } )
55- : undefined
34+ const fn = ( state : z . infer < typeof MessageV2 . ToolState > ) : Promise < void > => {
35+ if ( ! ( mid && pid ) ) return Promise . resolve ( )
36+ return Session . updatePart ( {
37+ id : pid ,
38+ messageID : mid ,
39+ sessionID : opts . sessionID ,
40+ type : "tool" as const ,
41+ tool : opts . tool ,
42+ callID : pid ,
43+ external : true ,
44+ state,
45+ } ) . then (
46+ ( ) => { } ,
47+ ( err ) => {
48+ log . warn ( "external part update failed" , { tool : opts . tool , error : err } )
49+ } ,
50+ )
51+ }
5652 return { mid, pid, fn }
5753}
5854
@@ -1126,15 +1122,14 @@ export const SessionRoutes = lazy(() =>
11261122 abort : c . req . raw . signal ,
11271123 messages : [ ] as MessageV2 . WithParts [ ] ,
11281124 metadata ( val : { title ?: string ; metadata ?: Record < string , unknown > } ) {
1129- emit
1130- . fn ( {
1131- status : "running" ,
1132- input : body . args ,
1133- title : val . title ,
1134- metadata : val . metadata ,
1135- time : { start : t0 } ,
1136- } )
1137- ?. catch ( ( ) => { } )
1125+ // fire-and-forget — emitter already logs on rejection
1126+ void emit . fn ( {
1127+ status : "running" ,
1128+ input : body . args ,
1129+ title : val . title ,
1130+ metadata : val . metadata ,
1131+ time : { start : t0 } ,
1132+ } )
11381133 } ,
11391134 async ask ( req : Omit < Permission . Request , "id" | "sessionID" | "tool" > ) {
11401135 await Permission . ask ( {
@@ -1304,17 +1299,18 @@ export const SessionRoutes = lazy(() =>
13041299 const timer = setInterval ( ( ) => stream . write ( "\x00OC_KEEPALIVE\x00" ) . catch ( ( ) => { } ) , 15_000 )
13051300
13061301 try {
1302+ const parts : Parameters < typeof SessionPrompt . prompt > [ 0 ] [ "parts" ] = [
1303+ { type : "text" , text : body . prompt } ,
1304+ ...( body . files ?? [ ] ) . map ( ( f ) => ( {
1305+ type : "file" as const ,
1306+ mime : f . mime ,
1307+ url : f . url ,
1308+ filename : f . filename ,
1309+ } ) ) ,
1310+ ]
13071311 const msg = await SessionPrompt . prompt ( {
13081312 sessionID : child . id ,
1309- parts : [
1310- { type : "text" , text : body . prompt } ,
1311- ...( body . files ?? [ ] ) . map ( ( f ) => ( {
1312- type : "file" as const ,
1313- mime : f . mime ,
1314- url : f . url ,
1315- filename : f . filename ,
1316- } ) ) ,
1317- ] ,
1313+ parts,
13181314 system : body . system ,
13191315 agent : body . agent ,
13201316 model,
@@ -1351,54 +1347,5 @@ export const SessionRoutes = lazy(() =>
13511347 }
13521348 } )
13531349 } ,
1354- )
1355- // Todo CRUD — create and bulk update
1356- . post (
1357- "/:sessionID/todo" ,
1358- describeRoute ( {
1359- summary : "Create session todo" ,
1360- operationId : "session.todo.create" ,
1361- responses : {
1362- 200 : {
1363- description : "Updated todo list" ,
1364- content : { "application/json" : { schema : resolver ( Todo . Info . array ( ) ) } } ,
1365- } ,
1366- ...errors ( 400 , 404 ) ,
1367- } ,
1368- } ) ,
1369- validator ( "param" , z . object ( { sessionID : SessionID . zod } ) ) ,
1370- validator ( "json" , Todo . Info ) ,
1371- async ( c ) => {
1372- const sessionID = c . req . valid ( "param" ) . sessionID
1373- await Session . get ( sessionID )
1374- const todo = c . req . valid ( "json" )
1375- const existing = await Todo . get ( sessionID )
1376- const todos = [ ...existing , todo ]
1377- await Todo . update ( { sessionID, todos } )
1378- return c . json ( todos )
1379- } ,
1380- )
1381- . put (
1382- "/:sessionID/todo" ,
1383- describeRoute ( {
1384- summary : "Update session todos" ,
1385- operationId : "session.todo.update" ,
1386- responses : {
1387- 200 : {
1388- description : "Updated todo list" ,
1389- content : { "application/json" : { schema : resolver ( Todo . Info . array ( ) ) } } ,
1390- } ,
1391- ...errors ( 400 , 404 ) ,
1392- } ,
1393- } ) ,
1394- validator ( "param" , z . object ( { sessionID : SessionID . zod } ) ) ,
1395- validator ( "json" , z . object ( { todos : Todo . Info . array ( ) } ) ) ,
1396- async ( c ) => {
1397- const sessionID = c . req . valid ( "param" ) . sessionID
1398- await Session . get ( sessionID )
1399- const body = c . req . valid ( "json" )
1400- await Todo . update ( { sessionID, todos : body . todos } )
1401- return c . json ( body . todos )
1402- } ,
14031350 ) ,
14041351)
0 commit comments