@selesai/code 0.13.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/core/agent-session.d.ts +1 -1
- package/dist/core/agent-session.js +1 -1
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.js +1 -1
- package/dist/core/system-prompt.d.ts +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/extensions/ascii.txt +9 -0
- package/dist/extensions/package.json +1 -2
- package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
- package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
- package/dist/extensions/pi-hermes-memory/README.md +643 -0
- package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
- package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
- package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
- package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
- package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
- package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
- package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
- package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
- package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
- package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
- package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
- package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
- package/dist/extensions/pi-hermes-memory/package.json +66 -0
- package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
- package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
- package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
- package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
- package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
- package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
- package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
- package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
- package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
- package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
- package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
- package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
- package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
- package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
- package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
- package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
- package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
- package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
- package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
- package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
- package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
- package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
- package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
- package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
- package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
- package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
- package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
- package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
- package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
- package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
- package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
- package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
- package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
- package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
- package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
- package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
- package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
- package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
- package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
- package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
- package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
- package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
- package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
- package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
- package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
- package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
- package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
- package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
- package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
- package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
- package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
- package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
- package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
- package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
- package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
- package/dist/extensions/pi-subagents/AGENTS.md +5 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
- package/dist/extensions/pi-subagents/README.md +12 -6
- package/dist/extensions/pi-subagents/VISION.md +81 -0
- package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
- package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
- package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
- package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
- package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
- package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
- package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
- package/dist/extensions/pi-subagents/docs/agents.md +488 -0
- package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
- package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
- package/dist/extensions/pi-subagents/docs/models.md +27 -4
- package/dist/extensions/pi-subagents/docs/observability.md +10 -9
- package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
- package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
- package/dist/extensions/pi-subagents/package-lock.json +389 -2
- package/dist/extensions/pi-subagents/package.json +3 -1
- package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
- package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
- package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
- package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
- package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
- package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
- package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
- package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
- package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
- package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
- package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
- package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
- package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
- package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
- package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -3
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
- package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
- package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
- package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
- package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
- package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
- package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
- package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
- package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
- package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
- package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
- package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
- package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
- package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
- package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
- package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
- package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
- package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
- package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
- package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
- package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
- package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
- package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
- package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
- package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
- package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
- package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
- package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
- package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
- package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
- package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
- package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
- package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
- package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
- package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
- package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
- package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
- package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
- package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
- package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
- package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
- package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
- package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
- package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
- package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
- package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
- package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
- package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
- package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
- package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
- package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
- package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
- package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
- package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
- package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
- package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
- package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
- package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
- package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
- package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
- package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
- package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
- package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +132 -0
- package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
- package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
- package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
- package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
- package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
- package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
- package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
- package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
- package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
- package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
- package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
- package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
- package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
- package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
- package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
- package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
- package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
- package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
- package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -7
- package/dist/skills/workflow/SKILL.md +65 -50
- package/package.json +112 -110
- package/dist/extensions/enable-readonly-tools.test.ts +0 -63
- package/dist/extensions/enable-readonly-tools.ts +0 -24
- package/dist/extensions/model-prompt-injector/config.json +0 -16
- package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
- package/dist/extensions/model-prompt-injector/index.ts +0 -148
- package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
- package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pi Hermes Memory Extension
|
|
3
|
+
*
|
|
4
|
+
* Brings Hermes-style persistent memory and a learning loop to any Pi user.
|
|
5
|
+
* After `pi install`, users get:
|
|
6
|
+
*
|
|
7
|
+
* 1. Persistent Memory — MEMORY.md + USER.md that survive across sessions
|
|
8
|
+
* 2. Background Learning Loop — auto-saves notable facts every N turns
|
|
9
|
+
* 3. Session-End Flush — saves memories before compaction/shutdown
|
|
10
|
+
* 4. Auto-Consolidation — merges memory when full instead of erroring
|
|
11
|
+
* 5. Correction Detection — immediate save on user corrections
|
|
12
|
+
* 6. Procedural Skills — SKILL.md files for reusable procedures
|
|
13
|
+
* 7. Tool-Call-Aware Nudge — review triggers on tool call count too
|
|
14
|
+
* 8. /memory-insights — shows what's stored
|
|
15
|
+
* 9. /memory-skills — lists procedural skills
|
|
16
|
+
* 10. /memory-consolidate — manual consolidation trigger
|
|
17
|
+
* 11. /memory-interview — onboarding interview to pre-fill user profile
|
|
18
|
+
* 12. /memory-switch-project — list project memories
|
|
19
|
+
* 13. Context Fencing — <memory-context> tags prevent injection through stored memory
|
|
20
|
+
* 14. Memory Aging — entry timestamps guide consolidation
|
|
21
|
+
*
|
|
22
|
+
* See docs/ROADMAP.md for full roadmap and Hermes competitive analysis.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import * as path from "node:path";
|
|
26
|
+
import * as fs from "node:fs";
|
|
27
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
28
|
+
import { MemoryStore } from "./store/memory-store.js";
|
|
29
|
+
import { SkillStore } from "./store/skill-store.js";
|
|
30
|
+
import { DatabaseManager } from "./store/db.js";
|
|
31
|
+
import { indexSession, upsertSessionFileMetadata, pruneEphemeralReviewSessions } from "./store/session-indexer.js";
|
|
32
|
+
import { runRecoveryMaintenance } from "./store/recovery-maintenance.js";
|
|
33
|
+
import { scheduleSessionBackfill, waitForSessionBackfill, SESSION_BACKFILL_SHUTDOWN_TIMEOUT_MS } from "./handlers/session-backfill.js";
|
|
34
|
+
import { scheduleLiveSessionIndex, waitForLiveSessionIndex, SESSION_LIVE_INDEX_SHUTDOWN_TIMEOUT_MS } from "./handlers/session-live-index.js";
|
|
35
|
+
import { parseSessionFile } from "./store/session-parser.js";
|
|
36
|
+
import { registerMemoryTool } from "./tools/memory-tool.js";
|
|
37
|
+
import { registerSkillTool } from "./tools/skill-tool.js";
|
|
38
|
+
import { registerSessionSearchTool } from "./tools/session-search-tool.js";
|
|
39
|
+
import { registerMemorySearchTool } from "./tools/memory-search-tool.js";
|
|
40
|
+
import { setupBackgroundReview } from "./handlers/background-review.js";
|
|
41
|
+
import { setupSessionFlush } from "./handlers/session-flush.js";
|
|
42
|
+
import { registerInsightsCommand } from "./handlers/insights.js";
|
|
43
|
+
import { triggerConsolidation, registerConsolidateCommand } from "./handlers/auto-consolidate.js";
|
|
44
|
+
import { setupCorrectionDetector } from "./handlers/correction-detector.js";
|
|
45
|
+
import { registerSkillsCommand } from "./handlers/skills-command.js";
|
|
46
|
+
import { registerInterviewCommand } from "./handlers/interview.js";
|
|
47
|
+
import { registerSwitchProjectCommand } from "./handlers/switch-project.js";
|
|
48
|
+
import { registerIndexSessionsCommand } from "./handlers/index-sessions.js";
|
|
49
|
+
import { registerLearnMemoryCommand } from "./handlers/learn-memory.js";
|
|
50
|
+
import { migrateThenSyncMarkdownMemories, registerSyncMarkdownMemoriesCommand } from "./handlers/sync-markdown-memories.js";
|
|
51
|
+
import { registerPreviewContextCommand } from "./handlers/preview-context.js";
|
|
52
|
+
import { registerStandingPinCommand } from "./handlers/standing-pin.js";
|
|
53
|
+
import { StandingInstructions } from "./store/standing-instructions.js";
|
|
54
|
+
import { STANDING_FILE } from "./constants.js";
|
|
55
|
+
import { loadConfig } from "./config.js";
|
|
56
|
+
import { shouldWarnAutoConsolidationFailure } from "./auto-consolidation-warning.js";
|
|
57
|
+
import { detectProject, detectProjectSkills } from "./project.js";
|
|
58
|
+
import { buildPromptContext } from "./prompt-context.js";
|
|
59
|
+
import { migrateLegacyProjectMemoryDirs } from "./project-memory-migration.js";
|
|
60
|
+
import { AGENT_ROOT } from "./paths.js";
|
|
61
|
+
import { isDatabaseMigrationPending } from "./extension-root-migration.js";
|
|
62
|
+
import { measureLifecycle, measureLifecycleSync } from "./lifecycle-timing.js";
|
|
63
|
+
|
|
64
|
+
export function resolveProjectSkillDiscovery(
|
|
65
|
+
skillStore: SkillStore,
|
|
66
|
+
projectsMemoryDir: string | undefined,
|
|
67
|
+
cwd?: string,
|
|
68
|
+
): { skillPaths: string[] } {
|
|
69
|
+
const detected = detectProjectSkills(projectsMemoryDir, cwd);
|
|
70
|
+
skillStore.setProjectContext(detected.name, detected.skillsDir);
|
|
71
|
+
|
|
72
|
+
// Pi auto-discovers its own `~/.selesai/agent/skills/`, but this extension keeps
|
|
73
|
+
// its generated skills in a directory of its own so users can audit, wipe, or
|
|
74
|
+
// ignore them without touching skills they installed themselves (#126). Both
|
|
75
|
+
// of ours must therefore be contributed here.
|
|
76
|
+
const skillPaths = [skillStore.getGlobalSkillsDir()];
|
|
77
|
+
if (detected.skillsDir) skillPaths.push(detected.skillsDir);
|
|
78
|
+
return { skillPaths };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function registerProjectSkillDiscoveryHandler(
|
|
82
|
+
pi: Pick<ExtensionAPI, "on">,
|
|
83
|
+
skillStore: SkillStore,
|
|
84
|
+
projectsMemoryDir: string | undefined,
|
|
85
|
+
): void {
|
|
86
|
+
pi.on("resources_discover", async (event, _ctx) => {
|
|
87
|
+
return resolveProjectSkillDiscovery(skillStore, projectsMemoryDir, (event as { cwd?: string }).cwd);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default function (pi: ExtensionAPI) {
|
|
92
|
+
const config = loadConfig();
|
|
93
|
+
|
|
94
|
+
const agentRoot = AGENT_ROOT;
|
|
95
|
+
const legacyGlobalDir = path.join(agentRoot, "memory");
|
|
96
|
+
const defaultGlobalDir = path.join(agentRoot, "pi-hermes-memory");
|
|
97
|
+
|
|
98
|
+
const configuredMemoryDir = config.memoryDir?.trim();
|
|
99
|
+
const pointsToLegacyMemoryDir = configuredMemoryDir
|
|
100
|
+
? path.resolve(configuredMemoryDir) === path.resolve(legacyGlobalDir)
|
|
101
|
+
: false;
|
|
102
|
+
|
|
103
|
+
const globalDir = !configuredMemoryDir || pointsToLegacyMemoryDir
|
|
104
|
+
? defaultGlobalDir
|
|
105
|
+
: configuredMemoryDir;
|
|
106
|
+
|
|
107
|
+
const shouldMigrateExtensionRoot = !configuredMemoryDir || pointsToLegacyMemoryDir;
|
|
108
|
+
let persistenceInitialized = false;
|
|
109
|
+
|
|
110
|
+
const store = new MemoryStore({ ...config, memoryDir: globalDir });
|
|
111
|
+
// Factory may run with no session (Pi public contract). Do not snapshot
|
|
112
|
+
// project identity from process.cwd() here — bind from session_start ctx.cwd
|
|
113
|
+
// and from tool execute ctx.cwd.
|
|
114
|
+
let projectName = "";
|
|
115
|
+
const skillStore = new SkillStore({
|
|
116
|
+
globalSkillsDir: path.join(globalDir, "skills"),
|
|
117
|
+
piGlobalSkillsDir: path.join(agentRoot, "skills"),
|
|
118
|
+
projectSkillsDir: null,
|
|
119
|
+
projectName: null,
|
|
120
|
+
legacySkillsDir: path.join(legacyGlobalDir, "skills"),
|
|
121
|
+
migrationSentinelPath: path.join(globalDir, ".skills-migrated-to-extension-storage"),
|
|
122
|
+
});
|
|
123
|
+
const dbManager = new DatabaseManager(globalDir);
|
|
124
|
+
let databaseMigrationPending = shouldMigrateExtensionRoot
|
|
125
|
+
&& isDatabaseMigrationPending(legacyGlobalDir, globalDir);
|
|
126
|
+
if (databaseMigrationPending) {
|
|
127
|
+
dbManager.setOpenGuard(() => {
|
|
128
|
+
if (databaseMigrationPending) {
|
|
129
|
+
throw new Error("Legacy sessions.db migration is pending");
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const sessionsDir = path.join(agentRoot, "sessions");
|
|
134
|
+
|
|
135
|
+
const refreshSkillProjectContext = (cwd?: string) => {
|
|
136
|
+
const resource = resolveProjectSkillDiscovery(skillStore, config.projectsMemoryDir, cwd);
|
|
137
|
+
return {
|
|
138
|
+
name: skillStore.getProjectName(),
|
|
139
|
+
skillsDir: skillStore.getProjectSkillsDir(),
|
|
140
|
+
resource,
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// Keep project memory available for users upgrading from the old
|
|
145
|
+
// ~/.selesai/agent/<project>/ layout. This is non-destructive: legacy folders
|
|
146
|
+
// remain in place while entries are copied/merged into projects-memory/.
|
|
147
|
+
migrateLegacyProjectMemoryDirs(agentRoot, config.projectsMemoryDir);
|
|
148
|
+
// Project-scoped store: ~/.selesai/agent/<projectsMemoryDir>/<project_name>/
|
|
149
|
+
// Bound from session/tool ctx.cwd, never from factory process.cwd().
|
|
150
|
+
const createProjectStore = (projectInfo: ReturnType<typeof detectProject>): MemoryStore | null => {
|
|
151
|
+
if (!projectInfo.memoryDir) return null;
|
|
152
|
+
return new MemoryStore({
|
|
153
|
+
...config,
|
|
154
|
+
memoryCharLimit: config.projectCharLimit,
|
|
155
|
+
memoryDir: projectInfo.memoryDir,
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
let projectMemoryDir: string | null = null;
|
|
159
|
+
let projectStore: MemoryStore | null = null;
|
|
160
|
+
const projectStoreRef = () => projectStore;
|
|
161
|
+
const projectNameRef = () => projectName;
|
|
162
|
+
let configureProjectStore: (candidate: MemoryStore | null) => void = () => {};
|
|
163
|
+
let configureMemoryToolProjectStore: (candidate: MemoryStore | null) => void = () => {};
|
|
164
|
+
const bindProjectFromCwd = async (cwd?: string): Promise<void> => {
|
|
165
|
+
if (!cwd) return;
|
|
166
|
+
const nextProject = detectProject(config.projectsMemoryDir, cwd);
|
|
167
|
+
const nextProjectMemoryDir = nextProject.memoryDir ?? null;
|
|
168
|
+
if (nextProjectMemoryDir !== projectMemoryDir) {
|
|
169
|
+
projectMemoryDir = nextProjectMemoryDir;
|
|
170
|
+
projectStore = createProjectStore(nextProject);
|
|
171
|
+
configureProjectStore(projectStore);
|
|
172
|
+
configureMemoryToolProjectStore(projectStore);
|
|
173
|
+
if (projectStore) await projectStore.loadFromDisk();
|
|
174
|
+
}
|
|
175
|
+
projectName = nextProject.name ?? "";
|
|
176
|
+
};
|
|
177
|
+
// Never written by review, consolidation or the correction detector — see
|
|
178
|
+
// store/standing-instructions.ts for why provenance has to be structural.
|
|
179
|
+
const standingStore = config.standingInstructionsEnabled !== false
|
|
180
|
+
? new StandingInstructions(path.join(globalDir, STANDING_FILE))
|
|
181
|
+
: null;
|
|
182
|
+
|
|
183
|
+
// ── 1. Load memory from disk on session start ──
|
|
184
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
185
|
+
if (!persistenceInitialized) {
|
|
186
|
+
try {
|
|
187
|
+
await measureLifecycle("session-start.persistence-sync", async () => {
|
|
188
|
+
await migrateThenSyncMarkdownMemories(
|
|
189
|
+
dbManager,
|
|
190
|
+
shouldMigrateExtensionRoot ? legacyGlobalDir : null,
|
|
191
|
+
globalDir,
|
|
192
|
+
config.projectsMemoryDir,
|
|
193
|
+
agentRoot,
|
|
194
|
+
{
|
|
195
|
+
onMigrationSucceeded: () => {
|
|
196
|
+
databaseMigrationPending = false;
|
|
197
|
+
dbManager.setOpenGuard(null);
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
persistenceInitialized = true;
|
|
203
|
+
} catch {
|
|
204
|
+
// Best-effort only: migration or SQLite backfill must not block startup.
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
await measureLifecycle("session-start.load", async () => {
|
|
209
|
+
await bindProjectFromCwd(ctx.cwd);
|
|
210
|
+
refreshSkillProjectContext(ctx.cwd);
|
|
211
|
+
await skillStore.migrateLegacySkills();
|
|
212
|
+
await skillStore.ensureDiscoveredRoots();
|
|
213
|
+
await store.loadFromDisk();
|
|
214
|
+
if (projectStore) await projectStore.loadFromDisk();
|
|
215
|
+
if (standingStore) await standingStore.load();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
if (persistenceInitialized) {
|
|
219
|
+
try {
|
|
220
|
+
pruneEphemeralReviewSessions(dbManager);
|
|
221
|
+
} catch (err) {
|
|
222
|
+
console.warn(`⚠️ Ephemeral session cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
await runRecoveryMaintenance({ config, globalDir });
|
|
226
|
+
} catch (err) {
|
|
227
|
+
console.warn(`⚠️ Snapshot retention sweep failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
228
|
+
}
|
|
229
|
+
scheduleSessionBackfill(dbManager, sessionsDir, {
|
|
230
|
+
notify: (message, level) => {
|
|
231
|
+
const ui = (ctx as { ui?: { notify?: (message: string, level?: string) => void } }).ui;
|
|
232
|
+
if (ui?.notify) {
|
|
233
|
+
ui.notify(message, level);
|
|
234
|
+
} else if (level === "error" || level === "warning") {
|
|
235
|
+
console.warn(message);
|
|
236
|
+
} else {
|
|
237
|
+
console.info(message);
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
registerProjectSkillDiscoveryHandler(pi, skillStore, config.projectsMemoryDir);
|
|
245
|
+
|
|
246
|
+
// ── 2. Inject memory policy by default; legacy mode keeps full frozen memory blocks ──
|
|
247
|
+
pi.on("before_agent_start", async (event, _ctx) => {
|
|
248
|
+
const promptContext = await buildPromptContext(config, store, projectStoreRef(), projectNameRef(), standingStore);
|
|
249
|
+
|
|
250
|
+
if (promptContext) {
|
|
251
|
+
return {
|
|
252
|
+
systemPrompt: event.systemPrompt + "\n\n" + promptContext,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// ── 3. Register action-specific memory write tools with SQLite sync ──
|
|
258
|
+
configureMemoryToolProjectStore = registerMemoryTool(pi, store, projectStoreRef, dbManager, projectNameRef, bindProjectFromCwd);
|
|
259
|
+
|
|
260
|
+
// ── 4. Register the skill tool ──
|
|
261
|
+
registerSkillTool(pi, skillStore);
|
|
262
|
+
|
|
263
|
+
// ── 5. Setup background learning loop (with tool-call-aware nudge) ──
|
|
264
|
+
setupBackgroundReview(pi, store, projectStoreRef, config, {
|
|
265
|
+
dbManager,
|
|
266
|
+
projectName: projectNameRef,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// ── 6. Setup session-end flush ──
|
|
270
|
+
setupSessionFlush(pi, store, projectStoreRef, config, dbManager, projectNameRef);
|
|
271
|
+
|
|
272
|
+
// ── 7. Setup auto-consolidation (inject consolidator into stores) ──
|
|
273
|
+
// Keep the failure in the tool result regardless; session-console logging is
|
|
274
|
+
// separately configurable for users who already monitor tool results (#135).
|
|
275
|
+
const runAutoConsolidation = async (
|
|
276
|
+
target: "memory" | "user" | "failure",
|
|
277
|
+
targetStore: MemoryStore,
|
|
278
|
+
toolTarget: "memory" | "user" | "failure" | "project",
|
|
279
|
+
signal?: AbortSignal,
|
|
280
|
+
) => {
|
|
281
|
+
const result = await triggerConsolidation(
|
|
282
|
+
pi,
|
|
283
|
+
targetStore,
|
|
284
|
+
target,
|
|
285
|
+
signal,
|
|
286
|
+
config.consolidationTimeoutMs,
|
|
287
|
+
toolTarget,
|
|
288
|
+
config,
|
|
289
|
+
);
|
|
290
|
+
if (result.deferred) {
|
|
291
|
+
console.info(`⏳ Auto-consolidation for '${toolTarget}' deferred: ${result.error ?? "another session holds the consolidation lock"}`);
|
|
292
|
+
} else if (shouldWarnAutoConsolidationFailure(config.autoConsolidationWarnOnFailure, result.consolidated)) {
|
|
293
|
+
console.warn(`⚠️ Auto-consolidation failed for '${toolTarget}': ${result.error ?? "no reason reported"}`);
|
|
294
|
+
}
|
|
295
|
+
return result;
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
store.setConsolidator((target, signal) => runAutoConsolidation(target, store, target, signal));
|
|
299
|
+
configureProjectStore = (candidate) => {
|
|
300
|
+
if (!candidate) return;
|
|
301
|
+
candidate.setConsolidator((target, signal) =>
|
|
302
|
+
runAutoConsolidation(target, candidate, target === "memory" ? "project" : target, signal),
|
|
303
|
+
);
|
|
304
|
+
};
|
|
305
|
+
configureProjectStore(projectStore);
|
|
306
|
+
registerConsolidateCommand(pi, store, config.consolidationTimeoutMs, projectStoreRef, projectNameRef, config, dbManager);
|
|
307
|
+
|
|
308
|
+
// ── 8. Setup correction detection ──
|
|
309
|
+
setupCorrectionDetector(pi, store, projectStoreRef, config, dbManager, projectNameRef);
|
|
310
|
+
|
|
311
|
+
// ── 9. Register commands ──
|
|
312
|
+
registerInsightsCommand(pi, store, projectStoreRef, projectNameRef);
|
|
313
|
+
registerSkillsCommand(pi, skillStore);
|
|
314
|
+
registerInterviewCommand(pi, store);
|
|
315
|
+
registerSwitchProjectCommand(pi, config);
|
|
316
|
+
registerLearnMemoryCommand(pi);
|
|
317
|
+
registerSyncMarkdownMemoriesCommand(pi, dbManager, globalDir, config.projectsMemoryDir, agentRoot);
|
|
318
|
+
registerPreviewContextCommand(pi, store, projectStoreRef, projectNameRef, config, standingStore);
|
|
319
|
+
if (standingStore) registerStandingPinCommand(pi, standingStore);
|
|
320
|
+
|
|
321
|
+
// ── 10. Live session indexing ──
|
|
322
|
+
pi.on("message_end", async (_event, ctx) => {
|
|
323
|
+
scheduleLiveSessionIndex(dbManager, ctx.sessionManager, {
|
|
324
|
+
onError: (err) => console.warn(`⚠️ Live session indexing failed: ${err instanceof Error ? err.message : String(err)}`),
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// ── 11. SQLite session search + extended memory ──
|
|
329
|
+
registerSessionSearchTool(pi, dbManager, config.sessionSearch ?? { variant: "legacy" });
|
|
330
|
+
registerMemorySearchTool(pi, dbManager);
|
|
331
|
+
registerIndexSessionsCommand(pi);
|
|
332
|
+
|
|
333
|
+
// ── 12. Auto-index session on shutdown ──
|
|
334
|
+
// Registered last, so this runs after the session-flush shutdown handler and
|
|
335
|
+
// is the final DB activity. Closing here truncates the WAL via
|
|
336
|
+
// PRAGMA wal_checkpoint(TRUNCATE); without it the WAL only grows to its
|
|
337
|
+
// high-water mark and is never reclaimed across sessions.
|
|
338
|
+
//
|
|
339
|
+
// Ordering is safe: Pi's ExtensionRunner.emit() runs same-extension handlers
|
|
340
|
+
// sequentially in registration order and awaits each one, so the flush above
|
|
341
|
+
// fully completes before close() runs. WARNING: do not register another
|
|
342
|
+
// DB-writing session_shutdown handler after this block — it would run after
|
|
343
|
+
// close() and silently no-op.
|
|
344
|
+
pi.on("session_shutdown", async (_event, ctx) => {
|
|
345
|
+
try {
|
|
346
|
+
measureLifecycleSync("shutdown.active-index", () => {
|
|
347
|
+
const sessionFile = ctx.sessionManager.getSessionFile();
|
|
348
|
+
if (sessionFile && require("node:fs").existsSync(sessionFile)) {
|
|
349
|
+
const sessionData = parseSessionFile(sessionFile);
|
|
350
|
+
if (sessionData) {
|
|
351
|
+
dbManager.withCorruptionRecovery(() => {
|
|
352
|
+
indexSession(dbManager, sessionData);
|
|
353
|
+
// Keep session_files metadata in sync with the final on-disk state.
|
|
354
|
+
// Pi appends the closing session entry on shutdown after the last
|
|
355
|
+
// message_end, so without this upsert the stored size/mtime would be
|
|
356
|
+
// stale and the next startup would re-parse this file unnecessarily.
|
|
357
|
+
upsertSessionFileMetadata(dbManager, sessionFile, sessionData.id);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
} catch {
|
|
363
|
+
// Silent fail — don't block shutdown
|
|
364
|
+
} finally {
|
|
365
|
+
try {
|
|
366
|
+
await measureLifecycle("shutdown.index-waits", () => Promise.all([
|
|
367
|
+
waitForSessionBackfill(SESSION_BACKFILL_SHUTDOWN_TIMEOUT_MS),
|
|
368
|
+
waitForLiveSessionIndex(SESSION_LIVE_INDEX_SHUTDOWN_TIMEOUT_MS),
|
|
369
|
+
]));
|
|
370
|
+
} catch {
|
|
371
|
+
// Best effort only — shutdown should not be held up by indexing errors.
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
measureLifecycleSync("shutdown.database-close", () => dbManager.close());
|
|
375
|
+
} catch { /* best effort — never block shutdown */ }
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export interface LifecycleTimingOptions {
|
|
2
|
+
enabled?: boolean;
|
|
3
|
+
now?: () => number;
|
|
4
|
+
log?: (line: string) => void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function isEnabled(options: LifecycleTimingOptions): boolean {
|
|
8
|
+
return options.enabled ?? process.env.PI_TIMING === "1";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function recordDuration(
|
|
12
|
+
label: string,
|
|
13
|
+
startedAt: number,
|
|
14
|
+
options: LifecycleTimingOptions,
|
|
15
|
+
): void {
|
|
16
|
+
try {
|
|
17
|
+
const now = options.now ?? Date.now;
|
|
18
|
+
const log = options.log ?? ((line: string) => console.error(line));
|
|
19
|
+
const durationMs = Math.max(0, Math.round(now() - startedAt));
|
|
20
|
+
log(`[pi-hermes-memory timing] ${label}: ${durationMs}ms`);
|
|
21
|
+
} catch {
|
|
22
|
+
// Profiling must not alter lifecycle behavior.
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function measureLifecycleSync<T>(
|
|
27
|
+
label: string,
|
|
28
|
+
operation: () => T,
|
|
29
|
+
options: LifecycleTimingOptions = {},
|
|
30
|
+
): T {
|
|
31
|
+
if (!isEnabled(options)) return operation();
|
|
32
|
+
const now = options.now ?? Date.now;
|
|
33
|
+
const startedAt = now();
|
|
34
|
+
try {
|
|
35
|
+
return operation();
|
|
36
|
+
} finally {
|
|
37
|
+
recordDuration(label, startedAt, options);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function measureLifecycle<T>(
|
|
42
|
+
label: string,
|
|
43
|
+
operation: () => Promise<T>,
|
|
44
|
+
options: LifecycleTimingOptions = {},
|
|
45
|
+
): Promise<T> {
|
|
46
|
+
if (!isEnabled(options)) return operation();
|
|
47
|
+
const now = options.now ?? Date.now;
|
|
48
|
+
const startedAt = now();
|
|
49
|
+
try {
|
|
50
|
+
return await operation();
|
|
51
|
+
} finally {
|
|
52
|
+
recordDuration(label, startedAt, options);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as os from "node:os";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { DEFAULT_PROJECTS_MEMORY_DIR } from "./constants.js";
|
|
5
|
+
|
|
6
|
+
// Route through the host resolver only. The upstream `PI_CODING_AGENT_DIR`
|
|
7
|
+
// env var is deliberately NOT honored here: on the Selesai fork it would
|
|
8
|
+
// silently point memory at ~/.pi/agent while the host reads ~/.selesai/agent.
|
|
9
|
+
export const AGENT_ROOT = getAgentDir();
|
|
10
|
+
|
|
11
|
+
export function expandHome(input: string): string {
|
|
12
|
+
if (input === "~") return os.homedir();
|
|
13
|
+
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
14
|
+
return path.join(os.homedir(), input.slice(2));
|
|
15
|
+
}
|
|
16
|
+
return input;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function normalizeConfiguredMemoryDir(input: string): string | undefined {
|
|
20
|
+
const trimmed = input.trim();
|
|
21
|
+
if (!trimmed) return undefined;
|
|
22
|
+
|
|
23
|
+
const expanded = expandHome(trimmed);
|
|
24
|
+
if (path.isAbsolute(expanded)) return path.normalize(expanded);
|
|
25
|
+
return path.resolve(AGENT_ROOT, expanded);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isSafeRelativeDirectory(input: string): boolean {
|
|
29
|
+
const segments = input.split(/[\\/]+/).filter(Boolean);
|
|
30
|
+
return segments.length === 1 && segments[0] !== "." && segments[0] !== "..";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function normalizeProjectsMemoryDir(input: string): string | undefined {
|
|
34
|
+
const trimmed = input.trim();
|
|
35
|
+
if (!trimmed) return undefined;
|
|
36
|
+
|
|
37
|
+
const expanded = expandHome(trimmed);
|
|
38
|
+
let relative = expanded;
|
|
39
|
+
|
|
40
|
+
if (path.isAbsolute(expanded)) {
|
|
41
|
+
const resolved = path.resolve(expanded);
|
|
42
|
+
const relativeToAgentRoot = path.relative(AGENT_ROOT, resolved);
|
|
43
|
+
if (
|
|
44
|
+
relativeToAgentRoot === ""
|
|
45
|
+
|| relativeToAgentRoot.startsWith("..")
|
|
46
|
+
|| path.isAbsolute(relativeToAgentRoot)
|
|
47
|
+
) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
relative = relativeToAgentRoot;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const normalized = path.normalize(relative).replace(/^[\\/]+|[\\/]+$/g, "");
|
|
54
|
+
if (!isSafeRelativeDirectory(normalized)) return undefined;
|
|
55
|
+
return normalized;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function resolveProjectsRoot(projectsMemoryDir = DEFAULT_PROJECTS_MEMORY_DIR): string {
|
|
59
|
+
const normalized = normalizeProjectsMemoryDir(projectsMemoryDir) ?? DEFAULT_PROJECTS_MEMORY_DIR;
|
|
60
|
+
return path.join(AGENT_ROOT, normalized);
|
|
61
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MemoryStore } from "./store/memory-store.js";
|
|
2
|
+
|
|
3
|
+
export type ProjectStoreRef = MemoryStore | null | (() => MemoryStore | null);
|
|
4
|
+
export type ProjectNameRef = string | null | (() => string | null | undefined);
|
|
5
|
+
|
|
6
|
+
export function resolveProjectStore(ref: ProjectStoreRef): MemoryStore | null {
|
|
7
|
+
return typeof ref === "function" ? ref() : ref;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function resolveProjectName(ref: ProjectNameRef): string | null {
|
|
11
|
+
const value = typeof ref === "function" ? ref() : ref;
|
|
12
|
+
return value?.trim() || null;
|
|
13
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { ENTRY_DELIMITER, MEMORY_FILE } from "./constants.js";
|
|
4
|
+
|
|
5
|
+
export interface ProjectMemoryMigrationResult {
|
|
6
|
+
scanned: number;
|
|
7
|
+
copied: number;
|
|
8
|
+
merged: number;
|
|
9
|
+
skipped: number;
|
|
10
|
+
warnings: string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function readEntries(filePath: string): string[] {
|
|
14
|
+
if (!fs.existsSync(filePath)) return [];
|
|
15
|
+
const raw = fs.readFileSync(filePath, "utf-8").trim();
|
|
16
|
+
if (!raw) return [];
|
|
17
|
+
return raw.split(ENTRY_DELIMITER).map((entry) => entry.trim()).filter(Boolean);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function writeEntries(filePath: string, entries: string[]): void {
|
|
21
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
22
|
+
fs.writeFileSync(filePath, entries.join(ENTRY_DELIMITER), "utf-8");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function isLegacyProjectDir(agentRoot: string, projectsMemoryDir: string, name: string): boolean {
|
|
26
|
+
if (name === "memory" || name === "pi-hermes-memory" || name === "skills" || name === projectsMemoryDir) return false;
|
|
27
|
+
if (name.startsWith(".")) return false;
|
|
28
|
+
|
|
29
|
+
const dir = path.join(agentRoot, name);
|
|
30
|
+
return fs.existsSync(dir) && fs.statSync(dir).isDirectory() && fs.existsSync(path.join(dir, MEMORY_FILE));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function migrateLegacyProjectMemoryDirs(
|
|
34
|
+
agentRoot: string,
|
|
35
|
+
projectsMemoryDir = "projects-memory",
|
|
36
|
+
): ProjectMemoryMigrationResult {
|
|
37
|
+
const result: ProjectMemoryMigrationResult = {
|
|
38
|
+
scanned: 0,
|
|
39
|
+
copied: 0,
|
|
40
|
+
merged: 0,
|
|
41
|
+
skipped: 0,
|
|
42
|
+
warnings: [],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
if (!fs.existsSync(agentRoot)) return result;
|
|
46
|
+
|
|
47
|
+
const projectsRoot = path.join(agentRoot, projectsMemoryDir);
|
|
48
|
+
|
|
49
|
+
for (const name of fs.readdirSync(agentRoot)) {
|
|
50
|
+
if (!isLegacyProjectDir(agentRoot, projectsMemoryDir, name)) continue;
|
|
51
|
+
result.scanned++;
|
|
52
|
+
|
|
53
|
+
const legacyFile = path.join(agentRoot, name, MEMORY_FILE);
|
|
54
|
+
const targetFile = path.join(projectsRoot, name, MEMORY_FILE);
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const legacyEntries = readEntries(legacyFile);
|
|
58
|
+
if (legacyEntries.length === 0) {
|
|
59
|
+
result.skipped++;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!fs.existsSync(targetFile)) {
|
|
64
|
+
writeEntries(targetFile, legacyEntries);
|
|
65
|
+
result.copied++;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const targetEntries = readEntries(targetFile);
|
|
70
|
+
const mergedEntries = [...targetEntries];
|
|
71
|
+
const seen = new Set(targetEntries);
|
|
72
|
+
|
|
73
|
+
for (const entry of legacyEntries) {
|
|
74
|
+
if (!seen.has(entry)) {
|
|
75
|
+
seen.add(entry);
|
|
76
|
+
mergedEntries.push(entry);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (mergedEntries.length === targetEntries.length) {
|
|
81
|
+
result.skipped++;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
writeEntries(targetFile, mergedEntries);
|
|
86
|
+
result.merged++;
|
|
87
|
+
} catch (err) {
|
|
88
|
+
result.warnings.push(`${name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return result;
|
|
93
|
+
}
|