@agent-native/core 0.122.1 → 0.122.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -13
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +65 -1
- package/corpus/core/src/agent/run-loop-with-resume.ts +12 -0
- package/corpus/core/src/agent/run-store.ts +61 -1
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +182 -0
- package/corpus/core/src/integrations/a2a-continuations-store.ts +122 -12
- package/corpus/core/src/integrations/integration-campaign-recovery.ts +127 -0
- package/corpus/core/src/integrations/integration-campaigns-store.ts +1039 -0
- package/corpus/core/src/integrations/integration-durable-dispatch.ts +28 -3
- package/corpus/core/src/integrations/pending-tasks-retry-job.ts +8 -0
- package/corpus/core/src/integrations/plugin.ts +453 -35
- package/corpus/core/src/integrations/webhook-handler.ts +469 -11
- package/corpus/core/src/server/builder-design-systems.ts +1 -1
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +15 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-panel-window.ts +3 -3
- package/corpus/templates/analytics/changelog/2026-07-25-analytics-dashboards-and-scheduled-reports-are-faster-and-mo.md +6 -0
- package/corpus/templates/analytics/server/db/schema.ts +12 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +8 -4
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +136 -5
- package/corpus/templates/analytics/server/lib/dashboard-time-scope.ts +250 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-cache.ts +167 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +34 -9
- package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +105 -23
- package/corpus/templates/analytics/server/lib/first-party-unbounded-panel-repair.ts +169 -0
- package/corpus/templates/analytics/server/plugins/db.ts +41 -1
- package/corpus/templates/analytics/shared/dashboard-report-timeouts.ts +6 -3
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +7 -3
- package/corpus/templates/content/app/components/editor/body-hydration.ts +10 -0
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +1 -0
- package/corpus/templates/content/app/root.tsx +12 -1
- package/corpus/templates/content/changelog/2026-07-23-new-pages-open-immediately-while-slow-network-work-continues.md +6 -0
- package/corpus/templates/content/changelog/2026-07-25-database-preview-actions-open-reliably.md +6 -0
- package/corpus/templates/content/e2e/playwright.config.ts +1 -1
- package/corpus/templates/design/actions/edit-design.ts +66 -27
- package/corpus/templates/design/changelog/2026-07-25-design-edits-retry-concurrent-changes.md +6 -0
- package/corpus/templates/design/server/source-workspace.ts +5 -1
- package/corpus/templates/forms/.agents/skills/form-responses/SKILL.md +6 -4
- package/corpus/templates/forms/actions/create-form.ts +5 -1
- package/corpus/templates/forms/actions/export-responses.ts +22 -11
- package/corpus/templates/forms/actions/update-form.ts +5 -1
- package/corpus/templates/forms/changelog/2026-07-25-fields-can-be-created-without-ids.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-25-response-exports-use-file-storage.md +6 -0
- package/corpus/templates/forms/server/lib/validate-fields.ts +43 -0
- package/corpus/templates/slides/actions/extract-pdf.ts +4 -4
- package/corpus/templates/slides/actions/import-file.ts +3 -4
- package/corpus/templates/slides/changelog/2026-07-25-gemini-image-models-updated.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-25-pdf-imports-tolerate-missing-canvas.md +6 -0
- package/corpus/templates/slides/server/handlers/image-providers/gemini.ts +5 -2
- package/corpus/templates/slides/server/lib/pdf-parse-setup.ts +150 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +63 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts +7 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +7 -0
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +49 -0
- package/dist/agent/run-store.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/integrations/a2a-continuation-processor.d.ts +14 -0
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +134 -1
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts +23 -0
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +99 -13
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/integration-campaign-recovery.d.ts +16 -0
- package/dist/integrations/integration-campaign-recovery.d.ts.map +1 -0
- package/dist/integrations/integration-campaign-recovery.js +94 -0
- package/dist/integrations/integration-campaign-recovery.js.map +1 -0
- package/dist/integrations/integration-campaigns-store.d.ts +121 -0
- package/dist/integrations/integration-campaigns-store.d.ts.map +1 -0
- package/dist/integrations/integration-campaigns-store.js +784 -0
- package/dist/integrations/integration-campaigns-store.js.map +1 -0
- package/dist/integrations/integration-durable-dispatch.d.ts +3 -0
- package/dist/integrations/integration-durable-dispatch.d.ts.map +1 -1
- package/dist/integrations/integration-durable-dispatch.js +22 -3
- package/dist/integrations/integration-durable-dispatch.js.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.js +6 -0
- package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +325 -18
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts +16 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +368 -13
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/builder-design-systems.js +1 -1
- package/dist/server/builder-design-systems.js.map +1 -1
- package/package.json +3 -3
- package/src/agent/production-agent.ts +65 -1
- package/src/agent/run-loop-with-resume.ts +12 -0
- package/src/agent/run-store.ts +61 -1
- package/src/integrations/a2a-continuation-processor.ts +182 -0
- package/src/integrations/a2a-continuations-store.ts +122 -12
- package/src/integrations/integration-campaign-recovery.ts +127 -0
- package/src/integrations/integration-campaigns-store.ts +1039 -0
- package/src/integrations/integration-durable-dispatch.ts +28 -3
- package/src/integrations/pending-tasks-retry-job.ts +8 -0
- package/src/integrations/plugin.ts +453 -35
- package/src/integrations/webhook-handler.ts +469 -11
- package/src/server/builder-design-systems.ts +1 -1
|
@@ -20,8 +20,14 @@
|
|
|
20
20
|
* Both paths route through `appendAgentLoopContinuation` so the agent sees a
|
|
21
21
|
* uniform "continue" instruction regardless of which recovery fired.
|
|
22
22
|
*/
|
|
23
|
-
import {
|
|
23
|
+
import type { EngineMessage } from "./engine/types.js";
|
|
24
|
+
import { runAgentLoop, type AgentLoopContinuationReason } from "./production-agent.js";
|
|
24
25
|
import type { ResolveRunSoftTimeoutOptions } from "./run-manager.js";
|
|
26
|
+
/**
|
|
27
|
+
* Rebuild the same safe continuation context for a logical turn that resumes
|
|
28
|
+
* in a fresh hosted invocation.
|
|
29
|
+
*/
|
|
30
|
+
export declare function appendDurableContinuationContext(messages: EngineMessage[], reason: AgentLoopContinuationReason, threadId: string): Promise<void>;
|
|
25
31
|
/**
|
|
26
32
|
* Cap on continuation iterations inside a single
|
|
27
33
|
* `runAgentLoopDirectWithSoftTimeout` invocation. The host's hard function
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-loop-with-resume.d.ts","sourceRoot":"","sources":["../../src/agent/run-loop-with-resume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;
|
|
1
|
+
{"version":3,"file":"run-loop-with-resume.d.ts","sourceRoot":"","sources":["../../src/agent/run-loop-with-resume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EACL,YAAY,EAMZ,KAAK,2BAA2B,EACjC,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AA4FrE;;;GAGG;AACH,wBAAsB,gCAAgC,CACpD,QAAQ,EAAE,aAAa,EAAE,EACzB,MAAM,EAAE,2BAA2B,EACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAEf;AAsCD;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;wDAIwD;AACxD,eAAO,MAAM,+BAA+B,yBAAyB,CAAC;AAEtE;;;;;iCAKiC;AACjC,eAAO,MAAM,4BAA4B,QAGkD,CAAC;AAE5F;;;;;;;;GAQG;AACH,wBAAsB,iCAAiC,CACrD,IAAI,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,EACxC,aAAa,CAAC,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,4BAA4B,GAC5C,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CA4LnD"}
|
|
@@ -91,6 +91,13 @@ async function appendContinuationAndJournal(messages, reason, threadId, localEve
|
|
|
91
91
|
appendAgentLoopContinuation(messages, reason, actionPreparationContinuationOptions(events));
|
|
92
92
|
appendToolCallJournalNote(messages, events);
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Rebuild the same safe continuation context for a logical turn that resumes
|
|
96
|
+
* in a fresh hosted invocation.
|
|
97
|
+
*/
|
|
98
|
+
export async function appendDurableContinuationContext(messages, reason, threadId) {
|
|
99
|
+
await appendContinuationAndJournal(messages, reason, threadId);
|
|
100
|
+
}
|
|
94
101
|
async function hasCompletedSideEffectToolCallInCurrentTurn(threadId, localEvents = []) {
|
|
95
102
|
try {
|
|
96
103
|
const events = await readCurrentTurnEventsForResume(threadId, localEvents);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-loop-with-resume.js","sourceRoot":"","sources":["../../src/agent/run-loop-with-resume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EACL,YAAY,EACZ,2BAA2B,EAC3B,sBAAsB,EACtB,mCAAmC,EACnC,2CAA2C,EAC3C,oCAAoC,GAErC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EACL,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAGhC,KAAK,UAAU,8BAA8B,CAC3C,QAA4B,EAC5B,WAAW,GAA8B,EAAE;IAE3C,IAAI,eAAe,GAAqB,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,eAAe,GAAG,QAAQ;YACxB,CAAC,CAAC,MAAM,6BAA6B,CAAC,QAAQ,CAAC;YAC/C,CAAC,CAAC,EAAE,CAAC;IACT,CAAC;IAAC,MAAM,CAAC;QACP,eAAe,GAAG,EAAE,CAAC;IACvB,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,eAAe,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAO;QACL,GAAG,eAAe;QAClB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;KACnE,CAAC;AACJ,CAAC;AAED,SAAS,oCAAoC,CAC3C,MAAiC;IAEjC,MAAM,qBAAqB,GACzB,2CAA2C,CAAC,MAAM,CAAC,CAAC;IACtD,OAAO,qBAAqB,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAChE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAS,yBAAyB,CAChC,QAAyB,EACzB,MAAiC;IAEjC,IAAI,CAAC;QACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAChC,MAAM,OAAO,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;SACxC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,0EAA0E;QAC1E,uEAAuE;IACzE,CAAC;AACH,CAAC;AAED,KAAK,UAAU,4BAA4B,CACzC,QAAyB,EACzB,MAAmC,EACnC,QAA4B,EAC5B,WAAW,GAA8B,EAAE;IAE3C,MAAM,MAAM,GAAG,MAAM,8BAA8B,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC3E,2BAA2B,CACzB,QAAQ,EACR,MAAM,EACN,oCAAoC,CAAC,MAAM,CAAC,CAC7C,CAAC;IACF,yBAAyB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC9C,CAAC;AAED,KAAK,UAAU,2CAA2C,CACxD,QAA4B,EAC5B,WAAW,GAA8B,EAAE;IAE3C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,8BAA8B,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC3E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACtC,OAAO,MAAM,CAAC,IAAI,CAChB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,IAAI,KAAK,WAAW;YAC1B,KAAK,CAAC,mBAAmB,KAAK,IAAI;YAClC,KAAK,CAAC,OAAO,KAAK,IAAI,CACzB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,oCAAoC,CAC3C,MAAiC;IAEjC,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,IAAI,EAAE,IAAI,KAAK,eAAe;QAAE,OAAO,SAAS,CAAC;IACrD,IACE,IAAI,CAAC,MAAM,KAAK,aAAa;QAC7B,IAAI,CAAC,MAAM,KAAK,YAAY;QAC5B,IAAI,CAAC,MAAM,KAAK,aAAa;QAC7B,IAAI,CAAC,MAAM,KAAK,cAAc;QAC9B,IAAI,CAAC,MAAM,KAAK,iBAAiB;QACjC,IAAI,CAAC,MAAM,KAAK,qBAAqB,EACrC,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAE5C;;;;wDAIwD;AACxD,MAAM,CAAC,MAAM,+BAA+B,GAAG,sBAAsB,CAAC;AAEtE;;;;;iCAKiC;AACjC,MAAM,CAAC,MAAM,4BAA4B,GACvC,gDAAgD;IAChD,gDAAgD;IAChD,yFAAyF,CAAC;AAE5F;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,IAAwC,EACxC,aAAsB,EACtB,cAA6C;IAE7C,MAAM,6BAA6B,GACjC,IAAI,CAAC,6BAA6B;QAClC,oCAAoC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,EAAE,6BAA6B,EAAE,CAAC;IAC9D,MAAM,SAAS,GAAG,uBAAuB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IACzE,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,YAAY,CAAC,UAAU,CAAC,CAAC;IAEpD,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;IACnC,MAAM,KAAK,GAA6C;QACtD,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,CAAC;QACf,eAAe,EAAE,CAAC;QAClB,gBAAgB,EAAE,CAAC;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,IAA8C,EAAE,EAAE;QAClE,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC;QACtC,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC;QACxC,KAAK,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe,CAAC;QAC9C,KAAK,CAAC,gBAAgB,IAAI,IAAI,CAAC,gBAAgB,CAAC;QAChD,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAC3B,CAAC,CAAC;IAEF,MAAM,eAAe,GAAqB,EAAE,CAAC;IAC7C,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,qEAAqE;IACrE,0EAA0E;IAC1E,4EAA4E;IAC5E,8EAA8E;IAC9E,4EAA4E;IAC5E,qEAAqE;IACrE,IAAI,oCAAoC,GAAG,KAAK,CAAC;IACjD,OAAO,CAAC,cAAc,CAAC,OAAO,IAAI,QAAQ,GAAG,0BAA0B,EAAE,CAAC;QACxE,QAAQ,EAAE,CAAC;QACX,oCAAoC,GAAG,KAAK,CAAC;QAC7C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACnD,IAAI,cAAc,CAAC,OAAO,EAAE,CAAC;YAC3B,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,EAAE;gBAC1D,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;QACL,CAAC;QAED,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO;YACtC,YAAY,GAAG,IAAI,CAAC;YACpB,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC,EAAE,SAAS,CAAC,CAAC;QAEd,MAAM,iBAAiB,GAAG,eAAe,CAAC,MAAM,CAAC;QACjD,MAAM,IAAI,GAAG,CAAC,KAAqB,EAAE,EAAE;YACrC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC;gBACnC,GAAG,UAAU;gBACb,IAAI;gBACJ,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YACH,QAAQ,CAAC,SAAS,CAAC,CAAC;YACpB,MAAM,aAAa,GAAG,eAAe,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAC/D,MAAM,0BAA0B,GAC9B,oCAAoC,CAAC,aAAa,CAAC,CAAC;YACtD,IAAI,0BAA0B,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;gBAC1D,oCAAoC,GAAG,IAAI,CAAC;gBAC5C,MAAM,kBAAkB,GAAG,CAAC,GAAG,eAAe,CAAC,CAAC;gBAChD,IACE,CAAC,CAAC,MAAM,2CAA2C,CACjD,IAAI,CAAC,QAAQ,EACb,kBAAkB,CACnB,CAAC,EACF,CAAC;oBACD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC/B,CAAC;gBACD,MAAM,4BAA4B,CAChC,IAAI,CAAC,QAAQ,EACb,0BAA0B,EAC1B,IAAI,CAAC,QAAQ,EACb,kBAAkB,CACnB,CAAC;gBACF,SAAS;YACX,CAAC;YACD,IAAI,YAAY,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;gBAC5C,oCAAoC,GAAG,IAAI,CAAC;gBAC5C,MAAM,4BAA4B,CAChC,IAAI,CAAC,QAAQ,EACb,aAAa,EACb,IAAI,CAAC,QAAQ,EACb,eAAe,CAChB,CAAC;gBACF,SAAS;YACX,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,YAAY,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;gBAC5C,iEAAiE;gBACjE,kEAAkE;gBAClE,oCAAoC,GAAG,IAAI,CAAC;gBAC5C,IACE,CAAC,CAAC,MAAM,2CAA2C,CACjD,IAAI,CAAC,QAAQ,EACb,eAAe,CAChB,CAAC,EACF,CAAC;oBACD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC/B,CAAC;gBACD,MAAM,4BAA4B,CAChC,IAAI,CAAC,QAAQ,EACb,aAAa,EACb,IAAI,CAAC,QAAQ,EACb,eAAe,CAChB,CAAC;gBACF,SAAS;YACX,CAAC;YACD,wEAAwE;YACxE,kEAAkE;YAClE,wEAAwE;YACxE,wEAAwE;YACxE,uEAAuE;YACvE,oEAAoE;YACpE,2CAA2C;YAC3C,EAAE;YACF,uEAAuE;YACvE,yEAAyE;YACzE,oEAAoE;YACpE,qEAAqE;YACrE,kEAAkE;YAClE,IAAI,CAAC,cAAc,CAAC,OAAO,IAAI,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3D,oCAAoC,GAAG,IAAI,CAAC;gBAC5C,IACE,CAAC,CAAC,MAAM,2CAA2C,CACjD,IAAI,CAAC,QAAQ,EACb,eAAe,CAChB,CAAC,EACF,CAAC;oBACD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC/B,CAAC;gBACD,MAAM,4BAA4B,CAChC,IAAI,CAAC,QAAQ,EACb,mCAAmC,CAAC,GAAG,CAAC,EACxC,IAAI,CAAC,QAAQ,EACb,eAAe,CAChB,CAAC;gBACF,SAAS;YACX,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,cAAc,CAAC,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,+EAA+E;IAC/E,wDAAwD;IACxD,wEAAwE;IACxE,0EAA0E;IAC1E,2EAA2E;IAC3E,wEAAwE;IACxE,sEAAsE;IACtE,IAAI,CAAC,cAAc,CAAC,OAAO,IAAI,oCAAoC,EAAE,CAAC;QACpE,0EAA0E;QAC1E,yEAAyE;QACzE,wEAAwE;QACxE,uEAAuE;QACvE,IACE,CAAC,CAAC,MAAM,2CAA2C,CACjD,IAAI,CAAC,QAAQ,EACb,eAAe,CAChB,CAAC,EACF,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC;YACR,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,4BAA4B;YACnC,SAAS,EAAE,+BAA+B;YAC1C,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/**\n * Wraps `runAgentLoop` with two layered recovery mechanisms so a single hosted\n * invocation can survive interruptions without showing the user a dead chat:\n *\n * 1. **Soft timeout** — an inner timer that aborts the LLM call before the\n * hosting function's hard limit (Lambda 75s, Vercel 60s, etc.) so we have a\n * chance to gracefully wind down and append a continuation nudge. Without\n * this the function gets killed mid-stream and the user sees a frozen\n * spinner.\n *\n * 2. **Resumable-error continuation** — when the LLM call errors with a\n * transport- or gateway-level interruption (Builder gateway 45s timeout,\n * socket hang up, ECONNRESET, upstream 5xx that survived engine retries),\n * we save the conversation prefix, append a \"continue from where you left\n * off\" message, and run another LLM call. Anthropic's prompt cache makes\n * the resume call dramatically faster than the cold first attempt, and the\n * agent gets explicit context that it was cut off so it doesn't re-do\n * completed work.\n *\n * Both paths route through `appendAgentLoopContinuation` so the agent sees a\n * uniform \"continue\" instruction regardless of which recovery fired.\n */\n\nimport type { EngineMessage } from \"./engine/types.js\";\nimport {\n runAgentLoop,\n appendAgentLoopContinuation,\n isResumableEngineError,\n continuationReasonForResumableError,\n lastUnfinishedPreparingActionToolFromEvents,\n resolveFinalResponseGuardRequestText,\n type AgentLoopContinuationReason,\n} from \"./production-agent.js\";\nimport { resolveRunSoftTimeoutMs } from \"./run-manager.js\";\nimport type { ResolveRunSoftTimeoutOptions } from \"./run-manager.js\";\nimport { getCurrentTurnEventsForThread } from \"./run-store.js\";\nimport {\n classifyToolCallJournal,\n buildResumeJournalNote,\n} from \"./tool-call-journal.js\";\nimport type { AgentChatEvent } from \"./types.js\";\n\nasync function readCurrentTurnEventsForResume(\n threadId: string | undefined,\n localEvents: readonly AgentChatEvent[] = [],\n): Promise<AgentChatEvent[]> {\n let persistedEvents: AgentChatEvent[] = [];\n try {\n persistedEvents = threadId\n ? await getCurrentTurnEventsForThread(threadId)\n : [];\n } catch {\n persistedEvents = [];\n }\n if (localEvents.length === 0) return persistedEvents;\n const seen = new Set(persistedEvents.map((event) => JSON.stringify(event)));\n return [\n ...persistedEvents,\n ...localEvents.filter((event) => !seen.has(JSON.stringify(event))),\n ];\n}\n\nfunction actionPreparationContinuationOptions(\n events: readonly AgentChatEvent[],\n): { actionPreparationTool?: string } {\n const actionPreparationTool =\n lastUnfinishedPreparingActionToolFromEvents(events);\n return actionPreparationTool ? { actionPreparationTool } : {};\n}\n\n/**\n * Derive the per-turn tool-call journal from the durable run-event ledger and,\n * when there is anything to report, append a STRUCTURED note to the message\n * prefix so the resumed model:\n * - does NOT re-execute tool calls that already completed (avoiding duplicate\n * side effects like re-sending an email or re-creating a ticket), and\n * - is explicitly told about any tool call that started but whose outcome was\n * never recorded (\"interrupted, unknown outcome\") so it can decide.\n *\n * This is additive to the existing \"continue from where you left off\" nudge —\n * it is appended right after it. When the journal is empty (no completed or\n * interrupted tool calls — e.g. a turn with no tool activity, or a clean\n * continuation), nothing extra is appended and resume behavior is byte-for-byte\n * what it was before. Best-effort: any ledger read/parse failure is swallowed so\n * a journal hiccup can never block a recovery that would otherwise succeed.\n *\n * This prompt-level journal is paired with tool-layer enforcement in\n * production-agent.ts/runToolCall, which refuses to re-execute a journaled-\n * complete write tool (returning the journaled result instead). See\n * `tool-call-journal.ts` (`findCompletedJournalEntry`) for the keying used.\n */\nfunction appendToolCallJournalNote(\n messages: EngineMessage[],\n events: readonly AgentChatEvent[],\n): void {\n try {\n if (events.length === 0) return;\n const journal = classifyToolCallJournal(events);\n const note = buildResumeJournalNote(journal);\n if (!note) return;\n messages.push({\n role: \"user\",\n content: [{ type: \"text\", text: note }],\n });\n } catch {\n // The journal is a hardening layer, never a gate. A failed ledger read or\n // parse must not break the resume that the continuation nudge already set\n // up — the model still continues, just without the structured journal.\n }\n}\n\nasync function appendContinuationAndJournal(\n messages: EngineMessage[],\n reason: AgentLoopContinuationReason,\n threadId: string | undefined,\n localEvents: readonly AgentChatEvent[] = [],\n): Promise<void> {\n const events = await readCurrentTurnEventsForResume(threadId, localEvents);\n appendAgentLoopContinuation(\n messages,\n reason,\n actionPreparationContinuationOptions(events),\n );\n appendToolCallJournalNote(messages, events);\n}\n\nasync function hasCompletedSideEffectToolCallInCurrentTurn(\n threadId: string | undefined,\n localEvents: readonly AgentChatEvent[] = [],\n): Promise<boolean> {\n try {\n const events = await readCurrentTurnEventsForResume(threadId, localEvents);\n if (events.length === 0) return false;\n return events.some(\n (event) =>\n event.type === \"tool_done\" &&\n event.completedSideEffect === true &&\n event.isError !== true,\n );\n } catch {\n return false;\n }\n}\n\nfunction internalContinuationReasonForAttempt(\n events: readonly AgentChatEvent[],\n): AgentLoopContinuationReason | undefined {\n const last = events.at(-1);\n if (last?.type !== \"auto_continue\") return undefined;\n if (\n last.reason === \"run_timeout\" ||\n last.reason === \"loop_limit\" ||\n last.reason === \"no_progress\" ||\n last.reason === \"stream_ended\" ||\n last.reason === \"gateway_timeout\" ||\n last.reason === \"network_interrupted\"\n ) {\n return last.reason;\n }\n return undefined;\n}\n\n/**\n * Cap on continuation iterations inside a single\n * `runAgentLoopDirectWithSoftTimeout` invocation. The host's hard function\n * timeout usually bounds this naturally — but a defensive cap prevents an\n * instant-error spiral from looping forever inside hosting environments with a\n * generous budget.\n *\n * 6 leaves room for: 1 normal completion + a few resume rounds for design\n * generation (prompt + 3 variants ≈ 4 LLM calls), with a small safety margin.\n */\nexport const MAX_RUN_LOOP_CONTINUATIONS = 6;\n\n/** Machine-readable code carried on the give-up terminal `error` event so the\n * client renders a loud \"stopped before finishing\" terminal instead of an\n * ambiguous silent stall. Deliberately NOT in the client's auto-recoverable\n * allow-list (`isAutoRecoverableError`) so it terminates the chain rather than\n * looping another POST that would hit the same wall. */\nexport const RUN_BUDGET_EXHAUSTED_ERROR_CODE = \"run_budget_exhausted\";\n\n/** User-facing terminal message when a hosted run is cut off mid-step and\n * exhausts its in-invocation continuation budget without finishing. Generic and\n * framework-level (not app-specific). Mirrors the `reliable-mutations` skill's\n * \"fail loud, retry as a single bulk action\" guidance so the user understands\n * the turn stopped before finishing without implying that earlier completed\n * tool calls did not persist. */\nexport const RUN_BUDGET_EXHAUSTED_MESSAGE =\n \"I ran out of time before finishing this step. \" +\n \"I stopped rather than keep retrying silently. \" +\n \"Check any completed tool cards above before retrying, ideally as one smaller follow-up.\";\n\n/**\n * Internal entry point used by the agent-chat plugin's run handler. Wraps\n * `runAgentLoop` with soft-timeout + resumable-error continuation recovery.\n *\n * The `softTimeoutMs` argument falls back to `resolveRunSoftTimeoutMs(...)` so\n * different hosting environments (Lambda, Vercel, Cloudflare, local dev) get\n * an appropriate inner budget. Setting it to <= 0 disables both layers — the\n * call goes straight to `runAgentLoop` with no wrapping.\n */\nexport async function runAgentLoopDirectWithSoftTimeout(\n opts: Parameters<typeof runAgentLoop>[0],\n softTimeoutMs?: number,\n timeoutOptions?: ResolveRunSoftTimeoutOptions,\n): Promise<Awaited<ReturnType<typeof runAgentLoop>>> {\n const finalResponseGuardRequestText =\n opts.finalResponseGuardRequestText ??\n resolveFinalResponseGuardRequestText(opts.messages);\n const stableOpts = { ...opts, finalResponseGuardRequestText };\n const timeoutMs = resolveRunSoftTimeoutMs(softTimeoutMs, timeoutOptions);\n if (timeoutMs <= 0) return runAgentLoop(stableOpts);\n\n const upstreamSignal = opts.signal;\n const usage: Awaited<ReturnType<typeof runAgentLoop>> = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n model: opts.model,\n };\n\n const addUsage = (next: Awaited<ReturnType<typeof runAgentLoop>>) => {\n usage.inputTokens += next.inputTokens;\n usage.outputTokens += next.outputTokens;\n usage.cacheReadTokens += next.cacheReadTokens;\n usage.cacheWriteTokens += next.cacheWriteTokens;\n usage.model = next.model;\n };\n\n const localTurnEvents: AgentChatEvent[] = [];\n let attempts = 0;\n // Tracks whether the most recent attempt ended by scheduling another\n // continuation (soft-timeout or resumable error → `continue`) rather than\n // returning a finished turn. When the loop then exits because the budget is\n // exhausted (NOT because the user aborted and NOT because the turn finished),\n // this is the silent give-up case: emit a loud terminal so the user sees an\n // unambiguous \"stopped before finishing\" instead of a bare done/\"…\".\n let lastAttemptWasUnfinishedContinuation = false;\n while (!upstreamSignal.aborted && attempts < MAX_RUN_LOOP_CONTINUATIONS) {\n attempts++;\n lastAttemptWasUnfinishedContinuation = false;\n const controller = new AbortController();\n const abortFromUpstream = () => controller.abort();\n if (upstreamSignal.aborted) {\n controller.abort();\n } else {\n upstreamSignal.addEventListener(\"abort\", abortFromUpstream, {\n once: true,\n });\n }\n\n let softTimedOut = false;\n const timer = setTimeout(() => {\n if (controller.signal.aborted) return;\n softTimedOut = true;\n controller.abort();\n }, timeoutMs);\n\n const attemptStartIndex = localTurnEvents.length;\n const send = (event: AgentChatEvent) => {\n localTurnEvents.push(event);\n opts.send(event);\n };\n\n try {\n const nextUsage = await runAgentLoop({\n ...stableOpts,\n send,\n signal: controller.signal,\n });\n addUsage(nextUsage);\n const attemptEvents = localTurnEvents.slice(attemptStartIndex);\n const internalContinuationReason =\n internalContinuationReasonForAttempt(attemptEvents);\n if (internalContinuationReason && !upstreamSignal.aborted) {\n lastAttemptWasUnfinishedContinuation = true;\n const continuationEvents = [...localTurnEvents];\n if (\n !(await hasCompletedSideEffectToolCallInCurrentTurn(\n opts.threadId,\n continuationEvents,\n ))\n ) {\n opts.send({ type: \"clear\" });\n }\n await appendContinuationAndJournal(\n opts.messages,\n internalContinuationReason,\n opts.threadId,\n continuationEvents,\n );\n continue;\n }\n if (softTimedOut && !upstreamSignal.aborted) {\n lastAttemptWasUnfinishedContinuation = true;\n await appendContinuationAndJournal(\n opts.messages,\n \"run_timeout\",\n opts.threadId,\n localTurnEvents,\n );\n continue;\n }\n return usage;\n } catch (err) {\n if (softTimedOut && !upstreamSignal.aborted) {\n // Clear partial text the client received before the abort so the\n // resumed model doesn't re-emit it and produce duplicated output.\n lastAttemptWasUnfinishedContinuation = true;\n if (\n !(await hasCompletedSideEffectToolCallInCurrentTurn(\n opts.threadId,\n localTurnEvents,\n ))\n ) {\n opts.send({ type: \"clear\" });\n }\n await appendContinuationAndJournal(\n opts.messages,\n \"run_timeout\",\n opts.threadId,\n localTurnEvents,\n );\n continue;\n }\n // Resumable transport / gateway interruptions: the LLM call was cut off\n // mid-stream (gateway 45s timeout, socket hang up, function-level\n // timeout that didn't trip our soft timer first). Treat it the same way\n // as a soft timeout — append a \"continue from where you left off\" nudge\n // and let the loop run another LLM call. The conversation prefix up to\n // the cut-off is preserved in opts.messages, and Anthropic's prompt\n // cache makes the resume call much faster.\n //\n // Emit 'clear' so any partial streamed text is discarded on the client\n // before the model resumes. Without this the model restarts its sentence\n // from scratch and the fold produces duplicated text in one message\n // (the partial text was already sent to the client but never entered\n // the in-memory messages array, so the next attempt re-emits it).\n if (!upstreamSignal.aborted && isResumableEngineError(err)) {\n lastAttemptWasUnfinishedContinuation = true;\n if (\n !(await hasCompletedSideEffectToolCallInCurrentTurn(\n opts.threadId,\n localTurnEvents,\n ))\n ) {\n opts.send({ type: \"clear\" });\n }\n await appendContinuationAndJournal(\n opts.messages,\n continuationReasonForResumableError(err),\n opts.threadId,\n localTurnEvents,\n );\n continue;\n }\n throw err;\n } finally {\n clearTimeout(timer);\n upstreamSignal.removeEventListener(\"abort\", abortFromUpstream);\n }\n }\n\n // The loop exited without a clean return. If the user aborted, that's a Stop —\n // stay silent. Otherwise we only get here by exhausting\n // MAX_RUN_LOOP_CONTINUATIONS while the last attempt was still trying to\n // continue (soft-timeout / resumable error). That is the genuinely-silent\n // give-up the run-manager would otherwise report as a clean `done`: emit a\n // loud, non-auto-continuing terminal so the user knows the turn stopped\n // before finishing and nothing was partially saved by the run itself.\n if (!upstreamSignal.aborted && lastAttemptWasUnfinishedContinuation) {\n // Discard any partial text already streamed for the unfinished attempt so\n // the terminal message stands alone instead of trailing a half sentence.\n // Preserve completed tool cards: they are the user's only durable proof\n // that a side effect landed before the final assistant note timed out.\n if (\n !(await hasCompletedSideEffectToolCallInCurrentTurn(\n opts.threadId,\n localTurnEvents,\n ))\n ) {\n opts.send({ type: \"clear\" });\n }\n opts.send({\n type: \"error\",\n error: RUN_BUDGET_EXHAUSTED_MESSAGE,\n errorCode: RUN_BUDGET_EXHAUSTED_ERROR_CODE,\n recoverable: true,\n });\n }\n\n return usage;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"run-loop-with-resume.js","sourceRoot":"","sources":["../../src/agent/run-loop-with-resume.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Wraps `runAgentLoop` with two layered recovery mechanisms so a single hosted\n * invocation can survive interruptions without showing the user a dead chat:\n *\n * 1. **Soft timeout** — an inner timer that aborts the LLM call before the\n * hosting function's hard limit (Lambda 75s, Vercel 60s, etc.) so we have a\n * chance to gracefully wind down and append a continuation nudge. Without\n * this the function gets killed mid-stream and the user sees a frozen\n * spinner.\n *\n * 2. **Resumable-error continuation** — when the LLM call errors with a\n * transport- or gateway-level interruption (Builder gateway 45s timeout,\n * socket hang up, ECONNRESET, upstream 5xx that survived engine retries),\n * we save the conversation prefix, append a \"continue from where you left\n * off\" message, and run another LLM call. Anthropic's prompt cache makes\n * the resume call dramatically faster than the cold first attempt, and the\n * agent gets explicit context that it was cut off so it doesn't re-do\n * completed work.\n *\n * Both paths route through `appendAgentLoopContinuation` so the agent sees a\n * uniform \"continue\" instruction regardless of which recovery fired.\n */\n\nimport type { EngineMessage } from \"./engine/types.js\";\nimport {\n runAgentLoop,\n appendAgentLoopContinuation,\n isResumableEngineError,\n continuationReasonForResumableError,\n lastUnfinishedPreparingActionToolFromEvents,\n resolveFinalResponseGuardRequestText,\n type AgentLoopContinuationReason,\n} from \"./production-agent.js\";\nimport { resolveRunSoftTimeoutMs } from \"./run-manager.js\";\nimport type { ResolveRunSoftTimeoutOptions } from \"./run-manager.js\";\nimport { getCurrentTurnEventsForThread } from \"./run-store.js\";\nimport {\n classifyToolCallJournal,\n buildResumeJournalNote,\n} from \"./tool-call-journal.js\";\nimport type { AgentChatEvent } from \"./types.js\";\n\nasync function readCurrentTurnEventsForResume(\n threadId: string | undefined,\n localEvents: readonly AgentChatEvent[] = [],\n): Promise<AgentChatEvent[]> {\n let persistedEvents: AgentChatEvent[] = [];\n try {\n persistedEvents = threadId\n ? await getCurrentTurnEventsForThread(threadId)\n : [];\n } catch {\n persistedEvents = [];\n }\n if (localEvents.length === 0) return persistedEvents;\n const seen = new Set(persistedEvents.map((event) => JSON.stringify(event)));\n return [\n ...persistedEvents,\n ...localEvents.filter((event) => !seen.has(JSON.stringify(event))),\n ];\n}\n\nfunction actionPreparationContinuationOptions(\n events: readonly AgentChatEvent[],\n): { actionPreparationTool?: string } {\n const actionPreparationTool =\n lastUnfinishedPreparingActionToolFromEvents(events);\n return actionPreparationTool ? { actionPreparationTool } : {};\n}\n\n/**\n * Derive the per-turn tool-call journal from the durable run-event ledger and,\n * when there is anything to report, append a STRUCTURED note to the message\n * prefix so the resumed model:\n * - does NOT re-execute tool calls that already completed (avoiding duplicate\n * side effects like re-sending an email or re-creating a ticket), and\n * - is explicitly told about any tool call that started but whose outcome was\n * never recorded (\"interrupted, unknown outcome\") so it can decide.\n *\n * This is additive to the existing \"continue from where you left off\" nudge —\n * it is appended right after it. When the journal is empty (no completed or\n * interrupted tool calls — e.g. a turn with no tool activity, or a clean\n * continuation), nothing extra is appended and resume behavior is byte-for-byte\n * what it was before. Best-effort: any ledger read/parse failure is swallowed so\n * a journal hiccup can never block a recovery that would otherwise succeed.\n *\n * This prompt-level journal is paired with tool-layer enforcement in\n * production-agent.ts/runToolCall, which refuses to re-execute a journaled-\n * complete write tool (returning the journaled result instead). See\n * `tool-call-journal.ts` (`findCompletedJournalEntry`) for the keying used.\n */\nfunction appendToolCallJournalNote(\n messages: EngineMessage[],\n events: readonly AgentChatEvent[],\n): void {\n try {\n if (events.length === 0) return;\n const journal = classifyToolCallJournal(events);\n const note = buildResumeJournalNote(journal);\n if (!note) return;\n messages.push({\n role: \"user\",\n content: [{ type: \"text\", text: note }],\n });\n } catch {\n // The journal is a hardening layer, never a gate. A failed ledger read or\n // parse must not break the resume that the continuation nudge already set\n // up — the model still continues, just without the structured journal.\n }\n}\n\nasync function appendContinuationAndJournal(\n messages: EngineMessage[],\n reason: AgentLoopContinuationReason,\n threadId: string | undefined,\n localEvents: readonly AgentChatEvent[] = [],\n): Promise<void> {\n const events = await readCurrentTurnEventsForResume(threadId, localEvents);\n appendAgentLoopContinuation(\n messages,\n reason,\n actionPreparationContinuationOptions(events),\n );\n appendToolCallJournalNote(messages, events);\n}\n\n/**\n * Rebuild the same safe continuation context for a logical turn that resumes\n * in a fresh hosted invocation.\n */\nexport async function appendDurableContinuationContext(\n messages: EngineMessage[],\n reason: AgentLoopContinuationReason,\n threadId: string,\n): Promise<void> {\n await appendContinuationAndJournal(messages, reason, threadId);\n}\n\nasync function hasCompletedSideEffectToolCallInCurrentTurn(\n threadId: string | undefined,\n localEvents: readonly AgentChatEvent[] = [],\n): Promise<boolean> {\n try {\n const events = await readCurrentTurnEventsForResume(threadId, localEvents);\n if (events.length === 0) return false;\n return events.some(\n (event) =>\n event.type === \"tool_done\" &&\n event.completedSideEffect === true &&\n event.isError !== true,\n );\n } catch {\n return false;\n }\n}\n\nfunction internalContinuationReasonForAttempt(\n events: readonly AgentChatEvent[],\n): AgentLoopContinuationReason | undefined {\n const last = events.at(-1);\n if (last?.type !== \"auto_continue\") return undefined;\n if (\n last.reason === \"run_timeout\" ||\n last.reason === \"loop_limit\" ||\n last.reason === \"no_progress\" ||\n last.reason === \"stream_ended\" ||\n last.reason === \"gateway_timeout\" ||\n last.reason === \"network_interrupted\"\n ) {\n return last.reason;\n }\n return undefined;\n}\n\n/**\n * Cap on continuation iterations inside a single\n * `runAgentLoopDirectWithSoftTimeout` invocation. The host's hard function\n * timeout usually bounds this naturally — but a defensive cap prevents an\n * instant-error spiral from looping forever inside hosting environments with a\n * generous budget.\n *\n * 6 leaves room for: 1 normal completion + a few resume rounds for design\n * generation (prompt + 3 variants ≈ 4 LLM calls), with a small safety margin.\n */\nexport const MAX_RUN_LOOP_CONTINUATIONS = 6;\n\n/** Machine-readable code carried on the give-up terminal `error` event so the\n * client renders a loud \"stopped before finishing\" terminal instead of an\n * ambiguous silent stall. Deliberately NOT in the client's auto-recoverable\n * allow-list (`isAutoRecoverableError`) so it terminates the chain rather than\n * looping another POST that would hit the same wall. */\nexport const RUN_BUDGET_EXHAUSTED_ERROR_CODE = \"run_budget_exhausted\";\n\n/** User-facing terminal message when a hosted run is cut off mid-step and\n * exhausts its in-invocation continuation budget without finishing. Generic and\n * framework-level (not app-specific). Mirrors the `reliable-mutations` skill's\n * \"fail loud, retry as a single bulk action\" guidance so the user understands\n * the turn stopped before finishing without implying that earlier completed\n * tool calls did not persist. */\nexport const RUN_BUDGET_EXHAUSTED_MESSAGE =\n \"I ran out of time before finishing this step. \" +\n \"I stopped rather than keep retrying silently. \" +\n \"Check any completed tool cards above before retrying, ideally as one smaller follow-up.\";\n\n/**\n * Internal entry point used by the agent-chat plugin's run handler. Wraps\n * `runAgentLoop` with soft-timeout + resumable-error continuation recovery.\n *\n * The `softTimeoutMs` argument falls back to `resolveRunSoftTimeoutMs(...)` so\n * different hosting environments (Lambda, Vercel, Cloudflare, local dev) get\n * an appropriate inner budget. Setting it to <= 0 disables both layers — the\n * call goes straight to `runAgentLoop` with no wrapping.\n */\nexport async function runAgentLoopDirectWithSoftTimeout(\n opts: Parameters<typeof runAgentLoop>[0],\n softTimeoutMs?: number,\n timeoutOptions?: ResolveRunSoftTimeoutOptions,\n): Promise<Awaited<ReturnType<typeof runAgentLoop>>> {\n const finalResponseGuardRequestText =\n opts.finalResponseGuardRequestText ??\n resolveFinalResponseGuardRequestText(opts.messages);\n const stableOpts = { ...opts, finalResponseGuardRequestText };\n const timeoutMs = resolveRunSoftTimeoutMs(softTimeoutMs, timeoutOptions);\n if (timeoutMs <= 0) return runAgentLoop(stableOpts);\n\n const upstreamSignal = opts.signal;\n const usage: Awaited<ReturnType<typeof runAgentLoop>> = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n model: opts.model,\n };\n\n const addUsage = (next: Awaited<ReturnType<typeof runAgentLoop>>) => {\n usage.inputTokens += next.inputTokens;\n usage.outputTokens += next.outputTokens;\n usage.cacheReadTokens += next.cacheReadTokens;\n usage.cacheWriteTokens += next.cacheWriteTokens;\n usage.model = next.model;\n };\n\n const localTurnEvents: AgentChatEvent[] = [];\n let attempts = 0;\n // Tracks whether the most recent attempt ended by scheduling another\n // continuation (soft-timeout or resumable error → `continue`) rather than\n // returning a finished turn. When the loop then exits because the budget is\n // exhausted (NOT because the user aborted and NOT because the turn finished),\n // this is the silent give-up case: emit a loud terminal so the user sees an\n // unambiguous \"stopped before finishing\" instead of a bare done/\"…\".\n let lastAttemptWasUnfinishedContinuation = false;\n while (!upstreamSignal.aborted && attempts < MAX_RUN_LOOP_CONTINUATIONS) {\n attempts++;\n lastAttemptWasUnfinishedContinuation = false;\n const controller = new AbortController();\n const abortFromUpstream = () => controller.abort();\n if (upstreamSignal.aborted) {\n controller.abort();\n } else {\n upstreamSignal.addEventListener(\"abort\", abortFromUpstream, {\n once: true,\n });\n }\n\n let softTimedOut = false;\n const timer = setTimeout(() => {\n if (controller.signal.aborted) return;\n softTimedOut = true;\n controller.abort();\n }, timeoutMs);\n\n const attemptStartIndex = localTurnEvents.length;\n const send = (event: AgentChatEvent) => {\n localTurnEvents.push(event);\n opts.send(event);\n };\n\n try {\n const nextUsage = await runAgentLoop({\n ...stableOpts,\n send,\n signal: controller.signal,\n });\n addUsage(nextUsage);\n const attemptEvents = localTurnEvents.slice(attemptStartIndex);\n const internalContinuationReason =\n internalContinuationReasonForAttempt(attemptEvents);\n if (internalContinuationReason && !upstreamSignal.aborted) {\n lastAttemptWasUnfinishedContinuation = true;\n const continuationEvents = [...localTurnEvents];\n if (\n !(await hasCompletedSideEffectToolCallInCurrentTurn(\n opts.threadId,\n continuationEvents,\n ))\n ) {\n opts.send({ type: \"clear\" });\n }\n await appendContinuationAndJournal(\n opts.messages,\n internalContinuationReason,\n opts.threadId,\n continuationEvents,\n );\n continue;\n }\n if (softTimedOut && !upstreamSignal.aborted) {\n lastAttemptWasUnfinishedContinuation = true;\n await appendContinuationAndJournal(\n opts.messages,\n \"run_timeout\",\n opts.threadId,\n localTurnEvents,\n );\n continue;\n }\n return usage;\n } catch (err) {\n if (softTimedOut && !upstreamSignal.aborted) {\n // Clear partial text the client received before the abort so the\n // resumed model doesn't re-emit it and produce duplicated output.\n lastAttemptWasUnfinishedContinuation = true;\n if (\n !(await hasCompletedSideEffectToolCallInCurrentTurn(\n opts.threadId,\n localTurnEvents,\n ))\n ) {\n opts.send({ type: \"clear\" });\n }\n await appendContinuationAndJournal(\n opts.messages,\n \"run_timeout\",\n opts.threadId,\n localTurnEvents,\n );\n continue;\n }\n // Resumable transport / gateway interruptions: the LLM call was cut off\n // mid-stream (gateway 45s timeout, socket hang up, function-level\n // timeout that didn't trip our soft timer first). Treat it the same way\n // as a soft timeout — append a \"continue from where you left off\" nudge\n // and let the loop run another LLM call. The conversation prefix up to\n // the cut-off is preserved in opts.messages, and Anthropic's prompt\n // cache makes the resume call much faster.\n //\n // Emit 'clear' so any partial streamed text is discarded on the client\n // before the model resumes. Without this the model restarts its sentence\n // from scratch and the fold produces duplicated text in one message\n // (the partial text was already sent to the client but never entered\n // the in-memory messages array, so the next attempt re-emits it).\n if (!upstreamSignal.aborted && isResumableEngineError(err)) {\n lastAttemptWasUnfinishedContinuation = true;\n if (\n !(await hasCompletedSideEffectToolCallInCurrentTurn(\n opts.threadId,\n localTurnEvents,\n ))\n ) {\n opts.send({ type: \"clear\" });\n }\n await appendContinuationAndJournal(\n opts.messages,\n continuationReasonForResumableError(err),\n opts.threadId,\n localTurnEvents,\n );\n continue;\n }\n throw err;\n } finally {\n clearTimeout(timer);\n upstreamSignal.removeEventListener(\"abort\", abortFromUpstream);\n }\n }\n\n // The loop exited without a clean return. If the user aborted, that's a Stop —\n // stay silent. Otherwise we only get here by exhausting\n // MAX_RUN_LOOP_CONTINUATIONS while the last attempt was still trying to\n // continue (soft-timeout / resumable error). That is the genuinely-silent\n // give-up the run-manager would otherwise report as a clean `done`: emit a\n // loud, non-auto-continuing terminal so the user knows the turn stopped\n // before finishing and nothing was partially saved by the run itself.\n if (!upstreamSignal.aborted && lastAttemptWasUnfinishedContinuation) {\n // Discard any partial text already streamed for the unfinished attempt so\n // the terminal message stands alone instead of trailing a half sentence.\n // Preserve completed tool cards: they are the user's only durable proof\n // that a side effect landed before the final assistant note timed out.\n if (\n !(await hasCompletedSideEffectToolCallInCurrentTurn(\n opts.threadId,\n localTurnEvents,\n ))\n ) {\n opts.send({ type: \"clear\" });\n }\n opts.send({\n type: \"error\",\n error: RUN_BUDGET_EXHAUSTED_MESSAGE,\n errorCode: RUN_BUDGET_EXHAUSTED_ERROR_CODE,\n recoverable: true,\n });\n }\n\n return usage;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-store.d.ts","sourceRoot":"","sources":["../../src/agent/run-store.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,QAAS,CAAC;AAEnC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kCAAkC,QAAS,CAAC;AAEzD,eAAO,MAAM,qBAAqB;aAChC,IAAI,EAAE,OAAO;aACb,KAAK,EACH,qHAAqH;aACvH,SAAS,EAAE,WAAW;aACtB,WAAW;aACX,OAAO,EACL,gIAAgI;CAC1H,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,oCAAoC;aAC/C,IAAI,EAAE,OAAO;aACb,KAAK,EACH,gHAAgH;aAClH,SAAS,EAAE,iCAAiC;aAC5C,WAAW;aACX,OAAO,EACL,oNAAoN;CAC9M,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,4CAA4C;aACvD,IAAI,EAAE,OAAO;aACb,KAAK,EACH,oHAAoH;aACtH,SAAS,EAAE,0BAA0B;aACrC,WAAW;aACX,OAAO,EACL,yGAAyG;CACnG,CAAC;AAEX;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iCAAiC,QAAS,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,4CAA4C,QAAa,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,sCAAsC,QAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"run-store.d.ts","sourceRoot":"","sources":["../../src/agent/run-store.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/run-store.js
CHANGED
|
@@ -145,6 +145,32 @@ export const UNCLAIMED_BACKGROUND_RUN_FAST_SWEEP_MS = 20_000;
|
|
|
145
145
|
* constant ever changes.
|
|
146
146
|
*/
|
|
147
147
|
const STALE_RUN_RECOVERY_MAX_TURN_RUNS = 25;
|
|
148
|
+
/**
|
|
149
|
+
* Circuit breaker for a DETERMINISTIC dead-on-arrival loop: some request
|
|
150
|
+
* shapes make the worker hang almost immediately every single time (e.g. an
|
|
151
|
+
* un-timed-out provider fetch that blocks the event loop) rather than merely
|
|
152
|
+
* hitting a transient blip. Because `attemptStaleRunRecovery` replays the
|
|
153
|
+
* SAME captured `dispatch_payload` on every successor (never a fresh
|
|
154
|
+
* request), such a turn was retrying an unwinnable request up to
|
|
155
|
+
* `STALE_RUN_RECOVERY_MAX_TURN_RUNS` (25) times — ~25 * 53s ≈ 22 minutes,
|
|
156
|
+
* each cycle re-billing the full input context — before finally giving up.
|
|
157
|
+
* Confirmed live in prod (assets: one turn cycled 24x, each attempt an
|
|
158
|
+
* identical ~32K-token request that made a token of real progress around
|
|
159
|
+
* ~8s in then went completely silent for the rest of its life until the 45s
|
|
160
|
+
* reap). Stop recovering after this many CONSECUTIVE stale_run reaps that
|
|
161
|
+
* each made near-zero real progress — a single blip never trips it (needs
|
|
162
|
+
* 3 in a row), and a run that's genuinely grinding through long work right
|
|
163
|
+
* up to its heartbeat window is untouched (see `hasNoForwardProgress`).
|
|
164
|
+
*/
|
|
165
|
+
const STALE_RUN_RECOVERY_CONSECUTIVE_NO_PROGRESS_LIMIT = 3;
|
|
166
|
+
/**
|
|
167
|
+
* A reaped run counts as having made no forward progress if it never
|
|
168
|
+
* emitted a real event (`last_progress_at` unset) or died within this many
|
|
169
|
+
* ms of starting — well short of the 45s background reap window, so a run
|
|
170
|
+
* that was legitimately working almost up to the reap boundary is not
|
|
171
|
+
* penalized. See `STALE_RUN_RECOVERY_CONSECUTIVE_NO_PROGRESS_LIMIT`.
|
|
172
|
+
*/
|
|
173
|
+
const STALE_RUN_RECOVERY_NO_PROGRESS_WINDOW_MS = 20_000;
|
|
148
174
|
/**
|
|
149
175
|
* Maximum time the stale reapers (`reapIfStale`, `reapAllStaleRuns`,
|
|
150
176
|
* `cleanupOldRuns`'s heartbeat-stale pass) will suspend reaping a "running"
|
|
@@ -1296,6 +1322,29 @@ async function attemptStaleRunRecovery(db, runId) {
|
|
|
1296
1322
|
turnRunCount > STALE_RUN_RECOVERY_MAX_TURN_RUNS) {
|
|
1297
1323
|
return { outcome: "budget_exhausted" };
|
|
1298
1324
|
}
|
|
1325
|
+
// See `STALE_RUN_RECOVERY_CONSECUTIVE_NO_PROGRESS_LIMIT`: a run whose last
|
|
1326
|
+
// N attempts (including the one just reaped, already written by the
|
|
1327
|
+
// caller's UPDATE earlier in this same transaction) all died as stale_run
|
|
1328
|
+
// having made essentially no real progress is retrying an unwinnable
|
|
1329
|
+
// request, not recovering from a blip. Stop far short of the 25-run/~22min
|
|
1330
|
+
// budget above instead of grinding through it.
|
|
1331
|
+
const { rows: recentRows } = await db.execute({
|
|
1332
|
+
sql: `SELECT error_code, started_at, last_progress_at FROM agent_runs WHERE turn_id = ? ORDER BY started_at DESC LIMIT ?`,
|
|
1333
|
+
args: [turnId, STALE_RUN_RECOVERY_CONSECUTIVE_NO_PROGRESS_LIMIT],
|
|
1334
|
+
});
|
|
1335
|
+
const recent = (recentRows ?? []);
|
|
1336
|
+
const allDeadOnArrival = recent.length === STALE_RUN_RECOVERY_CONSECUTIVE_NO_PROGRESS_LIMIT &&
|
|
1337
|
+
recent.every((r) => {
|
|
1338
|
+
if (r.error_code !== STALE_RUN_ERROR_EVENT.errorCode)
|
|
1339
|
+
return false;
|
|
1340
|
+
const started = Number(r.started_at) || 0;
|
|
1341
|
+
const progress = r.last_progress_at == null ? null : Number(r.last_progress_at);
|
|
1342
|
+
return (progress === null ||
|
|
1343
|
+
progress - started < STALE_RUN_RECOVERY_NO_PROGRESS_WINDOW_MS);
|
|
1344
|
+
});
|
|
1345
|
+
if (allDeadOnArrival) {
|
|
1346
|
+
return { outcome: "repeated_no_progress" };
|
|
1347
|
+
}
|
|
1299
1348
|
const successorRunId = generateRecoveryRunId();
|
|
1300
1349
|
const now = Date.now();
|
|
1301
1350
|
await db.execute({
|