@scitrera/memorylayer-cc-plugin 0.0.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/LICENSE +177 -0
  2. package/README.md +11 -4
  3. package/dist/bin/memorylayer-hook.js +27 -9
  4. package/dist/bin/memorylayer-hook.js.map +1 -1
  5. package/dist/src/hooks/client.d.ts +21 -0
  6. package/dist/src/hooks/client.d.ts.map +1 -0
  7. package/dist/src/hooks/client.js +57 -0
  8. package/dist/src/hooks/client.js.map +1 -0
  9. package/dist/src/hooks/formatters.d.ts +33 -0
  10. package/dist/src/hooks/formatters.d.ts.map +1 -0
  11. package/dist/src/hooks/formatters.js +187 -0
  12. package/dist/src/hooks/formatters.js.map +1 -0
  13. package/dist/src/hooks/handlers/post-tool.d.ts +10 -0
  14. package/dist/src/hooks/handlers/post-tool.d.ts.map +1 -0
  15. package/dist/src/hooks/handlers/post-tool.js +98 -0
  16. package/dist/src/hooks/handlers/post-tool.js.map +1 -0
  17. package/dist/src/hooks/handlers/pre-compact.d.ts +5 -0
  18. package/dist/src/hooks/handlers/pre-compact.d.ts.map +1 -0
  19. package/dist/src/hooks/handlers/pre-compact.js +117 -0
  20. package/dist/src/hooks/handlers/pre-compact.js.map +1 -0
  21. package/dist/src/hooks/handlers/pre-tool.d.ts +10 -0
  22. package/dist/src/hooks/handlers/pre-tool.d.ts.map +1 -0
  23. package/dist/src/hooks/handlers/pre-tool.js +114 -0
  24. package/dist/src/hooks/handlers/pre-tool.js.map +1 -0
  25. package/dist/src/hooks/handlers/session-start.d.ts +10 -0
  26. package/dist/src/hooks/handlers/session-start.d.ts.map +1 -0
  27. package/dist/src/hooks/handlers/session-start.js +111 -0
  28. package/dist/src/hooks/handlers/session-start.js.map +1 -0
  29. package/dist/src/hooks/handlers/stop.d.ts +14 -0
  30. package/dist/src/hooks/handlers/stop.d.ts.map +1 -0
  31. package/dist/src/hooks/handlers/stop.js +49 -0
  32. package/dist/src/hooks/handlers/stop.js.map +1 -0
  33. package/dist/src/hooks/handlers/user-prompt.d.ts +10 -0
  34. package/dist/src/hooks/handlers/user-prompt.d.ts.map +1 -0
  35. package/dist/src/hooks/handlers/user-prompt.js +128 -0
  36. package/dist/src/hooks/handlers/user-prompt.js.map +1 -0
  37. package/dist/src/hooks/index.d.ts +18 -0
  38. package/dist/src/hooks/index.d.ts.map +1 -0
  39. package/dist/src/hooks/index.js +23 -0
  40. package/dist/src/hooks/index.js.map +1 -0
  41. package/dist/src/hooks/observation.d.ts +59 -0
  42. package/dist/src/hooks/observation.d.ts.map +1 -0
  43. package/dist/src/hooks/observation.js +421 -0
  44. package/dist/src/hooks/observation.js.map +1 -0
  45. package/dist/src/hooks/state.d.ts +73 -0
  46. package/dist/src/hooks/state.d.ts.map +1 -0
  47. package/dist/src/hooks/state.js +168 -0
  48. package/dist/src/hooks/state.js.map +1 -0
  49. package/dist/src/hooks/types.d.ts +86 -0
  50. package/dist/src/hooks/types.d.ts.map +1 -0
  51. package/dist/src/hooks/types.js +14 -0
  52. package/dist/src/hooks/types.js.map +1 -0
  53. package/package.json +15 -5
@@ -0,0 +1,111 @@
1
+ /**
2
+ * SessionStart hook handler
3
+ * Retrieves briefing and relevant memories at session start
4
+ */
5
+ import { getClient } from "../client.js";
6
+ import { formatSessionStart } from "../formatters.js";
7
+ import { markRecallDone } from "../state.js";
8
+ /**
9
+ * Extract a topic from the user's first message in transcript
10
+ */
11
+ function extractTopic(input) {
12
+ if (!input.transcript || input.transcript.length === 0) {
13
+ return undefined;
14
+ }
15
+ // Find first user messageno
16
+ const userMsg = input.transcript.find(m => m.role === "user");
17
+ if (!userMsg) {
18
+ return undefined;
19
+ }
20
+ // Use first 100 chars as topic query (truncate for API efficiency)
21
+ const content = userMsg.content.trim();
22
+ if (content.length > 100) {
23
+ return content.substring(0, 100);
24
+ }
25
+ return content || undefined;
26
+ }
27
+ /**
28
+ * Check for existing sandbox state from a prior session or pre-compaction.
29
+ * Returns the inspect result if a sandbox exists, null otherwise.
30
+ */
31
+ async function checkSandboxState(client) {
32
+ try {
33
+ const status = await client.contextStatus();
34
+ if (status.exists && (status.variable_count ?? 0) > 0) {
35
+ // Sandbox has variables — fetch the overview
36
+ return await client.contextInspect({});
37
+ }
38
+ }
39
+ catch {
40
+ // Context environment may not be available, that's fine
41
+ }
42
+ return null;
43
+ }
44
+ /**
45
+ * Handle SessionStart event
46
+ */
47
+ export async function handleSessionStart(input) {
48
+ try {
49
+ const client = getClient();
50
+ const topic = extractTopic(input);
51
+ const sessionId = client.getSessionId();
52
+ if (sessionId) {
53
+ try {
54
+ const pack = await client.getContextPack(sessionId, {
55
+ topic,
56
+ budgetTokens: 2048,
57
+ includeSandboxSummary: true,
58
+ includeCheckpointRecovery: true,
59
+ });
60
+ if (topic)
61
+ markRecallDone(topic);
62
+ return {
63
+ success: true,
64
+ additionalContext: `${pack.rendered}\n\nMemoryLayer context cursor: ${pack.cursor}`,
65
+ };
66
+ }
67
+ catch (error) {
68
+ console.error("[session-start] context pack unavailable; using compatibility retrieval:", error instanceof Error ? error.message : error);
69
+ }
70
+ }
71
+ // Compatibility path for servers that do not yet expose context packs.
72
+ const [briefingResult, directiveResult, sandboxResult] = await Promise.allSettled([
73
+ client.getBriefing({ limit: 10, includeMemories: false }),
74
+ client.recall({
75
+ query: "user directives and preferences",
76
+ subtypes: ["directive", "preference"],
77
+ limit: 10,
78
+ }),
79
+ checkSandboxState(client),
80
+ ]);
81
+ const briefing = briefingResult.status === "fulfilled" ? briefingResult.value : null;
82
+ const directives = directiveResult.status === "fulfilled"
83
+ ? directiveResult.value.memories
84
+ : [];
85
+ const sandboxState = sandboxResult.status === "fulfilled" ? sandboxResult.value : null;
86
+ // If there's a topic in the transcript, recall for it too
87
+ let topicRecall = null;
88
+ if (topic) {
89
+ try {
90
+ topicRecall = await client.recall({ query: topic, limit: 10, detail_level: "abstract", });
91
+ markRecallDone(topic);
92
+ }
93
+ catch {
94
+ // Topic recall is optional, continue without it
95
+ }
96
+ }
97
+ // Format the combined output
98
+ const context = formatSessionStart(briefing, directives, topicRecall, topic, sandboxState);
99
+ return {
100
+ success: true,
101
+ additionalContext: context,
102
+ };
103
+ }
104
+ catch (error) {
105
+ return {
106
+ success: false,
107
+ error: `SessionStart handler error: ${error instanceof Error ? error.message : error}`,
108
+ };
109
+ }
110
+ }
111
+ //# sourceMappingURL=session-start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../../../src/hooks/handlers/session-start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Stop hook handler
3
+ * Commits session and persists working memory at session end
4
+ */
5
+ import type { HookOutput } from "../types.js";
6
+ /**
7
+ * Handle Stop event -- commit and end the server session.
8
+ *
9
+ * Stop hooks cannot inject additional context (Claude Code is shutting down),
10
+ * so this handler performs side effects only: committing working memory
11
+ * to long-term storage and ending the server session.
12
+ */
13
+ export declare function handleStop(): Promise<HookOutput>;
14
+ //# sourceMappingURL=stop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../../../src/hooks/handlers/stop.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C;;;;;;GAMG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CAqCtD"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Stop hook handler
3
+ * Commits session and persists working memory at session end
4
+ */
5
+ import { getClient, checkHealth } from "../client.js";
6
+ /**
7
+ * Handle Stop event -- commit and end the server session.
8
+ *
9
+ * Stop hooks cannot inject additional context (Claude Code is shutting down),
10
+ * so this handler performs side effects only: committing working memory
11
+ * to long-term storage and ending the server session.
12
+ */
13
+ export async function handleStop() {
14
+ const healthy = await checkHealth();
15
+ if (!healthy) {
16
+ return { success: true };
17
+ }
18
+ // getClient() syncs session ID from env/hook-state via resolveSessionId
19
+ const client = getClient();
20
+ const sessionId = client.getSessionId();
21
+ if (!sessionId) {
22
+ console.error("[stop] no session ID available, skipping commit/end");
23
+ return { success: true };
24
+ }
25
+ try {
26
+ // Commit working memory to long-term storage
27
+ try {
28
+ await client.commitSession(sessionId, { importance_threshold: 0.5 });
29
+ }
30
+ catch {
31
+ // Commit may fail if session expired or not supported
32
+ }
33
+ // End the server session
34
+ try {
35
+ await client.endSession(sessionId, {
36
+ commit: true,
37
+ importance_threshold: 0.5,
38
+ });
39
+ }
40
+ catch {
41
+ // Session may already be ended
42
+ }
43
+ }
44
+ catch {
45
+ // Best-effort -- don't fail the hook on shutdown
46
+ }
47
+ return { success: true };
48
+ }
49
+ //# sourceMappingURL=stop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../../../../src/hooks/handlers/stop.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;IACpC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,wEAAwE;IACxE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IACxC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC;QAEH,6CAA6C;QAC7C,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC;YACP,sDAAsD;QACxD,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE;gBACjC,MAAM,EAAE,IAAI;gBACZ,oBAAoB,EAAE,GAAG;aAC1B,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;QACjC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;IACnD,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * UserPromptSubmit hook handler
3
+ * Detects patterns in user prompts and provides recall guidance
4
+ */
5
+ import type { HookInput, HookOutput } from "../types.js";
6
+ /**
7
+ * Handle UserPromptSubmit event
8
+ */
9
+ export declare function handleUserPromptSubmit(input: HookInput): Promise<HookOutput>;
10
+ //# sourceMappingURL=user-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-prompt.d.ts","sourceRoot":"","sources":["../../../../src/hooks/handlers/user-prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAE,UAAU,EAAC,MAAM,aAAa,CAAC;AAgEvD;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CA0DlF"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * UserPromptSubmit hook handler
3
+ * Detects patterns in user prompts and provides recall guidance
4
+ */
5
+ import { getClient, checkHealth } from "../client.js";
6
+ import { formatRecallResult } from "../formatters.js";
7
+ import { wasRecallDoneThisTurn, markRecallDone, setCurrentTopic, setCurrentPrompt } from "../state.js";
8
+ /** Pattern categories and their recall queries */
9
+ const PATTERNS = {
10
+ preference: {
11
+ regex: /\b(which\s+\w+\s+should|should\s+we\s+use|what\s+do\s+we\s+use|how\s+do\s+we|what'?s\s+our|preferred|convention|do\s+we\s+have\s+a|what'?s\s+the\s+(default|standard|preferred))\b/i,
12
+ queries: ["directive", "preference", "convention"],
13
+ },
14
+ recall: {
15
+ regex: /\b(remember|recall|what did we|how did we|remind me|what was the|what were the|what do you (know|remember))\b/i,
16
+ queries: ["context", "history", "decision"],
17
+ },
18
+ analysis: {
19
+ regex: /\b(review|assess|analyze|evaluate|audit|investigate|explore|research|compare|status|state of|readiness|gap analysis)\b/i,
20
+ queries: ["status", "assessment", "gaps", "problems"],
21
+ },
22
+ implementation: {
23
+ regex: /\b(implement|build|create|add|fix|refactor|update|change|modify)\b/i,
24
+ queries: ["patterns", "solutions", "issues"],
25
+ },
26
+ error: {
27
+ regex: /\b(error|bug|issue|broken|failing|crash|exception|doesn't work|not working)\b/i,
28
+ queries: ["fix", "error", "solution"],
29
+ },
30
+ };
31
+ /**
32
+ * Detect which pattern category matches the prompt
33
+ */
34
+ function detectPattern(prompt) {
35
+ for (const [category, config] of Object.entries(PATTERNS)) {
36
+ if (config.regex.test(prompt)) {
37
+ return category;
38
+ }
39
+ }
40
+ return null;
41
+ }
42
+ /**
43
+ * Extract key terms from the prompt for recall query
44
+ */
45
+ function extractKeyTerms(prompt) {
46
+ // Remove common words and extract meaningful terms
47
+ const stopWords = new Set([
48
+ "the", "a", "an", "is", "are", "was", "were", "be", "been",
49
+ "have", "has", "had", "do", "does", "did", "will", "would",
50
+ "could", "should", "may", "might", "must", "can", "this",
51
+ "that", "these", "those", "i", "you", "we", "they", "it",
52
+ "my", "your", "our", "their", "its", "please", "help", "me",
53
+ "want", "need", "like", "to", "for", "with", "on", "in", "at",
54
+ ]);
55
+ const words = prompt.toLowerCase()
56
+ .replace(/[^\w\s]/g, " ")
57
+ .split(/\s+/)
58
+ .filter(w => w.length > 2 && !stopWords.has(w));
59
+ // Take first 5 meaningful words
60
+ return words.slice(0, 5).join(" ");
61
+ }
62
+ /**
63
+ * Handle UserPromptSubmit event
64
+ */
65
+ export async function handleUserPromptSubmit(input) {
66
+ const prompt = input.user_prompt;
67
+ if (!prompt) {
68
+ return { success: true };
69
+ }
70
+ // Persist the user's prompt for intent detection in PostToolUse
71
+ setCurrentPrompt(prompt);
72
+ // Skip if recall was already done this turn
73
+ if (wasRecallDoneThisTurn()) {
74
+ return { success: true };
75
+ }
76
+ // Check server health
77
+ const healthy = await checkHealth();
78
+ if (!healthy) {
79
+ return { success: true };
80
+ }
81
+ // Store the user's topic for cross-hook context (Edit/Write recall)
82
+ const keyTerms = extractKeyTerms(prompt);
83
+ if (keyTerms) {
84
+ setCurrentTopic(keyTerms);
85
+ }
86
+ // Detect pattern category
87
+ const pattern = detectPattern(prompt);
88
+ if (!pattern) {
89
+ return { success: true };
90
+ }
91
+ try {
92
+ // Build recall query from prompt + pattern-specific terms
93
+ const patternQueries = PATTERNS[pattern].queries;
94
+ const query = `${keyTerms} ${patternQueries[0]}`.trim();
95
+ // Perform recall using the same client as MCP tools
96
+ const client = getClient();
97
+ const result = await client.recall({ query, limit: 10 });
98
+ markRecallDone(query);
99
+ if (result.memories.length === 0) {
100
+ return { success: true };
101
+ }
102
+ // Format guidance based on pattern
103
+ const guidance = getPatternGuidance(pattern);
104
+ const recallOutput = formatRecallResult(result, query);
105
+ return {
106
+ success: true,
107
+ additionalContext: `${guidance}\n\n${recallOutput}`,
108
+ };
109
+ }
110
+ catch {
111
+ // Don't fail the hook on recall errors
112
+ return { success: true };
113
+ }
114
+ }
115
+ /**
116
+ * Get guidance text for each pattern type
117
+ */
118
+ function getPatternGuidance(pattern) {
119
+ const guidance = {
120
+ preference: "This is a preference/convention question. Relevant directives and decisions found:",
121
+ recall: "Recalled memories matching this request:",
122
+ analysis: "This request involves analysis/research. Relevant prior context found:",
123
+ implementation: "This request involves implementation. Relevant patterns/solutions found:",
124
+ error: "This request mentions an error/bug. Relevant prior fixes found:",
125
+ };
126
+ return guidance[pattern] || "Relevant memories found:";
127
+ }
128
+ //# sourceMappingURL=user-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-prompt.js","sourceRoot":"","sources":["../../../../src/hooks/handlers/user-prompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * MemoryLayer Claude Code hooks
3
+ *
4
+ * This module provides TypeScript-based hooks for Claude Code integration.
5
+ * Hooks inject memory context into Claude's processing at key points,
6
+ * using the same MemoryLayerClient as the MCP tools.
7
+ */
8
+ export { HookEvent, type HookInput, type HookOutput, type TranscriptMessage, type HookState, } from "./types.js";
9
+ export { readHookState, writeHookState, markRecallDone, wasRecallDoneThisTurn, resetRecallStatus, updateSessionInfo, getWorkspaceId, getSessionIdFromHookState, resolveSessionId, getCheckpointBoundary, acknowledgeCheckpointBoundary, } from "./state.js";
10
+ export { getClient, checkHealth, } from "./client.js";
11
+ export { formatRecallResult, formatBriefing, formatDirectives, formatSessionStart, formatSandboxState, formatStorageGuidance, } from "./formatters.js";
12
+ export { handleSessionStart } from "./handlers/session-start.js";
13
+ export { handleUserPromptSubmit } from "./handlers/user-prompt.js";
14
+ export { handlePreToolUse } from "./handlers/pre-tool.js";
15
+ export { handlePostToolUse } from "./handlers/post-tool.js";
16
+ export { handleStop } from "./handlers/stop.js";
17
+ export { handlePreCompact } from "./handlers/pre-compact.js";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,SAAS,EACT,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,SAAS,GACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,yBAAyB,EACzB,gBAAgB,EAChB,qBAAqB,EACrB,6BAA6B,GAC9B,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,SAAS,EACT,WAAW,GACZ,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * MemoryLayer Claude Code hooks
3
+ *
4
+ * This module provides TypeScript-based hooks for Claude Code integration.
5
+ * Hooks inject memory context into Claude's processing at key points,
6
+ * using the same MemoryLayerClient as the MCP tools.
7
+ */
8
+ // Types
9
+ export { HookEvent, } from "./types.js";
10
+ // State management
11
+ export { readHookState, writeHookState, markRecallDone, wasRecallDoneThisTurn, resetRecallStatus, updateSessionInfo, getWorkspaceId, getSessionIdFromHookState, resolveSessionId, getCheckpointBoundary, acknowledgeCheckpointBoundary, } from "./state.js";
12
+ // Client (same MemoryLayerClient used by MCP tools)
13
+ export { getClient, checkHealth, } from "./client.js";
14
+ // Formatters
15
+ export { formatRecallResult, formatBriefing, formatDirectives, formatSessionStart, formatSandboxState, formatStorageGuidance, } from "./formatters.js";
16
+ // Handlers
17
+ export { handleSessionStart } from "./handlers/session-start.js";
18
+ export { handleUserPromptSubmit } from "./handlers/user-prompt.js";
19
+ export { handlePreToolUse } from "./handlers/pre-tool.js";
20
+ export { handlePostToolUse } from "./handlers/post-tool.js";
21
+ export { handleStop } from "./handlers/stop.js";
22
+ export { handlePreCompact } from "./handlers/pre-compact.js";
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,QAAQ;AACR,OAAO,EACL,SAAS,GAKV,MAAM,YAAY,CAAC;AAEpB,mBAAmB;AACnB,OAAO,EACL,aAAa,EACb,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,yBAAyB,EACzB,gBAAgB,EAChB,qBAAqB,EACrB,6BAA6B,GAC9B,MAAM,YAAY,CAAC;AAEpB,oDAAoD;AACpD,OAAO,EACL,SAAS,EACT,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,aAAa;AACb,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,WAAW;AACX,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Observation extraction for auto-capture hooks.
3
+ * Extracts structured observation data from tool usage.
4
+ */
5
+ import type { HookInput } from './types.js';
6
+ export declare function shouldSkipTool(toolName: string): boolean;
7
+ export type ObservationType = 'read' | 'write' | 'execute' | 'search' | 'other';
8
+ export interface ObservationData {
9
+ type: ObservationType;
10
+ title: string;
11
+ toolName: string;
12
+ filesRead: string[];
13
+ filesModified: string[];
14
+ facts: string[];
15
+ concepts: string[];
16
+ intent: string | null;
17
+ contentHash: string;
18
+ summary: string;
19
+ }
20
+ /**
21
+ * Classify tool as read/write/execute/search/other
22
+ */
23
+ export declare function getObservationType(toolName: string): ObservationType;
24
+ /**
25
+ * Extract file paths from tool input, classified as read or modified
26
+ */
27
+ export declare function extractFilePaths(toolName: string, toolInput: unknown): {
28
+ filesRead: string[];
29
+ filesModified: string[];
30
+ };
31
+ /**
32
+ * Generate observation title from tool usage
33
+ */
34
+ export declare function generateTitle(toolName: string, toolInput: unknown): string;
35
+ /**
36
+ * Extract facts from tool input/response
37
+ */
38
+ export declare function extractFacts(toolName: string, toolInput: unknown, toolOutput?: string): string[];
39
+ /**
40
+ * Extract concepts/topics from tool usage
41
+ */
42
+ export declare function extractConcepts(toolName: string, toolInput: unknown): string[];
43
+ /**
44
+ * Detect intent from tool usage and user prompt
45
+ */
46
+ export declare function detectIntent(toolName: string, toolInput: unknown, prompt?: string): string | null;
47
+ /**
48
+ * Compute content hash for deduplication
49
+ */
50
+ export declare function computeContentHash(...parts: string[]): string;
51
+ /**
52
+ * Truncate string to max length
53
+ */
54
+ export declare function truncate(str: string, maxLen?: number): string;
55
+ /**
56
+ * Build observation from hook input
57
+ */
58
+ export declare function buildObservation(input: HookInput, currentPrompt?: string): ObservationData | null;
59
+ //# sourceMappingURL=observation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../../../src/hooks/observation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAiB5C,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGxD;AAGD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEhF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAWpE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CA+BvH;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAgC1E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAuDhG;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,EAAE,CAgG9E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8CjG;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAK7D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAY,GAAG,MAAM,CAGlE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAuCjG"}