@coool/opencode-adaptive 0.0.0-stage → 1.0.1
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/LICENSE +21 -0
- package/README.md +99 -2
- package/dist/adapters/codex-capacity/index.d.ts +4 -0
- package/dist/adapters/codex-capacity/index.js +5 -0
- package/dist/adapters/codex-capacity/index.js.map +1 -0
- package/dist/adapters/codex-capacity/parse.d.ts +28 -0
- package/dist/adapters/codex-capacity/parse.js +146 -0
- package/dist/adapters/codex-capacity/parse.js.map +1 -0
- package/dist/adapters/codex-capacity/reading.d.ts +9 -0
- package/dist/adapters/codex-capacity/reading.js +45 -0
- package/dist/adapters/codex-capacity/reading.js.map +1 -0
- package/dist/adapters/codex-capacity/sensor.d.ts +23 -0
- package/dist/adapters/codex-capacity/sensor.js +30 -0
- package/dist/adapters/codex-capacity/sensor.js.map +1 -0
- package/dist/adapters/codex-capacity/types.d.ts +31 -0
- package/dist/adapters/codex-capacity/types.js +18 -0
- package/dist/adapters/codex-capacity/types.js.map +1 -0
- package/dist/adapters/opencode/escalation-tool.d.ts +51 -0
- package/dist/adapters/opencode/escalation-tool.js +61 -0
- package/dist/adapters/opencode/escalation-tool.js.map +1 -0
- package/dist/adapters/opencode/events.d.ts +23 -0
- package/dist/adapters/opencode/events.js +68 -0
- package/dist/adapters/opencode/events.js.map +1 -0
- package/dist/adapters/opencode/hooks.d.ts +34 -0
- package/dist/adapters/opencode/hooks.js +29 -0
- package/dist/adapters/opencode/hooks.js.map +1 -0
- package/dist/adapters/opencode/index.d.ts +16 -0
- package/dist/adapters/opencode/index.js +9 -0
- package/dist/adapters/opencode/index.js.map +1 -0
- package/dist/adapters/opencode/inventory.d.ts +30 -0
- package/dist/adapters/opencode/inventory.js +53 -0
- package/dist/adapters/opencode/inventory.js.map +1 -0
- package/dist/adapters/opencode/report.d.ts +91 -0
- package/dist/adapters/opencode/report.js +145 -0
- package/dist/adapters/opencode/report.js.map +1 -0
- package/dist/adapters/opencode/session-ops.d.ts +39 -0
- package/dist/adapters/opencode/session-ops.js +32 -0
- package/dist/adapters/opencode/session-ops.js.map +1 -0
- package/dist/adapters/opencode/storage.d.ts +15 -0
- package/dist/adapters/opencode/storage.js +8 -0
- package/dist/adapters/opencode/storage.js.map +1 -0
- package/dist/adapters/opencode/tier-tool.d.ts +37 -0
- package/dist/adapters/opencode/tier-tool.js +72 -0
- package/dist/adapters/opencode/tier-tool.js.map +1 -0
- package/dist/adapters/opencode/types.d.ts +101 -0
- package/dist/adapters/opencode/types.js +2 -0
- package/dist/adapters/opencode/types.js.map +1 -0
- package/dist/core/compatibility/gate.d.ts +7 -0
- package/dist/core/compatibility/gate.js +51 -0
- package/dist/core/compatibility/gate.js.map +1 -0
- package/dist/core/compatibility/index.d.ts +2 -0
- package/dist/core/compatibility/index.js +3 -0
- package/dist/core/compatibility/index.js.map +1 -0
- package/dist/core/compatibility/types.d.ts +53 -0
- package/dist/core/compatibility/types.js +27 -0
- package/dist/core/compatibility/types.js.map +1 -0
- package/dist/core/scheduler/admit.d.ts +6 -0
- package/dist/core/scheduler/admit.js +154 -0
- package/dist/core/scheduler/admit.js.map +1 -0
- package/dist/core/scheduler/escalate.d.ts +6 -0
- package/dist/core/scheduler/escalate.js +45 -0
- package/dist/core/scheduler/escalate.js.map +1 -0
- package/dist/core/scheduler/index.d.ts +4 -0
- package/dist/core/scheduler/index.js +5 -0
- package/dist/core/scheduler/index.js.map +1 -0
- package/dist/core/scheduler/mode.d.ts +8 -0
- package/dist/core/scheduler/mode.js +10 -0
- package/dist/core/scheduler/mode.js.map +1 -0
- package/dist/core/scheduler/types.d.ts +136 -0
- package/dist/core/scheduler/types.js +75 -0
- package/dist/core/scheduler/types.js.map +1 -0
- package/dist/core/tier-policy/index.d.ts +3 -0
- package/dist/core/tier-policy/index.js +4 -0
- package/dist/core/tier-policy/index.js.map +1 -0
- package/dist/core/tier-policy/resolve.d.ts +18 -0
- package/dist/core/tier-policy/resolve.js +52 -0
- package/dist/core/tier-policy/resolve.js.map +1 -0
- package/dist/core/tier-policy/tier-list.d.ts +10 -0
- package/dist/core/tier-policy/tier-list.js +23 -0
- package/dist/core/tier-policy/tier-list.js.map +1 -0
- package/dist/core/tier-policy/types.d.ts +86 -0
- package/dist/core/tier-policy/types.js +49 -0
- package/dist/core/tier-policy/types.js.map +1 -0
- package/dist/core/work-unit/index.d.ts +3 -0
- package/dist/core/work-unit/index.js +4 -0
- package/dist/core/work-unit/index.js.map +1 -0
- package/dist/core/work-unit/interruption.d.ts +7 -0
- package/dist/core/work-unit/interruption.js +12 -0
- package/dist/core/work-unit/interruption.js.map +1 -0
- package/dist/core/work-unit/tracker.d.ts +53 -0
- package/dist/core/work-unit/tracker.js +156 -0
- package/dist/core/work-unit/tracker.js.map +1 -0
- package/dist/core/work-unit/types.d.ts +151 -0
- package/dist/core/work-unit/types.js +23 -0
- package/dist/core/work-unit/types.js.map +1 -0
- package/dist/execution/continuation/execute.d.ts +18 -0
- package/dist/execution/continuation/execute.js +31 -0
- package/dist/execution/continuation/execute.js.map +1 -0
- package/dist/execution/continuation/index.d.ts +4 -0
- package/dist/execution/continuation/index.js +4 -0
- package/dist/execution/continuation/index.js.map +1 -0
- package/dist/execution/continuation/plan.d.ts +12 -0
- package/dist/execution/continuation/plan.js +18 -0
- package/dist/execution/continuation/plan.js.map +1 -0
- package/dist/execution/continuation/prompts.d.ts +7 -0
- package/dist/execution/continuation/prompts.js +8 -0
- package/dist/execution/continuation/prompts.js.map +1 -0
- package/dist/execution/continuation/types.d.ts +68 -0
- package/dist/execution/continuation/types.js +15 -0
- package/dist/execution/continuation/types.js.map +1 -0
- package/dist/execution/escalation/index.d.ts +1 -0
- package/dist/execution/escalation/index.js +2 -0
- package/dist/execution/escalation/index.js.map +1 -0
- package/dist/execution/escalation/types.d.ts +30 -0
- package/dist/execution/escalation/types.js +49 -0
- package/dist/execution/escalation/types.js.map +1 -0
- package/dist/execution/index.d.ts +4 -0
- package/dist/execution/index.js +5 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/parking/index.d.ts +2 -0
- package/dist/execution/parking/index.js +2 -0
- package/dist/execution/parking/index.js.map +1 -0
- package/dist/execution/parking/plan.d.ts +39 -0
- package/dist/execution/parking/plan.js +34 -0
- package/dist/execution/parking/plan.js.map +1 -0
- package/dist/execution/retry/decide.d.ts +29 -0
- package/dist/execution/retry/decide.js +75 -0
- package/dist/execution/retry/decide.js.map +1 -0
- package/dist/execution/retry/index.d.ts +2 -0
- package/dist/execution/retry/index.js +3 -0
- package/dist/execution/retry/index.js.map +1 -0
- package/dist/execution/retry/types.d.ts +64 -0
- package/dist/execution/retry/types.js +9 -0
- package/dist/execution/retry/types.js.map +1 -0
- package/dist/gui-experimental.cjs +1 -0
- package/dist/gui.d.ts +16 -0
- package/dist/gui.js +73 -0
- package/dist/gui.js.map +1 -0
- package/dist/health/capacity/index.d.ts +3 -0
- package/dist/health/capacity/index.js +4 -0
- package/dist/health/capacity/index.js.map +1 -0
- package/dist/health/capacity/merge.d.ts +57 -0
- package/dist/health/capacity/merge.js +154 -0
- package/dist/health/capacity/merge.js.map +1 -0
- package/dist/health/capacity/registry.d.ts +40 -0
- package/dist/health/capacity/registry.js +106 -0
- package/dist/health/capacity/registry.js.map +1 -0
- package/dist/health/capacity/types.d.ts +73 -0
- package/dist/health/capacity/types.js +6 -0
- package/dist/health/capacity/types.js.map +1 -0
- package/dist/health/circuit-breaker/breaker.d.ts +91 -0
- package/dist/health/circuit-breaker/breaker.js +150 -0
- package/dist/health/circuit-breaker/breaker.js.map +1 -0
- package/dist/health/circuit-breaker/index.d.ts +2 -0
- package/dist/health/circuit-breaker/index.js +3 -0
- package/dist/health/circuit-breaker/index.js.map +1 -0
- package/dist/health/circuit-breaker/types.d.ts +52 -0
- package/dist/health/circuit-breaker/types.js +13 -0
- package/dist/health/circuit-breaker/types.js.map +1 -0
- package/dist/health/classifier/classify.d.ts +8 -0
- package/dist/health/classifier/classify.js +245 -0
- package/dist/health/classifier/classify.js.map +1 -0
- package/dist/health/classifier/index.d.ts +2 -0
- package/dist/health/classifier/index.js +3 -0
- package/dist/health/classifier/index.js.map +1 -0
- package/dist/health/classifier/types.d.ts +71 -0
- package/dist/health/classifier/types.js +27 -0
- package/dist/health/classifier/types.js.map +1 -0
- package/dist/health/index.d.ts +4 -0
- package/dist/health/index.js +5 -0
- package/dist/health/index.js.map +1 -0
- package/dist/health/resource-health/index.d.ts +4 -0
- package/dist/health/resource-health/index.js +5 -0
- package/dist/health/resource-health/index.js.map +1 -0
- package/dist/health/resource-health/key.d.ts +18 -0
- package/dist/health/resource-health/key.js +54 -0
- package/dist/health/resource-health/key.js.map +1 -0
- package/dist/health/resource-health/registry.d.ts +46 -0
- package/dist/health/resource-health/registry.js +276 -0
- package/dist/health/resource-health/registry.js.map +1 -0
- package/dist/health/resource-health/transitions.d.ts +9 -0
- package/dist/health/resource-health/transitions.js +157 -0
- package/dist/health/resource-health/transitions.js.map +1 -0
- package/dist/health/resource-health/types.d.ts +122 -0
- package/dist/health/resource-health/types.js +44 -0
- package/dist/health/resource-health/types.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +105 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin-id.d.ts +2 -0
- package/dist/plugin-id.js +3 -0
- package/dist/plugin-id.js.map +1 -0
- package/dist/rpc/definition.d.ts +123 -0
- package/dist/rpc/definition.js +130 -0
- package/dist/rpc/definition.js.map +1 -0
- package/dist/rpc/handlers.d.ts +53 -0
- package/dist/rpc/handlers.js +125 -0
- package/dist/rpc/handlers.js.map +1 -0
- package/dist/rpc/status.d.ts +42 -0
- package/dist/rpc/status.js +45 -0
- package/dist/rpc/status.js.map +1 -0
- package/dist/rpc.d.ts +10 -0
- package/dist/rpc.js +8 -0
- package/dist/rpc.js.map +1 -0
- package/dist/state/capacity/index.d.ts +3 -0
- package/dist/state/capacity/index.js +4 -0
- package/dist/state/capacity/index.js.map +1 -0
- package/dist/state/capacity/parse.d.ts +2 -0
- package/dist/state/capacity/parse.js +122 -0
- package/dist/state/capacity/parse.js.map +1 -0
- package/dist/state/capacity/store.d.ts +18 -0
- package/dist/state/capacity/store.js +78 -0
- package/dist/state/capacity/store.js.map +1 -0
- package/dist/state/capacity/types.d.ts +37 -0
- package/dist/state/capacity/types.js +11 -0
- package/dist/state/capacity/types.js.map +1 -0
- package/dist/state/health/index.d.ts +4 -0
- package/dist/state/health/index.js +4 -0
- package/dist/state/health/index.js.map +1 -0
- package/dist/state/health/parse.d.ts +2 -0
- package/dist/state/health/parse.js +137 -0
- package/dist/state/health/parse.js.map +1 -0
- package/dist/state/health/store.d.ts +17 -0
- package/dist/state/health/store.js +69 -0
- package/dist/state/health/store.js.map +1 -0
- package/dist/state/health/types.d.ts +23 -0
- package/dist/state/health/types.js +5 -0
- package/dist/state/health/types.js.map +1 -0
- package/dist/state/parked-work/index.d.ts +4 -0
- package/dist/state/parked-work/index.js +4 -0
- package/dist/state/parked-work/index.js.map +1 -0
- package/dist/state/parked-work/parse.d.ts +6 -0
- package/dist/state/parked-work/parse.js +83 -0
- package/dist/state/parked-work/parse.js.map +1 -0
- package/dist/state/parked-work/store.d.ts +17 -0
- package/dist/state/parked-work/store.js +98 -0
- package/dist/state/parked-work/store.js.map +1 -0
- package/dist/state/parked-work/types.d.ts +41 -0
- package/dist/state/parked-work/types.js +7 -0
- package/dist/state/parked-work/types.js.map +1 -0
- package/dist/state/receipts/bound.d.ts +14 -0
- package/dist/state/receipts/bound.js +77 -0
- package/dist/state/receipts/bound.js.map +1 -0
- package/dist/state/receipts/index.d.ts +6 -0
- package/dist/state/receipts/index.js +5 -0
- package/dist/state/receipts/index.js.map +1 -0
- package/dist/state/receipts/parse.d.ts +6 -0
- package/dist/state/receipts/parse.js +226 -0
- package/dist/state/receipts/parse.js.map +1 -0
- package/dist/state/receipts/store.d.ts +34 -0
- package/dist/state/receipts/store.js +148 -0
- package/dist/state/receipts/store.js.map +1 -0
- package/dist/state/receipts/types.d.ts +61 -0
- package/dist/state/receipts/types.js +12 -0
- package/dist/state/receipts/types.js.map +1 -0
- package/dist/state/session-modes/index.d.ts +4 -0
- package/dist/state/session-modes/index.js +4 -0
- package/dist/state/session-modes/index.js.map +1 -0
- package/dist/state/session-modes/parse.d.ts +8 -0
- package/dist/state/session-modes/parse.js +62 -0
- package/dist/state/session-modes/parse.js.map +1 -0
- package/dist/state/session-modes/store.d.ts +20 -0
- package/dist/state/session-modes/store.js +87 -0
- package/dist/state/session-modes/store.js.map +1 -0
- package/dist/state/session-modes/types.d.ts +41 -0
- package/dist/state/session-modes/types.js +7 -0
- package/dist/state/session-modes/types.js.map +1 -0
- package/dist/state/settings/index.d.ts +4 -0
- package/dist/state/settings/index.js +4 -0
- package/dist/state/settings/index.js.map +1 -0
- package/dist/state/settings/parse.d.ts +33 -0
- package/dist/state/settings/parse.js +261 -0
- package/dist/state/settings/parse.js.map +1 -0
- package/dist/state/settings/store.d.ts +21 -0
- package/dist/state/settings/store.js +65 -0
- package/dist/state/settings/store.js.map +1 -0
- package/dist/state/settings/types.d.ts +62 -0
- package/dist/state/settings/types.js +12 -0
- package/dist/state/settings/types.js.map +1 -0
- package/dist/state/tier-requests/index.d.ts +4 -0
- package/dist/state/tier-requests/index.js +4 -0
- package/dist/state/tier-requests/index.js.map +1 -0
- package/dist/state/tier-requests/parse.d.ts +3 -0
- package/dist/state/tier-requests/parse.js +53 -0
- package/dist/state/tier-requests/parse.js.map +1 -0
- package/dist/state/tier-requests/store.d.ts +27 -0
- package/dist/state/tier-requests/store.js +96 -0
- package/dist/state/tier-requests/store.js.map +1 -0
- package/dist/state/tier-requests/types.d.ts +30 -0
- package/dist/state/tier-requests/types.js +7 -0
- package/dist/state/tier-requests/types.js.map +1 -0
- package/dist/supervisor/index.d.ts +4 -0
- package/dist/supervisor/index.js +4 -0
- package/dist/supervisor/index.js.map +1 -0
- package/dist/supervisor/log.d.ts +10 -0
- package/dist/supervisor/log.js +14 -0
- package/dist/supervisor/log.js.map +1 -0
- package/dist/supervisor/supervisor.d.ts +86 -0
- package/dist/supervisor/supervisor.js +1629 -0
- package/dist/supervisor/supervisor.js.map +1 -0
- package/dist/supervisor/types.d.ts +49 -0
- package/dist/supervisor/types.js +3 -0
- package/dist/supervisor/types.js.map +1 -0
- package/dist/supervisor/view.d.ts +3 -0
- package/dist/supervisor/view.js +4 -0
- package/dist/supervisor/view.js.map +1 -0
- package/dist/tui.d.ts +15 -0
- package/dist/tui.js +256 -0
- package/dist/tui.js.map +1 -0
- package/dist/ui/gui/api.d.ts +17 -0
- package/dist/ui/gui/api.js +21 -0
- package/dist/ui/gui/api.js.map +1 -0
- package/dist/ui/gui/view.d.ts +26 -0
- package/dist/ui/gui/view.js +49 -0
- package/dist/ui/gui/view.js.map +1 -0
- package/dist/ui/tui/controller.d.ts +97 -0
- package/dist/ui/tui/controller.js +415 -0
- package/dist/ui/tui/controller.js.map +1 -0
- package/dist/ui/tui/menu.d.ts +55 -0
- package/dist/ui/tui/menu.js +176 -0
- package/dist/ui/tui/menu.js.map +1 -0
- package/dist/ui/tui/options.d.ts +19 -0
- package/dist/ui/tui/options.js +17 -0
- package/dist/ui/tui/options.js.map +1 -0
- package/dist/ui/tui/receipts.d.ts +21 -0
- package/dist/ui/tui/receipts.js +112 -0
- package/dist/ui/tui/receipts.js.map +1 -0
- package/dist/ui/tui/status.d.ts +22 -0
- package/dist/ui/tui/status.js +92 -0
- package/dist/ui/tui/status.js.map +1 -0
- package/dist/ui/tui/tiers.d.ts +51 -0
- package/dist/ui/tui/tiers.js +108 -0
- package/dist/ui/tui/tiers.js.map +1 -0
- package/package.json +85 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/work-unit/types.ts"],"names":[],"mappings":"AAiBA,sEAAsE;AACtE,MAAM,UAAU,YAAY,CAAC,CAAW,EAAE,CAAW;IACnD,OAAO,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,CAAA;AAClF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,mBAAmB;IACnB,mBAAmB;IACnB,SAAS;CAC2B,CAAA;AAmGtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,8BAA8B,CAAsC,CAAA","sourcesContent":["/**\n * Work-unit model (ADP-001): one unit is exactly one OpenCode execution\n * episode — `session.execution.started` → `succeeded`/`failed`/`interrupted`.\n * Tool/step/text continuations never open, close, or split a unit (only the\n * execution events do); a subagent runs in its own session and therefore gets\n * its own units; a later continuation on the same session (e.g. a new /goal\n * round) is a new episode of that session.\n */\nimport type { InterruptReason } from \"./interruption.js\"\n\n/** OpenCode model reference (`Model.Ref`): provider, model, optional variant. */\nexport interface ModelRef {\n readonly providerID: string\n readonly id: string\n readonly variant?: string | undefined\n}\n\n/** Full-field equality; a variant change is a different reference. */\nexport function sameModelRef(a: ModelRef, b: ModelRef): boolean {\n return a.providerID === b.providerID && a.id === b.id && a.variant === b.variant\n}\n\n/**\n * How the model in effect became known. `selected-*` comes from the\n * `session.model.selected` event (which fires for both manual and\n * plugin-made switches — the tracker resolves which via pending own-switch\n * notes, see `WorkUnitTracker.noteOwnSwitch`); `request` comes from the\n * `context` hook and reports the model actually executing.\n */\nexport const MODEL_SOURCES = [\n \"selected-adaptive\",\n \"selected-external\",\n \"request\",\n] as const satisfies readonly string[]\n\nexport type ModelSource = (typeof MODEL_SOURCES)[number]\n\nexport interface ModelTransition {\n readonly at: number\n readonly model: ModelRef\n readonly source: ModelSource\n}\n\n/**\n * Minimal shape of the wire `Session.StructuredError` carried by\n * `session.execution.failed` (`response.body` is deliberately dropped here —\n * the adapter folds it into bounded `ErrorEvidence` for the classifier).\n */\nexport interface ExecutionError {\n readonly type: string\n readonly message: string\n readonly status?: number | undefined\n readonly retryAfterMs?: number | undefined\n}\n\n/**\n * The episode lifecycle. `kind` doubles as status: `\"active\"` while the\n * execution runs, then the terminal kind it closed with.\n */\ninterface UnitBase {\n /** Stable per-episode identifier: `${sessionID}#${episode}`. */\n readonly id: string\n readonly sessionID: string\n /** 1-based count of episodes started for this session (tracker lifetime). */\n readonly episode: number\n readonly startedAt: number\n /**\n * Model in effect for the unit: seeded from the last known selection when\n * the unit opens, then updated by transitions.\n */\n readonly model?: ModelRef | undefined\n readonly transitions: readonly ModelTransition[]\n}\n\nexport interface ActiveUnit extends UnitBase {\n readonly kind: \"active\"\n}\n\nexport interface SucceededUnit extends UnitBase {\n readonly kind: \"succeeded\"\n readonly closedAt: number\n}\n\nexport interface FailedUnit extends UnitBase {\n readonly kind: \"failed\"\n readonly closedAt: number\n readonly error: ExecutionError\n}\n\nexport interface InterruptedUnit extends UnitBase {\n readonly kind: \"interrupted\"\n readonly closedAt: number\n readonly reason: InterruptReason\n}\n\nexport type ClosedUnit = SucceededUnit | FailedUnit | InterruptedUnit\n\nexport type WorkUnit = ActiveUnit | ClosedUnit\n\n/**\n * Normalized episode events. The OpenCode adapter unwraps host event payloads\n * (`event.data.*`) and forwards them here; `model-request` is fed from the\n * `context` session hook.\n */\nexport type WorkUnitEvent =\n | { readonly kind: \"execution-started\"; readonly sessionID: string; readonly at: number }\n | { readonly kind: \"execution-succeeded\"; readonly sessionID: string; readonly at: number }\n | {\n readonly kind: \"execution-failed\"\n readonly sessionID: string\n readonly at: number\n readonly error: ExecutionError\n }\n | {\n readonly kind: \"execution-interrupted\"\n readonly sessionID: string\n readonly at: number\n readonly reason: InterruptReason\n }\n | {\n readonly kind: \"model-selected\"\n readonly sessionID: string\n readonly at: number\n readonly model: ModelRef\n }\n | {\n readonly kind: \"model-request\"\n readonly sessionID: string\n readonly at: number\n readonly model: ModelRef\n }\n\n/**\n * Why an event produced no state change. Only terminal events can be ignored\n * — they arrive without an active unit when the terminal was already handled\n * (duplicate delivery) or never preceded by `execution-started`.\n */\nexport const IGNORED_REASONS = [\"terminal-without-active-unit\"] as const satisfies readonly string[]\n\nexport type IgnoredReason = (typeof IGNORED_REASONS)[number]\n\n/** Result of an execution-started event: the tracker always opens (possibly superseding). */\nexport type OpenedResult = Extract<ApplyResult, { kind: \"opened\" }>\n\n/** Result of a selection event: the tracker always records model knowledge. */\nexport type SelectionResult = Extract<\n ApplyResult,\n { kind: \"model-noted\" } | { kind: \"model-tracked\" }\n>\n\nexport type ApplyResult =\n | {\n readonly kind: \"opened\"\n readonly unit: ActiveUnit\n readonly superseded?: ClosedUnit | undefined\n }\n | { readonly kind: \"closed\"; readonly unit: ClosedUnit }\n | {\n readonly kind: \"model-tracked\"\n readonly unit: ActiveUnit\n readonly transition: ModelTransition\n }\n /** Model knowledge recorded with no active unit; remembered for the next admission. */\n | { readonly kind: \"model-noted\"; readonly transition: ModelTransition }\n | { readonly kind: \"ignored\"; readonly reason: IgnoredReason }\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ContinuationOutcome } from "./types.js";
|
|
2
|
+
import type { ContinuationExecuteInput } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Executes a planned continuation through the narrow ops seam, enforcing
|
|
5
|
+
* the partial-work invariants in one place (ADP-014/ADP-023):
|
|
6
|
+
*
|
|
7
|
+
* 1. Every owned path settles the session FIRST — Adaptive never switches
|
|
8
|
+
* or prompts while a failed execution is still settling.
|
|
9
|
+
* 2. The delivered prompt is always the fixed continuation prompt over the
|
|
10
|
+
* existing session/workspace state — the original instruction is never
|
|
11
|
+
* re-sent, so the never-replay invariant holds by construction.
|
|
12
|
+
* 3. `allow-native` performs no host operations at all.
|
|
13
|
+
*
|
|
14
|
+
* Ops failures propagate to the caller (the wiring's fail-open wrapper
|
|
15
|
+
* decides degradation); the ordering guarantee holds up to the first
|
|
16
|
+
* failure because each step awaits the previous one.
|
|
17
|
+
*/
|
|
18
|
+
export declare function executeContinuation(input: ContinuationExecuteInput): Promise<ContinuationOutcome>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { CONTINUATION_PROMPT } from "./prompts.js";
|
|
2
|
+
/**
|
|
3
|
+
* Executes a planned continuation through the narrow ops seam, enforcing
|
|
4
|
+
* the partial-work invariants in one place (ADP-014/ADP-023):
|
|
5
|
+
*
|
|
6
|
+
* 1. Every owned path settles the session FIRST — Adaptive never switches
|
|
7
|
+
* or prompts while a failed execution is still settling.
|
|
8
|
+
* 2. The delivered prompt is always the fixed continuation prompt over the
|
|
9
|
+
* existing session/workspace state — the original instruction is never
|
|
10
|
+
* re-sent, so the never-replay invariant holds by construction.
|
|
11
|
+
* 3. `allow-native` performs no host operations at all.
|
|
12
|
+
*
|
|
13
|
+
* Ops failures propagate to the caller (the wiring's fail-open wrapper
|
|
14
|
+
* decides degradation); the ordering guarantee holds up to the first
|
|
15
|
+
* failure because each step awaits the previous one.
|
|
16
|
+
*/
|
|
17
|
+
export async function executeContinuation(input) {
|
|
18
|
+
const { action, ops, sessionID } = input;
|
|
19
|
+
if (action.kind === "allow-native")
|
|
20
|
+
return { kind: "left-native" };
|
|
21
|
+
if (action.kind === "in-session") {
|
|
22
|
+
await ops.settle(sessionID);
|
|
23
|
+
await ops.switchModel(sessionID, action.model);
|
|
24
|
+
await ops.prompt(sessionID, CONTINUATION_PROMPT);
|
|
25
|
+
return { kind: "resumed" };
|
|
26
|
+
}
|
|
27
|
+
await ops.settle(sessionID);
|
|
28
|
+
await ops.prompt(sessionID, CONTINUATION_PROMPT);
|
|
29
|
+
return { kind: "continuation-started" };
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=execute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/execution/continuation/execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAIlD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAA+B;IAE/B,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,KAAK,CAAA;IACxC,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc;QAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;IAClE,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACjC,MAAM,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC3B,MAAM,GAAG,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;QAC9C,MAAM,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAA;QAChD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;IAC5B,CAAC;IACD,MAAM,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAC3B,MAAM,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAA;IAChD,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAA;AACzC,CAAC","sourcesContent":["import { CONTINUATION_PROMPT } from \"./prompts.js\"\nimport type { ContinuationOutcome } from \"./types.js\"\nimport type { ContinuationExecuteInput } from \"./types.js\"\n\n/**\n * Executes a planned continuation through the narrow ops seam, enforcing\n * the partial-work invariants in one place (ADP-014/ADP-023):\n *\n * 1. Every owned path settles the session FIRST — Adaptive never switches\n * or prompts while a failed execution is still settling.\n * 2. The delivered prompt is always the fixed continuation prompt over the\n * existing session/workspace state — the original instruction is never\n * re-sent, so the never-replay invariant holds by construction.\n * 3. `allow-native` performs no host operations at all.\n *\n * Ops failures propagate to the caller (the wiring's fail-open wrapper\n * decides degradation); the ordering guarantee holds up to the first\n * failure because each step awaits the previous one.\n */\nexport async function executeContinuation(\n input: ContinuationExecuteInput,\n): Promise<ContinuationOutcome> {\n const { action, ops, sessionID } = input\n if (action.kind === \"allow-native\") return { kind: \"left-native\" }\n if (action.kind === \"in-session\") {\n await ops.settle(sessionID)\n await ops.switchModel(sessionID, action.model)\n await ops.prompt(sessionID, CONTINUATION_PROMPT)\n return { kind: \"resumed\" }\n }\n await ops.settle(sessionID)\n await ops.prompt(sessionID, CONTINUATION_PROMPT)\n return { kind: \"continuation-started\" }\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { ContinuationAction, ContinuationActionKind, ContinuationExecuteInput, ContinuationOps, ContinuationOutcome, ContinuationPlanInput, } from "./types.js";
|
|
2
|
+
export { CONTINUATION_PROMPT } from "./prompts.js";
|
|
3
|
+
export { planContinuation } from "./plan.js";
|
|
4
|
+
export { executeContinuation } from "./execute.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/execution/continuation/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA","sourcesContent":["export type {\n ContinuationAction,\n ContinuationActionKind,\n ContinuationExecuteInput,\n ContinuationOps,\n ContinuationOutcome,\n ContinuationPlanInput,\n} from \"./types.js\"\nexport { CONTINUATION_PROMPT } from \"./prompts.js\"\nexport { planContinuation } from \"./plan.js\"\nexport { executeContinuation } from \"./execute.js\"\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ContinuationAction, ContinuationPlanInput } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Partial-work safety planner (ADP-023). Total, deterministic, pure.
|
|
4
|
+
*
|
|
5
|
+
* - No owned recovery: OpenCode's native retry is the preferred recovery;
|
|
6
|
+
* Adaptive leaves it alone.
|
|
7
|
+
* - Owned recovery and the in-session path is possible: continue the same
|
|
8
|
+
* session on the recovered candidate (settle → switch → resume).
|
|
9
|
+
* - Owned recovery and the in-session path is impossible: start a clean
|
|
10
|
+
* continuation work unit from existing durable session state.
|
|
11
|
+
*/
|
|
12
|
+
export declare function planContinuation(input: ContinuationPlanInput): ContinuationAction;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Partial-work safety planner (ADP-023). Total, deterministic, pure.
|
|
3
|
+
*
|
|
4
|
+
* - No owned recovery: OpenCode's native retry is the preferred recovery;
|
|
5
|
+
* Adaptive leaves it alone.
|
|
6
|
+
* - Owned recovery and the in-session path is possible: continue the same
|
|
7
|
+
* session on the recovered candidate (settle → switch → resume).
|
|
8
|
+
* - Owned recovery and the in-session path is impossible: start a clean
|
|
9
|
+
* continuation work unit from existing durable session state.
|
|
10
|
+
*/
|
|
11
|
+
export function planContinuation(input) {
|
|
12
|
+
if (input.recovery.kind === "none")
|
|
13
|
+
return { kind: "allow-native" };
|
|
14
|
+
if (input.continuationPossible)
|
|
15
|
+
return { kind: "in-session", model: input.recovery.model };
|
|
16
|
+
return { kind: "clean-continuation" };
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/execution/continuation/plan.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA4B;IAC3D,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAA;IACnE,IAAI,KAAK,CAAC,oBAAoB;QAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;IAC1F,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAA;AACvC,CAAC","sourcesContent":["import type { ContinuationAction, ContinuationPlanInput } from \"./types.js\"\n\n/**\n * Partial-work safety planner (ADP-023). Total, deterministic, pure.\n *\n * - No owned recovery: OpenCode's native retry is the preferred recovery;\n * Adaptive leaves it alone.\n * - Owned recovery and the in-session path is possible: continue the same\n * session on the recovered candidate (settle → switch → resume).\n * - Owned recovery and the in-session path is impossible: start a clean\n * continuation work unit from existing durable session state.\n */\nexport function planContinuation(input: ContinuationPlanInput): ContinuationAction {\n if (input.recovery.kind === \"none\") return { kind: \"allow-native\" }\n if (input.continuationPossible) return { kind: \"in-session\", model: input.recovery.model }\n return { kind: \"clean-continuation\" }\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuation prompt for owned recovery and parked-work resume (ADP-023).
|
|
3
|
+
* Continues from session state; never replays the original instruction once
|
|
4
|
+
* tool side effects may exist. The executor sends exactly this prompt — the
|
|
5
|
+
* never-replay invariant is structural, not a caller responsibility.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CONTINUATION_PROMPT = "Continue the interrupted work from the current session state. Do not repeat completed work; resume from what the session already produced.";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuation prompt for owned recovery and parked-work resume (ADP-023).
|
|
3
|
+
* Continues from session state; never replays the original instruction once
|
|
4
|
+
* tool side effects may exist. The executor sends exactly this prompt — the
|
|
5
|
+
* never-replay invariant is structural, not a caller responsibility.
|
|
6
|
+
*/
|
|
7
|
+
export const CONTINUATION_PROMPT = "Continue the interrupted work from the current session state. Do not repeat completed work; resume from what the session already produced.";
|
|
8
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/execution/continuation/prompts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,4IAA4I,CAAA","sourcesContent":["/**\n * Continuation prompt for owned recovery and parked-work resume (ADP-023).\n * Continues from session state; never replays the original instruction once\n * tool side effects may exist. The executor sends exactly this prompt — the\n * never-replay invariant is structural, not a caller responsibility.\n */\nexport const CONTINUATION_PROMPT =\n \"Continue the interrupted work from the current session state. Do not repeat completed work; resume from what the session already produced.\"\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ModelRef } from "../../core/work-unit/types.js";
|
|
2
|
+
import type { RecoveryOption } from "../retry/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* What Adaptive does for a failed work unit's recovery (ADP-013/ADP-014).
|
|
5
|
+
* - `allow-native`: Adaptive did not take ownership (no veto) — OpenCode's
|
|
6
|
+
* native retry lifecycle is the preferred recovery and stays untouched.
|
|
7
|
+
* - `in-session`: Adaptive vetoed native retry and continues the same
|
|
8
|
+
* session on a recovered candidate (settle → switch → resume).
|
|
9
|
+
* - `clean-continuation`: the in-session path is not possible; start a
|
|
10
|
+
* clean continuation work unit from existing durable session state.
|
|
11
|
+
*
|
|
12
|
+
* The union has no "replay" variant by construction: every owned path
|
|
13
|
+
* continues from session state, so "Adaptive replays the original
|
|
14
|
+
* instruction after side effects" is unrepresentable, not merely avoided.
|
|
15
|
+
*/
|
|
16
|
+
export declare const CONTINUATION_ACTIONS: readonly ["allow-native", "in-session", "clean-continuation"];
|
|
17
|
+
export type ContinuationActionKind = (typeof CONTINUATION_ACTIONS)[number];
|
|
18
|
+
export type ContinuationAction = {
|
|
19
|
+
kind: "allow-native";
|
|
20
|
+
} | {
|
|
21
|
+
kind: "in-session";
|
|
22
|
+
model: ModelRef;
|
|
23
|
+
} | {
|
|
24
|
+
kind: "clean-continuation";
|
|
25
|
+
};
|
|
26
|
+
export interface ContinuationPlanInput {
|
|
27
|
+
/**
|
|
28
|
+
* Recovery option computed by the wiring for the failing unit: `none`
|
|
29
|
+
* means Adaptive did not veto (OpenCode's native retry is the preferred
|
|
30
|
+
* recovery); `switch` means Adaptive vetoed and owns the recovery.
|
|
31
|
+
*/
|
|
32
|
+
readonly recovery: RecoveryOption;
|
|
33
|
+
/**
|
|
34
|
+
* True when the in-session owned path is possible (session alive, settle
|
|
35
|
+
* + switch + resume available). Only consulted for `switch` recovery.
|
|
36
|
+
*/
|
|
37
|
+
readonly continuationPossible: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Narrow seam over the host session operations the owned continuation
|
|
41
|
+
* needs. Implemented by the OpenCode adapter (which tags its own model
|
|
42
|
+
* switches for attribution before calling the host); tests use fakes that
|
|
43
|
+
* record call order. Never imports `@opencode/plugin`.
|
|
44
|
+
*/
|
|
45
|
+
export interface ContinuationOps {
|
|
46
|
+
/**
|
|
47
|
+
* Wait until the session's failed execution has settled. Every owned
|
|
48
|
+
* path settles first — Adaptive never switches or prompts while a failed
|
|
49
|
+
* execution is still settling.
|
|
50
|
+
*/
|
|
51
|
+
settle(sessionID: string): Promise<void>;
|
|
52
|
+
/** Switch the session's model (own-switch attribution handled by the adapter). */
|
|
53
|
+
switchModel(sessionID: string, model: ModelRef): Promise<void>;
|
|
54
|
+
/** Deliver a prompt to the session; starts/continues execution. */
|
|
55
|
+
prompt(sessionID: string, text: string): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
export interface ContinuationExecuteInput {
|
|
58
|
+
readonly sessionID: string;
|
|
59
|
+
readonly action: ContinuationAction;
|
|
60
|
+
readonly ops: ContinuationOps;
|
|
61
|
+
}
|
|
62
|
+
export type ContinuationOutcome = {
|
|
63
|
+
kind: "left-native";
|
|
64
|
+
} | {
|
|
65
|
+
kind: "resumed";
|
|
66
|
+
} | {
|
|
67
|
+
kind: "continuation-started";
|
|
68
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What Adaptive does for a failed work unit's recovery (ADP-013/ADP-014).
|
|
3
|
+
* - `allow-native`: Adaptive did not take ownership (no veto) — OpenCode's
|
|
4
|
+
* native retry lifecycle is the preferred recovery and stays untouched.
|
|
5
|
+
* - `in-session`: Adaptive vetoed native retry and continues the same
|
|
6
|
+
* session on a recovered candidate (settle → switch → resume).
|
|
7
|
+
* - `clean-continuation`: the in-session path is not possible; start a
|
|
8
|
+
* clean continuation work unit from existing durable session state.
|
|
9
|
+
*
|
|
10
|
+
* The union has no "replay" variant by construction: every owned path
|
|
11
|
+
* continues from session state, so "Adaptive replays the original
|
|
12
|
+
* instruction after side effects" is unrepresentable, not merely avoided.
|
|
13
|
+
*/
|
|
14
|
+
export const CONTINUATION_ACTIONS = ["allow-native", "in-session", "clean-continuation"];
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/execution/continuation/types.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,cAAc,EAAE,YAAY,EAAE,oBAAoB,CAAU,CAAA","sourcesContent":["import type { ModelRef } from \"../../core/work-unit/types.js\"\nimport type { RecoveryOption } from \"../retry/types.js\"\n\n/**\n * What Adaptive does for a failed work unit's recovery (ADP-013/ADP-014).\n * - `allow-native`: Adaptive did not take ownership (no veto) — OpenCode's\n * native retry lifecycle is the preferred recovery and stays untouched.\n * - `in-session`: Adaptive vetoed native retry and continues the same\n * session on a recovered candidate (settle → switch → resume).\n * - `clean-continuation`: the in-session path is not possible; start a\n * clean continuation work unit from existing durable session state.\n *\n * The union has no \"replay\" variant by construction: every owned path\n * continues from session state, so \"Adaptive replays the original\n * instruction after side effects\" is unrepresentable, not merely avoided.\n */\nexport const CONTINUATION_ACTIONS = [\"allow-native\", \"in-session\", \"clean-continuation\"] as const\nexport type ContinuationActionKind = (typeof CONTINUATION_ACTIONS)[number]\n\nexport type ContinuationAction =\n | { kind: \"allow-native\" }\n | { kind: \"in-session\"; model: ModelRef }\n | { kind: \"clean-continuation\" }\n\nexport interface ContinuationPlanInput {\n /**\n * Recovery option computed by the wiring for the failing unit: `none`\n * means Adaptive did not veto (OpenCode's native retry is the preferred\n * recovery); `switch` means Adaptive vetoed and owns the recovery.\n */\n readonly recovery: RecoveryOption\n /**\n * True when the in-session owned path is possible (session alive, settle\n * + switch + resume available). Only consulted for `switch` recovery.\n */\n readonly continuationPossible: boolean\n}\n\n/**\n * Narrow seam over the host session operations the owned continuation\n * needs. Implemented by the OpenCode adapter (which tags its own model\n * switches for attribution before calling the host); tests use fakes that\n * record call order. Never imports `@opencode/plugin`.\n */\nexport interface ContinuationOps {\n /**\n * Wait until the session's failed execution has settled. Every owned\n * path settles first — Adaptive never switches or prompts while a failed\n * execution is still settling.\n */\n settle(sessionID: string): Promise<void>\n /** Switch the session's model (own-switch attribution handled by the adapter). */\n switchModel(sessionID: string, model: ModelRef): Promise<void>\n /** Deliver a prompt to the session; starts/continues execution. */\n prompt(sessionID: string, text: string): Promise<void>\n}\n\nexport interface ContinuationExecuteInput {\n readonly sessionID: string\n readonly action: ContinuationAction\n readonly ops: ContinuationOps\n}\n\nexport type ContinuationOutcome =\n { kind: \"left-native\" } | { kind: \"resumed\" } | { kind: \"continuation-started\" }\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/execution/escalation/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA","sourcesContent":["export * from \"./types.js\"\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Adaptive-owned escalation request surface (T-18, ADP-015..017). The
|
|
3
|
+
* schema requires a reason and evidence — it is deliberately the smallest
|
|
4
|
+
* typed mechanism for an agent to request stronger capability, and it is not
|
|
5
|
+
* a planning or task-management API. The request is recorded against the
|
|
6
|
+
* current work unit and applies at the next safe boundary within the finite
|
|
7
|
+
* per-unit budget; a completing unit discards it (routing re-runs fresh).
|
|
8
|
+
*/
|
|
9
|
+
/** The tool name as registered with the host. */
|
|
10
|
+
export declare const ESCALATION_TOOL_NAME = "adaptive_escalate";
|
|
11
|
+
/** Each field is bounded — the request never carries unbounded prose. */
|
|
12
|
+
export declare const MAX_ESCALATION_FIELD_LENGTH = 256;
|
|
13
|
+
export interface EscalationRequest {
|
|
14
|
+
readonly reason: string;
|
|
15
|
+
readonly evidence: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Truncates to `max` UTF-16 code units without splitting a surrogate pair:
|
|
19
|
+
* a trailing high surrogate whose low half was cut is dropped, so the
|
|
20
|
+
* persisted evidence never carries a lone surrogate.
|
|
21
|
+
*/
|
|
22
|
+
export declare function truncateBounded(text: string, max: number): string;
|
|
23
|
+
/**
|
|
24
|
+
* Total parser for the tool input (the host forwards model-produced JSON, so
|
|
25
|
+
* the runtime shape is untrusted even though the standard schema describes
|
|
26
|
+
* it). Both fields are required, non-empty, and bounded.
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseEscalationRequest(input: unknown): EscalationRequest | undefined;
|
|
29
|
+
/** One-line summary recorded as escalation evidence (bounded). */
|
|
30
|
+
export declare function escalationDetail(request: EscalationRequest): string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Adaptive-owned escalation request surface (T-18, ADP-015..017). The
|
|
3
|
+
* schema requires a reason and evidence — it is deliberately the smallest
|
|
4
|
+
* typed mechanism for an agent to request stronger capability, and it is not
|
|
5
|
+
* a planning or task-management API. The request is recorded against the
|
|
6
|
+
* current work unit and applies at the next safe boundary within the finite
|
|
7
|
+
* per-unit budget; a completing unit discards it (routing re-runs fresh).
|
|
8
|
+
*/
|
|
9
|
+
/** The tool name as registered with the host. */
|
|
10
|
+
export const ESCALATION_TOOL_NAME = "adaptive_escalate";
|
|
11
|
+
/** Each field is bounded — the request never carries unbounded prose. */
|
|
12
|
+
export const MAX_ESCALATION_FIELD_LENGTH = 256;
|
|
13
|
+
/**
|
|
14
|
+
* Truncates to `max` UTF-16 code units without splitting a surrogate pair:
|
|
15
|
+
* a trailing high surrogate whose low half was cut is dropped, so the
|
|
16
|
+
* persisted evidence never carries a lone surrogate.
|
|
17
|
+
*/
|
|
18
|
+
export function truncateBounded(text, max) {
|
|
19
|
+
if (text.length <= max)
|
|
20
|
+
return text;
|
|
21
|
+
const cut = text.slice(0, max);
|
|
22
|
+
const last = cut.charCodeAt(cut.length - 1);
|
|
23
|
+
return last >= 0xd800 && last <= 0xdbff ? cut.slice(0, -1) : cut;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Total parser for the tool input (the host forwards model-produced JSON, so
|
|
27
|
+
* the runtime shape is untrusted even though the standard schema describes
|
|
28
|
+
* it). Both fields are required, non-empty, and bounded.
|
|
29
|
+
*/
|
|
30
|
+
export function parseEscalationRequest(input) {
|
|
31
|
+
if (typeof input !== "object" || input === null)
|
|
32
|
+
return undefined;
|
|
33
|
+
const record = input;
|
|
34
|
+
const reason = record["reason"];
|
|
35
|
+
const evidence = record["evidence"];
|
|
36
|
+
if (typeof reason !== "string" || reason.length === 0)
|
|
37
|
+
return undefined;
|
|
38
|
+
if (typeof evidence !== "string" || evidence.length === 0)
|
|
39
|
+
return undefined;
|
|
40
|
+
return {
|
|
41
|
+
reason: truncateBounded(reason, MAX_ESCALATION_FIELD_LENGTH),
|
|
42
|
+
evidence: truncateBounded(evidence, MAX_ESCALATION_FIELD_LENGTH),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** One-line summary recorded as escalation evidence (bounded). */
|
|
46
|
+
export function escalationDetail(request) {
|
|
47
|
+
return truncateBounded(`${request.reason}: ${request.evidence}`, MAX_ESCALATION_FIELD_LENGTH);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/execution/escalation/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,iDAAiD;AACjD,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAA;AAEvD,yEAAyE;AACzE,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAA;AAO9C;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,GAAW;IACvD,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,CAAA;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC3C,OAAO,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AAClE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAA;IACjE,MAAM,MAAM,GAAG,KAAgC,CAAA;IAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;IACnC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IACvE,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IAC3E,OAAO;QACL,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,2BAA2B,CAAC;QAC5D,QAAQ,EAAE,eAAe,CAAC,QAAQ,EAAE,2BAA2B,CAAC;KACjE,CAAA;AACH,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,gBAAgB,CAAC,OAA0B;IACzD,OAAO,eAAe,CAAC,GAAG,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,QAAQ,EAAE,EAAE,2BAA2B,CAAC,CAAA;AAC/F,CAAC","sourcesContent":["/**\n * The Adaptive-owned escalation request surface (T-18, ADP-015..017). The\n * schema requires a reason and evidence — it is deliberately the smallest\n * typed mechanism for an agent to request stronger capability, and it is not\n * a planning or task-management API. The request is recorded against the\n * current work unit and applies at the next safe boundary within the finite\n * per-unit budget; a completing unit discards it (routing re-runs fresh).\n */\n\n/** The tool name as registered with the host. */\nexport const ESCALATION_TOOL_NAME = \"adaptive_escalate\"\n\n/** Each field is bounded — the request never carries unbounded prose. */\nexport const MAX_ESCALATION_FIELD_LENGTH = 256\n\nexport interface EscalationRequest {\n readonly reason: string\n readonly evidence: string\n}\n\n/**\n * Truncates to `max` UTF-16 code units without splitting a surrogate pair:\n * a trailing high surrogate whose low half was cut is dropped, so the\n * persisted evidence never carries a lone surrogate.\n */\nexport function truncateBounded(text: string, max: number): string {\n if (text.length <= max) return text\n const cut = text.slice(0, max)\n const last = cut.charCodeAt(cut.length - 1)\n return last >= 0xd800 && last <= 0xdbff ? cut.slice(0, -1) : cut\n}\n\n/**\n * Total parser for the tool input (the host forwards model-produced JSON, so\n * the runtime shape is untrusted even though the standard schema describes\n * it). Both fields are required, non-empty, and bounded.\n */\nexport function parseEscalationRequest(input: unknown): EscalationRequest | undefined {\n if (typeof input !== \"object\" || input === null) return undefined\n const record = input as Record<string, unknown>\n const reason = record[\"reason\"]\n const evidence = record[\"evidence\"]\n if (typeof reason !== \"string\" || reason.length === 0) return undefined\n if (typeof evidence !== \"string\" || evidence.length === 0) return undefined\n return {\n reason: truncateBounded(reason, MAX_ESCALATION_FIELD_LENGTH),\n evidence: truncateBounded(evidence, MAX_ESCALATION_FIELD_LENGTH),\n }\n}\n\n/** One-line summary recorded as escalation evidence (bounded). */\nexport function escalationDetail(request: EscalationRequest): string {\n return truncateBounded(`${request.reason}: ${request.evidence}`, MAX_ESCALATION_FIELD_LENGTH)\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/execution/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA","sourcesContent":["export * from \"./retry/index.js\"\nexport * from \"./continuation/index.js\"\nexport * from \"./parking/index.js\"\nexport * from \"./escalation/index.js\"\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/execution/parking/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA","sourcesContent":["export { selectResumable } from \"./plan.js\"\nexport type { ResumeContext, ResumePlan } from \"./plan.js\"\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ParkedRecord } from "../../state/parked-work/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resume-attempt budget (ADP-011): a record whose continuation prompt kept
|
|
4
|
+
* failing is dropped once its attempts reach this count — the idle loop
|
|
5
|
+
* must be provably bounded, not "as long as idle events keep firing".
|
|
6
|
+
*/
|
|
7
|
+
export declare const MAX_PARKED_ATTEMPTS = 5;
|
|
8
|
+
/**
|
|
9
|
+
* Predicates supplied by the wiring at each safe boundary. Kept as
|
|
10
|
+
* injected predicates so this module stays host-agnostic and fully
|
|
11
|
+
* unit-testable with fakes.
|
|
12
|
+
*/
|
|
13
|
+
export interface ResumeContext {
|
|
14
|
+
/** Whether the parked record's tier still has configured resources. */
|
|
15
|
+
tierConfigured(tier: ParkedRecord["tier"]): boolean;
|
|
16
|
+
/** Whether the session the record belongs to still exists. */
|
|
17
|
+
sessionAlive(sessionID: string): boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface ResumePlan {
|
|
20
|
+
/**
|
|
21
|
+
* Records worth a fresh routing attempt now, oldest parked first (ties
|
|
22
|
+
* keep park order). The wiring re-runs routing for each; a successful
|
|
23
|
+
* route pops the record via the store and starts a clean continuation.
|
|
24
|
+
*/
|
|
25
|
+
readonly attempt: readonly ParkedRecord[];
|
|
26
|
+
/** Tier no longer configured — keep parked until the user configures it. */
|
|
27
|
+
readonly hold: readonly ParkedRecord[];
|
|
28
|
+
/**
|
|
29
|
+
* Session gone, or the record exhausted its resume-attempt budget — the
|
|
30
|
+
* record can never (or may no longer) resume; the wiring drops it.
|
|
31
|
+
*/
|
|
32
|
+
readonly drop: readonly ParkedRecord[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parked-work resume selection at a safe boundary (ADP-024). Total,
|
|
36
|
+
* deterministic, pure: partitions the parked list by resumability without
|
|
37
|
+
* consulting health (routing re-decides with fresh health per attempt).
|
|
38
|
+
*/
|
|
39
|
+
export declare function selectResumable(records: readonly ParkedRecord[], context: ResumeContext): ResumePlan;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resume-attempt budget (ADP-011): a record whose continuation prompt kept
|
|
3
|
+
* failing is dropped once its attempts reach this count — the idle loop
|
|
4
|
+
* must be provably bounded, not "as long as idle events keep firing".
|
|
5
|
+
*/
|
|
6
|
+
export const MAX_PARKED_ATTEMPTS = 5;
|
|
7
|
+
/**
|
|
8
|
+
* Parked-work resume selection at a safe boundary (ADP-024). Total,
|
|
9
|
+
* deterministic, pure: partitions the parked list by resumability without
|
|
10
|
+
* consulting health (routing re-decides with fresh health per attempt).
|
|
11
|
+
*/
|
|
12
|
+
export function selectResumable(records, context) {
|
|
13
|
+
const attempt = [];
|
|
14
|
+
const hold = [];
|
|
15
|
+
const drop = [];
|
|
16
|
+
const byAge = [...records].sort((a, b) => a.parkedAt - b.parkedAt);
|
|
17
|
+
for (const record of byAge) {
|
|
18
|
+
if (!context.sessionAlive(record.sessionID)) {
|
|
19
|
+
drop.push(record);
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if ((record.attempts ?? 0) >= MAX_PARKED_ATTEMPTS) {
|
|
23
|
+
drop.push(record);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (!context.tierConfigured(record.tier)) {
|
|
27
|
+
hold.push(record);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
attempt.push(record);
|
|
31
|
+
}
|
|
32
|
+
return { attempt, hold, drop };
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/execution/parking/plan.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAA;AA8BpC;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAgC,EAChC,OAAsB;IAEtB,MAAM,OAAO,GAAmB,EAAE,CAAA;IAClC,MAAM,IAAI,GAAmB,EAAE,CAAA;IAC/B,MAAM,IAAI,GAAmB,EAAE,CAAA;IAC/B,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAA;IAClE,KAAK,MAAM,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACjB,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,mBAAmB,EAAE,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACjB,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACjB,SAAQ;QACV,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACtB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;AAChC,CAAC","sourcesContent":["import type { ParkedRecord } from \"../../state/parked-work/types.js\"\n\n/**\n * Resume-attempt budget (ADP-011): a record whose continuation prompt kept\n * failing is dropped once its attempts reach this count — the idle loop\n * must be provably bounded, not \"as long as idle events keep firing\".\n */\nexport const MAX_PARKED_ATTEMPTS = 5\n\n/**\n * Predicates supplied by the wiring at each safe boundary. Kept as\n * injected predicates so this module stays host-agnostic and fully\n * unit-testable with fakes.\n */\nexport interface ResumeContext {\n /** Whether the parked record's tier still has configured resources. */\n tierConfigured(tier: ParkedRecord[\"tier\"]): boolean\n /** Whether the session the record belongs to still exists. */\n sessionAlive(sessionID: string): boolean\n}\n\nexport interface ResumePlan {\n /**\n * Records worth a fresh routing attempt now, oldest parked first (ties\n * keep park order). The wiring re-runs routing for each; a successful\n * route pops the record via the store and starts a clean continuation.\n */\n readonly attempt: readonly ParkedRecord[]\n /** Tier no longer configured — keep parked until the user configures it. */\n readonly hold: readonly ParkedRecord[]\n /**\n * Session gone, or the record exhausted its resume-attempt budget — the\n * record can never (or may no longer) resume; the wiring drops it.\n */\n readonly drop: readonly ParkedRecord[]\n}\n\n/**\n * Parked-work resume selection at a safe boundary (ADP-024). Total,\n * deterministic, pure: partitions the parked list by resumability without\n * consulting health (routing re-decides with fresh health per attempt).\n */\nexport function selectResumable(\n records: readonly ParkedRecord[],\n context: ResumeContext,\n): ResumePlan {\n const attempt: ParkedRecord[] = []\n const hold: ParkedRecord[] = []\n const drop: ParkedRecord[] = []\n const byAge = [...records].sort((a, b) => a.parkedAt - b.parkedAt)\n for (const record of byAge) {\n if (!context.sessionAlive(record.sessionID)) {\n drop.push(record)\n continue\n }\n if ((record.attempts ?? 0) >= MAX_PARKED_ATTEMPTS) {\n drop.push(record)\n continue\n }\n if (!context.tierConfigured(record.tier)) {\n hold.push(record)\n continue\n }\n attempt.push(record)\n }\n return { attempt, hold, drop }\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { OperatingMode } from "../../core/scheduler/types.js";
|
|
2
|
+
import type { RetryCoreDecision, RetryInput, RetryDecision } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Retry-hook policy (ADP-013/014). Total, deterministic, side-effect free.
|
|
5
|
+
*
|
|
6
|
+
* Veto (take ownership of horizontal recovery) only when ALL hold:
|
|
7
|
+
* - the classification is failover-eligible (infrastructure failure —
|
|
8
|
+
* capability problems and host decisions never veto);
|
|
9
|
+
* - the evidence is definitive — ambiguous evidence (Retry-After headers
|
|
10
|
+
* alone, bounded-textual matches) conservatively leaves OpenCode's native
|
|
11
|
+
* retry, which the host schedules with its parsed `retryAfterMs` (ADP-012);
|
|
12
|
+
* - a same-tier recovery candidate exists AND differs from the resource that
|
|
13
|
+
* just failed — without one, the native retry of the same resource IS the
|
|
14
|
+
* preferred horizontal recovery (vetoing onto the failed resource would
|
|
15
|
+
* discard the host's backoff and re-prompt it immediately). A breaker-probe
|
|
16
|
+
* recovery is exempt: its target IS the failed resource by design, and the
|
|
17
|
+
* veto is what starts the probe episode;
|
|
18
|
+
* - the host still wants to retry (`retry: true`) — an already-vetoed or
|
|
19
|
+
* exhausted lifecycle is never resurrected; recovery defers to the next
|
|
20
|
+
* safe boundary (ADP-014, ADP-023);
|
|
21
|
+
* - the per-unit veto budget has room left.
|
|
22
|
+
*/
|
|
23
|
+
export declare function decideRetry(input: RetryInput): RetryCoreDecision;
|
|
24
|
+
/**
|
|
25
|
+
* Mode wrapper — the same core decision for Observe and Control; Observe
|
|
26
|
+
* wraps it for receipt recording without intervening; OFF never touches
|
|
27
|
+
* execution (the hook is not even registered, this keeps the union closed).
|
|
28
|
+
*/
|
|
29
|
+
export declare function forMode(decision: RetryCoreDecision, mode: OperatingMode): RetryDecision;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { MAX_VETOES_PER_UNIT } from "./types.js";
|
|
2
|
+
import { sameModelRef } from "../../core/work-unit/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Retry-hook policy (ADP-013/014). Total, deterministic, side-effect free.
|
|
5
|
+
*
|
|
6
|
+
* Veto (take ownership of horizontal recovery) only when ALL hold:
|
|
7
|
+
* - the classification is failover-eligible (infrastructure failure —
|
|
8
|
+
* capability problems and host decisions never veto);
|
|
9
|
+
* - the evidence is definitive — ambiguous evidence (Retry-After headers
|
|
10
|
+
* alone, bounded-textual matches) conservatively leaves OpenCode's native
|
|
11
|
+
* retry, which the host schedules with its parsed `retryAfterMs` (ADP-012);
|
|
12
|
+
* - a same-tier recovery candidate exists AND differs from the resource that
|
|
13
|
+
* just failed — without one, the native retry of the same resource IS the
|
|
14
|
+
* preferred horizontal recovery (vetoing onto the failed resource would
|
|
15
|
+
* discard the host's backoff and re-prompt it immediately). A breaker-probe
|
|
16
|
+
* recovery is exempt: its target IS the failed resource by design, and the
|
|
17
|
+
* veto is what starts the probe episode;
|
|
18
|
+
* - the host still wants to retry (`retry: true`) — an already-vetoed or
|
|
19
|
+
* exhausted lifecycle is never resurrected; recovery defers to the next
|
|
20
|
+
* safe boundary (ADP-014, ADP-023);
|
|
21
|
+
* - the per-unit veto budget has room left.
|
|
22
|
+
*/
|
|
23
|
+
export function decideRetry(input) {
|
|
24
|
+
if (!input.classification.failoverEligible) {
|
|
25
|
+
return { kind: "leave" };
|
|
26
|
+
}
|
|
27
|
+
if (!input.classification.definitive) {
|
|
28
|
+
return { kind: "leave" };
|
|
29
|
+
}
|
|
30
|
+
const recovery = input.recovery;
|
|
31
|
+
if (recovery.kind === "none") {
|
|
32
|
+
return { kind: "leave" };
|
|
33
|
+
}
|
|
34
|
+
// A probe recovery targets the very resource that just failed (the
|
|
35
|
+
// half-open probe re-admits it); the veto is what starts the probe episode,
|
|
36
|
+
// so the same-resource exemption below must not swallow it.
|
|
37
|
+
// The host reports base-model calls with variant "default" (verified on
|
|
38
|
+
// 2.2.5, same fact refKey normalizes in the supervisor), so the sameness
|
|
39
|
+
// check must not treat that spelling as a different resource.
|
|
40
|
+
const sameResource = recovery.probeId === undefined &&
|
|
41
|
+
sameModelRef({
|
|
42
|
+
...recovery.model,
|
|
43
|
+
variant: recovery.model.variant === "default" ? undefined : recovery.model.variant,
|
|
44
|
+
}, {
|
|
45
|
+
...input.failingModel,
|
|
46
|
+
variant: input.failingModel.variant === "default" ? undefined : input.failingModel.variant,
|
|
47
|
+
});
|
|
48
|
+
if (sameResource) {
|
|
49
|
+
return { kind: "leave" };
|
|
50
|
+
}
|
|
51
|
+
const native = input.native;
|
|
52
|
+
if (!native.retry) {
|
|
53
|
+
return { kind: "leave" };
|
|
54
|
+
}
|
|
55
|
+
if (input.vetoesUsed >= MAX_VETOES_PER_UNIT) {
|
|
56
|
+
return { kind: "leave" };
|
|
57
|
+
}
|
|
58
|
+
return { kind: "veto", model: recovery.model };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Mode wrapper — the same core decision for Observe and Control; Observe
|
|
62
|
+
* wraps it for receipt recording without intervening; OFF never touches
|
|
63
|
+
* execution (the hook is not even registered, this keeps the union closed).
|
|
64
|
+
*/
|
|
65
|
+
export function forMode(decision, mode) {
|
|
66
|
+
switch (mode) {
|
|
67
|
+
case "active":
|
|
68
|
+
return decision;
|
|
69
|
+
case "observe":
|
|
70
|
+
return { kind: "observe-only", would: decision };
|
|
71
|
+
case "off":
|
|
72
|
+
return { kind: "leave" };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=decide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decide.js","sourceRoot":"","sources":["../../../src/execution/retry/decide.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAU5D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,gBAAgB,EAAE,CAAC;QAC3C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IAC1B,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IAC1B,CAAC;IACD,MAAM,QAAQ,GAAmB,KAAK,CAAC,QAAQ,CAAA;IAC/C,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IAC1B,CAAC;IACD,mEAAmE;IACnE,4EAA4E;IAC5E,4DAA4D;IAC5D,wEAAwE;IACxE,yEAAyE;IACzE,8DAA8D;IAC9D,MAAM,YAAY,GAChB,QAAQ,CAAC,OAAO,KAAK,SAAS;QAC9B,YAAY,CACV;YACE,GAAG,QAAQ,CAAC,KAAK;YACjB,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO;SACnF,EACD;YACE,GAAG,KAAK,CAAC,YAAY;YACrB,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO;SAC3F,CACF,CAAA;IACH,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IAC1B,CAAC;IACD,MAAM,MAAM,GAAwB,KAAK,CAAC,MAAM,CAAA;IAChD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IAC1B,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,IAAI,mBAAmB,EAAE,CAAC;QAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IAC1B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAA;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,QAA2B,EAAE,IAAmB;IACtE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB,KAAK,SAAS;YACZ,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;QAClD,KAAK,KAAK;YACR,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IAC5B,CAAC;AACH,CAAC","sourcesContent":["import { MAX_VETOES_PER_UNIT } from \"./types.js\"\nimport { sameModelRef } from \"../../core/work-unit/types.js\"\nimport type { OperatingMode } from \"../../core/scheduler/types.js\"\nimport type {\n NativeRetryDecision,\n RecoveryOption,\n RetryCoreDecision,\n RetryInput,\n RetryDecision,\n} from \"./types.js\"\n\n/**\n * Retry-hook policy (ADP-013/014). Total, deterministic, side-effect free.\n *\n * Veto (take ownership of horizontal recovery) only when ALL hold:\n * - the classification is failover-eligible (infrastructure failure —\n * capability problems and host decisions never veto);\n * - the evidence is definitive — ambiguous evidence (Retry-After headers\n * alone, bounded-textual matches) conservatively leaves OpenCode's native\n * retry, which the host schedules with its parsed `retryAfterMs` (ADP-012);\n * - a same-tier recovery candidate exists AND differs from the resource that\n * just failed — without one, the native retry of the same resource IS the\n * preferred horizontal recovery (vetoing onto the failed resource would\n * discard the host's backoff and re-prompt it immediately). A breaker-probe\n * recovery is exempt: its target IS the failed resource by design, and the\n * veto is what starts the probe episode;\n * - the host still wants to retry (`retry: true`) — an already-vetoed or\n * exhausted lifecycle is never resurrected; recovery defers to the next\n * safe boundary (ADP-014, ADP-023);\n * - the per-unit veto budget has room left.\n */\nexport function decideRetry(input: RetryInput): RetryCoreDecision {\n if (!input.classification.failoverEligible) {\n return { kind: \"leave\" }\n }\n if (!input.classification.definitive) {\n return { kind: \"leave\" }\n }\n const recovery: RecoveryOption = input.recovery\n if (recovery.kind === \"none\") {\n return { kind: \"leave\" }\n }\n // A probe recovery targets the very resource that just failed (the\n // half-open probe re-admits it); the veto is what starts the probe episode,\n // so the same-resource exemption below must not swallow it.\n // The host reports base-model calls with variant \"default\" (verified on\n // 2.2.5, same fact refKey normalizes in the supervisor), so the sameness\n // check must not treat that spelling as a different resource.\n const sameResource =\n recovery.probeId === undefined &&\n sameModelRef(\n {\n ...recovery.model,\n variant: recovery.model.variant === \"default\" ? undefined : recovery.model.variant,\n },\n {\n ...input.failingModel,\n variant: input.failingModel.variant === \"default\" ? undefined : input.failingModel.variant,\n },\n )\n if (sameResource) {\n return { kind: \"leave\" }\n }\n const native: NativeRetryDecision = input.native\n if (!native.retry) {\n return { kind: \"leave\" }\n }\n if (input.vetoesUsed >= MAX_VETOES_PER_UNIT) {\n return { kind: \"leave\" }\n }\n return { kind: \"veto\", model: recovery.model }\n}\n\n/**\n * Mode wrapper — the same core decision for Observe and Control; Observe\n * wraps it for receipt recording without intervening; OFF never touches\n * execution (the hook is not even registered, this keeps the union closed).\n */\nexport function forMode(decision: RetryCoreDecision, mode: OperatingMode): RetryDecision {\n switch (mode) {\n case \"active\":\n return decision\n case \"observe\":\n return { kind: \"observe-only\", would: decision }\n case \"off\":\n return { kind: \"leave\" }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/execution/retry/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA","sourcesContent":["export * from \"./types.js\"\nexport * from \"./decide.js\"\n"]}
|