@caupulican/pi-adaptative 0.90.6 → 0.90.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/dist/bundled-resources/skills/tool-call-repair/SKILL.md +5 -4
- package/dist/bundled-resources/skills/tool-call-repair/references/failure-grammar.md +6 -3
- package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +1 -0
- package/dist/core/agent-session-contracts.d.ts +4 -0
- package/dist/core/agent-session-contracts.d.ts.map +1 -1
- package/dist/core/agent-session-contracts.js.map +1 -1
- package/dist/core/agent-session.d.ts +13 -17
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +112 -205
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts +7 -1
- package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
- package/dist/core/autonomy/bounded-completion.js +8 -2
- package/dist/core/autonomy/bounded-completion.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts +1 -1
- package/dist/core/autonomy/contracts.d.ts.map +1 -1
- package/dist/core/autonomy/contracts.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +14 -0
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +32 -0
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/billing-failover-controller.js +1 -1
- package/dist/core/billing-failover-controller.js.map +1 -1
- package/dist/core/context/current-work-memory.d.ts +1 -1
- package/dist/core/context/current-work-memory.d.ts.map +1 -1
- package/dist/core/context/current-work-memory.js +2 -1
- package/dist/core/context/current-work-memory.js.map +1 -1
- package/dist/core/context/long-term-memory-trigger.d.ts +1 -1
- package/dist/core/context/long-term-memory-trigger.d.ts.map +1 -1
- package/dist/core/context/long-term-memory-trigger.js +2 -1
- package/dist/core/context/long-term-memory-trigger.js.map +1 -1
- package/dist/core/delegation/managed-lane-controller.js +2 -2
- package/dist/core/delegation/managed-lane-controller.js.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts +13 -0
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js +71 -8
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.js +13 -8
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
- package/dist/core/delegation/worker-claim.d.ts.map +1 -1
- package/dist/core/delegation/worker-claim.js +14 -1
- package/dist/core/delegation/worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts +6 -9
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +95 -42
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-fleet-limits.d.ts.map +1 -1
- package/dist/core/delegation/worker-fleet-limits.js +5 -1
- package/dist/core/delegation/worker-fleet-limits.js.map +1 -1
- package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -1
- package/dist/core/delegation/worker-lane-projection.js +7 -4
- package/dist/core/delegation/worker-lane-projection.js.map +1 -1
- package/dist/core/delegation/worker-lifecycle.d.ts +8 -0
- package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
- package/dist/core/delegation/worker-lifecycle.js.map +1 -1
- package/dist/core/delegation/worker-notification-coordinator.d.ts +23 -0
- package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-notification-coordinator.js +69 -17
- package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +7 -0
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +24 -7
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-system-prompt.d.ts +54 -0
- package/dist/core/delegation/worker-system-prompt.d.ts.map +1 -0
- package/dist/core/delegation/worker-system-prompt.js +85 -0
- package/dist/core/delegation/worker-system-prompt.js.map +1 -0
- package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-tree-budget-coordinator.js +4 -0
- package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +4 -0
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-write-reservation-coordinator.js +28 -1
- package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -1
- package/dist/core/durable-custom-message-turn-controller.d.ts +24 -0
- package/dist/core/durable-custom-message-turn-controller.d.ts.map +1 -0
- package/dist/core/durable-custom-message-turn-controller.js +71 -0
- package/dist/core/durable-custom-message-turn-controller.js.map +1 -0
- package/dist/core/extension-binding-controller.d.ts +107 -0
- package/dist/core/extension-binding-controller.d.ts.map +1 -0
- package/dist/core/extension-binding-controller.js +224 -0
- package/dist/core/extension-binding-controller.js.map +1 -0
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.d.ts +22 -7
- package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.js +76 -12
- package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
- package/dist/core/goal-loop-controller.d.ts +5 -9
- package/dist/core/goal-loop-controller.d.ts.map +1 -1
- package/dist/core/goal-loop-controller.js +19 -7
- package/dist/core/goal-loop-controller.js.map +1 -1
- package/dist/core/goals/compact-goal-context.d.ts +1 -1
- package/dist/core/goals/compact-goal-context.d.ts.map +1 -1
- package/dist/core/goals/compact-goal-context.js +2 -1
- package/dist/core/goals/compact-goal-context.js.map +1 -1
- package/dist/core/goals/goal-execution-errors.d.ts +18 -0
- package/dist/core/goals/goal-execution-errors.d.ts.map +1 -0
- package/dist/core/goals/goal-execution-errors.js +21 -0
- package/dist/core/goals/goal-execution-errors.js.map +1 -0
- package/dist/core/goals/goal-lifecycle.d.ts.map +1 -1
- package/dist/core/goals/goal-lifecycle.js +3 -3
- package/dist/core/goals/goal-lifecycle.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts +41 -1
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-session-controller.js +217 -20
- package/dist/core/goals/goal-session-controller.js.map +1 -1
- package/dist/core/goals/goal-state.d.ts +6 -7
- package/dist/core/goals/goal-state.d.ts.map +1 -1
- package/dist/core/goals/goal-state.js +1 -1
- package/dist/core/goals/goal-state.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +2 -2
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/goals/natural-language-goal.d.ts +24 -0
- package/dist/core/goals/natural-language-goal.d.ts.map +1 -1
- package/dist/core/goals/natural-language-goal.js +121 -3
- package/dist/core/goals/natural-language-goal.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +10 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +3 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/orchestration/capability-gateway.d.ts +1 -1
- package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
- package/dist/core/orchestration/capability-gateway.js +4 -4
- package/dist/core/orchestration/capability-gateway.js.map +1 -1
- package/dist/core/orchestration/event-store.d.ts +8 -0
- package/dist/core/orchestration/event-store.d.ts.map +1 -1
- package/dist/core/orchestration/event-store.js +9 -7
- package/dist/core/orchestration/event-store.js.map +1 -1
- package/dist/core/orchestration/task-runtime-reducer.js +1 -1
- package/dist/core/orchestration/task-runtime-reducer.js.map +1 -1
- package/dist/core/orchestration/worker-model-pins.d.ts +7 -0
- package/dist/core/orchestration/worker-model-pins.d.ts.map +1 -1
- package/dist/core/orchestration/worker-model-pins.js +17 -1
- package/dist/core/orchestration/worker-model-pins.js.map +1 -1
- package/dist/core/provider-request-runtime-controller.d.ts +10 -0
- package/dist/core/provider-request-runtime-controller.d.ts.map +1 -1
- package/dist/core/provider-request-runtime-controller.js +24 -2
- package/dist/core/provider-request-runtime-controller.js.map +1 -1
- package/dist/core/provider-tool-text.d.ts +15 -1
- package/dist/core/provider-tool-text.d.ts.map +1 -1
- package/dist/core/provider-tool-text.js +42 -10
- package/dist/core/provider-tool-text.js.map +1 -1
- package/dist/core/research/research-lane-controller.d.ts +1 -1
- package/dist/core/research/research-lane-controller.d.ts.map +1 -1
- package/dist/core/research/research-lane-controller.js +2 -1
- package/dist/core/research/research-lane-controller.js.map +1 -1
- package/dist/core/resource-loader.d.ts +3 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +8 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +11 -0
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +9 -0
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/session-supervision-runtime.d.ts.map +1 -1
- package/dist/core/session-supervision-runtime.js +2 -1
- package/dist/core/session-supervision-runtime.js.map +1 -1
- package/dist/core/settings-manager.d.ts +2 -2
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +7 -2
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tool-recovery-logger.d.ts +2 -0
- package/dist/core/tool-recovery-logger.d.ts.map +1 -1
- package/dist/core/tool-recovery-logger.js +11 -0
- package/dist/core/tool-recovery-logger.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +13 -0
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +20 -18
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/goal.d.ts +2 -0
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +9 -0
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/util/atomic-file.d.ts +7 -0
- package/dist/core/util/atomic-file.d.ts.map +1 -1
- package/dist/core/util/atomic-file.js +8 -6
- package/dist/core/util/atomic-file.js.map +1 -1
- package/dist/core/util/faultable-fs.d.ts +30 -0
- package/dist/core/util/faultable-fs.d.ts.map +1 -0
- package/dist/core/util/faultable-fs.js +30 -0
- package/dist/core/util/faultable-fs.js.map +1 -0
- package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.js +1 -0
- package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
- package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
- package/dist/modes/interactive/components/activity-lane.js +4 -3
- package/dist/modes/interactive/components/activity-lane.js.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +2 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +3 -2
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/report-commands.js +1 -1
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.d.ts +1 -1
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +3 -2
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/docs/providers.md +3 -0
- package/docs/settings.md +4 -2
- package/docs/tool-repair.md +1 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +9 -4
|
@@ -123,6 +123,8 @@ export interface GoalToolDependencies {
|
|
|
123
123
|
* task state itself; this is the only place that supplies it.
|
|
124
124
|
*/
|
|
125
125
|
getOpenTaskSteps?: () => readonly OpenTaskStepRef[];
|
|
126
|
+
/** Model-facing start authority for the current foreground turn. Omitted by direct owner/test callers. */
|
|
127
|
+
authorizeStart?: (input: Pick<GoalToolInput, "userGoal" | "tokenBudget">) => string | undefined;
|
|
126
128
|
}
|
|
127
129
|
export declare function createGoalToolDefinition(deps: GoalToolDependencies): ToolDefinition;
|
|
128
130
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal.d.ts","sourceRoot":"","sources":["../../../src/core/tools/goal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,KAAK,iBAAiB,EAAwB,MAAM,4BAA4B,CAAC;AAC1F,OAAO,KAAK,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAGN,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,MAAM,4BAA4B,CAAC;AAQpC,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;EAsEf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,cAAc,GAAG,KAAK,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;iHAE6G;IAC7G,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;uGAImG;IACnG,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACpC,mEAAmE;IACnE,YAAY,EAAE,MAAM,SAAS,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACxE,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,SAAS,UAAU,EAAE,CAAC;IAC7C;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAE,MAAM,SAAS,WAAW,EAAE,CAAC;IACvD;;;;;;;;;OASG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC9B,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACrB,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC3D;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACrB,KAAK,OAAO,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,mGAAmG;IACnG,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;OAGG;IACH,oCAAoC,CAAC,EAAE,MAAM,OAAO,CAAC;IACrD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,SAAS,eAAe,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"goal.d.ts","sourceRoot":"","sources":["../../../src/core/tools/goal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,KAAK,iBAAiB,EAAwB,MAAM,4BAA4B,CAAC;AAC1F,OAAO,KAAK,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAGN,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,MAAM,4BAA4B,CAAC;AAQpC,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;EAsEf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,cAAc,GAAG,KAAK,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;iHAE6G;IAC7G,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;uGAImG;IACnG,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACpC,mEAAmE;IACnE,YAAY,EAAE,MAAM,SAAS,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACxE,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,SAAS,UAAU,EAAE,CAAC;IAC7C;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAE,MAAM,SAAS,WAAW,EAAE,CAAC;IACvD;;;;;;;;;OASG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC9B,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACrB,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC3D;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACrB,KAAK,OAAO,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,mGAAmG;IACnG,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;OAGG;IACH,oCAAoC,CAAC,EAAE,MAAM,OAAO,CAAC;IACrD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,SAAS,eAAe,EAAE,CAAC;IACpD,0GAA0G;IAC1G,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,aAAa,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;CAChG;AAqKD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,oBAAoB,GAAG,cAAc,CA+LnF"}
|
package/dist/core/tools/goal.js
CHANGED
|
@@ -249,6 +249,15 @@ export function createGoalToolDefinition(deps) {
|
|
|
249
249
|
details: { action: "get", applied: false, state },
|
|
250
250
|
};
|
|
251
251
|
}
|
|
252
|
+
if (input.action === "start" && deps.authorizeStart) {
|
|
253
|
+
const error = deps.authorizeStart(input);
|
|
254
|
+
if (error) {
|
|
255
|
+
return {
|
|
256
|
+
content: [{ type: "text", text: `goal start failed: ${error}` }],
|
|
257
|
+
details: { action: "start", applied: false, error },
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
}
|
|
252
261
|
const mapped = toGoalAction(input);
|
|
253
262
|
if ("error" in mapped) {
|
|
254
263
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal.js","sourceRoot":"","sources":["../../../src/core/tools/goal.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat as fsStat } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport type { WorkerClaim } from \"../autonomy/contracts.ts\";\nimport type { LaneRecord } from \"../autonomy/lane-tracker.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { type GoalStateRevision, getGoalStateRevision } from \"../goals/goal-lifecycle.ts\";\nimport type { GoalEvidenceKind, GoalState } from \"../goals/goal-state.ts\";\nimport {\n\tapplyGoalAction,\n\ttype GoalAction,\n\ttype GoalActionName,\n\ttype OpenTaskStepRef,\n\tsummarizeGoalState,\n} from \"../goals/goal-tool-core.ts\";\nimport {\n\temptyOrchestrationCall,\n\ttype OrchestrationPanelModel,\n\trenderOrchestrationToolResult,\n} from \"./orchestration-panel.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\n\nconst goalSchema = Type.Object(\n\t{\n\t\taction: Type.Union(\n\t\t\t[\n\t\t\t\tType.Literal(\"get\"),\n\t\t\t\tType.Literal(\"start\"),\n\t\t\t\tType.Literal(\"add_requirement\"),\n\t\t\t\tType.Literal(\"satisfy_requirement\"),\n\t\t\t\tType.Literal(\"block_requirement\"),\n\t\t\t\tType.Literal(\"reopen_requirement\"),\n\t\t\t\tType.Literal(\"dispatch_worker\"),\n\t\t\t\tType.Literal(\"add_evidence\"),\n\t\t\t\tType.Literal(\"progress\"),\n\t\t\t\tType.Literal(\"no_progress\"),\n\t\t\t\tType.Literal(\"complete\"),\n\t\t\t\tType.Literal(\"block_goal\"),\n\t\t\t],\n\t\t\t{ description: \"Goal record action.\" },\n\t\t),\n\t\tgoalId: Type.Optional(Type.String({ description: \"Stable goal id. Required for action 'start'.\" })),\n\t\tuserGoal: Type.Optional(Type.String({ description: \"The goal statement. Required for action 'start'.\" })),\n\t\ttokenBudget: Type.Optional(\n\t\t\tType.Integer({ minimum: 1, description: \"Optional positive token budget for action 'start'.\" }),\n\t\t),\n\t\trequirementId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription: \"Requirement id for requirement actions.\",\n\t\t\t}),\n\t\t),\n\t\ttext: Type.Optional(Type.String({ description: \"Requirement text. Required for add_requirement.\" })),\n\t\tdependencies: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Optional IDs of requirements that must be satisfied before this one. Valid for add_requirement.\",\n\t\t\t}),\n\t\t),\n\t\tinstructions: Type.Optional(Type.String({ description: \"Worker instructions. Required for dispatch_worker.\" })),\n\t\tevidenceId: Type.Optional(Type.String({ description: \"Evidence id. Required for add_evidence.\" })),\n\t\tevidenceIds: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription: \"Existing evidence ids for satisfy_requirement.\",\n\t\t\t}),\n\t\t),\n\t\tkind: Type.Optional(\n\t\t\tType.Union(\n\t\t\t\t[\n\t\t\t\t\tType.Literal(\"file\"),\n\t\t\t\t\tType.Literal(\"test\"),\n\t\t\t\t\tType.Literal(\"tool\"),\n\t\t\t\t\tType.Literal(\"user\"),\n\t\t\t\t\tType.Literal(\"finding\"),\n\t\t\t\t\tType.Literal(\"worker\"),\n\t\t\t\t],\n\t\t\t\t{ description: \"Evidence kind. Required for add_evidence.\" },\n\t\t\t),\n\t\t),\n\t\tsummary: Type.Optional(Type.String({ description: \"Evidence summary. Required for add_evidence.\" })),\n\t\turi: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription: \"Optional file/URL, toolCallId, or laneId evidence locator.\",\n\t\t\t}),\n\t\t),\n\t\treason: Type.Optional(Type.String({ description: \"Reason for block_requirement or block_goal.\" })),\n\t\tdispatchTarget: Type.Optional(\n\t\t\tType.Union([Type.Literal(\"in_process\"), Type.Literal(\"tmux\")], {\n\t\t\t\tdescription: \"Legacy target. Native is default; use tmux only for an owner-requested persistent pane.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type GoalToolInput = Static<typeof goalSchema>;\n\nexport interface GoalToolDetails {\n\taction: GoalActionName | \"get\";\n\tapplied: boolean;\n\terror?: string;\n\tstate?: GoalState;\n\t/** Set on 'dispatch_worker' when a worker lane actually started; mirrors the requirement's\n\t * new `boundLaneId`. The in-process route by default, or a real persistent tmux lane when\n\t * `dispatchTarget:\"tmux\"` was selected and routed -- see {@link GoalToolDependencies.dispatchTmuxWorker}. */\n\tdispatchedLaneId?: string;\n\t/** Set on 'dispatch_worker' when no worker was dispatched: a wired dependency declined (e.g. worker\n\t * delegation disabled, already at capacity, or an honest tmux skip reason -- see\n\t * {@link GoalToolDependencies.dispatchTmuxWorker}), or the indeterminate-binding guard refused a\n\t * re-dispatch against an already-bound requirement (`requirement_already_bound`/`bound_lane_indeterminate`).\n\t * The binding is recorded (or, for a guard refusal, left exactly as it was) with no NEW laneId. */\n\tdispatchSkipReason?: string;\n}\n\nexport interface GoalToolDependencies {\n\t/** Read the latest persisted goal state for the active session. */\n\tgetGoalState: () => GoalState | undefined;\n\t/** Persist a new goal state snapshot to the active session. */\n\tsaveGoalState: (state: GoalState, expected?: GoalStateRevision) => void;\n\t/** Clock injection for deterministic tests. */\n\tnow?: () => string;\n\t/**\n\t * Check whether `toolCallId` exists in this session's records, for validating kind:\"tool\"\n\t * evidence refs at add_evidence time. When not wired, a \"tool\" ref cannot be proven and is\n\t * recorded as `verified: false` rather than assumed true.\n\t */\n\thasToolCallId?: (toolCallId: string) => boolean;\n\t/**\n\t * Read the session's live worker lane records, for validating kind:\"worker\" evidence refs\n\t * (the `uri` is a laneId) at add_evidence time. Read-defensive: when not wired -- exactly like\n\t * `hasToolCallId` -- a \"worker\" ref cannot be proven and is recorded as `verified: false` rather\n\t * than assumed true. Live wiring is added separately.\n\t */\n\tgetLaneRecords?: () => readonly LaneRecord[];\n\t/**\n\t * Read persisted worker claim snapshots (keyed by `WorkerClaim.requestId`, which is the same\n\t * id as the dispatching lane's laneId), for validating kind:\"worker\" evidence refs. See\n\t * {@link getLaneRecords}. A matching claim that is `parentReviewRequired && !parentReviewedAt`\n\t * verifies `false` -- an unreviewed worker completion must never ungate goal completion through\n\t * the existing verified/complete gate.\n\t */\n\tgetWorkerClaimSnapshots?: () => readonly WorkerClaim[];\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `dispatchTarget` is 'in_process'\n\t * (the default) or when {@link dispatchTmuxWorker} is not wired: dispatches a real in-process\n\t * worker lane for the given requirement and returns the resulting laneId to bind onto it. When\n\t * the dependency is present but the underlying delegation starter declines (disabled, already at\n\t * capacity, etc.), return `{ skipReason }` instead of a laneId -- a real, non-silent skip that\n\t * the tool response surfaces, distinct from this dependency being altogether unwired (`undefined`\n\t * dep, or the dep returning `undefined`), which records the binding attempt structurally with no\n\t * laneId (a no-op).\n\t */\n\tstartWorkerDelegation?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => { laneId?: string; skipReason?: string } | undefined;\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `input.dispatchTarget === \"tmux\"`:\n\t * dispatches a REAL persistent tmux worker via the tmux_agent_manager extension's `fire_task`\n\t * action (core structurally invokes the same tool call the model would make; no extension change,\n\t * no faked launch or laneId -- see `tmux-dispatch.ts`'s `dispatchTmuxWorker`). Selected ONLY when\n\t * BOTH `input.dispatchTarget === \"tmux\"` AND this dependency is present; otherwise the EXISTING\n\t * {@link startWorkerDelegation} in-process path runs, byte-identical to before this field existed.\n\t * The honest skip-reason vocabulary this can return: `tmux_extension_not_loaded`,\n\t * `no_standing_grant` (the owner has not authorized unattended tmux dispatch),\n\t * `tmux_dispatch_failed`, `tmux_dispatch_incomplete`, `lane_correlation_failed`,\n\t * `worktree_create_failed` (worktree-sync is enabled but the lane-first `create_lane` call was\n\t * refused -- e.g. max lanes reached -- so no fire_task call was ever attempted),\n\t * `worker_capability_insufficient` (the model is sub-full class, has an unknown context window,\n\t * does not advertise a native tool-call path, or is graded-demoted to text-protocol/none -- see\n\t * `model-capability.ts`'s `evaluateLaneWorkerRefusal`; this is the parent's best-effort check\n\t * only, refused before any lane/pane side effect -- the dispatched child still refuses\n\t * authoritatively at its own startup regardless).\n\t */\n\tdispatchTmuxWorker?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => Promise<{ laneId?: string; skipReason?: string }>;\n\t/** Working directory for resolving kind:\"file\" evidence ref paths. Defaults to `process.cwd()`. */\n\tcwd?: () => string;\n\t/**\n\t * Gate agent-facing 'complete' on verified/user evidence backing. Defaults to `true` (on)\n\t * when omitted -- the conservative default; set to a function returning `false` to opt out.\n\t */\n\trequireVerifiedEvidenceForCompletion?: () => boolean;\n\t/**\n\t * Read-only open (non-terminal) task_steps steps on the active branch, for the goal⇄task\n\t * cross-visibility nudge in the tool response. When omitted, `summarizeGoalState` gets\n\t * no task-step context and simply emits no nudge -- goal-tool-core stays pure and never reads\n\t * task state itself; this is the only place that supplies it.\n\t */\n\tgetOpenTaskSteps?: () => readonly OpenTaskStepRef[];\n}\n\nfunction allowsNativeTmuxFallback(reason: string | undefined): boolean {\n\treturn reason === \"tmux_unavailable\" || reason === \"tmux_extension_not_loaded\";\n}\n\n/**\n * Validate an evidence ref's `uri` against session records (\"tool\") or the filesystem (\"file\").\n * Returns `undefined` for kinds/refs that carry nothing checkable (e.g. \"user\"/\"finding\"/\"test\",\n * or a missing `uri`) -- absence of a ref is not the same as a ref that failed to verify.\n */\nasync function resolveEvidenceVerified(\n\tkind: GoalEvidenceKind,\n\turi: string | undefined,\n\tdeps: GoalToolDependencies,\n): Promise<boolean | undefined> {\n\tconst trimmedUri = uri?.trim();\n\tif (!trimmedUri) return undefined;\n\tif (kind === \"tool\") {\n\t\treturn deps.hasToolCallId ? deps.hasToolCallId(trimmedUri) : false;\n\t}\n\tif (kind === \"file\") {\n\t\tconst cwd = deps.cwd?.() ?? process.cwd();\n\t\ttry {\n\t\t\tconst stats = await fsStat(resolveToCwd(trimmedUri, cwd));\n\t\t\treturn stats.isFile();\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (kind === \"worker\") {\n\t\tif (!deps.getLaneRecords || !deps.getWorkerClaimSnapshots) return false;\n\t\tconst laneId = trimmedUri;\n\t\tconst record = deps.getLaneRecords().find((candidate) => candidate.laneId === laneId);\n\t\tif (!record) return false;\n\t\tconst claim = deps.getWorkerClaimSnapshots().find((candidate) => candidate.requestId === laneId);\n\t\tif (!claim) return false;\n\t\t// An unreviewed mutation (parentReviewRequired && no parentReviewedAt) can never verify true --\n\t\t// this is what stops an unreviewed worker completion from ungating goal completion through\n\t\t// the existing verified/complete gate (goal-tool-core's isVerifiedOrUserEvidence/complete).\n\t\tif (claim.parentReviewRequired === true && claim.parentReviewedAt === undefined) return false;\n\t\treturn claim.status === \"completed\";\n\t}\n\treturn undefined;\n}\n\nfunction toGoalAction(input: GoalToolInput): GoalAction | { error: string } {\n\tswitch (input.action) {\n\t\tcase \"start\":\n\t\t\treturn {\n\t\t\t\taction: \"start\",\n\t\t\t\tgoalId: input.goalId ?? \"\",\n\t\t\t\tuserGoal: input.userGoal ?? \"\",\n\t\t\t\ttokenBudget: input.tokenBudget,\n\t\t\t};\n\t\tcase \"add_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"add_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\ttext: input.text ?? \"\",\n\t\t\t\tdependencies: input.dependencies,\n\t\t\t};\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"satisfy_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tevidenceIds: input.evidenceIds,\n\t\t\t};\n\t\tcase \"block_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"block_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\treason: input.reason ?? \"\",\n\t\t\t};\n\t\tcase \"reopen_requirement\":\n\t\t\treturn { action: \"reopen_requirement\", requirementId: input.requirementId ?? \"\" };\n\t\tcase \"dispatch_worker\":\n\t\t\treturn {\n\t\t\t\taction: \"dispatch_worker\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tinstructions: input.instructions ?? \"\",\n\t\t\t};\n\t\tcase \"add_evidence\": {\n\t\t\tif (input.kind === undefined) {\n\t\t\t\treturn { error: \"add_evidence requires a kind.\" };\n\t\t\t}\n\t\t\tconst kind: GoalEvidenceKind = input.kind;\n\t\t\treturn {\n\t\t\t\taction: \"add_evidence\",\n\t\t\t\tevidenceId: input.evidenceId ?? \"\",\n\t\t\t\tkind,\n\t\t\t\tsummary: input.summary ?? \"\",\n\t\t\t\turi: input.uri,\n\t\t\t};\n\t\t}\n\t\tcase \"progress\":\n\t\t\treturn { action: \"progress\" };\n\t\tcase \"no_progress\":\n\t\t\treturn { action: \"no_progress\" };\n\t\tcase \"complete\":\n\t\t\treturn { action: \"complete\" };\n\t\tcase \"block_goal\":\n\t\t\treturn { action: \"block_goal\", reason: input.reason ?? \"\" };\n\t\tcase \"get\":\n\t\t\treturn { error: \"get is handled as a read-only action.\" };\n\t\tdefault:\n\t\t\treturn { error: \"Unknown goal action.\" };\n\t}\n}\n\nfunction goalPanelModel(details: GoalToolDetails | undefined): OrchestrationPanelModel {\n\tconst state = details?.state;\n\tif (!state) {\n\t\treturn {\n\t\t\tlabel: \"goal\",\n\t\t\taction: details?.action,\n\t\t\tstatus: details?.error ? \"error\" : \"idle\",\n\t\t\temptyText: details?.error ?? \"No goal state was returned.\",\n\t\t};\n\t}\n\tconst satisfied = state.requirements.filter((requirement) => requirement.status === \"satisfied\").length;\n\treturn {\n\t\tlabel: \"goal\",\n\t\taction: details.action,\n\t\tstatus:\n\t\t\tstate.status === \"completed\"\n\t\t\t\t? \"success\"\n\t\t\t\t: state.status === \"blocked\" ||\n\t\t\t\t\t\tstate.status === \"paused\" ||\n\t\t\t\t\t\tstate.status === \"usage_limited\" ||\n\t\t\t\t\t\tstate.status === \"budget_limited\"\n\t\t\t\t\t? \"warning\"\n\t\t\t\t\t: state.status === \"cancelled\"\n\t\t\t\t\t\t? \"idle\"\n\t\t\t\t\t\t: \"running\",\n\t\tsummary: [\n\t\t\t`${satisfied}/${state.requirements.length} requirements`,\n\t\t\t`${state.evidence.length} evidence`,\n\t\t\t...(state.tokenBudget !== undefined ? [`${state.tokensUsed ?? 0}/${state.tokenBudget} tokens`] : []),\n\t\t],\n\t\trows: state.requirements.map((requirement) => ({\n\t\t\tstatus:\n\t\t\t\trequirement.status === \"satisfied\"\n\t\t\t\t\t? (\"completed\" as const)\n\t\t\t\t\t: requirement.status === \"open\"\n\t\t\t\t\t\t? (\"pending\" as const)\n\t\t\t\t\t\t: (\"blocked\" as const),\n\t\t\tlabel: requirement.text,\n\t\t\tmeta: [\n\t\t\t\trequirement.id,\n\t\t\t\trequirement.evidenceIds.length > 0 ? `${requirement.evidenceIds.length} evidence` : undefined,\n\t\t\t\trequirement.boundLaneId ? `worker ${requirement.boundLaneId}` : undefined,\n\t\t\t].filter((value): value is string => value !== undefined),\n\t\t\tdetails: requirement.blockedReason ? [`blocked: ${requirement.blockedReason}`] : undefined,\n\t\t})),\n\t\tnotices: [\n\t\t\t...(details.dispatchSkipReason\n\t\t\t\t? [{ status: \"warning\" as const, text: `Worker dispatch skipped: ${details.dispatchSkipReason}` }]\n\t\t\t\t: []),\n\t\t\t...(state.blockedReason ? [{ status: \"warning\" as const, text: state.blockedReason }] : []),\n\t\t],\n\t\temptyText: \"No requirements recorded.\",\n\t};\n}\n\nexport function createGoalToolDefinition(deps: GoalToolDependencies): ToolDefinition {\n\tconst now = deps.now ?? (() => new Date().toISOString());\n\treturn {\n\t\tname: \"goal\",\n\t\tlabel: \"goal\",\n\t\tdescription:\n\t\t\t\"Read or update the durable goal for explicitly persistent work. Use task_steps for plans and delegate for workers; owner or system controls lifecycle and budget stops.\",\n\t\tpromptSnippet: \"Read or update the durable goal.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Start only for explicit persistent chat/system goal. get if uncertain; never replace unfinished goal; tokenBudget only if requested.\",\n\t\t\t\"Plans: task_steps. Workers: delegate. Legacy actions only for legacy goals.\",\n\t\t\t\"complete needs current authoritative evidence, no remaining work. block_goal needs same real impasse for 3 goal turns.\",\n\t\t],\n\t\tparameters: goalSchema,\n\t\trenderShell: \"self\",\n\t\trenderCall() {\n\t\t\treturn emptyOrchestrationCall();\n\t\t},\n\t\trenderResult(result, { expanded, isPartial }, theme) {\n\t\t\tconst details = result.details as GoalToolDetails | undefined;\n\t\t\treturn renderOrchestrationToolResult(theme, goalPanelModel(details), {\n\t\t\t\tisPartial,\n\t\t\t\tcollapse: !expanded && details?.applied === true,\n\t\t\t\texpanded: true,\n\t\t\t});\n\t\t},\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tinput: GoalToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: GoalToolDetails;\n\t\t}> {\n\t\t\tif (input.action === \"get\") {\n\t\t\t\tconst state = deps.getGoalState();\n\t\t\t\tif (!state) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No goal exists for this session.\" }],\n\t\t\t\t\t\tdetails: { action: \"get\", applied: false },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summarizeGoalState(state) }],\n\t\t\t\t\tdetails: { action: \"get\", applied: false, state },\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst mapped = toGoalAction(input);\n\t\t\tif (\"error\" in mapped) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${mapped.error}` }],\n\t\t\t\t\tdetails: { action: input.action, applied: false, error: mapped.error },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet action: GoalAction = mapped;\n\t\t\tif (action.action === \"add_evidence\") {\n\t\t\t\tconst verified = await resolveEvidenceVerified(action.kind, action.uri, deps);\n\t\t\t\taction = { ...action, verified };\n\t\t\t}\n\t\t\t// Honest dispatch reporting: distinguish \"dispatched\" (laneId), \"declined\" (skipReason --\n\t\t\t// the dependency IS wired but the underlying delegation starter refused, e.g. disabled or\n\t\t\t// already at capacity), and \"unwired\" (no dependency at all) -- never collapse a real\n\t\t\t// decline into a silent no-laneId no-op indistinguishable from the dep being absent.\n\t\t\tlet dispatchNote: string | undefined;\n\t\t\tlet dispatchSkipReason: string | undefined;\n\t\t\t// Indeterminate-binding dedupe guard: checked BEFORE any dispatch side effect, for BOTH\n\t\t\t// routes. A requirement already bound to a lane that is either still live (a plain\n\t\t\t// duplicate) or whose liveness/outcome cannot be determined at all (for example, a legacy\n\t\t\t// snapshot with no lane record or worker result) must never be\n\t\t\t// re-dispatched silently; only a CONFIRMED terminal outcome allows a legitimate retry.\n\t\t\tlet dispatchGuardRefused = false;\n\t\t\tif (action.action === \"dispatch_worker\") {\n\t\t\t\t// Captured into a `const` so the \"dispatch_worker\" narrowing survives into the closures\n\t\t\t\t// below -- TS does not narrow a `let`-bound outer variable across a callback boundary.\n\t\t\t\tconst dispatchAction = action;\n\t\t\t\tconst boundRequirement = deps\n\t\t\t\t\t.getGoalState()\n\t\t\t\t\t?.requirements.find((r) => r.id === dispatchAction.requirementId);\n\t\t\t\tconst bound = boundRequirement?.boundLaneId;\n\t\t\t\tif (bound !== undefined) {\n\t\t\t\t\tconst boundLaneRecord = deps.getLaneRecords?.().find((record) => record.laneId === bound);\n\t\t\t\t\tconst isLiveInFlight =\n\t\t\t\t\t\tboundLaneRecord !== undefined &&\n\t\t\t\t\t\t(boundLaneRecord.status === \"queued\" || boundLaneRecord.status === \"running\");\n\t\t\t\t\tif (isLiveInFlight) {\n\t\t\t\t\t\tdispatchSkipReason = \"requirement_already_bound\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// `boundLaneRecord` present here is necessarily terminal (isLiveInFlight was false).\n\t\t\t\t\t\tconst hasTerminalOutcome =\n\t\t\t\t\t\t\tboundLaneRecord !== undefined ||\n\t\t\t\t\t\t\t(deps.getWorkerClaimSnapshots?.().some((claim) => claim.requestId === bound) ?? false);\n\t\t\t\t\t\tif (!hasTerminalOutcome) dispatchSkipReason = \"bound_lane_indeterminate\";\n\t\t\t\t\t}\n\t\t\t\t\tif (dispatchSkipReason) {\n\t\t\t\t\t\tdispatchGuardRefused = true;\n\t\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${dispatchAction.requirementId}' remains bound to lane '${bound}'.`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (action.action === \"dispatch_worker\" && !dispatchGuardRefused) {\n\t\t\t\tconst tmuxRequested = input.dispatchTarget === \"tmux\";\n\t\t\t\tlet useTmux = tmuxRequested && deps.dispatchTmuxWorker !== undefined;\n\t\t\t\tlet tmuxFallbackReason: string | undefined;\n\t\t\t\tlet dispatched: { laneId?: string; skipReason?: string } | undefined;\n\t\t\t\tif (useTmux) {\n\t\t\t\t\tdispatched = await deps.dispatchTmuxWorker?.({\n\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t});\n\t\t\t\t\tif (\n\t\t\t\t\t\t!dispatched?.laneId &&\n\t\t\t\t\t\tallowsNativeTmuxFallback(dispatched?.skipReason) &&\n\t\t\t\t\t\tdeps.startWorkerDelegation\n\t\t\t\t\t) {\n\t\t\t\t\t\ttmuxFallbackReason = dispatched?.skipReason;\n\t\t\t\t\t\tuseTmux = false;\n\t\t\t\t\t\tdispatched = deps.startWorkerDelegation({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (tmuxRequested) tmuxFallbackReason = \"tmux_extension_not_loaded\";\n\t\t\t\t\tdispatched = deps.startWorkerDelegation?.({\n\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\taction = { ...action, laneId: dispatched?.laneId };\n\t\t\t\tif (dispatched?.laneId) {\n\t\t\t\t\tdispatchNote = tmuxFallbackReason\n\t\t\t\t\t\t? `Tmux route returned ${tmuxFallbackReason}; dispatched native fallback worker lane '${dispatched.laneId}' for requirement '${action.requirementId}'.`\n\t\t\t\t\t\t: useTmux\n\t\t\t\t\t\t\t? `Dispatched tmux worker lane '${dispatched.laneId}' for requirement '${action.requirementId}'.`\n\t\t\t\t\t\t\t: `Dispatched in-process worker lane '${dispatched.laneId}' for requirement '${action.requirementId}' (native default).`;\n\t\t\t\t} else {\n\t\t\t\t\tconst wired = useTmux ? deps.dispatchTmuxWorker : deps.startWorkerDelegation;\n\t\t\t\t\tdispatchSkipReason = dispatched?.skipReason ?? (wired ? \"declined\" : \"dependency_unwired\");\n\t\t\t\t\tdispatchNote = `${tmuxFallbackReason ? `Tmux route returned ${tmuxFallbackReason}; ` : \"\"}No worker was dispatched (${dispatchSkipReason}); requirement '${action.requirementId}' is recorded but not bound to a lane.`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst current = deps.getGoalState();\n\t\t\tlet nextState: GoalState;\n\t\t\tif (action.action === \"dispatch_worker\" && dispatchGuardRefused) {\n\t\t\t\t// Short-circuit: the guard refused before any dispatch attempt -- never call\n\t\t\t\t// applyGoalAction for this turn, so the requirement's existing `boundLaneId` is\n\t\t\t\t// preserved exactly as-is rather than clobbered to `undefined` by the reducer's\n\t\t\t\t// unconditional `boundLaneId: event.laneId` write (goal-state.ts's dispatch_worker case).\n\t\t\t\t// `current` is guaranteed defined here: the guard only refuses when a requirement with\n\t\t\t\t// a `boundLaneId` was found on it.\n\t\t\t\tnextState = current as GoalState;\n\t\t\t} else {\n\t\t\t\tconst result = applyGoalAction(current, action, now(), {\n\t\t\t\t\trequireVerifiedEvidenceForCompletion: deps.requireVerifiedEvidenceForCompletion?.() ?? true,\n\t\t\t\t});\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${result.error}` }],\n\t\t\t\t\t\tdetails: { action: input.action, applied: false, error: result.error, state: current },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tdeps.saveGoalState(result.state, current ? getGoalStateRevision(current) : undefined);\n\t\t\t\tnextState = result.state;\n\t\t\t}\n\n\t\t\tconst summary = summarizeGoalState(nextState, { action, openTaskSteps: deps.getOpenTaskSteps?.() });\n\t\t\tconst text = dispatchNote\n\t\t\t\t? `goal ${input.action} recorded.\\n${summary}\\n${dispatchNote}`\n\t\t\t\t: `goal ${input.action} recorded.\\n${summary}`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: input.action,\n\t\t\t\t\tapplied: true,\n\t\t\t\t\tstate: nextState,\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && action.laneId ? { dispatchedLaneId: action.laneId } : {}),\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && !action.laneId ? { dispatchSkipReason } : {}),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"goal.js","sourceRoot":"","sources":["../../../src/core/tools/goal.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat as fsStat } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport type { WorkerClaim } from \"../autonomy/contracts.ts\";\nimport type { LaneRecord } from \"../autonomy/lane-tracker.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { type GoalStateRevision, getGoalStateRevision } from \"../goals/goal-lifecycle.ts\";\nimport type { GoalEvidenceKind, GoalState } from \"../goals/goal-state.ts\";\nimport {\n\tapplyGoalAction,\n\ttype GoalAction,\n\ttype GoalActionName,\n\ttype OpenTaskStepRef,\n\tsummarizeGoalState,\n} from \"../goals/goal-tool-core.ts\";\nimport {\n\temptyOrchestrationCall,\n\ttype OrchestrationPanelModel,\n\trenderOrchestrationToolResult,\n} from \"./orchestration-panel.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\n\nconst goalSchema = Type.Object(\n\t{\n\t\taction: Type.Union(\n\t\t\t[\n\t\t\t\tType.Literal(\"get\"),\n\t\t\t\tType.Literal(\"start\"),\n\t\t\t\tType.Literal(\"add_requirement\"),\n\t\t\t\tType.Literal(\"satisfy_requirement\"),\n\t\t\t\tType.Literal(\"block_requirement\"),\n\t\t\t\tType.Literal(\"reopen_requirement\"),\n\t\t\t\tType.Literal(\"dispatch_worker\"),\n\t\t\t\tType.Literal(\"add_evidence\"),\n\t\t\t\tType.Literal(\"progress\"),\n\t\t\t\tType.Literal(\"no_progress\"),\n\t\t\t\tType.Literal(\"complete\"),\n\t\t\t\tType.Literal(\"block_goal\"),\n\t\t\t],\n\t\t\t{ description: \"Goal record action.\" },\n\t\t),\n\t\tgoalId: Type.Optional(Type.String({ description: \"Stable goal id. Required for action 'start'.\" })),\n\t\tuserGoal: Type.Optional(Type.String({ description: \"The goal statement. Required for action 'start'.\" })),\n\t\ttokenBudget: Type.Optional(\n\t\t\tType.Integer({ minimum: 1, description: \"Optional positive token budget for action 'start'.\" }),\n\t\t),\n\t\trequirementId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription: \"Requirement id for requirement actions.\",\n\t\t\t}),\n\t\t),\n\t\ttext: Type.Optional(Type.String({ description: \"Requirement text. Required for add_requirement.\" })),\n\t\tdependencies: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Optional IDs of requirements that must be satisfied before this one. Valid for add_requirement.\",\n\t\t\t}),\n\t\t),\n\t\tinstructions: Type.Optional(Type.String({ description: \"Worker instructions. Required for dispatch_worker.\" })),\n\t\tevidenceId: Type.Optional(Type.String({ description: \"Evidence id. Required for add_evidence.\" })),\n\t\tevidenceIds: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription: \"Existing evidence ids for satisfy_requirement.\",\n\t\t\t}),\n\t\t),\n\t\tkind: Type.Optional(\n\t\t\tType.Union(\n\t\t\t\t[\n\t\t\t\t\tType.Literal(\"file\"),\n\t\t\t\t\tType.Literal(\"test\"),\n\t\t\t\t\tType.Literal(\"tool\"),\n\t\t\t\t\tType.Literal(\"user\"),\n\t\t\t\t\tType.Literal(\"finding\"),\n\t\t\t\t\tType.Literal(\"worker\"),\n\t\t\t\t],\n\t\t\t\t{ description: \"Evidence kind. Required for add_evidence.\" },\n\t\t\t),\n\t\t),\n\t\tsummary: Type.Optional(Type.String({ description: \"Evidence summary. Required for add_evidence.\" })),\n\t\turi: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription: \"Optional file/URL, toolCallId, or laneId evidence locator.\",\n\t\t\t}),\n\t\t),\n\t\treason: Type.Optional(Type.String({ description: \"Reason for block_requirement or block_goal.\" })),\n\t\tdispatchTarget: Type.Optional(\n\t\t\tType.Union([Type.Literal(\"in_process\"), Type.Literal(\"tmux\")], {\n\t\t\t\tdescription: \"Legacy target. Native is default; use tmux only for an owner-requested persistent pane.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type GoalToolInput = Static<typeof goalSchema>;\n\nexport interface GoalToolDetails {\n\taction: GoalActionName | \"get\";\n\tapplied: boolean;\n\terror?: string;\n\tstate?: GoalState;\n\t/** Set on 'dispatch_worker' when a worker lane actually started; mirrors the requirement's\n\t * new `boundLaneId`. The in-process route by default, or a real persistent tmux lane when\n\t * `dispatchTarget:\"tmux\"` was selected and routed -- see {@link GoalToolDependencies.dispatchTmuxWorker}. */\n\tdispatchedLaneId?: string;\n\t/** Set on 'dispatch_worker' when no worker was dispatched: a wired dependency declined (e.g. worker\n\t * delegation disabled, already at capacity, or an honest tmux skip reason -- see\n\t * {@link GoalToolDependencies.dispatchTmuxWorker}), or the indeterminate-binding guard refused a\n\t * re-dispatch against an already-bound requirement (`requirement_already_bound`/`bound_lane_indeterminate`).\n\t * The binding is recorded (or, for a guard refusal, left exactly as it was) with no NEW laneId. */\n\tdispatchSkipReason?: string;\n}\n\nexport interface GoalToolDependencies {\n\t/** Read the latest persisted goal state for the active session. */\n\tgetGoalState: () => GoalState | undefined;\n\t/** Persist a new goal state snapshot to the active session. */\n\tsaveGoalState: (state: GoalState, expected?: GoalStateRevision) => void;\n\t/** Clock injection for deterministic tests. */\n\tnow?: () => string;\n\t/**\n\t * Check whether `toolCallId` exists in this session's records, for validating kind:\"tool\"\n\t * evidence refs at add_evidence time. When not wired, a \"tool\" ref cannot be proven and is\n\t * recorded as `verified: false` rather than assumed true.\n\t */\n\thasToolCallId?: (toolCallId: string) => boolean;\n\t/**\n\t * Read the session's live worker lane records, for validating kind:\"worker\" evidence refs\n\t * (the `uri` is a laneId) at add_evidence time. Read-defensive: when not wired -- exactly like\n\t * `hasToolCallId` -- a \"worker\" ref cannot be proven and is recorded as `verified: false` rather\n\t * than assumed true. Live wiring is added separately.\n\t */\n\tgetLaneRecords?: () => readonly LaneRecord[];\n\t/**\n\t * Read persisted worker claim snapshots (keyed by `WorkerClaim.requestId`, which is the same\n\t * id as the dispatching lane's laneId), for validating kind:\"worker\" evidence refs. See\n\t * {@link getLaneRecords}. A matching claim that is `parentReviewRequired && !parentReviewedAt`\n\t * verifies `false` -- an unreviewed worker completion must never ungate goal completion through\n\t * the existing verified/complete gate.\n\t */\n\tgetWorkerClaimSnapshots?: () => readonly WorkerClaim[];\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `dispatchTarget` is 'in_process'\n\t * (the default) or when {@link dispatchTmuxWorker} is not wired: dispatches a real in-process\n\t * worker lane for the given requirement and returns the resulting laneId to bind onto it. When\n\t * the dependency is present but the underlying delegation starter declines (disabled, already at\n\t * capacity, etc.), return `{ skipReason }` instead of a laneId -- a real, non-silent skip that\n\t * the tool response surfaces, distinct from this dependency being altogether unwired (`undefined`\n\t * dep, or the dep returning `undefined`), which records the binding attempt structurally with no\n\t * laneId (a no-op).\n\t */\n\tstartWorkerDelegation?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => { laneId?: string; skipReason?: string } | undefined;\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `input.dispatchTarget === \"tmux\"`:\n\t * dispatches a REAL persistent tmux worker via the tmux_agent_manager extension's `fire_task`\n\t * action (core structurally invokes the same tool call the model would make; no extension change,\n\t * no faked launch or laneId -- see `tmux-dispatch.ts`'s `dispatchTmuxWorker`). Selected ONLY when\n\t * BOTH `input.dispatchTarget === \"tmux\"` AND this dependency is present; otherwise the EXISTING\n\t * {@link startWorkerDelegation} in-process path runs, byte-identical to before this field existed.\n\t * The honest skip-reason vocabulary this can return: `tmux_extension_not_loaded`,\n\t * `no_standing_grant` (the owner has not authorized unattended tmux dispatch),\n\t * `tmux_dispatch_failed`, `tmux_dispatch_incomplete`, `lane_correlation_failed`,\n\t * `worktree_create_failed` (worktree-sync is enabled but the lane-first `create_lane` call was\n\t * refused -- e.g. max lanes reached -- so no fire_task call was ever attempted),\n\t * `worker_capability_insufficient` (the model is sub-full class, has an unknown context window,\n\t * does not advertise a native tool-call path, or is graded-demoted to text-protocol/none -- see\n\t * `model-capability.ts`'s `evaluateLaneWorkerRefusal`; this is the parent's best-effort check\n\t * only, refused before any lane/pane side effect -- the dispatched child still refuses\n\t * authoritatively at its own startup regardless).\n\t */\n\tdispatchTmuxWorker?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => Promise<{ laneId?: string; skipReason?: string }>;\n\t/** Working directory for resolving kind:\"file\" evidence ref paths. Defaults to `process.cwd()`. */\n\tcwd?: () => string;\n\t/**\n\t * Gate agent-facing 'complete' on verified/user evidence backing. Defaults to `true` (on)\n\t * when omitted -- the conservative default; set to a function returning `false` to opt out.\n\t */\n\trequireVerifiedEvidenceForCompletion?: () => boolean;\n\t/**\n\t * Read-only open (non-terminal) task_steps steps on the active branch, for the goal⇄task\n\t * cross-visibility nudge in the tool response. When omitted, `summarizeGoalState` gets\n\t * no task-step context and simply emits no nudge -- goal-tool-core stays pure and never reads\n\t * task state itself; this is the only place that supplies it.\n\t */\n\tgetOpenTaskSteps?: () => readonly OpenTaskStepRef[];\n\t/** Model-facing start authority for the current foreground turn. Omitted by direct owner/test callers. */\n\tauthorizeStart?: (input: Pick<GoalToolInput, \"userGoal\" | \"tokenBudget\">) => string | undefined;\n}\n\nfunction allowsNativeTmuxFallback(reason: string | undefined): boolean {\n\treturn reason === \"tmux_unavailable\" || reason === \"tmux_extension_not_loaded\";\n}\n\n/**\n * Validate an evidence ref's `uri` against session records (\"tool\") or the filesystem (\"file\").\n * Returns `undefined` for kinds/refs that carry nothing checkable (e.g. \"user\"/\"finding\"/\"test\",\n * or a missing `uri`) -- absence of a ref is not the same as a ref that failed to verify.\n */\nasync function resolveEvidenceVerified(\n\tkind: GoalEvidenceKind,\n\turi: string | undefined,\n\tdeps: GoalToolDependencies,\n): Promise<boolean | undefined> {\n\tconst trimmedUri = uri?.trim();\n\tif (!trimmedUri) return undefined;\n\tif (kind === \"tool\") {\n\t\treturn deps.hasToolCallId ? deps.hasToolCallId(trimmedUri) : false;\n\t}\n\tif (kind === \"file\") {\n\t\tconst cwd = deps.cwd?.() ?? process.cwd();\n\t\ttry {\n\t\t\tconst stats = await fsStat(resolveToCwd(trimmedUri, cwd));\n\t\t\treturn stats.isFile();\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (kind === \"worker\") {\n\t\tif (!deps.getLaneRecords || !deps.getWorkerClaimSnapshots) return false;\n\t\tconst laneId = trimmedUri;\n\t\tconst record = deps.getLaneRecords().find((candidate) => candidate.laneId === laneId);\n\t\tif (!record) return false;\n\t\tconst claim = deps.getWorkerClaimSnapshots().find((candidate) => candidate.requestId === laneId);\n\t\tif (!claim) return false;\n\t\t// An unreviewed mutation (parentReviewRequired && no parentReviewedAt) can never verify true --\n\t\t// this is what stops an unreviewed worker completion from ungating goal completion through\n\t\t// the existing verified/complete gate (goal-tool-core's isVerifiedOrUserEvidence/complete).\n\t\tif (claim.parentReviewRequired === true && claim.parentReviewedAt === undefined) return false;\n\t\treturn claim.status === \"completed\";\n\t}\n\treturn undefined;\n}\n\nfunction toGoalAction(input: GoalToolInput): GoalAction | { error: string } {\n\tswitch (input.action) {\n\t\tcase \"start\":\n\t\t\treturn {\n\t\t\t\taction: \"start\",\n\t\t\t\tgoalId: input.goalId ?? \"\",\n\t\t\t\tuserGoal: input.userGoal ?? \"\",\n\t\t\t\ttokenBudget: input.tokenBudget,\n\t\t\t};\n\t\tcase \"add_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"add_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\ttext: input.text ?? \"\",\n\t\t\t\tdependencies: input.dependencies,\n\t\t\t};\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"satisfy_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tevidenceIds: input.evidenceIds,\n\t\t\t};\n\t\tcase \"block_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"block_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\treason: input.reason ?? \"\",\n\t\t\t};\n\t\tcase \"reopen_requirement\":\n\t\t\treturn { action: \"reopen_requirement\", requirementId: input.requirementId ?? \"\" };\n\t\tcase \"dispatch_worker\":\n\t\t\treturn {\n\t\t\t\taction: \"dispatch_worker\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tinstructions: input.instructions ?? \"\",\n\t\t\t};\n\t\tcase \"add_evidence\": {\n\t\t\tif (input.kind === undefined) {\n\t\t\t\treturn { error: \"add_evidence requires a kind.\" };\n\t\t\t}\n\t\t\tconst kind: GoalEvidenceKind = input.kind;\n\t\t\treturn {\n\t\t\t\taction: \"add_evidence\",\n\t\t\t\tevidenceId: input.evidenceId ?? \"\",\n\t\t\t\tkind,\n\t\t\t\tsummary: input.summary ?? \"\",\n\t\t\t\turi: input.uri,\n\t\t\t};\n\t\t}\n\t\tcase \"progress\":\n\t\t\treturn { action: \"progress\" };\n\t\tcase \"no_progress\":\n\t\t\treturn { action: \"no_progress\" };\n\t\tcase \"complete\":\n\t\t\treturn { action: \"complete\" };\n\t\tcase \"block_goal\":\n\t\t\treturn { action: \"block_goal\", reason: input.reason ?? \"\" };\n\t\tcase \"get\":\n\t\t\treturn { error: \"get is handled as a read-only action.\" };\n\t\tdefault:\n\t\t\treturn { error: \"Unknown goal action.\" };\n\t}\n}\n\nfunction goalPanelModel(details: GoalToolDetails | undefined): OrchestrationPanelModel {\n\tconst state = details?.state;\n\tif (!state) {\n\t\treturn {\n\t\t\tlabel: \"goal\",\n\t\t\taction: details?.action,\n\t\t\tstatus: details?.error ? \"error\" : \"idle\",\n\t\t\temptyText: details?.error ?? \"No goal state was returned.\",\n\t\t};\n\t}\n\tconst satisfied = state.requirements.filter((requirement) => requirement.status === \"satisfied\").length;\n\treturn {\n\t\tlabel: \"goal\",\n\t\taction: details.action,\n\t\tstatus:\n\t\t\tstate.status === \"completed\"\n\t\t\t\t? \"success\"\n\t\t\t\t: state.status === \"blocked\" ||\n\t\t\t\t\t\tstate.status === \"paused\" ||\n\t\t\t\t\t\tstate.status === \"usage_limited\" ||\n\t\t\t\t\t\tstate.status === \"budget_limited\"\n\t\t\t\t\t? \"warning\"\n\t\t\t\t\t: state.status === \"cancelled\"\n\t\t\t\t\t\t? \"idle\"\n\t\t\t\t\t\t: \"running\",\n\t\tsummary: [\n\t\t\t`${satisfied}/${state.requirements.length} requirements`,\n\t\t\t`${state.evidence.length} evidence`,\n\t\t\t...(state.tokenBudget !== undefined ? [`${state.tokensUsed ?? 0}/${state.tokenBudget} tokens`] : []),\n\t\t],\n\t\trows: state.requirements.map((requirement) => ({\n\t\t\tstatus:\n\t\t\t\trequirement.status === \"satisfied\"\n\t\t\t\t\t? (\"completed\" as const)\n\t\t\t\t\t: requirement.status === \"open\"\n\t\t\t\t\t\t? (\"pending\" as const)\n\t\t\t\t\t\t: (\"blocked\" as const),\n\t\t\tlabel: requirement.text,\n\t\t\tmeta: [\n\t\t\t\trequirement.id,\n\t\t\t\trequirement.evidenceIds.length > 0 ? `${requirement.evidenceIds.length} evidence` : undefined,\n\t\t\t\trequirement.boundLaneId ? `worker ${requirement.boundLaneId}` : undefined,\n\t\t\t].filter((value): value is string => value !== undefined),\n\t\t\tdetails: requirement.blockedReason ? [`blocked: ${requirement.blockedReason}`] : undefined,\n\t\t})),\n\t\tnotices: [\n\t\t\t...(details.dispatchSkipReason\n\t\t\t\t? [{ status: \"warning\" as const, text: `Worker dispatch skipped: ${details.dispatchSkipReason}` }]\n\t\t\t\t: []),\n\t\t\t...(state.blockedReason ? [{ status: \"warning\" as const, text: state.blockedReason }] : []),\n\t\t],\n\t\temptyText: \"No requirements recorded.\",\n\t};\n}\n\nexport function createGoalToolDefinition(deps: GoalToolDependencies): ToolDefinition {\n\tconst now = deps.now ?? (() => new Date().toISOString());\n\treturn {\n\t\tname: \"goal\",\n\t\tlabel: \"goal\",\n\t\tdescription:\n\t\t\t\"Read or update the durable goal for explicitly persistent work. Use task_steps for plans and delegate for workers; owner or system controls lifecycle and budget stops.\",\n\t\tpromptSnippet: \"Read or update the durable goal.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Start only for explicit persistent chat/system goal. get if uncertain; never replace unfinished goal; tokenBudget only if requested.\",\n\t\t\t\"Plans: task_steps. Workers: delegate. Legacy actions only for legacy goals.\",\n\t\t\t\"complete needs current authoritative evidence, no remaining work. block_goal needs same real impasse for 3 goal turns.\",\n\t\t],\n\t\tparameters: goalSchema,\n\t\trenderShell: \"self\",\n\t\trenderCall() {\n\t\t\treturn emptyOrchestrationCall();\n\t\t},\n\t\trenderResult(result, { expanded, isPartial }, theme) {\n\t\t\tconst details = result.details as GoalToolDetails | undefined;\n\t\t\treturn renderOrchestrationToolResult(theme, goalPanelModel(details), {\n\t\t\t\tisPartial,\n\t\t\t\tcollapse: !expanded && details?.applied === true,\n\t\t\t\texpanded: true,\n\t\t\t});\n\t\t},\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tinput: GoalToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: GoalToolDetails;\n\t\t}> {\n\t\t\tif (input.action === \"get\") {\n\t\t\t\tconst state = deps.getGoalState();\n\t\t\t\tif (!state) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No goal exists for this session.\" }],\n\t\t\t\t\t\tdetails: { action: \"get\", applied: false },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summarizeGoalState(state) }],\n\t\t\t\t\tdetails: { action: \"get\", applied: false, state },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (input.action === \"start\" && deps.authorizeStart) {\n\t\t\t\tconst error = deps.authorizeStart(input);\n\t\t\t\tif (error) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `goal start failed: ${error}` }],\n\t\t\t\t\t\tdetails: { action: \"start\", applied: false, error },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst mapped = toGoalAction(input);\n\t\t\tif (\"error\" in mapped) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${mapped.error}` }],\n\t\t\t\t\tdetails: { action: input.action, applied: false, error: mapped.error },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet action: GoalAction = mapped;\n\t\t\tif (action.action === \"add_evidence\") {\n\t\t\t\tconst verified = await resolveEvidenceVerified(action.kind, action.uri, deps);\n\t\t\t\taction = { ...action, verified };\n\t\t\t}\n\t\t\t// Honest dispatch reporting: distinguish \"dispatched\" (laneId), \"declined\" (skipReason --\n\t\t\t// the dependency IS wired but the underlying delegation starter refused, e.g. disabled or\n\t\t\t// already at capacity), and \"unwired\" (no dependency at all) -- never collapse a real\n\t\t\t// decline into a silent no-laneId no-op indistinguishable from the dep being absent.\n\t\t\tlet dispatchNote: string | undefined;\n\t\t\tlet dispatchSkipReason: string | undefined;\n\t\t\t// Indeterminate-binding dedupe guard: checked BEFORE any dispatch side effect, for BOTH\n\t\t\t// routes. A requirement already bound to a lane that is either still live (a plain\n\t\t\t// duplicate) or whose liveness/outcome cannot be determined at all (for example, a legacy\n\t\t\t// snapshot with no lane record or worker result) must never be\n\t\t\t// re-dispatched silently; only a CONFIRMED terminal outcome allows a legitimate retry.\n\t\t\tlet dispatchGuardRefused = false;\n\t\t\tif (action.action === \"dispatch_worker\") {\n\t\t\t\t// Captured into a `const` so the \"dispatch_worker\" narrowing survives into the closures\n\t\t\t\t// below -- TS does not narrow a `let`-bound outer variable across a callback boundary.\n\t\t\t\tconst dispatchAction = action;\n\t\t\t\tconst boundRequirement = deps\n\t\t\t\t\t.getGoalState()\n\t\t\t\t\t?.requirements.find((r) => r.id === dispatchAction.requirementId);\n\t\t\t\tconst bound = boundRequirement?.boundLaneId;\n\t\t\t\tif (bound !== undefined) {\n\t\t\t\t\tconst boundLaneRecord = deps.getLaneRecords?.().find((record) => record.laneId === bound);\n\t\t\t\t\tconst isLiveInFlight =\n\t\t\t\t\t\tboundLaneRecord !== undefined &&\n\t\t\t\t\t\t(boundLaneRecord.status === \"queued\" || boundLaneRecord.status === \"running\");\n\t\t\t\t\tif (isLiveInFlight) {\n\t\t\t\t\t\tdispatchSkipReason = \"requirement_already_bound\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// `boundLaneRecord` present here is necessarily terminal (isLiveInFlight was false).\n\t\t\t\t\t\tconst hasTerminalOutcome =\n\t\t\t\t\t\t\tboundLaneRecord !== undefined ||\n\t\t\t\t\t\t\t(deps.getWorkerClaimSnapshots?.().some((claim) => claim.requestId === bound) ?? false);\n\t\t\t\t\t\tif (!hasTerminalOutcome) dispatchSkipReason = \"bound_lane_indeterminate\";\n\t\t\t\t\t}\n\t\t\t\t\tif (dispatchSkipReason) {\n\t\t\t\t\t\tdispatchGuardRefused = true;\n\t\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${dispatchAction.requirementId}' remains bound to lane '${bound}'.`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (action.action === \"dispatch_worker\" && !dispatchGuardRefused) {\n\t\t\t\tconst tmuxRequested = input.dispatchTarget === \"tmux\";\n\t\t\t\tlet useTmux = tmuxRequested && deps.dispatchTmuxWorker !== undefined;\n\t\t\t\tlet tmuxFallbackReason: string | undefined;\n\t\t\t\tlet dispatched: { laneId?: string; skipReason?: string } | undefined;\n\t\t\t\tif (useTmux) {\n\t\t\t\t\tdispatched = await deps.dispatchTmuxWorker?.({\n\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t});\n\t\t\t\t\tif (\n\t\t\t\t\t\t!dispatched?.laneId &&\n\t\t\t\t\t\tallowsNativeTmuxFallback(dispatched?.skipReason) &&\n\t\t\t\t\t\tdeps.startWorkerDelegation\n\t\t\t\t\t) {\n\t\t\t\t\t\ttmuxFallbackReason = dispatched?.skipReason;\n\t\t\t\t\t\tuseTmux = false;\n\t\t\t\t\t\tdispatched = deps.startWorkerDelegation({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (tmuxRequested) tmuxFallbackReason = \"tmux_extension_not_loaded\";\n\t\t\t\t\tdispatched = deps.startWorkerDelegation?.({\n\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\taction = { ...action, laneId: dispatched?.laneId };\n\t\t\t\tif (dispatched?.laneId) {\n\t\t\t\t\tdispatchNote = tmuxFallbackReason\n\t\t\t\t\t\t? `Tmux route returned ${tmuxFallbackReason}; dispatched native fallback worker lane '${dispatched.laneId}' for requirement '${action.requirementId}'.`\n\t\t\t\t\t\t: useTmux\n\t\t\t\t\t\t\t? `Dispatched tmux worker lane '${dispatched.laneId}' for requirement '${action.requirementId}'.`\n\t\t\t\t\t\t\t: `Dispatched in-process worker lane '${dispatched.laneId}' for requirement '${action.requirementId}' (native default).`;\n\t\t\t\t} else {\n\t\t\t\t\tconst wired = useTmux ? deps.dispatchTmuxWorker : deps.startWorkerDelegation;\n\t\t\t\t\tdispatchSkipReason = dispatched?.skipReason ?? (wired ? \"declined\" : \"dependency_unwired\");\n\t\t\t\t\tdispatchNote = `${tmuxFallbackReason ? `Tmux route returned ${tmuxFallbackReason}; ` : \"\"}No worker was dispatched (${dispatchSkipReason}); requirement '${action.requirementId}' is recorded but not bound to a lane.`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst current = deps.getGoalState();\n\t\t\tlet nextState: GoalState;\n\t\t\tif (action.action === \"dispatch_worker\" && dispatchGuardRefused) {\n\t\t\t\t// Short-circuit: the guard refused before any dispatch attempt -- never call\n\t\t\t\t// applyGoalAction for this turn, so the requirement's existing `boundLaneId` is\n\t\t\t\t// preserved exactly as-is rather than clobbered to `undefined` by the reducer's\n\t\t\t\t// unconditional `boundLaneId: event.laneId` write (goal-state.ts's dispatch_worker case).\n\t\t\t\t// `current` is guaranteed defined here: the guard only refuses when a requirement with\n\t\t\t\t// a `boundLaneId` was found on it.\n\t\t\t\tnextState = current as GoalState;\n\t\t\t} else {\n\t\t\t\tconst result = applyGoalAction(current, action, now(), {\n\t\t\t\t\trequireVerifiedEvidenceForCompletion: deps.requireVerifiedEvidenceForCompletion?.() ?? true,\n\t\t\t\t});\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${result.error}` }],\n\t\t\t\t\t\tdetails: { action: input.action, applied: false, error: result.error, state: current },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tdeps.saveGoalState(result.state, current ? getGoalStateRevision(current) : undefined);\n\t\t\t\tnextState = result.state;\n\t\t\t}\n\n\t\t\tconst summary = summarizeGoalState(nextState, { action, openTaskSteps: deps.getOpenTaskSteps?.() });\n\t\t\tconst text = dispatchNote\n\t\t\t\t? `goal ${input.action} recorded.\\n${summary}\\n${dispatchNote}`\n\t\t\t\t: `goal ${input.action} recorded.\\n${summary}`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: input.action,\n\t\t\t\t\tapplied: true,\n\t\t\t\t\tstate: nextState,\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && action.laneId ? { dispatchedLaneId: action.laneId } : {}),\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && !action.laneId ? { dispatchSkipReason } : {}),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* them gain locking without forcing an async ripple through their callers; the async variant is for
|
|
18
18
|
* call sites that are already async.
|
|
19
19
|
*/
|
|
20
|
+
import { type FaultableFs } from "./faultable-fs.ts";
|
|
20
21
|
export interface AtomicFileLockOptions {
|
|
21
22
|
/**
|
|
22
23
|
* Bounded retry attempts while waiting for a lock already held elsewhere. Both variants use a
|
|
@@ -53,6 +54,12 @@ export interface AtomicFileLockOptions {
|
|
|
53
54
|
export interface AtomicFileWriteOptions {
|
|
54
55
|
/** POSIX permission bits applied to the temporary file and inherited by the renamed destination. */
|
|
55
56
|
mode?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Injection seam for the mutating fs primitives this write issues (`mkdirSync`, `writeFileSync`,
|
|
59
|
+
* `renameSync`). Defaults to real `node:fs` — omitting this option is a zero-behavior-change no-op.
|
|
60
|
+
* Only the destructive-testing harness passes a fault-injecting implementation.
|
|
61
|
+
*/
|
|
62
|
+
fs?: FaultableFs;
|
|
56
63
|
}
|
|
57
64
|
/**
|
|
58
65
|
* Existing auth/settings/trust paths historically used 10 total attempts separated by 20ms. Keep
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomic-file.d.ts","sourceRoot":"","sources":["../../../src/core/util/atomic-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"atomic-file.d.ts","sourceRoot":"","sources":["../../../src/core/util/atomic-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,EAAE,KAAK,WAAW,EAAU,MAAM,mBAAmB,CAAC;AA4D7D,MAAM,WAAW,qBAAqB;IACrC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iGAAiG;IACjG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sGAAsG;IACtG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACtC,oGAAoG;IACpG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,EAAE,CAAC,EAAE,WAAW,CAAC;CACjB;AAcD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAAC,qBAAqB,CAIxE,CAAC;AAwGH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,MAAM,IAAI,CAkBrG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,CAAC,CAarG;AAED,0GAA0G;AAC1G,wBAAsB,YAAY,CAAC,CAAC,EACnC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACxB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,CAAC,CAAC,CAqBZ;AA4CD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAa7G;AAED,wDAAwD;AACxD,wBAAsB,eAAe,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAcf"}
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
* call sites that are already async.
|
|
19
19
|
*/
|
|
20
20
|
import { randomUUID } from "node:crypto";
|
|
21
|
-
import { promises as fsPromises, mkdirSync,
|
|
21
|
+
import { promises as fsPromises, mkdirSync, unlinkSync } from "node:fs";
|
|
22
22
|
import { dirname, resolve } from "node:path";
|
|
23
23
|
import lockfile from "proper-lockfile";
|
|
24
|
+
import { nodeFs } from "./faultable-fs.js";
|
|
24
25
|
/**
|
|
25
26
|
* Bounded rename retry budget for the win32-only transient-rename handling below (see
|
|
26
27
|
* {@link isTransientRenameErrorOnWin32}). Backoff doubles each attempt starting at
|
|
@@ -52,10 +53,10 @@ function isTransientRenameErrorOnWin32(err) {
|
|
|
52
53
|
return code === "EPERM" || code === "EACCES" || code === "EBUSY";
|
|
53
54
|
}
|
|
54
55
|
/** Sync counterpart of the rename-retry policy; see {@link isTransientRenameErrorOnWin32}. */
|
|
55
|
-
function renameSyncWithRetry(tmpPath, filePath) {
|
|
56
|
+
function renameSyncWithRetry(tmpPath, filePath, fs) {
|
|
56
57
|
for (let attempt = 0; attempt <= RENAME_RETRY_ATTEMPTS; attempt++) {
|
|
57
58
|
try {
|
|
58
|
-
renameSync(tmpPath, filePath);
|
|
59
|
+
fs.renameSync(tmpPath, filePath);
|
|
59
60
|
return;
|
|
60
61
|
}
|
|
61
62
|
catch (err) {
|
|
@@ -302,13 +303,14 @@ async function removeTemporaryPath(tmpPath) {
|
|
|
302
303
|
}
|
|
303
304
|
}
|
|
304
305
|
export function writeFileAtomicSync(filePath, content, options) {
|
|
305
|
-
|
|
306
|
+
const fs = options?.fs ?? nodeFs;
|
|
307
|
+
fs.mkdirSync(dirname(filePath), { recursive: true });
|
|
306
308
|
const tmpPath = temporaryPath(filePath);
|
|
307
309
|
let renamed = false;
|
|
308
310
|
try {
|
|
309
311
|
// `wx` makes a nonce collision harmless: never truncate another writer's temporary file.
|
|
310
|
-
writeFileSync(tmpPath, content, { encoding: "utf-8", flag: "wx", mode: options?.mode });
|
|
311
|
-
renameSyncWithRetry(tmpPath, filePath);
|
|
312
|
+
fs.writeFileSync(tmpPath, content, { encoding: "utf-8", flag: "wx", mode: options?.mode });
|
|
313
|
+
renameSyncWithRetry(tmpPath, filePath, fs);
|
|
312
314
|
renamed = true;
|
|
313
315
|
}
|
|
314
316
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomic-file.js","sourceRoot":"","sources":["../../../src/core/util/atomic-file.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared atomic-file helper: a single lock+tmp+rename implementation reused by every\n * on-disk store that does a read-modify-write against a JSON/text file. Modeled on the pattern\n * already proven in `memory/providers/file-store.ts` (proper-lockfile advisory lock + write-tmp-\n * then-rename); before this helper existed the pattern was copy-pasted per store, and most copies\n * were missing either the lock, the atomic write, or both.\n *\n * Two call shapes:\n * - `withFileLock(Sync)` — hold an exclusive advisory lock across an arbitrary read-modify-write\n * callback. The lock spans BOTH the read and the write, closing the classic RMW race where two\n * writers each read the old content before either writes back.\n * - `writeFileAtomic(Sync)` — write-tmp-then-rename. Used INSIDE a `withFileLock` callback (or\n * standalone, for a pure overwrite that has no read step to race).\n *\n * Sync and async variants are both exported. Most existing stores expose a synchronous public API\n * called from hot, non-async paths (e.g. a per-token-stream perf sample), so the sync variant lets\n * them gain locking without forcing an async ripple through their callers; the async variant is for\n * call sites that are already async.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { promises as fsPromises, mkdirSync, renameSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\n\n/**\n * Bounded rename retry budget for the win32-only transient-rename handling below (see\n * {@link isTransientRenameErrorOnWin32}). Backoff doubles each attempt starting at\n * {@link RENAME_RETRY_MIN_TIMEOUT_MS} and capped at {@link RENAME_RETRY_MAX_TIMEOUT_MS}, mirroring\n * the doubling-backoff shape used for lock acquisition above. With {@link RENAME_RETRY_ATTEMPTS}\n * extra attempts (10, 20, 40, 80, ... capped at 200) the worst-case total wait is ~1.03s\n * (10+20+40+80+160+200+200+200+200 ~= 1110ms across 9 gaps), which comfortably covers the\n * millisecond-scale window Defender/the Windows Search indexer hold a freshly-written file open\n * without FILE_SHARE_DELETE before releasing it.\n */\nconst RENAME_RETRY_ATTEMPTS = 9;\nconst RENAME_RETRY_MIN_TIMEOUT_MS = 10;\nconst RENAME_RETRY_MAX_TIMEOUT_MS = 200;\n\n/**\n * On win32, antivirus (e.g. Windows Defender's real-time scanner) and the Windows Search indexer\n * routinely open a freshly-written file for a brief scan without `FILE_SHARE_DELETE`, which makes a\n * rename over/of that file fail transiently with EPERM/EACCES/EBUSY for a few milliseconds. This is\n * a well-documented platform semantic, not a bug in our write path — it's exactly why the\n * `graceful-fs` package ships its own win32 rename-retry wrapper. POSIX platforms never exhibit this\n * transient (a POSIX rename either succeeds or fails for a real, non-transient reason), so retry is\n * gated strictly to win32 to keep POSIX behavior byte-identical to a bare rename.\n */\nfunction isTransientRenameErrorOnWin32(err: unknown): boolean {\n\tif (process.platform !== \"win32\") return false;\n\tif (typeof err !== \"object\" || err === null) return false;\n\tconst code = (err as { code?: string }).code;\n\treturn code === \"EPERM\" || code === \"EACCES\" || code === \"EBUSY\";\n}\n\n/** Sync counterpart of the rename-retry policy; see {@link isTransientRenameErrorOnWin32}. */\nfunction renameSyncWithRetry(tmpPath: string, filePath: string): void {\n\tfor (let attempt = 0; attempt <= RENAME_RETRY_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\trenameSync(tmpPath, filePath);\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tif (!isTransientRenameErrorOnWin32(err) || attempt === RENAME_RETRY_ATTEMPTS) throw err;\n\t\t\tconst backoffMs = Math.min(RENAME_RETRY_MIN_TIMEOUT_MS * 2 ** attempt, RENAME_RETRY_MAX_TIMEOUT_MS);\n\t\t\tblockingSleepMs(backoffMs);\n\t\t}\n\t}\n}\n\n/** Async counterpart of the rename-retry policy; see {@link isTransientRenameErrorOnWin32}. */\nasync function renameWithRetry(tmpPath: string, filePath: string): Promise<void> {\n\tfor (let attempt = 0; attempt <= RENAME_RETRY_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\tawait fsPromises.rename(tmpPath, filePath);\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tif (!isTransientRenameErrorOnWin32(err) || attempt === RENAME_RETRY_ATTEMPTS) throw err;\n\t\t\tconst backoffMs = Math.min(RENAME_RETRY_MIN_TIMEOUT_MS * 2 ** attempt, RENAME_RETRY_MAX_TIMEOUT_MS);\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, backoffMs));\n\t\t}\n\t}\n}\n\nexport interface AtomicFileLockOptions {\n\t/**\n\t * Bounded retry attempts while waiting for a lock already held elsewhere. Both variants use a\n\t * SHORT, capped backoff (see {@link RETRY_MIN_TIMEOUT_MS}/{@link RETRY_MAX_TIMEOUT_MS}) — these\n\t * stores' critical sections are sub-millisecond reads+writes of small JSON/text files, so\n\t * contention should clear in milliseconds, not the multi-second-to-31-second worst case\n\t * proper-lockfile's OWN default backoff produces for a bare numeric `retries` (its default\n\t * `minTimeout` is 1000ms with factor 2 — see node_modules/retry/lib/retry.js). Passing a bare\n\t * number straight through would turn brief contention into a multi-second stall on a hot path\n\t * (e.g. a per-token-stream perf sample), so both variants instead build an explicit short-backoff\n\t * `retry` options object.\n\t * - Async (`withFileLock`): forwarded as `{retries, minTimeout, maxTimeout}` to proper-lockfile.\n\t * - Sync (`withFileLockSync`): proper-lockfile's sync API REJECTS `retries > 0` outright (it\n\t * requires the whole acquire flow to be synchronous — see proper-lockfile/lib/adapter.js\n\t * `toSyncOptions`, which throws `ESYNC`). So the sync path implements its own bounded retry\n\t * around single `lockfile.lockSync` attempts, blocking briefly between them (Atomics.wait) —\n\t * callers are already fully synchronous fs code, so a short blocking wait on contention matches\n\t * the existing execution model rather than introducing a new one.\n\t */\n\tretries?: number;\n\t/** Initial delay between sync/async acquisition attempts; defaults to 25ms. */\n\tminRetryDelayMs?: number;\n\t/** Maximum delay between sync/async acquisition attempts; defaults to 500ms. */\n\tmaxRetryDelayMs?: number;\n\t/** Retry-delay multiplier; defaults to 2. Set max=min for a fixed delay. */\n\tretryFactor?: number;\n\t/** Resolve symlinks before locking (proper-lockfile `realpath`); false matches file-store.ts. */\n\trealpath?: boolean;\n\t/** Lock staleness window in ms (proper-lockfile `stale`); omitted = proper-lockfile's own default. */\n\tstale?: number;\n\t/** Explicit proper-lockfile directory path; defaults to `${filePath}.lock`. */\n\tlockfilePath?: string;\n}\n\nexport interface AtomicFileWriteOptions {\n\t/** POSIX permission bits applied to the temporary file and inherited by the renamed destination. */\n\tmode?: number;\n}\n\nconst DEFAULT_RETRIES = 10;\nconst DEFAULT_REALPATH = false;\n/**\n * Capped doubling backoff shared by both variants — see {@link AtomicFileLockOptions.retries}.\n * With the current defaults (10 retries, 25ms floor, 500ms cap) the total worst-case contention\n * budget is ~3.3s (25+50+100+200+400+500+500+500+500+500), comfortably over the >= 2s floor this\n * needs to survive a loaded CI runner (e.g. the Windows CI mkdir/rmdir lock-directory churn under\n * two-real-OS-thread contention).\n */\nconst RETRY_MIN_TIMEOUT_MS = 25;\nconst RETRY_MAX_TIMEOUT_MS = 500;\n\n/**\n * Existing auth/settings/trust paths historically used 10 total attempts separated by 20ms. Keep\n * that low-latency user-facing policy explicit while routing the mechanism through this module.\n */\nexport const LOW_LATENCY_FILE_LOCK_OPTIONS: Readonly<AtomicFileLockOptions> = Object.freeze({\n\tretries: 9,\n\tminRetryDelayMs: 20,\n\tmaxRetryDelayMs: 20,\n});\n\nfunction lockDirectory(filePath: string, lockfilePath?: string): string {\n\treturn dirname(lockfilePath ?? filePath);\n}\n\nfunction ensureLockDirSync(filePath: string, lockfilePath?: string): void {\n\tmkdirSync(lockDirectory(filePath, lockfilePath), { recursive: true });\n}\n\nasync function ensureLockDir(filePath: string, lockfilePath?: string): Promise<void> {\n\tawait fsPromises.mkdir(lockDirectory(filePath, lockfilePath), { recursive: true });\n}\n\nfunction isLockedError(err: unknown): boolean {\n\tif (typeof err !== \"object\" || err === null) return false;\n\tconst code = (err as { code?: string }).code;\n\tif (code === \"ELOCKED\") return true;\n\t// On win32, mkdir-ing the lock directory can transiently surface EPERM (rather than the\n\t// expected EEXIST) when a previous incarnation of that directory is concurrently being\n\t// rmdir'd by the racing releaser — the mkdir lands mid-teardown and the OS reports \"operation\n\t// not permitted\" instead of \"already exists\". This is contention, not a real permissions\n\t// failure, so treat it identically to ELOCKED: retry with the existing backoff rather than\n\t// letting it escape as fatal. POSIX platforms don't exhibit this transient and keep surfacing\n\t// real EPERM (e.g. an actually unwritable directory) as fatal.\n\tif (code === \"EPERM\" && process.platform === \"win32\") return true;\n\treturn false;\n}\n\n/** Block the calling thread for `ms` without spinning the CPU (Atomics.wait on a private buffer). */\nfunction blockingSleepMs(ms: number): void {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\ntype PendingPathOperations = Map<string, Promise<void>>;\n\nconst pendingAsyncFileLockTails: PendingPathOperations = new Map();\nconst pendingAtomicWriteTails: PendingPathOperations = new Map();\n\nfunction pathOperationKey(filePath: string): string {\n\tconst absolutePath = resolve(filePath);\n\treturn process.platform === \"win32\" ? absolutePath.toLowerCase() : absolutePath;\n}\n\n/**\n * Queue only operations that target the same platform path. This prevents same-process callers\n * from entering synchronized OS retry storms without imposing a process-wide or cross-tenant\n * bottleneck. The tail always resolves and self-removes, including after a failed operation.\n */\nasync function withSerializedPathOperation<T>(\n\ttails: PendingPathOperations,\n\tfilePath: string,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tconst key = pathOperationKey(filePath);\n\tconst preceding = tails.get(key) ?? Promise.resolve();\n\tlet releaseTail: (() => void) | undefined;\n\tconst tail = new Promise<void>((resolveTail) => {\n\t\treleaseTail = resolveTail;\n\t});\n\ttails.set(key, tail);\n\n\tawait preceding;\n\ttry {\n\t\treturn await fn();\n\t} finally {\n\t\treleaseTail?.();\n\t\tif (tails.get(key) === tail) tails.delete(key);\n\t}\n}\n\n/**\n * Acquire a proper-lockfile sync lock with bounded retry on `ELOCKED` (proper-lockfile's sync API\n * itself forbids `retries > 0`; see {@link AtomicFileLockOptions.retries}).\n *\n * Backoff doubles each attempt (mirroring the `retry` module's own `factor: 2` default that the\n * async path gets for free from proper-lockfile), starting at {@link RETRY_MIN_TIMEOUT_MS} and\n * capped at {@link RETRY_MAX_TIMEOUT_MS}.\n *\n * This is budget PARITY between two implementations of the same lock-acquisition contract, not\n * flake-masking: `options.retries` (a count of RETRIES, i.e. attempts after the first) means the\n * same thing on both paths, so both must make `retries + 1` total acquisition attempts with the\n * same per-gap backoff schedule. The async path gets `retries + 1` attempts for free from the\n * `retry` module (it retries `options.retries` times after its initial attempt); the sync path\n * used to loop exactly `attempts` times total (one fewer gap, and one fewer attempt than the\n * async path for the same `retries` value), which under-budgeted it relative to its async sibling\n * and surfaced as spurious ELOCKED failures under real contention (e.g. two OS threads hammering\n * the same file, or mkdir/rmdir lock-directory churn on a loaded Windows CI runner).\n */\nfunction retryCount(options: AtomicFileLockOptions): number {\n\tconst configured = options.retries ?? DEFAULT_RETRIES;\n\treturn Number.isFinite(configured) ? Math.max(0, Math.floor(configured)) : DEFAULT_RETRIES;\n}\n\nfunction retryDelayMs(options: AtomicFileLockOptions, attempt: number): number {\n\tconst configuredMin = options.minRetryDelayMs ?? RETRY_MIN_TIMEOUT_MS;\n\tconst minDelay = Number.isFinite(configuredMin) ? Math.max(0, configuredMin) : RETRY_MIN_TIMEOUT_MS;\n\tconst configuredMax = options.maxRetryDelayMs ?? RETRY_MAX_TIMEOUT_MS;\n\tconst maxDelay = Number.isFinite(configuredMax) ? Math.max(minDelay, configuredMax) : RETRY_MAX_TIMEOUT_MS;\n\tconst configuredFactor = options.retryFactor ?? 2;\n\tconst factor = Number.isFinite(configuredFactor) ? Math.max(1, configuredFactor) : 2;\n\treturn Math.min(minDelay * factor ** (attempt - 1), maxDelay);\n}\n\n/**\n * Acquire a synchronous advisory file lock and return its release function. This is the shared\n * mechanism for coordinators that must hold several locks in a deterministic order before entering\n * one critical section; callers retain ownership of release ordering and release-error semantics.\n */\nexport function acquireFileLockSync(filePath: string, options: AtomicFileLockOptions = {}): () => void {\n\tensureLockDirSync(filePath, options.lockfilePath);\n\tconst attempts = retryCount(options) + 1;\n\tconst lockOptions = {\n\t\tlockfilePath: options.lockfilePath,\n\t\trealpath: options.realpath ?? DEFAULT_REALPATH,\n\t\tstale: options.stale,\n\t};\n\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(filePath, lockOptions);\n\t\t} catch (err) {\n\t\t\tif (!isLockedError(err) || attempt === attempts) throw err;\n\t\t\tblockingSleepMs(retryDelayMs(options, attempt));\n\t\t}\n\t}\n\t// Unreachable (the loop always returns or throws), but keeps the function's return type honest.\n\tthrow new Error(`Failed to acquire lock for ${filePath}`);\n}\n\n/**\n * Hold an exclusive advisory lock on `filePath` for the duration of `fn` (sync). Always releases,\n * including when `fn` throws.\n */\nexport function withFileLockSync<T>(filePath: string, fn: () => T, options?: AtomicFileLockOptions): T {\n\tconst release = acquireFileLockSync(filePath, options);\n\ttry {\n\t\treturn fn();\n\t} finally {\n\t\t// A lock-cleanup failure must never mask fn()'s result (or replace fn()'s own thrown error) —\n\t\t// by this point fn() has already durably committed or failed on its own terms.\n\t\ttry {\n\t\t\trelease();\n\t\t} catch {\n\t\t\t// best-effort cleanup; a stale lock self-expires via proper-lockfile's `stale` window\n\t\t}\n\t}\n}\n\n/** Async counterpart of {@link withFileLockSync}. Always releases, including when `fn` throws/rejects. */\nexport async function withFileLock<T>(\n\tfilePath: string,\n\tfn: () => Promise<T> | T,\n\toptions?: AtomicFileLockOptions,\n): Promise<T> {\n\treturn withSerializedPathOperation(pendingAsyncFileLockTails, options?.lockfilePath ?? filePath, async () => {\n\t\tawait ensureLockDir(filePath, options?.lockfilePath);\n\t\tconst release = await lockfile.lock(filePath, {\n\t\t\tlockfilePath: options?.lockfilePath,\n\t\t\trealpath: options?.realpath ?? DEFAULT_REALPATH,\n\t\t\tretries: {\n\t\t\t\tretries: retryCount(options ?? {}),\n\t\t\t\tfactor: options?.retryFactor ?? 2,\n\t\t\t\tminTimeout: options?.minRetryDelayMs ?? RETRY_MIN_TIMEOUT_MS,\n\t\t\t\tmaxTimeout: options?.maxRetryDelayMs ?? RETRY_MAX_TIMEOUT_MS,\n\t\t\t},\n\t\t\tstale: options?.stale,\n\t\t});\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\t// See {@link withFileLockSync} — cleanup failures must not mask fn()'s outcome.\n\t\t\tawait release().catch(() => {});\n\t\t}\n\t});\n}\n\n/**\n * Write `content` to `filePath` via write-tmp-then-rename (sync); the rename is atomic on the same\n * filesystem, so a concurrent reader never observes a partially-written file. Does NOT itself lock —\n * call from inside {@link withFileLockSync} when the write follows a read that must not race another\n * writer's read+write; call standalone for an unconditional overwrite with no read step.\n */\nfunction temporaryPath(filePath: string): string {\n\treturn `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n}\n\n/**\n * Async standalone overwrites can legitimately target the same file at once. Unique temporary\n * names prevent writers from corrupting each other's staging files, but Windows still serializes\n * replacement renames internally. Letting every writer retry in lockstep creates a thundering herd\n * that can exhaust the bounded Defender/indexer retry budget even though no external process owns\n * the destination. Keep one FIFO tail per destination inside this process so each destination has\n * one writer at a time; writes to different destinations remain fully parallel. The tail is always\n * resolved and removed, including after a failed write, so one failure cannot poison later writes\n * or retain tenant paths indefinitely. File-lock queues are separate from atomic-write queues so a\n * write inside a held advisory lock never waits on itself.\n */\nasync function withSerializedAtomicWrite<T>(filePath: string, fn: () => Promise<T>): Promise<T> {\n\treturn withSerializedPathOperation(pendingAtomicWriteTails, filePath, fn);\n}\n\n/** Remove one invocation's temporary path without masking the original write/rename failure. */\nfunction removeTemporaryPathSync(tmpPath: string): void {\n\ttry {\n\t\tunlinkSync(tmpPath);\n\t} catch {\n\t\t// The rename may have consumed the path, or another failure may have prevented its creation.\n\t}\n}\n\nasync function removeTemporaryPath(tmpPath: string): Promise<void> {\n\ttry {\n\t\tawait fsPromises.unlink(tmpPath);\n\t} catch {\n\t\t// The rename may have consumed the path, or another failure may have prevented its creation.\n\t}\n}\n\nexport function writeFileAtomicSync(filePath: string, content: string, options?: AtomicFileWriteOptions): void {\n\tmkdirSync(dirname(filePath), { recursive: true });\n\tconst tmpPath = temporaryPath(filePath);\n\tlet renamed = false;\n\ttry {\n\t\t// `wx` makes a nonce collision harmless: never truncate another writer's temporary file.\n\t\twriteFileSync(tmpPath, content, { encoding: \"utf-8\", flag: \"wx\", mode: options?.mode });\n\t\trenameSyncWithRetry(tmpPath, filePath);\n\t\trenamed = true;\n\t} finally {\n\t\tif (!renamed) removeTemporaryPathSync(tmpPath);\n\t}\n}\n\n/** Async counterpart of {@link writeFileAtomicSync}. */\nexport async function writeFileAtomic(\n\tfilePath: string,\n\tcontent: string,\n\toptions?: AtomicFileWriteOptions,\n): Promise<void> {\n\tawait withSerializedAtomicWrite(filePath, async () => {\n\t\tawait fsPromises.mkdir(dirname(filePath), { recursive: true });\n\t\tconst tmpPath = temporaryPath(filePath);\n\t\tlet renamed = false;\n\t\ttry {\n\t\t\t// `wx` makes a nonce collision harmless: never truncate another writer's temporary file.\n\t\t\tawait fsPromises.writeFile(tmpPath, content, { encoding: \"utf-8\", flag: \"wx\", mode: options?.mode });\n\t\t\tawait renameWithRetry(tmpPath, filePath);\n\t\t\trenamed = true;\n\t\t} finally {\n\t\t\tif (!renamed) await removeTemporaryPath(tmpPath);\n\t\t}\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"atomic-file.js","sourceRoot":"","sources":["../../../src/core/util/atomic-file.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared atomic-file helper: a single lock+tmp+rename implementation reused by every\n * on-disk store that does a read-modify-write against a JSON/text file. Modeled on the pattern\n * already proven in `memory/providers/file-store.ts` (proper-lockfile advisory lock + write-tmp-\n * then-rename); before this helper existed the pattern was copy-pasted per store, and most copies\n * were missing either the lock, the atomic write, or both.\n *\n * Two call shapes:\n * - `withFileLock(Sync)` — hold an exclusive advisory lock across an arbitrary read-modify-write\n * callback. The lock spans BOTH the read and the write, closing the classic RMW race where two\n * writers each read the old content before either writes back.\n * - `writeFileAtomic(Sync)` — write-tmp-then-rename. Used INSIDE a `withFileLock` callback (or\n * standalone, for a pure overwrite that has no read step to race).\n *\n * Sync and async variants are both exported. Most existing stores expose a synchronous public API\n * called from hot, non-async paths (e.g. a per-token-stream perf sample), so the sync variant lets\n * them gain locking without forcing an async ripple through their callers; the async variant is for\n * call sites that are already async.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { promises as fsPromises, mkdirSync, unlinkSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { type FaultableFs, nodeFs } from \"./faultable-fs.ts\";\n\n/**\n * Bounded rename retry budget for the win32-only transient-rename handling below (see\n * {@link isTransientRenameErrorOnWin32}). Backoff doubles each attempt starting at\n * {@link RENAME_RETRY_MIN_TIMEOUT_MS} and capped at {@link RENAME_RETRY_MAX_TIMEOUT_MS}, mirroring\n * the doubling-backoff shape used for lock acquisition above. With {@link RENAME_RETRY_ATTEMPTS}\n * extra attempts (10, 20, 40, 80, ... capped at 200) the worst-case total wait is ~1.03s\n * (10+20+40+80+160+200+200+200+200 ~= 1110ms across 9 gaps), which comfortably covers the\n * millisecond-scale window Defender/the Windows Search indexer hold a freshly-written file open\n * without FILE_SHARE_DELETE before releasing it.\n */\nconst RENAME_RETRY_ATTEMPTS = 9;\nconst RENAME_RETRY_MIN_TIMEOUT_MS = 10;\nconst RENAME_RETRY_MAX_TIMEOUT_MS = 200;\n\n/**\n * On win32, antivirus (e.g. Windows Defender's real-time scanner) and the Windows Search indexer\n * routinely open a freshly-written file for a brief scan without `FILE_SHARE_DELETE`, which makes a\n * rename over/of that file fail transiently with EPERM/EACCES/EBUSY for a few milliseconds. This is\n * a well-documented platform semantic, not a bug in our write path — it's exactly why the\n * `graceful-fs` package ships its own win32 rename-retry wrapper. POSIX platforms never exhibit this\n * transient (a POSIX rename either succeeds or fails for a real, non-transient reason), so retry is\n * gated strictly to win32 to keep POSIX behavior byte-identical to a bare rename.\n */\nfunction isTransientRenameErrorOnWin32(err: unknown): boolean {\n\tif (process.platform !== \"win32\") return false;\n\tif (typeof err !== \"object\" || err === null) return false;\n\tconst code = (err as { code?: string }).code;\n\treturn code === \"EPERM\" || code === \"EACCES\" || code === \"EBUSY\";\n}\n\n/** Sync counterpart of the rename-retry policy; see {@link isTransientRenameErrorOnWin32}. */\nfunction renameSyncWithRetry(tmpPath: string, filePath: string, fs: FaultableFs): void {\n\tfor (let attempt = 0; attempt <= RENAME_RETRY_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\tfs.renameSync(tmpPath, filePath);\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tif (!isTransientRenameErrorOnWin32(err) || attempt === RENAME_RETRY_ATTEMPTS) throw err;\n\t\t\tconst backoffMs = Math.min(RENAME_RETRY_MIN_TIMEOUT_MS * 2 ** attempt, RENAME_RETRY_MAX_TIMEOUT_MS);\n\t\t\tblockingSleepMs(backoffMs);\n\t\t}\n\t}\n}\n\n/** Async counterpart of the rename-retry policy; see {@link isTransientRenameErrorOnWin32}. */\nasync function renameWithRetry(tmpPath: string, filePath: string): Promise<void> {\n\tfor (let attempt = 0; attempt <= RENAME_RETRY_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\tawait fsPromises.rename(tmpPath, filePath);\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tif (!isTransientRenameErrorOnWin32(err) || attempt === RENAME_RETRY_ATTEMPTS) throw err;\n\t\t\tconst backoffMs = Math.min(RENAME_RETRY_MIN_TIMEOUT_MS * 2 ** attempt, RENAME_RETRY_MAX_TIMEOUT_MS);\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, backoffMs));\n\t\t}\n\t}\n}\n\nexport interface AtomicFileLockOptions {\n\t/**\n\t * Bounded retry attempts while waiting for a lock already held elsewhere. Both variants use a\n\t * SHORT, capped backoff (see {@link RETRY_MIN_TIMEOUT_MS}/{@link RETRY_MAX_TIMEOUT_MS}) — these\n\t * stores' critical sections are sub-millisecond reads+writes of small JSON/text files, so\n\t * contention should clear in milliseconds, not the multi-second-to-31-second worst case\n\t * proper-lockfile's OWN default backoff produces for a bare numeric `retries` (its default\n\t * `minTimeout` is 1000ms with factor 2 — see node_modules/retry/lib/retry.js). Passing a bare\n\t * number straight through would turn brief contention into a multi-second stall on a hot path\n\t * (e.g. a per-token-stream perf sample), so both variants instead build an explicit short-backoff\n\t * `retry` options object.\n\t * - Async (`withFileLock`): forwarded as `{retries, minTimeout, maxTimeout}` to proper-lockfile.\n\t * - Sync (`withFileLockSync`): proper-lockfile's sync API REJECTS `retries > 0` outright (it\n\t * requires the whole acquire flow to be synchronous — see proper-lockfile/lib/adapter.js\n\t * `toSyncOptions`, which throws `ESYNC`). So the sync path implements its own bounded retry\n\t * around single `lockfile.lockSync` attempts, blocking briefly between them (Atomics.wait) —\n\t * callers are already fully synchronous fs code, so a short blocking wait on contention matches\n\t * the existing execution model rather than introducing a new one.\n\t */\n\tretries?: number;\n\t/** Initial delay between sync/async acquisition attempts; defaults to 25ms. */\n\tminRetryDelayMs?: number;\n\t/** Maximum delay between sync/async acquisition attempts; defaults to 500ms. */\n\tmaxRetryDelayMs?: number;\n\t/** Retry-delay multiplier; defaults to 2. Set max=min for a fixed delay. */\n\tretryFactor?: number;\n\t/** Resolve symlinks before locking (proper-lockfile `realpath`); false matches file-store.ts. */\n\trealpath?: boolean;\n\t/** Lock staleness window in ms (proper-lockfile `stale`); omitted = proper-lockfile's own default. */\n\tstale?: number;\n\t/** Explicit proper-lockfile directory path; defaults to `${filePath}.lock`. */\n\tlockfilePath?: string;\n}\n\nexport interface AtomicFileWriteOptions {\n\t/** POSIX permission bits applied to the temporary file and inherited by the renamed destination. */\n\tmode?: number;\n\t/**\n\t * Injection seam for the mutating fs primitives this write issues (`mkdirSync`, `writeFileSync`,\n\t * `renameSync`). Defaults to real `node:fs` — omitting this option is a zero-behavior-change no-op.\n\t * Only the destructive-testing harness passes a fault-injecting implementation.\n\t */\n\tfs?: FaultableFs;\n}\n\nconst DEFAULT_RETRIES = 10;\nconst DEFAULT_REALPATH = false;\n/**\n * Capped doubling backoff shared by both variants — see {@link AtomicFileLockOptions.retries}.\n * With the current defaults (10 retries, 25ms floor, 500ms cap) the total worst-case contention\n * budget is ~3.3s (25+50+100+200+400+500+500+500+500+500), comfortably over the >= 2s floor this\n * needs to survive a loaded CI runner (e.g. the Windows CI mkdir/rmdir lock-directory churn under\n * two-real-OS-thread contention).\n */\nconst RETRY_MIN_TIMEOUT_MS = 25;\nconst RETRY_MAX_TIMEOUT_MS = 500;\n\n/**\n * Existing auth/settings/trust paths historically used 10 total attempts separated by 20ms. Keep\n * that low-latency user-facing policy explicit while routing the mechanism through this module.\n */\nexport const LOW_LATENCY_FILE_LOCK_OPTIONS: Readonly<AtomicFileLockOptions> = Object.freeze({\n\tretries: 9,\n\tminRetryDelayMs: 20,\n\tmaxRetryDelayMs: 20,\n});\n\nfunction lockDirectory(filePath: string, lockfilePath?: string): string {\n\treturn dirname(lockfilePath ?? filePath);\n}\n\nfunction ensureLockDirSync(filePath: string, lockfilePath?: string): void {\n\tmkdirSync(lockDirectory(filePath, lockfilePath), { recursive: true });\n}\n\nasync function ensureLockDir(filePath: string, lockfilePath?: string): Promise<void> {\n\tawait fsPromises.mkdir(lockDirectory(filePath, lockfilePath), { recursive: true });\n}\n\nfunction isLockedError(err: unknown): boolean {\n\tif (typeof err !== \"object\" || err === null) return false;\n\tconst code = (err as { code?: string }).code;\n\tif (code === \"ELOCKED\") return true;\n\t// On win32, mkdir-ing the lock directory can transiently surface EPERM (rather than the\n\t// expected EEXIST) when a previous incarnation of that directory is concurrently being\n\t// rmdir'd by the racing releaser — the mkdir lands mid-teardown and the OS reports \"operation\n\t// not permitted\" instead of \"already exists\". This is contention, not a real permissions\n\t// failure, so treat it identically to ELOCKED: retry with the existing backoff rather than\n\t// letting it escape as fatal. POSIX platforms don't exhibit this transient and keep surfacing\n\t// real EPERM (e.g. an actually unwritable directory) as fatal.\n\tif (code === \"EPERM\" && process.platform === \"win32\") return true;\n\treturn false;\n}\n\n/** Block the calling thread for `ms` without spinning the CPU (Atomics.wait on a private buffer). */\nfunction blockingSleepMs(ms: number): void {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\ntype PendingPathOperations = Map<string, Promise<void>>;\n\nconst pendingAsyncFileLockTails: PendingPathOperations = new Map();\nconst pendingAtomicWriteTails: PendingPathOperations = new Map();\n\nfunction pathOperationKey(filePath: string): string {\n\tconst absolutePath = resolve(filePath);\n\treturn process.platform === \"win32\" ? absolutePath.toLowerCase() : absolutePath;\n}\n\n/**\n * Queue only operations that target the same platform path. This prevents same-process callers\n * from entering synchronized OS retry storms without imposing a process-wide or cross-tenant\n * bottleneck. The tail always resolves and self-removes, including after a failed operation.\n */\nasync function withSerializedPathOperation<T>(\n\ttails: PendingPathOperations,\n\tfilePath: string,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tconst key = pathOperationKey(filePath);\n\tconst preceding = tails.get(key) ?? Promise.resolve();\n\tlet releaseTail: (() => void) | undefined;\n\tconst tail = new Promise<void>((resolveTail) => {\n\t\treleaseTail = resolveTail;\n\t});\n\ttails.set(key, tail);\n\n\tawait preceding;\n\ttry {\n\t\treturn await fn();\n\t} finally {\n\t\treleaseTail?.();\n\t\tif (tails.get(key) === tail) tails.delete(key);\n\t}\n}\n\n/**\n * Acquire a proper-lockfile sync lock with bounded retry on `ELOCKED` (proper-lockfile's sync API\n * itself forbids `retries > 0`; see {@link AtomicFileLockOptions.retries}).\n *\n * Backoff doubles each attempt (mirroring the `retry` module's own `factor: 2` default that the\n * async path gets for free from proper-lockfile), starting at {@link RETRY_MIN_TIMEOUT_MS} and\n * capped at {@link RETRY_MAX_TIMEOUT_MS}.\n *\n * This is budget PARITY between two implementations of the same lock-acquisition contract, not\n * flake-masking: `options.retries` (a count of RETRIES, i.e. attempts after the first) means the\n * same thing on both paths, so both must make `retries + 1` total acquisition attempts with the\n * same per-gap backoff schedule. The async path gets `retries + 1` attempts for free from the\n * `retry` module (it retries `options.retries` times after its initial attempt); the sync path\n * used to loop exactly `attempts` times total (one fewer gap, and one fewer attempt than the\n * async path for the same `retries` value), which under-budgeted it relative to its async sibling\n * and surfaced as spurious ELOCKED failures under real contention (e.g. two OS threads hammering\n * the same file, or mkdir/rmdir lock-directory churn on a loaded Windows CI runner).\n */\nfunction retryCount(options: AtomicFileLockOptions): number {\n\tconst configured = options.retries ?? DEFAULT_RETRIES;\n\treturn Number.isFinite(configured) ? Math.max(0, Math.floor(configured)) : DEFAULT_RETRIES;\n}\n\nfunction retryDelayMs(options: AtomicFileLockOptions, attempt: number): number {\n\tconst configuredMin = options.minRetryDelayMs ?? RETRY_MIN_TIMEOUT_MS;\n\tconst minDelay = Number.isFinite(configuredMin) ? Math.max(0, configuredMin) : RETRY_MIN_TIMEOUT_MS;\n\tconst configuredMax = options.maxRetryDelayMs ?? RETRY_MAX_TIMEOUT_MS;\n\tconst maxDelay = Number.isFinite(configuredMax) ? Math.max(minDelay, configuredMax) : RETRY_MAX_TIMEOUT_MS;\n\tconst configuredFactor = options.retryFactor ?? 2;\n\tconst factor = Number.isFinite(configuredFactor) ? Math.max(1, configuredFactor) : 2;\n\treturn Math.min(minDelay * factor ** (attempt - 1), maxDelay);\n}\n\n/**\n * Acquire a synchronous advisory file lock and return its release function. This is the shared\n * mechanism for coordinators that must hold several locks in a deterministic order before entering\n * one critical section; callers retain ownership of release ordering and release-error semantics.\n */\nexport function acquireFileLockSync(filePath: string, options: AtomicFileLockOptions = {}): () => void {\n\tensureLockDirSync(filePath, options.lockfilePath);\n\tconst attempts = retryCount(options) + 1;\n\tconst lockOptions = {\n\t\tlockfilePath: options.lockfilePath,\n\t\trealpath: options.realpath ?? DEFAULT_REALPATH,\n\t\tstale: options.stale,\n\t};\n\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(filePath, lockOptions);\n\t\t} catch (err) {\n\t\t\tif (!isLockedError(err) || attempt === attempts) throw err;\n\t\t\tblockingSleepMs(retryDelayMs(options, attempt));\n\t\t}\n\t}\n\t// Unreachable (the loop always returns or throws), but keeps the function's return type honest.\n\tthrow new Error(`Failed to acquire lock for ${filePath}`);\n}\n\n/**\n * Hold an exclusive advisory lock on `filePath` for the duration of `fn` (sync). Always releases,\n * including when `fn` throws.\n */\nexport function withFileLockSync<T>(filePath: string, fn: () => T, options?: AtomicFileLockOptions): T {\n\tconst release = acquireFileLockSync(filePath, options);\n\ttry {\n\t\treturn fn();\n\t} finally {\n\t\t// A lock-cleanup failure must never mask fn()'s result (or replace fn()'s own thrown error) —\n\t\t// by this point fn() has already durably committed or failed on its own terms.\n\t\ttry {\n\t\t\trelease();\n\t\t} catch {\n\t\t\t// best-effort cleanup; a stale lock self-expires via proper-lockfile's `stale` window\n\t\t}\n\t}\n}\n\n/** Async counterpart of {@link withFileLockSync}. Always releases, including when `fn` throws/rejects. */\nexport async function withFileLock<T>(\n\tfilePath: string,\n\tfn: () => Promise<T> | T,\n\toptions?: AtomicFileLockOptions,\n): Promise<T> {\n\treturn withSerializedPathOperation(pendingAsyncFileLockTails, options?.lockfilePath ?? filePath, async () => {\n\t\tawait ensureLockDir(filePath, options?.lockfilePath);\n\t\tconst release = await lockfile.lock(filePath, {\n\t\t\tlockfilePath: options?.lockfilePath,\n\t\t\trealpath: options?.realpath ?? DEFAULT_REALPATH,\n\t\t\tretries: {\n\t\t\t\tretries: retryCount(options ?? {}),\n\t\t\t\tfactor: options?.retryFactor ?? 2,\n\t\t\t\tminTimeout: options?.minRetryDelayMs ?? RETRY_MIN_TIMEOUT_MS,\n\t\t\t\tmaxTimeout: options?.maxRetryDelayMs ?? RETRY_MAX_TIMEOUT_MS,\n\t\t\t},\n\t\t\tstale: options?.stale,\n\t\t});\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\t// See {@link withFileLockSync} — cleanup failures must not mask fn()'s outcome.\n\t\t\tawait release().catch(() => {});\n\t\t}\n\t});\n}\n\n/**\n * Write `content` to `filePath` via write-tmp-then-rename (sync); the rename is atomic on the same\n * filesystem, so a concurrent reader never observes a partially-written file. Does NOT itself lock —\n * call from inside {@link withFileLockSync} when the write follows a read that must not race another\n * writer's read+write; call standalone for an unconditional overwrite with no read step.\n */\nfunction temporaryPath(filePath: string): string {\n\treturn `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n}\n\n/**\n * Async standalone overwrites can legitimately target the same file at once. Unique temporary\n * names prevent writers from corrupting each other's staging files, but Windows still serializes\n * replacement renames internally. Letting every writer retry in lockstep creates a thundering herd\n * that can exhaust the bounded Defender/indexer retry budget even though no external process owns\n * the destination. Keep one FIFO tail per destination inside this process so each destination has\n * one writer at a time; writes to different destinations remain fully parallel. The tail is always\n * resolved and removed, including after a failed write, so one failure cannot poison later writes\n * or retain tenant paths indefinitely. File-lock queues are separate from atomic-write queues so a\n * write inside a held advisory lock never waits on itself.\n */\nasync function withSerializedAtomicWrite<T>(filePath: string, fn: () => Promise<T>): Promise<T> {\n\treturn withSerializedPathOperation(pendingAtomicWriteTails, filePath, fn);\n}\n\n/** Remove one invocation's temporary path without masking the original write/rename failure. */\nfunction removeTemporaryPathSync(tmpPath: string): void {\n\ttry {\n\t\tunlinkSync(tmpPath);\n\t} catch {\n\t\t// The rename may have consumed the path, or another failure may have prevented its creation.\n\t}\n}\n\nasync function removeTemporaryPath(tmpPath: string): Promise<void> {\n\ttry {\n\t\tawait fsPromises.unlink(tmpPath);\n\t} catch {\n\t\t// The rename may have consumed the path, or another failure may have prevented its creation.\n\t}\n}\n\nexport function writeFileAtomicSync(filePath: string, content: string, options?: AtomicFileWriteOptions): void {\n\tconst fs = options?.fs ?? nodeFs;\n\tfs.mkdirSync(dirname(filePath), { recursive: true });\n\tconst tmpPath = temporaryPath(filePath);\n\tlet renamed = false;\n\ttry {\n\t\t// `wx` makes a nonce collision harmless: never truncate another writer's temporary file.\n\t\tfs.writeFileSync(tmpPath, content, { encoding: \"utf-8\", flag: \"wx\", mode: options?.mode });\n\t\trenameSyncWithRetry(tmpPath, filePath, fs);\n\t\trenamed = true;\n\t} finally {\n\t\tif (!renamed) removeTemporaryPathSync(tmpPath);\n\t}\n}\n\n/** Async counterpart of {@link writeFileAtomicSync}. */\nexport async function writeFileAtomic(\n\tfilePath: string,\n\tcontent: string,\n\toptions?: AtomicFileWriteOptions,\n): Promise<void> {\n\tawait withSerializedAtomicWrite(filePath, async () => {\n\t\tawait fsPromises.mkdir(dirname(filePath), { recursive: true });\n\t\tconst tmpPath = temporaryPath(filePath);\n\t\tlet renamed = false;\n\t\ttry {\n\t\t\t// `wx` makes a nonce collision harmless: never truncate another writer's temporary file.\n\t\t\tawait fsPromises.writeFile(tmpPath, content, { encoding: \"utf-8\", flag: \"wx\", mode: options?.mode });\n\t\t\tawait renameWithRetry(tmpPath, filePath);\n\t\t\trenamed = true;\n\t\t} finally {\n\t\t\tif (!renamed) await removeTemporaryPath(tmpPath);\n\t\t}\n\t});\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injection seam for the narrow set of synchronous mutating filesystem operations that durable
|
|
3
|
+
* stores actually issue on their write path (`mkdirSync`, `writeFileSync`, `renameSync`,
|
|
4
|
+
* `unlinkSync`). Production code always uses {@link nodeFs}, the real `node:fs` bindings, via each
|
|
5
|
+
* store's `fs` constructor option defaulting to it — so wiring this seam changes nothing for any
|
|
6
|
+
* existing caller that does not pass `fs` explicitly.
|
|
7
|
+
*
|
|
8
|
+
* The destructive-testing harness (`test-destructive/harness/faultable-fs.ts`) implements this same
|
|
9
|
+
* interface with a fault-injecting variant (`failAtOp`, `tornWriteAtOp`, `enospcAfterBytes`) to drive
|
|
10
|
+
* crash-consistency sweeps without touching real disks or real timers. Read ops are intentionally
|
|
11
|
+
* excluded: a "crash" in this model is always a `node:fs`-mutating operation not completing; restart
|
|
12
|
+
* recovery always reads the real, unfaulted surviving files.
|
|
13
|
+
*/
|
|
14
|
+
export type FaultableFsWriteFileOptions = {
|
|
15
|
+
encoding?: "utf-8";
|
|
16
|
+
flag?: string;
|
|
17
|
+
mode?: number;
|
|
18
|
+
} | "utf-8";
|
|
19
|
+
/** The mutating fs primitives a durable store's write path issues, kept 1:1 with actual call sites. */
|
|
20
|
+
export interface FaultableFs {
|
|
21
|
+
mkdirSync(path: string, options: {
|
|
22
|
+
recursive: true;
|
|
23
|
+
}): void;
|
|
24
|
+
writeFileSync(path: string, data: string, options?: FaultableFsWriteFileOptions): void;
|
|
25
|
+
renameSync(oldPath: string, newPath: string): void;
|
|
26
|
+
unlinkSync(path: string): void;
|
|
27
|
+
}
|
|
28
|
+
/** The real `node:fs` bindings, wrapped to satisfy {@link FaultableFs}. Zero behavior change vs. calling `node:fs` directly. */
|
|
29
|
+
export declare const nodeFs: FaultableFs;
|
|
30
|
+
//# sourceMappingURL=faultable-fs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"faultable-fs.d.ts","sourceRoot":"","sources":["../../../src/core/util/faultable-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,MAAM,MAAM,2BAA2B,GAAG;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC;AAEzG,uGAAuG;AACvG,MAAM,WAAW,WAAW;IAC3B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,SAAS,EAAE,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5D,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IACvF,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACnD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,gIAAgI;AAChI,eAAO,MAAM,MAAM,EAAE,WAapB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injection seam for the narrow set of synchronous mutating filesystem operations that durable
|
|
3
|
+
* stores actually issue on their write path (`mkdirSync`, `writeFileSync`, `renameSync`,
|
|
4
|
+
* `unlinkSync`). Production code always uses {@link nodeFs}, the real `node:fs` bindings, via each
|
|
5
|
+
* store's `fs` constructor option defaulting to it — so wiring this seam changes nothing for any
|
|
6
|
+
* existing caller that does not pass `fs` explicitly.
|
|
7
|
+
*
|
|
8
|
+
* The destructive-testing harness (`test-destructive/harness/faultable-fs.ts`) implements this same
|
|
9
|
+
* interface with a fault-injecting variant (`failAtOp`, `tornWriteAtOp`, `enospcAfterBytes`) to drive
|
|
10
|
+
* crash-consistency sweeps without touching real disks or real timers. Read ops are intentionally
|
|
11
|
+
* excluded: a "crash" in this model is always a `node:fs`-mutating operation not completing; restart
|
|
12
|
+
* recovery always reads the real, unfaulted surviving files.
|
|
13
|
+
*/
|
|
14
|
+
import { mkdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
15
|
+
/** The real `node:fs` bindings, wrapped to satisfy {@link FaultableFs}. Zero behavior change vs. calling `node:fs` directly. */
|
|
16
|
+
export const nodeFs = {
|
|
17
|
+
mkdirSync: (path, options) => {
|
|
18
|
+
mkdirSync(path, options);
|
|
19
|
+
},
|
|
20
|
+
writeFileSync: (path, data, options) => {
|
|
21
|
+
writeFileSync(path, data, options);
|
|
22
|
+
},
|
|
23
|
+
renameSync: (oldPath, newPath) => {
|
|
24
|
+
renameSync(oldPath, newPath);
|
|
25
|
+
},
|
|
26
|
+
unlinkSync: (path) => {
|
|
27
|
+
unlinkSync(path);
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=faultable-fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"faultable-fs.js","sourceRoot":"","sources":["../../../src/core/util/faultable-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAY3E,gIAAgI;AAChI,MAAM,CAAC,MAAM,MAAM,GAAgB;IAClC,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;QAC5B,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1B,CAAC;IACD,aAAa,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QACtC,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;QAChC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;QACpB,UAAU,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;CACD,CAAC","sourcesContent":["/**\n * Injection seam for the narrow set of synchronous mutating filesystem operations that durable\n * stores actually issue on their write path (`mkdirSync`, `writeFileSync`, `renameSync`,\n * `unlinkSync`). Production code always uses {@link nodeFs}, the real `node:fs` bindings, via each\n * store's `fs` constructor option defaulting to it — so wiring this seam changes nothing for any\n * existing caller that does not pass `fs` explicitly.\n *\n * The destructive-testing harness (`test-destructive/harness/faultable-fs.ts`) implements this same\n * interface with a fault-injecting variant (`failAtOp`, `tornWriteAtOp`, `enospcAfterBytes`) to drive\n * crash-consistency sweeps without touching real disks or real timers. Read ops are intentionally\n * excluded: a \"crash\" in this model is always a `node:fs`-mutating operation not completing; restart\n * recovery always reads the real, unfaulted surviving files.\n */\n\nimport { mkdirSync, renameSync, unlinkSync, writeFileSync } from \"node:fs\";\n\nexport type FaultableFsWriteFileOptions = { encoding?: \"utf-8\"; flag?: string; mode?: number } | \"utf-8\";\n\n/** The mutating fs primitives a durable store's write path issues, kept 1:1 with actual call sites. */\nexport interface FaultableFs {\n\tmkdirSync(path: string, options: { recursive: true }): void;\n\twriteFileSync(path: string, data: string, options?: FaultableFsWriteFileOptions): void;\n\trenameSync(oldPath: string, newPath: string): void;\n\tunlinkSync(path: string): void;\n}\n\n/** The real `node:fs` bindings, wrapped to satisfy {@link FaultableFs}. Zero behavior change vs. calling `node:fs` directly. */\nexport const nodeFs: FaultableFs = {\n\tmkdirSync: (path, options) => {\n\t\tmkdirSync(path, options);\n\t},\n\twriteFileSync: (path, data, options) => {\n\t\twriteFileSync(path, data, options);\n\t},\n\trenameSync: (oldPath, newPath) => {\n\t\trenameSync(oldPath, newPath);\n\t},\n\tunlinkSync: (path) => {\n\t\tunlinkSync(path);\n\t},\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-dialogs-controller.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/auth-dialogs-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAgB,KAAK,KAAK,EAAgD,MAAM,mBAAmB,CAAC;AAC3G,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAIN,kBAAkB,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,KAAK,sBAAsB,EAA0B,MAAM,iCAAiC,CAAC;AAMtG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAgBlE,wBAAgB,qBAAqB,CACpC,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,EACrC,kBAAkB,GAAE,WAAW,CAAC,MAAM,CAA4B,GAChE,OAAO,CAQT;AAED,MAAM,WAAW,uBAAuB;IACvC,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,IAAI,KAAK;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7F,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,IAAI,IAAI,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IACxC,SAAS,IAAI,SAAS,CAAC;IACvB,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,gBAAgB,IAAI,IAAI,CAAC;IACzB,uBAAuB,IAAI,IAAI,CAAC;IAChC,uCAAuC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAClE,qBAAqB,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACrE;AAED,MAAM,WAAW,yBAAyB;IACzC,UAAU,IAAI,YAAY,CAAC;IAC3B,EAAE,EAAE,uBAAuB,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvF,kBAAkB,CAAC,EAAE,OAAO,kBAAkB,CAAC;CAC/C;AAED,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,iBAAiB,CAAmC;IAC5D,OAAO,CAAC,0BAA0B,CAA2B;IAC7D,OAAO,CAAC,gCAAgC,CAAS;IACjD,OAAO,CAAC,yBAAyB,CAA2B;IAE5D,YAAY,IAAI,EAAE,yBAAyB,EAE1C;IAED,OAAO,KAAK,OAAO,GAElB;IACD,OAAO,KAAK,EAAE,GAEb;IAED,kBAAkB,IAAI,IAAI,CAQzB;IAED,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,uBAAuB;IAM/B,OAAO,CAAC,4BAA4B;IAMpC,OAAO,CAAC,kBAAkB;YAMZ,qBAAqB;IAkBnC,OAAO,CAAC,uBAAuB;
|
|
1
|
+
{"version":3,"file":"auth-dialogs-controller.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/auth-dialogs-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -121,6 +121,7 @@ export class AuthDialogsController {
|
|
|
121
121
|
id: provider.id,
|
|
122
122
|
name: provider.name,
|
|
123
123
|
authType: "oauth",
|
|
124
|
+
loginLabel: provider.loginLabel,
|
|
124
125
|
}));
|
|
125
126
|
const modelProviders = new Set(this.session.modelRegistry.getAll().map((model) => model.provider));
|
|
126
127
|
for (const providerId of modelProviders) {
|