@agent-native/core 0.204.0 → 0.204.1-nightly-20261008034100
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/dist/action.js +5 -6
- package/dist/agent/auto-continue.d.ts +35 -0
- package/dist/agent/auto-continue.js +38 -0
- package/dist/agent/connection-required-note.d.ts +52 -0
- package/dist/agent/connection-required-note.js +187 -0
- package/dist/agent/jev-tool-prefetch.d.ts +5 -1
- package/dist/agent/jev-tool-prefetch.js +19 -6
- package/dist/agent/previous-turn-note.d.ts +9 -0
- package/dist/agent/previous-turn-note.js +48 -0
- package/dist/agent/production-agent.d.ts +17 -13
- package/dist/agent/production-agent.js +185 -43
- package/dist/agent/reaped-run-thread.d.ts +13 -0
- package/dist/agent/reaped-run-thread.js +45 -0
- package/dist/agent/run-store.d.ts +29 -5
- package/dist/agent/run-store.js +144 -30
- package/dist/agent/thread-data-builder.d.ts +16 -0
- package/dist/agent/thread-data-builder.js +30 -8
- package/dist/agent/thread-message-projection.js +5 -3
- package/dist/agent/tool-search.js +5 -1
- package/dist/agent/types.d.ts +3 -0
- package/dist/audit/config.d.ts +6 -0
- package/dist/audit/config.js +12 -1
- package/dist/audit/index.d.ts +1 -1
- package/dist/audit/index.js +1 -1
- package/dist/audit/store.js +39 -4
- package/dist/cli/skills.d.ts +1 -0
- package/dist/cli/skills.js +1 -1
- package/dist/client/chat/agentkit-agent-native.js +83 -7
- package/dist/client/chat/agentkit-protocol.js +140 -67
- package/dist/client/chat/runtime.js +5 -3
- package/dist/client/use-run-stuck-detection.d.ts +18 -1
- package/dist/client/use-run-stuck-detection.js +115 -75
- package/dist/db/request-telemetry.d.ts +7 -1
- package/dist/db/request-telemetry.js +20 -1
- package/dist/deploy/build.d.ts +25 -1
- package/dist/deploy/build.js +176 -3
- package/dist/deploy/workspace-deploy.js +8 -3
- package/dist/extensions/fetch-tool.js +50 -14
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/integrations/adapters/email.js +11 -3
- package/dist/integrations/adapters/telegram.js +4 -2
- package/dist/jobs/actions/automation-no-op.d.ts +12 -0
- package/dist/jobs/actions/automation-no-op.js +20 -0
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/jobs/background-automation-runner.d.ts +8 -1
- package/dist/jobs/background-automation-runner.js +102 -19
- package/dist/jobs/run-history.d.ts +1 -1
- package/dist/jobs/run-history.js +8 -4
- package/dist/jobs/scheduler.js +25 -12
- package/dist/localization/automation-outcome-messages.d.ts +22 -0
- package/dist/localization/automation-outcome-messages.js +90 -0
- package/dist/localization/default-messages.d.ts +2 -0
- package/dist/localization/default-messages.js +4 -2
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/metrics.d.ts +3 -0
- package/dist/observability/metrics.js +10 -0
- package/dist/observability/migrations.js +22 -0
- package/dist/observability/routes.d.ts +13 -8
- package/dist/observability/routes.js +88 -14
- package/dist/observability/sentiment.d.ts +5 -0
- package/dist/observability/sentiment.js +75 -25
- package/dist/observability/store.d.ts +28 -0
- package/dist/observability/store.js +58 -0
- package/dist/observability/traces.js +37 -5
- package/dist/org/index.d.ts +2 -2
- package/dist/progress/actions.js +1 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
- package/dist/provider-api/actions/provider-api.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.js +6 -2
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.d.ts +1 -0
- package/dist/provider-api/index.js +18 -0
- package/dist/provider-api/result-outcome.d.ts +1 -0
- package/dist/provider-api/result-outcome.js +20 -0
- package/dist/provider-api/staging.js +10 -9
- package/dist/server/agent-chat/prompt-resources.d.ts +8 -2
- package/dist/server/agent-chat/prompt-resources.js +30 -7
- package/dist/server/agent-chat/recurring-jobs-runtime.d.ts +19 -4
- package/dist/server/agent-chat/recurring-jobs-runtime.js +52 -16
- package/dist/server/agent-chat/sweep-trigger-auth.d.ts +18 -0
- package/dist/server/agent-chat/sweep-trigger-auth.js +36 -0
- package/dist/server/agent-chat-plugin.js +20 -13
- package/dist/server/agent-engine-default-model-route.d.ts +2 -2
- package/dist/server/auth.js +4 -4
- package/dist/server/framework-request-handler.js +19 -0
- package/dist/server/http-response-telemetry.js +4 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/request-context.d.ts +6 -0
- package/dist/shared/context-status.d.ts +21 -0
- package/dist/shared/context-status.js +54 -0
- package/dist/templates/chat/app/components/chat/ChatRouteContent.tsx +8 -1
- package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +8 -1
- package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +3 -1
- package/dist/triggers/actions/manage-automation.d.ts +7 -7
- package/dist/triggers/dispatcher.js +10 -7
- package/docs/content/audit-log.mdx +3 -3
- package/docs/content/cloudflare.mdx +27 -0
- package/docs/content/deployment-environment-variables.mdx +2 -0
- package/docs/content/durable-resume.mdx +3 -1
- package/docs/content/environment-variables.mdx +2 -0
- package/docs/content/recurring-jobs.mdx +29 -9
- package/docs/content/vercel.mdx +30 -0
- package/package.json +3 -3
- package/src/templates/chat/app/components/chat/ChatRouteContent.tsx +8 -1
- package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +8 -1
- package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +3 -1
|
@@ -28,25 +28,29 @@ import { parseServiceIdentityEmail } from "../org/service-identity.js";
|
|
|
28
28
|
import { ServicePrincipalRefusedError } from "../org/service-principal-guard.js";
|
|
29
29
|
import { completeRun as completeProgressRun, startRun as startProgressRun, updateRunProgress, } from "../progress/registry.js";
|
|
30
30
|
import { readOptionalKeyCache, writeOptionalKeyCache, } from "../secrets/optional-key-cache.js";
|
|
31
|
-
import { COMPACT_PROMPT_RESOURCES_TOTAL_MAX_CHARS,
|
|
31
|
+
import { COMPACT_PROMPT_RESOURCES_TOTAL_MAX_CHARS, preloadJevContextWithStatus, } from "../server/agent-chat/prompt-resources.js";
|
|
32
32
|
import { isRuntimeVisibleScope, parseSkillFrontmatter, } from "../server/agent-chat/skill-frontmatter.js";
|
|
33
|
+
import { captureError } from "../server/capture-error.js";
|
|
33
34
|
import { canUseDeployCredentialFallbackForRequest, getProviderCredentialAuthFailure, isBuilderGatewayDeployConfigured, readDeployCredentialEnv, resolveBuilderGatewayAuth, } from "../server/credential-provider.js";
|
|
34
35
|
import { orderCredentialScopes } from "../server/credential-read-order.js";
|
|
35
36
|
import { readBody } from "../server/h3-helpers.js";
|
|
36
37
|
import { resolveHostedHarnessPolicy } from "../server/hosted-harness-policy.js";
|
|
37
38
|
import { isPersonalProviderKeyUseRestricted, isPersonalProviderPolicyKey, PERSONAL_PROVIDER_KEYS_RESTRICTED_ERROR_CODE, PERSONAL_PROVIDER_KEYS_RESTRICTED_MESSAGE, } from "../server/personal-provider-key-policy.js";
|
|
38
|
-
import { assertRequestActionSurfaceIsolation, getRequestRunContext, ensureRequestRunContext, getRequestContext, getRequestOrgId, getRequestUserEmail, runWithRequestContext, } from "../server/request-context.js";
|
|
39
|
+
import { assertRequestActionSurfaceIsolation, getRequestRunContext, ensureRequestRunContext, getRequestContext, getRequestAuthCapability, getRequestOrgId, getRequestUserEmail, runWithRequestContext, } from "../server/request-context.js";
|
|
39
40
|
import { secretKeyNames } from "../server/secret-key-aliases.js";
|
|
40
41
|
import { fireInternalDispatch } from "../server/self-dispatch.js";
|
|
41
42
|
import { retryContextFromRequest, } from "../shared/agent-chat-run-not-started.js";
|
|
42
43
|
import { ANALYTICS_CLIENT_PLATFORM_BODY_FIELD } from "../shared/analytics-platform.js";
|
|
44
|
+
import { isContextDegraded, preloadedContextUnavailableNote, readReportedContextStatus, screenContextUnavailableNote, SELECTION_CONTEXT_UNAVAILABLE_NOTE, worstContextStatus, } from "../shared/context-status.js";
|
|
43
45
|
import { parseBase64DataUrl } from "../shared/data-url.js";
|
|
44
46
|
import { stripDiagnosticSnippets } from "../shared/diagnostic-snippet.js";
|
|
45
47
|
import { isReasoningEffort, normalizeReasoningEffortForRequest, stepDownReasoningEffort, } from "../shared/reasoning-effort.js";
|
|
46
48
|
import { SYNTHETIC_TRAFFIC_BETA_E2E, SYNTHETIC_TRAFFIC_HEADER, } from "../shared/test-traffic.js";
|
|
47
49
|
import { actionPreparationContinuationNote } from "./action-continuation-guidance.js";
|
|
48
50
|
import { drainAgentWarnings, formatAgentWarningsForToolResult, } from "./action-warnings.js";
|
|
51
|
+
import { CONTINUE_UNAVAILABLE_CODE, } from "./auto-continue.js";
|
|
49
52
|
import { clipHead } from "./clip-text.js";
|
|
53
|
+
import { connectionRequiredMessage, priorConnectionContextNote, resolvePriorConnectionNote, } from "./connection-required-note.js";
|
|
50
54
|
import { buildSystemManifestSections, readContextXraySystemSections, } from "./context-xray/manifest.js";
|
|
51
55
|
import { AGENT_CHAT_BACKGROUND_RUN_FIELD, AGENT_CHAT_PROCESS_RUN_PATH, backgroundRuntimeDiagnosticDetail, dispatchPathTargetsNetlifyBackgroundFunction, isAgentChatDurableBackgroundEnabled, isAgentChatForegroundSelfChainEnabled, isInBackgroundFunctionRuntime, resolveAgentChatProcessRunDispatchPath, shouldUseBackgroundFunctionTimeoutForWorker, } from "./durable-background.js";
|
|
52
56
|
import { applyContextXrayTransformForIteration } from "./engine/context-directives-transform.js";
|
|
@@ -226,6 +230,10 @@ export function normalizeChatScope(value) {
|
|
|
226
230
|
function appStateKeyForBrowserTab(key, browserTabId) {
|
|
227
231
|
return browserTabId ? `${key}:${browserTabId}` : key;
|
|
228
232
|
}
|
|
233
|
+
/** `readAppState` throws when the request has no identity: that is no user to read for, not a failed read. */
|
|
234
|
+
function hasAppStateIdentity() {
|
|
235
|
+
return Boolean(getRequestUserEmail() || getRequestAuthCapability());
|
|
236
|
+
}
|
|
229
237
|
async function readAppStateForBrowserTab(key, browserTabId) {
|
|
230
238
|
if (!browserTabId)
|
|
231
239
|
return (await readAppState(key));
|
|
@@ -5108,6 +5116,7 @@ export async function runAgentLoop(opts) {
|
|
|
5108
5116
|
let result;
|
|
5109
5117
|
let chatUIResult;
|
|
5110
5118
|
let isError = false;
|
|
5119
|
+
let toolErrorCode;
|
|
5111
5120
|
let mcpApp;
|
|
5112
5121
|
let toolResultImages;
|
|
5113
5122
|
let toolArtifacts = [];
|
|
@@ -5334,12 +5343,15 @@ export async function runAgentLoop(opts) {
|
|
|
5334
5343
|
}
|
|
5335
5344
|
}
|
|
5336
5345
|
catch (err) {
|
|
5346
|
+
toolErrorCode = isActionContractError(err)
|
|
5347
|
+
? err.errorCode
|
|
5348
|
+
: undefined;
|
|
5337
5349
|
if (signal.aborted) {
|
|
5338
5350
|
result = INTERRUPTED_TOOL_RESULT_MARKER;
|
|
5339
5351
|
}
|
|
5340
5352
|
else if (isAgentConnectionRequiredError(err)) {
|
|
5341
|
-
const message = sanitizeToolErrorValue(err.message) ||
|
|
5342
|
-
`Connect ${err.provider} to continue
|
|
5353
|
+
const message = connectionRequiredMessage(sanitizeToolErrorValue(err.message) ||
|
|
5354
|
+
`Connect ${err.provider} to continue.`, err.reason);
|
|
5343
5355
|
result = sanitizeToolErrorValue(err.toolResult || message);
|
|
5344
5356
|
requestedConnection ??= {
|
|
5345
5357
|
requestId: randomUUID(),
|
|
@@ -5443,6 +5455,7 @@ export async function runAgentLoop(opts) {
|
|
|
5443
5455
|
input: toolCall.input,
|
|
5444
5456
|
result,
|
|
5445
5457
|
...(isError ? { isError: true } : {}),
|
|
5458
|
+
...(toolErrorCode ? { errorCode: toolErrorCode } : {}),
|
|
5446
5459
|
...(isError
|
|
5447
5460
|
? { completedSideEffect: false }
|
|
5448
5461
|
: receipt
|
|
@@ -6676,12 +6689,28 @@ export function createProductionAgentHandler(options) {
|
|
|
6676
6689
|
return { error: "Invalid request body" };
|
|
6677
6690
|
}
|
|
6678
6691
|
}
|
|
6679
|
-
const { message, history = [], structuredHistory, references = [], threadId, attachments, displayMessage, parentId, queuedMessageId, queuedMessageClaimId, agentKitMessageId: requestedAgentKitMessageId, internalContinuation, autoContinueOfRunId: requestedAutoContinueOfRunId, turnId: requestTurnId, model: requestModel, engine: requestEngine, effort: requestEffort, browserTabId, scope, harness: requestHarness, trackInRunsTray, skipPendingSelectionContext, } = body;
|
|
6680
|
-
const
|
|
6681
|
-
typeof
|
|
6682
|
-
|
|
6683
|
-
?
|
|
6692
|
+
const { message, history = [], structuredHistory, references = [], threadId, attachments, displayMessage, parentId, queuedMessageId, queuedMessageClaimId, agentKitMessageId: requestedAgentKitMessageId, internalContinuation, autoContinueOfRunId: requestedAutoContinueOfRunId, continueOfRunId: requestedContinueOfRunId, turnId: requestTurnId, model: requestModel, engine: requestEngine, effort: requestEffort, browserTabId, scope, harness: requestHarness, trackInRunsTray, skipPendingSelectionContext, } = body;
|
|
6693
|
+
const continuedRunId = (requested) => internalContinuation === true &&
|
|
6694
|
+
typeof requested === "string" &&
|
|
6695
|
+
requested.trim().length <= 200
|
|
6696
|
+
? requested.trim() || undefined
|
|
6684
6697
|
: undefined;
|
|
6698
|
+
const autoContinueOfRunId = continuedRunId(requestedAutoContinueOfRunId);
|
|
6699
|
+
// The stopped run this request resumes in its own turn, from the turn's
|
|
6700
|
+
// history and journal, whether the chat or a person asked.
|
|
6701
|
+
const continueOf = autoContinueOfRunId
|
|
6702
|
+
? { runId: autoContinueOfRunId, trigger: "auto" }
|
|
6703
|
+
: (() => {
|
|
6704
|
+
const runId = continuedRunId(requestedContinueOfRunId);
|
|
6705
|
+
return runId ? { runId, trigger: "manual" } : undefined;
|
|
6706
|
+
})();
|
|
6707
|
+
const continueRefusal = (code) => ({
|
|
6708
|
+
error: continueOf?.trigger === "manual"
|
|
6709
|
+
? "This turn can no longer be continued."
|
|
6710
|
+
: "This turn will not continue automatically.",
|
|
6711
|
+
code,
|
|
6712
|
+
retryable: false,
|
|
6713
|
+
});
|
|
6685
6714
|
if (requestEngine !== undefined && typeof requestEngine !== "string") {
|
|
6686
6715
|
setResponseStatus(event, 400);
|
|
6687
6716
|
return { error: "engine must be a string" };
|
|
@@ -6834,6 +6863,7 @@ export function createProductionAgentHandler(options) {
|
|
|
6834
6863
|
});
|
|
6835
6864
|
let jevPromptCandidates = [];
|
|
6836
6865
|
let jevFallbackCandidateIds = [];
|
|
6866
|
+
const preparedReferenceStatus = readReportedContextStatus(preparedRequest);
|
|
6837
6867
|
if (preparedRequest) {
|
|
6838
6868
|
if (typeof preparedRequest.message === "string" &&
|
|
6839
6869
|
preparedRequest.message.trim().length > 0) {
|
|
@@ -7089,7 +7119,7 @@ export function createProductionAgentHandler(options) {
|
|
|
7089
7119
|
configuredEffort: options.reasoningEffort,
|
|
7090
7120
|
});
|
|
7091
7121
|
options.onEngineResolved?.(engine, effectiveModel);
|
|
7092
|
-
console.log(`[agent-chat] resolved engine=${engine.name} model=${effectiveModel} requestModel=${requestModel ?? "(none)"} requestEngine=${requestEngine ?? "(none)"} modelSource=${modelSelectionSource} turnId=${requestTurnId ?? "(none)"}`);
|
|
7122
|
+
console.log(`[agent-chat] resolved engine=${engine.name} model=${effectiveModel} requestModel=${requestModel ?? "(none)"} requestEngine=${requestEngine ?? "(none)"} modelSource=${modelSelectionSource} engineDefault=${engine.defaultModel} effort=${reasoningEffort ?? "unset"} turnId=${requestTurnId ?? "(none)"}`);
|
|
7093
7123
|
if (!(await isResolvedEngineUsableForRequest(engine, {
|
|
7094
7124
|
apiKey: effectiveApiKey,
|
|
7095
7125
|
credentialIdentity,
|
|
@@ -7180,6 +7210,17 @@ export function createProductionAgentHandler(options) {
|
|
|
7180
7210
|
return buildCurrentTimeUserContext();
|
|
7181
7211
|
}
|
|
7182
7212
|
})();
|
|
7213
|
+
// `empty` (no navigation yet) stays silent; a timeout or a throw adds a
|
|
7214
|
+
// note, because the model would otherwise read it as an app with no page.
|
|
7215
|
+
const screenStatuses = { screen: "empty", url: "empty", selection: "empty" };
|
|
7216
|
+
// Once a cap fires the model has the fallback note, so a read that
|
|
7217
|
+
// resolves late must not change what the trace says it saw.
|
|
7218
|
+
const noteScreenStatus = (source, status) => {
|
|
7219
|
+
if (screenStatuses[source] !== "timed_out") {
|
|
7220
|
+
screenStatuses[source] = status;
|
|
7221
|
+
}
|
|
7222
|
+
};
|
|
7223
|
+
const screenUnavailableNote = screenContextUnavailableNote(Boolean(surfacedRequestActions["view-screen"]));
|
|
7183
7224
|
const screenContextThunk = () => (async () => {
|
|
7184
7225
|
const screenStart = Date.now();
|
|
7185
7226
|
try {
|
|
@@ -7194,18 +7235,24 @@ export function createProductionAgentHandler(options) {
|
|
|
7194
7235
|
const screenText = typeof result === "string"
|
|
7195
7236
|
? result
|
|
7196
7237
|
: JSON.stringify(result, null, 2);
|
|
7238
|
+
noteScreenStatus("screen", "ok");
|
|
7197
7239
|
return `\n\n<current-screen>\n${capScreenContext(screenText)}\n</current-screen>`;
|
|
7198
7240
|
}
|
|
7199
7241
|
}
|
|
7200
7242
|
else {
|
|
7201
7243
|
const navigation = await readAppStateForBrowserTab("navigation", requestBrowserTabId);
|
|
7202
7244
|
if (navigation) {
|
|
7245
|
+
noteScreenStatus("screen", "ok");
|
|
7203
7246
|
return `\n\n<current-screen>\n${capScreenContext(JSON.stringify(navigation, null, 2))}\n</current-screen>`;
|
|
7204
7247
|
}
|
|
7205
7248
|
}
|
|
7206
7249
|
}
|
|
7207
|
-
catch {
|
|
7208
|
-
|
|
7250
|
+
catch (error) {
|
|
7251
|
+
if (!hasAppStateIdentity())
|
|
7252
|
+
return "";
|
|
7253
|
+
noteScreenStatus("screen", "failed");
|
|
7254
|
+
console.warn("[agent-chat] current-screen context unavailable:", error instanceof Error ? error.message : String(error));
|
|
7255
|
+
return screenUnavailableNote;
|
|
7209
7256
|
}
|
|
7210
7257
|
finally {
|
|
7211
7258
|
setupMarks.screenMs = Date.now() - screenStart;
|
|
@@ -7241,11 +7288,16 @@ export function createProductionAgentHandler(options) {
|
|
|
7241
7288
|
if (settingsPage)
|
|
7242
7289
|
lines.push(settingsPage);
|
|
7243
7290
|
}
|
|
7291
|
+
noteScreenStatus("url", "ok");
|
|
7244
7292
|
return `\n\n<current-url>\n${lines.join("\n")}\n</current-url>`;
|
|
7245
7293
|
}
|
|
7246
7294
|
}
|
|
7247
|
-
catch {
|
|
7248
|
-
|
|
7295
|
+
catch (error) {
|
|
7296
|
+
if (!hasAppStateIdentity())
|
|
7297
|
+
return "";
|
|
7298
|
+
noteScreenStatus("url", "failed");
|
|
7299
|
+
console.warn("[agent-chat] current-url context unavailable:", error instanceof Error ? error.message : String(error));
|
|
7300
|
+
return screenUnavailableNote;
|
|
7249
7301
|
}
|
|
7250
7302
|
return "";
|
|
7251
7303
|
})();
|
|
@@ -7260,12 +7312,17 @@ export function createProductionAgentHandler(options) {
|
|
|
7260
7312
|
const capturedAt = typeof sel.capturedAt === "number" ? sel.capturedAt : 0;
|
|
7261
7313
|
if (Date.now() - capturedAt > SELECTION_TTL_MS)
|
|
7262
7314
|
return "";
|
|
7315
|
+
noteScreenStatus("selection", "ok");
|
|
7263
7316
|
return (`\n\nThe user has selected the following text and pressed Cmd I to focus the agent. ` +
|
|
7264
7317
|
`Treat this as the immediate context to act on:\n` +
|
|
7265
7318
|
`<selection>\n${capSelectionContext(sel.text)}\n</selection>`);
|
|
7266
7319
|
}
|
|
7267
|
-
catch {
|
|
7268
|
-
|
|
7320
|
+
catch (error) {
|
|
7321
|
+
if (!hasAppStateIdentity())
|
|
7322
|
+
return "";
|
|
7323
|
+
noteScreenStatus("selection", "failed");
|
|
7324
|
+
console.warn("[agent-chat] selection context unavailable:", error instanceof Error ? error.message : String(error));
|
|
7325
|
+
return SELECTION_CONTEXT_UNAVAILABLE_NOTE;
|
|
7269
7326
|
}
|
|
7270
7327
|
return "";
|
|
7271
7328
|
})();
|
|
@@ -7376,7 +7433,7 @@ export function createProductionAgentHandler(options) {
|
|
|
7376
7433
|
source: "default",
|
|
7377
7434
|
};
|
|
7378
7435
|
const systemPromptTimeoutError = new Error("system prompt preparation timed out before the agent could start");
|
|
7379
|
-
let [systemPrompt, timeBlock, screenBlock, urlBlock, selectionBlock, filesContext, loopSettings, enrichedMessage, jevContextCredentials,] = await Promise.all([
|
|
7436
|
+
let [systemPrompt, timeBlock, screenBlock, urlBlock, selectionBlock, filesContext, loopSettings, enrichedMessage, jevContextCredentials, priorConnection,] = await Promise.all([
|
|
7380
7437
|
presendCap("systemPrompt", systemPromptThunk, "", 13000, () => {
|
|
7381
7438
|
// An empty configured prompt is valid, but an empty timeout fallback
|
|
7382
7439
|
// is not: required app instructions must either finish or fail before
|
|
@@ -7385,13 +7442,30 @@ export function createProductionAgentHandler(options) {
|
|
|
7385
7442
|
systemPromptError ??= systemPromptTimeoutError;
|
|
7386
7443
|
}),
|
|
7387
7444
|
presendCap("time", timeContextThunk, "", 9000),
|
|
7388
|
-
presendCap("screen", screenContextThunk,
|
|
7389
|
-
|
|
7390
|
-
|
|
7445
|
+
presendCap("screen", screenContextThunk, screenUnavailableNote, 9000, () => {
|
|
7446
|
+
screenStatuses.screen = "timed_out";
|
|
7447
|
+
}),
|
|
7448
|
+
presendCap("url", urlContextThunk, screenUnavailableNote, 9000, () => {
|
|
7449
|
+
screenStatuses.url = "timed_out";
|
|
7450
|
+
}),
|
|
7451
|
+
presendCap("selection", selectionContextThunk, SELECTION_CONTEXT_UNAVAILABLE_NOTE, 9000, () => {
|
|
7452
|
+
screenStatuses.selection = "timed_out";
|
|
7453
|
+
}),
|
|
7391
7454
|
presendCap("files", filesContextThunk, "", 12000),
|
|
7392
7455
|
presendCap("loopSettings", loopSettingsThunk, fallbackLoopSettings, 9000),
|
|
7393
7456
|
presendCap("enrichedMessage", enrichedMessageThunk, requestMessage, 9000),
|
|
7394
7457
|
presendCap("jevContextCredentials", () => getJevContextCredentials(ownerEmail ?? getRequestUserEmail()), { apiKey: undefined, personalApiKey: undefined, builderAuth: null }, 9000),
|
|
7458
|
+
presendCap("priorConnection",
|
|
7459
|
+
// The foreground of a dispatched run never prompts the model; the
|
|
7460
|
+
// worker re-reads, so reading here would pay for it twice.
|
|
7461
|
+
() => threadId && !dispatchToBackground
|
|
7462
|
+
? resolvePriorConnectionNote({
|
|
7463
|
+
threadId,
|
|
7464
|
+
orgId: getRequestOrgId() ?? null,
|
|
7465
|
+
appId: options.appId,
|
|
7466
|
+
excludeRunId: backgroundRunMarker?.runId,
|
|
7467
|
+
})
|
|
7468
|
+
: Promise.resolve({ status: "none" }), { status: "unreadable", error: "timed out" }, 9000),
|
|
7395
7469
|
]);
|
|
7396
7470
|
setupMark("ctxAll");
|
|
7397
7471
|
workerStep("context_all");
|
|
@@ -7409,7 +7483,21 @@ export function createProductionAgentHandler(options) {
|
|
|
7409
7483
|
},
|
|
7410
7484
|
});
|
|
7411
7485
|
}
|
|
7486
|
+
// Screen and URL share one note; the same failure needn't be told twice.
|
|
7487
|
+
if (urlBlock === screenBlock)
|
|
7488
|
+
urlBlock = "";
|
|
7412
7489
|
const screenContext = timeBlock + screenBlock + urlBlock + selectionBlock;
|
|
7490
|
+
// Referenced agents don't share this run's tools, so a note telling the
|
|
7491
|
+
// model to call view-screen would send them looking for a tool they lack.
|
|
7492
|
+
const withoutUnavailableNote = (block) => block === screenUnavailableNote ||
|
|
7493
|
+
block === SELECTION_CONTEXT_UNAVAILABLE_NOTE
|
|
7494
|
+
? ""
|
|
7495
|
+
: block;
|
|
7496
|
+
const referencedAgentContext = timeBlock +
|
|
7497
|
+
withoutUnavailableNote(screenBlock) +
|
|
7498
|
+
withoutUnavailableNote(urlBlock) +
|
|
7499
|
+
withoutUnavailableNote(selectionBlock);
|
|
7500
|
+
const screenStatus = worstContextStatus(...Object.values(screenStatuses));
|
|
7413
7501
|
const surfacedActionRegistry = requestMode === "plan"
|
|
7414
7502
|
? createPlanModeActionRegistry(surfacedRequestActions)
|
|
7415
7503
|
: surfacedRequestActions;
|
|
@@ -7434,7 +7522,7 @@ export function createProductionAgentHandler(options) {
|
|
|
7434
7522
|
const jevContextMaxChars = options.jevContextCompact
|
|
7435
7523
|
? Math.max(0, COMPACT_PROMPT_RESOURCES_TOTAL_MAX_CHARS - systemPrompt.length - 2)
|
|
7436
7524
|
: undefined;
|
|
7437
|
-
const [requestTools,
|
|
7525
|
+
const [requestTools, jevPreload] = await Promise.all([
|
|
7438
7526
|
preloadJevTools({
|
|
7439
7527
|
request: jevRequestContext,
|
|
7440
7528
|
skip: Boolean(internalContinuation || dispatchToBackground),
|
|
@@ -7447,7 +7535,7 @@ export function createProductionAgentHandler(options) {
|
|
|
7447
7535
|
availableTools: availableRequestTools,
|
|
7448
7536
|
readOnlyOnly: requestMode === "plan",
|
|
7449
7537
|
}),
|
|
7450
|
-
|
|
7538
|
+
preloadJevContextWithStatus({
|
|
7451
7539
|
request: jevRequestContext,
|
|
7452
7540
|
appId: options.appId,
|
|
7453
7541
|
owner: ownerEmail ?? undefined,
|
|
@@ -7464,8 +7552,23 @@ export function createProductionAgentHandler(options) {
|
|
|
7464
7552
|
fallbackCandidateIds: jevFallbackCandidateIds,
|
|
7465
7553
|
}),
|
|
7466
7554
|
]);
|
|
7555
|
+
const jevContext = jevPreload.context;
|
|
7467
7556
|
if (jevContext)
|
|
7468
7557
|
systemPrompt = `${systemPrompt}\n\n${jevContext}`;
|
|
7558
|
+
const prefetchStatus = worstContextStatus(jevPreload.status, preparedReferenceStatus);
|
|
7559
|
+
if (runContext) {
|
|
7560
|
+
runContext.contextStatus = {
|
|
7561
|
+
prefetch: prefetchStatus,
|
|
7562
|
+
screen: screenStatus,
|
|
7563
|
+
};
|
|
7564
|
+
}
|
|
7565
|
+
// Per-turn, so the stable system prompt prefix keeps caching.
|
|
7566
|
+
const prefetchNote = prefetchStatus && isContextDegraded(prefetchStatus)
|
|
7567
|
+
? preloadedContextUnavailableNote(prefetchStatus, {
|
|
7568
|
+
// The other source delivered, so only part of the context is missing.
|
|
7569
|
+
partial: jevPreload.status === "ok" || preparedReferenceStatus === "ok",
|
|
7570
|
+
})
|
|
7571
|
+
: "";
|
|
7469
7572
|
const contextXraySystemSections = [
|
|
7470
7573
|
...readContextXraySystemSections(event),
|
|
7471
7574
|
...(jevContext
|
|
@@ -7508,7 +7611,12 @@ export function createProductionAgentHandler(options) {
|
|
|
7508
7611
|
? "\n\n<plan-mode-note>Connected external agent mentions were not called because Plan mode is read-only. Mention that they can be called after the user switches to Act mode if the plan needs them.</plan-mode-note>"
|
|
7509
7612
|
: "";
|
|
7510
7613
|
const userContent = buildUserContentWithAttachments({
|
|
7511
|
-
text: enrichedMessage +
|
|
7614
|
+
text: enrichedMessage +
|
|
7615
|
+
screenContext +
|
|
7616
|
+
prefetchNote +
|
|
7617
|
+
priorConnectionContextNote(priorConnection) +
|
|
7618
|
+
filesContext +
|
|
7619
|
+
planModeAgentNote,
|
|
7512
7620
|
attachments: requestAttachments,
|
|
7513
7621
|
});
|
|
7514
7622
|
const historyMessages = structuredHistoryToEngineMessages(structuredHistory) ??
|
|
@@ -7603,9 +7711,7 @@ export function createProductionAgentHandler(options) {
|
|
|
7603
7711
|
...(dispatchToBackground
|
|
7604
7712
|
? { dispatchPayload: JSON.stringify(body) }
|
|
7605
7713
|
: {}),
|
|
7606
|
-
...(
|
|
7607
|
-
? { autoContinueOf: autoContinueOfRunId }
|
|
7608
|
-
: {}),
|
|
7714
|
+
...(continueOf ? { continueOf } : {}),
|
|
7609
7715
|
});
|
|
7610
7716
|
}
|
|
7611
7717
|
catch (error) {
|
|
@@ -7621,14 +7727,10 @@ export function createProductionAgentHandler(options) {
|
|
|
7621
7727
|
await setupResumeClaim?.release();
|
|
7622
7728
|
return { ok: true, stopped: true };
|
|
7623
7729
|
}
|
|
7624
|
-
if (slot.
|
|
7730
|
+
if (slot.continueRefused) {
|
|
7625
7731
|
await setupResumeClaim?.release();
|
|
7626
7732
|
setResponseStatus(event, 409);
|
|
7627
|
-
return
|
|
7628
|
-
error: "This turn will not continue automatically.",
|
|
7629
|
-
code: slot.autoContinueRefused,
|
|
7630
|
-
retryable: false,
|
|
7631
|
-
};
|
|
7733
|
+
return continueRefusal(slot.continueRefused);
|
|
7632
7734
|
}
|
|
7633
7735
|
if (slot.completedRunId) {
|
|
7634
7736
|
const stream = await replayCompletedTurn(threadId, effectiveTurnId);
|
|
@@ -7696,21 +7798,31 @@ export function createProductionAgentHandler(options) {
|
|
|
7696
7798
|
let turnInputTokens = Number.isFinite(priorTurnInputTokensFromBody)
|
|
7697
7799
|
? Math.max(0, priorTurnInputTokensFromBody)
|
|
7698
7800
|
: 0;
|
|
7699
|
-
// A server successor and
|
|
7700
|
-
// the same way: the thread's tool calls and results, plus the turn's
|
|
7801
|
+
// A server successor and a continuation, automatic or chosen, resume the
|
|
7802
|
+
// same turn the same way: the thread's tool calls and results, plus the turn's
|
|
7701
7803
|
// journal of finished steps, so nothing already done is sent again.
|
|
7702
|
-
if ((isChainedBackgroundContinuation ||
|
|
7703
|
-
effectiveThreadId) {
|
|
7804
|
+
if ((isChainedBackgroundContinuation || continueOf) && effectiveThreadId) {
|
|
7704
7805
|
try {
|
|
7705
7806
|
const { getThread } = await import("../chat-threads/store.js");
|
|
7706
|
-
const { resumeThreadHistoryForRequest } = await import("./thread-data-builder.js");
|
|
7707
|
-
const
|
|
7807
|
+
const { latestPromptTurnId, resumeThreadHistoryForRequest } = await import("./thread-data-builder.js");
|
|
7808
|
+
const threadData = (await getThread(effectiveThreadId))?.threadData;
|
|
7809
|
+
const { messages: resumed, foundTurnPrompt } = resumeThreadHistoryForRequest(threadData);
|
|
7708
7810
|
// A continuation always follows a stopped run, so a thread without
|
|
7709
7811
|
// that turn's prompt means its history was lost, not that there was
|
|
7710
7812
|
// none. A successor stays best-effort and resumes from what is there.
|
|
7711
|
-
if (
|
|
7813
|
+
if (continueOf && !foundTurnPrompt) {
|
|
7712
7814
|
throw new Error(`thread ${effectiveThreadId} has no turn prompt`);
|
|
7713
7815
|
}
|
|
7816
|
+
// Resuming takes the thread's newest prompt, so a newer one, even one
|
|
7817
|
+
// whose run never started, would run under this turn's journal.
|
|
7818
|
+
const promptTurnId = continueOf && threadData ? latestPromptTurnId(threadData) : undefined;
|
|
7819
|
+
if (promptTurnId && promptTurnId !== effectiveTurnId) {
|
|
7820
|
+
if (await updateRunStatusIfRunning(runId, "errored")) {
|
|
7821
|
+
await setRunTerminalReason(runId, CONTINUE_UNAVAILABLE_CODE);
|
|
7822
|
+
}
|
|
7823
|
+
setResponseStatus(event, 409);
|
|
7824
|
+
return continueRefusal(CONTINUE_UNAVAILABLE_CODE);
|
|
7825
|
+
}
|
|
7714
7826
|
if (resumed.length > 0) {
|
|
7715
7827
|
const actionPreparationTool = typeof backgroundRunMarker?.actionPreparationTool === "string" &&
|
|
7716
7828
|
backgroundRunMarker.actionPreparationTool.trim()
|
|
@@ -7720,7 +7832,7 @@ export function createProductionAgentHandler(options) {
|
|
|
7720
7832
|
? backgroundRunMarker.continuationReason
|
|
7721
7833
|
: "run_timeout";
|
|
7722
7834
|
const journalRead = await loadPriorTurnToolCallJournal(effectiveThreadId, effectiveTurnId);
|
|
7723
|
-
if (
|
|
7835
|
+
if (continueOf && journalRead.status === "unreadable") {
|
|
7724
7836
|
throw new Error(journalRead.error);
|
|
7725
7837
|
}
|
|
7726
7838
|
const journalNote = journalRead.status === "read" && journalRead.toolCallJournal
|
|
@@ -7735,7 +7847,7 @@ export function createProductionAgentHandler(options) {
|
|
|
7735
7847
|
}
|
|
7736
7848
|
}
|
|
7737
7849
|
catch (error) {
|
|
7738
|
-
if (
|
|
7850
|
+
if (continueOf) {
|
|
7739
7851
|
// The browser's history lacks the stopped run's tool results, so
|
|
7740
7852
|
// continuing from it could repeat a step that already finished.
|
|
7741
7853
|
console.warn(`[agent-chat] auto-continue history unreadable for thread ${effectiveThreadId}:`, error);
|
|
@@ -7767,6 +7879,22 @@ export function createProductionAgentHandler(options) {
|
|
|
7767
7879
|
console.warn(`[agent-chat] history recovery failed for thread ${threadId}; continuing with no prior context:`, err);
|
|
7768
7880
|
}
|
|
7769
7881
|
}
|
|
7882
|
+
if (!internalContinuation && !isChainedBackgroundContinuation && threadId) {
|
|
7883
|
+
try {
|
|
7884
|
+
const { loadStoppedPreviousTurnNote } = await import("./previous-turn-note.js");
|
|
7885
|
+
const note = await loadStoppedPreviousTurnNote(threadId, effectiveTurnId);
|
|
7886
|
+
const prompt = messages.at(-1);
|
|
7887
|
+
if (note && prompt?.role === "user") {
|
|
7888
|
+
prompt.content = [{ type: "text", text: note }, ...prompt.content];
|
|
7889
|
+
}
|
|
7890
|
+
}
|
|
7891
|
+
catch (err) {
|
|
7892
|
+
captureError(err, {
|
|
7893
|
+
tags: { source: "agent-chat", failureClass: "previous-turn-note" },
|
|
7894
|
+
extra: { threadId, turnId: effectiveTurnId },
|
|
7895
|
+
});
|
|
7896
|
+
}
|
|
7897
|
+
}
|
|
7770
7898
|
setupMark("depsThread");
|
|
7771
7899
|
workerStep("owner_thread");
|
|
7772
7900
|
if (options.onRunPrepared && !internalContinuation && !isBackgroundWorker) {
|
|
@@ -8166,7 +8294,10 @@ export function createProductionAgentHandler(options) {
|
|
|
8166
8294
|
{
|
|
8167
8295
|
role: "user",
|
|
8168
8296
|
content: [
|
|
8169
|
-
{
|
|
8297
|
+
{
|
|
8298
|
+
type: "text",
|
|
8299
|
+
text: enrichedMessage + referencedAgentContext,
|
|
8300
|
+
},
|
|
8170
8301
|
],
|
|
8171
8302
|
},
|
|
8172
8303
|
],
|
|
@@ -8259,7 +8390,7 @@ export function createProductionAgentHandler(options) {
|
|
|
8259
8390
|
const responseText = await callConnectedAgentReference({
|
|
8260
8391
|
agent: ref.name,
|
|
8261
8392
|
path: ref.path,
|
|
8262
|
-
message: enrichedMessage +
|
|
8393
|
+
message: enrichedMessage + referencedAgentContext,
|
|
8263
8394
|
send,
|
|
8264
8395
|
callAgent,
|
|
8265
8396
|
resolveCallerAuth: resolveA2ACallerAuth,
|
|
@@ -8416,6 +8547,17 @@ export function createProductionAgentHandler(options) {
|
|
|
8416
8547
|
: undefined,
|
|
8417
8548
|
metadata: {
|
|
8418
8549
|
modelSelectionSource,
|
|
8550
|
+
// What the request asked for; the loop may lower it on retry.
|
|
8551
|
+
reasoningEffortRequested: reasoningEffort ?? null,
|
|
8552
|
+
...(prefetchStatus
|
|
8553
|
+
? { contextPrefetchStatus: prefetchStatus }
|
|
8554
|
+
: {}),
|
|
8555
|
+
...(screenStatus
|
|
8556
|
+
? { screenContextStatus: screenStatus }
|
|
8557
|
+
: {}),
|
|
8558
|
+
...(priorConnection.status !== "none"
|
|
8559
|
+
? { priorConnectionRequest: priorConnection.status }
|
|
8560
|
+
: {}),
|
|
8419
8561
|
...(turnUsageLabel ? { label: turnUsageLabel } : {}),
|
|
8420
8562
|
...(experimentAssignments.length > 0
|
|
8421
8563
|
? { experimentAssignments }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Saves the reply of a run the server ended because its worker stopped
|
|
3
|
+
* (a crash, a killed function) into the thread, the way a run that finishes
|
|
4
|
+
* saves its own. That worker held the reply only in memory, so without this
|
|
5
|
+
* the turn's finished tool calls exist only in the run ledger, which is
|
|
6
|
+
* pruned, and the thread forgets an email already went out.
|
|
7
|
+
*
|
|
8
|
+
* A run continued in its turn is saved as the first part of that turn's
|
|
9
|
+
* reply; one with nothing after it keeps its error. Nothing is saved once a
|
|
10
|
+
* later turn started or a later prompt was saved, because the reply would
|
|
11
|
+
* land under that prompt instead of its own.
|
|
12
|
+
*/
|
|
13
|
+
export declare function foldReapedRunIntoThread(runId: string): Promise<void>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getThread, updateThreadData, withThreadDataLock, } from "../chat-threads/store.js";
|
|
2
|
+
import { readStoppedRunForThreadFold } from "./run-store.js";
|
|
3
|
+
import { buildAssistantMessage, extractThreadMeta, foldAssistantTurn, isRunPrompt, normalizeThreadRepository, } from "./thread-data-builder.js";
|
|
4
|
+
/**
|
|
5
|
+
* Saves the reply of a run the server ended because its worker stopped
|
|
6
|
+
* (a crash, a killed function) into the thread, the way a run that finishes
|
|
7
|
+
* saves its own. That worker held the reply only in memory, so without this
|
|
8
|
+
* the turn's finished tool calls exist only in the run ledger, which is
|
|
9
|
+
* pruned, and the thread forgets an email already went out.
|
|
10
|
+
*
|
|
11
|
+
* A run continued in its turn is saved as the first part of that turn's
|
|
12
|
+
* reply; one with nothing after it keeps its error. Nothing is saved once a
|
|
13
|
+
* later turn started or a later prompt was saved, because the reply would
|
|
14
|
+
* land under that prompt instead of its own.
|
|
15
|
+
*/
|
|
16
|
+
export async function foldReapedRunIntoThread(runId) {
|
|
17
|
+
const run = await readStoppedRunForThreadFold(runId);
|
|
18
|
+
if (!run || run.laterTurnStarted)
|
|
19
|
+
return;
|
|
20
|
+
const assistant = buildAssistantMessage(run.events, runId, {
|
|
21
|
+
turnId: run.turnId,
|
|
22
|
+
suppressInternalContinuation: run.continuedInTurn,
|
|
23
|
+
});
|
|
24
|
+
if (!assistant)
|
|
25
|
+
return;
|
|
26
|
+
await withThreadDataLock(run.threadId, async () => {
|
|
27
|
+
const thread = await getThread(run.threadId);
|
|
28
|
+
if (!thread)
|
|
29
|
+
return;
|
|
30
|
+
const repo = normalizeThreadRepository(JSON.parse(thread.threadData || "{}"));
|
|
31
|
+
const last = repo.messages.at(-1)?.message ?? repo.messages.at(-1);
|
|
32
|
+
const ownsLast = last?.role === "user"
|
|
33
|
+
? isRunPrompt(last, { runId, ...run })
|
|
34
|
+
: last?.role === "assistant" &&
|
|
35
|
+
last.metadata?.custom?.turnId === run.turnId;
|
|
36
|
+
if (!ownsLast)
|
|
37
|
+
return;
|
|
38
|
+
const folded = foldAssistantTurn(repo, assistant, {
|
|
39
|
+
runId,
|
|
40
|
+
turnId: run.turnId,
|
|
41
|
+
});
|
|
42
|
+
const meta = extractThreadMeta(folded);
|
|
43
|
+
await updateThreadData(run.threadId, JSON.stringify(folded), thread.title, meta.preview || thread.preview, folded.messages.length);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ArtifactReceipt } from "../artifacts/detect.js";
|
|
2
|
-
import { type
|
|
3
|
-
import type { AgentChatEvent } from "./types.js";
|
|
2
|
+
import { type ContinueRefusalCode, type ContinueTrigger } from "./auto-continue.js";
|
|
3
|
+
import type { AgentChatEvent, RunEvent } from "./types.js";
|
|
4
4
|
export declare const RUN_STALE_MS = 15000;
|
|
5
5
|
export declare const BACKGROUND_RUN_STALE_MS = 90000;
|
|
6
6
|
export declare const BACKGROUND_PROCESSING_RUN_STALE_MS = 45000;
|
|
@@ -164,6 +164,15 @@ export declare function shouldRedispatchUnclaimedBackgroundRun(row: {
|
|
|
164
164
|
startedAt: number;
|
|
165
165
|
}, now?: number): boolean;
|
|
166
166
|
export declare function countRunsForTurn(threadId: string, turnId: string): Promise<number>;
|
|
167
|
+
/**
|
|
168
|
+
* The newest run of the turn before `turnId` in a thread: how the previous
|
|
169
|
+
* request ended. Null when the thread has no earlier turn.
|
|
170
|
+
*/
|
|
171
|
+
export declare function getPreviousTurnNewestRun(threadId: string, turnId: string): Promise<{
|
|
172
|
+
turnId: string;
|
|
173
|
+
status: string;
|
|
174
|
+
terminalReason: string | null;
|
|
175
|
+
} | null>;
|
|
167
176
|
export declare function getTurnInitiatorByRun(runId: string): Promise<(AgentTurnInitiator & {
|
|
168
177
|
firstRunId: string;
|
|
169
178
|
}) | null>;
|
|
@@ -179,14 +188,17 @@ export declare function tryClaimRunSlot(threadId: string, runId: string, maxStal
|
|
|
179
188
|
dispatchPayload?: string;
|
|
180
189
|
continuationOrder?: number;
|
|
181
190
|
turnInitiator?: AgentTurnInitiator;
|
|
182
|
-
/** The
|
|
183
|
-
|
|
191
|
+
/** The stopped run this run continues in the same turn, and who asked. */
|
|
192
|
+
continueOf?: {
|
|
193
|
+
runId: string;
|
|
194
|
+
trigger: ContinueTrigger;
|
|
195
|
+
};
|
|
184
196
|
}): Promise<{
|
|
185
197
|
claimed: boolean;
|
|
186
198
|
activeRunId: string | null;
|
|
187
199
|
completedRunId?: string;
|
|
188
200
|
turnAborted?: boolean;
|
|
189
|
-
|
|
201
|
+
continueRefused?: ContinueRefusalCode;
|
|
190
202
|
}>;
|
|
191
203
|
export declare function setRunError(runId: string, errorCode: string | undefined, errorDetail: string | undefined): Promise<void>;
|
|
192
204
|
export declare function setRunTerminalReason(runId: string, terminalReason: string | undefined): Promise<void>;
|
|
@@ -280,6 +292,18 @@ export declare function getRunById(runId: string): Promise<{
|
|
|
280
292
|
errorDetail: string | null;
|
|
281
293
|
terminalReason: string | null;
|
|
282
294
|
} | null>;
|
|
295
|
+
/**
|
|
296
|
+
* What saving a run the server ended on its behalf needs: the run's ledger,
|
|
297
|
+
* and whether anything ran after it in its turn or in a later turn.
|
|
298
|
+
*/
|
|
299
|
+
export declare function readStoppedRunForThreadFold(runId: string): Promise<{
|
|
300
|
+
threadId: string;
|
|
301
|
+
turnId: string;
|
|
302
|
+
startedAt: number;
|
|
303
|
+
events: RunEvent[];
|
|
304
|
+
continuedInTurn: boolean;
|
|
305
|
+
laterTurnStarted: boolean;
|
|
306
|
+
} | null>;
|
|
283
307
|
export declare function getLastTerminalRunEvent(runId: string): Promise<{
|
|
284
308
|
seq: number;
|
|
285
309
|
event: Record<string, unknown>;
|