squish-memory 1.0.2 → 1.1.5
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/.env.example +130 -0
- package/CHANGELOG.md +55 -0
- package/README.md +150 -287
- package/config/hooks/claude-code-hooks.json +39 -0
- package/config/hooks/cursor-hooks.json +30 -0
- package/config/hooks/opencode-hooks.json +30 -0
- package/config/hooks/windsurf-hooks.json +30 -0
- package/config/mcp-mode-semantics.json +23 -21
- package/config/plugin-manifest.json +101 -152
- package/{plugin.json → config/plugin.json} +2 -2
- package/config/settings.json +52 -51
- package/{commands → core/commands}/init.md +39 -39
- package/dist/config.d.ts +28 -4
- package/dist/config.js +97 -29
- package/dist/core/adapters/config/claude-code.d.ts +45 -0
- package/dist/core/adapters/config/claude-code.js +113 -0
- package/dist/core/adapters/config/cursor.d.ts +26 -0
- package/dist/core/adapters/config/cursor.js +74 -0
- package/dist/core/adapters/config/opencode.d.ts +23 -0
- package/dist/core/adapters/config/opencode.js +73 -0
- package/dist/core/adapters/config/windsurf.d.ts +26 -0
- package/dist/core/adapters/config/windsurf.js +74 -0
- package/dist/core/adapters/index.d.ts +45 -0
- package/dist/core/adapters/index.js +84 -0
- package/dist/core/adapters/scripts/install-adapter.d.ts +19 -0
- package/dist/core/adapters/scripts/install-adapter.js +149 -0
- package/dist/core/adapters/timeline.d.ts +23 -0
- package/dist/core/adapters/timeline.js +88 -0
- package/dist/core/adapters/types.d.ts +157 -0
- package/dist/core/adapters/types.js +50 -0
- package/dist/{algorithms → core/algorithms}/analytics/token-estimator.d.ts +1 -1
- package/dist/{algorithms → core/algorithms}/analytics/token-estimator.js +3 -3
- package/dist/{algorithms → core/algorithms}/detection/semantic-ranker.d.ts +1 -1
- package/dist/{algorithms → core/algorithms}/detection/semantic-ranker.js +1 -1
- package/dist/{algorithms → core/algorithms}/detection/two-stage-detector.d.ts +1 -1
- package/dist/{algorithms → core/algorithms}/detection/two-stage-detector.js +7 -10
- package/dist/{algorithms → core/algorithms}/handlers/approve-merge.js +4 -4
- package/dist/{algorithms → core/algorithms}/handlers/detect-duplicates.js +3 -3
- package/dist/{algorithms → core/algorithms}/handlers/get-stats.js +3 -3
- package/dist/{algorithms → core/algorithms}/handlers/list-proposals.js +3 -3
- package/dist/{algorithms → core/algorithms}/handlers/preview-merge.js +3 -3
- package/dist/{algorithms → core/algorithms}/handlers/reject-merge.js +3 -3
- package/dist/{algorithms → core/algorithms}/handlers/reverse-merge.js +3 -3
- package/dist/core/algorithms/index.d.ts +21 -0
- package/dist/core/algorithms/index.js +26 -0
- package/dist/core/algorithms/operations/cache-maintenance.d.ts +12 -0
- package/dist/core/algorithms/operations/cache-maintenance.js +157 -0
- package/dist/{algorithms → core/algorithms}/safety/safety-checks.d.ts +1 -1
- package/dist/{algorithms → core/algorithms}/strategies/merge-strategies.d.ts +19 -1
- package/dist/{algorithms → core/algorithms}/strategies/merge-strategies.js +74 -123
- package/dist/core/algorithms/types.d.ts +133 -0
- package/dist/core/algorithms/types.js +5 -0
- package/dist/core/associations.d.ts +1 -2
- package/dist/core/associations.js +1 -2
- package/dist/core/autosave.d.ts +19 -0
- package/dist/core/autosave.js +16 -0
- package/dist/{commands → core/commands}/managed-sync.js +5 -5
- package/dist/core/commands/mcp-server.js +739 -0
- package/dist/core/context/agent-context.d.ts +106 -0
- package/dist/core/context/agent-context.js +274 -0
- package/dist/core/{context-paging.d.ts → context/context-paging.d.ts} +2 -12
- package/dist/core/{context-paging.js → context/context-paging.js} +19 -39
- package/dist/core/context/context-window.d.ts +40 -0
- package/dist/core/context/context-window.js +177 -0
- package/dist/core/context/context.js +22 -0
- package/dist/core/embeddings.d.ts +1 -1
- package/dist/core/embeddings.js +54 -2
- package/dist/core/error-handling.d.ts +63 -0
- package/dist/core/error-handling.js +173 -0
- package/dist/core/external-folder/index.d.ts +102 -0
- package/dist/core/external-folder/index.js +294 -0
- package/dist/core/hooks/agent-hooks.d.ts +74 -0
- package/dist/core/hooks/agent-hooks.js +244 -0
- package/dist/core/hooks/auto-tagger.d.ts +19 -0
- package/dist/core/hooks/auto-tagger.js +155 -0
- package/dist/core/hooks/capture-filter.d.ts +41 -0
- package/dist/core/hooks/capture-filter.js +128 -0
- package/dist/core/index.d.ts +6 -6
- package/dist/core/index.js +6 -6
- package/dist/core/{agent-memory.js → ingestion/agent-memory.js} +5 -7
- package/dist/core/{core-memory.js → ingestion/core-memory.js} +4 -4
- package/dist/core/ingestion/learnings.d.ts +57 -0
- package/dist/core/ingestion/learnings.js +202 -0
- package/dist/core/lib/db-client.d.ts +114 -0
- package/dist/core/lib/db-client.js +130 -0
- package/dist/core/lib/schemas.d.ts +129 -0
- package/dist/core/lib/schemas.js +87 -0
- package/dist/core/{utils.d.ts → lib/utils.d.ts} +1 -0
- package/dist/core/{utils.js → lib/utils.js} +31 -15
- package/dist/core/lib/validation.d.ts +38 -0
- package/dist/core/lib/validation.js +151 -0
- package/dist/core/lifecycle.d.ts +7 -0
- package/dist/core/lifecycle.js +140 -20
- package/dist/core/local-embeddings.d.ts +6 -1
- package/dist/core/local-embeddings.js +6 -15
- package/dist/core/logger.js +7 -1
- package/dist/core/mcp/tools.js +35 -3
- package/dist/core/memory/categorizer.js +1 -0
- package/dist/core/memory/conflict-detector.js +1 -1
- package/dist/core/memory/consolidation.d.ts +1 -10
- package/dist/core/memory/consolidation.js +2 -11
- package/dist/core/memory/context-collector.js +1 -1
- package/dist/core/memory/edit-workflow.js +1 -1
- package/dist/core/memory/entity-resolver.js +7 -7
- package/dist/core/memory/fact-extractor.js +12 -12
- package/dist/core/memory/feedback-tracker.js +1 -1
- package/dist/core/memory/hooks.d.ts +88 -0
- package/dist/core/memory/hooks.js +174 -0
- package/dist/core/memory/hybrid-retrieval.js +2 -2
- package/dist/core/memory/hybrid-search.d.ts +1 -6
- package/dist/core/memory/hybrid-search.js +70 -84
- package/dist/core/memory/importance.d.ts +8 -13
- package/dist/core/memory/importance.js +47 -74
- package/dist/core/memory/loader.d.ts +31 -0
- package/dist/core/memory/loader.js +141 -0
- package/dist/core/memory/markdown/markdown-storage.d.ts +72 -0
- package/dist/core/memory/markdown/markdown-storage.js +243 -0
- package/dist/core/memory/memories.d.ts +12 -4
- package/dist/core/memory/memories.js +192 -180
- package/dist/core/memory/memory-lifecycle.d.ts +8 -0
- package/dist/core/memory/memory-lifecycle.js +55 -0
- package/dist/core/memory/migrate.d.ts +21 -0
- package/dist/core/memory/migrate.js +134 -0
- package/dist/core/memory/normalization.d.ts +22 -0
- package/dist/core/memory/normalization.js +26 -0
- package/dist/core/memory/progressive-disclosure.js +1 -1
- package/dist/core/memory/query-rewriter.js +9 -9
- package/dist/core/memory/serialization.d.ts +4 -0
- package/dist/core/memory/serialization.js +49 -0
- package/dist/core/memory/stats.d.ts +5 -0
- package/dist/core/memory/stats.js +63 -12
- package/dist/core/memory/temporal-facts.js +21 -0
- package/dist/core/memory/write-gate.js +1 -1
- package/dist/core/obsidian-vault.d.ts +30 -0
- package/dist/core/obsidian-vault.js +94 -0
- package/dist/core/places/index.d.ts +14 -0
- package/dist/core/places/index.js +14 -0
- package/dist/core/places/memory-places.d.ts +68 -0
- package/dist/core/places/memory-places.js +261 -0
- package/dist/core/places/places.d.ts +88 -0
- package/dist/core/places/places.js +314 -0
- package/dist/core/places/rules.d.ts +74 -0
- package/dist/core/places/rules.js +240 -0
- package/dist/core/places/walking.d.ts +56 -0
- package/dist/core/places/walking.js +121 -0
- package/dist/core/projects.d.ts +5 -0
- package/dist/core/projects.js +39 -18
- package/dist/core/responses.d.ts +96 -0
- package/dist/core/responses.js +122 -0
- package/dist/core/scheduler/cron-scheduler.js +29 -7
- package/dist/core/scheduler/index.d.ts +1 -1
- package/dist/core/scheduler/index.js +1 -1
- package/dist/core/scheduler/job-runner.js +1 -1
- package/dist/core/search/conversations.js +40 -42
- package/dist/core/search/entities.js +6 -9
- package/dist/core/search/graph-boost.d.ts +7 -0
- package/dist/core/search/graph-boost.js +23 -0
- package/dist/core/search/qmd-search.js +4 -4
- package/dist/core/security/encrypt.d.ts +6 -0
- package/dist/core/security/encrypt.js +47 -0
- package/dist/core/{governance.d.ts → security/governance.d.ts} +6 -1
- package/dist/core/security/governance.js +79 -0
- package/dist/core/session/auto-load.js +6 -6
- package/dist/core/session/index.d.ts +1 -1
- package/dist/core/session/index.js +1 -1
- package/dist/core/session/self-iteration-job.d.ts +20 -0
- package/dist/core/session/self-iteration-job.js +282 -0
- package/dist/core/session/session-hooks.d.ts +18 -0
- package/dist/core/session/session-hooks.js +58 -0
- package/dist/core/session-hooks/self-iteration-job.js +35 -35
- package/dist/core/{cache.js → storage/cache.js} +2 -2
- package/dist/core/sync/qmd-sync.d.ts +1 -13
- package/dist/core/sync/qmd-sync.js +1 -13
- package/dist/core/toon.d.ts +43 -0
- package/dist/core/toon.js +160 -0
- package/dist/core/utils/memory-operations.js +1 -1
- package/dist/core/utils/vector-operations.d.ts +71 -0
- package/dist/core/utils/vector-operations.js +129 -0
- package/dist/db/adapter.d.ts +3 -3
- package/dist/db/adapter.js +99 -88
- package/dist/db/bootstrap.js +820 -522
- package/dist/{drizzle → db/drizzle}/schema-sqlite.d.ts +74 -25
- package/dist/{drizzle → db/drizzle}/schema-sqlite.js +91 -24
- package/dist/{drizzle → db/drizzle}/schema.d.ts +79 -32
- package/dist/{drizzle → db/drizzle}/schema.js +106 -35
- package/dist/db/drizzle.config.d.ts +3 -0
- package/dist/db/drizzle.config.js +12 -0
- package/dist/db/index.d.ts +1 -5
- package/dist/db/index.js +51 -8
- package/dist/db/neon.d.ts +8 -0
- package/dist/db/neon.js +20 -0
- package/dist/db/schema/index.d.ts +40 -0
- package/dist/db/schema/index.js +105 -0
- package/dist/db/schema/tables/context-sessions.d.ts +9 -0
- package/dist/db/schema/tables/context-sessions.js +37 -0
- package/dist/db/schema/tables/conversations.d.ts +9 -0
- package/dist/db/schema/tables/conversations.js +47 -0
- package/dist/db/schema/tables/core-memory.d.ts +9 -0
- package/dist/db/schema/tables/core-memory.js +41 -0
- package/dist/db/schema/tables/entities.d.ts +9 -0
- package/dist/db/schema/tables/entities.js +39 -0
- package/dist/db/schema/tables/entity-relations.d.ts +9 -0
- package/dist/db/schema/tables/entity-relations.js +31 -0
- package/dist/db/schema/tables/learnings.d.ts +9 -0
- package/dist/db/schema/tables/learnings.js +66 -0
- package/dist/db/schema/tables/memories.d.ts +9 -0
- package/dist/db/schema/tables/memories.js +161 -0
- package/dist/db/schema/tables/memory-associations.d.ts +9 -0
- package/dist/db/schema/tables/memory-associations.js +39 -0
- package/dist/db/schema/tables/memory-hash-cache.d.ts +9 -0
- package/dist/db/schema/tables/memory-hash-cache.js +29 -0
- package/dist/db/schema/tables/memory-merge-history.d.ts +9 -0
- package/dist/db/schema/tables/memory-merge-history.js +33 -0
- package/dist/db/schema/tables/memory-merge-proposals.d.ts +9 -0
- package/dist/db/schema/tables/memory-merge-proposals.js +39 -0
- package/dist/db/schema/tables/messages.d.ts +9 -0
- package/dist/db/schema/tables/messages.js +41 -0
- package/dist/db/schema/tables/namespaces.d.ts +9 -0
- package/dist/db/schema/tables/namespaces.js +37 -0
- package/dist/db/schema/tables/projects.d.ts +9 -0
- package/dist/db/schema/tables/projects.js +31 -0
- package/dist/db/schema/tables/users.d.ts +9 -0
- package/dist/db/schema/tables/users.js +27 -0
- package/dist/db/schema.d.ts +1 -1
- package/dist/db/schema.js +2 -2
- package/dist/db/supabase.d.ts +9 -0
- package/dist/db/supabase.js +24 -0
- package/dist/index.d.ts +2 -14
- package/dist/index.js +1320 -640
- package/dist/vendor/sql.js/sql-wasm.wasm +0 -0
- package/dist/webui/server.d.ts +5 -0
- package/dist/{api/web/web.js → webui/server.js} +511 -508
- package/generated/mcp/manifest.json +1 -1
- package/{.mcp.json → mcp.json.example} +1 -1
- package/package.json +159 -181
- package/scripts/README.md +60 -0
- package/scripts/copy-runtime-assets.mjs +26 -0
- package/scripts/generate-mcp.mjs +264 -264
- package/scripts/github-release.sh +4 -4
- package/scripts/install-claude-code.sh +85 -0
- package/scripts/install-cursor.sh +56 -0
- package/scripts/install-hooks.sh +73 -0
- package/scripts/install-interactive.mjs +357 -677
- package/scripts/install-opencode.sh +75 -0
- package/scripts/install-windsurf.sh +67 -0
- package/skills/squish-memory/SKILL.md +104 -114
- package/skills/squish-memory/{install.mjs → scripts/install.mjs} +2 -2
- package/skills/squish-memory/{install.sh → scripts/install.sh} +2 -2
- package/skills/squish-memory/write_skill.js +2 -0
- package/.claude-plugin/marketplace.json +0 -20
- package/.claude-plugin/plugin.json +0 -32
- package/.env.mcp.example +0 -60
- package/QUICK-START.md +0 -71
- package/bin/squish-add.mjs +0 -32
- package/bin/squish-rm.mjs +0 -21
- package/commands/observe.md +0 -5
- package/dist/api/web/index.d.ts +0 -3
- package/dist/api/web/index.js +0 -4
- package/dist/api/web/web-server.d.ts +0 -3
- package/dist/api/web/web-server.js +0 -6
- package/dist/api/web/web.d.ts +0 -4
- package/dist/commands/mcp-server.js +0 -393
- package/dist/core/context.js +0 -24
- package/dist/core/governance.js +0 -64
- package/dist/core/observations.d.ts +0 -26
- package/dist/core/observations.js +0 -110
- package/dist/core/requirements.d.ts +0 -20
- package/dist/core/requirements.js +0 -35
- package/hooks/hooks.json +0 -52
- package/hooks/post-tool-use.js +0 -26
- package/hooks/session-end.js +0 -28
- package/hooks/session-start.js +0 -33
- package/hooks/user-prompt-submit.js +0 -26
- package/hooks/utils.js +0 -153
- package/npx-installer.js +0 -208
- package/packages/plugin-claude-code/README.md +0 -73
- package/packages/plugin-claude-code/dist/plugin-wrapper.d.ts +0 -35
- package/packages/plugin-claude-code/dist/plugin-wrapper.js +0 -191
- package/packages/plugin-claude-code/package.json +0 -31
- package/packages/plugin-openclaw/README.md +0 -70
- package/packages/plugin-openclaw/dist/index.d.ts +0 -49
- package/packages/plugin-openclaw/dist/index.js +0 -262
- package/packages/plugin-openclaw/openclaw.plugin.json +0 -94
- package/packages/plugin-openclaw/package.json +0 -31
- package/packages/plugin-opencode/install.mjs +0 -217
- package/packages/plugin-opencode/package.json +0 -21
- package/scripts/db/check-db.mjs +0 -88
- package/scripts/db/fix-all-columns.mjs +0 -52
- package/scripts/db/fix-schema-all.mjs +0 -55
- package/scripts/db/fix-schema-full.mjs +0 -46
- package/scripts/db/fix-schema.mjs +0 -38
- package/scripts/db/init-db.mjs +0 -13
- package/scripts/db/recreate-db.mjs +0 -14
- package/scripts/install-mcp.mjs +0 -116
- package/scripts/install-web.sh +0 -120
- package/scripts/install.mjs +0 -340
- package/scripts/openclaw-bootstrap.mjs +0 -127
- package/scripts/package-release.sh +0 -71
- package/scripts/test/test-all-systems.mjs +0 -139
- package/scripts/test/test-memory-system.mjs +0 -139
- package/scripts/test/test-v0.5.0.mjs +0 -210
- package/skills/memory-guide/SKILL.md +0 -332
- package/skills/squish-cli/SKILL.md +0 -240
- package/skills/squish-mcp/SKILL.md +0 -355
- package/skills/squish-memory/claude-desktop.json +0 -12
- package/skills/squish-memory/openclaw.json +0 -13
- package/skills/squish-memory/opencode.json +0 -14
- package/skills/squish-memory/skill.json +0 -32
- /package/{commands → core/commands}/context-paging.md +0 -0
- /package/{commands → core/commands}/context-status.md +0 -0
- /package/{commands → core/commands}/context.md +0 -0
- /package/{commands → core/commands}/core-memory.md +0 -0
- /package/{commands → core/commands}/health.md +0 -0
- /package/{commands → core/commands}/merge.md +0 -0
- /package/{commands → core/commands}/recall.md +0 -0
- /package/{commands → core/commands}/remember.md +0 -0
- /package/{commands → core/commands}/search.md +0 -0
- /package/dist/{algorithms → core/algorithms}/detection/hash-filters.d.ts +0 -0
- /package/dist/{algorithms → core/algorithms}/detection/hash-filters.js +0 -0
- /package/dist/{algorithms → core/algorithms}/handlers/approve-merge.d.ts +0 -0
- /package/dist/{algorithms → core/algorithms}/handlers/detect-duplicates.d.ts +0 -0
- /package/dist/{algorithms → core/algorithms}/handlers/get-stats.d.ts +0 -0
- /package/dist/{algorithms → core/algorithms}/handlers/list-proposals.d.ts +0 -0
- /package/dist/{algorithms → core/algorithms}/handlers/preview-merge.d.ts +0 -0
- /package/dist/{algorithms → core/algorithms}/handlers/reject-merge.d.ts +0 -0
- /package/dist/{algorithms → core/algorithms}/handlers/reverse-merge.d.ts +0 -0
- /package/dist/{algorithms → core/algorithms}/safety/safety-checks.js +0 -0
- /package/dist/{algorithms → core/algorithms}/utils/response-builder.d.ts +0 -0
- /package/dist/{algorithms → core/algorithms}/utils/response-builder.js +0 -0
- /package/dist/{commands → core/commands}/managed-sync.d.ts +0 -0
- /package/dist/{commands → core/commands}/mcp-server.d.ts +0 -0
- /package/dist/core/{context.d.ts → context/context.d.ts} +0 -0
- /package/dist/core/{agent-memory.d.ts → ingestion/agent-memory.d.ts} +0 -0
- /package/dist/core/{core-memory.d.ts → ingestion/core-memory.d.ts} +0 -0
- /package/dist/core/{privacy.d.ts → security/privacy.d.ts} +0 -0
- /package/dist/core/{privacy.js → security/privacy.js} +0 -0
- /package/dist/core/{secret-detector.d.ts → security/secret-detector.d.ts} +0 -0
- /package/dist/core/{secret-detector.js → security/secret-detector.js} +0 -0
- /package/dist/core/{cache.d.ts → storage/cache.d.ts} +0 -0
- /package/dist/core/{database.d.ts → storage/database.d.ts} +0 -0
- /package/dist/core/{database.js → storage/database.js} +0 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External Folder Memory Manager
|
|
3
|
+
*
|
|
4
|
+
* Wraps QMD to treat an external folder as a secondary memory layer.
|
|
5
|
+
* - Writes hot memories to daily notes (YYYY-MM-DD.md) with frontmatter
|
|
6
|
+
* - Uses QMD to search both Squish DB and external folder
|
|
7
|
+
* - Auto-indexes on mount and write
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* squish mount /path/to/folder # Enable external memory
|
|
11
|
+
* squish mount status # Show status
|
|
12
|
+
* squish mount unmount # Disable
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync, mkdirSync, appendFileSync } from 'fs';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
import { spawn } from 'child_process';
|
|
17
|
+
import { logger } from '../logger.js';
|
|
18
|
+
import { config } from '../../config.js';
|
|
19
|
+
/**
|
|
20
|
+
* Format a memory as markdown with YAML frontmatter
|
|
21
|
+
*/
|
|
22
|
+
function formatMemoryAsMarkdown(memory) {
|
|
23
|
+
const frontmatter = [
|
|
24
|
+
'---',
|
|
25
|
+
`id: ${memory.id}`,
|
|
26
|
+
`type: ${memory.type}`,
|
|
27
|
+
`tags: [${memory.tags.join(', ')}]`,
|
|
28
|
+
`created: ${memory.createdAt}`,
|
|
29
|
+
];
|
|
30
|
+
if (memory.confidence) {
|
|
31
|
+
frontmatter.push(`confidence: ${memory.confidence}`);
|
|
32
|
+
}
|
|
33
|
+
if (memory.projectId) {
|
|
34
|
+
frontmatter.push(`project: ${memory.projectId}`);
|
|
35
|
+
}
|
|
36
|
+
frontmatter.push('---', '', memory.content);
|
|
37
|
+
return frontmatter.join('\n');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the daily note filename for a given date
|
|
41
|
+
*/
|
|
42
|
+
function getDailyNotePath(folderPath, date) {
|
|
43
|
+
const year = date.getFullYear();
|
|
44
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
45
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
46
|
+
return join(folderPath, `${year}-${month}-${day}.md`);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get today's date string
|
|
50
|
+
*/
|
|
51
|
+
function getTodayDateStr() {
|
|
52
|
+
const today = new Date();
|
|
53
|
+
const year = today.getFullYear();
|
|
54
|
+
const month = String(today.getMonth() + 1).padStart(2, '0');
|
|
55
|
+
const day = String(today.getDate()).padStart(2, '0');
|
|
56
|
+
return `${year}-${month}-${day}`;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* External Folder Memory Manager class
|
|
60
|
+
*/
|
|
61
|
+
export class ExternalFolderMemory {
|
|
62
|
+
mountedPath = null;
|
|
63
|
+
/**
|
|
64
|
+
* Check if external memory is enabled and mounted
|
|
65
|
+
*/
|
|
66
|
+
isEnabled() {
|
|
67
|
+
return config.externalMemoryEnabled && !!config.externalMemoryPath;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get the mounted path
|
|
71
|
+
*/
|
|
72
|
+
getPath() {
|
|
73
|
+
return this.isEnabled() ? config.externalMemoryPath : null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Mount external memory at a path
|
|
77
|
+
* Creates folder if needed, initializes structure
|
|
78
|
+
*/
|
|
79
|
+
async mount(path) {
|
|
80
|
+
if (!path) {
|
|
81
|
+
return { success: false, error: 'Path is required' };
|
|
82
|
+
}
|
|
83
|
+
// Resolve to absolute path
|
|
84
|
+
const absolutePath = join(process.cwd(), path);
|
|
85
|
+
// Security: validate path doesn't escape cwd (prevent path traversal)
|
|
86
|
+
const resolvedPath = absolutePath.split(/[\\/]/).join('/');
|
|
87
|
+
const cwdPath = process.cwd().split(/[\\/]/).join('/');
|
|
88
|
+
if (!resolvedPath.startsWith(cwdPath + '/') && resolvedPath !== cwdPath) {
|
|
89
|
+
return { success: false, error: 'Path traversal not allowed' };
|
|
90
|
+
}
|
|
91
|
+
// Create folder if it doesn't exist
|
|
92
|
+
if (!existsSync(absolutePath)) {
|
|
93
|
+
try {
|
|
94
|
+
mkdirSync(absolutePath, { recursive: true });
|
|
95
|
+
logger.info(`[ExternalMemory] Created folder: ${absolutePath}`);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return { success: false, error: `Failed to create folder: ${error}` };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Initialize QMD index for this folder
|
|
102
|
+
const indexed = await this.ensureIndexed(absolutePath);
|
|
103
|
+
if (!indexed) {
|
|
104
|
+
logger.warn('[ExternalMemory] QMD not found or indexing failed. Install with: bun install -g qmd');
|
|
105
|
+
}
|
|
106
|
+
this.mountedPath = absolutePath;
|
|
107
|
+
logger.info(`[ExternalMemory] Mounted at: ${absolutePath}`);
|
|
108
|
+
return { success: true };
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Unmount external memory
|
|
112
|
+
*/
|
|
113
|
+
unmount() {
|
|
114
|
+
this.mountedPath = null;
|
|
115
|
+
logger.info('[ExternalMemory] Unmounted');
|
|
116
|
+
return { success: true };
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Ensure QMD indexes the external folder
|
|
120
|
+
*/
|
|
121
|
+
async ensureIndexed(folderPath) {
|
|
122
|
+
const targetPath = folderPath || this.getPath();
|
|
123
|
+
if (!targetPath) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return new Promise((resolve) => {
|
|
127
|
+
// Run qmd add to index the folder
|
|
128
|
+
const process = spawn('qmd', ['add', targetPath], {
|
|
129
|
+
stdio: 'ignore'
|
|
130
|
+
});
|
|
131
|
+
process.on('close', (code) => {
|
|
132
|
+
if (code === 0) {
|
|
133
|
+
logger.info(`[ExternalMemory] Indexed folder: ${targetPath}`);
|
|
134
|
+
resolve(true);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
logger.warn(`[ExternalMemory] QMD add failed with code: ${code}`);
|
|
138
|
+
resolve(false);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
process.on('error', (error) => {
|
|
142
|
+
logger.warn(`[ExternalMemory] QMD add error: ${error}`);
|
|
143
|
+
resolve(false);
|
|
144
|
+
});
|
|
145
|
+
// Timeout after 30 seconds
|
|
146
|
+
setTimeout(() => {
|
|
147
|
+
process.kill();
|
|
148
|
+
resolve(false);
|
|
149
|
+
}, 30000);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Write a memory to the external folder (daily note)
|
|
154
|
+
*/
|
|
155
|
+
async writeMemory(memory) {
|
|
156
|
+
const folderPath = this.getPath();
|
|
157
|
+
if (!folderPath) {
|
|
158
|
+
return { success: false, error: 'External memory not enabled' };
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const date = memory.createdAt ? new Date(memory.createdAt) : new Date();
|
|
162
|
+
const dailyNotePath = getDailyNotePath(folderPath, date);
|
|
163
|
+
const dateStr = getTodayDateStr();
|
|
164
|
+
// Build memory block content
|
|
165
|
+
const memoryBlock = formatMemoryAsMarkdown(memory);
|
|
166
|
+
// Check if daily note exists, if not create with header
|
|
167
|
+
if (!existsSync(dailyNotePath)) {
|
|
168
|
+
const header = `# ${dateStr}\n\n## Squish Memories\n\n---\n\n`;
|
|
169
|
+
appendFileSync(dailyNotePath, header, 'utf-8');
|
|
170
|
+
logger.info(`[ExternalMemory] Created daily note: ${dailyNotePath}`);
|
|
171
|
+
}
|
|
172
|
+
// Append memory block with separator
|
|
173
|
+
appendFileSync(dailyNotePath, '\n---\n\n' + memoryBlock + '\n', 'utf-8');
|
|
174
|
+
logger.info(`[ExternalMemory] Wrote memory ${memory.id} to ${dateStr}.md`);
|
|
175
|
+
// Trigger QMD re-index (background)
|
|
176
|
+
this.triggerReindex().catch(() => { });
|
|
177
|
+
return { success: true };
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
181
|
+
logger.error(`[ExternalMemory] Write failed: ${errorMsg}`);
|
|
182
|
+
return { success: false, error: errorMsg };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Trigger background re-index via QMD
|
|
187
|
+
*/
|
|
188
|
+
async triggerReindex() {
|
|
189
|
+
const folderPath = this.getPath();
|
|
190
|
+
if (!folderPath)
|
|
191
|
+
return;
|
|
192
|
+
// Run qmd in background to re-index
|
|
193
|
+
spawn('qmd', ['add', folderPath], {
|
|
194
|
+
stdio: 'ignore',
|
|
195
|
+
detached: true
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get current status of external memory
|
|
200
|
+
*/
|
|
201
|
+
async getStatus() {
|
|
202
|
+
const path = this.getPath();
|
|
203
|
+
if (!path || !existsSync(path)) {
|
|
204
|
+
return {
|
|
205
|
+
mounted: false,
|
|
206
|
+
path: null,
|
|
207
|
+
qmdIndexed: false,
|
|
208
|
+
memoryCount: 0,
|
|
209
|
+
lastIndexed: null
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
// Count .md files and memories
|
|
213
|
+
let memoryCount = 0;
|
|
214
|
+
try {
|
|
215
|
+
const { readdirSync } = await import('fs');
|
|
216
|
+
const files = readdirSync(path).filter(f => f.endsWith('.md'));
|
|
217
|
+
memoryCount = files.length;
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
// Ignore
|
|
221
|
+
}
|
|
222
|
+
// Check if QMD has this folder indexed (via qmd list)
|
|
223
|
+
const qmdIndexed = await this.checkQMDIndexed(path);
|
|
224
|
+
return {
|
|
225
|
+
mounted: true,
|
|
226
|
+
path,
|
|
227
|
+
qmdIndexed,
|
|
228
|
+
memoryCount,
|
|
229
|
+
lastIndexed: null
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Check if folder is indexed by QMD
|
|
234
|
+
*/
|
|
235
|
+
async checkQMDIndexed(folderPath) {
|
|
236
|
+
return new Promise((resolve) => {
|
|
237
|
+
const process = spawn('qmd', ['list'], {
|
|
238
|
+
stdio: 'pipe'
|
|
239
|
+
});
|
|
240
|
+
let output = '';
|
|
241
|
+
process.stdout?.on('data', (data) => {
|
|
242
|
+
output += data.toString();
|
|
243
|
+
});
|
|
244
|
+
process.on('close', () => {
|
|
245
|
+
resolve(output.includes(folderPath));
|
|
246
|
+
});
|
|
247
|
+
process.on('error', () => {
|
|
248
|
+
resolve(false);
|
|
249
|
+
});
|
|
250
|
+
setTimeout(() => {
|
|
251
|
+
process.kill();
|
|
252
|
+
resolve(false);
|
|
253
|
+
}, 5000);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Convert a MemoryRecord to MemoryAsMarkdown format
|
|
258
|
+
*/
|
|
259
|
+
toMarkdownFormat(memory) {
|
|
260
|
+
return {
|
|
261
|
+
id: memory.id,
|
|
262
|
+
type: memory.type,
|
|
263
|
+
content: memory.content,
|
|
264
|
+
tags: memory.tags || [],
|
|
265
|
+
createdAt: memory.createdAt || new Date().toISOString(),
|
|
266
|
+
confidence: memory.confidenceLevel || undefined,
|
|
267
|
+
projectId: memory.projectId
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Singleton instance
|
|
272
|
+
let externalMemoryInstance = null;
|
|
273
|
+
/**
|
|
274
|
+
* Get the singleton ExternalFolderMemory instance
|
|
275
|
+
*/
|
|
276
|
+
export function getExternalMemory() {
|
|
277
|
+
if (!externalMemoryInstance) {
|
|
278
|
+
externalMemoryInstance = new ExternalFolderMemory();
|
|
279
|
+
}
|
|
280
|
+
return externalMemoryInstance;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Check if external memory is enabled
|
|
284
|
+
*/
|
|
285
|
+
export function isExternalMemoryEnabled() {
|
|
286
|
+
return getExternalMemory().isEnabled();
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Get external memory path
|
|
290
|
+
*/
|
|
291
|
+
export function getExternalMemoryPath() {
|
|
292
|
+
return getExternalMemory().getPath();
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Hooks - Core Logic
|
|
3
|
+
*
|
|
4
|
+
* Universal hooks for auto-capturing agent activities.
|
|
5
|
+
* Works with Claude Code, OpenCode, Cursor, Windsurf.
|
|
6
|
+
*
|
|
7
|
+
* Hook events:
|
|
8
|
+
* - sessionStart: Inject relevant memories on session start
|
|
9
|
+
* - postToolUse: Record observations after tool execution
|
|
10
|
+
* - sessionEnd: Save snapshot and sync learnings
|
|
11
|
+
* - preCompact: Save state before context compaction
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Generate a new session ID (universal across agents)
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateSessionId(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Get current session ID
|
|
19
|
+
*/
|
|
20
|
+
export declare function getCurrentSessionId(): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Set session ID (for resume/continue)
|
|
23
|
+
*/
|
|
24
|
+
export declare function setSessionId(sessionId: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Session start hook - inject relevant context
|
|
27
|
+
*/
|
|
28
|
+
export declare function handleSessionStart(params: {
|
|
29
|
+
projectPath: string;
|
|
30
|
+
mode: 'startup' | 'resume' | 'compact';
|
|
31
|
+
agentType: 'claude-code' | 'opencode' | 'cursor' | 'windsurf';
|
|
32
|
+
}): Promise<{
|
|
33
|
+
memories: string[];
|
|
34
|
+
sessionId: string;
|
|
35
|
+
count: number;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Post-tool-use hook - record observations
|
|
39
|
+
*/
|
|
40
|
+
export declare function handlePostToolUse(params: {
|
|
41
|
+
toolName: string;
|
|
42
|
+
toolInput: Record<string, unknown>;
|
|
43
|
+
toolResult: unknown;
|
|
44
|
+
projectPath: string;
|
|
45
|
+
agentType: 'claude-code' | 'opencode' | 'cursor' | 'windsurf';
|
|
46
|
+
}): Promise<{
|
|
47
|
+
captured: boolean;
|
|
48
|
+
memoryId?: string;
|
|
49
|
+
reason?: string;
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Session end hook - save snapshot and sync
|
|
53
|
+
*/
|
|
54
|
+
export declare function handleSessionEnd(params: {
|
|
55
|
+
projectPath: string;
|
|
56
|
+
agentType: 'claude-code' | 'opencode' | 'cursor' | 'windsurf';
|
|
57
|
+
workInProgress?: string;
|
|
58
|
+
}): Promise<{
|
|
59
|
+
snapshotId?: string;
|
|
60
|
+
memoriesSaved: number;
|
|
61
|
+
}>;
|
|
62
|
+
/**
|
|
63
|
+
* Pre-compact hook - save state for recovery
|
|
64
|
+
*/
|
|
65
|
+
export declare function handlePreCompact(params: {
|
|
66
|
+
projectPath: string;
|
|
67
|
+
agentType: 'claude-code' | 'opencode' | 'cursor' | 'windsurf';
|
|
68
|
+
}): Promise<{
|
|
69
|
+
stateSaved: boolean;
|
|
70
|
+
stateId?: string;
|
|
71
|
+
}>;
|
|
72
|
+
export { shouldCaptureTool, categorizeTool } from './capture-filter.js';
|
|
73
|
+
export { inferTags } from './auto-tagger.js';
|
|
74
|
+
//# sourceMappingURL=agent-hooks.d.ts.map
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Hooks - Core Logic
|
|
3
|
+
*
|
|
4
|
+
* Universal hooks for auto-capturing agent activities.
|
|
5
|
+
* Works with Claude Code, OpenCode, Cursor, Windsurf.
|
|
6
|
+
*
|
|
7
|
+
* Hook events:
|
|
8
|
+
* - sessionStart: Inject relevant memories on session start
|
|
9
|
+
* - postToolUse: Record observations after tool execution
|
|
10
|
+
* - sessionEnd: Save snapshot and sync learnings
|
|
11
|
+
* - preCompact: Save state before context compaction
|
|
12
|
+
*/
|
|
13
|
+
import { randomUUID } from 'crypto';
|
|
14
|
+
import { createLearning } from '../ingestion/learnings.js';
|
|
15
|
+
import { getRecent } from '../memory/memories.js';
|
|
16
|
+
import { logger } from '../logger.js';
|
|
17
|
+
import { shouldCaptureTool, categorizeTool } from './capture-filter.js';
|
|
18
|
+
import { inferTags } from './auto-tagger.js';
|
|
19
|
+
import { ensureProject, getProjectByPath } from '../projects.js';
|
|
20
|
+
import { autoAssignMemory, initializeDefaultPlaces } from '../places/index.js';
|
|
21
|
+
/** Session ID for tracking across agents */
|
|
22
|
+
let currentSessionId = null;
|
|
23
|
+
/**
|
|
24
|
+
* Generate a new session ID (universal across agents)
|
|
25
|
+
*/
|
|
26
|
+
export function generateSessionId() {
|
|
27
|
+
currentSessionId = randomUUID();
|
|
28
|
+
return currentSessionId;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get current session ID
|
|
32
|
+
*/
|
|
33
|
+
export function getCurrentSessionId() {
|
|
34
|
+
return currentSessionId;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Set session ID (for resume/continue)
|
|
38
|
+
*/
|
|
39
|
+
export function setSessionId(sessionId) {
|
|
40
|
+
currentSessionId = sessionId;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Session start hook - inject relevant context
|
|
44
|
+
*/
|
|
45
|
+
export async function handleSessionStart(params) {
|
|
46
|
+
const { projectPath, mode, agentType } = params;
|
|
47
|
+
// Ensure project exists
|
|
48
|
+
await ensureProject(projectPath);
|
|
49
|
+
// Generate or get session ID
|
|
50
|
+
if (!currentSessionId) {
|
|
51
|
+
currentSessionId = generateSessionId();
|
|
52
|
+
}
|
|
53
|
+
logger.info(`[Hooks] Session start: ${mode} (agent: ${agentType}, session: ${currentSessionId})`);
|
|
54
|
+
// Get recent memories based on mode
|
|
55
|
+
const limit = mode === 'compact' ? 3 : 5;
|
|
56
|
+
const memories = await getRecent(projectPath, limit);
|
|
57
|
+
// Get spatial memory context (places) for context injection
|
|
58
|
+
let placesContext = '';
|
|
59
|
+
try {
|
|
60
|
+
const { initializeDefaultPlaces, getProjectPlaces } = await import('../places/index.js');
|
|
61
|
+
const { getProjectByPath } = await import('../projects.js');
|
|
62
|
+
const project = await getProjectByPath(projectPath);
|
|
63
|
+
if (project) {
|
|
64
|
+
await initializeDefaultPlaces(project.id);
|
|
65
|
+
const places = await getProjectPlaces(project.id);
|
|
66
|
+
if (places.length > 0) {
|
|
67
|
+
const populatedPlaces = places.filter(p => p.memoryCount > 0).slice(0, 3);
|
|
68
|
+
if (populatedPlaces.length > 0) {
|
|
69
|
+
placesContext = '\n\nActive places: ' + populatedPlaces.map(p => `${p.name} (${p.memoryCount})`).join(', ');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
// Don't fail if places not available
|
|
76
|
+
logger.debug(`[Hooks] Places context not available: ${e}`);
|
|
77
|
+
}
|
|
78
|
+
// Format for injection
|
|
79
|
+
const formatted = memories.map((m, i) => `${i + 1}. [${m.type}] ${m.content?.substring(0, 100)}...`).join('\n');
|
|
80
|
+
const allContent = formatted + placesContext;
|
|
81
|
+
logger.info(`[Hooks] Injected ${memories.length} memories for session start`);
|
|
82
|
+
return {
|
|
83
|
+
memories: allContent ? allContent.split('\n') : [],
|
|
84
|
+
sessionId: currentSessionId,
|
|
85
|
+
count: memories.length,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Post-tool-use hook - record observations
|
|
90
|
+
*/
|
|
91
|
+
export async function handlePostToolUse(params) {
|
|
92
|
+
const { toolName, toolInput, toolResult, projectPath, agentType } = params;
|
|
93
|
+
// Ensure project exists
|
|
94
|
+
await ensureProject(projectPath);
|
|
95
|
+
// Ensure session ID exists
|
|
96
|
+
if (!currentSessionId) {
|
|
97
|
+
currentSessionId = generateSessionId();
|
|
98
|
+
}
|
|
99
|
+
// Check if we should capture this tool
|
|
100
|
+
if (!shouldCaptureTool(toolName)) {
|
|
101
|
+
return { captured: false, reason: `Tool ${toolName} filtered out` };
|
|
102
|
+
}
|
|
103
|
+
// Extract relevant information
|
|
104
|
+
const category = categorizeTool(toolName);
|
|
105
|
+
const target = extractTarget(toolName, toolInput);
|
|
106
|
+
const content = extractContent(toolName, toolInput, toolResult);
|
|
107
|
+
// Infer tags from context
|
|
108
|
+
const tags = inferTags(toolName, toolInput, content);
|
|
109
|
+
// Create learning/observation
|
|
110
|
+
const learningInput = {
|
|
111
|
+
type: 'insight',
|
|
112
|
+
content: `[${category}] ${content}`,
|
|
113
|
+
action: toolName,
|
|
114
|
+
target,
|
|
115
|
+
project: projectPath,
|
|
116
|
+
autoLink: true,
|
|
117
|
+
};
|
|
118
|
+
try {
|
|
119
|
+
const learning = await createLearning(learningInput);
|
|
120
|
+
logger.info(`[Hooks] Captured ${toolName} → ${learning.id} (session: ${currentSessionId})`);
|
|
121
|
+
// Auto-assign to place (if places are initialized)
|
|
122
|
+
try {
|
|
123
|
+
const project = await getProjectByPath(projectPath);
|
|
124
|
+
if (project) {
|
|
125
|
+
// Initialize default places if they don't exist
|
|
126
|
+
await initializeDefaultPlaces(project.id);
|
|
127
|
+
// Auto-assign the memory to a place
|
|
128
|
+
await autoAssignMemory({
|
|
129
|
+
memoryId: learning.id,
|
|
130
|
+
projectId: project.id,
|
|
131
|
+
toolName,
|
|
132
|
+
content: learningInput.content,
|
|
133
|
+
tags,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (placeError) {
|
|
138
|
+
// Don't fail the hook if place assignment fails
|
|
139
|
+
logger.warn(`[Hooks] Place assignment failed: ${placeError}`);
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
captured: true,
|
|
143
|
+
memoryId: learning.id,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
logger.error(`[Hooks] Failed to capture:`, error);
|
|
148
|
+
return { captured: false, reason: 'Failed to create learning' };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Session end hook - save snapshot and sync
|
|
153
|
+
*/
|
|
154
|
+
export async function handleSessionEnd(params) {
|
|
155
|
+
const { projectPath, agentType, workInProgress } = params;
|
|
156
|
+
// Ensure project exists
|
|
157
|
+
await ensureProject(projectPath);
|
|
158
|
+
logger.info(`[Hooks] Session end (agent: ${agentType}, session: ${currentSessionId})`);
|
|
159
|
+
// Save session snapshot as a learning
|
|
160
|
+
if (workInProgress) {
|
|
161
|
+
const snapshot = await createLearning({
|
|
162
|
+
type: 'insight',
|
|
163
|
+
content: `[SESSION SNAPSHOT] ${workInProgress}`,
|
|
164
|
+
action: 'session-end',
|
|
165
|
+
project: projectPath,
|
|
166
|
+
autoLink: false,
|
|
167
|
+
});
|
|
168
|
+
logger.info(`[Hooks] Saved session snapshot: ${snapshot.id}`);
|
|
169
|
+
currentSessionId = null; // Clear session
|
|
170
|
+
return {
|
|
171
|
+
snapshotId: snapshot.id,
|
|
172
|
+
memoriesSaved: 1,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
currentSessionId = null;
|
|
176
|
+
return {
|
|
177
|
+
memoriesSaved: 0,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Pre-compact hook - save state for recovery
|
|
182
|
+
*/
|
|
183
|
+
export async function handlePreCompact(params) {
|
|
184
|
+
const { projectPath, agentType } = params;
|
|
185
|
+
// Ensure project exists
|
|
186
|
+
await ensureProject(projectPath);
|
|
187
|
+
logger.info(`[Hooks] Pre-compact (agent: ${agentType})`);
|
|
188
|
+
// Get recent work for recovery
|
|
189
|
+
const recent = await getRecent(projectPath, 3);
|
|
190
|
+
// Save state
|
|
191
|
+
const state = await createLearning({
|
|
192
|
+
type: 'insight',
|
|
193
|
+
content: `[PRE-COMPACT] State saved for recovery. Recent: ${recent.map(r => r.content?.substring(0, 50)).join(' | ')}`,
|
|
194
|
+
action: 'pre-compact',
|
|
195
|
+
project: projectPath,
|
|
196
|
+
autoLink: false,
|
|
197
|
+
});
|
|
198
|
+
return {
|
|
199
|
+
stateSaved: true,
|
|
200
|
+
stateId: state.id,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Extract target from tool input
|
|
205
|
+
*/
|
|
206
|
+
function extractTarget(toolName, toolInput) {
|
|
207
|
+
switch (toolName) {
|
|
208
|
+
case 'Write':
|
|
209
|
+
case 'Edit':
|
|
210
|
+
return String(toolInput.filePath || toolInput.path || 'unknown');
|
|
211
|
+
case 'Bash':
|
|
212
|
+
return String(toolInput.command || toolInput.cmd || 'unknown');
|
|
213
|
+
case 'Task':
|
|
214
|
+
return String(toolInput.description || toolInput.name || 'unknown');
|
|
215
|
+
default:
|
|
216
|
+
return 'unknown';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Extract content summary from tool result
|
|
221
|
+
*/
|
|
222
|
+
function extractContent(toolName, toolInput, toolResult) {
|
|
223
|
+
switch (toolName) {
|
|
224
|
+
case 'Write':
|
|
225
|
+
return `Wrote: ${toolInput.filePath || toolInput.path}`;
|
|
226
|
+
case 'Edit':
|
|
227
|
+
return `Edited: ${toolInput.filePath || toolInput.path}`;
|
|
228
|
+
case 'Bash':
|
|
229
|
+
const cmd = String(toolInput.command || toolInput.cmd || '');
|
|
230
|
+
if (cmd.includes('commit'))
|
|
231
|
+
return `Git commit executed`;
|
|
232
|
+
if (cmd.includes('test'))
|
|
233
|
+
return `Tests run`;
|
|
234
|
+
return `Command: ${cmd.substring(0, 50)}`;
|
|
235
|
+
case 'Task':
|
|
236
|
+
return `Task: ${toolInput.description || toolInput.name || 'unknown'}`;
|
|
237
|
+
default:
|
|
238
|
+
return `Used: ${toolName}`;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Re-export for convenience
|
|
242
|
+
export { shouldCaptureTool, categorizeTool } from './capture-filter.js';
|
|
243
|
+
export { inferTags } from './auto-tagger.js';
|
|
244
|
+
//# sourceMappingURL=agent-hooks.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Tagger - Infer tags from context
|
|
3
|
+
*
|
|
4
|
+
* Analyzes tool input/output to automatically infer relevant tags.
|
|
5
|
+
* Uses pattern matching to classify actions.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Infer tags based on tool, input, and content
|
|
9
|
+
*/
|
|
10
|
+
export declare function inferTags(toolName: string, toolInput: Record<string, unknown>, content: string): string[];
|
|
11
|
+
/**
|
|
12
|
+
* Extract tags from commit message
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractCommitTags(commitMessage: string): string[];
|
|
15
|
+
/**
|
|
16
|
+
* Extract tags from file path
|
|
17
|
+
*/
|
|
18
|
+
export declare function extractFileTags(filePath: string): string[];
|
|
19
|
+
//# sourceMappingURL=auto-tagger.d.ts.map
|