@vinaes/succ 1.4.0 → 1.5.37
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/README.md +64 -10
- package/dist/cli.js +71 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/agents-md.d.ts.map +1 -1
- package/dist/commands/agents-md.js +3 -2
- package/dist/commands/agents-md.js.map +1 -1
- package/dist/commands/analyze-profile.d.ts.map +1 -1
- package/dist/commands/analyze-profile.js +32 -8
- package/dist/commands/analyze-profile.js.map +1 -1
- package/dist/commands/analyze-recursive.d.ts.map +1 -1
- package/dist/commands/analyze-recursive.js +6 -2
- package/dist/commands/analyze-recursive.js.map +1 -1
- package/dist/commands/analyze-utils.d.ts.map +1 -1
- package/dist/commands/analyze-utils.js +17 -4
- package/dist/commands/analyze-utils.js.map +1 -1
- package/dist/commands/benchmark-quality.d.ts.map +1 -1
- package/dist/commands/benchmark-quality.js +11 -4
- package/dist/commands/benchmark-quality.js.map +1 -1
- package/dist/commands/benchmark-sqlite-vec.d.ts.map +1 -1
- package/dist/commands/benchmark-sqlite-vec.js +4 -0
- package/dist/commands/benchmark-sqlite-vec.js.map +1 -1
- package/dist/commands/benchmark.d.ts.map +1 -1
- package/dist/commands/benchmark.js +5 -1
- package/dist/commands/benchmark.js.map +1 -1
- package/dist/commands/codex-chat.d.ts +8 -0
- package/dist/commands/codex-chat.d.ts.map +1 -0
- package/dist/commands/codex-chat.js +161 -0
- package/dist/commands/codex-chat.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +32 -4
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +13 -4
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/index-code.d.ts +4 -0
- package/dist/commands/index-code.d.ts.map +1 -1
- package/dist/commands/index-code.js +1 -1
- package/dist/commands/index-code.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +305 -203
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/memories.d.ts.map +1 -1
- package/dist/commands/memories.js +25 -14
- package/dist/commands/memories.js.map +1 -1
- package/dist/commands/progress.d.ts.map +1 -1
- package/dist/commands/progress.js +3 -2
- package/dist/commands/progress.js.map +1 -1
- package/dist/commands/reindex.d.ts.map +1 -1
- package/dist/commands/reindex.js +54 -36
- package/dist/commands/reindex.js.map +1 -1
- package/dist/commands/retention.d.ts.map +1 -1
- package/dist/commands/retention.js +7 -5
- package/dist/commands/retention.js.map +1 -1
- package/dist/commands/scan-code.d.ts +76 -0
- package/dist/commands/scan-code.d.ts.map +1 -0
- package/dist/commands/scan-code.js +385 -0
- package/dist/commands/scan-code.js.map +1 -0
- package/dist/commands/score.d.ts.map +1 -1
- package/dist/commands/score.js +3 -2
- package/dist/commands/score.js.map +1 -1
- package/dist/commands/session.d.ts +33 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +163 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +254 -15
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/soul.js +3 -2
- package/dist/commands/soul.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +14 -5
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +13 -4
- package/dist/commands/watch.js.map +1 -1
- package/dist/daemon/analyzer.d.ts.map +1 -1
- package/dist/daemon/analyzer.js +21 -5
- package/dist/daemon/analyzer.js.map +1 -1
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +32 -8
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/routes/analyzer.d.ts +3 -0
- package/dist/daemon/routes/analyzer.d.ts.map +1 -0
- package/dist/daemon/routes/analyzer.js +27 -0
- package/dist/daemon/routes/analyzer.js.map +1 -0
- package/dist/daemon/routes/hooks.d.ts +14 -0
- package/dist/daemon/routes/hooks.d.ts.map +1 -0
- package/dist/daemon/routes/hooks.js +1212 -0
- package/dist/daemon/routes/hooks.js.map +1 -0
- package/dist/daemon/routes/memory.d.ts +4 -0
- package/dist/daemon/routes/memory.d.ts.map +1 -0
- package/dist/daemon/routes/memory.js +71 -0
- package/dist/daemon/routes/memory.js.map +1 -0
- package/dist/daemon/routes/reflection.d.ts +10 -0
- package/dist/daemon/routes/reflection.d.ts.map +1 -0
- package/dist/daemon/routes/reflection.js +397 -0
- package/dist/daemon/routes/reflection.js.map +1 -0
- package/dist/daemon/routes/search.d.ts +5 -0
- package/dist/daemon/routes/search.d.ts.map +1 -0
- package/dist/daemon/routes/search.js +93 -0
- package/dist/daemon/routes/search.js.map +1 -0
- package/dist/daemon/routes/sessions.d.ts +3 -0
- package/dist/daemon/routes/sessions.d.ts.map +1 -0
- package/dist/daemon/routes/sessions.js +160 -0
- package/dist/daemon/routes/sessions.js.map +1 -0
- package/dist/daemon/routes/skills.d.ts +3 -0
- package/dist/daemon/routes/skills.d.ts.map +1 -0
- package/dist/daemon/routes/skills.js +36 -0
- package/dist/daemon/routes/skills.js.map +1 -0
- package/dist/daemon/routes/status.d.ts +3 -0
- package/dist/daemon/routes/status.d.ts.map +1 -0
- package/dist/daemon/routes/status.js +47 -0
- package/dist/daemon/routes/status.js.map +1 -0
- package/dist/daemon/routes/types.d.ts +240 -0
- package/dist/daemon/routes/types.d.ts.map +1 -0
- package/dist/daemon/routes/types.js +97 -0
- package/dist/daemon/routes/types.js.map +1 -0
- package/dist/daemon/routes/versioning.d.ts +27 -0
- package/dist/daemon/routes/versioning.d.ts.map +1 -0
- package/dist/daemon/routes/versioning.js +44 -0
- package/dist/daemon/routes/versioning.js.map +1 -0
- package/dist/daemon/routes/watcher.d.ts +3 -0
- package/dist/daemon/routes/watcher.d.ts.map +1 -0
- package/dist/daemon/routes/watcher.js +28 -0
- package/dist/daemon/routes/watcher.js.map +1 -0
- package/dist/daemon/service.d.ts +5 -23
- package/dist/daemon/service.d.ts.map +1 -1
- package/dist/daemon/service.js +177 -935
- package/dist/daemon/service.js.map +1 -1
- package/dist/daemon/session-processor.d.ts +4 -8
- package/dist/daemon/session-processor.d.ts.map +1 -1
- package/dist/daemon/session-processor.js +39 -38
- package/dist/daemon/session-processor.js.map +1 -1
- package/dist/lib/ai-readiness.d.ts.map +1 -1
- package/dist/lib/ai-readiness.js +33 -8
- package/dist/lib/ai-readiness.js.map +1 -1
- package/dist/lib/analyze-state.d.ts.map +1 -1
- package/dist/lib/analyze-state.js +25 -3
- package/dist/lib/analyze-state.js.map +1 -1
- package/dist/lib/auto-memory/consolidation.d.ts +41 -0
- package/dist/lib/auto-memory/consolidation.d.ts.map +1 -0
- package/dist/lib/auto-memory/consolidation.js +151 -0
- package/dist/lib/auto-memory/consolidation.js.map +1 -0
- package/dist/lib/bpe.d.ts.map +1 -1
- package/dist/lib/bpe.js +9 -10
- package/dist/lib/bpe.js.map +1 -1
- package/dist/lib/brain-export.d.ts +65 -0
- package/dist/lib/brain-export.d.ts.map +1 -0
- package/dist/lib/brain-export.js +413 -0
- package/dist/lib/brain-export.js.map +1 -0
- package/dist/lib/checkpoint.d.ts.map +1 -1
- package/dist/lib/checkpoint.js +22 -6
- package/dist/lib/checkpoint.js.map +1 -1
- package/dist/lib/chunker.d.ts.map +1 -1
- package/dist/lib/chunker.js +6 -1
- package/dist/lib/chunker.js.map +1 -1
- package/dist/lib/claude-ws-transport.d.ts.map +1 -1
- package/dist/lib/claude-ws-transport.js +12 -4
- package/dist/lib/claude-ws-transport.js.map +1 -1
- package/dist/lib/command-safety.d.ts +64 -0
- package/dist/lib/command-safety.d.ts.map +1 -0
- package/dist/lib/command-safety.js +625 -0
- package/dist/lib/command-safety.js.map +1 -0
- package/dist/lib/compact-briefing.d.ts.map +1 -1
- package/dist/lib/compact-briefing.js +10 -13
- package/dist/lib/compact-briefing.js.map +1 -1
- package/dist/lib/config-defaults.d.ts.map +1 -1
- package/dist/lib/config-defaults.js +3 -0
- package/dist/lib/config-defaults.js.map +1 -1
- package/dist/lib/config-display.d.ts +4 -0
- package/dist/lib/config-display.d.ts.map +1 -1
- package/dist/lib/config-display.js +6 -1
- package/dist/lib/config-display.js.map +1 -1
- package/dist/lib/config-types.d.ts +149 -0
- package/dist/lib/config-types.d.ts.map +1 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/config-validation.js +5 -0
- package/dist/lib/config-validation.js.map +1 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +92 -9
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/consolidate.d.ts.map +1 -1
- package/dist/lib/consolidate.js +66 -47
- package/dist/lib/consolidate.js.map +1 -1
- package/dist/lib/content-sanitizer.d.ts +29 -0
- package/dist/lib/content-sanitizer.d.ts.map +1 -0
- package/dist/lib/content-sanitizer.js +72 -0
- package/dist/lib/content-sanitizer.js.map +1 -0
- package/dist/lib/cross-repo.d.ts +44 -0
- package/dist/lib/cross-repo.d.ts.map +1 -0
- package/dist/lib/cross-repo.js +108 -0
- package/dist/lib/cross-repo.js.map +1 -0
- package/dist/lib/daemon-port.d.ts +12 -0
- package/dist/lib/daemon-port.d.ts.map +1 -0
- package/dist/lib/daemon-port.js +20 -0
- package/dist/lib/daemon-port.js.map +1 -0
- package/dist/lib/db/auto-memory.d.ts +40 -0
- package/dist/lib/db/auto-memory.d.ts.map +1 -0
- package/dist/lib/db/auto-memory.js +74 -0
- package/dist/lib/db/auto-memory.js.map +1 -0
- package/dist/lib/db/bm25-indexes.d.ts.map +1 -1
- package/dist/lib/db/bm25-indexes.js +16 -4
- package/dist/lib/db/bm25-indexes.js.map +1 -1
- package/dist/lib/db/documents.d.ts.map +1 -1
- package/dist/lib/db/documents.js +4 -1
- package/dist/lib/db/documents.js.map +1 -1
- package/dist/lib/db/global-memories.d.ts +2 -10
- package/dist/lib/db/global-memories.d.ts.map +1 -1
- package/dist/lib/db/global-memories.js +13 -6
- package/dist/lib/db/global-memories.js.map +1 -1
- package/dist/lib/db/graph.d.ts +5 -1
- package/dist/lib/db/graph.d.ts.map +1 -1
- package/dist/lib/db/graph.js +38 -8
- package/dist/lib/db/graph.js.map +1 -1
- package/dist/lib/db/hybrid-search.d.ts +4 -2
- package/dist/lib/db/hybrid-search.d.ts.map +1 -1
- package/dist/lib/db/hybrid-search.js +29 -11
- package/dist/lib/db/hybrid-search.js.map +1 -1
- package/dist/lib/db/index.d.ts +6 -1
- package/dist/lib/db/index.d.ts.map +1 -1
- package/dist/lib/db/index.js +5 -1
- package/dist/lib/db/index.js.map +1 -1
- package/dist/lib/db/memories.d.ts +19 -14
- package/dist/lib/db/memories.d.ts.map +1 -1
- package/dist/lib/db/memories.js +100 -37
- package/dist/lib/db/memories.js.map +1 -1
- package/dist/lib/db/parse-helpers.d.ts +14 -0
- package/dist/lib/db/parse-helpers.d.ts.map +1 -0
- package/dist/lib/db/parse-helpers.js +59 -0
- package/dist/lib/db/parse-helpers.js.map +1 -0
- package/dist/lib/db/recall-events.d.ts +49 -0
- package/dist/lib/db/recall-events.d.ts.map +1 -0
- package/dist/lib/db/recall-events.js +196 -0
- package/dist/lib/db/recall-events.js.map +1 -0
- package/dist/lib/db/retention.d.ts +4 -3
- package/dist/lib/db/retention.d.ts.map +1 -1
- package/dist/lib/db/retention.js +12 -1
- package/dist/lib/db/retention.js.map +1 -1
- package/dist/lib/db/schema.d.ts +2 -0
- package/dist/lib/db/schema.d.ts.map +1 -1
- package/dist/lib/db/schema.js +140 -80
- package/dist/lib/db/schema.js.map +1 -1
- package/dist/lib/db/skills.d.ts.map +1 -1
- package/dist/lib/db/skills.js +10 -6
- package/dist/lib/db/skills.js.map +1 -1
- package/dist/lib/diff-brain.d.ts +24 -0
- package/dist/lib/diff-brain.d.ts.map +1 -0
- package/dist/lib/diff-brain.js +114 -0
- package/dist/lib/diff-brain.js.map +1 -0
- package/dist/lib/diff-parser.d.ts +74 -0
- package/dist/lib/diff-parser.d.ts.map +1 -0
- package/dist/lib/diff-parser.js +200 -0
- package/dist/lib/diff-parser.js.map +1 -0
- package/dist/lib/embedding-pool.d.ts.map +1 -1
- package/dist/lib/embedding-pool.js +5 -1
- package/dist/lib/embedding-pool.js.map +1 -1
- package/dist/lib/embeddings.d.ts +12 -0
- package/dist/lib/embeddings.d.ts.map +1 -1
- package/dist/lib/embeddings.js +77 -19
- package/dist/lib/embeddings.js.map +1 -1
- package/dist/lib/errors.d.ts +2 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +4 -0
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/fault-logger.d.ts.map +1 -1
- package/dist/lib/fault-logger.js +22 -7
- package/dist/lib/fault-logger.js.map +1 -1
- package/dist/lib/git/co-change.d.ts +39 -0
- package/dist/lib/git/co-change.d.ts.map +1 -0
- package/dist/lib/git/co-change.js +139 -0
- package/dist/lib/git/co-change.js.map +1 -0
- package/dist/lib/graph/bridge-edges.d.ts +93 -0
- package/dist/lib/graph/bridge-edges.d.ts.map +1 -0
- package/dist/lib/graph/bridge-edges.js +276 -0
- package/dist/lib/graph/bridge-edges.js.map +1 -0
- package/dist/lib/graph/centrality.d.ts +11 -0
- package/dist/lib/graph/centrality.d.ts.map +1 -1
- package/dist/lib/graph/centrality.js +51 -3
- package/dist/lib/graph/centrality.js.map +1 -1
- package/dist/lib/graph/cleanup.d.ts.map +1 -1
- package/dist/lib/graph/cleanup.js +2 -1
- package/dist/lib/graph/cleanup.js.map +1 -1
- package/dist/lib/graph/community-detection.d.ts +17 -2
- package/dist/lib/graph/community-detection.d.ts.map +1 -1
- package/dist/lib/graph/community-detection.js +147 -48
- package/dist/lib/graph/community-detection.js.map +1 -1
- package/dist/lib/graph/community-summaries.d.ts +26 -0
- package/dist/lib/graph/community-summaries.d.ts.map +1 -0
- package/dist/lib/graph/community-summaries.js +130 -0
- package/dist/lib/graph/community-summaries.js.map +1 -0
- package/dist/lib/graph/contextual-proximity.d.ts.map +1 -1
- package/dist/lib/graph/contextual-proximity.js +11 -4
- package/dist/lib/graph/contextual-proximity.js.map +1 -1
- package/dist/lib/graph/graphology-bridge.d.ts +101 -0
- package/dist/lib/graph/graphology-bridge.d.ts.map +1 -0
- package/dist/lib/graph/graphology-bridge.js +488 -0
- package/dist/lib/graph/graphology-bridge.js.map +1 -0
- package/dist/lib/graph/llm-relations.d.ts.map +1 -1
- package/dist/lib/graph/llm-relations.js +27 -5
- package/dist/lib/graph/llm-relations.js.map +1 -1
- package/dist/lib/graph-export.d.ts.map +1 -1
- package/dist/lib/graph-export.js +2 -2
- package/dist/lib/graph-export.js.map +1 -1
- package/dist/lib/graph-scheduler.d.ts +0 -5
- package/dist/lib/graph-scheduler.d.ts.map +1 -1
- package/dist/lib/graph-scheduler.js +5 -1
- package/dist/lib/graph-scheduler.js.map +1 -1
- package/dist/lib/guardrails.d.ts +50 -0
- package/dist/lib/guardrails.d.ts.map +1 -0
- package/dist/lib/guardrails.js +502 -0
- package/dist/lib/guardrails.js.map +1 -0
- package/dist/lib/hook-rules.d.ts +1 -1
- package/dist/lib/hook-rules.d.ts.map +1 -1
- package/dist/lib/hook-rules.js +8 -2
- package/dist/lib/hook-rules.js.map +1 -1
- package/dist/lib/ifc/file-labels.d.ts +35 -0
- package/dist/lib/ifc/file-labels.d.ts.map +1 -0
- package/dist/lib/ifc/file-labels.js +208 -0
- package/dist/lib/ifc/file-labels.js.map +1 -0
- package/dist/lib/ifc/label.d.ts +38 -0
- package/dist/lib/ifc/label.d.ts.map +1 -0
- package/dist/lib/ifc/label.js +80 -0
- package/dist/lib/ifc/label.js.map +1 -0
- package/dist/lib/ifc/session-ifc.d.ts +92 -0
- package/dist/lib/ifc/session-ifc.d.ts.map +1 -0
- package/dist/lib/ifc/session-ifc.js +222 -0
- package/dist/lib/ifc/session-ifc.js.map +1 -0
- package/dist/lib/indexer.js +2 -2
- package/dist/lib/indexer.js.map +1 -1
- package/dist/lib/injection-detector.d.ts +83 -0
- package/dist/lib/injection-detector.d.ts.map +1 -0
- package/dist/lib/injection-detector.js +586 -0
- package/dist/lib/injection-detector.js.map +1 -0
- package/dist/lib/injection-semantic.d.ts +31 -0
- package/dist/lib/injection-semantic.d.ts.map +1 -0
- package/dist/lib/injection-semantic.js +230 -0
- package/dist/lib/injection-semantic.js.map +1 -0
- package/dist/lib/llm.d.ts.map +1 -1
- package/dist/lib/llm.js +19 -4
- package/dist/lib/llm.js.map +1 -1
- package/dist/lib/lock.d.ts.map +1 -1
- package/dist/lib/lock.js +24 -3
- package/dist/lib/lock.js.map +1 -1
- package/dist/lib/md-fetch.d.ts.map +1 -1
- package/dist/lib/md-fetch.js +9 -2
- package/dist/lib/md-fetch.js.map +1 -1
- package/dist/lib/observability.d.ts +75 -0
- package/dist/lib/observability.d.ts.map +1 -0
- package/dist/lib/observability.js +201 -0
- package/dist/lib/observability.js.map +1 -0
- package/dist/lib/ort-session.d.ts +26 -0
- package/dist/lib/ort-session.d.ts.map +1 -1
- package/dist/lib/ort-session.js +107 -3
- package/dist/lib/ort-session.js.map +1 -1
- package/dist/lib/prd/codebase-context.d.ts.map +1 -1
- package/dist/lib/prd/codebase-context.js +9 -2
- package/dist/lib/prd/codebase-context.js.map +1 -1
- package/dist/lib/prd/context.d.ts.map +1 -1
- package/dist/lib/prd/context.js +11 -3
- package/dist/lib/prd/context.js.map +1 -1
- package/dist/lib/prd/export.js +1 -1
- package/dist/lib/prd/export.js.map +1 -1
- package/dist/lib/prd/generate.d.ts.map +1 -1
- package/dist/lib/prd/generate.js +17 -4
- package/dist/lib/prd/generate.js.map +1 -1
- package/dist/lib/prd/parse.d.ts.map +1 -1
- package/dist/lib/prd/parse.js +6 -1
- package/dist/lib/prd/parse.js.map +1 -1
- package/dist/lib/prd/runner.d.ts +1 -2
- package/dist/lib/prd/runner.d.ts.map +1 -1
- package/dist/lib/prd/runner.js +43 -32
- package/dist/lib/prd/runner.js.map +1 -1
- package/dist/lib/prd/worktree.d.ts +1 -2
- package/dist/lib/prd/worktree.d.ts.map +1 -1
- package/dist/lib/prd/worktree.js +62 -70
- package/dist/lib/prd/worktree.js.map +1 -1
- package/dist/lib/precompute-context.d.ts.map +1 -1
- package/dist/lib/precompute-context.js +15 -34
- package/dist/lib/precompute-context.js.map +1 -1
- package/dist/lib/pricing.d.ts.map +1 -1
- package/dist/lib/pricing.js +5 -1
- package/dist/lib/pricing.js.map +1 -1
- package/dist/lib/process-registry.js +3 -3
- package/dist/lib/process-registry.js.map +1 -1
- package/dist/lib/public-api.d.ts +41 -1
- package/dist/lib/public-api.d.ts.map +1 -1
- package/dist/lib/public-api.js +38 -0
- package/dist/lib/public-api.js.map +1 -1
- package/dist/lib/quality.d.ts.map +1 -1
- package/dist/lib/quality.js +15 -6
- package/dist/lib/quality.js.map +1 -1
- package/dist/lib/query-expansion.d.ts +32 -0
- package/dist/lib/query-expansion.d.ts.map +1 -1
- package/dist/lib/query-expansion.js +62 -1
- package/dist/lib/query-expansion.js.map +1 -1
- package/dist/lib/reference-embeddings.d.ts.map +1 -1
- package/dist/lib/reference-embeddings.js +17 -4
- package/dist/lib/reference-embeddings.js.map +1 -1
- package/dist/lib/reflection-synthesizer.d.ts.map +1 -1
- package/dist/lib/reflection-synthesizer.js +7 -1
- package/dist/lib/reflection-synthesizer.js.map +1 -1
- package/dist/lib/reranker.d.ts +41 -0
- package/dist/lib/reranker.d.ts.map +1 -0
- package/dist/lib/reranker.js +294 -0
- package/dist/lib/reranker.js.map +1 -0
- package/dist/lib/retrieval-feedback.d.ts +100 -0
- package/dist/lib/retrieval-feedback.d.ts.map +1 -0
- package/dist/lib/retrieval-feedback.js +174 -0
- package/dist/lib/retrieval-feedback.js.map +1 -0
- package/dist/lib/review/context-pack.d.ts +58 -0
- package/dist/lib/review/context-pack.d.ts.map +1 -0
- package/dist/lib/review/context-pack.js +300 -0
- package/dist/lib/review/context-pack.js.map +1 -0
- package/dist/lib/search/hierarchical-summaries.d.ts +65 -0
- package/dist/lib/search/hierarchical-summaries.d.ts.map +1 -0
- package/dist/lib/search/hierarchical-summaries.js +423 -0
- package/dist/lib/search/hierarchical-summaries.js.map +1 -0
- package/dist/lib/search/hyde.d.ts +27 -0
- package/dist/lib/search/hyde.d.ts.map +1 -0
- package/dist/lib/search/hyde.js +141 -0
- package/dist/lib/search/hyde.js.map +1 -0
- package/dist/lib/search/late-chunking.d.ts +53 -0
- package/dist/lib/search/late-chunking.d.ts.map +1 -0
- package/dist/lib/search/late-chunking.js +230 -0
- package/dist/lib/search/late-chunking.js.map +1 -0
- package/dist/lib/search/ppr-retrieval.d.ts +49 -0
- package/dist/lib/search/ppr-retrieval.d.ts.map +1 -0
- package/dist/lib/search/ppr-retrieval.js +135 -0
- package/dist/lib/search/ppr-retrieval.js.map +1 -0
- package/dist/lib/search/repo-map.d.ts +43 -0
- package/dist/lib/search/repo-map.d.ts.map +1 -0
- package/dist/lib/search/repo-map.js +165 -0
- package/dist/lib/search/repo-map.js.map +1 -0
- package/dist/lib/session-analyzer.d.ts +90 -0
- package/dist/lib/session-analyzer.d.ts.map +1 -0
- package/dist/lib/session-analyzer.js +467 -0
- package/dist/lib/session-analyzer.js.map +1 -0
- package/dist/lib/session-observations.d.ts.map +1 -1
- package/dist/lib/session-observations.js +13 -3
- package/dist/lib/session-observations.js.map +1 -1
- package/dist/lib/session-summary.d.ts.map +1 -1
- package/dist/lib/session-summary.js +57 -50
- package/dist/lib/session-summary.js.map +1 -1
- package/dist/lib/session-surgeon.d.ts +53 -0
- package/dist/lib/session-surgeon.d.ts.map +1 -0
- package/dist/lib/session-surgeon.js +501 -0
- package/dist/lib/session-surgeon.js.map +1 -0
- package/dist/lib/similarity-utils.d.ts +26 -0
- package/dist/lib/similarity-utils.d.ts.map +1 -0
- package/dist/lib/similarity-utils.js +66 -0
- package/dist/lib/similarity-utils.js.map +1 -0
- package/dist/lib/skills.d.ts.map +1 -1
- package/dist/lib/skills.js +11 -11
- package/dist/lib/skills.js.map +1 -1
- package/dist/lib/storage/backends/interface.d.ts +13 -3
- package/dist/lib/storage/backends/interface.d.ts.map +1 -1
- package/dist/lib/storage/backends/postgresql.d.ts +52 -3
- package/dist/lib/storage/backends/postgresql.d.ts.map +1 -1
- package/dist/lib/storage/backends/postgresql.js +694 -49
- package/dist/lib/storage/backends/postgresql.js.map +1 -1
- package/dist/lib/storage/benchmark.js +2 -2
- package/dist/lib/storage/benchmark.js.map +1 -1
- package/dist/lib/storage/dispatcher/base.d.ts +114 -0
- package/dist/lib/storage/dispatcher/base.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/base.js +160 -0
- package/dist/lib/storage/dispatcher/base.js.map +1 -0
- package/dist/lib/storage/dispatcher/documents.d.ts +25 -0
- package/dist/lib/storage/dispatcher/documents.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/documents.js +194 -0
- package/dist/lib/storage/dispatcher/documents.js.map +1 -0
- package/dist/lib/storage/dispatcher/embeddings.d.ts +34 -0
- package/dist/lib/storage/dispatcher/embeddings.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/embeddings.js +144 -0
- package/dist/lib/storage/dispatcher/embeddings.js.map +1 -0
- package/dist/lib/storage/dispatcher/export-import.d.ts +139 -0
- package/dist/lib/storage/dispatcher/export-import.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/export-import.js +191 -0
- package/dist/lib/storage/dispatcher/export-import.js.map +1 -0
- package/dist/lib/storage/dispatcher/file-hashes.d.ts +13 -0
- package/dist/lib/storage/dispatcher/file-hashes.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/file-hashes.js +36 -0
- package/dist/lib/storage/dispatcher/file-hashes.js.map +1 -0
- package/dist/lib/storage/dispatcher/global-memories.d.ts +28 -0
- package/dist/lib/storage/dispatcher/global-memories.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/global-memories.js +151 -0
- package/dist/lib/storage/dispatcher/global-memories.js.map +1 -0
- package/dist/lib/storage/dispatcher/graph.d.ts +32 -0
- package/dist/lib/storage/dispatcher/graph.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/graph.js +146 -0
- package/dist/lib/storage/dispatcher/graph.js.map +1 -0
- package/dist/lib/storage/dispatcher/index.d.ts +34 -0
- package/dist/lib/storage/dispatcher/index.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/index.js +139 -0
- package/dist/lib/storage/dispatcher/index.js.map +1 -0
- package/dist/lib/storage/dispatcher/memories.d.ts +65 -0
- package/dist/lib/storage/dispatcher/memories.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/memories.js +466 -0
- package/dist/lib/storage/dispatcher/memories.js.map +1 -0
- package/dist/lib/storage/dispatcher/mixin-helper.d.ts +6 -0
- package/dist/lib/storage/dispatcher/mixin-helper.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/mixin-helper.js +10 -0
- package/dist/lib/storage/dispatcher/mixin-helper.js.map +1 -0
- package/dist/lib/storage/dispatcher/retention.d.ts +20 -0
- package/dist/lib/storage/dispatcher/retention.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/retention.js +123 -0
- package/dist/lib/storage/dispatcher/retention.js.map +1 -0
- package/dist/lib/storage/dispatcher/search.d.ts +34 -0
- package/dist/lib/storage/dispatcher/search.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/search.js +222 -0
- package/dist/lib/storage/dispatcher/search.js.map +1 -0
- package/dist/lib/storage/dispatcher/skills.d.ts +53 -0
- package/dist/lib/storage/dispatcher/skills.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/skills.js +98 -0
- package/dist/lib/storage/dispatcher/skills.js.map +1 -0
- package/dist/lib/storage/dispatcher/token-stats.d.ts +23 -0
- package/dist/lib/storage/dispatcher/token-stats.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/token-stats.js +92 -0
- package/dist/lib/storage/dispatcher/token-stats.js.map +1 -0
- package/dist/lib/storage/dispatcher/web-search.d.ts +10 -0
- package/dist/lib/storage/dispatcher/web-search.d.ts.map +1 -0
- package/dist/lib/storage/dispatcher/web-search.js +39 -0
- package/dist/lib/storage/dispatcher/web-search.js.map +1 -0
- package/dist/lib/storage/dispatcher-export.d.ts.map +1 -1
- package/dist/lib/storage/dispatcher-export.js +48 -39
- package/dist/lib/storage/dispatcher-export.js.map +1 -1
- package/dist/lib/storage/dispatcher.d.ts +1 -468
- package/dist/lib/storage/dispatcher.d.ts.map +1 -1
- package/dist/lib/storage/dispatcher.js +1 -1931
- package/dist/lib/storage/dispatcher.js.map +1 -1
- package/dist/lib/storage/index.d.ts +20 -5
- package/dist/lib/storage/index.d.ts.map +1 -1
- package/dist/lib/storage/index.js +36 -7
- package/dist/lib/storage/index.js.map +1 -1
- package/dist/lib/storage/migration/export-import.d.ts.map +1 -1
- package/dist/lib/storage/migration/export-import.js +9 -2
- package/dist/lib/storage/migration/export-import.js.map +1 -1
- package/dist/lib/storage/types.d.ts +152 -10
- package/dist/lib/storage/types.d.ts.map +1 -1
- package/dist/lib/storage/types.js +13 -0
- package/dist/lib/storage/types.js.map +1 -1
- package/dist/lib/storage/vector/interface.d.ts +4 -0
- package/dist/lib/storage/vector/interface.d.ts.map +1 -1
- package/dist/lib/storage/vector/qdrant.d.ts +13 -2
- package/dist/lib/storage/vector/qdrant.d.ts.map +1 -1
- package/dist/lib/storage/vector/qdrant.js +147 -61
- package/dist/lib/storage/vector/qdrant.js.map +1 -1
- package/dist/lib/token-budget.d.ts.map +1 -1
- package/dist/lib/token-budget.js +9 -2
- package/dist/lib/token-budget.js.map +1 -1
- package/dist/lib/transcript-utils.d.ts +60 -0
- package/dist/lib/transcript-utils.d.ts.map +1 -0
- package/dist/lib/transcript-utils.js +69 -0
- package/dist/lib/transcript-utils.js.map +1 -0
- package/dist/lib/tree-sitter/extractor.d.ts +1 -1
- package/dist/lib/tree-sitter/extractor.d.ts.map +1 -1
- package/dist/lib/tree-sitter/extractor.js +34 -9
- package/dist/lib/tree-sitter/extractor.js.map +1 -1
- package/dist/lib/tree-sitter/parser.d.ts.map +1 -1
- package/dist/lib/tree-sitter/parser.js +45 -11
- package/dist/lib/tree-sitter/parser.js.map +1 -1
- package/dist/lib/tree-sitter/public.d.ts +12 -0
- package/dist/lib/tree-sitter/public.d.ts.map +1 -1
- package/dist/lib/tree-sitter/public.js +33 -1
- package/dist/lib/tree-sitter/public.js.map +1 -1
- package/dist/lib/tree-sitter/queries.d.ts.map +1 -1
- package/dist/lib/tree-sitter/queries.js +8 -0
- package/dist/lib/tree-sitter/queries.js.map +1 -1
- package/dist/lib/working-memory-pipeline.d.ts.map +1 -1
- package/dist/lib/working-memory-pipeline.js +12 -3
- package/dist/lib/working-memory-pipeline.js.map +1 -1
- package/dist/lib/worktree-detect.d.ts +43 -0
- package/dist/lib/worktree-detect.d.ts.map +1 -0
- package/dist/lib/worktree-detect.js +154 -0
- package/dist/lib/worktree-detect.js.map +1 -0
- package/dist/lsp/client.d.ts +96 -0
- package/dist/lsp/client.d.ts.map +1 -0
- package/dist/lsp/client.js +435 -0
- package/dist/lsp/client.js.map +1 -0
- package/dist/lsp/installer.d.ts +39 -0
- package/dist/lsp/installer.d.ts.map +1 -0
- package/dist/lsp/installer.js +275 -0
- package/dist/lsp/installer.js.map +1 -0
- package/dist/lsp/manager.d.ts +62 -0
- package/dist/lsp/manager.d.ts.map +1 -0
- package/dist/lsp/manager.js +234 -0
- package/dist/lsp/manager.js.map +1 -0
- package/dist/lsp/servers.d.ts +52 -0
- package/dist/lsp/servers.d.ts.map +1 -0
- package/dist/lsp/servers.js +162 -0
- package/dist/lsp/servers.js.map +1 -0
- package/dist/mcp/helpers.d.ts.map +1 -1
- package/dist/mcp/helpers.js +8 -2
- package/dist/mcp/helpers.js.map +1 -1
- package/dist/mcp/profile.js +1 -1
- package/dist/mcp/server.d.ts +3 -2
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +19 -7
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/config.d.ts.map +1 -1
- package/dist/mcp/tools/config.js +28 -118
- package/dist/mcp/tools/config.js.map +1 -1
- package/dist/mcp/tools/dead-end.d.ts.map +1 -1
- package/dist/mcp/tools/dead-end.js +4 -3
- package/dist/mcp/tools/dead-end.js.map +1 -1
- package/dist/mcp/tools/debug.d.ts.map +1 -1
- package/dist/mcp/tools/debug.js +27 -112
- package/dist/mcp/tools/debug.js.map +1 -1
- package/dist/mcp/tools/graph.d.ts.map +1 -1
- package/dist/mcp/tools/graph.js +164 -176
- package/dist/mcp/tools/graph.js.map +1 -1
- package/dist/mcp/tools/indexing.d.ts +1 -1
- package/dist/mcp/tools/indexing.d.ts.map +1 -1
- package/dist/mcp/tools/indexing.js +63 -164
- package/dist/mcp/tools/indexing.js.map +1 -1
- package/dist/mcp/tools/memory/forget.d.ts +3 -0
- package/dist/mcp/tools/memory/forget.d.ts.map +1 -0
- package/dist/mcp/tools/memory/forget.js +175 -0
- package/dist/mcp/tools/memory/forget.js.map +1 -0
- package/dist/mcp/tools/memory/memory-helpers.d.ts +45 -0
- package/dist/mcp/tools/memory/memory-helpers.d.ts.map +1 -0
- package/dist/mcp/tools/memory/memory-helpers.js +291 -0
- package/dist/mcp/tools/memory/memory-helpers.js.map +1 -0
- package/dist/mcp/tools/memory/recall.d.ts +3 -0
- package/dist/mcp/tools/memory/recall.d.ts.map +1 -0
- package/dist/mcp/tools/memory/recall.js +495 -0
- package/dist/mcp/tools/memory/recall.js.map +1 -0
- package/dist/mcp/tools/memory/remember.d.ts +3 -0
- package/dist/mcp/tools/memory/remember.d.ts.map +1 -0
- package/dist/mcp/tools/memory/remember.js +256 -0
- package/dist/mcp/tools/memory/remember.js.map +1 -0
- package/dist/mcp/tools/memory/temporal-query.d.ts +8 -0
- package/dist/mcp/tools/memory/temporal-query.d.ts.map +1 -0
- package/dist/mcp/tools/memory/temporal-query.js +68 -0
- package/dist/mcp/tools/memory/temporal-query.js.map +1 -0
- package/dist/mcp/tools/memory.d.ts +0 -11
- package/dist/mcp/tools/memory.d.ts.map +1 -1
- package/dist/mcp/tools/memory.js +6 -1228
- package/dist/mcp/tools/memory.js.map +1 -1
- package/dist/mcp/tools/prd.d.ts.map +1 -1
- package/dist/mcp/tools/prd.js +19 -70
- package/dist/mcp/tools/prd.js.map +1 -1
- package/dist/mcp/tools/review.d.ts +8 -0
- package/dist/mcp/tools/review.d.ts.map +1 -0
- package/dist/mcp/tools/review.js +133 -0
- package/dist/mcp/tools/review.js.map +1 -0
- package/dist/mcp/tools/search.d.ts.map +1 -1
- package/dist/mcp/tools/search.js +79 -8
- package/dist/mcp/tools/search.js.map +1 -1
- package/dist/mcp/tools/status.d.ts.map +1 -1
- package/dist/mcp/tools/status.js +34 -75
- package/dist/mcp/tools/status.js.map +1 -1
- package/dist/mcp/tools/web-fetch.d.ts.map +1 -1
- package/dist/mcp/tools/web-fetch.js +5 -1
- package/dist/mcp/tools/web-fetch.js.map +1 -1
- package/dist/mcp/tools/web-search.d.ts.map +1 -1
- package/dist/mcp/tools/web-search.js +25 -103
- package/dist/mcp/tools/web-search.js.map +1 -1
- package/dist/prompts/guardrails.d.ts +14 -0
- package/dist/prompts/guardrails.d.ts.map +1 -0
- package/dist/prompts/guardrails.js +115 -0
- package/dist/prompts/guardrails.js.map +1 -0
- package/dist/prompts/index.d.ts +2 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +3 -1
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/prd.d.ts +0 -2
- package/dist/prompts/prd.d.ts.map +1 -1
- package/dist/prompts/prd.js +0 -2
- package/dist/prompts/prd.js.map +1 -1
- package/hooks/core/__tests__/adapter.test.cjs +340 -0
- package/hooks/core/adapter.cjs +463 -0
- package/hooks/core/config.cjs +83 -0
- package/hooks/core/daemon-boot.cjs +140 -0
- package/hooks/core/log.cjs +41 -0
- package/hooks/core/worktree.cjs +119 -0
- package/hooks/succ-post-tool.cjs +198 -134
- package/hooks/succ-pre-compact.cjs +262 -0
- package/hooks/succ-pre-tool.cjs +526 -182
- package/hooks/succ-session-end.cjs +40 -64
- package/hooks/succ-session-start.cjs +484 -430
- package/hooks/succ-stop-reflection.cjs +36 -62
- package/hooks/succ-user-prompt.cjs +137 -180
- package/package.json +17 -6
|
@@ -17,96 +17,43 @@
|
|
|
17
17
|
* - Knowledge base stats
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
const { execFileSync, spawn } = require('child_process');
|
|
21
20
|
const fs = require('fs');
|
|
22
21
|
const path = require('path');
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
const adapter = require('./core/adapter.cjs');
|
|
23
|
+
const { ensureDaemon } = require('./core/daemon-boot.cjs');
|
|
24
|
+
const { log: _log } = require('./core/log.cjs');
|
|
25
|
+
const { loadMergedConfig } = require('./core/config.cjs');
|
|
26
|
+
|
|
27
|
+
adapter.runHook('session-start', async ({ agent, hookInput, projectDir, succDir }) => {
|
|
28
|
+
const log = (msg) => _log(succDir, 'session-start', msg);
|
|
29
|
+
|
|
30
|
+
// Load merged config (global defaults, project overrides)
|
|
31
|
+
const config = loadMergedConfig(projectDir);
|
|
32
|
+
let includeCoAuthoredBy = config.includeCoAuthoredBy !== false;
|
|
33
|
+
let communicationAutoAdapt = config.communicationAutoAdapt !== false;
|
|
34
|
+
let communicationTrackHistory = config.communicationTrackHistory === true;
|
|
35
|
+
let hasOpenRouterKey = !!process.env.OPENROUTER_API_KEY;
|
|
36
|
+
if (!hasOpenRouterKey) {
|
|
37
|
+
const keys = [config.llm?.api_key, config.llm?.embeddings?.api_key, config.web_search?.api_key];
|
|
38
|
+
if (keys.some((k) => typeof k === 'string' && k.startsWith('sk-or-'))) {
|
|
39
|
+
hasOpenRouterKey = true;
|
|
31
40
|
}
|
|
32
|
-
const logFile = path.join(tmpDir, 'hooks.log');
|
|
33
|
-
const timestamp = new Date().toISOString();
|
|
34
|
-
fs.appendFileSync(logFile, `[${timestamp}] [session-start] ${message}\n`);
|
|
35
|
-
} catch {
|
|
36
|
-
// Logging failed, not critical
|
|
37
41
|
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
let input = '';
|
|
41
|
-
process.stdin.setEncoding('utf8');
|
|
42
|
-
process.stdin.on('readable', () => {
|
|
43
|
-
let chunk;
|
|
44
|
-
while ((chunk = process.stdin.read()) !== null) {
|
|
45
|
-
input += chunk;
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
process.stdin.on('end', async () => {
|
|
50
|
-
try {
|
|
51
|
-
const hookInput = JSON.parse(input);
|
|
52
|
-
let projectDir = hookInput.cwd || process.cwd();
|
|
53
|
-
|
|
54
|
-
// Windows path fix
|
|
55
|
-
if (process.platform === 'win32' && /^\/[a-z]\//.test(projectDir)) {
|
|
56
|
-
projectDir = projectDir[1].toUpperCase() + ':' + projectDir.slice(2);
|
|
57
|
-
}
|
|
58
42
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// Skip if succ is not initialized in this project
|
|
62
|
-
if (!fs.existsSync(succDir)) {
|
|
63
|
-
process.exit(0);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Load config settings (project config overrides global, but both are checked)
|
|
67
|
-
let includeCoAuthoredBy = true; // default: true
|
|
68
|
-
let communicationAutoAdapt = true; // default: true
|
|
69
|
-
let communicationTrackHistory = false; // default: false
|
|
70
|
-
let hasOpenRouterKey = !!process.env.OPENROUTER_API_KEY;
|
|
71
|
-
const configPaths = [
|
|
72
|
-
// Global first, then project overrides
|
|
73
|
-
path.join(require('os').homedir(), '.succ', 'config.json'),
|
|
74
|
-
path.join(succDir, 'config.json'),
|
|
75
|
-
];
|
|
76
|
-
for (const configPath of configPaths) {
|
|
77
|
-
if (fs.existsSync(configPath)) {
|
|
78
|
-
try {
|
|
79
|
-
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
80
|
-
if (config.includeCoAuthoredBy === false) {
|
|
81
|
-
includeCoAuthoredBy = false;
|
|
82
|
-
}
|
|
83
|
-
if (config.communicationAutoAdapt === false) {
|
|
84
|
-
communicationAutoAdapt = false;
|
|
85
|
-
}
|
|
86
|
-
if (config.communicationTrackHistory === true) {
|
|
87
|
-
communicationTrackHistory = true;
|
|
88
|
-
}
|
|
89
|
-
// Check for OpenRouter API key: llm.api_key, llm.embeddings.api_key, or web_search.api_key
|
|
90
|
-
if (!hasOpenRouterKey) {
|
|
91
|
-
const keys = [config.llm?.api_key, config.llm?.embeddings?.api_key, config.web_search?.api_key];
|
|
92
|
-
if (keys.some(k => typeof k === 'string' && k.startsWith('sk-or-'))) {
|
|
93
|
-
hasOpenRouterKey = true;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// No break — merge both configs (global defaults, project overrides)
|
|
97
|
-
} catch {
|
|
98
|
-
// Ignore parse errors
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
43
|
+
const contextParts = [];
|
|
44
|
+
const projectName = path.basename(projectDir);
|
|
102
45
|
|
|
103
|
-
|
|
104
|
-
const projectName = path.basename(projectDir);
|
|
46
|
+
// Git Context removed - Claude Code provides native git integration
|
|
105
47
|
|
|
106
|
-
|
|
48
|
+
// Canonical session identifiers — derived once, used consistently throughout
|
|
49
|
+
// canonicalSessionId matches pre-compact hook's derivation (session_id-based)
|
|
50
|
+
const transcriptPath = hookInput.transcript_path || '';
|
|
51
|
+
const canonicalSessionId = (hookInput.session_id || 'unknown')
|
|
52
|
+
.replace(/[^a-zA-Z0-9_\-]/g, '_')
|
|
53
|
+
.slice(0, 128);
|
|
107
54
|
|
|
108
|
-
|
|
109
|
-
|
|
55
|
+
// succ MCP Tools Reference (hybrid: XML wrapper + markdown examples)
|
|
56
|
+
contextParts.push(`<succ-tools>
|
|
110
57
|
<critical>
|
|
111
58
|
⚠️ ALWAYS pass project_path="${projectDir}" to ALL succ_* tool calls.
|
|
112
59
|
Without it, succ works in global-only mode and can't access project data.
|
|
@@ -210,12 +157,16 @@ Examples:
|
|
|
210
157
|
**succ_prd** action="export" [prd_id="prd_xxx"] — Obsidian Mermaid export
|
|
211
158
|
</prd>
|
|
212
159
|
|
|
213
|
-
${
|
|
160
|
+
${
|
|
161
|
+
hasOpenRouterKey
|
|
162
|
+
? `<web-search hint="Perplexity Sonar via OpenRouter.">
|
|
214
163
|
**succ_web** action="quick" query="..." — cheap & fast, simple facts
|
|
215
164
|
**succ_web** action="search" query="..." [model="perplexity/sonar-pro"] — quality search, complex queries
|
|
216
165
|
**succ_web** action="deep" query="..." — multi-step research (30-120s, 30+ sources)
|
|
217
166
|
**succ_web** action="history" [tool_name="..."] [limit=20] — past searches and costs
|
|
218
|
-
</web-search>`
|
|
167
|
+
</web-search>`
|
|
168
|
+
: ''
|
|
169
|
+
}
|
|
219
170
|
|
|
220
171
|
<debug hint="Structured debugging with hypothesis testing. Sessions in .succ/debugs/.">
|
|
221
172
|
**succ_debug** action="create|hypothesis|instrument|result|resolve|abandon|status|list|log|show_log|detect_lang|gen_log"
|
|
@@ -223,8 +174,8 @@ ${hasOpenRouterKey ? `<web-search hint="Perplexity Sonar via OpenRouter.">
|
|
|
223
174
|
</debug>
|
|
224
175
|
</succ-tools>`);
|
|
225
176
|
|
|
226
|
-
|
|
227
|
-
|
|
177
|
+
// succ Agents Reference - reminds AI about available subagents
|
|
178
|
+
contextParts.push(`<succ-agents hint="Use Task tool with subagent_type to launch these. All have semantic search + memories + brain vault.">
|
|
228
179
|
|
|
229
180
|
**MANDATORY: Use succ agents instead of built-in agents.**
|
|
230
181
|
| Task | Use (succ) | NEVER use (built-in) |
|
|
@@ -234,8 +185,12 @@ ${hasOpenRouterKey ? `<web-search hint="Perplexity Sonar via OpenRouter.">
|
|
|
234
185
|
| Multi-step tasks, research | succ-general | general-purpose agent |
|
|
235
186
|
| Code review | succ-code-reviewer | built-in review |
|
|
236
187
|
| Pre-commit review | succ-diff-reviewer | manual diff reading |
|
|
237
|
-
| Web page fetch | succ_fetch | WebFetch |${
|
|
238
|
-
|
|
188
|
+
| Web page fetch | succ_fetch | WebFetch |${
|
|
189
|
+
hasOpenRouterKey
|
|
190
|
+
? `
|
|
191
|
+
| Web search | succ_web(action="quick") / succ_web(action="search") | WebSearch / Brave |`
|
|
192
|
+
: ''
|
|
193
|
+
}
|
|
239
194
|
|
|
240
195
|
Direct file reads (Read/Grep) are fine when you know the exact path — for discovery, always succ agents.
|
|
241
196
|
|
|
@@ -249,401 +204,500 @@ Direct file reads (Read/Grep) are fine when you know the exact path — for disc
|
|
|
249
204
|
| succ-pattern-detective | After multiple bug fixes — surfaces recurring patterns |
|
|
250
205
|
</succ-agents>`);
|
|
251
206
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
207
|
+
// Commit Guidelines (strict order) - only if includeCoAuthoredBy is enabled
|
|
208
|
+
if (includeCoAuthoredBy) {
|
|
209
|
+
contextParts.push(`<commit-format>
|
|
210
|
+
RULE: Every commit footer MUST end with the succ lines. Other tools may appear before succ but succ is always LAST.
|
|
211
|
+
|
|
212
|
+
TEMPLATE — copy the relevant lines exactly:
|
|
213
|
+
Generated with [Claude Code](https://claude.ai/code)
|
|
214
|
+
powered by [succ](https://succ.ai)
|
|
215
|
+
|
|
216
|
+
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
217
|
+
Co-Authored-By: succ <mindpalace@succ.ai>
|
|
218
|
+
|
|
219
|
+
Other tools (Happy, Cursor, etc.) may add their own "via [Tool]" and "Co-Authored-By: Tool" lines.
|
|
220
|
+
Place them BEFORE the succ lines. The only hard rule: succ is always the last footer line and last Co-Authored-By.
|
|
264
221
|
</commit-format>`);
|
|
265
|
-
|
|
222
|
+
}
|
|
266
223
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
// Inject vault tracking hint if enabled (agent handles the actual work)
|
|
287
|
-
if (communicationTrackHistory && communicationAutoAdapt) {
|
|
288
|
-
soulContent += `\n\n### Vault Tracking\n\ncommunicationTrackHistory is enabled. The succ-style-tracker agent will create brain vault entries in .succ/brain/communication/ when updating preferences.`;
|
|
289
|
-
}
|
|
290
|
-
contextParts.push('<soul>\n' + soulContent + '\n</soul>');
|
|
224
|
+
// Pre-commit review + commit guidelines are now handled by PreToolUse hook (succ-pre-tool.cjs)
|
|
225
|
+
// They inject context at the exact moment of git commit, not at session start
|
|
226
|
+
|
|
227
|
+
// Soul Document
|
|
228
|
+
const soulPaths = [
|
|
229
|
+
path.join(succDir, 'soul.md'),
|
|
230
|
+
path.join(succDir, 'SOUL.md'),
|
|
231
|
+
path.join(projectDir, 'soul.md'),
|
|
232
|
+
path.join(projectDir, 'SOUL.md'),
|
|
233
|
+
];
|
|
234
|
+
|
|
235
|
+
for (const soulPath of soulPaths) {
|
|
236
|
+
if (fs.existsSync(soulPath)) {
|
|
237
|
+
let soulContent = fs.readFileSync(soulPath, 'utf8').trim();
|
|
238
|
+
if (soulContent) {
|
|
239
|
+
// Strip Adaptation rules if auto-adapt is disabled
|
|
240
|
+
if (!communicationAutoAdapt) {
|
|
241
|
+
soulContent = soulContent.replace(/### Adaptation[\s\S]*?(?=\n## |\n---|\s*$)/, '');
|
|
291
242
|
}
|
|
292
|
-
|
|
243
|
+
// Inject vault tracking hint if enabled (agent handles the actual work)
|
|
244
|
+
if (communicationTrackHistory && communicationAutoAdapt) {
|
|
245
|
+
soulContent += `\n\n### Vault Tracking\n\ncommunicationTrackHistory is enabled. The succ-style-tracker agent will create brain vault entries in .succ/brain/communication/ when updating preferences.`;
|
|
246
|
+
}
|
|
247
|
+
contextParts.push('<soul>\n' + soulContent + '\n</soul>');
|
|
293
248
|
}
|
|
249
|
+
break;
|
|
294
250
|
}
|
|
251
|
+
}
|
|
295
252
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
253
|
+
// Architecture / Brain Vault — inline overview + categorized doc index
|
|
254
|
+
const brainDir = path.join(succDir, 'brain');
|
|
255
|
+
if (fs.existsSync(brainDir)) {
|
|
256
|
+
try {
|
|
257
|
+
const archParts = [];
|
|
258
|
+
|
|
259
|
+
// Phase 1: Find and inline Architecture Overview (compact extract)
|
|
260
|
+
const knowledgeDir = path.join(brainDir, 'knowledge');
|
|
261
|
+
if (fs.existsSync(knowledgeDir)) {
|
|
262
|
+
const archFiles = fs
|
|
263
|
+
.readdirSync(knowledgeDir)
|
|
264
|
+
.filter((f) => /architect/i.test(f) && f.endsWith('.md'))
|
|
265
|
+
.sort(); // 00_Architecture.md first
|
|
266
|
+
if (archFiles.length > 0) {
|
|
267
|
+
const archContent = fs.readFileSync(path.join(knowledgeDir, archFiles[0]), 'utf8');
|
|
268
|
+
// Strip frontmatter
|
|
269
|
+
const body = archContent.replace(/^---[\s\S]*?\n---\s*\n/, '');
|
|
270
|
+
// Extract from start to second "---" or "## Tech Stack" — whichever comes first
|
|
271
|
+
// This gives us Overview + Core Mission (~15-20 lines)
|
|
272
|
+
const overviewEnd = body.search(/\n---\n|\n## Tech Stack|\n## Directory/);
|
|
273
|
+
const overview =
|
|
274
|
+
overviewEnd > 0 ? body.slice(0, overviewEnd).trim() : body.slice(0, 1500).trim();
|
|
275
|
+
if (overview) {
|
|
276
|
+
archParts.push(overview);
|
|
319
277
|
}
|
|
320
278
|
}
|
|
279
|
+
}
|
|
321
280
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
281
|
+
// Phase 2: Collect remaining docs grouped by category
|
|
282
|
+
const scanDirs = [
|
|
283
|
+
{ dir: 'knowledge', label: 'Knowledge & Research' },
|
|
284
|
+
{ dir: 'project', label: 'Project' },
|
|
285
|
+
];
|
|
286
|
+
const docGroups = {};
|
|
287
|
+
|
|
288
|
+
for (const { dir, label } of scanDirs) {
|
|
289
|
+
const fullDir = path.join(brainDir, dir);
|
|
290
|
+
if (!fs.existsSync(fullDir)) continue;
|
|
291
|
+
|
|
292
|
+
const files = fs.readdirSync(fullDir, { withFileTypes: true });
|
|
293
|
+
for (const entry of files) {
|
|
294
|
+
if (entry.isDirectory()) continue;
|
|
295
|
+
if (!entry.name.endsWith('.md')) continue;
|
|
296
|
+
|
|
297
|
+
const filePath = path.join(fullDir, entry.name);
|
|
298
|
+
const stat = fs.statSync(filePath);
|
|
299
|
+
if (stat.size < 2048) continue;
|
|
300
|
+
// Skip architecture files (already inlined above)
|
|
301
|
+
if (/architect/i.test(entry.name)) continue;
|
|
302
|
+
|
|
303
|
+
// Read first 500 bytes for frontmatter/H1
|
|
304
|
+
const fd = fs.openSync(filePath, 'r');
|
|
305
|
+
const buf = Buffer.alloc(500);
|
|
306
|
+
fs.readSync(fd, buf, 0, 500, 0);
|
|
307
|
+
fs.closeSync(fd);
|
|
308
|
+
const head = buf.toString('utf8');
|
|
309
|
+
|
|
310
|
+
let description = '';
|
|
311
|
+
const fmMatch = head.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
312
|
+
if (fmMatch) {
|
|
313
|
+
const descMatch = fmMatch[1].match(/description:\s*["']?([^"'\n]+)/);
|
|
314
|
+
if (descMatch) description = descMatch[1].trim();
|
|
315
|
+
}
|
|
316
|
+
if (!description) {
|
|
317
|
+
const h1Match = head.match(/^#\s+(.+)/m);
|
|
318
|
+
if (h1Match) description = h1Match[1].trim();
|
|
319
|
+
}
|
|
361
320
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
321
|
+
if (description) {
|
|
322
|
+
if (!docGroups[label]) docGroups[label] = [];
|
|
323
|
+
docGroups[label].push(`${entry.name}: ${description}`);
|
|
366
324
|
}
|
|
367
325
|
}
|
|
326
|
+
}
|
|
368
327
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
328
|
+
// Phase 3: Format grouped docs
|
|
329
|
+
const groupLines = [];
|
|
330
|
+
for (const [label, docs] of Object.entries(docGroups)) {
|
|
331
|
+
groupLines.push(`**${label}:** ${docs.join(' | ')}`);
|
|
332
|
+
}
|
|
333
|
+
if (groupLines.length > 0) {
|
|
334
|
+
archParts.push(groupLines.join('\n'));
|
|
335
|
+
}
|
|
377
336
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
// Brain vault scan failed, not critical
|
|
337
|
+
if (archParts.length > 0) {
|
|
338
|
+
contextParts.push(
|
|
339
|
+
`<architecture hint="Use succ_search to read full docs">\n${archParts.join('\n\n')}\n</architecture>`
|
|
340
|
+
);
|
|
383
341
|
}
|
|
342
|
+
} catch {
|
|
343
|
+
// intentionally empty — brain vault scan failed, not critical
|
|
384
344
|
}
|
|
345
|
+
}
|
|
385
346
|
|
|
386
|
-
|
|
387
|
-
|
|
347
|
+
// Check if this is a compact event (after /compact)
|
|
348
|
+
const isCompactEvent = hookInput.source === 'compact';
|
|
388
349
|
|
|
389
|
-
|
|
350
|
+
log(
|
|
351
|
+
`source=${hookInput.source}, isCompact=${isCompactEvent}, session=${hookInput.session_id || 'unknown'}`
|
|
352
|
+
);
|
|
390
353
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
} catch {
|
|
419
|
-
// Cleanup failed, not critical
|
|
354
|
+
// Precomputed Context from previous session (only on fresh start, not compact)
|
|
355
|
+
if (!isCompactEvent) {
|
|
356
|
+
const precomputedContextPath = path.join(succDir, 'next-session-context.md');
|
|
357
|
+
if (fs.existsSync(precomputedContextPath)) {
|
|
358
|
+
try {
|
|
359
|
+
const precomputedContent = fs.readFileSync(precomputedContextPath, 'utf8').trim();
|
|
360
|
+
if (precomputedContent) {
|
|
361
|
+
contextParts.push('<previous-session>\n' + precomputedContent + '\n</previous-session>');
|
|
362
|
+
|
|
363
|
+
// Archive the file after loading
|
|
364
|
+
const archiveDir = path.join(succDir, '.context-archive');
|
|
365
|
+
if (!fs.existsSync(archiveDir)) {
|
|
366
|
+
fs.mkdirSync(archiveDir, { recursive: true });
|
|
367
|
+
}
|
|
368
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
369
|
+
const archivePath = path.join(archiveDir, `context-${timestamp}.md`);
|
|
370
|
+
fs.renameSync(precomputedContextPath, archivePath);
|
|
371
|
+
|
|
372
|
+
// Cleanup old archives (keep last 10)
|
|
373
|
+
try {
|
|
374
|
+
const archives = fs
|
|
375
|
+
.readdirSync(archiveDir)
|
|
376
|
+
.filter((f) => f.startsWith('context-') && f.endsWith('.md'))
|
|
377
|
+
.sort()
|
|
378
|
+
.reverse();
|
|
379
|
+
for (const oldArchive of archives.slice(10)) {
|
|
380
|
+
fs.unlinkSync(path.join(archiveDir, oldArchive));
|
|
420
381
|
}
|
|
382
|
+
} catch {
|
|
383
|
+
// intentionally empty — cleanup failed, not critical
|
|
421
384
|
}
|
|
422
|
-
} catch {
|
|
423
|
-
// Ignore errors
|
|
424
385
|
}
|
|
386
|
+
} catch {
|
|
387
|
+
// intentionally empty — ignore errors
|
|
425
388
|
}
|
|
426
389
|
}
|
|
390
|
+
}
|
|
427
391
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
392
|
+
// Ensure daemon is running and get port (shared module)
|
|
393
|
+
const { port: daemonPort } = await ensureDaemon(projectDir, log);
|
|
394
|
+
|
|
395
|
+
// Propagate daemon port to Bash environment via CLAUDE_ENV_FILE
|
|
396
|
+
// ensureDaemon already verified the port is alive, so no need to re-check
|
|
397
|
+
if (daemonPort && process.env.CLAUDE_ENV_FILE) {
|
|
398
|
+
try {
|
|
399
|
+
fs.appendFileSync(process.env.CLAUDE_ENV_FILE, `export SUCC_DAEMON_PORT=${daemonPort}\n`);
|
|
400
|
+
log(`Wrote SUCC_DAEMON_PORT=${daemonPort} to CLAUDE_ENV_FILE`);
|
|
401
|
+
} catch (err) {
|
|
402
|
+
log(`Failed to write CLAUDE_ENV_FILE: ${err.message || err}`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
440
405
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
const startDaemon = () => {
|
|
454
|
-
const servicePath = path.join(projectDir, 'dist', 'daemon', 'service.js');
|
|
455
|
-
if (fs.existsSync(servicePath)) {
|
|
456
|
-
const daemon = spawn(process.execPath, ['--no-warnings', '--no-deprecation', servicePath], {
|
|
457
|
-
cwd: projectDir,
|
|
458
|
-
detached: true,
|
|
459
|
-
stdio: 'ignore',
|
|
460
|
-
windowsHide: true,
|
|
461
|
-
env: { ...process.env, NODE_OPTIONS: '' },
|
|
462
|
-
});
|
|
463
|
-
daemon.unref();
|
|
464
|
-
return true;
|
|
465
|
-
}
|
|
466
|
-
return false;
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
// Ensure daemon is running and get port
|
|
470
|
-
let daemonPort = getDaemonPort();
|
|
471
|
-
if (!daemonPort || !(await checkDaemon(daemonPort))) {
|
|
472
|
-
startDaemon();
|
|
473
|
-
// Wait for daemon to start (max 3 seconds)
|
|
474
|
-
for (let i = 0; i < 30; i++) {
|
|
475
|
-
await new Promise(r => setTimeout(r, 100));
|
|
476
|
-
daemonPort = getDaemonPort();
|
|
477
|
-
if (daemonPort && await checkDaemon(daemonPort)) {
|
|
478
|
-
break;
|
|
479
|
-
}
|
|
406
|
+
// Skip for service sessions (reflection subagents)
|
|
407
|
+
const isServiceSession = process.env.SUCC_SERVICE_SESSION === '1';
|
|
408
|
+
|
|
409
|
+
// IMPORTANT: Create compact-pending flag FIRST (before any slow operations)
|
|
410
|
+
// This ensures fallback context is available even if hook times out during briefing
|
|
411
|
+
// Hook timeout is 10s, briefing can take 60s+ → would block flag creation
|
|
412
|
+
if (isCompactEvent && !isServiceSession) {
|
|
413
|
+
const compactPendingFile = path.join(succDir, '.tmp', 'compact-pending');
|
|
414
|
+
try {
|
|
415
|
+
if (!fs.existsSync(path.join(succDir, '.tmp'))) {
|
|
416
|
+
fs.mkdirSync(path.join(succDir, '.tmp'), { recursive: true });
|
|
480
417
|
}
|
|
418
|
+
// Store the full context that should be injected (without briefing, that comes later)
|
|
419
|
+
const contextForFallback = adapter.adaptContext(agent, contextParts.join('\n\n'));
|
|
420
|
+
fs.writeFileSync(compactPendingFile, contextForFallback, 'utf8');
|
|
421
|
+
log(`Created compact-pending flag (${contextForFallback.length} chars)`);
|
|
422
|
+
} catch (err) {
|
|
423
|
+
log(`Failed to create compact-pending: ${err.message || err}`);
|
|
481
424
|
}
|
|
425
|
+
}
|
|
482
426
|
|
|
483
|
-
|
|
484
|
-
|
|
427
|
+
// Read pre-compact stats (saved by succ-pre-compact.cjs hook) and display delta
|
|
428
|
+
if (isCompactEvent && !isServiceSession) {
|
|
429
|
+
const statsFile = path.join(succDir, '.tmp', `pre-compact-stats-${canonicalSessionId}.json`);
|
|
430
|
+
try {
|
|
431
|
+
if (fs.existsSync(statsFile)) {
|
|
432
|
+
const stats = JSON.parse(fs.readFileSync(statsFile, 'utf8'));
|
|
433
|
+
const bt = stats.tokenTotals || {};
|
|
434
|
+
|
|
435
|
+
// Estimate post-compact token count from transcript (if available).
|
|
436
|
+
// null = transcript not available; skip delta display to avoid bogus "100% freed".
|
|
437
|
+
let postTokens = /** @type {number|null} */ (null);
|
|
438
|
+
const postByType = { text: 0, tool_use: 0, tool_result: 0, thinking: 0, image: 0 };
|
|
439
|
+
if (hookInput.transcript_path && fs.existsSync(hookInput.transcript_path)) {
|
|
440
|
+
try {
|
|
441
|
+
const postContent = fs.readFileSync(hookInput.transcript_path, 'utf8');
|
|
442
|
+
let postChars = 0;
|
|
443
|
+
for (const line of postContent.split('\n')) {
|
|
444
|
+
const trimmed = line.trim();
|
|
445
|
+
if (!trimmed) continue;
|
|
446
|
+
try {
|
|
447
|
+
const entry = JSON.parse(trimmed);
|
|
448
|
+
const msgContent = entry.message && entry.message.content;
|
|
449
|
+
if (typeof msgContent === 'string') {
|
|
450
|
+
postChars += msgContent.length;
|
|
451
|
+
postByType.text += msgContent.length;
|
|
452
|
+
} else if (Array.isArray(msgContent)) {
|
|
453
|
+
for (const block of msgContent) {
|
|
454
|
+
if (typeof block === 'string') {
|
|
455
|
+
postChars += block.length;
|
|
456
|
+
postByType.text += block.length;
|
|
457
|
+
} else if (block && block.type === 'text') {
|
|
458
|
+
const len = (block.text || '').length;
|
|
459
|
+
postChars += len;
|
|
460
|
+
postByType.text += len;
|
|
461
|
+
} else if (block && block.type === 'tool_use') {
|
|
462
|
+
const len = (block.input ? JSON.stringify(block.input).length : 0) +
|
|
463
|
+
(block.name || '').length + (block.id || '').length;
|
|
464
|
+
postChars += len;
|
|
465
|
+
postByType.tool_use += len;
|
|
466
|
+
} else if (block && block.type === 'tool_result') {
|
|
467
|
+
const rc = block.content;
|
|
468
|
+
let len = 0;
|
|
469
|
+
if (typeof rc === 'string') len = rc.length;
|
|
470
|
+
else if (Array.isArray(rc)) len = JSON.stringify(rc).length;
|
|
471
|
+
postChars += len;
|
|
472
|
+
postByType.tool_result += len;
|
|
473
|
+
} else if (block && block.type === 'thinking') {
|
|
474
|
+
const len = (block.thinking || '').length;
|
|
475
|
+
postChars += len;
|
|
476
|
+
postByType.thinking += len;
|
|
477
|
+
} else if (block && block.type === 'image') {
|
|
478
|
+
const len = block.source ? JSON.stringify(block.source).length : 100;
|
|
479
|
+
postChars += len;
|
|
480
|
+
postByType.image += len;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
} catch {
|
|
485
|
+
/* skip malformed lines */
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
postTokens = Math.ceil(postChars / 4);
|
|
489
|
+
for (const k of Object.keys(postByType)) {
|
|
490
|
+
postByType[k] = Math.ceil(postByType[k] / 4);
|
|
491
|
+
}
|
|
492
|
+
} catch {
|
|
493
|
+
log('Skipping compact stats delta: failed to analyze post-compact transcript');
|
|
494
|
+
}
|
|
495
|
+
}
|
|
485
496
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
497
|
+
// Only display delta if post-compact tokens were actually measured
|
|
498
|
+
if (postTokens !== null) {
|
|
499
|
+
const beforeTotal = bt.total || 0;
|
|
500
|
+
const freed = beforeTotal - postTokens;
|
|
501
|
+
const pct = beforeTotal > 0 ? ((freed / beforeTotal) * 100).toFixed(1) : '0.0';
|
|
502
|
+
|
|
503
|
+
const fk = (n) => (n >= 1000 ? (n / 1000).toFixed(1) + 'K' : String(n || 0));
|
|
504
|
+
|
|
505
|
+
const statsLines = [];
|
|
506
|
+
statsLines.push(`Compact: ${fk(beforeTotal)} → ${fk(postTokens)} tokens (${pct}% freed)`);
|
|
507
|
+
statsLines.push('');
|
|
508
|
+
statsLines.push(` ${'Type'.padEnd(16)} ${'Before'.padStart(8)} ${'After'.padStart(8)} ${'Freed'.padStart(8)}`);
|
|
509
|
+
statsLines.push(` ${'─'.repeat(16)} ${'─'.repeat(8)} ${'─'.repeat(8)} ${'─'.repeat(8)}`);
|
|
510
|
+
for (const key of ['text', 'tool_use', 'tool_result', 'thinking', 'image']) {
|
|
511
|
+
const val = bt[key] || 0;
|
|
512
|
+
const aVal = postByType[key] || 0;
|
|
513
|
+
const f = val - aVal;
|
|
514
|
+
if (val === 0 && f === 0) continue;
|
|
515
|
+
statsLines.push(` ${key.padEnd(16)} ${fk(val).padStart(8)} ${fk(aVal).padStart(8)} ${fk(f).padStart(8)}`);
|
|
516
|
+
}
|
|
517
|
+
statsLines.push(` ${'─'.repeat(16)} ${'─'.repeat(8)} ${'─'.repeat(8)} ${'─'.repeat(8)}`);
|
|
518
|
+
statsLines.push(
|
|
519
|
+
` ${'TOTAL'.padEnd(16)} ${fk(beforeTotal).padStart(8)} ${fk(postTokens).padStart(8)} ${fk(freed).padStart(8)}`
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
const topTools = (stats.topTools || []).slice(0, 5).filter((t) => t.tokens > 0);
|
|
523
|
+
if (topTools.length > 0) {
|
|
524
|
+
statsLines.push('');
|
|
525
|
+
statsLines.push(' Top tools (pre-compact):');
|
|
526
|
+
statsLines.push(' ' + topTools.map((t) => `${t.name}: ${fk(t.tokens)}`).join(' | '));
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
contextParts.push(`<compact-stats>\n${statsLines.join('\n')}\n</compact-stats>`);
|
|
530
|
+
log(`Compact stats: ${beforeTotal} → ${postTokens} tokens (${pct}% freed)`);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Cleanup stats file
|
|
534
|
+
try {
|
|
535
|
+
fs.unlinkSync(statsFile);
|
|
536
|
+
} catch (e) {
|
|
537
|
+
log(`Failed to cleanup stats file: ${e.message || e}`);
|
|
494
538
|
}
|
|
495
|
-
// Store the full context that should be injected (without briefing, that comes later)
|
|
496
|
-
const contextForFallback = contextParts.join('\n\n');
|
|
497
|
-
fs.writeFileSync(compactPendingFile, contextForFallback, 'utf8');
|
|
498
|
-
log(succDir, `Created compact-pending flag (${contextForFallback.length} chars)`);
|
|
499
|
-
} catch (err) {
|
|
500
|
-
log(succDir, `Failed to create compact-pending: ${err.message || err}`);
|
|
501
539
|
}
|
|
540
|
+
} catch (err) {
|
|
541
|
+
log(`Failed to read compact stats: ${err.message || err}`);
|
|
502
542
|
}
|
|
543
|
+
}
|
|
503
544
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
}
|
|
545
|
+
// Generate compact briefing (slow operation - may timeout)
|
|
546
|
+
// Even if this times out, we have the compact-pending fallback above
|
|
547
|
+
if (isCompactEvent && daemonPort && hookInput.transcript_path && !isServiceSession) {
|
|
548
|
+
log(`Generating compact briefing for ${hookInput.transcript_path}`);
|
|
549
|
+
try {
|
|
550
|
+
const response = await fetch(`http://127.0.0.1:${daemonPort}/api/briefing`, {
|
|
551
|
+
method: 'POST',
|
|
552
|
+
headers: { 'Content-Type': 'application/json' },
|
|
553
|
+
body: JSON.stringify({ transcript_path: hookInput.transcript_path }),
|
|
554
|
+
signal: AbortSignal.timeout(8000), // 8s timeout - must complete before 10s hook timeout
|
|
555
|
+
});
|
|
556
|
+
if (response.ok) {
|
|
557
|
+
const result = await response.json();
|
|
558
|
+
if (result.success && result.briefing) {
|
|
559
|
+
contextParts.push(
|
|
560
|
+
`<session-briefing source="compact">\n${result.briefing}\n</session-briefing>`
|
|
561
|
+
);
|
|
562
|
+
log(`Briefing generated: ${result.briefing.length} chars`);
|
|
523
563
|
} else {
|
|
524
|
-
log(
|
|
564
|
+
log(`Briefing failed: ${result.error || 'no briefing returned'}`);
|
|
525
565
|
}
|
|
526
|
-
}
|
|
527
|
-
log(
|
|
528
|
-
// Briefing generation failed, continue without it
|
|
566
|
+
} else {
|
|
567
|
+
log(`Briefing API error: ${response.status} ${response.statusText}`);
|
|
529
568
|
}
|
|
569
|
+
} catch (err) {
|
|
570
|
+
log(`Briefing exception: ${err.message || err}`);
|
|
571
|
+
// Briefing generation failed, continue without it
|
|
530
572
|
}
|
|
573
|
+
}
|
|
531
574
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
575
|
+
// Pinned + recent memories via daemon API (only on fresh start, compact uses briefing instead)
|
|
576
|
+
if (daemonPort && !isCompactEvent) {
|
|
577
|
+
const pinnedIds = new Set();
|
|
578
|
+
|
|
579
|
+
// Phase 1: Pinned memories (Tier 1 — correction_count >= 2 or is_invariant)
|
|
580
|
+
// Filter: skip observations (noisy subagent reports), limit to top 10 by priority_score
|
|
581
|
+
try {
|
|
582
|
+
const response = await fetch(`http://127.0.0.1:${daemonPort}/api/pinned`, {
|
|
583
|
+
signal: AbortSignal.timeout(3000),
|
|
584
|
+
});
|
|
585
|
+
if (response.ok) {
|
|
586
|
+
const data = await response.json();
|
|
587
|
+
const allPinned = data.results || [];
|
|
588
|
+
// Track ALL pinned IDs for dedup with recent (including filtered-out observations)
|
|
589
|
+
for (const m of allPinned) pinnedIds.add(m.id);
|
|
590
|
+
// Display only non-observation pinned, sorted by priority, top 10
|
|
591
|
+
const displayPinned = allPinned
|
|
592
|
+
.filter((m) => m.type !== 'observation')
|
|
593
|
+
.sort((a, b) => (b.priority_score || 0) - (a.priority_score || 0))
|
|
594
|
+
.slice(0, 10);
|
|
595
|
+
if (displayPinned.length > 0) {
|
|
596
|
+
const lines = displayPinned.map((m) => {
|
|
597
|
+
const preview = m.content.slice(0, 100).replace(/\n/g, ' ');
|
|
598
|
+
const type = m.type || 'obs';
|
|
599
|
+
const reason = m.is_invariant ? 'invariant' : `corrected x${m.correction_count}`;
|
|
600
|
+
return `#${m.id} [${type}] (${reason}) ${preview}${m.content.length > 100 ? '...' : ''}`;
|
|
601
|
+
});
|
|
602
|
+
contextParts.push(
|
|
603
|
+
`<pinned-memories count="${displayPinned.length}" total="${allPinned.length}" hint="Tier 1: always loaded, high confidence">\n${lines.join('\n')}\n</pinned-memories>`
|
|
604
|
+
);
|
|
561
605
|
}
|
|
562
|
-
} catch {
|
|
563
|
-
// pinned memories not available
|
|
564
606
|
}
|
|
607
|
+
} catch {
|
|
608
|
+
// intentionally empty — pinned memories not available
|
|
609
|
+
}
|
|
565
610
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
611
|
+
// Phase 2: Recent memories (excluding pinned to avoid duplication)
|
|
612
|
+
try {
|
|
613
|
+
const response = await fetch(`http://127.0.0.1:${daemonPort}/api/recall`, {
|
|
614
|
+
method: 'POST',
|
|
615
|
+
headers: { 'Content-Type': 'application/json' },
|
|
616
|
+
body: JSON.stringify({ query: '', limit: 5 }),
|
|
617
|
+
signal: AbortSignal.timeout(3000),
|
|
618
|
+
});
|
|
619
|
+
if (response.ok) {
|
|
620
|
+
const data = await response.json();
|
|
621
|
+
const memories = (data.results || []).filter((m) => !pinnedIds.has(m.id));
|
|
622
|
+
if (memories.length > 0) {
|
|
623
|
+
const lines = memories.map((m) => {
|
|
624
|
+
const preview = m.content.slice(0, 50).replace(/\n/g, ' ');
|
|
625
|
+
const type = m.type || 'obs';
|
|
626
|
+
return `#${m.id} [${type}] ${preview}${m.content.length > 50 ? '...' : ''}`;
|
|
627
|
+
});
|
|
628
|
+
contextParts.push(
|
|
629
|
+
`<recent-memories count="${memories.length}" hint="Use succ_recall for details">\n${lines.join('\n')}\n</recent-memories>`
|
|
630
|
+
);
|
|
585
631
|
}
|
|
586
|
-
} catch {
|
|
587
|
-
// memories not available
|
|
588
632
|
}
|
|
633
|
+
} catch {
|
|
634
|
+
// intentionally empty — memories not available
|
|
589
635
|
}
|
|
636
|
+
}
|
|
590
637
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
638
|
+
// Knowledge base stats via daemon API
|
|
639
|
+
if (daemonPort) {
|
|
640
|
+
try {
|
|
641
|
+
const response = await fetch(`http://127.0.0.1:${daemonPort}/api/status`, {
|
|
642
|
+
signal: AbortSignal.timeout(3000),
|
|
643
|
+
});
|
|
644
|
+
if (response.ok) {
|
|
645
|
+
const status = await response.json();
|
|
646
|
+
const docs = status.documents || 0;
|
|
647
|
+
const mems = status.memories || 0;
|
|
648
|
+
const code = status.codeChunks || 0;
|
|
649
|
+
if (docs > 0 || mems > 0 || code > 0) {
|
|
650
|
+
contextParts.push(
|
|
651
|
+
`<knowledge-base docs="${docs}" memories="${mems}" code-chunks="${code}" />`
|
|
652
|
+
);
|
|
605
653
|
}
|
|
606
|
-
} catch {
|
|
607
|
-
// status not available
|
|
608
654
|
}
|
|
655
|
+
} catch {
|
|
656
|
+
// intentionally empty — status not available
|
|
609
657
|
}
|
|
658
|
+
}
|
|
610
659
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
log(
|
|
622
|
-
} else {
|
|
623
|
-
log(succDir, `No context parts to output`);
|
|
660
|
+
// Output context
|
|
661
|
+
if (contextParts.length > 0) {
|
|
662
|
+
// Sanitize closing wrapper tags from dynamic content to prevent XML injection
|
|
663
|
+
// (e.g. a stored memory or soul.md containing literal "</session>" would break the envelope)
|
|
664
|
+
const body = contextParts.join('\n\n').replace(/<\/session>/gi, '</session>');
|
|
665
|
+
let additionalContext = `<session project="${projectName}">\n${body}\n</session>`;
|
|
666
|
+
// Strip Claude-only sections for non-Claude agents
|
|
667
|
+
additionalContext = adapter.adaptContext(agent, additionalContext);
|
|
668
|
+
const { json, exitCode } = adapter.formatOutput(agent, 'SessionStart', { additionalContext });
|
|
669
|
+
if (json && Object.keys(json).length > 0) {
|
|
670
|
+
console.log(JSON.stringify(json));
|
|
624
671
|
}
|
|
672
|
+
log(
|
|
673
|
+
`Output additionalContext: ${additionalContext.length} chars, parts=${contextParts.length}, agent=${agent}`
|
|
674
|
+
);
|
|
675
|
+
if (exitCode) process.exit(exitCode); // non-zero = deny (Cursor/Gemini); 0 falls through to session registration
|
|
676
|
+
} else {
|
|
677
|
+
log(`No context parts to output`);
|
|
678
|
+
}
|
|
625
679
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
}
|
|
640
|
-
|
|
680
|
+
// Register session with daemon
|
|
681
|
+
// transcriptPath and canonicalSessionId derived early — reuse here for consistency
|
|
682
|
+
if (daemonPort) {
|
|
683
|
+
try {
|
|
684
|
+
const res = await fetch(`http://127.0.0.1:${daemonPort}/api/session/register`, {
|
|
685
|
+
method: 'POST',
|
|
686
|
+
headers: { 'Content-Type': 'application/json' },
|
|
687
|
+
body: JSON.stringify({
|
|
688
|
+
session_id: canonicalSessionId,
|
|
689
|
+
transcript_path: transcriptPath,
|
|
690
|
+
is_service: isServiceSession,
|
|
691
|
+
}),
|
|
692
|
+
signal: AbortSignal.timeout(3000),
|
|
693
|
+
});
|
|
694
|
+
if (!res.ok) {
|
|
695
|
+
log(`Session register failed: ${res.status} ${res.statusText} session=${canonicalSessionId}`);
|
|
641
696
|
}
|
|
697
|
+
} catch (err) {
|
|
698
|
+
log(`Session register error for ${canonicalSessionId}: ${err.message || err}`);
|
|
642
699
|
}
|
|
643
|
-
|
|
644
|
-
process.exit(0);
|
|
645
|
-
|
|
646
|
-
} catch (err) {
|
|
647
|
-
process.exit(0);
|
|
648
700
|
}
|
|
701
|
+
|
|
702
|
+
process.exit(0);
|
|
649
703
|
});
|