@caupulican/pi-adaptative 0.81.39 → 0.81.40
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 +52 -0
- package/README.md +2 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +2 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +2 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +3 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +9 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +290 -107
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +357 -122
- package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +2 -2
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +9 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-directory-layout.d.ts +15 -0
- package/dist/core/agent-directory-layout.d.ts.map +1 -0
- package/dist/core/agent-directory-layout.js +72 -0
- package/dist/core/agent-directory-layout.js.map +1 -0
- package/dist/core/agent-paths.d.ts +19 -2
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +67 -4
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +52 -8
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +397 -79
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +71 -136
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +477 -1318
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/approval-gate.d.ts +3 -2
- package/dist/core/autonomy/approval-gate.d.ts.map +1 -1
- package/dist/core/autonomy/approval-gate.js +6 -28
- package/dist/core/autonomy/approval-gate.js.map +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
- package/dist/core/autonomy/bounded-completion.js +1 -1
- package/dist/core/autonomy/bounded-completion.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts +20 -12
- package/dist/core/autonomy/contracts.d.ts.map +1 -1
- package/dist/core/autonomy/contracts.js.map +1 -1
- package/dist/core/autonomy/foreground-envelope.d.ts +8 -2
- package/dist/core/autonomy/foreground-envelope.d.ts.map +1 -1
- package/dist/core/autonomy/foreground-envelope.js +8 -25
- package/dist/core/autonomy/foreground-envelope.js.map +1 -1
- package/dist/core/autonomy/gates.d.ts.map +1 -1
- package/dist/core/autonomy/gates.js +8 -10
- package/dist/core/autonomy/gates.js.map +1 -1
- package/dist/core/autonomy/lane-private-paths.d.ts +2 -0
- package/dist/core/autonomy/lane-private-paths.d.ts.map +1 -0
- package/dist/core/autonomy/lane-private-paths.js +16 -0
- package/dist/core/autonomy/lane-private-paths.js.map +1 -0
- package/dist/core/autonomy/lane-tool-surface.d.ts +10 -0
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +46 -8
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/lane-tracker.d.ts +14 -0
- package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tracker.js +38 -0
- package/dist/core/autonomy/lane-tracker.js.map +1 -1
- package/dist/core/autonomy/risk-assessment.d.ts +1 -2
- package/dist/core/autonomy/risk-assessment.d.ts.map +1 -1
- package/dist/core/autonomy/risk-assessment.js +1 -123
- package/dist/core/autonomy/risk-assessment.js.map +1 -1
- package/dist/core/autonomy/session-lane-record.d.ts +4 -4
- package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
- package/dist/core/autonomy/session-lane-record.js +16 -29
- package/dist/core/autonomy/session-lane-record.js.map +1 -1
- package/dist/core/autonomy/telemetry-events.d.ts +1 -1
- package/dist/core/autonomy/telemetry-events.d.ts.map +1 -1
- package/dist/core/autonomy/telemetry-events.js +1 -1
- package/dist/core/autonomy/telemetry-events.js.map +1 -1
- package/dist/core/autonomy-telemetry.d.ts +7 -7
- package/dist/core/autonomy-telemetry.d.ts.map +1 -1
- package/dist/core/autonomy-telemetry.js +9 -9
- package/dist/core/autonomy-telemetry.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +54 -236
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +140 -1273
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/capability-contract.d.ts +4 -0
- package/dist/core/capability-contract.d.ts.map +1 -0
- package/dist/core/capability-contract.js +28 -0
- package/dist/core/capability-contract.js.map +1 -0
- package/dist/core/compaction-controller.d.ts +90 -0
- package/dist/core/compaction-controller.d.ts.map +1 -0
- package/dist/core/compaction-controller.js +452 -0
- package/dist/core/compaction-controller.js.map +1 -0
- package/dist/core/compaction-support.d.ts +12 -11
- package/dist/core/compaction-support.d.ts.map +1 -1
- package/dist/core/compaction-support.js.map +1 -1
- package/dist/core/context/context-artifacts.d.ts +6 -2
- package/dist/core/context/context-artifacts.d.ts.map +1 -1
- package/dist/core/context/context-artifacts.js +34 -2
- package/dist/core/context/context-artifacts.js.map +1 -1
- package/dist/core/context/context-store-retention.d.ts +8 -2
- package/dist/core/context/context-store-retention.d.ts.map +1 -1
- package/dist/core/context/context-store-retention.js +158 -35
- package/dist/core/context/context-store-retention.js.map +1 -1
- package/dist/core/context/okf-memory.d.ts.map +1 -1
- package/dist/core/context/okf-memory.js +9 -11
- package/dist/core/context/okf-memory.js.map +1 -1
- package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -1
- package/dist/core/context/sqlite-runtime-index.js +6 -8
- package/dist/core/context/sqlite-runtime-index.js.map +1 -1
- package/dist/core/context-gc.d.ts +3 -0
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +10 -5
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts.map +1 -1
- package/dist/core/context-pipeline.js +9 -4
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +1 -0
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/delegation/managed-lane-controller.d.ts +34 -0
- package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -0
- package/dist/core/delegation/managed-lane-controller.js +217 -0
- package/dist/core/delegation/managed-lane-controller.js.map +1 -0
- package/dist/core/delegation/session-worker-claim.d.ts +44 -0
- package/dist/core/delegation/session-worker-claim.d.ts.map +1 -0
- package/dist/core/delegation/session-worker-claim.js +98 -0
- package/dist/core/delegation/session-worker-claim.js.map +1 -0
- package/dist/core/delegation/worker-actions.d.ts +7 -5
- package/dist/core/delegation/worker-actions.d.ts.map +1 -1
- package/dist/core/delegation/worker-actions.js +20 -4
- package/dist/core/delegation/worker-actions.js.map +1 -1
- package/dist/core/delegation/{worker-result.d.ts → worker-claim.d.ts} +13 -13
- package/dist/core/delegation/worker-claim.d.ts.map +1 -0
- package/dist/core/delegation/{worker-result.js → worker-claim.js} +61 -51
- package/dist/core/delegation/worker-claim.js.map +1 -0
- package/dist/core/delegation/worker-delegation-controller.d.ts +110 -0
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -0
- package/dist/core/delegation/worker-delegation-controller.js +861 -0
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -0
- package/dist/core/delegation/worker-delegation-request.d.ts +11 -0
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -0
- package/dist/core/delegation/worker-delegation-request.js +2 -0
- package/dist/core/delegation/worker-delegation-request.js.map +1 -0
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts +40 -0
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -0
- package/dist/core/delegation/worker-dispatch-scheduler.js +93 -0
- package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -0
- package/dist/core/delegation/worker-execution-policy.d.ts +62 -0
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -0
- package/dist/core/delegation/worker-execution-policy.js +160 -0
- package/dist/core/delegation/worker-execution-policy.js.map +1 -0
- package/dist/core/delegation/worker-lane-projection.d.ts +14 -0
- package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -0
- package/dist/core/delegation/worker-lane-projection.js +100 -0
- package/dist/core/delegation/worker-lane-projection.js.map +1 -0
- package/dist/core/delegation/worker-lifecycle.d.ts +97 -0
- package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -0
- package/dist/core/delegation/worker-lifecycle.js +339 -0
- package/dist/core/delegation/worker-lifecycle.js.map +1 -0
- package/dist/core/delegation/worker-notification-coordinator.d.ts +36 -0
- package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-notification-coordinator.js +90 -0
- package/dist/core/delegation/worker-notification-coordinator.js.map +1 -0
- package/dist/core/delegation/worker-profile-resolver.d.ts +55 -0
- package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -0
- package/dist/core/delegation/worker-profile-resolver.js +113 -0
- package/dist/core/delegation/worker-profile-resolver.js.map +1 -0
- package/dist/core/delegation/worker-runner.d.ts +25 -14
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +122 -53
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-task-label.d.ts +3 -0
- package/dist/core/delegation/worker-task-label.d.ts.map +1 -0
- package/dist/core/delegation/worker-task-label.js +11 -0
- package/dist/core/delegation/worker-task-label.js.map +1 -0
- package/dist/core/doctor.d.ts +8 -0
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +32 -1
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +5 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +50 -15
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +6 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/storage.d.ts +8 -0
- package/dist/core/extensions/storage.d.ts.map +1 -0
- package/dist/core/extensions/storage.js +28 -0
- package/dist/core/extensions/storage.js.map +1 -0
- package/dist/core/extensions/types.d.ts +70 -21
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/failure-corpus.d.ts +1 -15
- package/dist/core/failure-corpus.d.ts.map +1 -1
- package/dist/core/failure-corpus.js +9 -37
- package/dist/core/failure-corpus.js.map +1 -1
- package/dist/core/foreground-recovery-controller.d.ts +52 -0
- package/dist/core/foreground-recovery-controller.d.ts.map +1 -0
- package/dist/core/foreground-recovery-controller.js +111 -0
- package/dist/core/foreground-recovery-controller.js.map +1 -0
- package/dist/core/gateways/channel-provider.d.ts +3 -0
- package/dist/core/gateways/channel-provider.d.ts.map +1 -1
- package/dist/core/gateways/channel-provider.js +31 -6
- package/dist/core/gateways/channel-provider.js.map +1 -1
- package/dist/core/goals/goal-acceptance.d.ts +11 -0
- package/dist/core/goals/goal-acceptance.d.ts.map +1 -0
- package/dist/core/goals/goal-acceptance.js +25 -0
- package/dist/core/goals/goal-acceptance.js.map +1 -0
- package/dist/core/goals/goal-auto-continue-controller.d.ts +27 -0
- package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -0
- package/dist/core/goals/goal-auto-continue-controller.js +93 -0
- package/dist/core/goals/goal-auto-continue-controller.js.map +1 -0
- package/dist/core/goals/goal-continuation-controller.d.ts +1 -1
- package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-controller.js +10 -0
- package/dist/core/goals/goal-continuation-controller.js.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.d.ts +1 -1
- package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.js +6 -6
- package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
- package/dist/core/goals/goal-lifecycle.d.ts +20 -0
- package/dist/core/goals/goal-lifecycle.d.ts.map +1 -0
- package/dist/core/goals/goal-lifecycle.js +17 -0
- package/dist/core/goals/goal-lifecycle.js.map +1 -0
- package/dist/core/goals/goal-runtime-snapshot.d.ts +11 -9
- package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
- package/dist/core/goals/goal-runtime-snapshot.js +10 -8
- package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
- package/dist/core/goals/goal-state.d.ts +1 -0
- package/dist/core/goals/goal-state.d.ts.map +1 -1
- package/dist/core/goals/goal-state.js +7 -10
- package/dist/core/goals/goal-state.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts +8 -6
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +11 -41
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/goals/session-goal-state.d.ts +2 -4
- package/dist/core/goals/session-goal-state.d.ts.map +1 -1
- package/dist/core/goals/session-goal-state.js +10 -33
- package/dist/core/goals/session-goal-state.js.map +1 -1
- package/dist/core/human-input.d.ts +100 -0
- package/dist/core/human-input.d.ts.map +1 -0
- package/dist/core/human-input.js +362 -0
- package/dist/core/human-input.js.map +1 -0
- package/dist/core/index.d.ts +9 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +9 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/{telemetry.d.ts → install-telemetry.d.ts} +1 -1
- package/dist/core/install-telemetry.d.ts.map +1 -0
- package/dist/core/{telemetry.js → install-telemetry.js} +1 -1
- package/dist/core/install-telemetry.js.map +1 -0
- package/dist/core/keybindings.d.ts +17 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +24 -6
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/learning/learning-audit.d.ts +2 -4
- package/dist/core/learning/learning-audit.d.ts.map +1 -1
- package/dist/core/learning/learning-audit.js +9 -29
- package/dist/core/learning/learning-audit.js.map +1 -1
- package/dist/core/learning/learning-gate.d.ts.map +1 -1
- package/dist/core/learning/learning-gate.js +1 -6
- package/dist/core/learning/learning-gate.js.map +1 -1
- package/dist/core/learning/session-learning-decision.d.ts +2 -4
- package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
- package/dist/core/learning/session-learning-decision.js +9 -29
- package/dist/core/learning/session-learning-decision.js.map +1 -1
- package/dist/core/memory-controller.d.ts.map +1 -1
- package/dist/core/memory-controller.js +4 -4
- package/dist/core/memory-controller.js.map +1 -1
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +1 -0
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +6 -9
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-router/intent-classifier.d.ts +1 -4
- package/dist/core/model-router/intent-classifier.d.ts.map +1 -1
- package/dist/core/model-router/intent-classifier.js +1 -156
- package/dist/core/model-router/intent-classifier.js.map +1 -1
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +2 -2
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/model-selection-controller.d.ts +4 -4
- package/dist/core/model-selection-controller.d.ts.map +1 -1
- package/dist/core/model-selection-controller.js.map +1 -1
- package/dist/core/model-tool-protocol.d.ts +23 -0
- package/dist/core/model-tool-protocol.d.ts.map +1 -0
- package/dist/core/model-tool-protocol.js +43 -0
- package/dist/core/model-tool-protocol.js.map +1 -0
- package/dist/core/models/adaptation-store.d.ts +4 -6
- package/dist/core/models/adaptation-store.d.ts.map +1 -1
- package/dist/core/models/adaptation-store.js +95 -83
- package/dist/core/models/adaptation-store.js.map +1 -1
- package/dist/core/models/fitness-store.d.ts +2 -12
- package/dist/core/models/fitness-store.d.ts.map +1 -1
- package/dist/core/models/fitness-store.js +84 -57
- package/dist/core/models/fitness-store.js.map +1 -1
- package/dist/core/models/host-state-store.d.ts +34 -0
- package/dist/core/models/host-state-store.d.ts.map +1 -0
- package/dist/core/models/host-state-store.js +86 -0
- package/dist/core/models/host-state-store.js.map +1 -0
- package/dist/core/orchestration/agent-resume.d.ts +24 -0
- package/dist/core/orchestration/agent-resume.d.ts.map +1 -0
- package/dist/core/orchestration/agent-resume.js +90 -0
- package/dist/core/orchestration/agent-resume.js.map +1 -0
- package/dist/core/orchestration/capability-gateway.d.ts +61 -0
- package/dist/core/orchestration/capability-gateway.d.ts.map +1 -0
- package/dist/core/orchestration/capability-gateway.js +152 -0
- package/dist/core/orchestration/capability-gateway.js.map +1 -0
- package/dist/core/orchestration/contracts.d.ts +343 -0
- package/dist/core/orchestration/contracts.d.ts.map +1 -0
- package/dist/core/orchestration/contracts.js +135 -0
- package/dist/core/orchestration/contracts.js.map +1 -0
- package/dist/core/orchestration/delegation-ledger.d.ts +56 -0
- package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -0
- package/dist/core/orchestration/delegation-ledger.js +197 -0
- package/dist/core/orchestration/delegation-ledger.js.map +1 -0
- package/dist/core/orchestration/event-store.d.ts +83 -0
- package/dist/core/orchestration/event-store.d.ts.map +1 -0
- package/dist/core/orchestration/event-store.js +560 -0
- package/dist/core/orchestration/event-store.js.map +1 -0
- package/dist/core/orchestration/lane-tool-manifests.d.ts +9 -0
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -0
- package/dist/core/orchestration/lane-tool-manifests.js +37 -0
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -0
- package/dist/core/orchestration/model-binding.d.ts +15 -0
- package/dist/core/orchestration/model-binding.d.ts.map +1 -0
- package/dist/core/orchestration/model-binding.js +29 -0
- package/dist/core/orchestration/model-binding.js.map +1 -0
- package/dist/core/orchestration/policy-compiler.d.ts +49 -0
- package/dist/core/orchestration/policy-compiler.d.ts.map +1 -0
- package/dist/core/orchestration/policy-compiler.js +191 -0
- package/dist/core/orchestration/policy-compiler.js.map +1 -0
- package/dist/core/orchestration/policy-gate.d.ts +18 -0
- package/dist/core/orchestration/policy-gate.d.ts.map +1 -0
- package/dist/core/orchestration/policy-gate.js +24 -0
- package/dist/core/orchestration/policy-gate.js.map +1 -0
- package/dist/core/orchestration/profile-registry.d.ts +51 -0
- package/dist/core/orchestration/profile-registry.d.ts.map +1 -0
- package/dist/core/orchestration/profile-registry.js +393 -0
- package/dist/core/orchestration/profile-registry.js.map +1 -0
- package/dist/core/orchestration/profile-store.d.ts +31 -0
- package/dist/core/orchestration/profile-store.d.ts.map +1 -0
- package/dist/core/orchestration/profile-store.js +136 -0
- package/dist/core/orchestration/profile-store.js.map +1 -0
- package/dist/core/orchestration/risk-budget.d.ts +9 -0
- package/dist/core/orchestration/risk-budget.d.ts.map +1 -0
- package/dist/core/orchestration/risk-budget.js +48 -0
- package/dist/core/orchestration/risk-budget.js.map +1 -0
- package/dist/core/orchestration/task-runtime.d.ts +168 -0
- package/dist/core/orchestration/task-runtime.d.ts.map +1 -0
- package/dist/core/orchestration/task-runtime.js +1600 -0
- package/dist/core/orchestration/task-runtime.js.map +1 -0
- package/dist/core/orchestration/work-state-projection.d.ts +32 -0
- package/dist/core/orchestration/work-state-projection.d.ts.map +1 -0
- package/dist/core/orchestration/work-state-projection.js +116 -0
- package/dist/core/orchestration/work-state-projection.js.map +1 -0
- package/dist/core/orchestration/worker-execution-contract.d.ts +21 -0
- package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -0
- package/dist/core/orchestration/worker-execution-contract.js +179 -0
- package/dist/core/orchestration/worker-execution-contract.js.map +1 -0
- package/dist/core/orchestration/worker-result-adapter.d.ts +21 -0
- package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -0
- package/dist/core/orchestration/worker-result-adapter.js +109 -0
- package/dist/core/orchestration/worker-result-adapter.js.map +1 -0
- package/dist/core/process-identity.d.ts +11 -0
- package/dist/core/process-identity.d.ts.map +1 -0
- package/dist/core/process-identity.js +26 -0
- package/dist/core/process-identity.js.map +1 -0
- package/dist/core/process-matrix/codes.d.ts +14 -3
- package/dist/core/process-matrix/codes.d.ts.map +1 -1
- package/dist/core/process-matrix/codes.js.map +1 -1
- package/dist/core/process-matrix/resume-launcher.d.ts +26 -0
- package/dist/core/process-matrix/resume-launcher.d.ts.map +1 -0
- package/dist/core/process-matrix/resume-launcher.js +62 -0
- package/dist/core/process-matrix/resume-launcher.js.map +1 -0
- package/dist/core/process-matrix/runtime.d.ts +37 -22
- package/dist/core/process-matrix/runtime.d.ts.map +1 -1
- package/dist/core/process-matrix/runtime.js +399 -76
- package/dist/core/process-matrix/runtime.js.map +1 -1
- package/dist/core/process-matrix/store.d.ts +5 -2
- package/dist/core/process-matrix/store.d.ts.map +1 -1
- package/dist/core/process-matrix/store.js +123 -14
- package/dist/core/process-matrix/store.js.map +1 -1
- package/dist/core/process-matrix/supervisor.d.ts +10 -7
- package/dist/core/process-matrix/supervisor.d.ts.map +1 -1
- package/dist/core/process-matrix/supervisor.js +45 -14
- package/dist/core/process-matrix/supervisor.js.map +1 -1
- package/dist/core/profile-registry.d.ts.map +1 -1
- package/dist/core/profile-registry.js +6 -8
- package/dist/core/profile-registry.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +4 -4
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +2 -1
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/reload-blockers.d.ts.map +1 -1
- package/dist/core/reload-blockers.js +6 -8
- package/dist/core/reload-blockers.js.map +1 -1
- package/dist/core/research/evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/evidence-bundle.js +1 -6
- package/dist/core/research/evidence-bundle.js.map +1 -1
- package/dist/core/research/lane-model-resolver.d.ts +33 -0
- package/dist/core/research/lane-model-resolver.d.ts.map +1 -0
- package/dist/core/research/lane-model-resolver.js +65 -0
- package/dist/core/research/lane-model-resolver.js.map +1 -0
- package/dist/core/research/model-fitness-controller.d.ts +38 -0
- package/dist/core/research/model-fitness-controller.d.ts.map +1 -0
- package/dist/core/research/model-fitness-controller.js +106 -0
- package/dist/core/research/model-fitness-controller.js.map +1 -0
- package/dist/core/research/model-fitness.d.ts +1 -1
- package/dist/core/research/model-fitness.d.ts.map +1 -1
- package/dist/core/research/model-fitness.js +4 -4
- package/dist/core/research/model-fitness.js.map +1 -1
- package/dist/core/research/research-gate.d.ts.map +1 -1
- package/dist/core/research/research-gate.js +7 -7
- package/dist/core/research/research-gate.js.map +1 -1
- package/dist/core/research/research-lane-controller.d.ts +62 -0
- package/dist/core/research/research-lane-controller.d.ts.map +1 -0
- package/dist/core/research/research-lane-controller.js +292 -0
- package/dist/core/research/research-lane-controller.js.map +1 -0
- package/dist/core/research/session-evidence-bundle.d.ts +2 -4
- package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/session-evidence-bundle.js +10 -46
- package/dist/core/research/session-evidence-bundle.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +7 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/risk-classifier.d.ts +6 -0
- package/dist/core/risk-classifier.d.ts.map +1 -0
- package/dist/core/risk-classifier.js +225 -0
- package/dist/core/risk-classifier.js.map +1 -0
- package/dist/core/runtime-builder.d.ts +26 -20
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +237 -178
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/sdk.d.ts +6 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +61 -24
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-analytics.d.ts.map +1 -1
- package/dist/core/session-analytics.js +28 -1
- package/dist/core/session-analytics.js.map +1 -1
- package/dist/core/session-image-store.d.ts +33 -0
- package/dist/core/session-image-store.d.ts.map +1 -0
- package/dist/core/session-image-store.js +283 -0
- package/dist/core/session-image-store.js.map +1 -0
- package/dist/core/session-role.d.ts +6 -4
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js +10 -4
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/session-snapshot.d.ts +34 -0
- package/dist/core/session-snapshot.d.ts.map +1 -0
- package/dist/core/session-snapshot.js +68 -0
- package/dist/core/session-snapshot.js.map +1 -0
- package/dist/core/session-supervision-runtime.d.ts +31 -0
- package/dist/core/session-supervision-runtime.d.ts.map +1 -0
- package/dist/core/session-supervision-runtime.js +97 -0
- package/dist/core/session-supervision-runtime.js.map +1 -0
- package/dist/core/settings-manager.d.ts +9 -4
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +80 -28
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tasks/session-task-state.d.ts +2 -4
- package/dist/core/tasks/session-task-state.d.ts.map +1 -1
- package/dist/core/tasks/session-task-state.js +10 -28
- package/dist/core/tasks/session-task-state.js.map +1 -1
- package/dist/core/tasks/task-projection.d.ts +20 -0
- package/dist/core/tasks/task-projection.d.ts.map +1 -0
- package/dist/core/tasks/task-projection.js +47 -0
- package/dist/core/tasks/task-projection.js.map +1 -0
- package/dist/core/tasks/task-state.d.ts +4 -0
- package/dist/core/tasks/task-state.d.ts.map +1 -1
- package/dist/core/tasks/task-state.js +28 -11
- package/dist/core/tasks/task-state.js.map +1 -1
- package/dist/core/tool-capability-policy.d.ts +13 -0
- package/dist/core/tool-capability-policy.d.ts.map +1 -0
- package/dist/core/tool-capability-policy.js +85 -0
- package/dist/core/tool-capability-policy.js.map +1 -0
- package/dist/core/tool-protocol-controller.d.ts +91 -0
- package/dist/core/tool-protocol-controller.d.ts.map +1 -0
- package/dist/core/tool-protocol-controller.js +512 -0
- package/dist/core/tool-protocol-controller.js.map +1 -0
- package/dist/core/tool-recovery-log-records.d.ts +2 -3
- package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
- package/dist/core/tool-recovery-log-records.js +9 -35
- package/dist/core/tool-recovery-log-records.js.map +1 -1
- package/dist/core/tool-selection/tool-performance-store.d.ts +3 -7
- package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -1
- package/dist/core/tool-selection/tool-performance-store.js +97 -138
- package/dist/core/tool-selection/tool-performance-store.js.map +1 -1
- package/dist/core/tools/ask-question.d.ts +124 -0
- package/dist/core/tools/ask-question.d.ts.map +1 -0
- package/dist/core/tools/ask-question.js +693 -0
- package/dist/core/tools/ask-question.js.map +1 -0
- package/dist/core/tools/delegate-status.d.ts +31 -3
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +149 -29
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +15 -13
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +108 -23
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/extensionify.d.ts.map +1 -1
- package/dist/core/tools/extensionify.js +1 -0
- package/dist/core/tools/extensionify.js.map +1 -1
- package/dist/core/tools/goal.d.ts +5 -5
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +10 -10
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/model-fitness.d.ts.map +1 -1
- package/dist/core/tools/model-fitness.js +2 -2
- package/dist/core/tools/model-fitness.js.map +1 -1
- package/dist/core/tools/orchestration-panel.d.ts +43 -0
- package/dist/core/tools/orchestration-panel.d.ts.map +1 -0
- package/dist/core/tools/orchestration-panel.js +168 -0
- package/dist/core/tools/orchestration-panel.js.map +1 -0
- package/dist/core/tools/run-process.d.ts +26 -0
- package/dist/core/tools/run-process.d.ts.map +1 -0
- package/dist/core/tools/run-process.js +138 -0
- package/dist/core/tools/run-process.js.map +1 -0
- package/dist/core/tools/task-steps.d.ts +2 -0
- package/dist/core/tools/task-steps.d.ts.map +1 -1
- package/dist/core/tools/task-steps.js +102 -0
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tmux-dispatch.d.ts +3 -5
- package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
- package/dist/core/tools/tmux-dispatch.js +4 -4
- package/dist/core/tools/tmux-dispatch.js.map +1 -1
- package/dist/core/tools/windows-shell-engine.d.ts.map +1 -1
- package/dist/core/tools/windows-shell-engine.js +4 -6
- package/dist/core/tools/windows-shell-engine.js.map +1 -1
- package/dist/core/util/bounded-jsonl.d.ts +10 -0
- package/dist/core/util/bounded-jsonl.d.ts.map +1 -0
- package/dist/core/util/bounded-jsonl.js +75 -0
- package/dist/core/util/bounded-jsonl.js.map +1 -0
- package/dist/core/util/value-guards.d.ts +5 -0
- package/dist/core/util/value-guards.d.ts.map +1 -0
- package/dist/core/util/value-guards.js +12 -0
- package/dist/core/util/value-guards.js.map +1 -0
- package/dist/core/worktree-sync/store.d.ts +3 -3
- package/dist/core/worktree-sync/store.d.ts.map +1 -1
- package/dist/core/worktree-sync/store.js +10 -5
- package/dist/core/worktree-sync/store.js.map +1 -1
- package/dist/index.d.ts +13 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +128 -44
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +4 -6
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +186 -28
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/clipboard-input.d.ts +7 -1
- package/dist/modes/interactive/clipboard-input.d.ts.map +1 -1
- package/dist/modes/interactive/clipboard-input.js +44 -6
- package/dist/modes/interactive/clipboard-input.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +2 -2
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/config-backup.d.ts.map +1 -1
- package/dist/modes/interactive/config-backup.js +5 -4
- package/dist/modes/interactive/config-backup.js.map +1 -1
- package/dist/modes/interactive/extension-ui-host.d.ts +14 -0
- package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
- package/dist/modes/interactive/extension-ui-host.js +76 -15
- package/dist/modes/interactive/extension-ui-host.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +63 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/key-handlers.d.ts.map +1 -1
- package/dist/modes/interactive/key-handlers.js +1 -1
- package/dist/modes/interactive/key-handlers.js.map +1 -1
- package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -1
- package/dist/modes/interactive/profile-menu-controller.js +7 -7
- package/dist/modes/interactive/profile-menu-controller.js.map +1 -1
- package/dist/modes/interactive/report-commands.d.ts.map +1 -1
- package/dist/modes/interactive/report-commands.js +21 -0
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.d.ts +17 -2
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +50 -17
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/dist/modes/interactive/session-io-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-io-commands.js +16 -6
- package/dist/modes/interactive/session-io-commands.js.map +1 -1
- package/dist/modes/interactive/session-replacement-errors.d.ts +7 -0
- package/dist/modes/interactive/session-replacement-errors.d.ts.map +1 -0
- package/dist/modes/interactive/session-replacement-errors.js +15 -0
- package/dist/modes/interactive/session-replacement-errors.js.map +1 -0
- package/dist/modes/interactive/startup-checks.d.ts.map +1 -1
- package/dist/modes/interactive/startup-checks.js +1 -1
- package/dist/modes/interactive/startup-checks.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +82 -23
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +15 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js +138 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +2 -13
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +1 -0
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +52 -1
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/platform.d.ts +3 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/dist/utils/platform.js +8 -0
- package/dist/utils/platform.js.map +1 -0
- package/dist/utils/work-directory.d.ts +11 -0
- package/dist/utils/work-directory.d.ts.map +1 -1
- package/dist/utils/work-directory.js +30 -9
- package/dist/utils/work-directory.js.map +1 -1
- package/docs/UI_POLISH_ORCHESTRATION.md +44 -0
- package/docs/UI_QUALITY_ORCHESTRATION.md +30 -0
- package/docs/docs.json +4 -0
- package/docs/extensions.md +62 -2
- package/docs/harness-architecture.md +156 -0
- package/docs/keybindings.md +11 -1
- package/docs/process-matrix.md +59 -26
- package/docs/rpc.md +45 -2
- package/docs/sessions.md +15 -0
- package/docs/settings.md +125 -11
- package/docs/task-steps.md +8 -0
- package/docs/telemetry.md +19 -0
- package/docs/tmux-agent-manager.md +10 -3
- package/docs/ui-reference/README.md +9 -0
- package/docs/ui-reference/orchestration-after.txt +7 -0
- package/docs/ui-reference/orchestration-before.txt +7 -0
- package/docs/ui-reference/orchestration-reference.txt +6 -0
- package/docs/usage.md +14 -2
- package/docs/work-directory.md +19 -8
- 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/question.ts +34 -245
- package/examples/extensions/questionnaire.ts +41 -407
- 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 +4 -4
- package/dist/core/delegation/session-worker-result.d.ts +0 -46
- package/dist/core/delegation/session-worker-result.d.ts.map +0 -1
- package/dist/core/delegation/session-worker-result.js +0 -113
- package/dist/core/delegation/session-worker-result.js.map +0 -1
- package/dist/core/delegation/worker-result.d.ts.map +0 -1
- package/dist/core/delegation/worker-result.js.map +0 -1
- package/dist/core/telemetry.d.ts.map +0 -1
- package/dist/core/telemetry.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adaptation-store.js","sourceRoot":"","sources":["../../../src/core/models/adaptation-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { stateFile } from \"../agent-paths.ts\";\nimport { isWorkerSession } from \"../session-role.ts\";\nimport { withFileLockSync, writeFileAtomicSync } from \"../util/atomic-file.ts\";\nimport { currentHostFingerprint, type HostFingerprint } from \"./fitness-store.ts\";\nimport {\n\thasUsableModelPerfSample,\n\tisModelPerfProfile,\n\ttype ModelPerfProfile,\n\ttype ModelPerfSample,\n\tupdateModelPerfProfile,\n} from \"./perf-profile.ts\";\n\nconst STORE_VERSION = 1;\nconst MAX_RULES_PER_MODEL = 5;\nconst RETIRE_AFTER_MS = 30 * 24 * 60 * 60 * 1000;\n\nexport interface ModelAdaptationRule {\n\tmode: string;\n\ttext: string;\n\taddedAt: string;\n\tlastFiredAt: string;\n}\n\nexport type ModelProtocolCalibration =\n\t| {\n\t\t\tversion: number;\n\t\t\tstatus?: \"calibrated\";\n\t\t\tvariant: string;\n\t\t\tcalibratedAt: string;\n\t }\n\t| {\n\t\t\tversion: number;\n\t\t\tstatus: \"failed\";\n\t\t\tattemptedAt: string;\n\t\t\tvariantsTried: string[];\n\t };\n\nexport type ModelToolProbeVerdict = \"native\" | \"text-protocol\" | \"none\";\nexport type NativeToolProbeGrade = \"task\" | \"echo-only\" | \"absent\";\n\nexport interface ModelToolProbe {\n\tversion: number;\n\tstatus: ModelToolProbeVerdict;\n\tprobedAt: string;\n\tvariant?: string;\n\tnativeGrade?: NativeToolProbeGrade;\n\tdiagnostic?: string;\n}\n\nexport interface ModelTeachStats {\n\ttaught: number;\n\trecurrenceBefore: number;\n\trecurrenceAfter: number;\n}\n\nexport interface ModelAdaptationProfile {\n\trules: ModelAdaptationRule[];\n\tprotocol?: ModelProtocolCalibration;\n\ttoolProbe?: ModelToolProbe;\n\tperf?: ModelPerfProfile;\n\tteachStats: Record<string, ModelTeachStats>;\n}\n\nexport interface StoredModelAdaptation {\n\tmodel: string;\n\tprofile: ModelAdaptationProfile;\n\tat: string;\n\thost: HostFingerprint;\n}\n\ninterface AdaptationStoreFile {\n\tversion: 1;\n\t/** hostId -> modelRef -> latest stored adaptation profile. */\n\thosts: Record<string, Record<string, StoredModelAdaptation>>;\n}\n\nfunction emptyProfile(): ModelAdaptationProfile {\n\treturn { rules: [], teachStats: {} };\n}\n\nfunction normalizeProfile(profile: Partial<ModelAdaptationProfile> | undefined): ModelAdaptationProfile {\n\treturn {\n\t\trules: Array.isArray(profile?.rules) ? profile.rules.filter(isRule) : [],\n\t\t...(isProtocol(profile?.protocol) && { protocol: profile.protocol }),\n\t\t...(isToolProbe(profile?.toolProbe) && { toolProbe: profile.toolProbe }),\n\t\t...(isModelPerfProfile(profile?.perf) && { perf: profile.perf }),\n\t\tteachStats: isRecord(profile?.teachStats) ? filterTeachStats(profile.teachStats) : {},\n\t};\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isRule(value: unknown): value is ModelAdaptationRule {\n\treturn (\n\t\tisRecord(value) &&\n\t\ttypeof value.mode === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\ttypeof value.addedAt === \"string\" &&\n\t\ttypeof value.lastFiredAt === \"string\"\n\t);\n}\n\nfunction isProtocol(value: unknown): value is ModelProtocolCalibration {\n\tif (!isRecord(value) || typeof value.version !== \"number\") return false;\n\tif (value.status === \"failed\") {\n\t\treturn (\n\t\t\ttypeof value.attemptedAt === \"string\" &&\n\t\t\tArray.isArray(value.variantsTried) &&\n\t\t\tvalue.variantsTried.every((variant) => typeof variant === \"string\")\n\t\t);\n\t}\n\treturn (\n\t\t(value.status === undefined || value.status === \"calibrated\") &&\n\t\ttypeof value.variant === \"string\" &&\n\t\ttypeof value.calibratedAt === \"string\"\n\t);\n}\n\nfunction isToolProbe(value: unknown): value is ModelToolProbe {\n\treturn (\n\t\tisRecord(value) &&\n\t\ttypeof value.version === \"number\" &&\n\t\t(value.status === \"native\" || value.status === \"text-protocol\" || value.status === \"none\") &&\n\t\ttypeof value.probedAt === \"string\" &&\n\t\t(value.variant === undefined || typeof value.variant === \"string\") &&\n\t\t(value.nativeGrade === undefined ||\n\t\t\tvalue.nativeGrade === \"task\" ||\n\t\t\tvalue.nativeGrade === \"echo-only\" ||\n\t\t\tvalue.nativeGrade === \"absent\") &&\n\t\t(value.diagnostic === undefined || typeof value.diagnostic === \"string\")\n\t);\n}\n\nfunction isTeachStats(value: unknown): value is ModelTeachStats {\n\treturn (\n\t\tisRecord(value) &&\n\t\ttypeof value.taught === \"number\" &&\n\t\ttypeof value.recurrenceBefore === \"number\" &&\n\t\ttypeof value.recurrenceAfter === \"number\"\n\t);\n}\n\nfunction filterTeachStats(value: Record<string, unknown>): Record<string, ModelTeachStats> {\n\treturn Object.fromEntries(\n\t\tObject.entries(value).filter((entry): entry is [string, ModelTeachStats] => isTeachStats(entry[1])),\n\t);\n}\n\nfunction ruleRecency(rule: ModelAdaptationRule): number {\n\tconst lastFired = Date.parse(rule.lastFiredAt);\n\tif (Number.isFinite(lastFired)) return lastFired;\n\tconst added = Date.parse(rule.addedAt);\n\treturn Number.isFinite(added) ? added : 0;\n}\n\n/**\n * Minimum post-rule recurrences before efficacy can retire a rule early — a single relapse is\n * noise, not proof the rule stopped working.\n */\nconst MIN_RECURRENCE_AFTER_FOR_EFFICACY = 2;\n\n/**\n * Efficacy-based early retirement. `agent-session.ts`'s `_handleModelAdaptationTelemetry` bumps\n * `recurrenceBefore` each time a failure mode recurs BEFORE a standing rule exists for it (the\n * baseline that earned the rule), then switches to bumping `recurrenceAfter` each time the SAME mode\n * recurs AFTER the rule fired. So a rule that is actually working keeps `recurrenceAfter` low relative\n * to its own pre-rule baseline; a rule that has caught up to (or exceeded) that baseline has\n * demonstrably stopped reducing recurrence and should retire before the time-based outer bound.\n */\nfunction isRuleEffective(stats: ModelTeachStats | undefined): boolean {\n\tif (!stats || stats.recurrenceAfter < MIN_RECURRENCE_AFTER_FOR_EFFICACY) return true; // not enough post-rule evidence yet\n\treturn stats.recurrenceAfter < stats.recurrenceBefore;\n}\n\n/**\n * Prune rules past the time-based outer bound (`RETIRE_AFTER_MS`, always enforced) OR past efficacy\n * (a rule that stopped reducing recurrence retires early; a rule that keeps helping persists until\n * the outer bound).\n */\nfunction pruneRetiredRules(\n\trules: readonly ModelAdaptationRule[],\n\tteachStats: Record<string, ModelTeachStats>,\n\tnow: Date,\n): ModelAdaptationRule[] {\n\tconst cutoff = now.getTime() - RETIRE_AFTER_MS;\n\treturn rules.filter((rule) => ruleRecency(rule) >= cutoff && isRuleEffective(teachStats[rule.mode]));\n}\n\nfunction enforceRuleCap(rules: readonly ModelAdaptationRule[]): ModelAdaptationRule[] {\n\tif (rules.length <= MAX_RULES_PER_MODEL) return [...rules];\n\treturn [...rules].sort((a, b) => ruleRecency(b) - ruleRecency(a)).slice(0, MAX_RULES_PER_MODEL);\n}\n\nfunction mergeRule(rules: readonly ModelAdaptationRule[], rule: ModelAdaptationRule): ModelAdaptationRule[] {\n\tconst withoutSameMode = rules.filter((existing) => existing.mode !== rule.mode);\n\treturn enforceRuleCap([...withoutSameMode, rule]);\n}\n\nexport class ModelAdaptationStore {\n\tprivate readonly filePath: string;\n\tprivate readonly fingerprint: () => HostFingerprint;\n\tprivate readonly readOnly: boolean;\n\n\tconstructor(filePath: string, options?: { fingerprint?: () => HostFingerprint; readOnly?: boolean }) {\n\t\tthis.filePath = filePath;\n\t\tthis.fingerprint = options?.fingerprint ?? currentHostFingerprint;\n\t\tthis.readOnly = options?.readOnly ?? isWorkerSession();\n\t}\n\n\tstatic forAgentDir(\n\t\tagentDir: string,\n\t\toptions?: { fingerprint?: () => HostFingerprint; readOnly?: boolean },\n\t): ModelAdaptationStore {\n\t\treturn new ModelAdaptationStore(stateFile(agentDir, \"model-adaptation.json\"), options);\n\t}\n\n\tprivate load(): AdaptationStoreFile {\n\t\ttry {\n\t\t\tif (!existsSync(this.filePath)) return { version: STORE_VERSION, hosts: {} };\n\t\t\tconst parsed = JSON.parse(readFileSync(this.filePath, \"utf-8\")) as AdaptationStoreFile;\n\t\t\tif (parsed && parsed.version === STORE_VERSION && parsed.hosts && typeof parsed.hosts === \"object\") {\n\t\t\t\treturn parsed;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Unreadable/corrupt store: start fresh in memory; the next save rewrites the file.\n\t\t}\n\t\treturn { version: STORE_VERSION, hosts: {} };\n\t}\n\n\tprivate write(file: AdaptationStoreFile): void {\n\t\twriteFileAtomicSync(this.filePath, `${JSON.stringify(file, null, \"\\t\")}\\n`);\n\t}\n\n\t/**\n\t * Load-mutate-write under a single exclusive lock so two concurrent stores (e.g. two sessions\n\t * sharing an agentDir) can't both read the old file and clobber each other's write.\n\t */\n\tprivate store(model: string, profile: ModelAdaptationProfile, at: string): StoredModelAdaptation {\n\t\tconst host = this.fingerprint();\n\t\tconst entry: StoredModelAdaptation = { model, profile: normalizeProfile(profile), at, host };\n\t\t// Zero-footprint (worker session): no lock, no dir, no write -- `save()`/`get()`'s\n\t\t// prune-write path both funnel through here and get the normally-computed entry back.\n\t\tif (this.readOnly) return entry;\n\t\twithFileLockSync(this.filePath, () => {\n\t\t\tconst file = this.load();\n\t\t\tfile.hosts[host.id] = { ...(file.hosts[host.id] ?? {}), [model]: entry };\n\t\t\tthis.write(file);\n\t\t});\n\t\treturn entry;\n\t}\n\n\t/** Persist the profile for a model on the CURRENT host. Best-effort, returns the entry. */\n\tsave(model: string, profile: ModelAdaptationProfile, at?: string): StoredModelAdaptation {\n\t\treturn this.store(model, profile, at ?? new Date().toISOString());\n\t}\n\n\t/** Profile for a model on the current host; prunes retired rules before returning. */\n\tget(model: string, now: Date = new Date()): ModelAdaptationProfile {\n\t\tconst host = this.fingerprint();\n\t\tconst file = this.load();\n\t\tconst entry = file.hosts[host.id]?.[model];\n\t\tif (!entry) return emptyProfile();\n\t\tconst profile = normalizeProfile(entry.profile);\n\t\tconst prunedRules = pruneRetiredRules(profile.rules, profile.teachStats, now);\n\t\tif (prunedRules.length !== profile.rules.length) {\n\t\t\treturn this.store(model, { ...profile, rules: prunedRules }, now.toISOString()).profile;\n\t\t}\n\t\treturn profile;\n\t}\n\n\t/** Add or replace one standing rule, enforcing the per-model cap. */\n\taddRule(\n\t\tmodel: string,\n\t\trule: { mode: string; text: string; addedAt?: string; lastFiredAt?: string },\n\t\tnow = new Date(),\n\t): StoredModelAdaptation {\n\t\tconst profile = this.get(model, now);\n\t\tconst at = now.toISOString();\n\t\tconst nextRule: ModelAdaptationRule = {\n\t\t\tmode: rule.mode,\n\t\t\ttext: rule.text,\n\t\t\taddedAt: rule.addedAt ?? at,\n\t\t\tlastFiredAt: rule.lastFiredAt ?? at,\n\t\t};\n\t\treturn this.store(model, { ...profile, rules: mergeRule(profile.rules, nextRule) }, at);\n\t}\n\n\tremoveRule(model: string, mode: string, at = new Date()): boolean {\n\t\tconst profile = this.get(model, at);\n\t\tconst rules = profile.rules.filter((rule) => rule.mode !== mode);\n\t\tif (rules.length === profile.rules.length) return false;\n\t\tthis.store(model, { ...profile, rules }, at.toISOString());\n\t\treturn true;\n\t}\n\n\t/** Update last-fired recency for an existing rule. No-op when absent. */\n\tmarkRuleFired(model: string, mode: string, at = new Date()): StoredModelAdaptation | undefined {\n\t\tconst profile = this.get(model, at);\n\t\tconst rules = profile.rules.map((rule) =>\n\t\t\trule.mode === mode ? { ...rule, lastFiredAt: at.toISOString() } : rule,\n\t\t);\n\t\tif (rules.every((rule, index) => rule === profile.rules[index])) return undefined;\n\t\treturn this.store(model, { ...profile, rules }, at.toISOString());\n\t}\n\n\tsetProtocol(model: string, protocol: ModelProtocolCalibration, at?: string): StoredModelAdaptation {\n\t\tconst now = at ?? (protocol.status === \"failed\" ? protocol.attemptedAt : protocol.calibratedAt);\n\t\tconst profile = this.get(model, new Date(now));\n\t\treturn this.store(model, { ...profile, protocol }, now);\n\t}\n\n\tsetToolProbe(model: string, toolProbe: ModelToolProbe, at?: string): StoredModelAdaptation {\n\t\tconst now = at ?? toolProbe.probedAt;\n\t\tconst profile = this.get(model, new Date(now));\n\t\treturn this.store(model, { ...profile, toolProbe }, now);\n\t}\n\n\trecordPerfSample(model: string, sample: ModelPerfSample, at?: string): StoredModelAdaptation | undefined {\n\t\tif (!hasUsableModelPerfSample(sample)) return undefined;\n\t\tconst now = at ?? sample.at ?? new Date().toISOString();\n\t\tconst profile = this.get(model, new Date(now));\n\t\tconst perf = updateModelPerfProfile(profile.perf, sample, now);\n\t\tif (!perf) return undefined;\n\t\treturn this.store(model, { ...profile, perf }, now);\n\t}\n\n\tremoveProtocol(model: string, at = new Date()): boolean {\n\t\tconst profile = this.get(model, at);\n\t\tif (!profile.protocol) return false;\n\t\tconst { protocol: _protocol, ...rest } = profile;\n\t\tthis.store(model, rest, at.toISOString());\n\t\treturn true;\n\t}\n\n\tsetTeachStats(model: string, mode: string, stats: ModelTeachStats, at?: string): StoredModelAdaptation {\n\t\tconst now = at ?? new Date().toISOString();\n\t\tconst profile = this.get(model, new Date(now));\n\t\treturn this.store(model, { ...profile, teachStats: { ...profile.teachStats, [mode]: stats } }, now);\n\t}\n\n\t/** Profiles for the current host (default) or an explicit host id. */\n\tgetForHost(hostId?: string): StoredModelAdaptation[] {\n\t\tconst file = this.load();\n\t\treturn Object.values(file.hosts[hostId ?? this.fingerprint().id] ?? {}).map((entry) => ({\n\t\t\t...entry,\n\t\t\tprofile: normalizeProfile(entry.profile),\n\t\t}));\n\t}\n\n\t/** Every stored profile across all hosts (for cross-machine comparisons). */\n\tgetAll(): StoredModelAdaptation[] {\n\t\tconst file = this.load();\n\t\treturn Object.values(file.hosts).flatMap((models) =>\n\t\t\tObject.values(models).map((entry) => ({ ...entry, profile: normalizeProfile(entry.profile) })),\n\t\t);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"adaptation-store.js","sourceRoot":"","sources":["../../../src/core/models/adaptation-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { stateFile } from \"../agent-paths.ts\";\nimport { isWorkerSession } from \"../session-role.ts\";\nimport { isRecordObject } from \"../util/value-guards.ts\";\nimport { type HostFingerprint, HostStateStore, isHostFingerprint } from \"./host-state-store.ts\";\nimport {\n\thasUsableModelPerfSample,\n\tisModelPerfProfile,\n\ttype ModelPerfProfile,\n\ttype ModelPerfSample,\n\tupdateModelPerfProfile,\n} from \"./perf-profile.ts\";\n\nconst STORE_VERSION = 1;\nconst MAX_RULES_PER_MODEL = 5;\nconst RETIRE_AFTER_MS = 30 * 24 * 60 * 60 * 1000;\n\nexport interface ModelAdaptationRule {\n\tmode: string;\n\ttext: string;\n\taddedAt: string;\n\tlastFiredAt: string;\n}\n\nexport type ModelProtocolCalibration =\n\t| {\n\t\t\tversion: number;\n\t\t\tstatus?: \"calibrated\";\n\t\t\tvariant: string;\n\t\t\tcalibratedAt: string;\n\t }\n\t| {\n\t\t\tversion: number;\n\t\t\tstatus: \"failed\";\n\t\t\tattemptedAt: string;\n\t\t\tvariantsTried: string[];\n\t };\n\nexport type ModelToolProbeVerdict = \"native\" | \"text-protocol\" | \"none\";\nexport type NativeToolProbeGrade = \"task\" | \"echo-only\" | \"absent\";\n\nexport interface ModelToolProbe {\n\tversion: number;\n\tstatus: ModelToolProbeVerdict;\n\tprobedAt: string;\n\tvariant?: string;\n\tnativeGrade?: NativeToolProbeGrade;\n\tdiagnostic?: string;\n}\n\nexport interface ModelTeachStats {\n\ttaught: number;\n\trecurrenceBefore: number;\n\trecurrenceAfter: number;\n}\n\nexport interface ModelAdaptationProfile {\n\trules: ModelAdaptationRule[];\n\tprotocol?: ModelProtocolCalibration;\n\ttoolProbe?: ModelToolProbe;\n\tperf?: ModelPerfProfile;\n\tteachStats: Record<string, ModelTeachStats>;\n}\n\nexport interface StoredModelAdaptation {\n\tmodel: string;\n\tprofile: ModelAdaptationProfile;\n\tat: string;\n\thost: HostFingerprint;\n}\n\ninterface ProfileMutation {\n\tprofile: ModelAdaptationProfile;\n\tentry?: StoredModelAdaptation;\n\tapplied: boolean;\n}\n\nfunction emptyProfile(): ModelAdaptationProfile {\n\treturn { rules: [], teachStats: {} };\n}\n\nfunction normalizeProfile(profile: Partial<ModelAdaptationProfile> | undefined): ModelAdaptationProfile {\n\treturn {\n\t\trules: Array.isArray(profile?.rules) ? profile.rules.filter(isRule) : [],\n\t\t...(isProtocol(profile?.protocol) && { protocol: profile.protocol }),\n\t\t...(isToolProbe(profile?.toolProbe) && { toolProbe: profile.toolProbe }),\n\t\t...(isModelPerfProfile(profile?.perf) && { perf: profile.perf }),\n\t\tteachStats: isRecordObject(profile?.teachStats) ? filterTeachStats(profile.teachStats) : {},\n\t};\n}\n\nfunction isRule(value: unknown): value is ModelAdaptationRule {\n\treturn (\n\t\tisRecordObject(value) &&\n\t\ttypeof value.mode === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\ttypeof value.addedAt === \"string\" &&\n\t\ttypeof value.lastFiredAt === \"string\"\n\t);\n}\n\nfunction isProtocol(value: unknown): value is ModelProtocolCalibration {\n\tif (!isRecordObject(value) || typeof value.version !== \"number\") return false;\n\tif (value.status === \"failed\") {\n\t\treturn (\n\t\t\ttypeof value.attemptedAt === \"string\" &&\n\t\t\tArray.isArray(value.variantsTried) &&\n\t\t\tvalue.variantsTried.every((variant) => typeof variant === \"string\")\n\t\t);\n\t}\n\treturn (\n\t\t(value.status === undefined || value.status === \"calibrated\") &&\n\t\ttypeof value.variant === \"string\" &&\n\t\ttypeof value.calibratedAt === \"string\"\n\t);\n}\n\nfunction isToolProbe(value: unknown): value is ModelToolProbe {\n\treturn (\n\t\tisRecordObject(value) &&\n\t\ttypeof value.version === \"number\" &&\n\t\t(value.status === \"native\" || value.status === \"text-protocol\" || value.status === \"none\") &&\n\t\ttypeof value.probedAt === \"string\" &&\n\t\t(value.variant === undefined || typeof value.variant === \"string\") &&\n\t\t(value.nativeGrade === undefined ||\n\t\t\tvalue.nativeGrade === \"task\" ||\n\t\t\tvalue.nativeGrade === \"echo-only\" ||\n\t\t\tvalue.nativeGrade === \"absent\") &&\n\t\t(value.diagnostic === undefined || typeof value.diagnostic === \"string\")\n\t);\n}\n\nfunction isTeachStats(value: unknown): value is ModelTeachStats {\n\treturn (\n\t\tisRecordObject(value) &&\n\t\ttypeof value.taught === \"number\" &&\n\t\ttypeof value.recurrenceBefore === \"number\" &&\n\t\ttypeof value.recurrenceAfter === \"number\"\n\t);\n}\n\nfunction filterTeachStats(value: Record<string, unknown>): Record<string, ModelTeachStats> {\n\treturn Object.fromEntries(\n\t\tObject.entries(value).filter((entry): entry is [string, ModelTeachStats] => isTeachStats(entry[1])),\n\t);\n}\n\nfunction ruleRecency(rule: ModelAdaptationRule): number {\n\tconst lastFired = Date.parse(rule.lastFiredAt);\n\tif (Number.isFinite(lastFired)) return lastFired;\n\tconst added = Date.parse(rule.addedAt);\n\treturn Number.isFinite(added) ? added : 0;\n}\n\n/**\n * Minimum post-rule recurrences before efficacy can retire a rule early — a single relapse is\n * noise, not proof the rule stopped working.\n */\nconst MIN_RECURRENCE_AFTER_FOR_EFFICACY = 2;\n\n/**\n * Efficacy-based early retirement. `agent-session.ts`'s `_handleModelAdaptationTelemetry` bumps\n * `recurrenceBefore` each time a failure mode recurs BEFORE a standing rule exists for it (the\n * baseline that earned the rule), then switches to bumping `recurrenceAfter` each time the SAME mode\n * recurs AFTER the rule fired. So a rule that is actually working keeps `recurrenceAfter` low relative\n * to its own pre-rule baseline; a rule that has caught up to (or exceeded) that baseline has\n * demonstrably stopped reducing recurrence and should retire before the time-based outer bound.\n */\nfunction isRuleEffective(stats: ModelTeachStats | undefined): boolean {\n\tif (!stats || stats.recurrenceAfter < MIN_RECURRENCE_AFTER_FOR_EFFICACY) return true; // not enough post-rule evidence yet\n\treturn stats.recurrenceAfter < stats.recurrenceBefore;\n}\n\n/**\n * Prune rules past the time-based outer bound (`RETIRE_AFTER_MS`, always enforced) OR past efficacy\n * (a rule that stopped reducing recurrence retires early; a rule that keeps helping persists until\n * the outer bound).\n */\nfunction pruneRetiredRules(\n\trules: readonly ModelAdaptationRule[],\n\tteachStats: Record<string, ModelTeachStats>,\n\tnow: Date,\n): ModelAdaptationRule[] {\n\tconst cutoff = now.getTime() - RETIRE_AFTER_MS;\n\treturn rules.filter((rule) => ruleRecency(rule) >= cutoff && isRuleEffective(teachStats[rule.mode]));\n}\n\nfunction enforceRuleCap(rules: readonly ModelAdaptationRule[]): ModelAdaptationRule[] {\n\tif (rules.length <= MAX_RULES_PER_MODEL) return [...rules];\n\treturn [...rules].sort((a, b) => ruleRecency(b) - ruleRecency(a)).slice(0, MAX_RULES_PER_MODEL);\n}\n\nfunction mergeRule(rules: readonly ModelAdaptationRule[], rule: ModelAdaptationRule): ModelAdaptationRule[] {\n\tconst withoutSameMode = rules.filter((existing) => existing.mode !== rule.mode);\n\treturn enforceRuleCap([...withoutSameMode, rule]);\n}\n\nfunction parseAdaptationHost(value: unknown, hostId: string): Record<string, StoredModelAdaptation> | undefined {\n\tif (!isRecordObject(value)) return undefined;\n\tconst profiles: Record<string, StoredModelAdaptation> = {};\n\tfor (const [model, candidate] of Object.entries(value)) {\n\t\tif (\n\t\t\t!isRecordObject(candidate) ||\n\t\t\tcandidate.model !== model ||\n\t\t\ttypeof candidate.at !== \"string\" ||\n\t\t\t!isHostFingerprint(candidate.host) ||\n\t\t\tcandidate.host.id !== hostId ||\n\t\t\t!isRecordObject(candidate.profile)\n\t\t)\n\t\t\tcontinue;\n\t\tprofiles[model] = {\n\t\t\tmodel,\n\t\t\tprofile: normalizeProfile(candidate.profile),\n\t\t\tat: candidate.at,\n\t\t\thost: candidate.host,\n\t\t};\n\t}\n\treturn profiles;\n}\n\nexport class ModelAdaptationStore {\n\tprivate readonly storage: HostStateStore<Record<string, StoredModelAdaptation>>;\n\n\tconstructor(filePath: string, options?: { fingerprint?: () => HostFingerprint; readOnly?: boolean }) {\n\t\tthis.storage = new HostStateStore({\n\t\t\tfilePath,\n\t\t\tversion: STORE_VERSION,\n\t\t\tfingerprint: options?.fingerprint,\n\t\t\treadOnly: options?.readOnly ?? isWorkerSession(),\n\t\t\tparseHost: parseAdaptationHost,\n\t\t});\n\t}\n\n\tstatic forAgentDir(\n\t\tagentDir: string,\n\t\toptions?: { fingerprint?: () => HostFingerprint; readOnly?: boolean },\n\t): ModelAdaptationStore {\n\t\treturn new ModelAdaptationStore(stateFile(agentDir, \"model-adaptation.json\"), options);\n\t}\n\n\t/**\n\t * Load-mutate-write under a single exclusive lock so two concurrent stores (e.g. two sessions\n\t * sharing an agentDir) can't both read the old file and clobber each other's write.\n\t */\n\tprivate store(model: string, profile: ModelAdaptationProfile, at: string): StoredModelAdaptation {\n\t\treturn this.storage.mutateCurrentHost(\n\t\t\t() => ({}),\n\t\t\t(profiles, host) => {\n\t\t\t\tconst entry: StoredModelAdaptation = { model, profile: normalizeProfile(profile), at, host };\n\t\t\t\tprofiles[model] = entry;\n\t\t\t\treturn { result: entry, changed: true };\n\t\t\t},\n\t\t);\n\t}\n\n\t/** Keep the complete profile read-modify-write transaction under the host-state lock. */\n\tprivate mutateProfile(\n\t\tmodel: string,\n\t\tnow: Date,\n\t\tmutate: (profile: ModelAdaptationProfile) => ModelAdaptationProfile | undefined,\n\t\tstoredAt = now.toISOString(),\n\t): ProfileMutation {\n\t\treturn this.storage.mutateCurrentHost<ProfileMutation>(\n\t\t\t() => ({}),\n\t\t\t(profiles, host) => {\n\t\t\t\tconst current = normalizeProfile(profiles[model]?.profile);\n\t\t\t\tconst activeRules = pruneRetiredRules(current.rules, current.teachStats, now);\n\t\t\t\tconst pruned = activeRules.length !== current.rules.length;\n\t\t\t\tconst active = pruned ? { ...current, rules: activeRules } : current;\n\t\t\t\tconst requested = mutate(active);\n\t\t\t\tconst applied = requested !== undefined;\n\t\t\t\tif (!applied && !pruned) {\n\t\t\t\t\treturn { result: { profile: active, applied: false }, changed: false };\n\t\t\t\t}\n\t\t\t\tconst profile = normalizeProfile(requested ?? active);\n\t\t\t\tconst entry: StoredModelAdaptation = { model, profile, at: storedAt, host };\n\t\t\t\tprofiles[model] = entry;\n\t\t\t\treturn { result: { profile, entry, applied }, changed: true };\n\t\t\t},\n\t\t);\n\t}\n\n\t/** Persist the profile for a model on the CURRENT host. Best-effort, returns the entry. */\n\tsave(model: string, profile: ModelAdaptationProfile, at?: string): StoredModelAdaptation {\n\t\treturn this.store(model, profile, at ?? new Date().toISOString());\n\t}\n\n\t/** Profile for a model on the current host; prunes retired rules before returning. */\n\tget(model: string, now: Date = new Date()): ModelAdaptationProfile {\n\t\tconst entry = this.storage.getHost()?.[model];\n\t\tif (!entry) return emptyProfile();\n\t\tconst profile = normalizeProfile(entry.profile);\n\t\tconst prunedRules = pruneRetiredRules(profile.rules, profile.teachStats, now);\n\t\tif (prunedRules.length !== profile.rules.length) {\n\t\t\treturn this.mutateProfile(model, now, () => undefined).profile;\n\t\t}\n\t\treturn profile;\n\t}\n\n\t/** Add or replace one standing rule, enforcing the per-model cap. */\n\taddRule(\n\t\tmodel: string,\n\t\trule: { mode: string; text: string; addedAt?: string; lastFiredAt?: string },\n\t\tnow = new Date(),\n\t): StoredModelAdaptation {\n\t\tconst at = now.toISOString();\n\t\tconst nextRule: ModelAdaptationRule = {\n\t\t\tmode: rule.mode,\n\t\t\ttext: rule.text,\n\t\t\taddedAt: rule.addedAt ?? at,\n\t\t\tlastFiredAt: rule.lastFiredAt ?? at,\n\t\t};\n\t\tconst result = this.mutateProfile(model, now, (profile) => ({\n\t\t\t...profile,\n\t\t\trules: mergeRule(profile.rules, nextRule),\n\t\t}));\n\t\treturn result.entry!;\n\t}\n\n\tremoveRule(model: string, mode: string, at = new Date()): boolean {\n\t\treturn this.mutateProfile(model, at, (profile) => {\n\t\t\tconst rules = profile.rules.filter((rule) => rule.mode !== mode);\n\t\t\treturn rules.length === profile.rules.length ? undefined : { ...profile, rules };\n\t\t}).applied;\n\t}\n\n\t/** Update last-fired recency for an existing rule. No-op when absent. */\n\tmarkRuleFired(model: string, mode: string, at = new Date()): StoredModelAdaptation | undefined {\n\t\tconst result = this.mutateProfile(model, at, (profile) => {\n\t\t\tconst rules = profile.rules.map((rule) =>\n\t\t\t\trule.mode === mode ? { ...rule, lastFiredAt: at.toISOString() } : rule,\n\t\t\t);\n\t\t\treturn rules.every((rule, index) => rule === profile.rules[index]) ? undefined : { ...profile, rules };\n\t\t});\n\t\treturn result.applied ? result.entry : undefined;\n\t}\n\n\tsetProtocol(model: string, protocol: ModelProtocolCalibration, at?: string): StoredModelAdaptation {\n\t\tconst now = at ?? (protocol.status === \"failed\" ? protocol.attemptedAt : protocol.calibratedAt);\n\t\treturn this.mutateProfile(model, new Date(now), (profile) => ({ ...profile, protocol }), now).entry!;\n\t}\n\n\tsetToolProbe(model: string, toolProbe: ModelToolProbe, at?: string): StoredModelAdaptation {\n\t\tconst now = at ?? toolProbe.probedAt;\n\t\treturn this.mutateProfile(model, new Date(now), (profile) => ({ ...profile, toolProbe }), now).entry!;\n\t}\n\n\trecordPerfSample(model: string, sample: ModelPerfSample, at?: string): StoredModelAdaptation | undefined {\n\t\tif (!hasUsableModelPerfSample(sample)) return undefined;\n\t\tconst now = at ?? sample.at ?? new Date().toISOString();\n\t\tconst result = this.mutateProfile(\n\t\t\tmodel,\n\t\t\tnew Date(now),\n\t\t\t(profile) => {\n\t\t\t\tconst perf = updateModelPerfProfile(profile.perf, sample, now);\n\t\t\t\treturn perf ? { ...profile, perf } : undefined;\n\t\t\t},\n\t\t\tnow,\n\t\t);\n\t\treturn result.applied ? result.entry : undefined;\n\t}\n\n\tremoveProtocol(model: string, at = new Date()): boolean {\n\t\treturn this.mutateProfile(model, at, (profile) => {\n\t\t\tif (!profile.protocol) return undefined;\n\t\t\tconst { protocol: _protocol, ...rest } = profile;\n\t\t\treturn rest;\n\t\t}).applied;\n\t}\n\n\tsetTeachStats(model: string, mode: string, stats: ModelTeachStats, at?: string): StoredModelAdaptation {\n\t\tconst now = at ?? new Date().toISOString();\n\t\treturn this.mutateProfile(\n\t\t\tmodel,\n\t\t\tnew Date(now),\n\t\t\t(profile) => ({\n\t\t\t\t...profile,\n\t\t\t\tteachStats: { ...profile.teachStats, [mode]: stats },\n\t\t\t}),\n\t\t\tnow,\n\t\t).entry!;\n\t}\n\n\t/** Profiles for the current host (default) or an explicit host id. */\n\tgetForHost(hostId?: string): StoredModelAdaptation[] {\n\t\treturn Object.values(this.storage.getHost(hostId) ?? {}).map((entry) => ({\n\t\t\t...entry,\n\t\t\tprofile: normalizeProfile(entry.profile),\n\t\t}));\n\t}\n\n\t/** Every stored profile across all hosts (for cross-machine comparisons). */\n\tgetAll(): StoredModelAdaptation[] {\n\t\treturn this.storage\n\t\t\t.getAllHosts()\n\t\t\t.flatMap((models) =>\n\t\t\t\tObject.values(models).map((entry) => ({ ...entry, profile: normalizeProfile(entry.profile) })),\n\t\t\t);\n\t}\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ModelFitnessReport } from "../research/model-fitness.ts";
|
|
2
|
+
import { type HostFingerprint } from "./host-state-store.ts";
|
|
2
3
|
/**
|
|
3
4
|
* Durable, HOST-KEYED storage for model fitness reports. Fitness is a property of a model ON a
|
|
4
5
|
* host (tok/s and latency-driven failures do not travel between machines), so reports are keyed
|
|
@@ -6,14 +7,6 @@ import type { ModelFitnessReport } from "../research/model-fitness.ts";
|
|
|
6
7
|
* "waiting for better hardware" on another, and pi remembers both without confusing them —
|
|
7
8
|
* including when settings/dotfiles are synced across machines.
|
|
8
9
|
*/
|
|
9
|
-
export interface HostFingerprint {
|
|
10
|
-
/** Stable, human-readable id derived from the specs below. */
|
|
11
|
-
id: string;
|
|
12
|
-
cpu: string;
|
|
13
|
-
cores: number;
|
|
14
|
-
totalMemGb: number;
|
|
15
|
-
}
|
|
16
|
-
export declare function currentHostFingerprint(): HostFingerprint;
|
|
17
10
|
export interface StoredFitnessReport {
|
|
18
11
|
model: string;
|
|
19
12
|
report: ModelFitnessReport;
|
|
@@ -21,9 +14,7 @@ export interface StoredFitnessReport {
|
|
|
21
14
|
host: HostFingerprint;
|
|
22
15
|
}
|
|
23
16
|
export declare class FitnessStore {
|
|
24
|
-
private readonly
|
|
25
|
-
private readonly fingerprint;
|
|
26
|
-
private readonly readOnly;
|
|
17
|
+
private readonly storage;
|
|
27
18
|
constructor(filePath: string, options?: {
|
|
28
19
|
fingerprint?: () => HostFingerprint;
|
|
29
20
|
readOnly?: boolean;
|
|
@@ -32,7 +23,6 @@ export declare class FitnessStore {
|
|
|
32
23
|
fingerprint?: () => HostFingerprint;
|
|
33
24
|
readOnly?: boolean;
|
|
34
25
|
}): FitnessStore;
|
|
35
|
-
private load;
|
|
36
26
|
/** Persist the latest report for a model on the CURRENT host. Best-effort, returns the entry. */
|
|
37
27
|
save(model: string, report: ModelFitnessReport, at?: string): StoredFitnessReport;
|
|
38
28
|
/** Drop a model's report for the CURRENT host (uninstall cleanup). No-op when absent. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitness-store.d.ts","sourceRoot":"","sources":["../../../src/core/models/fitness-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fitness-store.d.ts","sourceRoot":"","sources":["../../../src/core/models/fitness-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,KAAK,eAAe,EAAqC,MAAM,uBAAuB,CAAC;AAEhG;;;;;;GAMG;AAEH,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,eAAe,CAAC;CACtB;AAyED,qBAAa,YAAY;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsD;IAE9E,YAAY,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,eAAe,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,EAQlG;IAED,MAAM,CAAC,WAAW,CACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,eAAe,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GACnE,YAAY,CAEd;IAED,iGAAiG;IACjG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAShF;IAED,yFAAyF;IACzF,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAS1B;IAED,qEAAqE;IACrE,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAEjD;IAED,4EAA4E;IAC5E,MAAM,IAAI,mBAAmB,EAAE,CAE9B;CACD","sourcesContent":["import { stateFile } from \"../agent-paths.ts\";\nimport type { ModelFitnessReport } from \"../research/model-fitness.ts\";\nimport { isWorkerSession } from \"../session-role.ts\";\nimport { isPlainRecord } from \"../util/value-guards.ts\";\nimport { type HostFingerprint, HostStateStore, isHostFingerprint } from \"./host-state-store.ts\";\n\n/**\n * Durable, HOST-KEYED storage for model fitness reports. Fitness is a property of a model ON a\n * host (tok/s and latency-driven failures do not travel between machines), so reports are keyed\n * by a hardware fingerprint: the same model can be \"the heavy lifter\" on one machine and\n * \"waiting for better hardware\" on another, and pi remembers both without confusing them —\n * including when settings/dotfiles are synced across machines.\n */\n\nexport interface StoredFitnessReport {\n\tmodel: string;\n\treport: ModelFitnessReport;\n\tat: string;\n\thost: HostFingerprint;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isLaneScore(value: unknown): boolean {\n\treturn (\n\t\tisPlainRecord(value) &&\n\t\tisFiniteNumber(value.succeeded) &&\n\t\tisFiniteNumber(value.total) &&\n\t\tArray.isArray(value.outcomes) &&\n\t\tvalue.outcomes.every((outcome) => typeof outcome === \"string\") &&\n\t\tisFiniteNumber(value.meanMs) &&\n\t\t(value.tokensPerSecond === undefined || isFiniteNumber(value.tokensPerSecond))\n\t);\n}\n\nfunction isFitnessReport(value: unknown): value is ModelFitnessReport {\n\treturn (\n\t\tisPlainRecord(value) &&\n\t\tisFiniteNumber(value.trials) &&\n\t\t(value.tokensPerSecond === undefined || isFiniteNumber(value.tokensPerSecond)) &&\n\t\tisLaneScore(value.research) &&\n\t\tisLaneScore(value.worker) &&\n\t\tisLaneScore(value.search) &&\n\t\tisLaneScore(value.toolCall) &&\n\t\tisLaneScore(value.digest) &&\n\t\tisPlainRecord(value.judge) &&\n\t\tisFiniteNumber(value.judge.parsed) &&\n\t\tisFiniteNumber(value.judge.planningElevated) &&\n\t\tisFiniteNumber(value.judge.planningTotal) &&\n\t\tisFiniteNumber(value.judge.trivialCheap) &&\n\t\tisFiniteNumber(value.judge.trivialTotal) &&\n\t\tisFiniteNumber(value.judge.total) &&\n\t\tArray.isArray(value.judge.outcomes) &&\n\t\tvalue.judge.outcomes.every((outcome) => typeof outcome === \"string\") &&\n\t\tisFiniteNumber(value.judge.meanMs) &&\n\t\t(value.judge.tokensPerSecond === undefined || isFiniteNumber(value.judge.tokensPerSecond)) &&\n\t\t(value.capacity === undefined ||\n\t\t\t(isPlainRecord(value.capacity) &&\n\t\t\t\tisFiniteNumber(value.capacity.registeredContextWindow) &&\n\t\t\t\tisFiniteNumber(value.capacity.servedContextWindow) &&\n\t\t\t\tArray.isArray(value.capacity.outcomes) &&\n\t\t\t\tvalue.capacity.outcomes.every((outcome) => typeof outcome === \"string\") &&\n\t\t\t\tisFiniteNumber(value.capacity.meanMs))) &&\n\t\tisFiniteNumber(value.totalCostUsd)\n\t);\n}\n\nfunction parseFitnessHost(value: unknown, hostId: string): Record<string, StoredFitnessReport> | undefined {\n\tif (!isPlainRecord(value)) return undefined;\n\tconst reports: Record<string, StoredFitnessReport> = {};\n\tfor (const [model, candidate] of Object.entries(value)) {\n\t\tif (\n\t\t\t!isPlainRecord(candidate) ||\n\t\t\tcandidate.model !== model ||\n\t\t\ttypeof candidate.at !== \"string\" ||\n\t\t\t!isHostFingerprint(candidate.host) ||\n\t\t\tcandidate.host.id !== hostId ||\n\t\t\t!isFitnessReport(candidate.report)\n\t\t)\n\t\t\tcontinue;\n\t\treports[model] = {\n\t\t\tmodel,\n\t\t\treport: candidate.report,\n\t\t\tat: candidate.at,\n\t\t\thost: candidate.host,\n\t\t};\n\t}\n\treturn reports;\n}\n\nexport class FitnessStore {\n\tprivate readonly storage: HostStateStore<Record<string, StoredFitnessReport>>;\n\n\tconstructor(filePath: string, options?: { fingerprint?: () => HostFingerprint; readOnly?: boolean }) {\n\t\tthis.storage = new HostStateStore({\n\t\t\tfilePath,\n\t\t\tversion: 1,\n\t\t\tfingerprint: options?.fingerprint,\n\t\t\treadOnly: options?.readOnly ?? isWorkerSession(),\n\t\t\tparseHost: parseFitnessHost,\n\t\t});\n\t}\n\n\tstatic forAgentDir(\n\t\tagentDir: string,\n\t\toptions?: { fingerprint?: () => HostFingerprint; readOnly?: boolean },\n\t): FitnessStore {\n\t\treturn new FitnessStore(stateFile(agentDir, \"model-fitness.json\"), options);\n\t}\n\n\t/** Persist the latest report for a model on the CURRENT host. Best-effort, returns the entry. */\n\tsave(model: string, report: ModelFitnessReport, at?: string): StoredFitnessReport {\n\t\treturn this.storage.mutateCurrentHost(\n\t\t\t() => ({}),\n\t\t\t(reports, host) => {\n\t\t\t\tconst entry: StoredFitnessReport = { model, report, at: at ?? new Date().toISOString(), host };\n\t\t\t\treports[model] = entry;\n\t\t\t\treturn { result: entry, changed: true };\n\t\t\t},\n\t\t);\n\t}\n\n\t/** Drop a model's report for the CURRENT host (uninstall cleanup). No-op when absent. */\n\tremove(model: string): void {\n\t\tthis.storage.mutateCurrentHost(\n\t\t\t() => ({}),\n\t\t\t(reports) => {\n\t\t\t\tif (!reports[model]) return { result: undefined, changed: false };\n\t\t\t\tdelete reports[model];\n\t\t\t\treturn { result: undefined, changed: true };\n\t\t\t},\n\t\t);\n\t}\n\n\t/** Reports for the current host (default) or an explicit host id. */\n\tgetForHost(hostId?: string): StoredFitnessReport[] {\n\t\treturn Object.values(this.storage.getHost(hostId) ?? {});\n\t}\n\n\t/** Every stored report across all hosts (for cross-machine comparisons). */\n\tgetAll(): StoredFitnessReport[] {\n\t\treturn this.storage.getAllHosts().flatMap((reports) => Object.values(reports));\n\t}\n}\n"]}
|
|
@@ -1,80 +1,107 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { cpus, totalmem } from "node:os";
|
|
3
|
-
import { dirname } from "node:path";
|
|
4
1
|
import { stateFile } from "../agent-paths.js";
|
|
5
2
|
import { isWorkerSession } from "../session-role.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
.
|
|
14
|
-
.
|
|
15
|
-
.
|
|
16
|
-
|
|
3
|
+
import { isPlainRecord } from "../util/value-guards.js";
|
|
4
|
+
import { HostStateStore, isHostFingerprint } from "./host-state-store.js";
|
|
5
|
+
function isFiniteNumber(value) {
|
|
6
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
7
|
+
}
|
|
8
|
+
function isLaneScore(value) {
|
|
9
|
+
return (isPlainRecord(value) &&
|
|
10
|
+
isFiniteNumber(value.succeeded) &&
|
|
11
|
+
isFiniteNumber(value.total) &&
|
|
12
|
+
Array.isArray(value.outcomes) &&
|
|
13
|
+
value.outcomes.every((outcome) => typeof outcome === "string") &&
|
|
14
|
+
isFiniteNumber(value.meanMs) &&
|
|
15
|
+
(value.tokensPerSecond === undefined || isFiniteNumber(value.tokensPerSecond)));
|
|
16
|
+
}
|
|
17
|
+
function isFitnessReport(value) {
|
|
18
|
+
return (isPlainRecord(value) &&
|
|
19
|
+
isFiniteNumber(value.trials) &&
|
|
20
|
+
(value.tokensPerSecond === undefined || isFiniteNumber(value.tokensPerSecond)) &&
|
|
21
|
+
isLaneScore(value.research) &&
|
|
22
|
+
isLaneScore(value.worker) &&
|
|
23
|
+
isLaneScore(value.search) &&
|
|
24
|
+
isLaneScore(value.toolCall) &&
|
|
25
|
+
isLaneScore(value.digest) &&
|
|
26
|
+
isPlainRecord(value.judge) &&
|
|
27
|
+
isFiniteNumber(value.judge.parsed) &&
|
|
28
|
+
isFiniteNumber(value.judge.planningElevated) &&
|
|
29
|
+
isFiniteNumber(value.judge.planningTotal) &&
|
|
30
|
+
isFiniteNumber(value.judge.trivialCheap) &&
|
|
31
|
+
isFiniteNumber(value.judge.trivialTotal) &&
|
|
32
|
+
isFiniteNumber(value.judge.total) &&
|
|
33
|
+
Array.isArray(value.judge.outcomes) &&
|
|
34
|
+
value.judge.outcomes.every((outcome) => typeof outcome === "string") &&
|
|
35
|
+
isFiniteNumber(value.judge.meanMs) &&
|
|
36
|
+
(value.judge.tokensPerSecond === undefined || isFiniteNumber(value.judge.tokensPerSecond)) &&
|
|
37
|
+
(value.capacity === undefined ||
|
|
38
|
+
(isPlainRecord(value.capacity) &&
|
|
39
|
+
isFiniteNumber(value.capacity.registeredContextWindow) &&
|
|
40
|
+
isFiniteNumber(value.capacity.servedContextWindow) &&
|
|
41
|
+
Array.isArray(value.capacity.outcomes) &&
|
|
42
|
+
value.capacity.outcomes.every((outcome) => typeof outcome === "string") &&
|
|
43
|
+
isFiniteNumber(value.capacity.meanMs))) &&
|
|
44
|
+
isFiniteNumber(value.totalCostUsd));
|
|
45
|
+
}
|
|
46
|
+
function parseFitnessHost(value, hostId) {
|
|
47
|
+
if (!isPlainRecord(value))
|
|
48
|
+
return undefined;
|
|
49
|
+
const reports = {};
|
|
50
|
+
for (const [model, candidate] of Object.entries(value)) {
|
|
51
|
+
if (!isPlainRecord(candidate) ||
|
|
52
|
+
candidate.model !== model ||
|
|
53
|
+
typeof candidate.at !== "string" ||
|
|
54
|
+
!isHostFingerprint(candidate.host) ||
|
|
55
|
+
candidate.host.id !== hostId ||
|
|
56
|
+
!isFitnessReport(candidate.report))
|
|
57
|
+
continue;
|
|
58
|
+
reports[model] = {
|
|
59
|
+
model,
|
|
60
|
+
report: candidate.report,
|
|
61
|
+
at: candidate.at,
|
|
62
|
+
host: candidate.host,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return reports;
|
|
17
66
|
}
|
|
18
67
|
export class FitnessStore {
|
|
19
|
-
|
|
20
|
-
fingerprint;
|
|
21
|
-
readOnly;
|
|
68
|
+
storage;
|
|
22
69
|
constructor(filePath, options) {
|
|
23
|
-
this.
|
|
24
|
-
|
|
25
|
-
|
|
70
|
+
this.storage = new HostStateStore({
|
|
71
|
+
filePath,
|
|
72
|
+
version: 1,
|
|
73
|
+
fingerprint: options?.fingerprint,
|
|
74
|
+
readOnly: options?.readOnly ?? isWorkerSession(),
|
|
75
|
+
parseHost: parseFitnessHost,
|
|
76
|
+
});
|
|
26
77
|
}
|
|
27
78
|
static forAgentDir(agentDir, options) {
|
|
28
79
|
return new FitnessStore(stateFile(agentDir, "model-fitness.json"), options);
|
|
29
80
|
}
|
|
30
|
-
load() {
|
|
31
|
-
try {
|
|
32
|
-
if (!existsSync(this.filePath))
|
|
33
|
-
return { version: 1, hosts: {} };
|
|
34
|
-
const parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
|
|
35
|
-
if (parsed && parsed.version === 1 && parsed.hosts && typeof parsed.hosts === "object") {
|
|
36
|
-
return parsed;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
// Unreadable/corrupt store: start fresh in memory; the next save rewrites the file.
|
|
41
|
-
}
|
|
42
|
-
return { version: 1, hosts: {} };
|
|
43
|
-
}
|
|
44
81
|
/** Persist the latest report for a model on the CURRENT host. Best-effort, returns the entry. */
|
|
45
82
|
save(model, report, at) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const file = this.load();
|
|
52
|
-
file.hosts[host.id] = { ...(file.hosts[host.id] ?? {}), [model]: entry };
|
|
53
|
-
mkdirSync(dirname(this.filePath), { recursive: true });
|
|
54
|
-
writeFileSync(this.filePath, `${JSON.stringify(file, null, "\t")}\n`, "utf-8");
|
|
55
|
-
return entry;
|
|
83
|
+
return this.storage.mutateCurrentHost(() => ({}), (reports, host) => {
|
|
84
|
+
const entry = { model, report, at: at ?? new Date().toISOString(), host };
|
|
85
|
+
reports[model] = entry;
|
|
86
|
+
return { result: entry, changed: true };
|
|
87
|
+
});
|
|
56
88
|
}
|
|
57
89
|
/** Drop a model's report for the CURRENT host (uninstall cleanup). No-op when absent. */
|
|
58
90
|
remove(model) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
delete file.hosts[host.id][model];
|
|
66
|
-
mkdirSync(dirname(this.filePath), { recursive: true });
|
|
67
|
-
writeFileSync(this.filePath, `${JSON.stringify(file, null, "\t")}\n`, "utf-8");
|
|
91
|
+
this.storage.mutateCurrentHost(() => ({}), (reports) => {
|
|
92
|
+
if (!reports[model])
|
|
93
|
+
return { result: undefined, changed: false };
|
|
94
|
+
delete reports[model];
|
|
95
|
+
return { result: undefined, changed: true };
|
|
96
|
+
});
|
|
68
97
|
}
|
|
69
98
|
/** Reports for the current host (default) or an explicit host id. */
|
|
70
99
|
getForHost(hostId) {
|
|
71
|
-
|
|
72
|
-
return Object.values(file.hosts[hostId ?? this.fingerprint().id] ?? {});
|
|
100
|
+
return Object.values(this.storage.getHost(hostId) ?? {});
|
|
73
101
|
}
|
|
74
102
|
/** Every stored report across all hosts (for cross-machine comparisons). */
|
|
75
103
|
getAll() {
|
|
76
|
-
|
|
77
|
-
return Object.values(file.hosts).flatMap((models) => Object.values(models));
|
|
104
|
+
return this.storage.getAllHosts().flatMap((reports) => Object.values(reports));
|
|
78
105
|
}
|
|
79
106
|
}
|
|
80
107
|
//# sourceMappingURL=fitness-store.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitness-store.js","sourceRoot":"","sources":["../../../src/core/models/fitness-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { cpus, totalmem } from \"node:os\";\nimport { dirname } from \"node:path\";\nimport { stateFile } from \"../agent-paths.ts\";\nimport type { ModelFitnessReport } from \"../research/model-fitness.ts\";\nimport { isWorkerSession } from \"../session-role.ts\";\n\n/**\n * Durable, HOST-KEYED storage for model fitness reports. Fitness is a property of a model ON a\n * host (tok/s and latency-driven failures do not travel between machines), so reports are keyed\n * by a hardware fingerprint: the same model can be \"the heavy lifter\" on one machine and\n * \"waiting for better hardware\" on another, and pi remembers both without confusing them —\n * including when settings/dotfiles are synced across machines.\n */\n\nexport interface HostFingerprint {\n\t/** Stable, human-readable id derived from the specs below. */\n\tid: string;\n\tcpu: string;\n\tcores: number;\n\ttotalMemGb: number;\n}\n\nexport function currentHostFingerprint(): HostFingerprint {\n\tconst cpuList = cpus();\n\tconst cpu = (cpuList[0]?.model ?? \"unknown-cpu\").trim();\n\tconst cores = Math.max(1, cpuList.length);\n\tconst totalMemGb = Math.round(totalmem() / 1024 ** 3);\n\tconst id = `${cpu\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\")\n\t\t.slice(0, 48)}-${cores}c-${totalMemGb}g`;\n\treturn { id, cpu, cores, totalMemGb };\n}\n\nexport interface StoredFitnessReport {\n\tmodel: string;\n\treport: ModelFitnessReport;\n\tat: string;\n\thost: HostFingerprint;\n}\n\ninterface FitnessStoreFile {\n\tversion: 1;\n\t/** hostId -> modelRef -> latest stored report. */\n\thosts: Record<string, Record<string, StoredFitnessReport>>;\n}\n\nexport class FitnessStore {\n\tprivate readonly filePath: string;\n\tprivate readonly fingerprint: () => HostFingerprint;\n\tprivate readonly readOnly: boolean;\n\n\tconstructor(filePath: string, options?: { fingerprint?: () => HostFingerprint; readOnly?: boolean }) {\n\t\tthis.filePath = filePath;\n\t\tthis.fingerprint = options?.fingerprint ?? currentHostFingerprint;\n\t\tthis.readOnly = options?.readOnly ?? isWorkerSession();\n\t}\n\n\tstatic forAgentDir(\n\t\tagentDir: string,\n\t\toptions?: { fingerprint?: () => HostFingerprint; readOnly?: boolean },\n\t): FitnessStore {\n\t\treturn new FitnessStore(stateFile(agentDir, \"model-fitness.json\"), options);\n\t}\n\n\tprivate load(): FitnessStoreFile {\n\t\ttry {\n\t\t\tif (!existsSync(this.filePath)) return { version: 1, hosts: {} };\n\t\t\tconst parsed = JSON.parse(readFileSync(this.filePath, \"utf-8\")) as FitnessStoreFile;\n\t\t\tif (parsed && parsed.version === 1 && parsed.hosts && typeof parsed.hosts === \"object\") {\n\t\t\t\treturn parsed;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Unreadable/corrupt store: start fresh in memory; the next save rewrites the file.\n\t\t}\n\t\treturn { version: 1, hosts: {} };\n\t}\n\n\t/** Persist the latest report for a model on the CURRENT host. Best-effort, returns the entry. */\n\tsave(model: string, report: ModelFitnessReport, at?: string): StoredFitnessReport {\n\t\tconst host = this.fingerprint();\n\t\tconst entry: StoredFitnessReport = { model, report, at: at ?? new Date().toISOString(), host };\n\t\t// Zero-footprint (worker session): no dir, no write -- still returns the computed entry.\n\t\tif (this.readOnly) return entry;\n\t\tconst file = this.load();\n\t\tfile.hosts[host.id] = { ...(file.hosts[host.id] ?? {}), [model]: entry };\n\t\tmkdirSync(dirname(this.filePath), { recursive: true });\n\t\twriteFileSync(this.filePath, `${JSON.stringify(file, null, \"\\t\")}\\n`, \"utf-8\");\n\t\treturn entry;\n\t}\n\n\t/** Drop a model's report for the CURRENT host (uninstall cleanup). No-op when absent. */\n\tremove(model: string): void {\n\t\tif (this.readOnly) return;\n\t\tconst host = this.fingerprint();\n\t\tconst file = this.load();\n\t\tif (!file.hosts[host.id]?.[model]) return;\n\t\tdelete file.hosts[host.id][model];\n\t\tmkdirSync(dirname(this.filePath), { recursive: true });\n\t\twriteFileSync(this.filePath, `${JSON.stringify(file, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t/** Reports for the current host (default) or an explicit host id. */\n\tgetForHost(hostId?: string): StoredFitnessReport[] {\n\t\tconst file = this.load();\n\t\treturn Object.values(file.hosts[hostId ?? this.fingerprint().id] ?? {});\n\t}\n\n\t/** Every stored report across all hosts (for cross-machine comparisons). */\n\tgetAll(): StoredFitnessReport[] {\n\t\tconst file = this.load();\n\t\treturn Object.values(file.hosts).flatMap((models) => Object.values(models));\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fitness-store.js","sourceRoot":"","sources":["../../../src/core/models/fitness-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { stateFile } from \"../agent-paths.ts\";\nimport type { ModelFitnessReport } from \"../research/model-fitness.ts\";\nimport { isWorkerSession } from \"../session-role.ts\";\nimport { isPlainRecord } from \"../util/value-guards.ts\";\nimport { type HostFingerprint, HostStateStore, isHostFingerprint } from \"./host-state-store.ts\";\n\n/**\n * Durable, HOST-KEYED storage for model fitness reports. Fitness is a property of a model ON a\n * host (tok/s and latency-driven failures do not travel between machines), so reports are keyed\n * by a hardware fingerprint: the same model can be \"the heavy lifter\" on one machine and\n * \"waiting for better hardware\" on another, and pi remembers both without confusing them —\n * including when settings/dotfiles are synced across machines.\n */\n\nexport interface StoredFitnessReport {\n\tmodel: string;\n\treport: ModelFitnessReport;\n\tat: string;\n\thost: HostFingerprint;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isLaneScore(value: unknown): boolean {\n\treturn (\n\t\tisPlainRecord(value) &&\n\t\tisFiniteNumber(value.succeeded) &&\n\t\tisFiniteNumber(value.total) &&\n\t\tArray.isArray(value.outcomes) &&\n\t\tvalue.outcomes.every((outcome) => typeof outcome === \"string\") &&\n\t\tisFiniteNumber(value.meanMs) &&\n\t\t(value.tokensPerSecond === undefined || isFiniteNumber(value.tokensPerSecond))\n\t);\n}\n\nfunction isFitnessReport(value: unknown): value is ModelFitnessReport {\n\treturn (\n\t\tisPlainRecord(value) &&\n\t\tisFiniteNumber(value.trials) &&\n\t\t(value.tokensPerSecond === undefined || isFiniteNumber(value.tokensPerSecond)) &&\n\t\tisLaneScore(value.research) &&\n\t\tisLaneScore(value.worker) &&\n\t\tisLaneScore(value.search) &&\n\t\tisLaneScore(value.toolCall) &&\n\t\tisLaneScore(value.digest) &&\n\t\tisPlainRecord(value.judge) &&\n\t\tisFiniteNumber(value.judge.parsed) &&\n\t\tisFiniteNumber(value.judge.planningElevated) &&\n\t\tisFiniteNumber(value.judge.planningTotal) &&\n\t\tisFiniteNumber(value.judge.trivialCheap) &&\n\t\tisFiniteNumber(value.judge.trivialTotal) &&\n\t\tisFiniteNumber(value.judge.total) &&\n\t\tArray.isArray(value.judge.outcomes) &&\n\t\tvalue.judge.outcomes.every((outcome) => typeof outcome === \"string\") &&\n\t\tisFiniteNumber(value.judge.meanMs) &&\n\t\t(value.judge.tokensPerSecond === undefined || isFiniteNumber(value.judge.tokensPerSecond)) &&\n\t\t(value.capacity === undefined ||\n\t\t\t(isPlainRecord(value.capacity) &&\n\t\t\t\tisFiniteNumber(value.capacity.registeredContextWindow) &&\n\t\t\t\tisFiniteNumber(value.capacity.servedContextWindow) &&\n\t\t\t\tArray.isArray(value.capacity.outcomes) &&\n\t\t\t\tvalue.capacity.outcomes.every((outcome) => typeof outcome === \"string\") &&\n\t\t\t\tisFiniteNumber(value.capacity.meanMs))) &&\n\t\tisFiniteNumber(value.totalCostUsd)\n\t);\n}\n\nfunction parseFitnessHost(value: unknown, hostId: string): Record<string, StoredFitnessReport> | undefined {\n\tif (!isPlainRecord(value)) return undefined;\n\tconst reports: Record<string, StoredFitnessReport> = {};\n\tfor (const [model, candidate] of Object.entries(value)) {\n\t\tif (\n\t\t\t!isPlainRecord(candidate) ||\n\t\t\tcandidate.model !== model ||\n\t\t\ttypeof candidate.at !== \"string\" ||\n\t\t\t!isHostFingerprint(candidate.host) ||\n\t\t\tcandidate.host.id !== hostId ||\n\t\t\t!isFitnessReport(candidate.report)\n\t\t)\n\t\t\tcontinue;\n\t\treports[model] = {\n\t\t\tmodel,\n\t\t\treport: candidate.report,\n\t\t\tat: candidate.at,\n\t\t\thost: candidate.host,\n\t\t};\n\t}\n\treturn reports;\n}\n\nexport class FitnessStore {\n\tprivate readonly storage: HostStateStore<Record<string, StoredFitnessReport>>;\n\n\tconstructor(filePath: string, options?: { fingerprint?: () => HostFingerprint; readOnly?: boolean }) {\n\t\tthis.storage = new HostStateStore({\n\t\t\tfilePath,\n\t\t\tversion: 1,\n\t\t\tfingerprint: options?.fingerprint,\n\t\t\treadOnly: options?.readOnly ?? isWorkerSession(),\n\t\t\tparseHost: parseFitnessHost,\n\t\t});\n\t}\n\n\tstatic forAgentDir(\n\t\tagentDir: string,\n\t\toptions?: { fingerprint?: () => HostFingerprint; readOnly?: boolean },\n\t): FitnessStore {\n\t\treturn new FitnessStore(stateFile(agentDir, \"model-fitness.json\"), options);\n\t}\n\n\t/** Persist the latest report for a model on the CURRENT host. Best-effort, returns the entry. */\n\tsave(model: string, report: ModelFitnessReport, at?: string): StoredFitnessReport {\n\t\treturn this.storage.mutateCurrentHost(\n\t\t\t() => ({}),\n\t\t\t(reports, host) => {\n\t\t\t\tconst entry: StoredFitnessReport = { model, report, at: at ?? new Date().toISOString(), host };\n\t\t\t\treports[model] = entry;\n\t\t\t\treturn { result: entry, changed: true };\n\t\t\t},\n\t\t);\n\t}\n\n\t/** Drop a model's report for the CURRENT host (uninstall cleanup). No-op when absent. */\n\tremove(model: string): void {\n\t\tthis.storage.mutateCurrentHost(\n\t\t\t() => ({}),\n\t\t\t(reports) => {\n\t\t\t\tif (!reports[model]) return { result: undefined, changed: false };\n\t\t\t\tdelete reports[model];\n\t\t\t\treturn { result: undefined, changed: true };\n\t\t\t},\n\t\t);\n\t}\n\n\t/** Reports for the current host (default) or an explicit host id. */\n\tgetForHost(hostId?: string): StoredFitnessReport[] {\n\t\treturn Object.values(this.storage.getHost(hostId) ?? {});\n\t}\n\n\t/** Every stored report across all hosts (for cross-machine comparisons). */\n\tgetAll(): StoredFitnessReport[] {\n\t\treturn this.storage.getAllHosts().flatMap((reports) => Object.values(reports));\n\t}\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface HostFingerprint {
|
|
2
|
+
id: string;
|
|
3
|
+
cpu: string;
|
|
4
|
+
cores: number;
|
|
5
|
+
totalMemGb: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function currentHostFingerprint(): HostFingerprint;
|
|
8
|
+
export declare function isHostFingerprint(value: unknown): value is HostFingerprint;
|
|
9
|
+
export interface HostStateMutation<TResult> {
|
|
10
|
+
result: TResult;
|
|
11
|
+
changed: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface HostStateStoreOptions<THostData> {
|
|
14
|
+
filePath: string;
|
|
15
|
+
version: number;
|
|
16
|
+
fingerprint?: () => HostFingerprint;
|
|
17
|
+
readOnly?: boolean;
|
|
18
|
+
parseHost(value: unknown, hostId: string): THostData | undefined;
|
|
19
|
+
}
|
|
20
|
+
/** Shared lock-safe, atomic substrate for versioned state partitioned by host fingerprint. */
|
|
21
|
+
export declare class HostStateStore<THostData> {
|
|
22
|
+
private readonly filePath;
|
|
23
|
+
private readonly version;
|
|
24
|
+
private readonly fingerprint;
|
|
25
|
+
private readonly readOnly;
|
|
26
|
+
private readonly parseHost;
|
|
27
|
+
constructor(options: HostStateStoreOptions<THostData>);
|
|
28
|
+
private currentHost;
|
|
29
|
+
getHost(hostId?: string): THostData | undefined;
|
|
30
|
+
getAllHosts(): THostData[];
|
|
31
|
+
mutateCurrentHost<TResult>(create: (host: HostFingerprint) => THostData, mutate: (data: THostData, host: HostFingerprint) => HostStateMutation<TResult>): TResult;
|
|
32
|
+
private load;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=host-state-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-state-store.d.ts","sourceRoot":"","sources":["../../../src/core/models/host-state-store.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,sBAAsB,IAAI,eAAe,CAWxD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAY1E;AAOD,MAAM,WAAW,iBAAiB,CAAC,OAAO;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB,CAAC,SAAS;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,eAAe,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CACjE;AAED,8FAA8F;AAC9F,qBAAa,cAAc,CAAC,SAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwB;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4D;IAEtF,YAAY,OAAO,EAAE,qBAAqB,CAAC,SAAS,CAAC,EAMpD;IAED,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,MAAM,SAAwB,GAAG,SAAS,GAAG,SAAS,CAE7D;IAED,WAAW,IAAI,SAAS,EAAE,CAEzB;IAED,iBAAiB,CAAC,OAAO,EACxB,MAAM,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,SAAS,EAC5C,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,KAAK,iBAAiB,CAAC,OAAO,CAAC,GAC5E,OAAO,CAaT;IAED,OAAO,CAAC,IAAI;CAiBZ","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { cpus, totalmem } from \"node:os\";\nimport { withFileLockSync, writeFileAtomicSync } from \"../util/atomic-file.ts\";\nimport { isPlainRecord } from \"../util/value-guards.ts\";\n\nexport interface HostFingerprint {\n\tid: string;\n\tcpu: string;\n\tcores: number;\n\ttotalMemGb: number;\n}\n\nexport function currentHostFingerprint(): HostFingerprint {\n\tconst cpuList = cpus();\n\tconst cpu = (cpuList[0]?.model ?? \"unknown-cpu\").trim();\n\tconst cores = Math.max(1, cpuList.length);\n\tconst totalMemGb = Math.round(totalmem() / 1024 ** 3);\n\tconst id = `${cpu\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\")\n\t\t.slice(0, 48)}-${cores}c-${totalMemGb}g`;\n\treturn { id, cpu, cores, totalMemGb };\n}\n\nexport function isHostFingerprint(value: unknown): value is HostFingerprint {\n\treturn (\n\t\tisPlainRecord(value) &&\n\t\ttypeof value.id === \"string\" &&\n\t\tvalue.id.length > 0 &&\n\t\ttypeof value.cpu === \"string\" &&\n\t\tNumber.isSafeInteger(value.cores) &&\n\t\tNumber(value.cores) > 0 &&\n\t\ttypeof value.totalMemGb === \"number\" &&\n\t\tNumber.isFinite(value.totalMemGb) &&\n\t\tvalue.totalMemGb >= 0\n\t);\n}\n\ninterface HostStateFile<THostData> {\n\tversion: number;\n\thosts: Record<string, THostData>;\n}\n\nexport interface HostStateMutation<TResult> {\n\tresult: TResult;\n\tchanged: boolean;\n}\n\nexport interface HostStateStoreOptions<THostData> {\n\tfilePath: string;\n\tversion: number;\n\tfingerprint?: () => HostFingerprint;\n\treadOnly?: boolean;\n\tparseHost(value: unknown, hostId: string): THostData | undefined;\n}\n\n/** Shared lock-safe, atomic substrate for versioned state partitioned by host fingerprint. */\nexport class HostStateStore<THostData> {\n\tprivate readonly filePath: string;\n\tprivate readonly version: number;\n\tprivate readonly fingerprint: () => HostFingerprint;\n\tprivate readonly readOnly: boolean;\n\tprivate readonly parseHost: (value: unknown, hostId: string) => THostData | undefined;\n\n\tconstructor(options: HostStateStoreOptions<THostData>) {\n\t\tthis.filePath = options.filePath;\n\t\tthis.version = options.version;\n\t\tthis.fingerprint = options.fingerprint ?? currentHostFingerprint;\n\t\tthis.readOnly = options.readOnly ?? false;\n\t\tthis.parseHost = options.parseHost;\n\t}\n\n\tprivate currentHost(): HostFingerprint {\n\t\treturn this.fingerprint();\n\t}\n\n\tgetHost(hostId = this.currentHost().id): THostData | undefined {\n\t\treturn this.load().hosts[hostId];\n\t}\n\n\tgetAllHosts(): THostData[] {\n\t\treturn Object.values(this.load().hosts);\n\t}\n\n\tmutateCurrentHost<TResult>(\n\t\tcreate: (host: HostFingerprint) => THostData,\n\t\tmutate: (data: THostData, host: HostFingerprint) => HostStateMutation<TResult>,\n\t): TResult {\n\t\tconst host = this.currentHost();\n\t\tconst execute = (): TResult => {\n\t\t\tconst file = this.load();\n\t\t\tconst data = file.hosts[host.id] ?? create(host);\n\t\t\tfile.hosts[host.id] = data;\n\t\t\tconst mutation = mutate(data, host);\n\t\t\tif (mutation.changed && !this.readOnly) {\n\t\t\t\twriteFileAtomicSync(this.filePath, `${JSON.stringify(file, null, \"\\t\")}\\n`);\n\t\t\t}\n\t\t\treturn mutation.result;\n\t\t};\n\t\treturn this.readOnly ? execute() : withFileLockSync(this.filePath, execute);\n\t}\n\n\tprivate load(): HostStateFile<THostData> {\n\t\tif (!existsSync(this.filePath)) return { version: this.version, hosts: {} };\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(readFileSync(this.filePath, \"utf-8\"));\n\t\t\tif (!isPlainRecord(parsed) || parsed.version !== this.version || !isPlainRecord(parsed.hosts)) {\n\t\t\t\treturn { version: this.version, hosts: {} };\n\t\t\t}\n\t\t\tconst hosts: Record<string, THostData> = {};\n\t\t\tfor (const [hostId, value] of Object.entries(parsed.hosts)) {\n\t\t\t\tconst host = this.parseHost(value, hostId);\n\t\t\t\tif (host !== undefined) hosts[hostId] = host;\n\t\t\t}\n\t\t\treturn { version: this.version, hosts };\n\t\t} catch {\n\t\t\treturn { version: this.version, hosts: {} };\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { cpus, totalmem } from "node:os";
|
|
3
|
+
import { withFileLockSync, writeFileAtomicSync } from "../util/atomic-file.js";
|
|
4
|
+
import { isPlainRecord } from "../util/value-guards.js";
|
|
5
|
+
export function currentHostFingerprint() {
|
|
6
|
+
const cpuList = cpus();
|
|
7
|
+
const cpu = (cpuList[0]?.model ?? "unknown-cpu").trim();
|
|
8
|
+
const cores = Math.max(1, cpuList.length);
|
|
9
|
+
const totalMemGb = Math.round(totalmem() / 1024 ** 3);
|
|
10
|
+
const id = `${cpu
|
|
11
|
+
.toLowerCase()
|
|
12
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
13
|
+
.replace(/^-+|-+$/g, "")
|
|
14
|
+
.slice(0, 48)}-${cores}c-${totalMemGb}g`;
|
|
15
|
+
return { id, cpu, cores, totalMemGb };
|
|
16
|
+
}
|
|
17
|
+
export function isHostFingerprint(value) {
|
|
18
|
+
return (isPlainRecord(value) &&
|
|
19
|
+
typeof value.id === "string" &&
|
|
20
|
+
value.id.length > 0 &&
|
|
21
|
+
typeof value.cpu === "string" &&
|
|
22
|
+
Number.isSafeInteger(value.cores) &&
|
|
23
|
+
Number(value.cores) > 0 &&
|
|
24
|
+
typeof value.totalMemGb === "number" &&
|
|
25
|
+
Number.isFinite(value.totalMemGb) &&
|
|
26
|
+
value.totalMemGb >= 0);
|
|
27
|
+
}
|
|
28
|
+
/** Shared lock-safe, atomic substrate for versioned state partitioned by host fingerprint. */
|
|
29
|
+
export class HostStateStore {
|
|
30
|
+
filePath;
|
|
31
|
+
version;
|
|
32
|
+
fingerprint;
|
|
33
|
+
readOnly;
|
|
34
|
+
parseHost;
|
|
35
|
+
constructor(options) {
|
|
36
|
+
this.filePath = options.filePath;
|
|
37
|
+
this.version = options.version;
|
|
38
|
+
this.fingerprint = options.fingerprint ?? currentHostFingerprint;
|
|
39
|
+
this.readOnly = options.readOnly ?? false;
|
|
40
|
+
this.parseHost = options.parseHost;
|
|
41
|
+
}
|
|
42
|
+
currentHost() {
|
|
43
|
+
return this.fingerprint();
|
|
44
|
+
}
|
|
45
|
+
getHost(hostId = this.currentHost().id) {
|
|
46
|
+
return this.load().hosts[hostId];
|
|
47
|
+
}
|
|
48
|
+
getAllHosts() {
|
|
49
|
+
return Object.values(this.load().hosts);
|
|
50
|
+
}
|
|
51
|
+
mutateCurrentHost(create, mutate) {
|
|
52
|
+
const host = this.currentHost();
|
|
53
|
+
const execute = () => {
|
|
54
|
+
const file = this.load();
|
|
55
|
+
const data = file.hosts[host.id] ?? create(host);
|
|
56
|
+
file.hosts[host.id] = data;
|
|
57
|
+
const mutation = mutate(data, host);
|
|
58
|
+
if (mutation.changed && !this.readOnly) {
|
|
59
|
+
writeFileAtomicSync(this.filePath, `${JSON.stringify(file, null, "\t")}\n`);
|
|
60
|
+
}
|
|
61
|
+
return mutation.result;
|
|
62
|
+
};
|
|
63
|
+
return this.readOnly ? execute() : withFileLockSync(this.filePath, execute);
|
|
64
|
+
}
|
|
65
|
+
load() {
|
|
66
|
+
if (!existsSync(this.filePath))
|
|
67
|
+
return { version: this.version, hosts: {} };
|
|
68
|
+
try {
|
|
69
|
+
const parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
|
|
70
|
+
if (!isPlainRecord(parsed) || parsed.version !== this.version || !isPlainRecord(parsed.hosts)) {
|
|
71
|
+
return { version: this.version, hosts: {} };
|
|
72
|
+
}
|
|
73
|
+
const hosts = {};
|
|
74
|
+
for (const [hostId, value] of Object.entries(parsed.hosts)) {
|
|
75
|
+
const host = this.parseHost(value, hostId);
|
|
76
|
+
if (host !== undefined)
|
|
77
|
+
hosts[hostId] = host;
|
|
78
|
+
}
|
|
79
|
+
return { version: this.version, hosts };
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return { version: this.version, hosts: {} };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=host-state-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-state-store.js","sourceRoot":"","sources":["../../../src/core/models/host-state-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AASxD,MAAM,UAAU,sBAAsB,GAAoB;IACzD,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC;IACvB,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,aAAa,CAAC,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC;IACtD,MAAM,EAAE,GAAG,GAAG,GAAG;SACf,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,KAAK,UAAU,GAAG,CAAC;IAC1C,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAAA,CACtC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc,EAA4B;IAC3E,OAAO,CACN,aAAa,CAAC,KAAK,CAAC;QACpB,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ;QAC5B,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC;QACnB,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ;QAC7B,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;QACvB,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QACpC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC;QACjC,KAAK,CAAC,UAAU,IAAI,CAAC,CACrB,CAAC;AAAA,CACF;AAoBD,8FAA8F;AAC9F,MAAM,OAAO,cAAc;IACT,QAAQ,CAAS;IACjB,OAAO,CAAS;IAChB,WAAW,CAAwB;IACnC,QAAQ,CAAU;IAClB,SAAS,CAA4D;IAEtF,YAAY,OAAyC,EAAE;QACtD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,sBAAsB,CAAC;QACjE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC;QAC1C,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAAA,CACnC;IAEO,WAAW,GAAoB;QACtC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAAA,CAC1B;IAED,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,EAAyB;QAC9D,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAAA,CACjC;IAED,WAAW,GAAgB;QAC1B,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;IAAA,CACxC;IAED,iBAAiB,CAChB,MAA4C,EAC5C,MAA8E,EACpE;QACV,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,GAAY,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;YACjD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;YAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACpC,IAAI,QAAQ,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACxC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7E,CAAC;YACD,OAAO,QAAQ,CAAC,MAAM,CAAC;QAAA,CACvB,CAAC;QACF,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAAA,CAC5E;IAEO,IAAI,GAA6B;QACxC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC5E,IAAI,CAAC;YACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;YACzE,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/F,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YAC7C,CAAC;YACD,MAAM,KAAK,GAA8B,EAAE,CAAC;YAC5C,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC3C,IAAI,IAAI,KAAK,SAAS;oBAAE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;YAC9C,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC7C,CAAC;IAAA,CACD;CACD","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { cpus, totalmem } from \"node:os\";\nimport { withFileLockSync, writeFileAtomicSync } from \"../util/atomic-file.ts\";\nimport { isPlainRecord } from \"../util/value-guards.ts\";\n\nexport interface HostFingerprint {\n\tid: string;\n\tcpu: string;\n\tcores: number;\n\ttotalMemGb: number;\n}\n\nexport function currentHostFingerprint(): HostFingerprint {\n\tconst cpuList = cpus();\n\tconst cpu = (cpuList[0]?.model ?? \"unknown-cpu\").trim();\n\tconst cores = Math.max(1, cpuList.length);\n\tconst totalMemGb = Math.round(totalmem() / 1024 ** 3);\n\tconst id = `${cpu\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\")\n\t\t.slice(0, 48)}-${cores}c-${totalMemGb}g`;\n\treturn { id, cpu, cores, totalMemGb };\n}\n\nexport function isHostFingerprint(value: unknown): value is HostFingerprint {\n\treturn (\n\t\tisPlainRecord(value) &&\n\t\ttypeof value.id === \"string\" &&\n\t\tvalue.id.length > 0 &&\n\t\ttypeof value.cpu === \"string\" &&\n\t\tNumber.isSafeInteger(value.cores) &&\n\t\tNumber(value.cores) > 0 &&\n\t\ttypeof value.totalMemGb === \"number\" &&\n\t\tNumber.isFinite(value.totalMemGb) &&\n\t\tvalue.totalMemGb >= 0\n\t);\n}\n\ninterface HostStateFile<THostData> {\n\tversion: number;\n\thosts: Record<string, THostData>;\n}\n\nexport interface HostStateMutation<TResult> {\n\tresult: TResult;\n\tchanged: boolean;\n}\n\nexport interface HostStateStoreOptions<THostData> {\n\tfilePath: string;\n\tversion: number;\n\tfingerprint?: () => HostFingerprint;\n\treadOnly?: boolean;\n\tparseHost(value: unknown, hostId: string): THostData | undefined;\n}\n\n/** Shared lock-safe, atomic substrate for versioned state partitioned by host fingerprint. */\nexport class HostStateStore<THostData> {\n\tprivate readonly filePath: string;\n\tprivate readonly version: number;\n\tprivate readonly fingerprint: () => HostFingerprint;\n\tprivate readonly readOnly: boolean;\n\tprivate readonly parseHost: (value: unknown, hostId: string) => THostData | undefined;\n\n\tconstructor(options: HostStateStoreOptions<THostData>) {\n\t\tthis.filePath = options.filePath;\n\t\tthis.version = options.version;\n\t\tthis.fingerprint = options.fingerprint ?? currentHostFingerprint;\n\t\tthis.readOnly = options.readOnly ?? false;\n\t\tthis.parseHost = options.parseHost;\n\t}\n\n\tprivate currentHost(): HostFingerprint {\n\t\treturn this.fingerprint();\n\t}\n\n\tgetHost(hostId = this.currentHost().id): THostData | undefined {\n\t\treturn this.load().hosts[hostId];\n\t}\n\n\tgetAllHosts(): THostData[] {\n\t\treturn Object.values(this.load().hosts);\n\t}\n\n\tmutateCurrentHost<TResult>(\n\t\tcreate: (host: HostFingerprint) => THostData,\n\t\tmutate: (data: THostData, host: HostFingerprint) => HostStateMutation<TResult>,\n\t): TResult {\n\t\tconst host = this.currentHost();\n\t\tconst execute = (): TResult => {\n\t\t\tconst file = this.load();\n\t\t\tconst data = file.hosts[host.id] ?? create(host);\n\t\t\tfile.hosts[host.id] = data;\n\t\t\tconst mutation = mutate(data, host);\n\t\t\tif (mutation.changed && !this.readOnly) {\n\t\t\t\twriteFileAtomicSync(this.filePath, `${JSON.stringify(file, null, \"\\t\")}\\n`);\n\t\t\t}\n\t\t\treturn mutation.result;\n\t\t};\n\t\treturn this.readOnly ? execute() : withFileLockSync(this.filePath, execute);\n\t}\n\n\tprivate load(): HostStateFile<THostData> {\n\t\tif (!existsSync(this.filePath)) return { version: this.version, hosts: {} };\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(readFileSync(this.filePath, \"utf-8\"));\n\t\t\tif (!isPlainRecord(parsed) || parsed.version !== this.version || !isPlainRecord(parsed.hosts)) {\n\t\t\t\treturn { version: this.version, hosts: {} };\n\t\t\t}\n\t\t\tconst hosts: Record<string, THostData> = {};\n\t\t\tfor (const [hostId, value] of Object.entries(parsed.hosts)) {\n\t\t\t\tconst host = this.parseHost(value, hostId);\n\t\t\t\tif (host !== undefined) hosts[hostId] = host;\n\t\t\t}\n\t\t\treturn { version: this.version, hosts };\n\t\t} catch {\n\t\t\treturn { version: this.version, hosts: {} };\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type AgentIdentityContract, type AgentResumeContext } from "./contracts.ts";
|
|
2
|
+
export interface PiResumeLaunchSpec {
|
|
3
|
+
executable: string;
|
|
4
|
+
args: readonly string[];
|
|
5
|
+
cwd: string;
|
|
6
|
+
env: Readonly<Record<string, string>>;
|
|
7
|
+
}
|
|
8
|
+
export interface BuildPiResumeLaunchSpecOptions {
|
|
9
|
+
executable?: string;
|
|
10
|
+
argsPrefix?: readonly string[];
|
|
11
|
+
parentPid: number;
|
|
12
|
+
parentSessionId: string;
|
|
13
|
+
taskRef?: string;
|
|
14
|
+
wakePrompt?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function isAgentIdentity(value: unknown): value is AgentIdentityContract;
|
|
17
|
+
/** Build and validate the one logical identity shared by orchestration and process supervision. */
|
|
18
|
+
export declare function createAgentIdentity(agentId: string, resumeContext: AgentResumeContext): AgentIdentityContract;
|
|
19
|
+
/**
|
|
20
|
+
* Build an argv-safe launch specification for the exact persisted Pi session behind a logical
|
|
21
|
+
* agent. The caller passes argv directly to spawn; no shell quoting or command string is involved.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildPiResumeLaunchSpec(agent: AgentIdentityContract, options: BuildPiResumeLaunchSpecOptions): PiResumeLaunchSpec;
|
|
24
|
+
//# sourceMappingURL=agent-resume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-resume.d.ts","sourceRoot":"","sources":["../../../src/core/orchestration/agent-resume.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,kBAAkB,EAAyB,MAAM,gBAAgB,CAAC;AAE5G,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,8BAA8B;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAiC9E;AAED,mGAAmG;AACnG,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,GAAG,qBAAqB,CAQ7G;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,qBAAqB,EAC5B,OAAO,EAAE,8BAA8B,GACrC,kBAAkB,CA2BpB","sourcesContent":["import { PI_ORCHESTRATION_AGENT_ID_ENV } from \"../process-identity.ts\";\nimport { isPlainRecord } from \"../util/value-guards.ts\";\nimport { type AgentIdentityContract, type AgentResumeContext, isResourcePointerKind } from \"./contracts.ts\";\n\nexport interface PiResumeLaunchSpec {\n\texecutable: string;\n\targs: readonly string[];\n\tcwd: string;\n\tenv: Readonly<Record<string, string>>;\n}\n\nexport interface BuildPiResumeLaunchSpecOptions {\n\texecutable?: string;\n\targsPrefix?: readonly string[];\n\tparentPid: number;\n\tparentSessionId: string;\n\ttaskRef?: string;\n\twakePrompt?: string;\n}\n\nfunction isOptionalString(value: unknown): value is string | undefined {\n\treturn value === undefined || typeof value === \"string\";\n}\n\nexport function isAgentIdentity(value: unknown): value is AgentIdentityContract {\n\tif (!isPlainRecord(value) || !isPlainRecord(value.resumeContext)) return false;\n\tconst context = value.resumeContext;\n\treturn (\n\t\ttypeof value.agentId === \"string\" &&\n\t\tvalue.agentId.trim().length > 0 &&\n\t\t(context.provider === \"pi\" || context.provider === \"external\") &&\n\t\ttypeof context.sessionId === \"string\" &&\n\t\tcontext.sessionId.trim().length > 0 &&\n\t\ttypeof context.cwd === \"string\" &&\n\t\tcontext.cwd.trim().length > 0 &&\n\t\tisOptionalString(context.sessionDir) &&\n\t\tisOptionalString(context.sessionFile) &&\n\t\tisOptionalString(context.worktreeLaneKey) &&\n\t\tisOptionalString(context.orchestrationProfileId) &&\n\t\tisOptionalString(context.modelRef) &&\n\t\tisOptionalString(context.latestCheckpointId) &&\n\t\tArray.isArray(context.resourceProfileNames) &&\n\t\tcontext.resourceProfileNames.every((name) => typeof name === \"string\" && name.trim().length > 0) &&\n\t\tArray.isArray(context.contextPointers) &&\n\t\tcontext.contextPointers.every(\n\t\t\t(pointer) =>\n\t\t\t\tisPlainRecord(pointer) &&\n\t\t\t\ttypeof pointer.id === \"string\" &&\n\t\t\t\tpointer.id.trim().length > 0 &&\n\t\t\t\tisResourcePointerKind(pointer.kind) &&\n\t\t\t\ttypeof pointer.uri === \"string\" &&\n\t\t\t\tpointer.uri.trim().length > 0 &&\n\t\t\t\ttypeof pointer.readOnly === \"boolean\" &&\n\t\t\t\tisOptionalString(pointer.digest) &&\n\t\t\t\t(pointer.metadata === undefined || isPlainRecord(pointer.metadata)),\n\t\t)\n\t);\n}\n\n/** Build and validate the one logical identity shared by orchestration and process supervision. */\nexport function createAgentIdentity(agentId: string, resumeContext: AgentResumeContext): AgentIdentityContract {\n\tconst normalizedAgentId = agentId.trim();\n\tif (!normalizedAgentId) throw new TypeError(\"A logical agent id is required.\");\n\tif (!resumeContext.sessionId.trim()) throw new TypeError(\"An agent session id is required.\");\n\tif (!resumeContext.cwd.trim()) throw new TypeError(\"An agent working directory is required.\");\n\tconst identity = { agentId: normalizedAgentId, resumeContext: structuredClone(resumeContext) };\n\tif (!isAgentIdentity(identity)) throw new TypeError(\"Agent resume context is invalid.\");\n\treturn identity;\n}\n\n/**\n * Build an argv-safe launch specification for the exact persisted Pi session behind a logical\n * agent. The caller passes argv directly to spawn; no shell quoting or command string is involved.\n */\nexport function buildPiResumeLaunchSpec(\n\tagent: AgentIdentityContract,\n\toptions: BuildPiResumeLaunchSpecOptions,\n): PiResumeLaunchSpec {\n\tconst identity = createAgentIdentity(agent.agentId, agent.resumeContext);\n\tconst context = identity.resumeContext;\n\tif (context.provider !== \"pi\") throw new TypeError(`Agent '${identity.agentId}' is not backed by a Pi session.`);\n\tif (!Number.isSafeInteger(options.parentPid) || options.parentPid <= 0) {\n\t\tthrow new TypeError(\"A positive parent pid is required to resume a Pi agent.\");\n\t}\n\tif (!options.parentSessionId.trim()) throw new TypeError(\"A parent session id is required to resume a Pi agent.\");\n\tconst args: string[] = [...(options.argsPrefix ?? [])];\n\tif (context.sessionDir) args.push(\"--session-dir\", context.sessionDir);\n\targs.push(\"--session\", context.sessionFile ?? context.sessionId);\n\targs.push(\"--parent-pid\", String(options.parentPid));\n\targs.push(\"--parent-session\", options.parentSessionId);\n\tif (options.taskRef?.trim()) args.push(\"--task-ref\", options.taskRef.trim());\n\tif (context.worktreeLaneKey) args.push(\"--worktree-lane\", context.worktreeLaneKey);\n\tif (context.orchestrationProfileId) {\n\t\targs.push(\"--orchestration-profile\", context.orchestrationProfileId);\n\t} else if (context.resourceProfileNames.length > 0) {\n\t\targs.push(\"--resource-profile\", context.resourceProfileNames.join(\",\"));\n\t}\n\tif (options.wakePrompt?.trim()) args.push(\"--print\", options.wakePrompt.trim());\n\treturn {\n\t\texecutable: options.executable ?? \"pi\",\n\t\targs,\n\t\tcwd: context.cwd,\n\t\tenv: { PI_SESSION_ROLE: \"worker\", [PI_ORCHESTRATION_AGENT_ID_ENV]: identity.agentId },\n\t};\n}\n"]}
|