@bolt-foundry/gambit-core 0.8.6 → 1.0.0-rc.2
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.
- package/README.md +22 -18
- package/esm/mod.d.ts +10 -4
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +7 -1
- package/esm/src/markdown.d.ts.map +1 -1
- package/esm/src/markdown.js +1 -0
- package/esm/src/runtime.d.ts +31 -1
- package/esm/src/runtime.d.ts.map +1 -1
- package/esm/src/runtime.js +158 -174
- package/esm/src/state.d.ts.map +1 -1
- package/esm/src/state.js +3 -2
- package/esm/src/text.d.ts +2 -0
- package/esm/src/text.d.ts.map +1 -0
- package/esm/src/text.js +3 -0
- package/esm/src/types.d.ts +4 -33
- package/esm/src/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/script/mod.d.ts +10 -4
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +14 -5
- package/script/src/markdown.d.ts.map +1 -1
- package/script/src/markdown.js +1 -0
- package/script/src/runtime.d.ts +31 -1
- package/script/src/runtime.d.ts.map +1 -1
- package/script/src/runtime.js +160 -174
- package/script/src/state.d.ts.map +1 -1
- package/script/src/state.js +3 -2
- package/script/src/text.d.ts +2 -0
- package/script/src/text.d.ts.map +1 -0
- package/script/src/text.js +6 -0
- package/script/src/types.d.ts +4 -33
- package/script/src/types.d.ts.map +1 -1
package/esm/src/runtime.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as dntShim from "../_dnt.shims.js";
|
|
|
3
3
|
import * as path from "../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
4
4
|
import { DEFAULT_GUARDRAILS, DEFAULT_STATUS_DELAY_MS, GAMBIT_TOOL_CONTEXT, GAMBIT_TOOL_END, GAMBIT_TOOL_INIT, GAMBIT_TOOL_RESPOND, } from "./constants.js";
|
|
5
5
|
import { loadDeck } from "./loader.js";
|
|
6
|
+
import { joinTextParts } from "./text.js";
|
|
6
7
|
import { canReadPath, canRunCommand, canRunPath, canWritePath, intersectPermissions, resolveEffectivePermissions, } from "./permissions.js";
|
|
7
8
|
import { ExecToolUnsupportedHostError, executeBuiltinCommand, } from "./runtime_exec_host.js";
|
|
8
9
|
import { createWorkerSandboxBridge, isWorkerSandboxHostSupported, WorkerSandboxUnsupportedHostError, } from "./runtime_worker_host.js";
|
|
@@ -18,6 +19,19 @@ function randomId(prefix) {
|
|
|
18
19
|
// Keep IDs short enough for OpenAI/OpenRouter tool_call id limits (~40 chars).
|
|
19
20
|
return `${prefix}-${suffix}`;
|
|
20
21
|
}
|
|
22
|
+
export function stringifyResponseOutput(output) {
|
|
23
|
+
const parts = [];
|
|
24
|
+
for (const item of output) {
|
|
25
|
+
if (item.type !== "message" || item.role !== "assistant")
|
|
26
|
+
continue;
|
|
27
|
+
for (const content of item.content) {
|
|
28
|
+
if (content.type === "output_text") {
|
|
29
|
+
parts.push(content.text);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return parts.join("");
|
|
34
|
+
}
|
|
21
35
|
const WORKER_SANDBOX_ENV = "GAMBIT_DECK_WORKER_SANDBOX";
|
|
22
36
|
const WORKER_TIMEOUT_MESSAGE = "Timeout exceeded";
|
|
23
37
|
const RUN_CANCELED_MESSAGE = "Run canceled";
|
|
@@ -444,6 +458,7 @@ export async function runDeck(opts) {
|
|
|
444
458
|
initialUserMessage: opts.initialUserMessage,
|
|
445
459
|
parentActionCallId: opts.parentActionCallId,
|
|
446
460
|
modelProvider: opts.modelProvider,
|
|
461
|
+
modelResolver: opts.modelResolver,
|
|
447
462
|
input: resolvedInput,
|
|
448
463
|
defaultModel: opts.defaultModel,
|
|
449
464
|
modelOverride: opts.modelOverride,
|
|
@@ -476,6 +491,7 @@ export async function runDeck(opts) {
|
|
|
476
491
|
runId,
|
|
477
492
|
parentActionCallId: opts.parentActionCallId,
|
|
478
493
|
modelProvider: opts.modelProvider,
|
|
494
|
+
modelResolver: opts.modelResolver,
|
|
479
495
|
input: resolvedInput,
|
|
480
496
|
inputProvided: opts.inputProvided ?? true,
|
|
481
497
|
initialUserMessage: opts.initialUserMessage,
|
|
@@ -508,7 +524,7 @@ export async function runDeck(opts) {
|
|
|
508
524
|
const deck = opts.runtimeTools?.length
|
|
509
525
|
? {
|
|
510
526
|
...loadedDeck,
|
|
511
|
-
tools: [...loadedDeck.tools, ...opts.runtimeTools],
|
|
527
|
+
tools: Array.from([...loadedDeck.tools, ...opts.runtimeTools].reduce((byName, tool) => byName.set(tool.name, tool), new Map()).values()),
|
|
512
528
|
}
|
|
513
529
|
: loadedDeck;
|
|
514
530
|
const permissions = resolveEffectivePermissions({
|
|
@@ -569,6 +585,7 @@ export async function runDeck(opts) {
|
|
|
569
585
|
runId,
|
|
570
586
|
parentActionCallId: opts.parentActionCallId,
|
|
571
587
|
modelProvider: opts.modelProvider,
|
|
588
|
+
modelResolver: opts.modelResolver,
|
|
572
589
|
input: validatedInput,
|
|
573
590
|
inputProvided: opts.inputProvided ?? true,
|
|
574
591
|
initialUserMessage: opts.initialUserMessage,
|
|
@@ -615,6 +632,7 @@ export async function runDeck(opts) {
|
|
|
615
632
|
runId,
|
|
616
633
|
parentActionCallId: opts.parentActionCallId,
|
|
617
634
|
modelProvider: opts.modelProvider,
|
|
635
|
+
modelResolver: opts.modelResolver,
|
|
618
636
|
input: validatedInput,
|
|
619
637
|
inputProvided: opts.inputProvided ?? true,
|
|
620
638
|
initialUserMessage: opts.initialUserMessage,
|
|
@@ -652,6 +670,7 @@ export async function runDeck(opts) {
|
|
|
652
670
|
initialUserMessage: opts.initialUserMessage,
|
|
653
671
|
parentActionCallId: opts.parentActionCallId,
|
|
654
672
|
modelProvider: opts.modelProvider,
|
|
673
|
+
modelResolver: opts.modelResolver,
|
|
655
674
|
input: validatedInput,
|
|
656
675
|
defaultModel: opts.defaultModel,
|
|
657
676
|
modelOverride: opts.modelOverride,
|
|
@@ -692,6 +711,57 @@ export async function runDeck(opts) {
|
|
|
692
711
|
}
|
|
693
712
|
}
|
|
694
713
|
}
|
|
714
|
+
export async function runDeckResponses(opts) {
|
|
715
|
+
const runId = opts.runId ?? opts.state?.runId ?? randomId("run");
|
|
716
|
+
const traceEvents = [];
|
|
717
|
+
const responseEvents = [];
|
|
718
|
+
let output = [];
|
|
719
|
+
let state = opts.state;
|
|
720
|
+
let usage;
|
|
721
|
+
let finishReason;
|
|
722
|
+
const trace = (event) => {
|
|
723
|
+
traceEvents.push(event);
|
|
724
|
+
if (event.type === "model.result" &&
|
|
725
|
+
event.mode === "responses" &&
|
|
726
|
+
!event.parentActionCallId) {
|
|
727
|
+
output = event.responseItems ?? [];
|
|
728
|
+
usage = event.usage;
|
|
729
|
+
finishReason = event.finishReason;
|
|
730
|
+
}
|
|
731
|
+
if (event.type === "model.stream.event" ||
|
|
732
|
+
event.type.startsWith("response.")) {
|
|
733
|
+
responseEvents.push(event);
|
|
734
|
+
}
|
|
735
|
+
opts.trace?.(event);
|
|
736
|
+
};
|
|
737
|
+
const onStateUpdate = (nextState) => {
|
|
738
|
+
state = nextState;
|
|
739
|
+
opts.onStateUpdate?.(nextState);
|
|
740
|
+
};
|
|
741
|
+
const legacyResult = await runDeck({
|
|
742
|
+
...opts,
|
|
743
|
+
runId,
|
|
744
|
+
responsesMode: true,
|
|
745
|
+
trace,
|
|
746
|
+
onStateUpdate,
|
|
747
|
+
});
|
|
748
|
+
const effects = traceEvents.filter((event) => event.type === "action.start" ||
|
|
749
|
+
event.type === "action.end" ||
|
|
750
|
+
event.type === "tool.call" ||
|
|
751
|
+
event.type === "tool.result");
|
|
752
|
+
return {
|
|
753
|
+
runId,
|
|
754
|
+
status: "completed",
|
|
755
|
+
output,
|
|
756
|
+
traceEvents,
|
|
757
|
+
responseEvents,
|
|
758
|
+
state,
|
|
759
|
+
usage,
|
|
760
|
+
finishReason,
|
|
761
|
+
effects,
|
|
762
|
+
legacyResult,
|
|
763
|
+
};
|
|
764
|
+
}
|
|
695
765
|
function toProviderParams(params) {
|
|
696
766
|
if (!params)
|
|
697
767
|
return undefined;
|
|
@@ -718,7 +788,7 @@ function toProviderParams(params) {
|
|
|
718
788
|
return Object.keys(out).length ? out : undefined;
|
|
719
789
|
}
|
|
720
790
|
async function resolveModelChoice(args) {
|
|
721
|
-
const resolver = args.
|
|
791
|
+
const resolver = args.modelResolver?.resolveModel;
|
|
722
792
|
if (resolver) {
|
|
723
793
|
return await resolver({
|
|
724
794
|
model: args.model,
|
|
@@ -738,11 +808,8 @@ async function resolveModelChoice(args) {
|
|
|
738
808
|
}
|
|
739
809
|
return { model: args.model, params: args.params };
|
|
740
810
|
}
|
|
741
|
-
function shouldExposeProviderToolArray(
|
|
742
|
-
|
|
743
|
-
if (!normalized)
|
|
744
|
-
return true;
|
|
745
|
-
return normalized !== "codex-cli" && !normalized.startsWith("codex-cli/");
|
|
811
|
+
function shouldExposeProviderToolArray(_model) {
|
|
812
|
+
return true;
|
|
746
813
|
}
|
|
747
814
|
function resolveContextSchema(deck) {
|
|
748
815
|
return deck.contextSchema ?? deck.inputSchema;
|
|
@@ -922,7 +989,7 @@ function messagesFromResponseItems(items) {
|
|
|
922
989
|
const callNameById = new Map();
|
|
923
990
|
for (const item of items) {
|
|
924
991
|
if (item.type === "message") {
|
|
925
|
-
const text = item.content.map((part) => part.text)
|
|
992
|
+
const text = joinTextParts(item.content.map((part) => part.text));
|
|
926
993
|
messages.push({
|
|
927
994
|
role: item.role,
|
|
928
995
|
content: text || null,
|
|
@@ -1975,7 +2042,7 @@ function mapResponseOutput(output) {
|
|
|
1975
2042
|
return {
|
|
1976
2043
|
message: {
|
|
1977
2044
|
role: "assistant",
|
|
1978
|
-
content: textParts.length ? textParts
|
|
2045
|
+
content: textParts.length ? joinTextParts(textParts) : null,
|
|
1979
2046
|
},
|
|
1980
2047
|
toolCalls: toolCalls.length ? toolCalls : undefined,
|
|
1981
2048
|
};
|
|
@@ -2039,6 +2106,7 @@ async function runComputeDeck(ctx) {
|
|
|
2039
2106
|
initialUserMessage: ctx.initialUserMessage,
|
|
2040
2107
|
parentActionCallId: ctx.parentActionCallId,
|
|
2041
2108
|
modelProvider: ctx.modelProvider,
|
|
2109
|
+
modelResolver: ctx.modelResolver,
|
|
2042
2110
|
input: ctx.input,
|
|
2043
2111
|
defaultModel: ctx.defaultModel,
|
|
2044
2112
|
modelOverride: ctx.modelOverride,
|
|
@@ -2795,54 +2863,11 @@ async function runLlmDeckInWorker(ctx) {
|
|
|
2795
2863
|
ctx.onStreamText?.(msg.chunk);
|
|
2796
2864
|
return;
|
|
2797
2865
|
}
|
|
2798
|
-
if (msg.type === "model.chat.request") {
|
|
2799
|
-
(async () => {
|
|
2800
|
-
const controller = new AbortController();
|
|
2801
|
-
modelRequestControllers.set(msg.requestId, controller);
|
|
2802
|
-
try {
|
|
2803
|
-
const result = await ctx.modelProvider.chat({
|
|
2804
|
-
...msg.input,
|
|
2805
|
-
signal: mergeAbortSignals(ctx.signal, controller.signal),
|
|
2806
|
-
onStreamText: (chunk) => {
|
|
2807
|
-
worker.postMessage({
|
|
2808
|
-
type: "model.chat.stream",
|
|
2809
|
-
requestId: msg.requestId,
|
|
2810
|
-
chunk,
|
|
2811
|
-
});
|
|
2812
|
-
},
|
|
2813
|
-
});
|
|
2814
|
-
worker.postMessage({
|
|
2815
|
-
type: "model.chat.result",
|
|
2816
|
-
requestId: msg.requestId,
|
|
2817
|
-
result,
|
|
2818
|
-
});
|
|
2819
|
-
}
|
|
2820
|
-
catch (err) {
|
|
2821
|
-
worker.postMessage({
|
|
2822
|
-
type: "model.chat.error",
|
|
2823
|
-
requestId: msg.requestId,
|
|
2824
|
-
error: {
|
|
2825
|
-
source: "model",
|
|
2826
|
-
name: err instanceof Error ? err.name : undefined,
|
|
2827
|
-
message: err instanceof Error ? err.message : String(err),
|
|
2828
|
-
code: err?.code,
|
|
2829
|
-
},
|
|
2830
|
-
});
|
|
2831
|
-
}
|
|
2832
|
-
finally {
|
|
2833
|
-
modelRequestControllers.delete(msg.requestId);
|
|
2834
|
-
}
|
|
2835
|
-
})();
|
|
2836
|
-
return;
|
|
2837
|
-
}
|
|
2838
2866
|
if (msg.type === "model.responses.request") {
|
|
2839
2867
|
(async () => {
|
|
2840
2868
|
const controller = new AbortController();
|
|
2841
2869
|
modelRequestControllers.set(msg.requestId, controller);
|
|
2842
2870
|
try {
|
|
2843
|
-
if (!ctx.modelProvider.responses) {
|
|
2844
|
-
throw new Error("Responses API unavailable for current model provider");
|
|
2845
|
-
}
|
|
2846
2871
|
const result = await ctx.modelProvider.responses({
|
|
2847
2872
|
...msg.input,
|
|
2848
2873
|
signal: mergeAbortSignals(ctx.signal, controller.signal),
|
|
@@ -2885,8 +2910,8 @@ async function runLlmDeckInWorker(ctx) {
|
|
|
2885
2910
|
if (msg.type === "model.resolveModel.request") {
|
|
2886
2911
|
(async () => {
|
|
2887
2912
|
try {
|
|
2888
|
-
const result = ctx.
|
|
2889
|
-
? await ctx.
|
|
2913
|
+
const result = ctx.modelResolver?.resolveModel
|
|
2914
|
+
? await ctx.modelResolver.resolveModel(msg.input)
|
|
2890
2915
|
: {
|
|
2891
2916
|
model: Array.isArray(msg.input.model)
|
|
2892
2917
|
? msg.input.model[0]
|
|
@@ -3098,6 +3123,7 @@ async function runComputeDeckInWorker(ctx) {
|
|
|
3098
3123
|
path: req.payload.path,
|
|
3099
3124
|
input: req.payload.input,
|
|
3100
3125
|
modelProvider: ctx.modelProvider,
|
|
3126
|
+
modelResolver: ctx.modelResolver,
|
|
3101
3127
|
isRoot: false,
|
|
3102
3128
|
guardrails: ctx.guardrails,
|
|
3103
3129
|
depth: ctx.depth + 1,
|
|
@@ -3378,6 +3404,7 @@ async function runComputeDeckInProcess(ctx) {
|
|
|
3378
3404
|
path: childPath,
|
|
3379
3405
|
input: opts.input,
|
|
3380
3406
|
modelProvider: ctx.modelProvider,
|
|
3407
|
+
modelResolver: ctx.modelResolver,
|
|
3381
3408
|
isRoot: false,
|
|
3382
3409
|
guardrails: ctx.guardrails,
|
|
3383
3410
|
depth: ctx.depth + 1,
|
|
@@ -3441,8 +3468,7 @@ async function runLlmDeck(ctx) {
|
|
|
3441
3468
|
const { deck, guardrails, depth, modelProvider, input, runId, inputProvided, initialUserMessage, } = ctx;
|
|
3442
3469
|
const actionCallId = randomId("action");
|
|
3443
3470
|
const start = performance.now();
|
|
3444
|
-
const useResponses =
|
|
3445
|
-
ctx.state?.format === "responses";
|
|
3471
|
+
const useResponses = true;
|
|
3446
3472
|
const validateResponseItemEmission = createResponseItemEmissionValidator(deck);
|
|
3447
3473
|
const intermediateEmitter = ctx.parentActionCallId !== undefined
|
|
3448
3474
|
? createIntermediateChildResponseEmitter({
|
|
@@ -3597,6 +3623,7 @@ async function runLlmDeck(ctx) {
|
|
|
3597
3623
|
model: modelCandidate,
|
|
3598
3624
|
params: toProviderParams(deck.modelParams),
|
|
3599
3625
|
modelProvider,
|
|
3626
|
+
modelResolver: ctx.modelResolver,
|
|
3600
3627
|
deckPath: deck.path,
|
|
3601
3628
|
});
|
|
3602
3629
|
const model = resolved.model;
|
|
@@ -3625,144 +3652,93 @@ async function runLlmDeck(ctx) {
|
|
|
3625
3652
|
parentActionCallId: ctx.parentActionCallId,
|
|
3626
3653
|
});
|
|
3627
3654
|
let responseOutputItems;
|
|
3628
|
-
const responses = modelProvider.responses;
|
|
3629
3655
|
const projectedToolCalls = new Set();
|
|
3630
3656
|
const projectedToolResults = new Set();
|
|
3631
3657
|
const projectedToolNames = new Map();
|
|
3632
3658
|
const canonicalizeStreamEvent = createCanonicalStreamEventController();
|
|
3633
|
-
const result = (
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
},
|
|
3646
|
-
state: ctx.state,
|
|
3647
|
-
deckPath: deck.path,
|
|
3648
|
-
signal: ctx.signal,
|
|
3649
|
-
onStreamEvent: (ctx.trace || ctx.onStreamText || deck.handlers?.onIdle)
|
|
3650
|
-
? (event) => {
|
|
3651
|
-
const normalizedEvent = validateResponseEventItems(event, validateResponseItemEmission);
|
|
3652
|
-
const streamEvent = canonicalizeStreamEvent(normalizedEvent);
|
|
3653
|
-
if (!streamEvent)
|
|
3654
|
-
return;
|
|
3655
|
-
if (ctx.trace) {
|
|
3656
|
-
const handledAsResponse = traceOpenResponsesStreamEvent({
|
|
3657
|
-
streamEvent,
|
|
3658
|
-
runId,
|
|
3659
|
-
actionCallId,
|
|
3660
|
-
deckPath: deck.path,
|
|
3661
|
-
model,
|
|
3662
|
-
parentActionCallId: ctx.parentActionCallId,
|
|
3663
|
-
trace: ctx.trace,
|
|
3664
|
-
});
|
|
3665
|
-
if (!handledAsResponse) {
|
|
3666
|
-
ctx.trace({
|
|
3667
|
-
type: "model.stream.event",
|
|
3668
|
-
runId,
|
|
3669
|
-
actionCallId,
|
|
3670
|
-
deckPath: deck.path,
|
|
3671
|
-
model,
|
|
3672
|
-
event: streamEvent,
|
|
3673
|
-
parentActionCallId: ctx.parentActionCallId,
|
|
3674
|
-
});
|
|
3675
|
-
}
|
|
3676
|
-
projectStreamToolTraceEvents({
|
|
3677
|
-
streamEvent,
|
|
3678
|
-
runId,
|
|
3679
|
-
parentActionCallId: actionCallId,
|
|
3680
|
-
trace: ctx.trace,
|
|
3681
|
-
emittedCalls: projectedToolCalls,
|
|
3682
|
-
emittedResults: projectedToolResults,
|
|
3683
|
-
toolNames: projectedToolNames,
|
|
3684
|
-
});
|
|
3685
|
-
}
|
|
3686
|
-
const eventType = typeof streamEvent.type === "string"
|
|
3687
|
-
? streamEvent.type
|
|
3688
|
-
: "";
|
|
3689
|
-
if (eventType === "response.output_text.delta") {
|
|
3690
|
-
sawDelta = true;
|
|
3691
|
-
const delta = typeof streamEvent.delta === "string"
|
|
3692
|
-
? streamEvent.delta
|
|
3693
|
-
: "";
|
|
3694
|
-
if (delta)
|
|
3695
|
-
wrappedOnStreamText(delta);
|
|
3696
|
-
}
|
|
3697
|
-
else if (eventType === "response.output_text.done" && !sawDelta) {
|
|
3698
|
-
const text = typeof streamEvent.text === "string"
|
|
3699
|
-
? streamEvent.text
|
|
3700
|
-
: "";
|
|
3701
|
-
if (text)
|
|
3702
|
-
wrappedOnStreamText(text);
|
|
3703
|
-
}
|
|
3704
|
-
}
|
|
3705
|
-
: undefined,
|
|
3706
|
-
});
|
|
3707
|
-
responseOutputItems = validateResponseOutputItems(response.output ?? [], validateResponseItemEmission, "response.output");
|
|
3708
|
-
const mapped = mapResponseOutput(responseOutputItems);
|
|
3709
|
-
return {
|
|
3710
|
-
message: mapped.message,
|
|
3711
|
-
finishReason: mapped.toolCalls?.length ? "tool_calls" : "stop",
|
|
3712
|
-
toolCalls: mapped.toolCalls,
|
|
3713
|
-
usage: response.usage,
|
|
3714
|
-
updatedState: response.updatedState,
|
|
3715
|
-
};
|
|
3716
|
-
})()
|
|
3717
|
-
: await modelProvider.chat({
|
|
3718
|
-
model,
|
|
3719
|
-
messages,
|
|
3720
|
-
tools,
|
|
3721
|
-
stream: ctx.stream,
|
|
3659
|
+
const result = await (async () => {
|
|
3660
|
+
const responseItems = responseItemsFromMessages(messages);
|
|
3661
|
+
let sawDelta = false;
|
|
3662
|
+
const response = await modelProvider.responses({
|
|
3663
|
+
request: {
|
|
3664
|
+
model,
|
|
3665
|
+
input: responseItems,
|
|
3666
|
+
tools: providerResponseTools,
|
|
3667
|
+
text: responseTextConfig,
|
|
3668
|
+
stream: ctx.stream,
|
|
3669
|
+
params: providerParams,
|
|
3670
|
+
},
|
|
3722
3671
|
state: ctx.state,
|
|
3723
3672
|
deckPath: deck.path,
|
|
3724
3673
|
signal: ctx.signal,
|
|
3725
|
-
|
|
3726
|
-
onStreamText: (ctx.onStreamText || deck.handlers?.onIdle)
|
|
3727
|
-
? wrappedOnStreamText
|
|
3728
|
-
: undefined,
|
|
3729
|
-
onStreamEvent: ctx.trace
|
|
3674
|
+
onStreamEvent: (ctx.trace || ctx.onStreamText || deck.handlers?.onIdle)
|
|
3730
3675
|
? (event) => {
|
|
3731
|
-
const
|
|
3676
|
+
const normalizedEvent = validateResponseEventItems(event, validateResponseItemEmission);
|
|
3677
|
+
const streamEvent = canonicalizeStreamEvent(normalizedEvent);
|
|
3732
3678
|
if (!streamEvent)
|
|
3733
3679
|
return;
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
actionCallId,
|
|
3738
|
-
deckPath: deck.path,
|
|
3739
|
-
model,
|
|
3740
|
-
parentActionCallId: ctx.parentActionCallId,
|
|
3741
|
-
trace: ctx.trace,
|
|
3742
|
-
});
|
|
3743
|
-
if (!handledAsResponse) {
|
|
3744
|
-
ctx.trace?.({
|
|
3745
|
-
type: "model.stream.event",
|
|
3680
|
+
if (ctx.trace) {
|
|
3681
|
+
const handledAsResponse = traceOpenResponsesStreamEvent({
|
|
3682
|
+
streamEvent,
|
|
3746
3683
|
runId,
|
|
3747
3684
|
actionCallId,
|
|
3748
3685
|
deckPath: deck.path,
|
|
3749
3686
|
model,
|
|
3750
|
-
event: streamEvent,
|
|
3751
3687
|
parentActionCallId: ctx.parentActionCallId,
|
|
3688
|
+
trace: ctx.trace,
|
|
3689
|
+
});
|
|
3690
|
+
if (!handledAsResponse) {
|
|
3691
|
+
ctx.trace({
|
|
3692
|
+
type: "model.stream.event",
|
|
3693
|
+
runId,
|
|
3694
|
+
actionCallId,
|
|
3695
|
+
deckPath: deck.path,
|
|
3696
|
+
model,
|
|
3697
|
+
event: streamEvent,
|
|
3698
|
+
parentActionCallId: ctx.parentActionCallId,
|
|
3699
|
+
});
|
|
3700
|
+
}
|
|
3701
|
+
projectStreamToolTraceEvents({
|
|
3702
|
+
streamEvent,
|
|
3703
|
+
runId,
|
|
3704
|
+
parentActionCallId: actionCallId,
|
|
3705
|
+
trace: ctx.trace,
|
|
3706
|
+
emittedCalls: projectedToolCalls,
|
|
3707
|
+
emittedResults: projectedToolResults,
|
|
3708
|
+
toolNames: projectedToolNames,
|
|
3752
3709
|
});
|
|
3753
3710
|
}
|
|
3754
|
-
|
|
3755
|
-
streamEvent
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3711
|
+
const eventType = typeof streamEvent.type === "string"
|
|
3712
|
+
? streamEvent.type
|
|
3713
|
+
: "";
|
|
3714
|
+
if (eventType === "response.output_text.delta") {
|
|
3715
|
+
sawDelta = true;
|
|
3716
|
+
const delta = typeof streamEvent.delta === "string"
|
|
3717
|
+
? streamEvent.delta
|
|
3718
|
+
: "";
|
|
3719
|
+
if (delta)
|
|
3720
|
+
wrappedOnStreamText(delta);
|
|
3721
|
+
}
|
|
3722
|
+
else if (eventType === "response.output_text.done" && !sawDelta) {
|
|
3723
|
+
const text = typeof streamEvent.text === "string"
|
|
3724
|
+
? streamEvent.text
|
|
3725
|
+
: "";
|
|
3726
|
+
if (text)
|
|
3727
|
+
wrappedOnStreamText(text);
|
|
3728
|
+
}
|
|
3763
3729
|
}
|
|
3764
3730
|
: undefined,
|
|
3765
3731
|
});
|
|
3732
|
+
responseOutputItems = validateResponseOutputItems(response.output ?? [], validateResponseItemEmission, "response.output");
|
|
3733
|
+
const mapped = mapResponseOutput(responseOutputItems);
|
|
3734
|
+
return {
|
|
3735
|
+
message: mapped.message,
|
|
3736
|
+
finishReason: mapped.toolCalls?.length ? "tool_calls" : "stop",
|
|
3737
|
+
toolCalls: mapped.toolCalls,
|
|
3738
|
+
usage: response.usage,
|
|
3739
|
+
updatedState: response.updatedState,
|
|
3740
|
+
};
|
|
3741
|
+
})();
|
|
3766
3742
|
idleController.touch();
|
|
3767
3743
|
let message = result.message;
|
|
3768
3744
|
ctx.trace?.({
|
|
@@ -4665,6 +4641,7 @@ async function handleToolCall(call, ctx) {
|
|
|
4665
4641
|
path: action.path,
|
|
4666
4642
|
input: actionInput,
|
|
4667
4643
|
modelProvider: ctx.modelProvider,
|
|
4644
|
+
modelResolver: ctx.modelResolver,
|
|
4668
4645
|
isRoot: false,
|
|
4669
4646
|
guardrails: ctx.guardrails,
|
|
4670
4647
|
depth: ctx.depth + 1,
|
|
@@ -4764,6 +4741,7 @@ async function handleToolCall(call, ctx) {
|
|
|
4764
4741
|
path: action.path,
|
|
4765
4742
|
input: actionInput,
|
|
4766
4743
|
modelProvider: ctx.modelProvider,
|
|
4744
|
+
modelResolver: ctx.modelResolver,
|
|
4767
4745
|
isRoot: false,
|
|
4768
4746
|
guardrails: ctx.guardrails,
|
|
4769
4747
|
depth: ctx.depth + 1,
|
|
@@ -4813,6 +4791,7 @@ async function handleToolCall(call, ctx) {
|
|
|
4813
4791
|
parentActionCallId: ctx.parentActionCallId,
|
|
4814
4792
|
handlerPath: busyCfg.path,
|
|
4815
4793
|
modelProvider: ctx.modelProvider,
|
|
4794
|
+
modelResolver: ctx.modelResolver,
|
|
4816
4795
|
guardrails: ctx.guardrails,
|
|
4817
4796
|
depth: ctx.depth,
|
|
4818
4797
|
defaultModel: ctx.defaultModel,
|
|
@@ -4914,6 +4893,7 @@ async function handleToolCall(call, ctx) {
|
|
|
4914
4893
|
parentActionCallId: ctx.parentActionCallId,
|
|
4915
4894
|
handlerPath: busyCfg.path,
|
|
4916
4895
|
modelProvider: ctx.modelProvider,
|
|
4896
|
+
modelResolver: ctx.modelResolver,
|
|
4917
4897
|
guardrails: ctx.guardrails,
|
|
4918
4898
|
depth: ctx.depth,
|
|
4919
4899
|
defaultModel: ctx.defaultModel,
|
|
@@ -5003,6 +4983,7 @@ async function runBusyHandler(args) {
|
|
|
5003
4983
|
path: args.handlerPath,
|
|
5004
4984
|
input,
|
|
5005
4985
|
modelProvider: args.modelProvider,
|
|
4986
|
+
modelResolver: args.modelResolver,
|
|
5006
4987
|
isRoot: false,
|
|
5007
4988
|
guardrails: args.guardrails,
|
|
5008
4989
|
depth: args.depth + 1,
|
|
@@ -5096,6 +5077,7 @@ function createIdleController(args) {
|
|
|
5096
5077
|
runId: args.runId,
|
|
5097
5078
|
parentActionCallId: args.parentActionCallId,
|
|
5098
5079
|
modelProvider: args.modelProvider,
|
|
5080
|
+
modelResolver: args.modelResolver,
|
|
5099
5081
|
guardrails: args.guardrails,
|
|
5100
5082
|
depth: args.depth,
|
|
5101
5083
|
defaultModel: args.defaultModel,
|
|
@@ -5170,6 +5152,7 @@ async function runIdleHandler(args) {
|
|
|
5170
5152
|
path: args.handlerPath,
|
|
5171
5153
|
input,
|
|
5172
5154
|
modelProvider: args.modelProvider,
|
|
5155
|
+
modelResolver: args.modelResolver,
|
|
5173
5156
|
isRoot: false,
|
|
5174
5157
|
guardrails: args.guardrails,
|
|
5175
5158
|
depth: args.depth + 1,
|
|
@@ -5249,6 +5232,7 @@ async function maybeHandleError(args) {
|
|
|
5249
5232
|
path: handlerPath,
|
|
5250
5233
|
input: envelopeInput,
|
|
5251
5234
|
modelProvider: args.ctx.modelProvider,
|
|
5235
|
+
modelResolver: args.ctx.modelResolver,
|
|
5252
5236
|
isRoot: false,
|
|
5253
5237
|
guardrails: args.ctx.guardrails,
|
|
5254
5238
|
depth: args.ctx.depth + 1,
|
package/esm/src/state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/src/state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/src/state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC9B,KAAK,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC5B,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;IAC3B,MAAM,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;CAC7C,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;AA2CF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAsBlE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,QAK5D"}
|
package/esm/src/state.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as dntShim from "../_dnt.shims.js";
|
|
2
2
|
import * as path from "../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
3
|
+
import { joinTextParts } from "./text.js";
|
|
3
4
|
function deriveMessagesFromItems(items) {
|
|
4
5
|
const messages = [];
|
|
5
6
|
const callNameById = new Map();
|
|
@@ -7,10 +8,10 @@ function deriveMessagesFromItems(items) {
|
|
|
7
8
|
if (item.type === "message") {
|
|
8
9
|
const text = item.content
|
|
9
10
|
.map((part) => part.text)
|
|
10
|
-
.
|
|
11
|
+
.filter(Boolean);
|
|
11
12
|
messages.push({
|
|
12
13
|
role: item.role,
|
|
13
|
-
content: text
|
|
14
|
+
content: text.length ? joinTextParts(text) : null,
|
|
14
15
|
});
|
|
15
16
|
continue;
|
|
16
17
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/src/text.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM,CAE1D"}
|
package/esm/src/text.js
ADDED
package/esm/src/types.d.ts
CHANGED
|
@@ -119,6 +119,7 @@ export type BaseDefinition = {
|
|
|
119
119
|
export type DeckDefinition<Input = unknown> = BaseDefinition & {
|
|
120
120
|
kind: "gambit.deck";
|
|
121
121
|
modelParams?: ModelParams;
|
|
122
|
+
workloop?: unknown;
|
|
122
123
|
tools?: ReadonlyArray<ExternalToolDefinition>;
|
|
123
124
|
responseItemExtensions?: ReadonlyArray<ResponseItemExtensionDefinition>;
|
|
124
125
|
handlers?: HandlersConfig;
|
|
@@ -559,7 +560,7 @@ export type ResponseEvent = {
|
|
|
559
560
|
payload: Record<string, JSONValue>;
|
|
560
561
|
};
|
|
561
562
|
export type ModelProvider = {
|
|
562
|
-
responses
|
|
563
|
+
responses: (input: {
|
|
563
564
|
request: CreateResponseRequest;
|
|
564
565
|
state?: SavedState;
|
|
565
566
|
deckPath?: string;
|
|
@@ -567,6 +568,8 @@ export type ModelProvider = {
|
|
|
567
568
|
onStreamEvent?: (event: ResponseEvent) => void;
|
|
568
569
|
onTraceEvent?: (event: ProviderTraceEvent) => void;
|
|
569
570
|
}) => Promise<CreateResponseResponse>;
|
|
571
|
+
};
|
|
572
|
+
export type ModelResolver = {
|
|
570
573
|
resolveModel?: (input: {
|
|
571
574
|
model: string | Array<string>;
|
|
572
575
|
params?: Record<string, unknown>;
|
|
@@ -575,38 +578,6 @@ export type ModelProvider = {
|
|
|
575
578
|
model: string;
|
|
576
579
|
params?: Record<string, unknown>;
|
|
577
580
|
}>;
|
|
578
|
-
chat: (input: {
|
|
579
|
-
model: string;
|
|
580
|
-
messages: Array<ModelMessage>;
|
|
581
|
-
tools?: Array<ToolDefinition>;
|
|
582
|
-
stream?: boolean;
|
|
583
|
-
state?: SavedState;
|
|
584
|
-
deckPath?: string;
|
|
585
|
-
signal?: AbortSignal;
|
|
586
|
-
onStreamText?: (chunk: string) => void;
|
|
587
|
-
onStreamEvent?: (event: Record<string, JSONValue>) => void;
|
|
588
|
-
onTraceEvent?: (event: ProviderTraceEvent) => void;
|
|
589
|
-
/**
|
|
590
|
-
* Provider-specific pass-through parameters (e.g. OpenAI chat completion
|
|
591
|
-
* fields like temperature/max_tokens).
|
|
592
|
-
*/
|
|
593
|
-
params?: Record<string, unknown>;
|
|
594
|
-
}) => Promise<{
|
|
595
|
-
message: ModelMessage;
|
|
596
|
-
finishReason: "stop" | "tool_calls" | "length";
|
|
597
|
-
toolCalls?: Array<{
|
|
598
|
-
id: string;
|
|
599
|
-
name: string;
|
|
600
|
-
args: Record<string, JSONValue>;
|
|
601
|
-
}>;
|
|
602
|
-
updatedState?: SavedState;
|
|
603
|
-
usage?: {
|
|
604
|
-
promptTokens: number;
|
|
605
|
-
completionTokens: number;
|
|
606
|
-
totalTokens: number;
|
|
607
|
-
reasoningTokens?: number;
|
|
608
|
-
};
|
|
609
|
-
}>;
|
|
610
581
|
};
|
|
611
582
|
export type ProviderTraceEvent = TraceEvent | (Omit<Extract<TraceEvent, {
|
|
612
583
|
type: "tool.call";
|