@bolt-foundry/gambit-core 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +228 -0
  2. package/cards/context.card.md +9 -0
  3. package/cards/end.card.md +10 -0
  4. package/cards/respond.card.md +10 -0
  5. package/esm/_dnt.polyfills.d.ts +99 -0
  6. package/esm/_dnt.polyfills.d.ts.map +1 -1
  7. package/esm/_dnt.polyfills.js +127 -1
  8. package/esm/deps/jsr.io/@std/path/1.1.4/constants.d.ts +1 -1
  9. package/esm/mod.d.ts +26 -2
  10. package/esm/mod.d.ts.map +1 -1
  11. package/esm/mod.js +0 -2
  12. package/esm/src/builtins.d.ts +3 -0
  13. package/esm/src/builtins.d.ts.map +1 -0
  14. package/esm/src/builtins.js +26 -0
  15. package/esm/src/loader.d.ts.map +1 -1
  16. package/esm/src/loader.js +6 -3
  17. package/esm/src/markdown.d.ts.map +1 -1
  18. package/esm/src/markdown.js +25 -4
  19. package/esm/src/openai_compat.d.ts.map +1 -1
  20. package/esm/src/openai_compat.js +92 -25
  21. package/esm/src/openresponses.d.ts +6 -0
  22. package/esm/src/openresponses.d.ts.map +1 -0
  23. package/esm/src/openresponses.js +75 -0
  24. package/esm/src/runtime.d.ts.map +1 -1
  25. package/esm/src/runtime.js +139 -35
  26. package/esm/src/state.d.ts +4 -3
  27. package/esm/src/state.d.ts.map +1 -1
  28. package/esm/src/types.d.ts +306 -33
  29. package/esm/src/types.d.ts.map +1 -1
  30. package/package.json +1 -2
  31. package/schemas/graders/contexts/conversation.ts +17 -0
  32. package/schemas/graders/contexts/turn.ts +10 -0
  33. package/schemas/graders/respond.ts +9 -0
  34. package/script/_dnt.polyfills.d.ts +99 -0
  35. package/script/_dnt.polyfills.d.ts.map +1 -1
  36. package/script/_dnt.polyfills.js +128 -0
  37. package/script/deps/jsr.io/@std/path/1.1.4/constants.d.ts +1 -1
  38. package/script/mod.d.ts +26 -2
  39. package/script/mod.d.ts.map +1 -1
  40. package/script/mod.js +1 -4
  41. package/script/src/builtins.d.ts +3 -0
  42. package/script/src/builtins.d.ts.map +1 -0
  43. package/script/src/builtins.js +63 -0
  44. package/script/src/loader.d.ts.map +1 -1
  45. package/script/src/loader.js +6 -3
  46. package/script/src/markdown.d.ts.map +1 -1
  47. package/script/src/markdown.js +25 -4
  48. package/script/src/openai_compat.d.ts.map +1 -1
  49. package/script/src/openai_compat.js +92 -25
  50. package/script/src/openresponses.d.ts +6 -0
  51. package/script/src/openresponses.d.ts.map +1 -0
  52. package/script/src/openresponses.js +81 -0
  53. package/script/src/runtime.d.ts.map +1 -1
  54. package/script/src/runtime.js +139 -35
  55. package/script/src/state.d.ts +4 -3
  56. package/script/src/state.d.ts.map +1 -1
  57. package/script/src/types.d.ts +306 -33
  58. package/script/src/types.d.ts.map +1 -1
  59. package/esm/src/providers/openrouter.d.ts +0 -8
  60. package/esm/src/providers/openrouter.d.ts.map +0 -1
  61. package/esm/src/providers/openrouter.js +0 -168
  62. package/script/src/providers/openrouter.d.ts +0 -8
  63. package/script/src/providers/openrouter.d.ts.map +0 -1
  64. package/script/src/providers/openrouter.js +0 -207
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.openResponseItemFromMessage = openResponseItemFromMessage;
4
+ exports.messageFromOpenResponseItem = messageFromOpenResponseItem;
5
+ exports.openResponseItemsFromMessages = openResponseItemsFromMessages;
6
+ exports.messagesFromOpenResponseOutput = messagesFromOpenResponseOutput;
7
+ function contentText(parts) {
8
+ return parts.map((part) => {
9
+ switch (part.type) {
10
+ case "input_text":
11
+ case "output_text":
12
+ case "text":
13
+ case "summary_text":
14
+ case "reasoning_text":
15
+ return part.text;
16
+ case "refusal":
17
+ return part.refusal;
18
+ default:
19
+ return "";
20
+ }
21
+ }).join("");
22
+ }
23
+ function openResponseItemFromMessage(message) {
24
+ return {
25
+ type: "message",
26
+ role: message.role,
27
+ content: message.content,
28
+ name: message.name,
29
+ tool_call_id: message.tool_call_id,
30
+ tool_calls: message.tool_calls,
31
+ };
32
+ }
33
+ function messageFromOpenResponseItem(item) {
34
+ switch (item.type) {
35
+ case "message":
36
+ return {
37
+ role: item.role,
38
+ content: typeof item.content === "string" || item.content === null
39
+ ? item.content
40
+ : contentText(item.content),
41
+ name: item.name,
42
+ tool_call_id: item.tool_call_id,
43
+ tool_calls: item.tool_calls,
44
+ };
45
+ case "function_call":
46
+ return {
47
+ role: "assistant",
48
+ content: null,
49
+ tool_calls: [
50
+ {
51
+ id: item.call_id,
52
+ type: "function",
53
+ function: { name: item.name, arguments: item.arguments },
54
+ },
55
+ ],
56
+ };
57
+ case "function_call_output":
58
+ return {
59
+ role: "tool",
60
+ content: item.output,
61
+ tool_call_id: item.call_id,
62
+ };
63
+ case "output_text":
64
+ return {
65
+ role: "assistant",
66
+ content: item.text,
67
+ };
68
+ case "reasoning":
69
+ case "item_reference":
70
+ default:
71
+ return null;
72
+ }
73
+ }
74
+ function openResponseItemsFromMessages(messages) {
75
+ return messages.map(openResponseItemFromMessage);
76
+ }
77
+ function messagesFromOpenResponseOutput(output) {
78
+ return output
79
+ .map(messageFromOpenResponseItem)
80
+ .filter((message) => message !== null);
81
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/src/runtime.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAEV,UAAU,EAGV,aAAa,EAGd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAc,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,IAAI,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAM1E;AAiBD,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,UAAU,KAAK,IAAI,CAAC;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,wBAAsB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAgGhE"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/src/runtime.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAEV,UAAU,EAGV,aAAa,EAKd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAc,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,IAAI,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAM1E;AAiBD,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,UAAU,KAAK,IAAI,CAAC;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,wBAAsB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAgGhE"}
@@ -193,7 +193,8 @@ function extractInitInput(state) {
193
193
  return undefined;
194
194
  for (let i = state.messages.length - 1; i >= 0; i--) {
195
195
  const msg = state.messages[i];
196
- if (msg.role === "tool" && msg.name === constants_js_1.GAMBIT_TOOL_INIT) {
196
+ if (msg.type === "message" && msg.role === "tool" &&
197
+ msg.name === constants_js_1.GAMBIT_TOOL_INIT) {
197
198
  const content = msg.content;
198
199
  if (typeof content !== "string")
199
200
  return undefined;
@@ -317,7 +318,10 @@ async function runLlmDeck(ctx) {
317
318
  const systemPrompt = buildSystemPrompt(deck);
318
319
  const refToolCallId = randomId("call");
319
320
  const messages = ctx.state?.messages
320
- ? ctx.state.messages.map(sanitizeMessage)
321
+ ? ctx.state.messages
322
+ .map(coerceToMessageItem)
323
+ .filter((item) => item !== null)
324
+ .map(sanitizeMessageItem)
321
325
  : [];
322
326
  const resumed = messages.length > 0;
323
327
  const sendInit = Boolean(inputProvided) && input !== undefined && !resumed;
@@ -334,7 +338,7 @@ async function runLlmDeck(ctx) {
334
338
  trace: ctx.trace,
335
339
  stream: ctx.stream,
336
340
  onStreamText: ctx.onStreamText,
337
- pushMessages: (msgs) => messages.push(...msgs.map(sanitizeMessage)),
341
+ pushMessages: (msgs) => messages.push(...msgs.map(sanitizeMessageItem)),
338
342
  });
339
343
  let streamingBuffer = "";
340
344
  let streamingCommitted = false;
@@ -346,7 +350,11 @@ async function runLlmDeck(ctx) {
346
350
  ctx.onStreamText?.(chunk);
347
351
  };
348
352
  if (!resumed) {
349
- messages.push(sanitizeMessage({ role: "system", content: systemPrompt }));
353
+ messages.push(sanitizeMessageItem({
354
+ type: "message",
355
+ role: "system",
356
+ content: systemPrompt,
357
+ }));
350
358
  if (sendInit) {
351
359
  ctx.trace?.({
352
360
  type: "tool.call",
@@ -356,7 +364,8 @@ async function runLlmDeck(ctx) {
356
364
  args: {},
357
365
  parentActionCallId: actionCallId,
358
366
  });
359
- messages.push(sanitizeMessage({
367
+ messages.push(sanitizeMessageItem({
368
+ type: "message",
360
369
  role: "assistant",
361
370
  content: null,
362
371
  tool_calls: [{
@@ -367,7 +376,8 @@ async function runLlmDeck(ctx) {
367
376
  arguments: "{}",
368
377
  },
369
378
  }],
370
- }), sanitizeMessage({
379
+ }), sanitizeMessageItem({
380
+ type: "message",
371
381
  role: "tool",
372
382
  name: constants_js_1.GAMBIT_TOOL_INIT,
373
383
  tool_call_id: refToolCallId,
@@ -384,7 +394,8 @@ async function runLlmDeck(ctx) {
384
394
  }
385
395
  }
386
396
  if (initialUserMessage !== undefined) {
387
- const userMessage = sanitizeMessage({
397
+ const userMessage = sanitizeMessageItem({
398
+ type: "message",
388
399
  role: "user",
389
400
  content: formatInputForUser(initialUserMessage),
390
401
  });
@@ -432,44 +443,65 @@ async function runLlmDeck(ctx) {
432
443
  stream: ctx.stream,
433
444
  messageCount: messages.length,
434
445
  toolCount: tools.length,
435
- messages: messages.map(sanitizeMessage),
446
+ messages: messages.map(sanitizeMessageItem),
436
447
  tools,
437
448
  stateMessages,
438
449
  parentActionCallId: ctx.parentActionCallId,
439
450
  });
440
- const result = await modelProvider.chat({
451
+ const result = await modelProvider.responses({
441
452
  model,
442
- messages,
453
+ input: messages,
443
454
  tools,
444
455
  stream: ctx.stream,
445
456
  state: ctx.state,
446
457
  params: toProviderParams(deck.modelParams),
447
- onStreamText: (ctx.onStreamText || deck.handlers?.onIdle)
448
- ? wrappedOnStreamText
458
+ onStreamEvent: (ctx.onStreamText || deck.handlers?.onIdle)
459
+ ? (event) => {
460
+ switch (event.type) {
461
+ case "response.output_text.delta":
462
+ wrappedOnStreamText(event.delta);
463
+ break;
464
+ case "response.refusal.delta":
465
+ if (event.delta)
466
+ wrappedOnStreamText(event.delta);
467
+ break;
468
+ case "response.refusal.done":
469
+ if (event.refusal)
470
+ wrappedOnStreamText(event.refusal);
471
+ break;
472
+ default:
473
+ break;
474
+ }
475
+ }
449
476
  : undefined,
450
477
  });
451
478
  idleController.touch();
452
- const message = result.message;
479
+ const message = messageItemFromResponse(result.output);
480
+ const toolCalls = extractToolCalls(result.output, message);
453
481
  ctx.trace?.({
454
482
  type: "model.result",
455
483
  runId,
456
484
  actionCallId,
457
485
  deckPath: deck.path,
458
486
  model,
459
- finishReason: result.finishReason,
460
- message: sanitizeMessage(message),
461
- toolCalls: result.toolCalls,
487
+ finishReason: result.finishReason ?? "stop",
488
+ message: sanitizeMessageItem(message),
489
+ toolCalls,
462
490
  stateMessages: result.updatedState?.messages?.length,
463
491
  parentActionCallId: ctx.parentActionCallId,
464
492
  });
465
493
  const computeState = (updated) => {
466
494
  const base = updated ??
467
- { runId, messages: messages.map(sanitizeMessage) };
495
+ { runId, messages: messages.map(sanitizeMessageItem) };
468
496
  const mergedMessages = base.messages && base.messages.length > 0
469
- ? base.messages.map(sanitizeMessage)
470
- : messages.map(sanitizeMessage);
497
+ ? sanitizeResponseItems(base.messages)
498
+ : messages.map(sanitizeMessageItem);
471
499
  const priorRefs = updated?.messageRefs ?? ctx.state?.messageRefs ?? [];
472
- const messageRefs = mergedMessages.map((m, idx) => priorRefs[idx] ?? { id: randomId("msg"), role: m.role });
500
+ const messageRefs = mergedMessages.map((m, idx) => priorRefs[idx] ?? {
501
+ id: randomId("msg"),
502
+ type: m.type,
503
+ role: m.type === "message" ? m.role : undefined,
504
+ });
473
505
  const feedback = updated?.feedback ?? ctx.state?.feedback;
474
506
  const traces = updated?.traces ?? ctx.state?.traces;
475
507
  return {
@@ -481,16 +513,20 @@ async function runLlmDeck(ctx) {
481
513
  traces,
482
514
  };
483
515
  };
484
- if (result.toolCalls && result.toolCalls.length > 0) {
516
+ if (toolCalls && toolCalls.length > 0) {
485
517
  let responded = false;
486
518
  let respondValue;
487
519
  let endSignal;
488
520
  const appendedMessages = [];
489
521
  if (!streamingCommitted && streamingBuffer) {
490
- messages.push(sanitizeMessage({ role: "assistant", content: streamingBuffer }));
522
+ messages.push(sanitizeMessageItem({
523
+ type: "message",
524
+ role: "assistant",
525
+ content: streamingBuffer,
526
+ }));
491
527
  streamingCommitted = true;
492
528
  }
493
- for (const call of result.toolCalls) {
529
+ for (const call of toolCalls) {
494
530
  if (respondEnabled && call.name === constants_js_1.GAMBIT_TOOL_RESPOND) {
495
531
  const status = typeof call.args?.status === "number"
496
532
  ? call.args.status
@@ -529,6 +565,7 @@ async function runLlmDeck(ctx) {
529
565
  });
530
566
  const toolContent = JSON.stringify(call.args ?? {});
531
567
  appendedMessages.push({
568
+ type: "message",
532
569
  role: "assistant",
533
570
  content: null,
534
571
  tool_calls: [{
@@ -541,6 +578,7 @@ async function runLlmDeck(ctx) {
541
578
  }],
542
579
  });
543
580
  appendedMessages.push({
581
+ type: "message",
544
582
  role: "tool",
545
583
  tool_call_id: call.id,
546
584
  name: call.name,
@@ -584,6 +622,7 @@ async function runLlmDeck(ctx) {
584
622
  });
585
623
  const toolContent = JSON.stringify(call.args ?? {});
586
624
  appendedMessages.push({
625
+ type: "message",
587
626
  role: "assistant",
588
627
  content: null,
589
628
  tool_calls: [{
@@ -596,6 +635,7 @@ async function runLlmDeck(ctx) {
596
635
  }],
597
636
  });
598
637
  appendedMessages.push({
638
+ type: "message",
599
639
  role: "tool",
600
640
  tool_call_id: call.id,
601
641
  name: call.name,
@@ -665,6 +705,7 @@ async function runLlmDeck(ctx) {
665
705
  parentActionCallId: actionCallId,
666
706
  });
667
707
  appendedMessages.push({
708
+ type: "message",
668
709
  role: "assistant",
669
710
  content: null,
670
711
  tool_calls: [{
@@ -677,13 +718,16 @@ async function runLlmDeck(ctx) {
677
718
  }],
678
719
  });
679
720
  appendedMessages.push({
721
+ type: "message",
680
722
  role: "tool",
681
723
  tool_call_id: call.id,
682
724
  name: call.name,
683
725
  content: toolResult.toolContent,
684
726
  });
685
727
  if (toolResult.extraMessages?.length) {
686
- appendedMessages.push(...toolResult.extraMessages);
728
+ appendedMessages.push(...toolResult.extraMessages
729
+ .map(coerceToMessageItem)
730
+ .filter((item) => item !== null));
687
731
  }
688
732
  ctx.trace?.({
689
733
  type: "action.end",
@@ -695,7 +739,7 @@ async function runLlmDeck(ctx) {
695
739
  });
696
740
  }
697
741
  if (appendedMessages.length) {
698
- messages.push(...appendedMessages.map(sanitizeMessage));
742
+ messages.push(...appendedMessages.map(sanitizeMessageItem));
699
743
  idleController.touch();
700
744
  }
701
745
  if (ctx.onStateUpdate) {
@@ -732,13 +776,13 @@ async function runLlmDeck(ctx) {
732
776
  throw new Error("Model stopped early (length) with no content");
733
777
  }
734
778
  if (message.content !== null && message.content !== undefined) {
735
- messages.push(sanitizeMessage(message));
779
+ messages.push(sanitizeMessageItem(message));
736
780
  if (ctx.onStateUpdate) {
737
781
  const state = computeState(result.updatedState);
738
782
  ctx.onStateUpdate(state);
739
783
  }
740
784
  if (ctx.parentActionCallId !== undefined &&
741
- (!result.toolCalls || result.toolCalls.length === 0)) {
785
+ (!toolCalls || toolCalls.length === 0)) {
742
786
  ctx.trace?.({
743
787
  type: "monolog",
744
788
  runId,
@@ -865,7 +909,7 @@ async function handleToolCall(call, ctx) {
865
909
  initialUserMessage: undefined,
866
910
  });
867
911
  if (envelope.length) {
868
- extraMessages.push(...envelope.map(sanitizeMessage));
912
+ extraMessages.push(...envelope.map(sanitizeMessageItem));
869
913
  }
870
914
  ctx.idle?.touch();
871
915
  }
@@ -944,7 +988,7 @@ async function handleToolCall(call, ctx) {
944
988
  initialUserMessage: undefined,
945
989
  });
946
990
  if (envelope.length) {
947
- extraMessages.push(...envelope.map(sanitizeMessage));
991
+ extraMessages.push(...envelope.map(sanitizeMessageItem));
948
992
  }
949
993
  ctx.idle?.touch();
950
994
  }
@@ -955,6 +999,7 @@ async function handleToolCall(call, ctx) {
955
999
  }
956
1000
  const completeEventId = randomId("event");
957
1001
  extraMessages.push({
1002
+ type: "message",
958
1003
  role: "assistant",
959
1004
  content: null,
960
1005
  tool_calls: [{
@@ -966,6 +1011,7 @@ async function handleToolCall(call, ctx) {
966
1011
  },
967
1012
  }],
968
1013
  }, {
1014
+ type: "message",
969
1015
  role: "tool",
970
1016
  tool_call_id: completeEventId,
971
1017
  name: constants_js_1.GAMBIT_TOOL_COMPLETE,
@@ -1040,6 +1086,7 @@ async function runBusyHandler(args) {
1040
1086
  logger.log(message);
1041
1087
  }
1042
1088
  return [{
1089
+ type: "message",
1043
1090
  role: "assistant",
1044
1091
  content: `${message} (elapsed ${elapsedMs}ms)`,
1045
1092
  }];
@@ -1094,8 +1141,9 @@ function createIdleController(args) {
1094
1141
  stream: args.stream,
1095
1142
  onStreamText: args.onStreamText,
1096
1143
  });
1097
- if (envelope.length)
1098
- args.pushMessages(envelope.map(sanitizeMessage));
1144
+ if (envelope.length) {
1145
+ args.pushMessages(envelope.map(sanitizeMessageItem));
1146
+ }
1099
1147
  }
1100
1148
  catch {
1101
1149
  // ignore idle handler errors
@@ -1180,6 +1228,7 @@ async function runIdleHandler(args) {
1180
1228
  logger.log(message);
1181
1229
  }
1182
1230
  return [{
1231
+ type: "message",
1183
1232
  role: "assistant",
1184
1233
  content: `${message} (idle for ${elapsedMs}ms)`,
1185
1234
  }];
@@ -1252,6 +1301,7 @@ async function maybeHandleError(args) {
1252
1301
  const callId = randomId("event");
1253
1302
  const extraMessages = [
1254
1303
  {
1304
+ type: "message",
1255
1305
  role: "assistant",
1256
1306
  content: null,
1257
1307
  tool_calls: [{
@@ -1264,6 +1314,7 @@ async function maybeHandleError(args) {
1264
1314
  }],
1265
1315
  },
1266
1316
  {
1317
+ type: "message",
1267
1318
  role: "tool",
1268
1319
  tool_call_id: callId,
1269
1320
  name: constants_js_1.GAMBIT_TOOL_COMPLETE,
@@ -1295,6 +1346,7 @@ async function maybeHandleError(args) {
1295
1346
  const callId = randomId("event");
1296
1347
  const extraMessages = [
1297
1348
  {
1349
+ type: "message",
1298
1350
  role: "assistant",
1299
1351
  content: null,
1300
1352
  tool_calls: [{
@@ -1307,6 +1359,7 @@ async function maybeHandleError(args) {
1307
1359
  }],
1308
1360
  },
1309
1361
  {
1362
+ type: "message",
1310
1363
  role: "tool",
1311
1364
  tool_call_id: callId,
1312
1365
  name: constants_js_1.GAMBIT_TOOL_COMPLETE,
@@ -1339,11 +1392,62 @@ function formatInputForUser(input) {
1339
1392
  return String(input);
1340
1393
  }
1341
1394
  }
1342
- function sanitizeMessage(msg) {
1343
- const toolCalls = msg.tool_calls && msg.tool_calls.length > 0
1344
- ? msg.tool_calls
1395
+ function sanitizeMessageItem(item) {
1396
+ const toolCalls = item.tool_calls && item.tool_calls.length > 0
1397
+ ? item.tool_calls
1345
1398
  : undefined;
1346
- return { ...msg, tool_calls: toolCalls };
1399
+ return { ...item, tool_calls: toolCalls };
1400
+ }
1401
+ function sanitizeResponseItems(items) {
1402
+ return items.map((item) => item.type === "message" ? sanitizeMessageItem(item) : item);
1403
+ }
1404
+ function coerceToMessageItem(item) {
1405
+ if (item.type === "message")
1406
+ return item;
1407
+ if (item.type === "output_text") {
1408
+ return { type: "message", role: "assistant", content: item.text };
1409
+ }
1410
+ return null;
1411
+ }
1412
+ function messageItemFromResponse(output) {
1413
+ const messageItem = output.find((item) => item.type === "message");
1414
+ if (messageItem && messageItem.type === "message")
1415
+ return messageItem;
1416
+ const textItem = output.find((item) => item.type === "output_text");
1417
+ if (textItem && textItem.type === "output_text") {
1418
+ return { type: "message", role: "assistant", content: textItem.text };
1419
+ }
1420
+ return { type: "message", role: "assistant", content: null };
1421
+ }
1422
+ function safeJsonArgs(str) {
1423
+ try {
1424
+ const parsed = JSON.parse(str);
1425
+ if (parsed && typeof parsed === "object") {
1426
+ return parsed;
1427
+ }
1428
+ }
1429
+ catch {
1430
+ // ignore bad tool args
1431
+ }
1432
+ return {};
1433
+ }
1434
+ function extractToolCalls(output, message) {
1435
+ const responseCalls = output.filter((item) => item.type === "function_call");
1436
+ if (responseCalls.length > 0) {
1437
+ return responseCalls.map((item) => ({
1438
+ id: item.call_id,
1439
+ name: item.name,
1440
+ args: safeJsonArgs(item.arguments),
1441
+ }));
1442
+ }
1443
+ const messageCalls = message.tool_calls ?? [];
1444
+ if (messageCalls.length === 0)
1445
+ return undefined;
1446
+ return messageCalls.map((call) => ({
1447
+ id: call.id,
1448
+ name: call.function.name,
1449
+ args: safeJsonArgs(call.function.arguments),
1450
+ }));
1347
1451
  }
1348
1452
  async function buildToolDefs(deck) {
1349
1453
  const defs = [];
@@ -1,7 +1,7 @@
1
- import type { ModelMessage, TraceEvent } from "./types.js";
1
+ import type { OpenResponseItem, OpenResponseMessageItem, TraceEvent } from "./types.js";
2
2
  export type SavedState = {
3
3
  runId: string;
4
- messages: Array<ModelMessage>;
4
+ messages: Array<OpenResponseItem>;
5
5
  meta?: Record<string, unknown>;
6
6
  messageRefs?: Array<MessageRef>;
7
7
  feedback?: Array<FeedbackEntry>;
@@ -11,7 +11,8 @@ export type SavedState = {
11
11
  };
12
12
  export type MessageRef = {
13
13
  id: string;
14
- role: ModelMessage["role"];
14
+ type: OpenResponseItem["type"];
15
+ role?: OpenResponseMessageItem["role"];
15
16
  };
16
17
  export type FeedbackEntry = {
17
18
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/src/state.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC3B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,iBAAiB,CAAC,EAAE,aAAa,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAclE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,QAK5D"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/src/state.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACvB,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC3B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,iBAAiB,CAAC,EAAE,aAAa,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAclE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,QAK5D"}