@agent-native/core 0.208.0 → 0.209.0-nightly-20261014070126
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/agent-native.eject.json +1 -0
- package/dist/agent/approval-key.d.ts +2 -0
- package/dist/agent/approval-key.js +12 -0
- package/dist/agent/context-xray/tokenize.js +12 -3
- package/dist/agent/engine/translate-anthropic.js +4 -0
- package/dist/agent/engine/types.d.ts +2 -0
- package/dist/agent/production-agent.d.ts +20 -5
- package/dist/agent/production-agent.js +227 -34
- package/dist/agent/run-manager.js +57 -11
- package/dist/agent/run-store.d.ts +10 -0
- package/dist/agent/run-store.js +49 -4
- package/dist/agent/thread-data-builder.d.ts +2 -0
- package/dist/agent/thread-data-builder.js +288 -14
- package/dist/agent/tool-approval-store.d.ts +3 -1
- package/dist/agent/tool-approval-store.js +26 -12
- package/dist/agent/tool-call-journal.d.ts +1 -1
- package/dist/agent/tool-call-journal.js +5 -3
- package/dist/agent/types.d.ts +7 -0
- package/dist/client/chat/agentkit-agent-native.js +18 -0
- package/dist/client/chat/agentkit-protocol.js +56 -5
- package/dist/client/chat/runtime.d.ts +10 -0
- package/dist/client/chat/runtime.js +257 -26
- package/dist/client/sse-event-processor.d.ts +22 -0
- package/dist/client/sse-event-processor.js +91 -11
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +24 -1
- package/dist/connections/catalog.js +12 -0
- package/dist/data-programs/schema.d.ts +1 -0
- package/dist/data-programs/schema.js +3 -0
- package/dist/data-programs/store.js +2 -1
- package/dist/deploy/build.js +16 -14
- package/dist/eject/workspace-connections.js +1 -0
- package/dist/extensions/fetch-tool.js +114 -23
- package/dist/extensions/schema.d.ts +1 -0
- package/dist/extensions/schema.js +3 -0
- package/dist/extensions/store.js +2 -1
- package/dist/extensions/web-content.d.ts +5 -1
- package/dist/extensions/web-content.js +24 -6
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +9 -9
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.d.ts +2 -0
- package/dist/provider-api/index.js +95 -12
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +2 -2
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/auth.js +1 -0
- package/dist/server/core-routes-plugin.js +1 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +2 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.js +2 -0
- package/dist/shared/context-status.js +1 -1
- package/dist/shared/optional-peer-ssr.d.ts +2 -0
- package/dist/shared/optional-peer-ssr.js +123 -0
- package/dist/shared/tool-inputs.d.ts +2 -0
- package/dist/shared/tool-inputs.js +56 -0
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/tracking/index.d.ts +1 -0
- package/dist/tracking/index.js +1 -0
- package/dist/vite/client.js +46 -3
- package/dist/workspace-connections/store.d.ts +3 -1
- package/dist/workspace-connections/store.js +18 -8
- package/dist/workspace-files/constants.d.ts +3 -0
- package/dist/workspace-files/constants.js +3 -0
- package/dist/workspace-files/store.d.ts +2 -3
- package/dist/workspace-files/store.js +2 -3
- package/docs/content/automations.mdx +19 -13
- package/package.json +3 -3
- package/src/eject/workspace-connections.ts +1 -0
package/agent-native.eject.json
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
2
|
+
import { bytesToHex } from "@noble/hashes/utils.js";
|
|
3
|
+
const APPROVAL_KEY_HISTORY_PREFIX = "agent-tool-approval-key-sha256:";
|
|
4
|
+
const HASHED_APPROVAL_KEY_PATTERN = /^agent-tool-approval-key-sha256:[a-f0-9]{64}$/;
|
|
5
|
+
export function hashAgentToolApprovalKey(approvalKey) {
|
|
6
|
+
return bytesToHex(sha256(new TextEncoder().encode(approvalKey)));
|
|
7
|
+
}
|
|
8
|
+
export function approvalKeyForHistory(approvalKey) {
|
|
9
|
+
if (HASHED_APPROVAL_KEY_PATTERN.test(approvalKey))
|
|
10
|
+
return approvalKey;
|
|
11
|
+
return `${APPROVAL_KEY_HISTORY_PREFIX}${hashAgentToolApprovalKey(approvalKey)}`;
|
|
12
|
+
}
|
|
@@ -7,9 +7,18 @@ async function loadTokenizer() {
|
|
|
7
7
|
// browser fallback, while the documented estimate below is sufficient
|
|
8
8
|
// when an edge runtime cannot resolve the tokenizer.
|
|
9
9
|
tokenizerPromise = import(/* @vite-ignore */ TOKENIZER_MODULE_ID)
|
|
10
|
-
.then((mod) =>
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
.then((mod) => {
|
|
11
|
+
// The package's countTokens rebuilds the BPE encoder on every call
|
|
12
|
+
// (~20 ms); counting a whole context part by part before each model
|
|
13
|
+
// call turned that into seconds of dead time per turn.
|
|
14
|
+
if (typeof mod.getTokenizer === "function") {
|
|
15
|
+
const encoder = mod.getTokenizer();
|
|
16
|
+
return (text) => encoder.encode(text.normalize("NFKC"), "all").length;
|
|
17
|
+
}
|
|
18
|
+
return typeof mod.countTokens === "function"
|
|
19
|
+
? mod.countTokens
|
|
20
|
+
: null;
|
|
21
|
+
})
|
|
13
22
|
.catch(() => null);
|
|
14
23
|
}
|
|
15
24
|
return tokenizerPromise;
|
|
@@ -189,6 +189,10 @@ export function backfillEngineMessagesToolResults(messages) {
|
|
|
189
189
|
toolInput,
|
|
190
190
|
content: interrupted ? INTERRUPTED_TOOL_RESULT_FOR_MODEL : part.content,
|
|
191
191
|
...(part.isError || interrupted ? { isError: true } : {}),
|
|
192
|
+
...(part.approvalPause === undefined
|
|
193
|
+
? {}
|
|
194
|
+
: { approvalPause: part.approvalPause }),
|
|
195
|
+
...(part.approvalAskId ? { approvalAskId: part.approvalAskId } : {}),
|
|
192
196
|
...(part.images && part.images.length > 0
|
|
193
197
|
? { images: part.images }
|
|
194
198
|
: {}),
|
|
@@ -530,6 +530,7 @@ export declare const MAX_SAME_ERROR_ACROSS_ARGUMENTS = 3;
|
|
|
530
530
|
export declare const MAX_IDENTICAL_TOOL_CALLS = 8;
|
|
531
531
|
export interface TerminalActionStop {
|
|
532
532
|
message: string;
|
|
533
|
+
transcriptMessage?: string;
|
|
533
534
|
errorCode?: string;
|
|
534
535
|
details?: string;
|
|
535
536
|
}
|
|
@@ -545,6 +546,9 @@ export type AgentToolCallExecutionResult = {
|
|
|
545
546
|
} | {
|
|
546
547
|
status: "failed";
|
|
547
548
|
output: string;
|
|
549
|
+
terminalError?: Extract<AgentChatEvent, {
|
|
550
|
+
type: "error";
|
|
551
|
+
}>;
|
|
548
552
|
};
|
|
549
553
|
export interface ExecuteAgentToolCallOptions {
|
|
550
554
|
actions: Record<string, ActionEntry>;
|
|
@@ -564,6 +568,7 @@ export interface ExecuteAgentToolCallOptions {
|
|
|
564
568
|
threadId?: string;
|
|
565
569
|
turnId?: string;
|
|
566
570
|
approvedToolCalls?: string[];
|
|
571
|
+
approvedToolCallAskId?: string;
|
|
567
572
|
onApprovalRequired?: (binding: AgentApprovalBinding) => Promise<string | void>;
|
|
568
573
|
consumeApproval?: (binding: AgentApprovalBinding) => Promise<boolean>;
|
|
569
574
|
isToolAlwaysAllowed?: (binding: AgentApprovalBinding) => Promise<boolean>;
|
|
@@ -574,6 +579,7 @@ export interface AgentApprovalBinding {
|
|
|
574
579
|
input: unknown;
|
|
575
580
|
callId: string;
|
|
576
581
|
approvalKey: string;
|
|
582
|
+
approvalId?: string;
|
|
577
583
|
}
|
|
578
584
|
export declare function executeAgentToolCall(options: ExecuteAgentToolCallOptions): Promise<AgentToolCallExecutionResult>;
|
|
579
585
|
export declare function filterInitialEngineTools(tools: EngineTool[], initialToolNames?: string[]): EngineTool[];
|
|
@@ -592,11 +598,19 @@ export declare function buildFirstRequestPayloadDetail(input: {
|
|
|
592
598
|
availableToolCount: number;
|
|
593
599
|
}): string;
|
|
594
600
|
export declare function toolCallCacheKey(toolName: string, input: unknown): string;
|
|
595
|
-
export declare function findApprovedStructuredToolCall(history: AgentChatStructuredMessage[] | undefined, approvedToolCalls: readonly string[] | undefined): {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
601
|
+
export declare function findApprovedStructuredToolCall(history: AgentChatStructuredMessage[] | undefined, approvedToolCalls: readonly string[] | undefined, approvedToolCallAskIds?: readonly string[]): {
|
|
602
|
+
status: "found";
|
|
603
|
+
toolCall: {
|
|
604
|
+
name: string;
|
|
605
|
+
input: unknown;
|
|
606
|
+
callId: string;
|
|
607
|
+
approvalAskId?: string;
|
|
608
|
+
};
|
|
609
|
+
} | {
|
|
610
|
+
status: "ambiguous";
|
|
611
|
+
} | {
|
|
612
|
+
status: "missing";
|
|
613
|
+
};
|
|
600
614
|
export declare function normalizeToolErrorForBreaker(error: string): string;
|
|
601
615
|
/**
|
|
602
616
|
* Tool errors the model has no way to clear: the missing thing lives outside
|
|
@@ -695,6 +709,7 @@ export declare function runAgentLoop(opts: {
|
|
|
695
709
|
hardMaxResultChars?: number;
|
|
696
710
|
};
|
|
697
711
|
approvedToolCalls?: string[];
|
|
712
|
+
approvedToolCallAskId?: string;
|
|
698
713
|
/**
|
|
699
714
|
* Server-side approval persistence hooks. The HTTP transport supplies these
|
|
700
715
|
* so client-supplied history is never the authorization source; direct loop
|
|
@@ -83,7 +83,7 @@ import { writeLedgerEntry, readLedgerEntry, clearLedgerForThread, AgentTurnIniti
|
|
|
83
83
|
import { buildCurrentTimeUserContext } from "./runtime-context.js";
|
|
84
84
|
import { claimSetupResume, setupResumeRefusedRunId, } from "./setup-resume-claim.js";
|
|
85
85
|
import { consumeAgentToolApproval, createAgentToolApproval, isAgentToolAlwaysAllowed, resolveAgentToolApprovalTurnId, } from "./tool-approval-store.js";
|
|
86
|
-
import { findCompletedJournalEntry } from "./tool-call-journal.js";
|
|
86
|
+
import { findCompletedJournalEntry, isUnavailableToolCallInput, } from "./tool-call-journal.js";
|
|
87
87
|
import { redactSensitiveFields, sanitizeToolErrorText, sanitizeToolErrorValue, } from "./tool-error-redaction.js";
|
|
88
88
|
import { describeToolResultImages, extractAgentImagesFromActionResult, } from "./tool-result-images.js";
|
|
89
89
|
import { createToolSearchEntry, extractToolSearchResultNames, filterActionsForAgentDiscovery, readLoadedToolNames, searchToolRegistry, TOOL_SEARCH_ACTION_NAME, withLoadedToolNames, } from "./tool-search.js";
|
|
@@ -1332,6 +1332,17 @@ export function serializeDurableDispatchPayload(body) {
|
|
|
1332
1332
|
}
|
|
1333
1333
|
return payload;
|
|
1334
1334
|
}
|
|
1335
|
+
function approvedInputRequiresForeground(input) {
|
|
1336
|
+
const originalPayload = JSON.stringify({ input });
|
|
1337
|
+
try {
|
|
1338
|
+
return serializeDurableDispatchPayload({ input }) !== originalPayload;
|
|
1339
|
+
}
|
|
1340
|
+
catch (error) {
|
|
1341
|
+
if (error instanceof DurableAttachmentReferenceRequiredError)
|
|
1342
|
+
return true;
|
|
1343
|
+
throw error;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1335
1346
|
function toolInputActivityLabel(toolName) {
|
|
1336
1347
|
return toolName ? `Preparing ${toolName} action` : "Preparing action input";
|
|
1337
1348
|
}
|
|
@@ -2165,6 +2176,12 @@ export function structuredHistoryToEngineMessages(history, imageResolutions) {
|
|
|
2165
2176
|
toolInput,
|
|
2166
2177
|
content: wire.content,
|
|
2167
2178
|
...(part.isError ? { isError: true } : {}),
|
|
2179
|
+
...(typeof part.approvalPause === "boolean"
|
|
2180
|
+
? { approvalPause: part.approvalPause }
|
|
2181
|
+
: {}),
|
|
2182
|
+
...(typeof part.approvalAskId === "string"
|
|
2183
|
+
? { approvalAskId: part.approvalAskId }
|
|
2184
|
+
: {}),
|
|
2168
2185
|
});
|
|
2169
2186
|
}
|
|
2170
2187
|
}
|
|
@@ -3100,6 +3117,9 @@ export async function executeAgentToolCall(options) {
|
|
|
3100
3117
|
const events = [];
|
|
3101
3118
|
const send = (event) => {
|
|
3102
3119
|
events.push(event);
|
|
3120
|
+
if (event.type === "text" && event.text === "Tool execution complete.") {
|
|
3121
|
+
return;
|
|
3122
|
+
}
|
|
3103
3123
|
options.send?.(event);
|
|
3104
3124
|
};
|
|
3105
3125
|
const controller = options.signal ? null : new AbortController();
|
|
@@ -3138,6 +3158,7 @@ export async function executeAgentToolCall(options) {
|
|
|
3138
3158
|
threadId: options.threadId,
|
|
3139
3159
|
turnId: options.turnId,
|
|
3140
3160
|
approvedToolCalls: options.approvedToolCalls,
|
|
3161
|
+
approvedToolCallAskId: options.approvedToolCallAskId,
|
|
3141
3162
|
onApprovalRequired: options.onApprovalRequired,
|
|
3142
3163
|
consumeApproval: options.consumeApproval,
|
|
3143
3164
|
isToolAlwaysAllowed: options.isToolAlwaysAllowed,
|
|
@@ -3153,6 +3174,7 @@ export async function executeAgentToolCall(options) {
|
|
|
3153
3174
|
const completed = [...events]
|
|
3154
3175
|
.reverse()
|
|
3155
3176
|
.find((event) => event.type === "tool_done" && event.tool === options.name);
|
|
3177
|
+
const terminalError = events.find((event) => event.type === "error" && event.recoverable === false);
|
|
3156
3178
|
if (approval) {
|
|
3157
3179
|
return {
|
|
3158
3180
|
status: "approval_required",
|
|
@@ -3160,6 +3182,13 @@ export async function executeAgentToolCall(options) {
|
|
|
3160
3182
|
output: completed?.result ?? `Awaiting human approval to run ${options.name}.`,
|
|
3161
3183
|
};
|
|
3162
3184
|
}
|
|
3185
|
+
if (terminalError) {
|
|
3186
|
+
return {
|
|
3187
|
+
status: "failed",
|
|
3188
|
+
output: completed?.result ?? terminalError.error,
|
|
3189
|
+
terminalError,
|
|
3190
|
+
};
|
|
3191
|
+
}
|
|
3163
3192
|
if (!completed) {
|
|
3164
3193
|
return {
|
|
3165
3194
|
status: "failed",
|
|
@@ -3304,12 +3333,14 @@ function stableStringify(value) {
|
|
|
3304
3333
|
export function toolCallCacheKey(toolName, input) {
|
|
3305
3334
|
return `${toolName}:${stableStringify(normalizeToolCallInputForHistory(input, toolName))}`;
|
|
3306
3335
|
}
|
|
3307
|
-
export function findApprovedStructuredToolCall(history, approvedToolCalls) {
|
|
3308
|
-
if (!Array.isArray(history) || !approvedToolCalls?.length)
|
|
3309
|
-
return
|
|
3336
|
+
export function findApprovedStructuredToolCall(history, approvedToolCalls, approvedToolCallAskIds) {
|
|
3337
|
+
if (!Array.isArray(history) || !approvedToolCalls?.length) {
|
|
3338
|
+
return { status: "missing" };
|
|
3339
|
+
}
|
|
3310
3340
|
const approved = new Set(approvedToolCalls);
|
|
3341
|
+
const approvedAskIds = new Set(approvedToolCallAskIds ?? []);
|
|
3311
3342
|
const calls = new Map();
|
|
3312
|
-
|
|
3343
|
+
const matches = [];
|
|
3313
3344
|
for (const message of history) {
|
|
3314
3345
|
if (message.role === "assistant") {
|
|
3315
3346
|
for (const part of message.content) {
|
|
@@ -3327,7 +3358,14 @@ export function findApprovedStructuredToolCall(history, approvedToolCalls) {
|
|
|
3327
3358
|
: "";
|
|
3328
3359
|
if (!callId || !name)
|
|
3329
3360
|
continue;
|
|
3330
|
-
calls.set(callId, {
|
|
3361
|
+
calls.set(callId, {
|
|
3362
|
+
name,
|
|
3363
|
+
input: part.input !== undefined
|
|
3364
|
+
? part.input
|
|
3365
|
+
: (part.args ?? { omitted: "tool-input" }),
|
|
3366
|
+
...(part.approvalKey ? { approvalKey: part.approvalKey } : {}),
|
|
3367
|
+
...(part.approvalAskId ? { approvalAskId: part.approvalAskId } : {}),
|
|
3368
|
+
});
|
|
3331
3369
|
}
|
|
3332
3370
|
continue;
|
|
3333
3371
|
}
|
|
@@ -3335,19 +3373,53 @@ export function findApprovedStructuredToolCall(history, approvedToolCalls) {
|
|
|
3335
3373
|
if (part.type !== "tool-result")
|
|
3336
3374
|
continue;
|
|
3337
3375
|
const call = calls.get(part.toolCallId);
|
|
3338
|
-
if (!call
|
|
3376
|
+
if (!call) {
|
|
3339
3377
|
continue;
|
|
3340
3378
|
}
|
|
3341
|
-
const
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3379
|
+
const matchesApproval = approvedAskIds.size > 0
|
|
3380
|
+
? Boolean(call.approvalAskId && approvedAskIds.has(call.approvalAskId))
|
|
3381
|
+
: approved.has(call.approvalKey ?? toolCallCacheKey(call.name, call.input));
|
|
3382
|
+
if (!matchesApproval) {
|
|
3345
3383
|
continue;
|
|
3346
3384
|
}
|
|
3347
|
-
|
|
3385
|
+
if (part.approvalPause !== true)
|
|
3386
|
+
continue;
|
|
3387
|
+
if (approvedAskIds.size > 0 &&
|
|
3388
|
+
(!call.approvalAskId ||
|
|
3389
|
+
!approvedAskIds.has(call.approvalAskId) ||
|
|
3390
|
+
part.approvalAskId !== call.approvalAskId)) {
|
|
3391
|
+
continue;
|
|
3392
|
+
}
|
|
3393
|
+
if (call.approvalAskId &&
|
|
3394
|
+
part.approvalAskId &&
|
|
3395
|
+
call.approvalAskId !== part.approvalAskId) {
|
|
3396
|
+
continue;
|
|
3397
|
+
}
|
|
3398
|
+
matches.push({
|
|
3399
|
+
name: call.name,
|
|
3400
|
+
input: call.input,
|
|
3401
|
+
callId: part.toolCallId,
|
|
3402
|
+
...((part.approvalAskId ?? call.approvalAskId)
|
|
3403
|
+
? { approvalAskId: part.approvalAskId ?? call.approvalAskId }
|
|
3404
|
+
: {}),
|
|
3405
|
+
});
|
|
3348
3406
|
}
|
|
3349
3407
|
}
|
|
3350
|
-
|
|
3408
|
+
if (approvedAskIds.size > 0) {
|
|
3409
|
+
const distinctAskIds = new Set(matches.map((match) => match.approvalAskId).filter(Boolean));
|
|
3410
|
+
if (distinctAskIds.size !== 1 ||
|
|
3411
|
+
distinctAskIds.size !== approvedAskIds.size) {
|
|
3412
|
+
return { status: matches.length === 0 ? "missing" : "ambiguous" };
|
|
3413
|
+
}
|
|
3414
|
+
const exactMatches = matches.filter((match) => approvedAskIds.has(match.approvalAskId ?? ""));
|
|
3415
|
+
if (exactMatches.length === 0)
|
|
3416
|
+
return { status: "missing" };
|
|
3417
|
+
return { status: "found", toolCall: exactMatches.at(-1) };
|
|
3418
|
+
}
|
|
3419
|
+
if (matches.length > 1)
|
|
3420
|
+
return { status: "ambiguous" };
|
|
3421
|
+
const toolCall = matches[0];
|
|
3422
|
+
return toolCall ? { status: "found", toolCall } : { status: "missing" };
|
|
3351
3423
|
}
|
|
3352
3424
|
const INTERRUPTED_TOOL_LEDGER_POLL_MS = process.env.NODE_ENV === "test" ? 0 : 2_000;
|
|
3353
3425
|
async function waitForInterruptedToolLedgerEntry(opts) {
|
|
@@ -4330,7 +4402,7 @@ export async function runAgentLoop(opts) {
|
|
|
4330
4402
|
const sendTerminalActionStop = (stop) => {
|
|
4331
4403
|
if (stop.errorCode === "needs-approval" ||
|
|
4332
4404
|
stop.errorCode === "awaiting-user-input") {
|
|
4333
|
-
send({ type: "text", text: stop.message });
|
|
4405
|
+
send({ type: "text", text: stop.transcriptMessage ?? stop.message });
|
|
4334
4406
|
return;
|
|
4335
4407
|
}
|
|
4336
4408
|
send({
|
|
@@ -5132,12 +5204,23 @@ export async function runAgentLoop(opts) {
|
|
|
5132
5204
|
let requestedActionStop = null;
|
|
5133
5205
|
let requestedConnection;
|
|
5134
5206
|
let turnYieldedToUser = false;
|
|
5135
|
-
const noteToolCallSucceeded = (actionEntry) => {
|
|
5207
|
+
const noteToolCallSucceeded = (actionEntry, toolName, toolInput) => {
|
|
5136
5208
|
if (actionEntry.endsTurn !== true)
|
|
5137
5209
|
return;
|
|
5138
5210
|
turnYieldedToUser = true;
|
|
5211
|
+
const question = toolName === "ask-question" &&
|
|
5212
|
+
typeof toolInput === "object" &&
|
|
5213
|
+
toolInput !== null &&
|
|
5214
|
+
"question" in toolInput &&
|
|
5215
|
+
typeof toolInput.question === "string"
|
|
5216
|
+
? toolInput.question.trim()
|
|
5217
|
+
: "";
|
|
5218
|
+
const waitingMessage = "Waiting for your answer before continuing";
|
|
5139
5219
|
requestedActionStop ??= {
|
|
5140
|
-
message:
|
|
5220
|
+
message: question
|
|
5221
|
+
? `${waitingMessage}: ${question}`
|
|
5222
|
+
: `${waitingMessage}.`,
|
|
5223
|
+
transcriptMessage: `${waitingMessage}.`,
|
|
5141
5224
|
errorCode: "awaiting-user-input",
|
|
5142
5225
|
};
|
|
5143
5226
|
};
|
|
@@ -5396,13 +5479,16 @@ export async function runAgentLoop(opts) {
|
|
|
5396
5479
|
}
|
|
5397
5480
|
}
|
|
5398
5481
|
const approvalKey = toolCallCacheKey(toolCall.name, toolCall.input);
|
|
5482
|
+
const requestedApproval = approvedToolCallKeys.delete(approvalKey);
|
|
5399
5483
|
const approvalBinding = {
|
|
5400
5484
|
toolName: toolCall.name,
|
|
5401
5485
|
input: toolCall.input,
|
|
5402
5486
|
callId: toolCall.id,
|
|
5403
5487
|
approvalKey,
|
|
5488
|
+
...(requestedApproval && opts.approvedToolCallAskId
|
|
5489
|
+
? { approvalId: opts.approvedToolCallAskId }
|
|
5490
|
+
: {}),
|
|
5404
5491
|
};
|
|
5405
|
-
const requestedApproval = approvedToolCallKeys.delete(approvalKey);
|
|
5406
5492
|
const wasApproved = requestedApproval && opts.consumeApproval
|
|
5407
5493
|
? await opts.consumeApproval(approvalBinding)
|
|
5408
5494
|
: requestedApproval;
|
|
@@ -5489,6 +5575,7 @@ export async function runAgentLoop(opts) {
|
|
|
5489
5575
|
input: journalToolInput,
|
|
5490
5576
|
result,
|
|
5491
5577
|
completedSideEffect: false,
|
|
5578
|
+
approvalPause: true,
|
|
5492
5579
|
});
|
|
5493
5580
|
recordToolResult(result, false);
|
|
5494
5581
|
turnYieldedToUser = true;
|
|
@@ -5550,7 +5637,7 @@ export async function runAgentLoop(opts) {
|
|
|
5550
5637
|
: {}),
|
|
5551
5638
|
});
|
|
5552
5639
|
recordToolResult(result, false, journaled.artifacts);
|
|
5553
|
-
noteToolCallSucceeded(actionEntry);
|
|
5640
|
+
noteToolCallSucceeded(actionEntry, toolCall.name, toolCall.input);
|
|
5554
5641
|
resetAfterSuccessfulWrite(toolCall.name, toolCall.input);
|
|
5555
5642
|
return {
|
|
5556
5643
|
type: "tool-result",
|
|
@@ -5614,7 +5701,7 @@ export async function runAgentLoop(opts) {
|
|
|
5614
5701
|
: {}),
|
|
5615
5702
|
});
|
|
5616
5703
|
recordToolResult(result, false, ledgerResult.artifacts);
|
|
5617
|
-
noteToolCallSucceeded(actionEntry);
|
|
5704
|
+
noteToolCallSucceeded(actionEntry, toolCall.name, toolCall.input);
|
|
5618
5705
|
resetAfterSuccessfulWrite(toolCall.name, toolCall.input);
|
|
5619
5706
|
return {
|
|
5620
5707
|
type: "tool-result",
|
|
@@ -6160,7 +6247,7 @@ export async function runAgentLoop(opts) {
|
|
|
6160
6247
|
});
|
|
6161
6248
|
recordToolResult(result, isError, toolArtifacts, receipt);
|
|
6162
6249
|
if (!isError) {
|
|
6163
|
-
noteToolCallSucceeded(actionEntry);
|
|
6250
|
+
noteToolCallSucceeded(actionEntry, toolCall.name, toolCall.input);
|
|
6164
6251
|
if (cacheKey) {
|
|
6165
6252
|
readOnlyToolResultCache.set(cacheKey, {
|
|
6166
6253
|
content: result,
|
|
@@ -7364,6 +7451,9 @@ export async function chainServerDrivenContinuation(opts) {
|
|
|
7364
7451
|
}
|
|
7365
7452
|
: {}),
|
|
7366
7453
|
};
|
|
7454
|
+
// Approval selectors apply only to the request that consumes their one-shot grants.
|
|
7455
|
+
delete continuationBody.approvedToolCalls;
|
|
7456
|
+
delete continuationBody.approvedToolCallAskIds;
|
|
7367
7457
|
delete continuationBody[AGENT_CHAT_BACKGROUND_RUN_FIELD];
|
|
7368
7458
|
try {
|
|
7369
7459
|
if (await d.isTurnAborted(effectiveThreadId, effectiveTurnId)) {
|
|
@@ -7769,7 +7859,7 @@ export function createProductionAgentHandler(options) {
|
|
|
7769
7859
|
}
|
|
7770
7860
|
backgroundRunClaimedEarly = true;
|
|
7771
7861
|
}
|
|
7772
|
-
|
|
7862
|
+
let dispatchToBackground = !isBackgroundWorker &&
|
|
7773
7863
|
isAgentChatDurableBackgroundEnabled({
|
|
7774
7864
|
appOptIn: options.durableBackgroundRuns,
|
|
7775
7865
|
});
|
|
@@ -7826,23 +7916,117 @@ export function createProductionAgentHandler(options) {
|
|
|
7826
7916
|
setResponseStatus(event, 401);
|
|
7827
7917
|
return { error: "Background agent runs require a persisted initiator" };
|
|
7828
7918
|
}
|
|
7829
|
-
const
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
.
|
|
7919
|
+
const submittedApprovedToolCalls = body.approvedToolCalls;
|
|
7920
|
+
if (submittedApprovedToolCalls !== undefined &&
|
|
7921
|
+
(!Array.isArray(submittedApprovedToolCalls) ||
|
|
7922
|
+
submittedApprovedToolCalls.length > 200 ||
|
|
7923
|
+
submittedApprovedToolCalls.some((key) => typeof key !== "string" || key.length === 0))) {
|
|
7924
|
+
setResponseStatus(event, 422);
|
|
7925
|
+
return {
|
|
7926
|
+
error: "The agent run failed.",
|
|
7927
|
+
code: "approved_tool_call_invalid",
|
|
7928
|
+
retryable: false,
|
|
7929
|
+
};
|
|
7930
|
+
}
|
|
7931
|
+
const requestedApprovedToolCalls = Array.isArray(submittedApprovedToolCalls) &&
|
|
7932
|
+
submittedApprovedToolCalls.length > 0
|
|
7933
|
+
? submittedApprovedToolCalls
|
|
7833
7934
|
: undefined;
|
|
7834
|
-
const
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7935
|
+
const submittedApprovedToolCallAskIds = body.approvedToolCallAskIds;
|
|
7936
|
+
if (submittedApprovedToolCallAskIds !== undefined &&
|
|
7937
|
+
(!Array.isArray(submittedApprovedToolCallAskIds) ||
|
|
7938
|
+
submittedApprovedToolCallAskIds.length > 200 ||
|
|
7939
|
+
submittedApprovedToolCallAskIds.some((id) => typeof id !== "string" || id.length === 0 || id.trim() !== id))) {
|
|
7940
|
+
setResponseStatus(event, 422);
|
|
7941
|
+
return {
|
|
7942
|
+
error: "The agent run failed.",
|
|
7943
|
+
code: "approved_tool_call_ask_id_invalid",
|
|
7944
|
+
retryable: false,
|
|
7945
|
+
};
|
|
7946
|
+
}
|
|
7947
|
+
const requestedApprovedToolCallAskIds = Array.isArray(submittedApprovedToolCallAskIds) &&
|
|
7948
|
+
submittedApprovedToolCallAskIds.length > 0
|
|
7949
|
+
? submittedApprovedToolCallAskIds
|
|
7950
|
+
: undefined;
|
|
7951
|
+
// The approval fast path replays one call, so reject batches before any key can be dropped.
|
|
7952
|
+
if (requestedApprovedToolCalls && requestedApprovedToolCalls.length > 1) {
|
|
7953
|
+
setResponseStatus(event, 422);
|
|
7954
|
+
return {
|
|
7955
|
+
error: "The agent run failed.",
|
|
7956
|
+
code: "approved_tool_call_count_unsupported",
|
|
7957
|
+
retryable: false,
|
|
7958
|
+
};
|
|
7959
|
+
}
|
|
7960
|
+
if (requestedApprovedToolCallAskIds &&
|
|
7961
|
+
(requestedApprovedToolCallAskIds.length !== 1 ||
|
|
7962
|
+
requestedApprovedToolCalls?.length !== 1)) {
|
|
7963
|
+
setResponseStatus(event, 422);
|
|
7964
|
+
return {
|
|
7965
|
+
error: "The agent run failed.",
|
|
7966
|
+
code: "approved_tool_call_ask_id_count_unsupported",
|
|
7967
|
+
retryable: false,
|
|
7968
|
+
};
|
|
7969
|
+
}
|
|
7970
|
+
const approvedToolCallLookup = findApprovedStructuredToolCall(requestStructuredHistory, requestedApprovedToolCalls, requestedApprovedToolCallAskIds);
|
|
7971
|
+
if (approvedToolCallLookup.status === "ambiguous") {
|
|
7972
|
+
setResponseStatus(event, 422);
|
|
7973
|
+
return {
|
|
7974
|
+
error: "The agent run failed.",
|
|
7975
|
+
code: "approved_tool_call_history_ambiguous",
|
|
7976
|
+
retryable: false,
|
|
7977
|
+
};
|
|
7978
|
+
}
|
|
7979
|
+
const exactApprovedToolCall = approvedToolCallLookup.status === "found"
|
|
7980
|
+
? approvedToolCallLookup.toolCall
|
|
7981
|
+
: undefined;
|
|
7982
|
+
if (requestedApprovedToolCalls?.length && !exactApprovedToolCall) {
|
|
7983
|
+
setResponseStatus(event, 422);
|
|
7984
|
+
return {
|
|
7985
|
+
error: "The agent run failed.",
|
|
7986
|
+
code: "approved_tool_call_history_missing",
|
|
7987
|
+
retryable: false,
|
|
7988
|
+
};
|
|
7989
|
+
}
|
|
7990
|
+
if (exactApprovedToolCall &&
|
|
7991
|
+
isUnavailableToolCallInput(exactApprovedToolCall.input)) {
|
|
7992
|
+
setResponseStatus(event, 422);
|
|
7993
|
+
return {
|
|
7994
|
+
error: "The agent run failed.",
|
|
7995
|
+
code: "approved_tool_call_input_unavailable",
|
|
7996
|
+
retryable: false,
|
|
7997
|
+
};
|
|
7998
|
+
}
|
|
7999
|
+
if (dispatchToBackground && exactApprovedToolCall) {
|
|
8000
|
+
if (approvedInputRequiresForeground(exactApprovedToolCall.input)) {
|
|
8001
|
+
// The dispatch payload must not persist raw bytes; execute while this request still has them.
|
|
8002
|
+
dispatchToBackground = false;
|
|
8003
|
+
}
|
|
8004
|
+
}
|
|
8005
|
+
const approvedToolCallsForExecution = exactApprovedToolCall
|
|
8006
|
+
? [
|
|
8007
|
+
toolCallCacheKey(exactApprovedToolCall.name, exactApprovedToolCall.input),
|
|
8008
|
+
]
|
|
8009
|
+
: requestedApprovedToolCalls;
|
|
8010
|
+
const resolvedApprovalTurnId = ownerEmail && threadId && approvedToolCallsForExecution?.length
|
|
7838
8011
|
? await resolveAgentToolApprovalTurnId({
|
|
7839
8012
|
ownerEmail,
|
|
7840
8013
|
orgId: getRequestOrgId() ?? null,
|
|
7841
8014
|
threadId,
|
|
7842
8015
|
requestedTurnId: requestTurnId,
|
|
7843
|
-
approvalKeys:
|
|
8016
|
+
approvalKeys: approvedToolCallsForExecution,
|
|
8017
|
+
...(requestedApprovedToolCallAskIds
|
|
8018
|
+
? { approvalId: requestedApprovedToolCallAskIds[0] }
|
|
8019
|
+
: {}),
|
|
7844
8020
|
})
|
|
7845
8021
|
: null;
|
|
8022
|
+
if (requestedApprovedToolCallAskIds?.length && !resolvedApprovalTurnId) {
|
|
8023
|
+
setResponseStatus(event, 409);
|
|
8024
|
+
return {
|
|
8025
|
+
error: "The agent run failed.",
|
|
8026
|
+
code: "approved_tool_call_not_pending",
|
|
8027
|
+
retryable: false,
|
|
8028
|
+
};
|
|
8029
|
+
}
|
|
7846
8030
|
// The continuation marker is client-controlled. Defer setup admission only
|
|
7847
8031
|
// for automatic successors when the named stop and turn can be checked
|
|
7848
8032
|
// under the run-slot lock. A user's manual Continue starts new work and
|
|
@@ -8836,7 +9020,6 @@ export function createProductionAgentHandler(options) {
|
|
|
8836
9020
|
// may truncate tool arguments and intentionally assigns fresh replay ids.
|
|
8837
9021
|
// The loop still consumes only a matching server-created grant for the
|
|
8838
9022
|
// current owner/org/thread/turn/tool/input tuple.
|
|
8839
|
-
const exactApprovedToolCall = findApprovedStructuredToolCall(requestStructuredHistory, requestedApprovedToolCalls);
|
|
8840
9023
|
const firstRequestPayloadDetail = buildFirstRequestPayloadDetail({
|
|
8841
9024
|
isFirstRequest: requestHistory.length === 0,
|
|
8842
9025
|
systemPrompt: requestSystemPrompt,
|
|
@@ -8851,7 +9034,7 @@ export function createProductionAgentHandler(options) {
|
|
|
8851
9034
|
const isClientTurnContinuation = !isBackgroundWorker &&
|
|
8852
9035
|
internalContinuation === true &&
|
|
8853
9036
|
!continueOf &&
|
|
8854
|
-
!
|
|
9037
|
+
!approvedToolCallsForExecution?.length &&
|
|
8855
9038
|
typeof message === "string" &&
|
|
8856
9039
|
message.startsWith(AGENT_INTERNAL_CONTINUE_PROMPT) &&
|
|
8857
9040
|
typeof threadId === "string" &&
|
|
@@ -8921,7 +9104,7 @@ export function createProductionAgentHandler(options) {
|
|
|
8921
9104
|
...(turnInitiator ? { turnInitiator } : {}),
|
|
8922
9105
|
replayCompletedTurn: typeof requestTurnId === "string" &&
|
|
8923
9106
|
Boolean(requestTurnId.trim()) &&
|
|
8924
|
-
!
|
|
9107
|
+
!approvedToolCallsForExecution,
|
|
8925
9108
|
dispatchMode: dispatchToBackground
|
|
8926
9109
|
? "background"
|
|
8927
9110
|
: foregroundSelfChainEligible
|
|
@@ -8982,6 +9165,7 @@ export function createProductionAgentHandler(options) {
|
|
|
8982
9165
|
toolName: binding.toolName,
|
|
8983
9166
|
callId: binding.callId,
|
|
8984
9167
|
approvalKey: binding.approvalKey,
|
|
9168
|
+
...(binding.approvalId ? { approvalId: binding.approvalId } : {}),
|
|
8985
9169
|
};
|
|
8986
9170
|
};
|
|
8987
9171
|
const approvalHooks = {
|
|
@@ -9003,7 +9187,6 @@ export function createProductionAgentHandler(options) {
|
|
|
9003
9187
|
});
|
|
9004
9188
|
},
|
|
9005
9189
|
};
|
|
9006
|
-
const approvedToolCallsForExecution = requestedApprovedToolCalls;
|
|
9007
9190
|
if (isBackgroundWorker &&
|
|
9008
9191
|
(await isTurnAborted(effectiveThreadId, effectiveTurnId))) {
|
|
9009
9192
|
await markRunAborted(runId, "user").catch(() => { });
|
|
@@ -9779,6 +9962,11 @@ export function createProductionAgentHandler(options) {
|
|
|
9779
9962
|
...(approvedToolCallsForExecution
|
|
9780
9963
|
? { approvedToolCalls: approvedToolCallsForExecution }
|
|
9781
9964
|
: {}),
|
|
9965
|
+
...(requestedApprovedToolCallAskIds
|
|
9966
|
+
? {
|
|
9967
|
+
approvedToolCallAskId: requestedApprovedToolCallAskIds[0],
|
|
9968
|
+
}
|
|
9969
|
+
: {}),
|
|
9782
9970
|
onApprovalRequired: approvalHooks.onApprovalRequired,
|
|
9783
9971
|
consumeApproval: approvalHooks.consumeApproval,
|
|
9784
9972
|
isToolAlwaysAllowed: approvalHooks.isToolAlwaysAllowed,
|
|
@@ -9816,6 +10004,11 @@ export function createProductionAgentHandler(options) {
|
|
|
9816
10004
|
threadId: effectiveThreadId,
|
|
9817
10005
|
turnId: effectiveTurnId,
|
|
9818
10006
|
approvedToolCalls: approvedToolCallsForExecution,
|
|
10007
|
+
...(requestedApprovedToolCallAskIds
|
|
10008
|
+
? {
|
|
10009
|
+
approvedToolCallAskId: requestedApprovedToolCallAskIds[0],
|
|
10010
|
+
}
|
|
10011
|
+
: {}),
|
|
9819
10012
|
onApprovalRequired: approvalHooks.onApprovalRequired,
|
|
9820
10013
|
consumeApproval: approvalHooks.consumeApproval,
|
|
9821
10014
|
isToolAlwaysAllowed: approvalHooks.isToolAlwaysAllowed,
|