@dogpile/sdk 0.5.0 → 0.6.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.
- package/CHANGELOG.md +27 -0
- package/dist/browser/index.js +3992 -4997
- package/dist/browser/index.js.map +1 -1
- package/dist/providers/openai-compatible.d.ts.map +1 -1
- package/dist/providers/openai-compatible.js +5 -1
- package/dist/providers/openai-compatible.js.map +1 -1
- package/dist/runtime/broadcast.d.ts +1 -0
- package/dist/runtime/broadcast.d.ts.map +1 -1
- package/dist/runtime/broadcast.js +132 -69
- package/dist/runtime/broadcast.js.map +1 -1
- package/dist/runtime/coordinator.d.ts +4 -2
- package/dist/runtime/coordinator.d.ts.map +1 -1
- package/dist/runtime/coordinator.js +114 -39
- package/dist/runtime/coordinator.js.map +1 -1
- package/dist/runtime/defaults.d.ts.map +1 -1
- package/dist/runtime/defaults.js +2 -1
- package/dist/runtime/defaults.js.map +1 -1
- package/dist/runtime/engine.d.ts.map +1 -1
- package/dist/runtime/engine.js +54 -34
- package/dist/runtime/engine.js.map +1 -1
- package/dist/runtime/model.d.ts.map +1 -1
- package/dist/runtime/model.js +6 -3
- package/dist/runtime/model.js.map +1 -1
- package/dist/runtime/redaction.d.ts +13 -0
- package/dist/runtime/redaction.d.ts.map +1 -0
- package/dist/runtime/redaction.js +278 -0
- package/dist/runtime/redaction.js.map +1 -0
- package/dist/runtime/sanitization.d.ts +4 -0
- package/dist/runtime/sanitization.d.ts.map +1 -0
- package/dist/runtime/sanitization.js +63 -0
- package/dist/runtime/sanitization.js.map +1 -0
- package/dist/runtime/shared.d.ts +1 -0
- package/dist/runtime/shared.d.ts.map +1 -1
- package/dist/runtime/shared.js +128 -65
- package/dist/runtime/shared.js.map +1 -1
- package/dist/runtime/tools/built-in.d.ts +2 -0
- package/dist/runtime/tools/built-in.d.ts.map +1 -1
- package/dist/runtime/tools/built-in.js +153 -15
- package/dist/runtime/tools/built-in.js.map +1 -1
- package/dist/runtime/tools.d.ts.map +1 -1
- package/dist/runtime/tools.js +29 -7
- package/dist/runtime/tools.js.map +1 -1
- package/dist/runtime/validation.d.ts.map +1 -1
- package/dist/runtime/validation.js +3 -0
- package/dist/runtime/validation.js.map +1 -1
- package/dist/types/events.d.ts +3 -3
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/replay.d.ts +3 -1
- package/dist/types/replay.d.ts.map +1 -1
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -1
- package/src/providers/openai-compatible.ts +5 -1
- package/src/runtime/broadcast.ts +156 -72
- package/src/runtime/coordinator.ts +143 -47
- package/src/runtime/defaults.ts +2 -1
- package/src/runtime/engine.ts +77 -40
- package/src/runtime/model.ts +6 -3
- package/src/runtime/redaction.ts +355 -0
- package/src/runtime/sanitization.ts +81 -0
- package/src/runtime/shared.ts +152 -68
- package/src/runtime/tools/built-in.ts +168 -15
- package/src/runtime/tools.ts +39 -8
- package/src/runtime/validation.ts +3 -0
- package/src/types/events.ts +3 -3
- package/src/types/replay.ts +3 -1
- package/src/types.ts +20 -0
|
@@ -60,6 +60,8 @@ export interface WebSearchToolAdapterOptions {
|
|
|
60
60
|
readonly fetch?: WebSearchFetch;
|
|
61
61
|
readonly headers?: HeadersInit;
|
|
62
62
|
readonly defaultMaxResults?: number;
|
|
63
|
+
readonly allowHosts?: readonly string[];
|
|
64
|
+
readonly allowPrivateNetwork?: boolean;
|
|
63
65
|
readonly identity?: BuiltInDogpileToolIdentityOptions;
|
|
64
66
|
readonly permissions?: readonly RuntimeToolPermission[];
|
|
65
67
|
readonly buildRequest?: WebSearchFetchRequestBuilder;
|
|
@@ -271,11 +273,15 @@ export function createWebSearchToolAdapter(
|
|
|
271
273
|
options: WebSearchToolAdapterOptions
|
|
272
274
|
): RuntimeToolAdapterContract<WebSearchToolInput, WebSearchToolOutput> {
|
|
273
275
|
const identity = mergeIdentity(webSearchIdentity, options.identity);
|
|
276
|
+
const endpointUrl = new URL(String(options.endpoint));
|
|
277
|
+
const allowedHosts = normalizeAllowedHosts(options.allowHosts ?? [endpointUrl.hostname]);
|
|
278
|
+
const allowPrivateNetwork = options.allowPrivateNetwork ?? false;
|
|
279
|
+
const permissions = options.permissions ?? webSearchPermissionsFor(allowedHosts, allowPrivateNetwork);
|
|
274
280
|
|
|
275
281
|
return normalizeBuiltInDogpileTool({
|
|
276
282
|
name: "webSearch",
|
|
277
283
|
...(options.identity ? { identity: options.identity } : {}),
|
|
278
|
-
|
|
284
|
+
permissions,
|
|
279
285
|
async execute(input, context): Promise<RuntimeToolResult<WebSearchToolOutput>> {
|
|
280
286
|
const fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
281
287
|
|
|
@@ -295,6 +301,15 @@ export function createWebSearchToolAdapter(
|
|
|
295
301
|
const request = options.buildRequest
|
|
296
302
|
? options.buildRequest(input, context)
|
|
297
303
|
: defaultWebSearchRequest(options, input, context);
|
|
304
|
+
const policyError = validateWebSearchRequestPolicy(request.url, allowedHosts, allowPrivateNetwork);
|
|
305
|
+
if (policyError !== undefined) {
|
|
306
|
+
return {
|
|
307
|
+
type: "error",
|
|
308
|
+
toolCallId: context.toolCallId,
|
|
309
|
+
tool: identity,
|
|
310
|
+
error: policyError
|
|
311
|
+
};
|
|
312
|
+
}
|
|
298
313
|
const response = await fetchImplementation(request.url, {
|
|
299
314
|
...request.init,
|
|
300
315
|
...(context.abortSignal ? { signal: context.abortSignal } : {})
|
|
@@ -616,10 +631,19 @@ async function executeSandboxWithPolicy(
|
|
|
616
631
|
} satisfies RuntimeToolAdapterError;
|
|
617
632
|
}
|
|
618
633
|
|
|
619
|
-
const
|
|
634
|
+
const policy = createToolPolicyAbortController(context.abortSignal);
|
|
635
|
+
const executionContext: RuntimeToolExecutionContext = {
|
|
636
|
+
...context,
|
|
637
|
+
abortSignal: policy.signal
|
|
638
|
+
};
|
|
639
|
+
const execution = Promise.resolve().then(() => execute(input, executionContext));
|
|
620
640
|
|
|
621
641
|
if (timeoutMs === undefined && context.abortSignal === undefined) {
|
|
622
|
-
|
|
642
|
+
try {
|
|
643
|
+
return await execution;
|
|
644
|
+
} finally {
|
|
645
|
+
policy.cleanup();
|
|
646
|
+
}
|
|
623
647
|
}
|
|
624
648
|
|
|
625
649
|
return await new Promise<CodeExecToolOutput>((resolve, reject) => {
|
|
@@ -627,31 +651,33 @@ async function executeSandboxWithPolicy(
|
|
|
627
651
|
|
|
628
652
|
const cleanup = (): void => {
|
|
629
653
|
if (timeoutId !== undefined) clearTimeout(timeoutId);
|
|
630
|
-
|
|
654
|
+
policy.signal.removeEventListener("abort", abortHandler);
|
|
655
|
+
policy.cleanup();
|
|
631
656
|
};
|
|
632
657
|
|
|
633
658
|
const abortHandler = (): void => {
|
|
634
659
|
cleanup();
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
660
|
+
const reason = policy.signal.reason;
|
|
661
|
+
reject(isRuntimeToolAdapterError(reason)
|
|
662
|
+
? reason
|
|
663
|
+
: {
|
|
664
|
+
code: "aborted",
|
|
665
|
+
message: "Code execution was aborted.",
|
|
666
|
+
retryable: true
|
|
667
|
+
} satisfies RuntimeToolAdapterError);
|
|
640
668
|
};
|
|
641
669
|
|
|
642
|
-
|
|
643
|
-
context.abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
644
|
-
}
|
|
670
|
+
policy.signal.addEventListener("abort", abortHandler, { once: true });
|
|
645
671
|
|
|
646
672
|
if (timeoutMs !== undefined) {
|
|
647
673
|
timeoutId = setTimeout(() => {
|
|
648
|
-
|
|
649
|
-
reject({
|
|
674
|
+
const error = {
|
|
650
675
|
code: "timeout",
|
|
651
676
|
message: `Code execution exceeded timeout of ${timeoutMs}ms.`,
|
|
652
677
|
retryable: true,
|
|
653
678
|
detail: { timeoutMs }
|
|
654
|
-
} satisfies RuntimeToolAdapterError
|
|
679
|
+
} satisfies RuntimeToolAdapterError;
|
|
680
|
+
policy.abort(error);
|
|
655
681
|
}, timeoutMs);
|
|
656
682
|
}
|
|
657
683
|
|
|
@@ -662,6 +688,133 @@ async function executeSandboxWithPolicy(
|
|
|
662
688
|
});
|
|
663
689
|
}
|
|
664
690
|
|
|
691
|
+
function webSearchPermissionsFor(
|
|
692
|
+
allowedHosts: ReadonlySet<string>,
|
|
693
|
+
allowPrivateNetwork: boolean
|
|
694
|
+
): readonly RuntimeToolPermission[] {
|
|
695
|
+
return [
|
|
696
|
+
{
|
|
697
|
+
kind: "network",
|
|
698
|
+
allowHosts: Array.from(allowedHosts).sort(),
|
|
699
|
+
allowPrivateNetwork
|
|
700
|
+
}
|
|
701
|
+
];
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function validateWebSearchRequestPolicy(
|
|
705
|
+
requestUrl: string | URL,
|
|
706
|
+
allowedHosts: ReadonlySet<string>,
|
|
707
|
+
allowPrivateNetwork: boolean
|
|
708
|
+
): RuntimeToolAdapterError | undefined {
|
|
709
|
+
const url = new URL(String(requestUrl));
|
|
710
|
+
const host = normalizeHost(url.hostname);
|
|
711
|
+
|
|
712
|
+
if (!allowedHosts.has(host)) {
|
|
713
|
+
return {
|
|
714
|
+
code: "permission-denied",
|
|
715
|
+
message: `webSearch request host ${url.hostname} is not allowed.`,
|
|
716
|
+
retryable: false,
|
|
717
|
+
detail: {
|
|
718
|
+
reason: "host-not-allowed",
|
|
719
|
+
host: url.hostname,
|
|
720
|
+
allowedHosts: Array.from(allowedHosts).sort()
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
if (!allowPrivateNetwork && classifyNetworkHost(host) === "private") {
|
|
726
|
+
return {
|
|
727
|
+
code: "permission-denied",
|
|
728
|
+
message: `webSearch request host ${url.hostname} is private-network and is not allowed.`,
|
|
729
|
+
retryable: false,
|
|
730
|
+
detail: {
|
|
731
|
+
reason: "private-network-not-allowed",
|
|
732
|
+
host: url.hostname
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
return undefined;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
function normalizeAllowedHosts(hosts: readonly string[]): ReadonlySet<string> {
|
|
741
|
+
return new Set(hosts.map(normalizeHost));
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function normalizeHost(host: string): string {
|
|
745
|
+
return host.toLowerCase().replace(/^\[|\]$/g, "");
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function classifyNetworkHost(host: string): "private" | "public" {
|
|
749
|
+
const mappedIpv4 = ipv4MappedToDottedQuad(host);
|
|
750
|
+
if (mappedIpv4 !== undefined) {
|
|
751
|
+
return classifyNetworkHost(mappedIpv4);
|
|
752
|
+
}
|
|
753
|
+
if (host === "localhost") return "private";
|
|
754
|
+
if (host.endsWith(".local")) return "private";
|
|
755
|
+
if (/^127(?:\.\d{1,3}){3}$/.test(host)) return "private";
|
|
756
|
+
if (/^10(?:\.\d{1,3}){3}$/.test(host)) return "private";
|
|
757
|
+
if (/^172\.(?:1[6-9]|2\d|3[01])(?:\.\d{1,3}){2}$/.test(host)) return "private";
|
|
758
|
+
if (/^192\.168(?:\.\d{1,3}){2}$/.test(host)) return "private";
|
|
759
|
+
if (/^169\.254(?:\.\d{1,3}){2}$/.test(host)) return "private";
|
|
760
|
+
if (host === "::1") return "private";
|
|
761
|
+
if (/^f[cd][0-9a-f]{2}:/.test(host)) return "private";
|
|
762
|
+
if (/^fe[89ab][0-9a-f]?:/.test(host)) return "private";
|
|
763
|
+
return "public";
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
function ipv4MappedToDottedQuad(host: string): string | undefined {
|
|
767
|
+
const match = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(host);
|
|
768
|
+
if (match === null) {
|
|
769
|
+
return undefined;
|
|
770
|
+
}
|
|
771
|
+
const high = Number.parseInt(match[1] ?? "", 16);
|
|
772
|
+
const low = Number.parseInt(match[2] ?? "", 16);
|
|
773
|
+
if (!Number.isFinite(high) || !Number.isFinite(low)) {
|
|
774
|
+
return undefined;
|
|
775
|
+
}
|
|
776
|
+
return `${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
interface ToolPolicyAbortController {
|
|
780
|
+
readonly signal: AbortSignal;
|
|
781
|
+
abort(reason: unknown): void;
|
|
782
|
+
cleanup(): void;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
function createToolPolicyAbortController(parentSignal: AbortSignal | undefined): ToolPolicyAbortController {
|
|
786
|
+
const controller = new AbortController();
|
|
787
|
+
let removeParentListener = (): void => {};
|
|
788
|
+
|
|
789
|
+
if (parentSignal?.aborted) {
|
|
790
|
+
controller.abort(parentSignal.reason);
|
|
791
|
+
} else if (parentSignal !== undefined) {
|
|
792
|
+
const abortFromParent = (): void => {
|
|
793
|
+
controller.abort(parentSignal.reason ?? {
|
|
794
|
+
code: "aborted",
|
|
795
|
+
message: "Code execution was aborted.",
|
|
796
|
+
retryable: true
|
|
797
|
+
} satisfies RuntimeToolAdapterError);
|
|
798
|
+
};
|
|
799
|
+
parentSignal.addEventListener("abort", abortFromParent, { once: true });
|
|
800
|
+
removeParentListener = (): void => {
|
|
801
|
+
parentSignal.removeEventListener("abort", abortFromParent);
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
return {
|
|
806
|
+
signal: controller.signal,
|
|
807
|
+
abort(reason: unknown): void {
|
|
808
|
+
if (!controller.signal.aborted) {
|
|
809
|
+
controller.abort(reason);
|
|
810
|
+
}
|
|
811
|
+
},
|
|
812
|
+
cleanup(): void {
|
|
813
|
+
removeParentListener();
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
|
|
665
818
|
function normalizeWebSearchResult(value: unknown): WebSearchToolResult {
|
|
666
819
|
if (!isJsonObject(value)) {
|
|
667
820
|
throw {
|
package/src/runtime/tools.ts
CHANGED
|
@@ -16,6 +16,8 @@ import type {
|
|
|
16
16
|
import { validateRuntimeToolRegistrations } from "./validation.js";
|
|
17
17
|
import { normalizeRuntimeToolAdapterError } from "./tools/built-in.js";
|
|
18
18
|
|
|
19
|
+
const DEFAULT_MAX_CONCURRENT_TOOL_CALLS = 4;
|
|
20
|
+
|
|
19
21
|
// Re-export the public surface from the split modules so the
|
|
20
22
|
// `@dogpile/sdk/runtime/tools` subpath stays stable.
|
|
21
23
|
export {
|
|
@@ -98,12 +100,18 @@ export interface RuntimeToolExecutorOptions {
|
|
|
98
100
|
export function createRuntimeToolExecutor(options: RuntimeToolExecutorOptions): RuntimeToolExecutor {
|
|
99
101
|
validateRuntimeToolRegistrations(options.tools);
|
|
100
102
|
const tools = Array.from(options.tools);
|
|
103
|
+
const toolsById = new Map<string, RuntimeTool<JsonObject, JsonValue>>();
|
|
104
|
+
for (const tool of tools) {
|
|
105
|
+
if (!toolsById.has(tool.identity.id)) {
|
|
106
|
+
toolsById.set(tool.identity.id, tool);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
101
109
|
let callCount = 0;
|
|
102
110
|
|
|
103
111
|
return {
|
|
104
112
|
tools,
|
|
105
113
|
async execute(request: RuntimeToolExecutionRequest): Promise<RuntimeToolResult> {
|
|
106
|
-
const tool =
|
|
114
|
+
const tool = toolsById.get(request.toolId);
|
|
107
115
|
const identity = tool?.identity ?? {
|
|
108
116
|
id: request.toolId,
|
|
109
117
|
name: request.toolId
|
|
@@ -182,9 +190,9 @@ export async function executeModelResponseToolRequests(options: {
|
|
|
182
190
|
readonly turn: number;
|
|
183
191
|
readonly metadata?: JsonObject;
|
|
184
192
|
}): Promise<readonly TranscriptToolCall[]> {
|
|
185
|
-
const
|
|
193
|
+
const requests = options.response.toolRequests ?? [];
|
|
186
194
|
|
|
187
|
-
|
|
195
|
+
return mapWithConcurrency(requests, DEFAULT_MAX_CONCURRENT_TOOL_CALLS, async (request) => {
|
|
188
196
|
const result = await options.executor.execute({
|
|
189
197
|
...request,
|
|
190
198
|
agentId: request.agentId ?? options.agentId,
|
|
@@ -192,15 +200,14 @@ export async function executeModelResponseToolRequests(options: {
|
|
|
192
200
|
turn: request.turn ?? options.turn,
|
|
193
201
|
metadata: mergeToolMetadata(options.metadata, request.metadata)
|
|
194
202
|
});
|
|
195
|
-
|
|
203
|
+
|
|
204
|
+
return {
|
|
196
205
|
toolCallId: result.toolCallId,
|
|
197
206
|
tool: result.tool,
|
|
198
207
|
input: request.input,
|
|
199
208
|
result
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return toolCalls;
|
|
209
|
+
};
|
|
210
|
+
});
|
|
204
211
|
}
|
|
205
212
|
|
|
206
213
|
function runtimeToolIdentityManifest(identity: RuntimeToolIdentity): JsonObject {
|
|
@@ -321,3 +328,27 @@ function mergeToolMetadata(base: JsonObject | undefined, request: JsonObject | u
|
|
|
321
328
|
function defaultToolCallId(runId: string, callIndex: number): string {
|
|
322
329
|
return `${runId}:tool-${callIndex + 1}`;
|
|
323
330
|
}
|
|
331
|
+
|
|
332
|
+
async function mapWithConcurrency<T, R>(
|
|
333
|
+
items: readonly T[],
|
|
334
|
+
maxConcurrent: number,
|
|
335
|
+
mapper: (item: T, index: number) => Promise<R>
|
|
336
|
+
): Promise<R[]> {
|
|
337
|
+
if (items.length === 0) {
|
|
338
|
+
return [];
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const results: R[] = new Array(items.length);
|
|
342
|
+
let nextIndex = 0;
|
|
343
|
+
const workerCount = Math.min(maxConcurrent, items.length);
|
|
344
|
+
|
|
345
|
+
await Promise.all(Array.from({ length: workerCount }, async () => {
|
|
346
|
+
while (nextIndex < items.length) {
|
|
347
|
+
const index = nextIndex;
|
|
348
|
+
nextIndex += 1;
|
|
349
|
+
results[index] = await mapper(items[index]!, index);
|
|
350
|
+
}
|
|
351
|
+
}));
|
|
352
|
+
|
|
353
|
+
return results;
|
|
354
|
+
}
|
|
@@ -73,6 +73,7 @@ export function validateDogpileOptions(options: DogpileOptions): void {
|
|
|
73
73
|
validateOptionalAbortSignal(options.signal, "signal");
|
|
74
74
|
validateOptionalNonNegativeInteger(options.maxDepth, "maxDepth");
|
|
75
75
|
validateOptionalPositiveInteger(options.maxConcurrentChildren, "maxConcurrentChildren");
|
|
76
|
+
validateOptionalPositiveInteger(options.maxConcurrentAgentTurns, "maxConcurrentAgentTurns");
|
|
76
77
|
validateOptionalPositiveFiniteNumber(options.defaultSubRunTimeoutMs, "defaultSubRunTimeoutMs");
|
|
77
78
|
validateOptionalOnChildFailure(options.onChildFailure, "onChildFailure");
|
|
78
79
|
}
|
|
@@ -91,6 +92,7 @@ export function validateRunCallOptions(options: unknown, path = "options"): void
|
|
|
91
92
|
const record = requireRecord(options, path);
|
|
92
93
|
validateOptionalNonNegativeInteger(record.maxDepth, `${path}.maxDepth`);
|
|
93
94
|
validateOptionalPositiveInteger(record.maxConcurrentChildren, `${path}.maxConcurrentChildren`);
|
|
95
|
+
validateOptionalPositiveInteger(record.maxConcurrentAgentTurns, `${path}.maxConcurrentAgentTurns`);
|
|
94
96
|
validateOptionalOnChildFailure(record.onChildFailure, `${path}.onChildFailure`);
|
|
95
97
|
}
|
|
96
98
|
|
|
@@ -113,6 +115,7 @@ export function validateEngineOptions(options: EngineOptions): void {
|
|
|
113
115
|
validateOptionalAbortSignal(options.signal, "signal");
|
|
114
116
|
validateOptionalNonNegativeInteger(options.maxDepth, "maxDepth");
|
|
115
117
|
validateOptionalPositiveInteger(options.maxConcurrentChildren, "maxConcurrentChildren");
|
|
118
|
+
validateOptionalPositiveInteger(options.maxConcurrentAgentTurns, "maxConcurrentAgentTurns");
|
|
116
119
|
validateOptionalPositiveFiniteNumber(options.defaultSubRunTimeoutMs, "defaultSubRunTimeoutMs");
|
|
117
120
|
validateOptionalOnChildFailure(options.onChildFailure, "onChildFailure");
|
|
118
121
|
}
|
package/src/types/events.ts
CHANGED
|
@@ -140,7 +140,7 @@ export interface ModelResponseEvent {
|
|
|
140
140
|
* - `input`: prompt text visible to that agent for this turn.
|
|
141
141
|
* - `chunkIndex`: zero-based chunk index within this model turn.
|
|
142
142
|
* - `text`: text delta from the provider.
|
|
143
|
-
* - `
|
|
143
|
+
* - `outputLength`: accumulated output character length after applying the chunk.
|
|
144
144
|
*/
|
|
145
145
|
export interface ModelOutputChunkEvent {
|
|
146
146
|
/** Discriminant for event rendering and exhaustive switches. */
|
|
@@ -161,8 +161,8 @@ export interface ModelOutputChunkEvent {
|
|
|
161
161
|
readonly chunkIndex: number;
|
|
162
162
|
/** Text delta produced by the model provider. */
|
|
163
163
|
readonly text: string;
|
|
164
|
-
/** Accumulated output
|
|
165
|
-
readonly
|
|
164
|
+
/** Accumulated output character length after applying this chunk. */
|
|
165
|
+
readonly outputLength: number;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
/**
|
package/src/types/replay.ts
CHANGED
|
@@ -163,8 +163,10 @@ export interface ReplayTraceProtocolDecision {
|
|
|
163
163
|
readonly contributionCount?: number;
|
|
164
164
|
/** Prompt/input associated with turn decisions. */
|
|
165
165
|
readonly input?: string;
|
|
166
|
-
/** Output associated with turn or
|
|
166
|
+
/** Output associated with turn/final decisions, or a streaming text delta. */
|
|
167
167
|
readonly output?: string;
|
|
168
|
+
/** Accumulated output character length for streaming output observations. */
|
|
169
|
+
readonly outputLength?: number;
|
|
168
170
|
/** Cumulative cost visible at this decision point. */
|
|
169
171
|
readonly cost?: CostSummary;
|
|
170
172
|
/** Normalized budget stop reason for budget-stop decisions. */
|
package/src/types.ts
CHANGED
|
@@ -1929,6 +1929,14 @@ export interface DogpileOptions extends BudgetCostTierOptions {
|
|
|
1929
1929
|
* ceiling; the effective value is `min(engine, run ?? Infinity, decision ?? Infinity)`.
|
|
1930
1930
|
*/
|
|
1931
1931
|
readonly maxConcurrentChildren?: number;
|
|
1932
|
+
/**
|
|
1933
|
+
* Maximum agent model turns that may execute in parallel for shared,
|
|
1934
|
+
* broadcast, and coordinator worker fan-out.
|
|
1935
|
+
*
|
|
1936
|
+
* Defaults to 4. Per-run values can only lower the engine ceiling.
|
|
1937
|
+
* This is independent from delegated child-run concurrency.
|
|
1938
|
+
*/
|
|
1939
|
+
readonly maxConcurrentAgentTurns?: number;
|
|
1932
1940
|
/**
|
|
1933
1941
|
* Fallback timeout (milliseconds) applied to delegated sub-runs when neither
|
|
1934
1942
|
* the parent's `budget.timeoutMs` nor the decision-level
|
|
@@ -2058,6 +2066,14 @@ export interface EngineOptions {
|
|
|
2058
2066
|
* call sites via {@link RunCallOptions.maxConcurrentChildren}.
|
|
2059
2067
|
*/
|
|
2060
2068
|
readonly maxConcurrentChildren?: number;
|
|
2069
|
+
/**
|
|
2070
|
+
* Maximum agent model turns that may execute in parallel for shared,
|
|
2071
|
+
* broadcast, and coordinator worker fan-out.
|
|
2072
|
+
*
|
|
2073
|
+
* Defaults to 4. Per-run lowering happens at `engine.run` / `engine.stream`
|
|
2074
|
+
* call sites via {@link RunCallOptions.maxConcurrentAgentTurns}.
|
|
2075
|
+
*/
|
|
2076
|
+
readonly maxConcurrentAgentTurns?: number;
|
|
2061
2077
|
/**
|
|
2062
2078
|
* Fallback timeout (milliseconds) applied to delegated sub-runs when neither
|
|
2063
2079
|
* the parent's `budget.timeoutMs` nor the decision-level
|
|
@@ -2097,6 +2113,10 @@ export interface RunCallOptions {
|
|
|
2097
2113
|
* ceiling.
|
|
2098
2114
|
*/
|
|
2099
2115
|
readonly maxConcurrentChildren?: number;
|
|
2116
|
+
/**
|
|
2117
|
+
* Per-run agent-turn fan-out ceiling. Cannot raise the engine's ceiling.
|
|
2118
|
+
*/
|
|
2119
|
+
readonly maxConcurrentAgentTurns?: number;
|
|
2100
2120
|
/** Per-run child-failure behavior. Overrides the engine default. */
|
|
2101
2121
|
readonly onChildFailure?: OnChildFailureMode;
|
|
2102
2122
|
}
|