@caupulican/pi-adaptative 0.94.1 → 0.95.0
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 +39 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/README.md +32 -13
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +7 -4
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +173 -293
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +247 -392
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.d.ts +52 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.d.ts.map +1 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.js +118 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.js.map +1 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.ts +169 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/templates/builder-validator.json +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/templates/provider-prompt-smoke.json +1 -1
- package/dist/bundled-resources/skills/pi-harness-learning/SKILL.md +13 -7
- package/dist/bundled-resources/skills/worker-profile-writer/SKILL.md +11 -11
- package/dist/core/agent-session.d.ts +11 -41
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +93 -160
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.d.ts +6 -1
- package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.js +26 -25
- package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
- package/dist/core/autonomy/lane-private-paths.d.ts.map +1 -1
- package/dist/core/autonomy/lane-private-paths.js +2 -1
- package/dist/core/autonomy/lane-private-paths.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts +8 -8
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +45 -30
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/worker-session-private-scope.d.ts +12 -0
- package/dist/core/autonomy/worker-session-private-scope.d.ts.map +1 -0
- package/dist/core/autonomy/worker-session-private-scope.js +42 -0
- package/dist/core/autonomy/worker-session-private-scope.js.map +1 -0
- package/dist/core/autonomy/worker-tool-adapter-registry.d.ts +65 -0
- package/dist/core/autonomy/worker-tool-adapter-registry.d.ts.map +1 -0
- package/dist/core/autonomy/worker-tool-adapter-registry.js +145 -0
- package/dist/core/autonomy/worker-tool-adapter-registry.js.map +1 -0
- package/dist/core/background-lane-controller.d.ts +1 -1
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +1 -1
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/background-tool-task-controller.d.ts +8 -2
- package/dist/core/background-tool-task-controller.d.ts.map +1 -1
- package/dist/core/background-tool-task-controller.js +10 -2
- package/dist/core/background-tool-task-controller.js.map +1 -1
- package/dist/core/cost-guard-controller.d.ts +37 -0
- package/dist/core/cost-guard-controller.d.ts.map +1 -0
- package/dist/core/cost-guard-controller.js +71 -0
- package/dist/core/cost-guard-controller.js.map +1 -0
- package/dist/core/cost-guard.d.ts +9 -4
- package/dist/core/cost-guard.d.ts.map +1 -1
- package/dist/core/cost-guard.js +7 -3
- package/dist/core/cost-guard.js.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.js +0 -1
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
- package/dist/core/delegation/worker-authority-resolver.d.ts +16 -3
- package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -1
- package/dist/core/delegation/worker-authority-resolver.js +114 -55
- package/dist/core/delegation/worker-authority-resolver.js.map +1 -1
- package/dist/core/delegation/worker-claim.d.ts +1 -2
- package/dist/core/delegation/worker-claim.d.ts.map +1 -1
- package/dist/core/delegation/worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts +19 -6
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +125 -40
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-delegation-request.d.ts +3 -3
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-request.js +13 -19
- package/dist/core/delegation/worker-delegation-request.js.map +1 -1
- package/dist/core/delegation/worker-execution-policy.d.ts +3 -2
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
- package/dist/core/delegation/worker-execution-policy.js +54 -39
- package/dist/core/delegation/worker-execution-policy.js.map +1 -1
- package/dist/core/delegation/worker-fleet-limits.d.ts +3 -3
- package/dist/core/delegation/worker-fleet-limits.d.ts.map +1 -1
- package/dist/core/delegation/worker-fleet-limits.js +7 -7
- package/dist/core/delegation/worker-fleet-limits.js.map +1 -1
- package/dist/core/delegation/worker-machine-scope.d.ts +12 -0
- package/dist/core/delegation/worker-machine-scope.d.ts.map +1 -0
- package/dist/core/delegation/worker-machine-scope.js +38 -0
- package/dist/core/delegation/worker-machine-scope.js.map +1 -0
- package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.js +6 -1
- package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +5 -7
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +1 -4
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +3 -2
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-write-reservation-coordinator.js +50 -25
- package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -1
- package/dist/core/durable-custom-message-turn-controller.d.ts +6 -0
- package/dist/core/durable-custom-message-turn-controller.d.ts.map +1 -1
- package/dist/core/durable-custom-message-turn-controller.js +38 -15
- package/dist/core/durable-custom-message-turn-controller.js.map +1 -1
- package/dist/core/extension-binding-controller.d.ts +5 -1
- package/dist/core/extension-binding-controller.d.ts.map +1 -1
- package/dist/core/extension-binding-controller.js +15 -0
- package/dist/core/extension-binding-controller.js.map +1 -1
- package/dist/core/extensions/factory-runtime.d.ts.map +1 -1
- package/dist/core/extensions/factory-runtime.js +5 -0
- package/dist/core/extensions/factory-runtime.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +1 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +8 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.d.ts +14 -0
- package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.js +188 -72
- package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts +2 -0
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-session-controller.js +8 -0
- package/dist/core/goals/goal-session-controller.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts +5 -4
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +23 -19
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/learning/auto-learn-settings.d.ts +84 -0
- package/dist/core/learning/auto-learn-settings.d.ts.map +1 -0
- package/dist/core/learning/auto-learn-settings.js +66 -0
- package/dist/core/learning/auto-learn-settings.js.map +1 -0
- package/dist/core/learning/reflection-engine.d.ts +4 -0
- package/dist/core/learning/reflection-engine.d.ts.map +1 -1
- package/dist/core/learning/reflection-engine.js +48 -10
- package/dist/core/learning/reflection-engine.js.map +1 -1
- package/dist/core/local-prefix-warm-controller.d.ts +24 -0
- package/dist/core/local-prefix-warm-controller.d.ts.map +1 -0
- package/dist/core/local-prefix-warm-controller.js +79 -0
- package/dist/core/local-prefix-warm-controller.js.map +1 -0
- package/dist/core/memory/providers/file-store.d.ts +2 -0
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +71 -15
- package/dist/core/memory/providers/file-store.js.map +1 -1
- package/dist/core/memory/worker-memory-tools.d.ts +5 -0
- package/dist/core/memory/worker-memory-tools.d.ts.map +1 -0
- package/dist/core/memory/worker-memory-tools.js +5 -0
- package/dist/core/memory/worker-memory-tools.js.map +1 -0
- package/dist/core/model-capability.d.ts +7 -0
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +12 -0
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -10
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +3 -2
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +3 -2
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/orchestration/contracts.d.ts +16 -12
- package/dist/core/orchestration/contracts.d.ts.map +1 -1
- package/dist/core/orchestration/contracts.js +2 -2
- package/dist/core/orchestration/contracts.js.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts +2 -2
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.js +6 -1
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
- package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
- package/dist/core/orchestration/profile-registry.js +14 -0
- package/dist/core/orchestration/profile-registry.js.map +1 -1
- package/dist/core/orchestration/task-profile-writer.d.ts +7 -4
- package/dist/core/orchestration/task-profile-writer.d.ts.map +1 -1
- package/dist/core/orchestration/task-profile-writer.js +71 -59
- package/dist/core/orchestration/task-profile-writer.js.map +1 -1
- package/dist/core/orchestration/thinking-level-schema.d.ts +7 -0
- package/dist/core/orchestration/thinking-level-schema.d.ts.map +1 -0
- package/dist/core/orchestration/thinking-level-schema.js +19 -0
- package/dist/core/orchestration/thinking-level-schema.js.map +1 -0
- package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.js +12 -5
- package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
- package/dist/core/provider-prompt-contracts.d.ts +1 -4
- package/dist/core/provider-prompt-contracts.d.ts.map +1 -1
- package/dist/core/provider-prompt-contracts.js +4 -10
- package/dist/core/provider-prompt-contracts.js.map +1 -1
- package/dist/core/provider-request-context-controller.d.ts +2 -0
- package/dist/core/provider-request-context-controller.d.ts.map +1 -1
- package/dist/core/provider-request-context-controller.js +10 -3
- package/dist/core/provider-request-context-controller.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +56 -27
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +206 -117
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +1 -0
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +25 -14
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.js +55 -10
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
- package/dist/core/session-role.d.ts +6 -8
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js +8 -18
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/settings-manager.d.ts +13 -16
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +53 -50
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skill-vault.d.ts +15 -0
- package/dist/core/skill-vault.d.ts.map +1 -1
- package/dist/core/skill-vault.js +79 -45
- package/dist/core/skill-vault.js.map +1 -1
- package/dist/core/skills.d.ts +3 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +6 -6
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +2 -0
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.js +52 -12
- package/dist/core/system-prompt-builder.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tool-capability-policy.d.ts +3 -0
- package/dist/core/tool-capability-policy.d.ts.map +1 -1
- package/dist/core/tool-capability-policy.js +13 -2
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/toolkit/script-runner.d.ts +2 -1
- package/dist/core/toolkit/script-runner.d.ts.map +1 -1
- package/dist/core/toolkit/script-runner.js +10 -2
- package/dist/core/toolkit/script-runner.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts +1 -1
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +1 -1
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +4 -15
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +111 -73
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/goal.d.ts +3 -4
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +24 -7
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/profile-writer.d.ts +2 -8
- package/dist/core/tools/profile-writer.d.ts.map +1 -1
- package/dist/core/tools/profile-writer.js +6 -18
- package/dist/core/tools/profile-writer.js.map +1 -1
- package/dist/core/tools/run-toolkit-script.d.ts +1 -1
- package/dist/core/tools/run-toolkit-script.d.ts.map +1 -1
- package/dist/core/tools/run-toolkit-script.js +2 -2
- package/dist/core/tools/run-toolkit-script.js.map +1 -1
- package/dist/core/tools/skill-audit.d.ts +28 -1
- package/dist/core/tools/skill-audit.d.ts.map +1 -1
- package/dist/core/tools/skill-audit.js +56 -12
- package/dist/core/tools/skill-audit.js.map +1 -1
- package/dist/core/tools/skill.d.ts +12 -1
- package/dist/core/tools/skill.d.ts.map +1 -1
- package/dist/core/tools/skill.js +52 -0
- package/dist/core/tools/skill.js.map +1 -1
- package/dist/core/tools/skillify.d.ts.map +1 -1
- package/dist/core/tools/skillify.js +16 -7
- package/dist/core/tools/skillify.js.map +1 -1
- package/dist/core/tools/task-steps.js +1 -1
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tmux-dispatch.d.ts +4 -16
- package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
- package/dist/core/tools/tmux-dispatch.js +5 -20
- package/dist/core/tools/tmux-dispatch.js.map +1 -1
- package/dist/core/worktree-sync/codes.d.ts +1 -2
- package/dist/core/worktree-sync/codes.d.ts.map +1 -1
- package/dist/core/worktree-sync/codes.js +1 -2
- package/dist/core/worktree-sync/codes.js.map +1 -1
- package/dist/core/worktree-sync/lane-gate.d.ts +4 -8
- package/dist/core/worktree-sync/lane-gate.d.ts.map +1 -1
- package/dist/core/worktree-sync/lane-gate.js +5 -51
- package/dist/core/worktree-sync/lane-gate.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.d.ts +6 -7
- package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.js +30 -207
- package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
- package/dist/modes/interactive/autonomy-commands.js +2 -2
- package/dist/modes/interactive/autonomy-commands.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +17 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.js +2 -2
- package/dist/modes/interactive/components/fitness-role-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +150 -73
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/report-commands.d.ts.map +1 -1
- package/dist/modes/interactive/report-commands.js +8 -4
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -1
- package/dist/modes/interactive/settings-selector-flow.js +10 -0
- package/dist/modes/interactive/settings-selector-flow.js.map +1 -1
- package/docs/extensions.md +8 -0
- package/docs/harness-architecture.md +28 -32
- package/docs/index.md +1 -1
- package/docs/process-matrix.md +8 -6
- package/docs/resources.md +1 -1
- package/docs/settings.md +61 -51
- package/docs/tmux-agent-manager.md +47 -40
- package/docs/usage.md +1 -1
- package/docs/worker-profiles.md +8 -6
- package/docs/worktree-sync.md +26 -20
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +0 -133
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +0 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +0 -199
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +0 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +0 -312
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** The authoritative Auto Learn defaults used by runtime resolution and settings UI. */
|
|
2
|
+
export const DEFAULT_AUTO_LEARN_SETTINGS = {
|
|
3
|
+
enabled: true,
|
|
4
|
+
model: "active",
|
|
5
|
+
thinkingLevel: "low",
|
|
6
|
+
longSessionMessages: 32,
|
|
7
|
+
longSessionContextPercent: 70,
|
|
8
|
+
cooldownMinutes: 24 * 60,
|
|
9
|
+
leaseMinutes: 90,
|
|
10
|
+
maxConcurrentLearners: 1,
|
|
11
|
+
applyHighConfidence: false,
|
|
12
|
+
reflectionReview: true,
|
|
13
|
+
reflectionMinToolCalls: 12,
|
|
14
|
+
reflectionCooldownMinutes: 24 * 60,
|
|
15
|
+
complexTaskToolCalls: 12,
|
|
16
|
+
};
|
|
17
|
+
export const AUTONOMY_AUTO_LEARN_PRESETS = {
|
|
18
|
+
off: DEFAULT_AUTO_LEARN_SETTINGS,
|
|
19
|
+
safe: {
|
|
20
|
+
...DEFAULT_AUTO_LEARN_SETTINGS,
|
|
21
|
+
longSessionMessages: 64,
|
|
22
|
+
longSessionContextPercent: 85,
|
|
23
|
+
leaseMinutes: 60,
|
|
24
|
+
},
|
|
25
|
+
balanced: {
|
|
26
|
+
...DEFAULT_AUTO_LEARN_SETTINGS,
|
|
27
|
+
longSessionMessages: 64,
|
|
28
|
+
longSessionContextPercent: 85,
|
|
29
|
+
},
|
|
30
|
+
full: {
|
|
31
|
+
...DEFAULT_AUTO_LEARN_SETTINGS,
|
|
32
|
+
longSessionMessages: 64,
|
|
33
|
+
longSessionContextPercent: 85,
|
|
34
|
+
applyHighConfidence: true,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
export function getAutoLearnPreset(mode, current = {}) {
|
|
38
|
+
const preset = AUTONOMY_AUTO_LEARN_PRESETS[mode] ?? AUTONOMY_AUTO_LEARN_PRESETS.off;
|
|
39
|
+
return { ...preset, model: current.model?.trim() || preset.model };
|
|
40
|
+
}
|
|
41
|
+
export function resolveAutoLearnSettings(mode, settings = {}) {
|
|
42
|
+
const preset = getAutoLearnPreset(mode, settings);
|
|
43
|
+
return {
|
|
44
|
+
enabled: settings.enabled ?? preset.enabled,
|
|
45
|
+
model: settings.model?.trim() || preset.model,
|
|
46
|
+
thinkingLevel: settings.thinkingLevel ?? preset.thinkingLevel,
|
|
47
|
+
longSessionMessages: settings.longSessionMessages ?? preset.longSessionMessages,
|
|
48
|
+
longSessionContextPercent: settings.longSessionContextPercent ?? preset.longSessionContextPercent,
|
|
49
|
+
cooldownMinutes: settings.cooldownMinutes ?? preset.cooldownMinutes,
|
|
50
|
+
leaseMinutes: settings.leaseMinutes ?? preset.leaseMinutes,
|
|
51
|
+
maxConcurrentLearners: settings.maxConcurrentLearners ?? preset.maxConcurrentLearners,
|
|
52
|
+
applyHighConfidence: settings.applyHighConfidence ?? preset.applyHighConfidence,
|
|
53
|
+
reflectionReview: settings.reflectionReview ?? preset.reflectionReview,
|
|
54
|
+
reflectionMinToolCalls: settings.reflectionMinToolCalls ?? preset.reflectionMinToolCalls,
|
|
55
|
+
reflectionCooldownMinutes: settings.reflectionCooldownMinutes ?? preset.reflectionCooldownMinutes,
|
|
56
|
+
complexTaskToolCalls: settings.complexTaskToolCalls ?? preset.complexTaskToolCalls,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** One settings/environment gate shared by root prompt construction and current-turn cue delivery. */
|
|
60
|
+
export function isCurrentSessionReflectionEnabled(settings, env = process.env) {
|
|
61
|
+
return (settings.enabled &&
|
|
62
|
+
settings.reflectionReview &&
|
|
63
|
+
env.PI_NATIVE_REFLECTION !== "0" &&
|
|
64
|
+
env.PI_AUTO_LEARN_CHILD !== "1");
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=auto-learn-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-learn-settings.js","sourceRoot":"","sources":["../../../src/core/learning/auto-learn-settings.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AutoLearnSettings, AutonomyMode } from \"../settings-manager.ts\";\n\n/** The authoritative Auto Learn defaults used by runtime resolution and settings UI. */\nexport const DEFAULT_AUTO_LEARN_SETTINGS = {\n\tenabled: true,\n\tmodel: \"active\",\n\tthinkingLevel: \"low\",\n\tlongSessionMessages: 32,\n\tlongSessionContextPercent: 70,\n\tcooldownMinutes: 24 * 60,\n\tleaseMinutes: 90,\n\tmaxConcurrentLearners: 1,\n\tapplyHighConfidence: false,\n\treflectionReview: true,\n\treflectionMinToolCalls: 12,\n\treflectionCooldownMinutes: 24 * 60,\n\tcomplexTaskToolCalls: 12,\n} as const satisfies Required<AutoLearnSettings>;\n\nexport const AUTONOMY_AUTO_LEARN_PRESETS = {\n\toff: DEFAULT_AUTO_LEARN_SETTINGS,\n\tsafe: {\n\t\t...DEFAULT_AUTO_LEARN_SETTINGS,\n\t\tlongSessionMessages: 64,\n\t\tlongSessionContextPercent: 85,\n\t\tleaseMinutes: 60,\n\t},\n\tbalanced: {\n\t\t...DEFAULT_AUTO_LEARN_SETTINGS,\n\t\tlongSessionMessages: 64,\n\t\tlongSessionContextPercent: 85,\n\t},\n\tfull: {\n\t\t...DEFAULT_AUTO_LEARN_SETTINGS,\n\t\tlongSessionMessages: 64,\n\t\tlongSessionContextPercent: 85,\n\t\tapplyHighConfidence: true,\n\t},\n} as const satisfies Record<AutonomyMode, Required<AutoLearnSettings>>;\n\nexport function getAutoLearnPreset(mode: AutonomyMode, current: AutoLearnSettings = {}): Required<AutoLearnSettings> {\n\tconst preset = AUTONOMY_AUTO_LEARN_PRESETS[mode] ?? AUTONOMY_AUTO_LEARN_PRESETS.off;\n\treturn { ...preset, model: current.model?.trim() || preset.model };\n}\n\nexport function resolveAutoLearnSettings(\n\tmode: AutonomyMode,\n\tsettings: AutoLearnSettings = {},\n): Required<AutoLearnSettings> {\n\tconst preset = getAutoLearnPreset(mode, settings);\n\treturn {\n\t\tenabled: settings.enabled ?? preset.enabled,\n\t\tmodel: settings.model?.trim() || preset.model,\n\t\tthinkingLevel: settings.thinkingLevel ?? preset.thinkingLevel,\n\t\tlongSessionMessages: settings.longSessionMessages ?? preset.longSessionMessages,\n\t\tlongSessionContextPercent: settings.longSessionContextPercent ?? preset.longSessionContextPercent,\n\t\tcooldownMinutes: settings.cooldownMinutes ?? preset.cooldownMinutes,\n\t\tleaseMinutes: settings.leaseMinutes ?? preset.leaseMinutes,\n\t\tmaxConcurrentLearners: settings.maxConcurrentLearners ?? preset.maxConcurrentLearners,\n\t\tapplyHighConfidence: settings.applyHighConfidence ?? preset.applyHighConfidence,\n\t\treflectionReview: settings.reflectionReview ?? preset.reflectionReview,\n\t\treflectionMinToolCalls: settings.reflectionMinToolCalls ?? preset.reflectionMinToolCalls,\n\t\treflectionCooldownMinutes: settings.reflectionCooldownMinutes ?? preset.reflectionCooldownMinutes,\n\t\tcomplexTaskToolCalls: settings.complexTaskToolCalls ?? preset.complexTaskToolCalls,\n\t};\n}\n\n/** One settings/environment gate shared by root prompt construction and current-turn cue delivery. */\nexport function isCurrentSessionReflectionEnabled(\n\tsettings: Pick<Required<AutoLearnSettings>, \"enabled\" | \"reflectionReview\">,\n\tenv: NodeJS.ProcessEnv = process.env,\n): boolean {\n\treturn (\n\t\tsettings.enabled &&\n\t\tsettings.reflectionReview &&\n\t\tenv.PI_NATIVE_REFLECTION !== \"0\" &&\n\t\tenv.PI_AUTO_LEARN_CHILD !== \"1\"\n\t);\n}\n"]}
|
|
@@ -73,6 +73,10 @@ export interface ReflectionResult {
|
|
|
73
73
|
usage: Usage;
|
|
74
74
|
rationale: string;
|
|
75
75
|
}
|
|
76
|
+
/** Maximum number of durable writes accepted from one isolated reflection response. */
|
|
77
|
+
export declare const MAX_REFLECTION_WRITES = 32;
|
|
78
|
+
/** Maximum number of response entries inspected while looking for accepted writes. */
|
|
79
|
+
export declare const MAX_REFLECTION_SCAN_ENTRIES: number;
|
|
76
80
|
/**
|
|
77
81
|
* STATIC reflection system prompt (Hermes-parity #33). It is byte-identical across every reflection
|
|
78
82
|
* pass — the variable parts (existing memory snapshot + the turn transcript) live in the USER prompt —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reflection-engine.d.ts","sourceRoot":"","sources":["../../../src/core/learning/reflection-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,
|
|
1
|
+
{"version":3,"file":"reflection-engine.d.ts","sourceRoot":"","sources":["../../../src/core/learning/reflection-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { PI_OKF_TYPES, validateOkfMemoryDocumentInput } from "../context/okf-memory.js";
|
|
1
|
+
import { OKF_MEMORY_LIMITS, PI_OKF_TYPES, validateOkfMemoryDocumentInput, } from "../context/okf-memory.js";
|
|
2
2
|
import { REFLECTION_SYSTEM_PROMPT } from "../provider-prompt-contracts.js";
|
|
3
|
+
import { MAX_ACTIVE_SKILL_BODY_BYTES } from "../skill-vault.js";
|
|
4
|
+
import { MAX_SKILL_DESCRIPTION_LENGTH, MAX_SKILL_NAME_LENGTH } from "../skills.js";
|
|
3
5
|
export { REFLECTION_SYSTEM_PROMPT };
|
|
4
6
|
/**
|
|
5
7
|
* Pure zero-I/O heuristic to decide whether the current turn justifies a reflection run
|
|
@@ -31,12 +33,45 @@ export function decideDemand(signals) {
|
|
|
31
33
|
}
|
|
32
34
|
return { act: "skip", reason: "Signals do not justify reflection overhead", tokenBudget: 0 };
|
|
33
35
|
}
|
|
36
|
+
/** Maximum number of durable writes accepted from one isolated reflection response. */
|
|
37
|
+
export const MAX_REFLECTION_WRITES = 32;
|
|
38
|
+
/** Maximum number of response entries inspected while looking for accepted writes. */
|
|
39
|
+
export const MAX_REFLECTION_SCAN_ENTRIES = MAX_REFLECTION_WRITES * 4;
|
|
34
40
|
function isRecord(value) {
|
|
35
41
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36
42
|
}
|
|
37
43
|
function isStringArray(value) {
|
|
38
44
|
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
39
45
|
}
|
|
46
|
+
function currentHotMemory(existingMemory) {
|
|
47
|
+
const marker = "## MEMORY.md:\n";
|
|
48
|
+
const markerIndex = existingMemory.indexOf(marker);
|
|
49
|
+
if (markerIndex === -1) {
|
|
50
|
+
// Unit callers may provide a raw MEMORY.md snapshot. A rendered persistent-memory block
|
|
51
|
+
// without this section, however, proves that MEMORY.md is empty; never treat OKF text as hot memory.
|
|
52
|
+
return existingMemory.includes("=== Persistent Memory (file-store) ===") ||
|
|
53
|
+
/<\s*untrusted_content\b/i.test(existingMemory)
|
|
54
|
+
? ""
|
|
55
|
+
: existingMemory;
|
|
56
|
+
}
|
|
57
|
+
const afterMemory = existingMemory.slice(markerIndex + marker.length);
|
|
58
|
+
const boundaries = [afterMemory.indexOf("\n## USER.md:"), afterMemory.search(/<\s*untrusted_content\b/i)].filter((index) => index >= 0);
|
|
59
|
+
const boundaryIndex = boundaries.length > 0 ? Math.min(...boundaries) : -1;
|
|
60
|
+
return boundaryIndex === -1 ? afterMemory : afterMemory.slice(0, boundaryIndex);
|
|
61
|
+
}
|
|
62
|
+
function containsExactHotMemoryItem(existingMemory, sourceText) {
|
|
63
|
+
if (sourceText.length === 0)
|
|
64
|
+
return false;
|
|
65
|
+
const memoryLines = currentHotMemory(existingMemory).split("\n");
|
|
66
|
+
const sourceLines = sourceText.split("\n");
|
|
67
|
+
return memoryLines.some((_, index) => sourceLines.every((line, offset) => memoryLines[index + offset] === line));
|
|
68
|
+
}
|
|
69
|
+
function boundedText(value, maxChars) {
|
|
70
|
+
return typeof value === "string" && value.length <= maxChars;
|
|
71
|
+
}
|
|
72
|
+
function boundedSkillBody(value) {
|
|
73
|
+
return typeof value === "string" && Buffer.byteLength(value, "utf8") <= MAX_ACTIVE_SKILL_BODY_BYTES;
|
|
74
|
+
}
|
|
40
75
|
/** One parser/validation path for both structured reflection operations. */
|
|
41
76
|
function parseStructuredReflectionWrite(value, existingMemory) {
|
|
42
77
|
if (!isRecord(value) || (value.kind !== "okf_add" && value.kind !== "okf_organize"))
|
|
@@ -64,7 +99,8 @@ function parseStructuredReflectionWrite(value, existingMemory) {
|
|
|
64
99
|
if (value.kind === "okf_organize") {
|
|
65
100
|
if (typeof value.sourceText !== "string" ||
|
|
66
101
|
value.sourceText.length === 0 ||
|
|
67
|
-
|
|
102
|
+
value.sourceText.length > OKF_MEMORY_LIMITS.bodyChars ||
|
|
103
|
+
!containsExactHotMemoryItem(existingMemory, value.sourceText)) {
|
|
68
104
|
return undefined;
|
|
69
105
|
}
|
|
70
106
|
write = { kind: "okf_organize", ...common, sourceText: value.sourceText };
|
|
@@ -123,29 +159,31 @@ Return JSON updates.`;
|
|
|
123
159
|
const rationale = parsed.rationale || "";
|
|
124
160
|
const writes = [];
|
|
125
161
|
if (Array.isArray(parsed.writes)) {
|
|
126
|
-
|
|
162
|
+
const scanCount = Math.min(parsed.writes.length, MAX_REFLECTION_SCAN_ENTRIES);
|
|
163
|
+
for (let index = 0; index < scanCount && writes.length < MAX_REFLECTION_WRITES; index++) {
|
|
164
|
+
const w = parsed.writes[index];
|
|
127
165
|
if (w && typeof w === "object") {
|
|
128
166
|
const structuredWrite = parseStructuredReflectionWrite(w, input.existingMemory);
|
|
129
167
|
if (w.kind === "memory_add" &&
|
|
130
168
|
(w.section === "MEMORY" || w.section === "USER") &&
|
|
131
|
-
|
|
169
|
+
boundedText(w.text, OKF_MEMORY_LIMITS.bodyChars)) {
|
|
132
170
|
writes.push({ kind: "memory_add", section: w.section, text: w.text });
|
|
133
171
|
}
|
|
134
172
|
else if (structuredWrite) {
|
|
135
173
|
writes.push(structuredWrite);
|
|
136
174
|
}
|
|
137
175
|
else if (w.kind === "memory_replace" &&
|
|
138
|
-
|
|
139
|
-
|
|
176
|
+
boundedText(w.target, OKF_MEMORY_LIMITS.bodyChars) &&
|
|
177
|
+
boundedText(w.text, OKF_MEMORY_LIMITS.bodyChars)) {
|
|
140
178
|
writes.push({ kind: "memory_replace", target: w.target, text: w.text });
|
|
141
179
|
}
|
|
142
|
-
else if (w.kind === "memory_remove" &&
|
|
180
|
+
else if (w.kind === "memory_remove" && boundedText(w.target, OKF_MEMORY_LIMITS.bodyChars)) {
|
|
143
181
|
writes.push({ kind: "memory_remove", target: w.target });
|
|
144
182
|
}
|
|
145
183
|
else if (w.kind === "promote_skill" &&
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
184
|
+
boundedText(w.name, MAX_SKILL_NAME_LENGTH) &&
|
|
185
|
+
boundedText(w.description, MAX_SKILL_DESCRIPTION_LENGTH) &&
|
|
186
|
+
boundedSkillBody(w.body)) {
|
|
149
187
|
writes.push({ kind: "promote_skill", name: w.name, description: w.description, body: w.body });
|
|
150
188
|
}
|
|
151
189
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reflection-engine.js","sourceRoot":"","sources":["../../../src/core/learning/reflection-engine.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Usage } from \"@caupulican/pi-ai\";\nimport { PI_OKF_TYPES, type PiOkfType, validateOkfMemoryDocumentInput } from \"../context/okf-memory.ts\";\nimport { REFLECTION_SYSTEM_PROMPT } from \"../provider-prompt-contracts.ts\";\n\nexport { REFLECTION_SYSTEM_PROMPT };\n\nexport type StopReason = \"stop\" | \"toolUse\" | \"aborted\" | \"error\" | string;\n\nexport interface IsolatedCompletionResult {\n\ttext: string;\n\tusage: Usage;\n\tstopReason: StopReason;\n}\n\nexport type ReflectionTrigger = \"complex\" | \"corrective\" | \"durable\" | \"session-end\" | \"none\";\n\nexport interface DemandSignals {\n\ttrigger: ReflectionTrigger;\n\ttoolCallCount: number;\n\thadCorrection: boolean;\n\tcontextHeadroomPct: number; // 0..100\n\tusefulLately: number; // 0..1 rolling score\n}\n\nexport interface DemandPlan {\n\tact: \"skip\" | \"reflect\";\n\treason: string;\n\ttokenBudget: number;\n}\n\n/**\n * Pure zero-I/O heuristic to decide whether the current turn justifies a reflection run\n * and determine the token budget under the cheap-tool net-negative doctrine.\n */\nexport function decideDemand(signals: DemandSignals): DemandPlan {\n\tif (signals.trigger === \"none\") {\n\t\treturn { act: \"skip\", reason: \"No trigger detected\", tokenBudget: 0 };\n\t}\n\tif (signals.contextHeadroomPct < 10) {\n\t\treturn { act: \"skip\", reason: \"Context headroom is critically low (< 10%)\", tokenBudget: 0 };\n\t}\n\n\t// Dynamic token budget based on headroom (keep reflection bounded between 500 and 1500 tokens)\n\tconst baseBudget = 1000;\n\tconst tokenBudget = Math.max(500, Math.min(1500, Math.round(baseBudget * (signals.contextHeadroomPct / 100))));\n\n\tif (signals.hadCorrection) {\n\t\treturn { act: \"reflect\", reason: \"Correction detected in the turn\", tokenBudget };\n\t}\n\tif (signals.trigger === \"durable\") {\n\t\treturn { act: \"reflect\", reason: \"Durable fact or preference detected in the turn\", tokenBudget };\n\t}\n\tif (signals.trigger === \"session-end\") {\n\t\treturn { act: \"reflect\", reason: \"Session end reflection triggered\", tokenBudget };\n\t}\n\tif (signals.trigger === \"complex\") {\n\t\tif (signals.toolCallCount >= 3) {\n\t\t\treturn { act: \"reflect\", reason: `Complex turn with ${signals.toolCallCount} tool calls`, tokenBudget };\n\t\t}\n\t}\n\n\treturn { act: \"skip\", reason: \"Signals do not justify reflection overhead\", tokenBudget: 0 };\n}\n\nexport interface ReflectionInput {\n\trecentTurnText: string; // host serializes the just-finished turn\n\texistingMemory: string; // current MEMORY.md + USER.md snapshot\n\tplan: DemandPlan;\n\t// host-injected isolated completion function:\n\tcomplete: (systemPrompt: string, userPrompt: string) => Promise<IsolatedCompletionResult>;\n}\n\nexport type ReflectionWrite =\n\t| { kind: \"memory_add\"; section: \"MEMORY\" | \"USER\"; text: string }\n\t| {\n\t\t\tkind: \"okf_add\";\n\t\t\ttype: PiOkfType;\n\t\t\ttitle: string;\n\t\t\tdescription: string;\n\t\t\tscope: \"project\";\n\t\t\ttext: string;\n\t\t\ttags?: string[];\n\t\t\tevidenceRefs: string[];\n\t }\n\t| {\n\t\t\tkind: \"okf_organize\";\n\t\t\ttype: PiOkfType;\n\t\t\ttitle: string;\n\t\t\tdescription: string;\n\t\t\tscope: \"project\";\n\t\t\ttext: string;\n\t\t\tsourceText: string;\n\t\t\ttags?: string[];\n\t\t\tevidenceRefs: string[];\n\t }\n\t| { kind: \"memory_replace\"; target: string; text: string }\n\t| { kind: \"memory_remove\"; target: string }\n\t// R7 memory-to-behavior: promote a recurring procedural workflow into an executable skill.\n\t| { kind: \"promote_skill\"; name: string; description: string; body: string };\n\nexport interface ReflectionResult {\n\twrites: ReflectionWrite[];\n\tusage: Usage;\n\trationale: string;\n}\n\ntype StructuredReflectionWrite = Extract<ReflectionWrite, { kind: \"okf_add\" | \"okf_organize\" }>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((entry) => typeof entry === \"string\");\n}\n\n/** One parser/validation path for both structured reflection operations. */\nfunction parseStructuredReflectionWrite(value: unknown, existingMemory: string): StructuredReflectionWrite | undefined {\n\tif (!isRecord(value) || (value.kind !== \"okf_add\" && value.kind !== \"okf_organize\")) return undefined;\n\tif (\n\t\t!PI_OKF_TYPES.includes(value.type as PiOkfType) ||\n\t\ttypeof value.title !== \"string\" ||\n\t\ttypeof value.description !== \"string\" ||\n\t\tvalue.scope !== \"project\" ||\n\t\ttypeof value.text !== \"string\" ||\n\t\t!isStringArray(value.evidenceRefs) ||\n\t\tvalue.evidenceRefs.length === 0 ||\n\t\t(value.tags !== undefined && !isStringArray(value.tags))\n\t) {\n\t\treturn undefined;\n\t}\n\tconst common = {\n\t\ttype: value.type as PiOkfType,\n\t\ttitle: value.title,\n\t\tdescription: value.description,\n\t\tscope: \"project\" as const,\n\t\ttext: value.text,\n\t\t...(value.tags !== undefined ? { tags: value.tags } : {}),\n\t\tevidenceRefs: value.evidenceRefs,\n\t};\n\tlet write: StructuredReflectionWrite;\n\tif (value.kind === \"okf_organize\") {\n\t\tif (\n\t\t\ttypeof value.sourceText !== \"string\" ||\n\t\t\tvalue.sourceText.length === 0 ||\n\t\t\t!existingMemory.includes(value.sourceText)\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t\twrite = { kind: \"okf_organize\", ...common, sourceText: value.sourceText };\n\t} else {\n\t\twrite = { kind: \"okf_add\", ...common };\n\t}\n\treturn validateOkfMemoryDocumentInput(\n\t\t{\n\t\t\ttype: write.type,\n\t\t\ttitle: write.title,\n\t\t\tdescription: write.description,\n\t\t\tscope: write.scope,\n\t\t\tbody: write.text,\n\t\t\ttags: write.tags,\n\t\t\tevidenceRefs: write.evidenceRefs,\n\t\t},\n\t\t{ projectOnly: true, requireEvidence: true },\n\t).length === 0\n\t\t? write\n\t\t: undefined;\n}\n\n/**\n * STATIC reflection system prompt (Hermes-parity #33). It is byte-identical across every reflection\n * pass — the variable parts (existing memory snapshot + the turn transcript) live in the USER prompt —\n * so the provider prompt-cache reuses this prefix instead of re-billing it each pass (cost guard).\n * Do NOT interpolate per-call data into this constant or caching breaks.\n */\nexport class ReflectionEngine {\n\t/**\n\t * Build the reflection prompt, call the injected isolated complete(),\n\t * parse the response, confront existing memory, and return memory writes.\n\t * Zero direct I/O.\n\t */\n\tasync reflect(input: ReflectionInput): Promise<ReflectionResult> {\n\t\tconst systemPrompt = REFLECTION_SYSTEM_PROMPT;\n\n\t\t// Variable inputs go in the USER prompt so the system prefix above stays cache-stable (#33).\n\t\tconst userPrompt = `Existing memory:\n${input.existingMemory}\n\nRecent turn transcript:\n${input.recentTurnText}\n\nReturn JSON updates.`;\n\n\t\tlet usage: Usage | undefined;\n\t\ttry {\n\t\t\tconst compResult = await input.complete(systemPrompt, userPrompt);\n\t\t\tusage = compResult.usage;\n\t\t\tconst text = compResult.text;\n\n\t\t\tconst jsonMatch = text.match(/```json\\s*([\\s\\S]*?)\\s*```/) || text.match(/{[\\s\\S]*}/);\n\t\t\tif (!jsonMatch) {\n\t\t\t\treturn {\n\t\t\t\t\twrites: [],\n\t\t\t\t\tusage: compResult.usage,\n\t\t\t\t\trationale: `Failed to locate JSON response. Raw text:\\n${text}`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst parsed = JSON.parse(jsonMatch[1] || jsonMatch[0]);\n\t\t\tconst rationale = parsed.rationale || \"\";\n\t\t\tconst writes: ReflectionWrite[] = [];\n\n\t\t\tif (Array.isArray(parsed.writes)) {\n\t\t\t\tfor (const w of parsed.writes) {\n\t\t\t\t\tif (w && typeof w === \"object\") {\n\t\t\t\t\t\tconst structuredWrite = parseStructuredReflectionWrite(w, input.existingMemory);\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tw.kind === \"memory_add\" &&\n\t\t\t\t\t\t\t(w.section === \"MEMORY\" || w.section === \"USER\") &&\n\t\t\t\t\t\t\ttypeof w.text === \"string\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\twrites.push({ kind: \"memory_add\", section: w.section, text: w.text });\n\t\t\t\t\t\t} else if (structuredWrite) {\n\t\t\t\t\t\t\twrites.push(structuredWrite);\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tw.kind === \"memory_replace\" &&\n\t\t\t\t\t\t\ttypeof w.target === \"string\" &&\n\t\t\t\t\t\t\ttypeof w.text === \"string\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\twrites.push({ kind: \"memory_replace\", target: w.target, text: w.text });\n\t\t\t\t\t\t} else if (w.kind === \"memory_remove\" && typeof w.target === \"string\") {\n\t\t\t\t\t\t\twrites.push({ kind: \"memory_remove\", target: w.target });\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tw.kind === \"promote_skill\" &&\n\t\t\t\t\t\t\ttypeof w.name === \"string\" &&\n\t\t\t\t\t\t\ttypeof w.description === \"string\" &&\n\t\t\t\t\t\t\ttypeof w.body === \"string\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\twrites.push({ kind: \"promote_skill\", name: w.name, description: w.description, body: w.body });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\twrites,\n\t\t\t\tusage: compResult.usage,\n\t\t\t\trationale,\n\t\t\t};\n\t\t} catch (err) {\n\t\t\t// Zeroed/fallback usage representation\n\t\t\tconst emptyUsage: Usage = {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t};\n\t\t\treturn {\n\t\t\t\twrites: [],\n\t\t\t\tusage: usage ?? emptyUsage,\n\t\t\t\trationale: `Error during reflection: ${String(err)}`,\n\t\t\t};\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reflection-engine.js","sourceRoot":"","sources":["../../../src/core/learning/reflection-engine.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Usage } from \"@caupulican/pi-ai\";\nimport {\n\tOKF_MEMORY_LIMITS,\n\tPI_OKF_TYPES,\n\ttype PiOkfType,\n\tvalidateOkfMemoryDocumentInput,\n} from \"../context/okf-memory.ts\";\nimport { REFLECTION_SYSTEM_PROMPT } from \"../provider-prompt-contracts.ts\";\nimport { MAX_ACTIVE_SKILL_BODY_BYTES } from \"../skill-vault.ts\";\nimport { MAX_SKILL_DESCRIPTION_LENGTH, MAX_SKILL_NAME_LENGTH } from \"../skills.ts\";\n\nexport { REFLECTION_SYSTEM_PROMPT };\n\nexport type StopReason = \"stop\" | \"toolUse\" | \"aborted\" | \"error\" | string;\n\nexport interface IsolatedCompletionResult {\n\ttext: string;\n\tusage: Usage;\n\tstopReason: StopReason;\n}\n\nexport type ReflectionTrigger = \"complex\" | \"corrective\" | \"durable\" | \"session-end\" | \"none\";\n\nexport interface DemandSignals {\n\ttrigger: ReflectionTrigger;\n\ttoolCallCount: number;\n\thadCorrection: boolean;\n\tcontextHeadroomPct: number; // 0..100\n\tusefulLately: number; // 0..1 rolling score\n}\n\nexport interface DemandPlan {\n\tact: \"skip\" | \"reflect\";\n\treason: string;\n\ttokenBudget: number;\n}\n\n/**\n * Pure zero-I/O heuristic to decide whether the current turn justifies a reflection run\n * and determine the token budget under the cheap-tool net-negative doctrine.\n */\nexport function decideDemand(signals: DemandSignals): DemandPlan {\n\tif (signals.trigger === \"none\") {\n\t\treturn { act: \"skip\", reason: \"No trigger detected\", tokenBudget: 0 };\n\t}\n\tif (signals.contextHeadroomPct < 10) {\n\t\treturn { act: \"skip\", reason: \"Context headroom is critically low (< 10%)\", tokenBudget: 0 };\n\t}\n\n\t// Dynamic token budget based on headroom (keep reflection bounded between 500 and 1500 tokens)\n\tconst baseBudget = 1000;\n\tconst tokenBudget = Math.max(500, Math.min(1500, Math.round(baseBudget * (signals.contextHeadroomPct / 100))));\n\n\tif (signals.hadCorrection) {\n\t\treturn { act: \"reflect\", reason: \"Correction detected in the turn\", tokenBudget };\n\t}\n\tif (signals.trigger === \"durable\") {\n\t\treturn { act: \"reflect\", reason: \"Durable fact or preference detected in the turn\", tokenBudget };\n\t}\n\tif (signals.trigger === \"session-end\") {\n\t\treturn { act: \"reflect\", reason: \"Session end reflection triggered\", tokenBudget };\n\t}\n\tif (signals.trigger === \"complex\") {\n\t\tif (signals.toolCallCount >= 3) {\n\t\t\treturn { act: \"reflect\", reason: `Complex turn with ${signals.toolCallCount} tool calls`, tokenBudget };\n\t\t}\n\t}\n\n\treturn { act: \"skip\", reason: \"Signals do not justify reflection overhead\", tokenBudget: 0 };\n}\n\nexport interface ReflectionInput {\n\trecentTurnText: string; // host serializes the just-finished turn\n\texistingMemory: string; // current MEMORY.md + USER.md snapshot\n\tplan: DemandPlan;\n\t// host-injected isolated completion function:\n\tcomplete: (systemPrompt: string, userPrompt: string) => Promise<IsolatedCompletionResult>;\n}\n\nexport type ReflectionWrite =\n\t| { kind: \"memory_add\"; section: \"MEMORY\" | \"USER\"; text: string }\n\t| {\n\t\t\tkind: \"okf_add\";\n\t\t\ttype: PiOkfType;\n\t\t\ttitle: string;\n\t\t\tdescription: string;\n\t\t\tscope: \"project\";\n\t\t\ttext: string;\n\t\t\ttags?: string[];\n\t\t\tevidenceRefs: string[];\n\t }\n\t| {\n\t\t\tkind: \"okf_organize\";\n\t\t\ttype: PiOkfType;\n\t\t\ttitle: string;\n\t\t\tdescription: string;\n\t\t\tscope: \"project\";\n\t\t\ttext: string;\n\t\t\tsourceText: string;\n\t\t\ttags?: string[];\n\t\t\tevidenceRefs: string[];\n\t }\n\t| { kind: \"memory_replace\"; target: string; text: string }\n\t| { kind: \"memory_remove\"; target: string }\n\t// R7 memory-to-behavior: promote a recurring procedural workflow into an executable skill.\n\t| { kind: \"promote_skill\"; name: string; description: string; body: string };\n\nexport interface ReflectionResult {\n\twrites: ReflectionWrite[];\n\tusage: Usage;\n\trationale: string;\n}\n\n/** Maximum number of durable writes accepted from one isolated reflection response. */\nexport const MAX_REFLECTION_WRITES = 32;\n/** Maximum number of response entries inspected while looking for accepted writes. */\nexport const MAX_REFLECTION_SCAN_ENTRIES = MAX_REFLECTION_WRITES * 4;\n\ntype StructuredReflectionWrite = Extract<ReflectionWrite, { kind: \"okf_add\" | \"okf_organize\" }>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((entry) => typeof entry === \"string\");\n}\n\nfunction currentHotMemory(existingMemory: string): string {\n\tconst marker = \"## MEMORY.md:\\n\";\n\tconst markerIndex = existingMemory.indexOf(marker);\n\tif (markerIndex === -1) {\n\t\t// Unit callers may provide a raw MEMORY.md snapshot. A rendered persistent-memory block\n\t\t// without this section, however, proves that MEMORY.md is empty; never treat OKF text as hot memory.\n\t\treturn existingMemory.includes(\"=== Persistent Memory (file-store) ===\") ||\n\t\t\t/<\\s*untrusted_content\\b/i.test(existingMemory)\n\t\t\t? \"\"\n\t\t\t: existingMemory;\n\t}\n\tconst afterMemory = existingMemory.slice(markerIndex + marker.length);\n\tconst boundaries = [afterMemory.indexOf(\"\\n## USER.md:\"), afterMemory.search(/<\\s*untrusted_content\\b/i)].filter(\n\t\t(index) => index >= 0,\n\t);\n\tconst boundaryIndex = boundaries.length > 0 ? Math.min(...boundaries) : -1;\n\treturn boundaryIndex === -1 ? afterMemory : afterMemory.slice(0, boundaryIndex);\n}\n\nfunction containsExactHotMemoryItem(existingMemory: string, sourceText: string): boolean {\n\tif (sourceText.length === 0) return false;\n\tconst memoryLines = currentHotMemory(existingMemory).split(\"\\n\");\n\tconst sourceLines = sourceText.split(\"\\n\");\n\treturn memoryLines.some((_, index) => sourceLines.every((line, offset) => memoryLines[index + offset] === line));\n}\n\nfunction boundedText(value: unknown, maxChars: number): value is string {\n\treturn typeof value === \"string\" && value.length <= maxChars;\n}\n\nfunction boundedSkillBody(value: unknown): value is string {\n\treturn typeof value === \"string\" && Buffer.byteLength(value, \"utf8\") <= MAX_ACTIVE_SKILL_BODY_BYTES;\n}\n\n/** One parser/validation path for both structured reflection operations. */\nfunction parseStructuredReflectionWrite(value: unknown, existingMemory: string): StructuredReflectionWrite | undefined {\n\tif (!isRecord(value) || (value.kind !== \"okf_add\" && value.kind !== \"okf_organize\")) return undefined;\n\tif (\n\t\t!PI_OKF_TYPES.includes(value.type as PiOkfType) ||\n\t\ttypeof value.title !== \"string\" ||\n\t\ttypeof value.description !== \"string\" ||\n\t\tvalue.scope !== \"project\" ||\n\t\ttypeof value.text !== \"string\" ||\n\t\t!isStringArray(value.evidenceRefs) ||\n\t\tvalue.evidenceRefs.length === 0 ||\n\t\t(value.tags !== undefined && !isStringArray(value.tags))\n\t) {\n\t\treturn undefined;\n\t}\n\tconst common = {\n\t\ttype: value.type as PiOkfType,\n\t\ttitle: value.title,\n\t\tdescription: value.description,\n\t\tscope: \"project\" as const,\n\t\ttext: value.text,\n\t\t...(value.tags !== undefined ? { tags: value.tags } : {}),\n\t\tevidenceRefs: value.evidenceRefs,\n\t};\n\tlet write: StructuredReflectionWrite;\n\tif (value.kind === \"okf_organize\") {\n\t\tif (\n\t\t\ttypeof value.sourceText !== \"string\" ||\n\t\t\tvalue.sourceText.length === 0 ||\n\t\t\tvalue.sourceText.length > OKF_MEMORY_LIMITS.bodyChars ||\n\t\t\t!containsExactHotMemoryItem(existingMemory, value.sourceText)\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t\twrite = { kind: \"okf_organize\", ...common, sourceText: value.sourceText };\n\t} else {\n\t\twrite = { kind: \"okf_add\", ...common };\n\t}\n\treturn validateOkfMemoryDocumentInput(\n\t\t{\n\t\t\ttype: write.type,\n\t\t\ttitle: write.title,\n\t\t\tdescription: write.description,\n\t\t\tscope: write.scope,\n\t\t\tbody: write.text,\n\t\t\ttags: write.tags,\n\t\t\tevidenceRefs: write.evidenceRefs,\n\t\t},\n\t\t{ projectOnly: true, requireEvidence: true },\n\t).length === 0\n\t\t? write\n\t\t: undefined;\n}\n\n/**\n * STATIC reflection system prompt (Hermes-parity #33). It is byte-identical across every reflection\n * pass — the variable parts (existing memory snapshot + the turn transcript) live in the USER prompt —\n * so the provider prompt-cache reuses this prefix instead of re-billing it each pass (cost guard).\n * Do NOT interpolate per-call data into this constant or caching breaks.\n */\nexport class ReflectionEngine {\n\t/**\n\t * Build the reflection prompt, call the injected isolated complete(),\n\t * parse the response, confront existing memory, and return memory writes.\n\t * Zero direct I/O.\n\t */\n\tasync reflect(input: ReflectionInput): Promise<ReflectionResult> {\n\t\tconst systemPrompt = REFLECTION_SYSTEM_PROMPT;\n\n\t\t// Variable inputs go in the USER prompt so the system prefix above stays cache-stable (#33).\n\t\tconst userPrompt = `Existing memory:\n${input.existingMemory}\n\nRecent turn transcript:\n${input.recentTurnText}\n\nReturn JSON updates.`;\n\n\t\tlet usage: Usage | undefined;\n\t\ttry {\n\t\t\tconst compResult = await input.complete(systemPrompt, userPrompt);\n\t\t\tusage = compResult.usage;\n\t\t\tconst text = compResult.text;\n\n\t\t\tconst jsonMatch = text.match(/```json\\s*([\\s\\S]*?)\\s*```/) || text.match(/{[\\s\\S]*}/);\n\t\t\tif (!jsonMatch) {\n\t\t\t\treturn {\n\t\t\t\t\twrites: [],\n\t\t\t\t\tusage: compResult.usage,\n\t\t\t\t\trationale: `Failed to locate JSON response. Raw text:\\n${text}`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst parsed = JSON.parse(jsonMatch[1] || jsonMatch[0]);\n\t\t\tconst rationale = parsed.rationale || \"\";\n\t\t\tconst writes: ReflectionWrite[] = [];\n\n\t\t\tif (Array.isArray(parsed.writes)) {\n\t\t\t\tconst scanCount = Math.min(parsed.writes.length, MAX_REFLECTION_SCAN_ENTRIES);\n\t\t\t\tfor (let index = 0; index < scanCount && writes.length < MAX_REFLECTION_WRITES; index++) {\n\t\t\t\t\tconst w = parsed.writes[index];\n\t\t\t\t\tif (w && typeof w === \"object\") {\n\t\t\t\t\t\tconst structuredWrite = parseStructuredReflectionWrite(w, input.existingMemory);\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tw.kind === \"memory_add\" &&\n\t\t\t\t\t\t\t(w.section === \"MEMORY\" || w.section === \"USER\") &&\n\t\t\t\t\t\t\tboundedText(w.text, OKF_MEMORY_LIMITS.bodyChars)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\twrites.push({ kind: \"memory_add\", section: w.section, text: w.text });\n\t\t\t\t\t\t} else if (structuredWrite) {\n\t\t\t\t\t\t\twrites.push(structuredWrite);\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tw.kind === \"memory_replace\" &&\n\t\t\t\t\t\t\tboundedText(w.target, OKF_MEMORY_LIMITS.bodyChars) &&\n\t\t\t\t\t\t\tboundedText(w.text, OKF_MEMORY_LIMITS.bodyChars)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\twrites.push({ kind: \"memory_replace\", target: w.target, text: w.text });\n\t\t\t\t\t\t} else if (w.kind === \"memory_remove\" && boundedText(w.target, OKF_MEMORY_LIMITS.bodyChars)) {\n\t\t\t\t\t\t\twrites.push({ kind: \"memory_remove\", target: w.target });\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tw.kind === \"promote_skill\" &&\n\t\t\t\t\t\t\tboundedText(w.name, MAX_SKILL_NAME_LENGTH) &&\n\t\t\t\t\t\t\tboundedText(w.description, MAX_SKILL_DESCRIPTION_LENGTH) &&\n\t\t\t\t\t\t\tboundedSkillBody(w.body)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\twrites.push({ kind: \"promote_skill\", name: w.name, description: w.description, body: w.body });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\twrites,\n\t\t\t\tusage: compResult.usage,\n\t\t\t\trationale,\n\t\t\t};\n\t\t} catch (err) {\n\t\t\t// Zeroed/fallback usage representation\n\t\t\tconst emptyUsage: Usage = {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t};\n\t\t\treturn {\n\t\t\t\twrites: [],\n\t\t\t\tusage: usage ?? emptyUsage,\n\t\t\t\trationale: `Error during reflection: ${String(err)}`,\n\t\t\t};\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Best-effort, preemptible standing-prefix warmup for loopback OpenAI-compatible models. */
|
|
2
|
+
import type { AgentTool, StreamFn } from "@caupulican/pi-agent-core/types";
|
|
3
|
+
import type { Api, Model, SimpleStreamOptions } from "@caupulican/pi-ai";
|
|
4
|
+
import type { RequestAuth } from "./request-auth.ts";
|
|
5
|
+
export interface LocalPrefixWarmControllerDeps {
|
|
6
|
+
getStreamFn(): StreamFn;
|
|
7
|
+
getTools(): AgentTool[];
|
|
8
|
+
getSystemPrompt(): string;
|
|
9
|
+
getRequestHooks(): Pick<SimpleStreamOptions, "onPayload" | "onResponse">;
|
|
10
|
+
isRawStreamSimple(streamFn: StreamFn): boolean;
|
|
11
|
+
getRequiredRequestAuth(model: Model<Api>): Promise<RequestAuth>;
|
|
12
|
+
ensureManagedModelReady(model: Model<Api>): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export declare function isWarmableLocalModel(model: Model<Api>): boolean;
|
|
15
|
+
export declare class LocalPrefixWarmController {
|
|
16
|
+
private readonly deps;
|
|
17
|
+
private active;
|
|
18
|
+
private readonly completed;
|
|
19
|
+
constructor(deps: LocalPrefixWarmControllerDeps);
|
|
20
|
+
schedule(model: Model<Api> | undefined): void;
|
|
21
|
+
cancel(): void;
|
|
22
|
+
private run;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=local-prefix-warm-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-prefix-warm-controller.d.ts","sourceRoot":"","sources":["../../src/core/local-prefix-warm-controller.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAG7F,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAIzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,6BAA6B;IAC7C,WAAW,IAAI,QAAQ,CAAC;IACxB,QAAQ,IAAI,SAAS,EAAE,CAAC;IACxB,eAAe,IAAI,MAAM,CAAC;IAC1B,eAAe,IAAI,IAAI,CAAC,mBAAmB,EAAE,WAAW,GAAG,YAAY,CAAC,CAAC;IACzE,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC/C,sBAAsB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAChE,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAE/D;AAED,qBAAa,yBAAyB;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgC;IACrD,OAAO,CAAC,MAAM,CAAmG;IACjH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAE/C,YAAY,IAAI,EAAE,6BAA6B,EAE9C;IAED,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,GAAG,IAAI,CAc5C;IAED,MAAM,IAAI,IAAI,CAMb;YAEa,GAAG;CAmCjB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Best-effort, preemptible standing-prefix warmup for loopback OpenAI-compatible models. */
|
|
2
|
+
import { projectToolsForProvider } from "@caupulican/pi-agent-core/provider-tool-projection";
|
|
3
|
+
import { formatModelRouterModel } from "./model-router-controller.js";
|
|
4
|
+
import { HF_TRANSFORMERS_PROVIDER, OLLAMA_PROVIDER } from "./models/local-registration.js";
|
|
5
|
+
import { isLoopbackModelEndpoint } from "./models/model-endpoint.js";
|
|
6
|
+
export function isWarmableLocalModel(model) {
|
|
7
|
+
return model.api === "openai-completions" && isLoopbackModelEndpoint(model.baseUrl);
|
|
8
|
+
}
|
|
9
|
+
export class LocalPrefixWarmController {
|
|
10
|
+
constructor(deps) {
|
|
11
|
+
this.completed = new Set();
|
|
12
|
+
this.deps = deps;
|
|
13
|
+
}
|
|
14
|
+
schedule(model) {
|
|
15
|
+
if (!model || !isWarmableLocalModel(model))
|
|
16
|
+
return;
|
|
17
|
+
const modelKey = formatModelRouterModel(model);
|
|
18
|
+
if (this.completed.has(modelKey) || this.active?.modelKey === modelKey)
|
|
19
|
+
return;
|
|
20
|
+
this.cancel();
|
|
21
|
+
const controller = new AbortController();
|
|
22
|
+
const timer = setTimeout(() => {
|
|
23
|
+
const active = this.active;
|
|
24
|
+
if (!active || active.controller !== controller || controller.signal.aborted)
|
|
25
|
+
return;
|
|
26
|
+
active.timer = undefined;
|
|
27
|
+
void this.run(model, modelKey, controller);
|
|
28
|
+
}, 0);
|
|
29
|
+
timer.unref?.();
|
|
30
|
+
this.active = { modelKey, controller, timer };
|
|
31
|
+
}
|
|
32
|
+
cancel() {
|
|
33
|
+
const active = this.active;
|
|
34
|
+
if (!active)
|
|
35
|
+
return;
|
|
36
|
+
if (active.timer)
|
|
37
|
+
clearTimeout(active.timer);
|
|
38
|
+
active.controller.abort(new Error("prefix warmer preempted"));
|
|
39
|
+
this.active = undefined;
|
|
40
|
+
}
|
|
41
|
+
async run(model, modelKey, controller) {
|
|
42
|
+
try {
|
|
43
|
+
const streamFn = this.deps.getStreamFn();
|
|
44
|
+
const options = {
|
|
45
|
+
maxTokens: 1,
|
|
46
|
+
signal: controller.signal,
|
|
47
|
+
...this.deps.getRequestHooks(),
|
|
48
|
+
};
|
|
49
|
+
if (this.deps.isRawStreamSimple(streamFn)) {
|
|
50
|
+
const auth = await this.deps.getRequiredRequestAuth(model);
|
|
51
|
+
options.apiKey = auth.apiKey;
|
|
52
|
+
options.headers = auth.headers;
|
|
53
|
+
}
|
|
54
|
+
if (controller.signal.aborted)
|
|
55
|
+
return;
|
|
56
|
+
if (model.provider === OLLAMA_PROVIDER || model.provider === HF_TRANSFORMERS_PROVIDER) {
|
|
57
|
+
await this.deps.ensureManagedModelReady(model);
|
|
58
|
+
}
|
|
59
|
+
if (controller.signal.aborted)
|
|
60
|
+
return;
|
|
61
|
+
const stream = await streamFn(model, {
|
|
62
|
+
systemPrompt: this.deps.getSystemPrompt(),
|
|
63
|
+
tools: projectToolsForProvider(this.deps.getTools()),
|
|
64
|
+
messages: [],
|
|
65
|
+
}, options);
|
|
66
|
+
await stream.result();
|
|
67
|
+
if (!controller.signal.aborted)
|
|
68
|
+
this.completed.add(modelKey);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// A cache miss must never affect the real turn.
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
if (this.active?.controller === controller)
|
|
75
|
+
this.active = undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=local-prefix-warm-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-prefix-warm-controller.js","sourceRoot":"","sources":["../../src/core/local-prefix-warm-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/** Best-effort, preemptible standing-prefix warmup for loopback OpenAI-compatible models. */\n\nimport { projectToolsForProvider } from \"@caupulican/pi-agent-core/provider-tool-projection\";\nimport type { AgentTool, StreamFn } from \"@caupulican/pi-agent-core/types\";\nimport type { Api, Model, SimpleStreamOptions } from \"@caupulican/pi-ai\";\nimport { formatModelRouterModel } from \"./model-router-controller.ts\";\nimport { HF_TRANSFORMERS_PROVIDER, OLLAMA_PROVIDER } from \"./models/local-registration.ts\";\nimport { isLoopbackModelEndpoint } from \"./models/model-endpoint.ts\";\nimport type { RequestAuth } from \"./request-auth.ts\";\n\nexport interface LocalPrefixWarmControllerDeps {\n\tgetStreamFn(): StreamFn;\n\tgetTools(): AgentTool[];\n\tgetSystemPrompt(): string;\n\tgetRequestHooks(): Pick<SimpleStreamOptions, \"onPayload\" | \"onResponse\">;\n\tisRawStreamSimple(streamFn: StreamFn): boolean;\n\tgetRequiredRequestAuth(model: Model<Api>): Promise<RequestAuth>;\n\tensureManagedModelReady(model: Model<Api>): Promise<void>;\n}\n\nexport function isWarmableLocalModel(model: Model<Api>): boolean {\n\treturn model.api === \"openai-completions\" && isLoopbackModelEndpoint(model.baseUrl);\n}\n\nexport class LocalPrefixWarmController {\n\tprivate readonly deps: LocalPrefixWarmControllerDeps;\n\tprivate active: { modelKey: string; controller: AbortController; timer: NodeJS.Timeout | undefined } | undefined;\n\tprivate readonly completed = new Set<string>();\n\n\tconstructor(deps: LocalPrefixWarmControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tschedule(model: Model<Api> | undefined): void {\n\t\tif (!model || !isWarmableLocalModel(model)) return;\n\t\tconst modelKey = formatModelRouterModel(model);\n\t\tif (this.completed.has(modelKey) || this.active?.modelKey === modelKey) return;\n\t\tthis.cancel();\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => {\n\t\t\tconst active = this.active;\n\t\t\tif (!active || active.controller !== controller || controller.signal.aborted) return;\n\t\t\tactive.timer = undefined;\n\t\t\tvoid this.run(model, modelKey, controller);\n\t\t}, 0);\n\t\ttimer.unref?.();\n\t\tthis.active = { modelKey, controller, timer };\n\t}\n\n\tcancel(): void {\n\t\tconst active = this.active;\n\t\tif (!active) return;\n\t\tif (active.timer) clearTimeout(active.timer);\n\t\tactive.controller.abort(new Error(\"prefix warmer preempted\"));\n\t\tthis.active = undefined;\n\t}\n\n\tprivate async run(model: Model<Api>, modelKey: string, controller: AbortController): Promise<void> {\n\t\ttry {\n\t\t\tconst streamFn = this.deps.getStreamFn();\n\t\t\tconst options: SimpleStreamOptions = {\n\t\t\t\tmaxTokens: 1,\n\t\t\t\tsignal: controller.signal,\n\t\t\t\t...this.deps.getRequestHooks(),\n\t\t\t};\n\t\t\tif (this.deps.isRawStreamSimple(streamFn)) {\n\t\t\t\tconst auth = await this.deps.getRequiredRequestAuth(model);\n\t\t\t\toptions.apiKey = auth.apiKey;\n\t\t\t\toptions.headers = auth.headers;\n\t\t\t}\n\t\t\tif (controller.signal.aborted) return;\n\t\t\tif (model.provider === OLLAMA_PROVIDER || model.provider === HF_TRANSFORMERS_PROVIDER) {\n\t\t\t\tawait this.deps.ensureManagedModelReady(model);\n\t\t\t}\n\t\t\tif (controller.signal.aborted) return;\n\t\t\tconst stream = await streamFn(\n\t\t\t\tmodel,\n\t\t\t\t{\n\t\t\t\t\tsystemPrompt: this.deps.getSystemPrompt(),\n\t\t\t\t\ttools: projectToolsForProvider(this.deps.getTools()),\n\t\t\t\t\tmessages: [],\n\t\t\t\t},\n\t\t\t\toptions,\n\t\t\t);\n\t\t\tawait stream.result();\n\t\t\tif (!controller.signal.aborted) this.completed.add(modelKey);\n\t\t} catch {\n\t\t\t// A cache miss must never affect the real turn.\n\t\t} finally {\n\t\t\tif (this.active?.controller === controller) this.active = undefined;\n\t\t}\n\t}\n}\n"]}
|
|
@@ -72,6 +72,8 @@ export declare class FileStoreProvider implements MemoryProvider {
|
|
|
72
72
|
prefetch(_query: string): Promise<string>;
|
|
73
73
|
shutdown(): Promise<void>;
|
|
74
74
|
private executeMemoryCommand;
|
|
75
|
+
private hasExactHotMemoryItem;
|
|
76
|
+
private removeExactHotMemoryItem;
|
|
75
77
|
/** Reflection-owned structured write. Organization is OKF-first, then exact hot-memory removal. */
|
|
76
78
|
applyStructuredReflectionWrite(write: StructuredReflectionWrite, signal?: AbortSignal): Promise<StructuredReflectionApplyResult>;
|
|
77
79
|
/** Restore hot memory first, then conditionally remove the exact audited OKF bytes. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../../../src/core/memory/providers/file-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAGN,KAAK,SAAS,EAEd,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../../../src/core/memory/providers/file-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ import { hasInvisibleUnicode, scanContextFileThreats, stripInvisibleUnicode, } f
|
|
|
7
7
|
import { jaccard, tokenize } from "../../tools/skill-audit.js";
|
|
8
8
|
import { isMissingFileError, withFileLock, writeFileAtomic } from "../../util/atomic-file.js";
|
|
9
9
|
import { OkfProjectMemoryStore } from "../okf-project-memory-store.js";
|
|
10
|
+
import { ROOT_MEMORY_TOOL_NAME } from "../worker-memory-tools.js";
|
|
10
11
|
import { UserMemoryArchive } from "./user-memory-archive.js";
|
|
11
12
|
/**
|
|
12
13
|
* Confront-before-write (anti append-rot): if `content` is a near-duplicate of an existing
|
|
@@ -83,6 +84,17 @@ export const FILE_STORE_MEMORY_SYSTEM_NOTE = "[System Note: Below is a snapshot
|
|
|
83
84
|
function contentDigest(content) {
|
|
84
85
|
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
85
86
|
}
|
|
87
|
+
function removeExactHotMemoryItem(existing, sourceText) {
|
|
88
|
+
if (sourceText.length === 0)
|
|
89
|
+
return undefined;
|
|
90
|
+
const memoryLines = existing.split("\n");
|
|
91
|
+
const sourceLines = sourceText.split("\n");
|
|
92
|
+
const start = memoryLines.findIndex((_, index) => sourceLines.every((line, offset) => memoryLines[index + offset] === line));
|
|
93
|
+
if (start === -1)
|
|
94
|
+
return undefined;
|
|
95
|
+
memoryLines.splice(start, sourceLines.length);
|
|
96
|
+
return memoryLines.join("\n");
|
|
97
|
+
}
|
|
86
98
|
function parseManagedMemoryState(raw) {
|
|
87
99
|
let parsed;
|
|
88
100
|
try {
|
|
@@ -241,6 +253,8 @@ export class FileStoreProvider {
|
|
|
241
253
|
});
|
|
242
254
|
}
|
|
243
255
|
systemPromptBlock(budget) {
|
|
256
|
+
if (this.ctx?.isChildSession)
|
|
257
|
+
return "";
|
|
244
258
|
const sanitize = (content) => {
|
|
245
259
|
// Strip hidden/bidi-control chars before injecting memory into the prompt (defence in depth: the
|
|
246
260
|
// write path already blocks them, but a file edited out-of-band could carry them). Strip #31.
|
|
@@ -292,8 +306,59 @@ export class FileStoreProvider {
|
|
|
292
306
|
const result = await tool.execute("reflection-memory", params, signal, undefined, undefined);
|
|
293
307
|
return result;
|
|
294
308
|
}
|
|
309
|
+
async hasExactHotMemoryItem(sourceText) {
|
|
310
|
+
return withFileLock(this.memoryFilePath, async () => {
|
|
311
|
+
const current = await fs.readFile(this.memoryFilePath, "utf8");
|
|
312
|
+
return removeExactHotMemoryItem(current, sourceText) !== undefined;
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
async removeExactHotMemoryItem(sourceText) {
|
|
316
|
+
try {
|
|
317
|
+
return await withFileLock(this.memoryFilePath, async () => {
|
|
318
|
+
const currentOnDisk = await fs.readFile(this.memoryFilePath, "utf8");
|
|
319
|
+
const currentDigest = contentDigest(currentOnDisk);
|
|
320
|
+
const stateRead = await readManagedMemoryState(this.memoryStatePath);
|
|
321
|
+
let managedState;
|
|
322
|
+
if (stateRead.status === "valid") {
|
|
323
|
+
const reconciled = reconcileManagedMemoryState(currentDigest, stateRead.state);
|
|
324
|
+
if (reconciled.recognized) {
|
|
325
|
+
managedState = reconciled.state;
|
|
326
|
+
if (reconciled.changed)
|
|
327
|
+
await writeManagedMemoryState(this.memoryStatePath, reconciled.state);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (!managedState)
|
|
331
|
+
return { success: false, error: "Drift detected" };
|
|
332
|
+
const newContent = removeExactHotMemoryItem(currentOnDisk, sourceText);
|
|
333
|
+
if (newContent === undefined)
|
|
334
|
+
return { success: false, error: "Exact hot-memory item was not found" };
|
|
335
|
+
const newDigest = contentDigest(newContent);
|
|
336
|
+
await writeManagedMemoryState(this.memoryStatePath, {
|
|
337
|
+
version: 1,
|
|
338
|
+
committedDigest: managedState.committedDigest,
|
|
339
|
+
pendingDigest: newDigest,
|
|
340
|
+
});
|
|
341
|
+
await writeFileAtomic(this.memoryFilePath, newContent, { mode: 0o600 });
|
|
342
|
+
await writeManagedMemoryState(this.memoryStatePath, { version: 1, committedDigest: newDigest });
|
|
343
|
+
this.lastWrittenMemory = newContent;
|
|
344
|
+
this.options.onDurableMemoryChanged?.();
|
|
345
|
+
return { success: true };
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
return { success: false, error: String(error) };
|
|
350
|
+
}
|
|
351
|
+
}
|
|
295
352
|
/** Reflection-owned structured write. Organization is OKF-first, then exact hot-memory removal. */
|
|
296
353
|
async applyStructuredReflectionWrite(write, signal) {
|
|
354
|
+
if (write.kind === "okf_organize" && !(await this.hasExactHotMemoryItem(write.sourceText))) {
|
|
355
|
+
return {
|
|
356
|
+
applied: false,
|
|
357
|
+
created: false,
|
|
358
|
+
sourceRemoved: false,
|
|
359
|
+
error: "Exact hot-memory item was not found",
|
|
360
|
+
};
|
|
361
|
+
}
|
|
297
362
|
const added = await this.executeMemoryCommand({
|
|
298
363
|
action: "add",
|
|
299
364
|
target: "okf",
|
|
@@ -319,8 +384,8 @@ export class FileStoreProvider {
|
|
|
319
384
|
};
|
|
320
385
|
}
|
|
321
386
|
await this.options.beforeOrganizeHotRemoval?.();
|
|
322
|
-
const removed = await this.
|
|
323
|
-
const sourceRemoved = removed.
|
|
387
|
+
const removed = await this.removeExactHotMemoryItem(write.sourceText);
|
|
388
|
+
const sourceRemoved = removed.success;
|
|
324
389
|
return {
|
|
325
390
|
// A newly-created OKF record is a real durable change even if exact hot cleanup was
|
|
326
391
|
// interrupted. This records a reversible partial apply instead of hiding landed data.
|
|
@@ -328,7 +393,7 @@ export class FileStoreProvider {
|
|
|
328
393
|
created,
|
|
329
394
|
...(storedDigest ? { digest: storedDigest } : {}),
|
|
330
395
|
sourceRemoved,
|
|
331
|
-
...(!sourceRemoved ? { error: removed.
|
|
396
|
+
...(!sourceRemoved ? { error: removed.error ?? "Hot-memory removal failed" } : {}),
|
|
332
397
|
};
|
|
333
398
|
}
|
|
334
399
|
/** Restore hot memory first, then conditionally remove the exact audited OKF bytes. */
|
|
@@ -353,9 +418,11 @@ export class FileStoreProvider {
|
|
|
353
418
|
return [];
|
|
354
419
|
}
|
|
355
420
|
getToolDefinitions() {
|
|
421
|
+
if (this.ctx?.isChildSession)
|
|
422
|
+
return [];
|
|
356
423
|
return [
|
|
357
424
|
{
|
|
358
|
-
name:
|
|
425
|
+
name: ROOT_MEMORY_TOOL_NAME,
|
|
359
426
|
label: "Persistent Memory Manager",
|
|
360
427
|
description: "Add, replace, or remove durable facts and preferences. Use target 'okf' with structured metadata for durable project decisions, architecture, rules, debugging findings, and references; USER.md overflow is migrated into indexed OKF shards.",
|
|
361
428
|
promptSnippet: "Persist verified facts; route durable project knowledge to structured OKF records.",
|
|
@@ -365,17 +432,6 @@ export class FileStoreProvider {
|
|
|
365
432
|
],
|
|
366
433
|
parameters: memorySchema,
|
|
367
434
|
execute: async (_toolCallId, params, _signal, _onUpdate, _execCtx) => {
|
|
368
|
-
if (this.ctx?.isChildSession) {
|
|
369
|
-
return {
|
|
370
|
-
content: [
|
|
371
|
-
{
|
|
372
|
-
type: "text",
|
|
373
|
-
text: "Error: Writes to persistent memory are not allowed in child sessions (subagents).",
|
|
374
|
-
},
|
|
375
|
-
],
|
|
376
|
-
details: { success: false, error: "Child session write-gated" },
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
435
|
const { action, target, content, oldContent, title, type, description, scope, tags, evidenceRefs, expectedDigest, } = params;
|
|
380
436
|
// Strict-scope injection guard on the high-privilege WRITE path (agy #31): a poisoned
|
|
381
437
|
// memory entry persists across sessions and is injected into every future system prompt,
|