@fingerskier/augment 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/README.md +494 -450
- package/dist/cli.js +5 -4
- package/dist/cli.js.map +1 -1
- package/dist/daemon/client.d.ts +6 -0
- package/dist/daemon/client.js +19 -0
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/http.js +79 -9
- package/dist/daemon/http.js.map +1 -1
- package/dist/daemon/lifetime-lock.js +12 -12
- package/dist/db.js +107 -107
- package/dist/decoction.d.ts +51 -0
- package/dist/decoction.js +184 -0
- package/dist/decoction.js.map +1 -0
- package/dist/hooks.d.ts +8 -5
- package/dist/hooks.js +49 -20
- package/dist/hooks.js.map +1 -1
- package/dist/install.d.ts +14 -2
- package/dist/install.js +189 -1
- package/dist/install.js.map +1 -1
- package/dist/mcp/apps.js +480 -480
- package/dist/mcp/server.js +83 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/memory/files.js +21 -2
- package/dist/memory/files.js.map +1 -1
- package/dist/memory/project.d.ts +3 -0
- package/dist/memory/project.js +20 -0
- package/dist/memory/project.js.map +1 -1
- package/dist/pi/extension.d.ts +6 -0
- package/dist/pi/extension.js +74 -20
- package/dist/pi/extension.js.map +1 -1
- package/dist/proposals.js +16 -15
- package/dist/proposals.js.map +1 -1
- package/dist/service.d.ts +134 -2
- package/dist/service.js +578 -51
- package/dist/service.js.map +1 -1
- package/docs/FEATURES.md +771 -615
- package/docs/verify-memory-flow.md +4 -3
- package/integrations/claude/skills/augment-context/SKILL.md +74 -74
- package/integrations/claude/skills/augment-decoction/SKILL.md +36 -0
- package/integrations/claude/skills/augment-dream/SKILL.md +34 -0
- package/integrations/claude/skills/augment-dream/agents/openai.yaml +4 -0
- package/integrations/claude/skills/augment-sleep/SKILL.md +26 -26
- package/integrations/codex/SKILL.md +107 -74
- package/integrations/examples/claude-mcp-config.json +17 -17
- package/integrations/examples/codex-mcp-config.json +17 -17
- package/integrations/examples/grok-mcp-config.toml +18 -0
- package/integrations/grok/AGENTS.md +61 -0
- package/integrations/pi/skills/augment-decoction/SKILL.md +37 -0
- package/integrations/pi/skills/augment-dream/SKILL.md +36 -0
- package/package.json +85 -84
- package/dist/tally.d.ts +0 -46
- package/dist/tally.js +0 -94
- package/dist/tally.js.map +0 -1
package/dist/db.js
CHANGED
|
@@ -31,51 +31,51 @@ export class AugmentDatabase {
|
|
|
31
31
|
await this.execute(`PRAGMA busy_timeout = 5000`);
|
|
32
32
|
await this.execute(`PRAGMA foreign_keys = ON`);
|
|
33
33
|
await this.batch([
|
|
34
|
-
`CREATE TABLE IF NOT EXISTS projects (
|
|
35
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
36
|
-
name TEXT NOT NULL UNIQUE,
|
|
37
|
-
org TEXT NOT NULL,
|
|
38
|
-
repo TEXT NOT NULL,
|
|
39
|
-
source TEXT NOT NULL,
|
|
40
|
-
created_at TEXT NOT NULL,
|
|
41
|
-
updated_at TEXT NOT NULL
|
|
34
|
+
`CREATE TABLE IF NOT EXISTS projects (
|
|
35
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
36
|
+
name TEXT NOT NULL UNIQUE,
|
|
37
|
+
org TEXT NOT NULL,
|
|
38
|
+
repo TEXT NOT NULL,
|
|
39
|
+
source TEXT NOT NULL,
|
|
40
|
+
created_at TEXT NOT NULL,
|
|
41
|
+
updated_at TEXT NOT NULL
|
|
42
42
|
)`,
|
|
43
|
-
`CREATE TABLE IF NOT EXISTS memories (
|
|
44
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
45
|
-
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
46
|
-
kind TEXT NOT NULL,
|
|
47
|
-
name TEXT NOT NULL,
|
|
48
|
-
relative_path TEXT NOT NULL UNIQUE,
|
|
49
|
-
content_hash TEXT NOT NULL,
|
|
50
|
-
frontmatter_hash TEXT NOT NULL,
|
|
51
|
-
size INTEGER NOT NULL,
|
|
52
|
-
density REAL NOT NULL,
|
|
53
|
-
mtime REAL NOT NULL,
|
|
54
|
-
tags_json TEXT NOT NULL,
|
|
55
|
-
links_json TEXT NOT NULL,
|
|
56
|
-
body TEXT NOT NULL,
|
|
57
|
-
created_at TEXT NOT NULL,
|
|
58
|
-
updated_at TEXT NOT NULL,
|
|
59
|
-
archived INTEGER NOT NULL DEFAULT 0,
|
|
60
|
-
consolidated_into TEXT,
|
|
61
|
-
derived_from_json TEXT
|
|
43
|
+
`CREATE TABLE IF NOT EXISTS memories (
|
|
44
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
45
|
+
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
46
|
+
kind TEXT NOT NULL,
|
|
47
|
+
name TEXT NOT NULL,
|
|
48
|
+
relative_path TEXT NOT NULL UNIQUE,
|
|
49
|
+
content_hash TEXT NOT NULL,
|
|
50
|
+
frontmatter_hash TEXT NOT NULL,
|
|
51
|
+
size INTEGER NOT NULL,
|
|
52
|
+
density REAL NOT NULL,
|
|
53
|
+
mtime REAL NOT NULL,
|
|
54
|
+
tags_json TEXT NOT NULL,
|
|
55
|
+
links_json TEXT NOT NULL,
|
|
56
|
+
body TEXT NOT NULL,
|
|
57
|
+
created_at TEXT NOT NULL,
|
|
58
|
+
updated_at TEXT NOT NULL,
|
|
59
|
+
archived INTEGER NOT NULL DEFAULT 0,
|
|
60
|
+
consolidated_into TEXT,
|
|
61
|
+
derived_from_json TEXT
|
|
62
62
|
)`,
|
|
63
|
-
`CREATE TABLE IF NOT EXISTS memory_embeddings (
|
|
64
|
-
memory_id INTEGER PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
|
|
65
|
-
model_id TEXT NOT NULL,
|
|
66
|
-
model_version TEXT NOT NULL,
|
|
67
|
-
dimensions INTEGER NOT NULL,
|
|
68
|
-
vector_json TEXT NOT NULL,
|
|
69
|
-
embedded_hash TEXT NOT NULL,
|
|
70
|
-
embedded_at TEXT NOT NULL
|
|
63
|
+
`CREATE TABLE IF NOT EXISTS memory_embeddings (
|
|
64
|
+
memory_id INTEGER PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
|
|
65
|
+
model_id TEXT NOT NULL,
|
|
66
|
+
model_version TEXT NOT NULL,
|
|
67
|
+
dimensions INTEGER NOT NULL,
|
|
68
|
+
vector_json TEXT NOT NULL,
|
|
69
|
+
embedded_hash TEXT NOT NULL,
|
|
70
|
+
embedded_at TEXT NOT NULL
|
|
71
71
|
)`,
|
|
72
|
-
`CREATE TABLE IF NOT EXISTS links (
|
|
73
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
74
|
-
from_memory_id INTEGER NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
75
|
-
to_memory_id INTEGER NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
76
|
-
type TEXT NOT NULL,
|
|
77
|
-
created_at TEXT NOT NULL,
|
|
78
|
-
UNIQUE(from_memory_id, to_memory_id, type)
|
|
72
|
+
`CREATE TABLE IF NOT EXISTS links (
|
|
73
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
74
|
+
from_memory_id INTEGER NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
75
|
+
to_memory_id INTEGER NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
76
|
+
type TEXT NOT NULL,
|
|
77
|
+
created_at TEXT NOT NULL,
|
|
78
|
+
UNIQUE(from_memory_id, to_memory_id, type)
|
|
79
79
|
)`,
|
|
80
80
|
`CREATE INDEX IF NOT EXISTS idx_memories_project_id ON memories(project_id)`,
|
|
81
81
|
`CREATE INDEX IF NOT EXISTS idx_memories_kind ON memories(kind)`,
|
|
@@ -118,12 +118,12 @@ export class AugmentDatabase {
|
|
|
118
118
|
async upsertProject(name, source = "git") {
|
|
119
119
|
const parts = projectParts(name);
|
|
120
120
|
const now = new Date().toISOString();
|
|
121
|
-
await this.execute(`INSERT INTO projects (name, org, repo, source, created_at, updated_at)
|
|
122
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
123
|
-
ON CONFLICT(name) DO UPDATE SET
|
|
124
|
-
org = excluded.org,
|
|
125
|
-
repo = excluded.repo,
|
|
126
|
-
source = excluded.source,
|
|
121
|
+
await this.execute(`INSERT INTO projects (name, org, repo, source, created_at, updated_at)
|
|
122
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
123
|
+
ON CONFLICT(name) DO UPDATE SET
|
|
124
|
+
org = excluded.org,
|
|
125
|
+
repo = excluded.repo,
|
|
126
|
+
source = excluded.source,
|
|
127
127
|
updated_at = excluded.updated_at`, [name, parts.org, parts.repo, source, now, now]);
|
|
128
128
|
const project = await this.getProjectByName(name);
|
|
129
129
|
if (!project) {
|
|
@@ -148,27 +148,27 @@ export class AugmentDatabase {
|
|
|
148
148
|
async upsertMemory(memory) {
|
|
149
149
|
const project = await this.upsertProject(memory.frontmatter.project);
|
|
150
150
|
const now = new Date().toISOString();
|
|
151
|
-
await this.execute(`INSERT INTO memories (
|
|
152
|
-
project_id, kind, name, relative_path, content_hash, frontmatter_hash,
|
|
153
|
-
size, density, mtime, tags_json, links_json, body, created_at, updated_at,
|
|
154
|
-
archived, consolidated_into, derived_from_json
|
|
155
|
-
)
|
|
156
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
157
|
-
ON CONFLICT(relative_path) DO UPDATE SET
|
|
158
|
-
project_id = excluded.project_id,
|
|
159
|
-
kind = excluded.kind,
|
|
160
|
-
name = excluded.name,
|
|
161
|
-
content_hash = excluded.content_hash,
|
|
162
|
-
frontmatter_hash = excluded.frontmatter_hash,
|
|
163
|
-
size = excluded.size,
|
|
164
|
-
density = excluded.density,
|
|
165
|
-
mtime = excluded.mtime,
|
|
166
|
-
tags_json = excluded.tags_json,
|
|
167
|
-
links_json = excluded.links_json,
|
|
168
|
-
body = excluded.body,
|
|
169
|
-
updated_at = excluded.updated_at,
|
|
170
|
-
archived = excluded.archived,
|
|
171
|
-
consolidated_into = excluded.consolidated_into,
|
|
151
|
+
await this.execute(`INSERT INTO memories (
|
|
152
|
+
project_id, kind, name, relative_path, content_hash, frontmatter_hash,
|
|
153
|
+
size, density, mtime, tags_json, links_json, body, created_at, updated_at,
|
|
154
|
+
archived, consolidated_into, derived_from_json
|
|
155
|
+
)
|
|
156
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
157
|
+
ON CONFLICT(relative_path) DO UPDATE SET
|
|
158
|
+
project_id = excluded.project_id,
|
|
159
|
+
kind = excluded.kind,
|
|
160
|
+
name = excluded.name,
|
|
161
|
+
content_hash = excluded.content_hash,
|
|
162
|
+
frontmatter_hash = excluded.frontmatter_hash,
|
|
163
|
+
size = excluded.size,
|
|
164
|
+
density = excluded.density,
|
|
165
|
+
mtime = excluded.mtime,
|
|
166
|
+
tags_json = excluded.tags_json,
|
|
167
|
+
links_json = excluded.links_json,
|
|
168
|
+
body = excluded.body,
|
|
169
|
+
updated_at = excluded.updated_at,
|
|
170
|
+
archived = excluded.archived,
|
|
171
|
+
consolidated_into = excluded.consolidated_into,
|
|
172
172
|
derived_from_json = excluded.derived_from_json`, [
|
|
173
173
|
project.id,
|
|
174
174
|
memory.frontmatter.kind,
|
|
@@ -230,7 +230,7 @@ export class AugmentDatabase {
|
|
|
230
230
|
continue;
|
|
231
231
|
}
|
|
232
232
|
statements.push({
|
|
233
|
-
sql: `INSERT OR IGNORE INTO links (from_memory_id, to_memory_id, type, created_at)
|
|
233
|
+
sql: `INSERT OR IGNORE INTO links (from_memory_id, to_memory_id, type, created_at)
|
|
234
234
|
VALUES (?, ?, ?, ?)`,
|
|
235
235
|
args: [memory.id, target.id, link.type, now],
|
|
236
236
|
});
|
|
@@ -257,36 +257,36 @@ export class AugmentDatabase {
|
|
|
257
257
|
return result.rows.map((row) => memoryFromRow(row));
|
|
258
258
|
}
|
|
259
259
|
async listLinks(memoryId) {
|
|
260
|
-
const result = await this.execute(`SELECT
|
|
261
|
-
links.*,
|
|
262
|
-
from_memory.relative_path AS from_relative_path,
|
|
263
|
-
to_memory.relative_path AS to_relative_path
|
|
264
|
-
FROM links
|
|
265
|
-
JOIN memories AS from_memory ON from_memory.id = links.from_memory_id
|
|
266
|
-
JOIN memories AS to_memory ON to_memory.id = links.to_memory_id
|
|
267
|
-
WHERE links.from_memory_id = ? OR links.to_memory_id = ?
|
|
260
|
+
const result = await this.execute(`SELECT
|
|
261
|
+
links.*,
|
|
262
|
+
from_memory.relative_path AS from_relative_path,
|
|
263
|
+
to_memory.relative_path AS to_relative_path
|
|
264
|
+
FROM links
|
|
265
|
+
JOIN memories AS from_memory ON from_memory.id = links.from_memory_id
|
|
266
|
+
JOIN memories AS to_memory ON to_memory.id = links.to_memory_id
|
|
267
|
+
WHERE links.from_memory_id = ? OR links.to_memory_id = ?
|
|
268
268
|
ORDER BY links.id`, [memoryId, memoryId]);
|
|
269
269
|
return result.rows.map((row) => linkFromRow(row));
|
|
270
270
|
}
|
|
271
271
|
async getLinkById(id) {
|
|
272
|
-
const result = await this.execute(`SELECT
|
|
273
|
-
links.*,
|
|
274
|
-
from_memory.relative_path AS from_relative_path,
|
|
275
|
-
to_memory.relative_path AS to_relative_path
|
|
276
|
-
FROM links
|
|
277
|
-
JOIN memories AS from_memory ON from_memory.id = links.from_memory_id
|
|
278
|
-
JOIN memories AS to_memory ON to_memory.id = links.to_memory_id
|
|
272
|
+
const result = await this.execute(`SELECT
|
|
273
|
+
links.*,
|
|
274
|
+
from_memory.relative_path AS from_relative_path,
|
|
275
|
+
to_memory.relative_path AS to_relative_path
|
|
276
|
+
FROM links
|
|
277
|
+
JOIN memories AS from_memory ON from_memory.id = links.from_memory_id
|
|
278
|
+
JOIN memories AS to_memory ON to_memory.id = links.to_memory_id
|
|
279
279
|
WHERE links.id = ?`, [id]);
|
|
280
280
|
return result.rows[0] ? linkFromRow(result.rows[0]) : undefined;
|
|
281
281
|
}
|
|
282
282
|
async getAllLinks() {
|
|
283
|
-
const result = await this.execute(`SELECT
|
|
284
|
-
links.*,
|
|
285
|
-
from_memory.relative_path AS from_relative_path,
|
|
286
|
-
to_memory.relative_path AS to_relative_path
|
|
287
|
-
FROM links
|
|
288
|
-
JOIN memories AS from_memory ON from_memory.id = links.from_memory_id
|
|
289
|
-
JOIN memories AS to_memory ON to_memory.id = links.to_memory_id
|
|
283
|
+
const result = await this.execute(`SELECT
|
|
284
|
+
links.*,
|
|
285
|
+
from_memory.relative_path AS from_relative_path,
|
|
286
|
+
to_memory.relative_path AS to_relative_path
|
|
287
|
+
FROM links
|
|
288
|
+
JOIN memories AS from_memory ON from_memory.id = links.from_memory_id
|
|
289
|
+
JOIN memories AS to_memory ON to_memory.id = links.to_memory_id
|
|
290
290
|
ORDER BY links.id`);
|
|
291
291
|
return result.rows.map((row) => linkFromRow(row));
|
|
292
292
|
}
|
|
@@ -312,16 +312,16 @@ export class AugmentDatabase {
|
|
|
312
312
|
if (!record) {
|
|
313
313
|
throw new Error(`Cannot store embedding for missing memory`);
|
|
314
314
|
}
|
|
315
|
-
await this.execute(`INSERT INTO memory_embeddings (
|
|
316
|
-
memory_id, model_id, model_version, dimensions, vector_json, embedded_hash, embedded_at
|
|
317
|
-
)
|
|
318
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
319
|
-
ON CONFLICT(memory_id) DO UPDATE SET
|
|
320
|
-
model_id = excluded.model_id,
|
|
321
|
-
model_version = excluded.model_version,
|
|
322
|
-
dimensions = excluded.dimensions,
|
|
323
|
-
vector_json = excluded.vector_json,
|
|
324
|
-
embedded_hash = excluded.embedded_hash,
|
|
315
|
+
await this.execute(`INSERT INTO memory_embeddings (
|
|
316
|
+
memory_id, model_id, model_version, dimensions, vector_json, embedded_hash, embedded_at
|
|
317
|
+
)
|
|
318
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
319
|
+
ON CONFLICT(memory_id) DO UPDATE SET
|
|
320
|
+
model_id = excluded.model_id,
|
|
321
|
+
model_version = excluded.model_version,
|
|
322
|
+
dimensions = excluded.dimensions,
|
|
323
|
+
vector_json = excluded.vector_json,
|
|
324
|
+
embedded_hash = excluded.embedded_hash,
|
|
325
325
|
embedded_at = excluded.embedded_at`, [
|
|
326
326
|
record.id,
|
|
327
327
|
provider.modelId,
|
|
@@ -405,11 +405,11 @@ export class AugmentDatabase {
|
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
407
|
function memorySelectSql(suffix) {
|
|
408
|
-
return `SELECT
|
|
409
|
-
memories.*,
|
|
410
|
-
projects.name AS project_name
|
|
411
|
-
FROM memories
|
|
412
|
-
JOIN projects ON projects.id = memories.project_id
|
|
408
|
+
return `SELECT
|
|
409
|
+
memories.*,
|
|
410
|
+
projects.name AS project_name
|
|
411
|
+
FROM memories
|
|
412
|
+
JOIN projects ON projects.id = memories.project_id
|
|
413
413
|
${suffix}`;
|
|
414
414
|
}
|
|
415
415
|
function projectFromRow(row) {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { MemoryKind } from "./constants.js";
|
|
2
|
+
import type { MemoryRecord } from "./types.js";
|
|
3
|
+
export declare const DECOCTION_DEFAULT_MIN_COSINE = 0.75;
|
|
4
|
+
export declare const DECOCTION_MIN_PROJECTS = 4;
|
|
5
|
+
export declare const DECOCTION_DEFAULT_SNIPPET_CHARS = 280;
|
|
6
|
+
/** The corpus fields needed by read-only decoction discovery. */
|
|
7
|
+
export type DecoctionDiscoveryMemory = Pick<MemoryRecord, "id" | "project_name" | "kind" | "relative_path" | "content_hash" | "frontmatter_hash" | "tags" | "body" | "archived">;
|
|
8
|
+
/** Matches the memories + embeddings portion of AugmentService's corpus snapshot. */
|
|
9
|
+
export interface DecoctionDiscoveryInput {
|
|
10
|
+
memories: readonly DecoctionDiscoveryMemory[];
|
|
11
|
+
embeddings: ReadonlyMap<number, number[]>;
|
|
12
|
+
/** Raw cosine floor used for every pair in a cluster. */
|
|
13
|
+
minCosine?: number;
|
|
14
|
+
/** Maximum normalized body characters returned per source. */
|
|
15
|
+
snippetChars?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface DecoctionDiscoverySource {
|
|
18
|
+
id: number;
|
|
19
|
+
/** Durable identity; numeric ids can churn during an index rebuild. */
|
|
20
|
+
relative_path: string;
|
|
21
|
+
project_name: string;
|
|
22
|
+
kind: MemoryKind;
|
|
23
|
+
content_hash: string;
|
|
24
|
+
frontmatter_hash: string;
|
|
25
|
+
snippet: string;
|
|
26
|
+
}
|
|
27
|
+
export interface DecoctionDiscoveryCluster {
|
|
28
|
+
sources: DecoctionDiscoverySource[];
|
|
29
|
+
distinct_projects: number;
|
|
30
|
+
project_names: string[];
|
|
31
|
+
/** Lowest raw cosine among every pair of sources in this complete-link cluster. */
|
|
32
|
+
min_pairwise_cosine: number;
|
|
33
|
+
}
|
|
34
|
+
export interface DecoctionDiscoveryOutput {
|
|
35
|
+
/** Policy-eligible memories, including any that currently lack an embedding. */
|
|
36
|
+
eligible: number;
|
|
37
|
+
/** Eligible memories that have an embedding and therefore entered clustering. */
|
|
38
|
+
embedded: number;
|
|
39
|
+
min_cosine: number;
|
|
40
|
+
min_projects: typeof DECOCTION_MIN_PROJECTS;
|
|
41
|
+
clusters: DecoctionDiscoveryCluster[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Find cross-project evidence groups without mutating the corpus.
|
|
45
|
+
*
|
|
46
|
+
* This is agglomerative complete-link clustering: two groups can merge only
|
|
47
|
+
* when every cross-group source pair meets the raw cosine floor. In contrast
|
|
48
|
+
* to connected components, a chain of individually similar neighbors cannot
|
|
49
|
+
* pull dissimilar endpoints into the same generic-memory candidate.
|
|
50
|
+
*/
|
|
51
|
+
export declare function discoverDecoctionCandidates(input: DecoctionDiscoveryInput): DecoctionDiscoveryOutput;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { cosineSimilarity } from "./util/text.js";
|
|
2
|
+
export const DECOCTION_DEFAULT_MIN_COSINE = 0.75;
|
|
3
|
+
export const DECOCTION_MIN_PROJECTS = 4;
|
|
4
|
+
export const DECOCTION_DEFAULT_SNIPPET_CHARS = 280;
|
|
5
|
+
const EVIDENCE_KINDS = new Set(["WORK", "ISSUE", "SPEC", "ARCH"]);
|
|
6
|
+
const EXCLUDED_TAGS = new Set(["private", "no-generalize"]);
|
|
7
|
+
/**
|
|
8
|
+
* Find cross-project evidence groups without mutating the corpus.
|
|
9
|
+
*
|
|
10
|
+
* This is agglomerative complete-link clustering: two groups can merge only
|
|
11
|
+
* when every cross-group source pair meets the raw cosine floor. In contrast
|
|
12
|
+
* to connected components, a chain of individually similar neighbors cannot
|
|
13
|
+
* pull dissimilar endpoints into the same generic-memory candidate.
|
|
14
|
+
*/
|
|
15
|
+
export function discoverDecoctionCandidates(input) {
|
|
16
|
+
const minCosine = input.minCosine ?? DECOCTION_DEFAULT_MIN_COSINE;
|
|
17
|
+
const snippetChars = input.snippetChars ?? DECOCTION_DEFAULT_SNIPPET_CHARS;
|
|
18
|
+
validateOptions(minCosine, snippetChars);
|
|
19
|
+
const eligible = input.memories.filter(isEligibleEvidence).sort(compareMemories);
|
|
20
|
+
const candidates = eligible.filter((memory) => input.embeddings.has(memory.id));
|
|
21
|
+
const similarities = similarityMatrix(candidates, input.embeddings);
|
|
22
|
+
const working = completeLinkClusters(candidates, similarities, minCosine);
|
|
23
|
+
const clusters = working
|
|
24
|
+
.map((cluster) => toDiscoveryCluster(cluster, candidates, similarities, snippetChars))
|
|
25
|
+
.filter((cluster) => cluster.distinct_projects >= DECOCTION_MIN_PROJECTS)
|
|
26
|
+
.sort(compareDiscoveryClusters);
|
|
27
|
+
return {
|
|
28
|
+
eligible: eligible.length,
|
|
29
|
+
embedded: candidates.length,
|
|
30
|
+
min_cosine: minCosine,
|
|
31
|
+
min_projects: DECOCTION_MIN_PROJECTS,
|
|
32
|
+
clusters,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function isEligibleEvidence(memory) {
|
|
36
|
+
if (!EVIDENCE_KINDS.has(memory.kind) || memory.archived || isGeneric(memory)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return !memory.tags.some((tag) => EXCLUDED_TAGS.has(tag.trim().toLowerCase()));
|
|
40
|
+
}
|
|
41
|
+
function isGeneric(memory) {
|
|
42
|
+
if (memory.project_name === ".generic") {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
const normalizedPath = memory.relative_path.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
46
|
+
return normalizedPath.startsWith(".generic/");
|
|
47
|
+
}
|
|
48
|
+
function similarityMatrix(candidates, embeddings) {
|
|
49
|
+
const matrix = candidates.map(() => new Array(candidates.length).fill(1));
|
|
50
|
+
for (let left = 0; left < candidates.length; left += 1) {
|
|
51
|
+
const leftVector = embeddings.get(candidates[left].id);
|
|
52
|
+
for (let right = left + 1; right < candidates.length; right += 1) {
|
|
53
|
+
const rightVector = embeddings.get(candidates[right].id);
|
|
54
|
+
const similarity = leftVector && rightVector ? boundedCosine(leftVector, rightVector) : 0;
|
|
55
|
+
matrix[left][right] = similarity;
|
|
56
|
+
matrix[right][left] = similarity;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return matrix;
|
|
60
|
+
}
|
|
61
|
+
function completeLinkClusters(candidates, similarities, minCosine) {
|
|
62
|
+
let clusters = candidates.map((memory, index) => ({
|
|
63
|
+
members: [index],
|
|
64
|
+
key: memoryKey(memory),
|
|
65
|
+
}));
|
|
66
|
+
for (;;) {
|
|
67
|
+
let best;
|
|
68
|
+
for (let left = 0; left < clusters.length; left += 1) {
|
|
69
|
+
for (let right = left + 1; right < clusters.length; right += 1) {
|
|
70
|
+
const similarity = completeLinkSimilarity(clusters[left], clusters[right], similarities, minCosine);
|
|
71
|
+
if (similarity < minCosine) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const key = mergeKey(clusters[left], clusters[right]);
|
|
75
|
+
if (!best ||
|
|
76
|
+
similarity > best.similarity ||
|
|
77
|
+
(similarity === best.similarity && compareText(key, best.key) < 0)) {
|
|
78
|
+
best = { left, right, similarity, key };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (!best) {
|
|
83
|
+
return clusters;
|
|
84
|
+
}
|
|
85
|
+
const members = [...clusters[best.left].members, ...clusters[best.right].members].sort((a, b) => a - b);
|
|
86
|
+
const merged = { members, key: best.key };
|
|
87
|
+
clusters = clusters
|
|
88
|
+
.filter((_, index) => index !== best.left && index !== best.right)
|
|
89
|
+
.concat(merged)
|
|
90
|
+
.sort((a, b) => compareText(a.key, b.key));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function completeLinkSimilarity(left, right, similarities, floor) {
|
|
94
|
+
let minimum = 1;
|
|
95
|
+
for (const leftIndex of left.members) {
|
|
96
|
+
for (const rightIndex of right.members) {
|
|
97
|
+
minimum = Math.min(minimum, similarities[leftIndex][rightIndex]);
|
|
98
|
+
// This pair can never merge. Avoid scanning the remaining cross pairs.
|
|
99
|
+
if (minimum < floor) {
|
|
100
|
+
return minimum;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return minimum;
|
|
105
|
+
}
|
|
106
|
+
function toDiscoveryCluster(cluster, candidates, similarities, snippetChars) {
|
|
107
|
+
const members = cluster.members.map((index) => candidates[index]);
|
|
108
|
+
const projectNames = [...new Set(members.map((memory) => memory.project_name))].sort(compareText);
|
|
109
|
+
const sources = members
|
|
110
|
+
.map((memory) => ({
|
|
111
|
+
id: memory.id,
|
|
112
|
+
relative_path: memory.relative_path,
|
|
113
|
+
project_name: memory.project_name,
|
|
114
|
+
kind: memory.kind,
|
|
115
|
+
content_hash: memory.content_hash,
|
|
116
|
+
frontmatter_hash: memory.frontmatter_hash,
|
|
117
|
+
snippet: snippet(memory.body, snippetChars),
|
|
118
|
+
}))
|
|
119
|
+
.sort((a, b) => compareText(a.relative_path, b.relative_path) || a.id - b.id);
|
|
120
|
+
return {
|
|
121
|
+
sources,
|
|
122
|
+
distinct_projects: projectNames.length,
|
|
123
|
+
project_names: projectNames,
|
|
124
|
+
min_pairwise_cosine: minimumPairwise(cluster.members, similarities),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function minimumPairwise(members, similarities) {
|
|
128
|
+
if (members.length < 2) {
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
let minimum = 1;
|
|
132
|
+
for (let left = 0; left < members.length; left += 1) {
|
|
133
|
+
for (let right = left + 1; right < members.length; right += 1) {
|
|
134
|
+
minimum = Math.min(minimum, similarities[members[left]][members[right]]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return minimum;
|
|
138
|
+
}
|
|
139
|
+
function compareDiscoveryClusters(left, right) {
|
|
140
|
+
return (right.distinct_projects - left.distinct_projects ||
|
|
141
|
+
right.sources.length - left.sources.length ||
|
|
142
|
+
right.min_pairwise_cosine - left.min_pairwise_cosine ||
|
|
143
|
+
compareText(clusterPathKey(left), clusterPathKey(right)));
|
|
144
|
+
}
|
|
145
|
+
function snippet(body, maxChars) {
|
|
146
|
+
const normalized = body.replace(/\s+/g, " ").trim();
|
|
147
|
+
if (normalized.length <= maxChars) {
|
|
148
|
+
return normalized;
|
|
149
|
+
}
|
|
150
|
+
if (maxChars === 0) {
|
|
151
|
+
return "";
|
|
152
|
+
}
|
|
153
|
+
if (maxChars === 1) {
|
|
154
|
+
return "…";
|
|
155
|
+
}
|
|
156
|
+
return `${normalized.slice(0, maxChars - 1).trimEnd()}…`;
|
|
157
|
+
}
|
|
158
|
+
function boundedCosine(left, right) {
|
|
159
|
+
return Math.max(-1, Math.min(1, cosineSimilarity(left, right)));
|
|
160
|
+
}
|
|
161
|
+
function compareMemories(left, right) {
|
|
162
|
+
return compareText(left.relative_path, right.relative_path) || left.id - right.id;
|
|
163
|
+
}
|
|
164
|
+
function memoryKey(memory) {
|
|
165
|
+
return `${memory.relative_path}\u0000${memory.id}`;
|
|
166
|
+
}
|
|
167
|
+
function mergeKey(left, right) {
|
|
168
|
+
return compareText(left.key, right.key) <= 0 ? `${left.key}\u0001${right.key}` : `${right.key}\u0001${left.key}`;
|
|
169
|
+
}
|
|
170
|
+
function clusterPathKey(cluster) {
|
|
171
|
+
return cluster.sources.map((source) => `${source.relative_path}\u0000${source.id}`).join("\u0001");
|
|
172
|
+
}
|
|
173
|
+
function compareText(left, right) {
|
|
174
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
175
|
+
}
|
|
176
|
+
function validateOptions(minCosine, snippetChars) {
|
|
177
|
+
if (!Number.isFinite(minCosine) || minCosine < 0 || minCosine > 1) {
|
|
178
|
+
throw new RangeError("minCosine must be a finite number between 0 and 1");
|
|
179
|
+
}
|
|
180
|
+
if (!Number.isInteger(snippetChars) || snippetChars < 0) {
|
|
181
|
+
throw new RangeError("snippetChars must be a non-negative integer");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=decoction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoction.js","sourceRoot":"","sources":["../src/decoction.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AACjD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACxC,MAAM,CAAC,MAAM,+BAA+B,GAAG,GAAG,CAAC;AAEnD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAa,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAC9E,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC;AA4D5D;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAA8B;IACxE,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,4BAA4B,CAAC;IAClE,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,+BAA+B,CAAC;IAC3E,eAAe,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAEzC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACjF,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAChF,MAAM,YAAY,GAAG,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,oBAAoB,CAAC,UAAU,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;IAE1E,MAAM,QAAQ,GAAG,OAAO;SACrB,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;SACrF,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,iBAAiB,IAAI,sBAAsB,CAAC;SACxE,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAElC,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC,MAAM;QACzB,QAAQ,EAAE,UAAU,CAAC,MAAM;QAC3B,UAAU,EAAE,SAAS;QACrB,YAAY,EAAE,sBAAsB;QACpC,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAgC;IAC1D,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7E,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,SAAS,CAAC,MAAgC;IACjD,IAAI,MAAM,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,cAAc,GAAG,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACvF,OAAO,cAAc,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,gBAAgB,CACvB,UAA+C,EAC/C,UAAyC;IAEzC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,KAAK,CAAS,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClF,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QACvD,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QACvD,KAAK,IAAI,KAAK,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YACjE,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACzD,MAAM,UAAU,GAAG,UAAU,IAAI,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1F,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC;YACjC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC;QACnC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAC3B,UAA+C,EAC/C,YAAiC,EACjC,SAAiB;IAEjB,IAAI,QAAQ,GAAqB,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAClE,OAAO,EAAE,CAAC,KAAK,CAAC;QAChB,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC;KACvB,CAAC,CAAC,CAAC;IAEJ,SAAS,CAAC;QACR,IAAI,IAAkF,CAAC;QACvF,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;YACrD,KAAK,IAAI,KAAK,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;gBAC/D,MAAM,UAAU,GAAG,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;gBACpG,IAAI,UAAU,GAAG,SAAS,EAAE,CAAC;oBAC3B,SAAS;gBACX,CAAC;gBACD,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtD,IACE,CAAC,IAAI;oBACL,UAAU,GAAG,IAAI,CAAC,UAAU;oBAC5B,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAClE,CAAC;oBACD,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;gBAC1C,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxG,MAAM,MAAM,GAAmB,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;QAC1D,QAAQ,GAAG,QAAQ;aAChB,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC;aACjE,MAAM,CAAC,MAAM,CAAC;aACd,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAC7B,IAAoB,EACpB,KAAqB,EACrB,YAAiC,EACjC,KAAa;IAEb,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACrC,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACvC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YACjE,uEAAuE;YACvE,IAAI,OAAO,GAAG,KAAK,EAAE,CAAC;gBACpB,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,kBAAkB,CACzB,OAAuB,EACvB,UAA+C,EAC/C,YAAiC,EACjC,YAAoB;IAEpB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAClE,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClG,MAAM,OAAO,GAAG,OAAO;SACpB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC;KAC5C,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhF,OAAO;QACL,OAAO;QACP,iBAAiB,EAAE,YAAY,CAAC,MAAM;QACtC,aAAa,EAAE,YAAY;QAC3B,mBAAmB,EAAE,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC;KACpE,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,OAA0B,EAAE,YAAiC;IACpF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QACpD,KAAK,IAAI,KAAK,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC9D,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,wBAAwB,CAAC,IAA+B,EAAE,KAAgC;IACjG,OAAO,CACL,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB;QAChD,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM;QAC1C,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB;QACpD,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CACzD,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,IAAY,EAAE,QAAgB;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,IAAI,UAAU,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QAClC,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC;AAC3D,CAAC;AAED,SAAS,aAAa,CAAC,IAAc,EAAE,KAAe;IACpD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,eAAe,CAAC,IAA8B,EAAE,KAA+B;IACtF,OAAO,WAAW,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;AACpF,CAAC;AAED,SAAS,SAAS,CAAC,MAAgC;IACjD,OAAO,GAAG,MAAM,CAAC,aAAa,SAAS,MAAM,CAAC,EAAE,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,QAAQ,CAAC,IAAoB,EAAE,KAAqB;IAC3D,OAAO,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC;AACnH,CAAC;AAED,SAAS,cAAc,CAAC,OAAkC;IACxD,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,aAAa,SAAS,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACrG,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,KAAa;IAC9C,OAAO,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB,EAAE,YAAoB;IAC9D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,UAAU,CAAC,mDAAmD,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,UAAU,CAAC,6CAA6C,CAAC,CAAC;IACtE,CAAC;AACH,CAAC"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { type RecallOptions } from "./recall.js";
|
|
2
2
|
/**
|
|
3
|
-
* Host-agnostic hook handlers. Claude Code
|
|
4
|
-
* lifecycle-hook
|
|
5
|
-
* envelopes
|
|
6
|
-
*
|
|
7
|
-
* Codex
|
|
3
|
+
* Host-agnostic hook handlers. Claude Code, Codex CLI, and Grok Build share the
|
|
4
|
+
* same lifecycle-hook event names; Codex and Grok largely copied Claude's
|
|
5
|
+
* envelopes. Field-name differences are normalized below:
|
|
6
|
+
* - prompt: Claude `user_input`, Codex `prompt` (Grok may send either)
|
|
7
|
+
* - tool fields: Claude/Codex snake_case (`tool_name`, `tool_input`, `session_id`);
|
|
8
|
+
* Grok camelCase (`toolName`, `toolInput`, `sessionId`, `workspaceRoot`)
|
|
9
|
+
* - tool names: Grok's real names (`run_terminal_command`, `search_replace`, …)
|
|
10
|
+
* plus Claude aliases already accepted by Grok matchers
|
|
8
11
|
*
|
|
9
12
|
* Every handler is **fail-open**: a hook runs on every prompt and every turn
|
|
10
13
|
* boundary, so any failure must degrade to "do nothing" (empty stdout, exit 0)
|