eklavya 1.18.2 → 1.19.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.
- package/dist/assets/dashboard.html +559 -14
- package/dist/assets/tutor/references/focus-and-level.md +29 -0
- package/dist/cli.js +648 -20
- package/dist/cli.js.map +1 -1
- package/dist/config-path.js +156 -0
- package/dist/config-path.js.map +1 -0
- package/dist/config.js +231 -2
- package/dist/config.js.map +1 -1
- package/dist/dashboard.js +355 -0
- package/dist/dashboard.js.map +1 -1
- package/dist/eval/retrieval-score.js +77 -0
- package/dist/eval/retrieval-score.js.map +1 -0
- package/dist/hooks/capture-tool.js +107 -0
- package/dist/hooks/capture-tool.js.map +1 -0
- package/dist/hooks/checkpoint-quiz.js +5 -6
- package/dist/hooks/checkpoint-quiz.js.map +1 -1
- package/dist/hooks/lib.js +7 -33
- package/dist/hooks/lib.js.map +1 -1
- package/dist/hooks/memory-lib.js +181 -0
- package/dist/hooks/memory-lib.js.map +1 -0
- package/dist/hooks/prompt-submit-nudge.js +56 -20
- package/dist/hooks/prompt-submit-nudge.js.map +1 -1
- package/dist/hooks/session-start.js +73 -74
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/hooks/stop-quiz-check.js +44 -7
- package/dist/hooks/stop-quiz-check.js.map +1 -1
- package/dist/install.js +37 -0
- package/dist/install.js.map +1 -1
- package/dist/memory/capture.js +123 -0
- package/dist/memory/capture.js.map +1 -0
- package/dist/memory/code.js +186 -0
- package/dist/memory/code.js.map +1 -0
- package/dist/memory/collections.js +87 -0
- package/dist/memory/collections.js.map +1 -0
- package/dist/memory/embed.js +81 -0
- package/dist/memory/embed.js.map +1 -0
- package/dist/memory/hosts.js +71 -0
- package/dist/memory/hosts.js.map +1 -0
- package/dist/memory/identity.js +74 -0
- package/dist/memory/identity.js.map +1 -0
- package/dist/memory/import.js +916 -0
- package/dist/memory/import.js.map +1 -0
- package/dist/memory/learning.js +148 -0
- package/dist/memory/learning.js.map +1 -0
- package/dist/memory/notify.js +220 -0
- package/dist/memory/notify.js.map +1 -0
- package/dist/memory/privacy.js +117 -0
- package/dist/memory/privacy.js.map +1 -0
- package/dist/memory/provider.js +155 -0
- package/dist/memory/provider.js.map +1 -0
- package/dist/memory/recall.js +327 -0
- package/dist/memory/recall.js.map +1 -0
- package/dist/memory/replay.js +174 -0
- package/dist/memory/replay.js.map +1 -0
- package/dist/memory/search.js +143 -0
- package/dist/memory/search.js.map +1 -0
- package/dist/memory/spool.js +93 -0
- package/dist/memory/spool.js.map +1 -0
- package/dist/memory/store.js +399 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/summarize.js +178 -0
- package/dist/memory/summarize.js.map +1 -0
- package/dist/memory/sync.js +595 -0
- package/dist/memory/sync.js.map +1 -0
- package/dist/memory/tokens.js +55 -0
- package/dist/memory/tokens.js.map +1 -0
- package/dist/memory/worker.js +207 -0
- package/dist/memory/worker.js.map +1 -0
- package/dist/migrations/009_memory.sql +226 -0
- package/dist/migrations/010_import.sql +26 -0
- package/dist/migrations/011_sync.sql +76 -0
- package/dist/migrations/012_job_backoff.sql +13 -0
- package/dist/migrations/013_batch_provenance.sql +18 -0
- package/dist/migrations/014_batch_events_index.sql +18 -0
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/agents/tutor.md +3 -1
- package/dist/plugin/hooks/CLAUDE.md +30 -6
- package/dist/plugin/hooks/hooks.json +10 -0
- package/dist/plugin/skills/CLAUDE.md +17 -7
- package/dist/plugin/skills/memory/SKILL.md +88 -0
- package/dist/plugin/skills/setup/SKILL.md +16 -2
- package/dist/plugin/skills/tutor/references/focus-and-level.md +29 -0
- package/dist/time.js +41 -0
- package/dist/time.js.map +1 -0
- package/dist/tools/code_tools.js +73 -0
- package/dist/tools/code_tools.js.map +1 -0
- package/dist/tools/collection_tools.js +92 -0
- package/dist/tools/collection_tools.js.map +1 -0
- package/dist/tools/config_tools.js +104 -1
- package/dist/tools/config_tools.js.map +1 -1
- package/dist/tools/index.js +15 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/memory_read_tools.js +277 -0
- package/dist/tools/memory_read_tools.js.map +1 -0
- package/dist/tools/memory_write_tools.js +115 -0
- package/dist/tools/memory_write_tools.js.map +1 -0
- package/dist/user-skill/eklavya/SKILL.md +64 -8
- package/package.json +2 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostToolUse (every tool): record what the agent just did.
|
|
3
|
+
*
|
|
4
|
+
* This is the memory half's main intake. It matches every tool rather than one,
|
|
5
|
+
* so it is the hook that runs most often in a session — which is why it does
|
|
6
|
+
* the least: resolve identity, normalise one event, one insert, exit.
|
|
7
|
+
*
|
|
8
|
+
* It deliberately does not quiz, summarise, or call a provider. The checkpoint
|
|
9
|
+
* hook owns questions and the seam owns summaries; a capture path that also
|
|
10
|
+
* teaches is a capture path that makes every tool call slower.
|
|
11
|
+
*/
|
|
12
|
+
import { run, openExisting, config, cwdOf, sessionId } from './lib.js';
|
|
13
|
+
import { batchIfFull, identityOf, record } from './memory-lib.js';
|
|
14
|
+
/** Tools whose result is a file's contents rather than a change to one. */
|
|
15
|
+
const READ_TOOLS = new Set(['Read', 'NotebookRead', 'Glob', 'Grep']);
|
|
16
|
+
const EDIT_TOOLS = new Set(['Edit', 'Write', 'NotebookEdit', 'MultiEdit']);
|
|
17
|
+
function filesFrom(toolInput) {
|
|
18
|
+
if (!toolInput)
|
|
19
|
+
return [];
|
|
20
|
+
const candidates = [toolInput.file_path, toolInput.notebook_path, toolInput.path];
|
|
21
|
+
return candidates.filter((c) => typeof c === 'string' && c.length > 0);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* What the event's body says.
|
|
25
|
+
*
|
|
26
|
+
* Arguments rather than results, with one exception: a failure's message is the
|
|
27
|
+
* part worth remembering. A successful `Read` returning a whole file would make
|
|
28
|
+
* the corpus a second copy of the repository.
|
|
29
|
+
*/
|
|
30
|
+
function bodyFor(input, failed) {
|
|
31
|
+
const toolInput = input.tool_input ?? {};
|
|
32
|
+
const parts = [];
|
|
33
|
+
if (typeof toolInput.command === 'string')
|
|
34
|
+
parts.push(toolInput.command);
|
|
35
|
+
if (typeof toolInput.description === 'string')
|
|
36
|
+
parts.push(toolInput.description);
|
|
37
|
+
if (typeof toolInput.prompt === 'string')
|
|
38
|
+
parts.push(toolInput.prompt);
|
|
39
|
+
if (typeof toolInput.old_string === 'string' && typeof toolInput.new_string === 'string') {
|
|
40
|
+
parts.push(`- ${toolInput.old_string.slice(0, 600)}`, `+ ${toolInput.new_string.slice(0, 600)}`);
|
|
41
|
+
}
|
|
42
|
+
if (!parts.length) {
|
|
43
|
+
const keys = Object.keys(toolInput).filter((k) => k !== 'content');
|
|
44
|
+
if (keys.length)
|
|
45
|
+
parts.push(keys.map((k) => `${k}=${String(toolInput[k]).slice(0, 200)}`).join(' '));
|
|
46
|
+
}
|
|
47
|
+
if (failed)
|
|
48
|
+
parts.push(String(errorText(input.tool_response)).slice(0, 800));
|
|
49
|
+
return parts.join('\n');
|
|
50
|
+
}
|
|
51
|
+
function errorText(response) {
|
|
52
|
+
if (typeof response === 'string')
|
|
53
|
+
return response;
|
|
54
|
+
if (response && typeof response === 'object') {
|
|
55
|
+
const r = response;
|
|
56
|
+
if (typeof r.error === 'string')
|
|
57
|
+
return r.error;
|
|
58
|
+
if (typeof r.stderr === 'string')
|
|
59
|
+
return r.stderr;
|
|
60
|
+
}
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
function failed(response) {
|
|
64
|
+
if (!response || typeof response !== 'object')
|
|
65
|
+
return false;
|
|
66
|
+
const r = response;
|
|
67
|
+
return r.success === false || Boolean(r.error) || r.is_error === true;
|
|
68
|
+
}
|
|
69
|
+
function kindFor(tool, isError) {
|
|
70
|
+
if (isError)
|
|
71
|
+
return 'tool_error';
|
|
72
|
+
if (EDIT_TOOLS.has(tool))
|
|
73
|
+
return 'file_edit';
|
|
74
|
+
if (READ_TOOLS.has(tool))
|
|
75
|
+
return 'file_read';
|
|
76
|
+
return 'tool_use';
|
|
77
|
+
}
|
|
78
|
+
await run(async (input) => {
|
|
79
|
+
const db = openExisting();
|
|
80
|
+
if (!db)
|
|
81
|
+
return 0;
|
|
82
|
+
const cwd = cwdOf(input);
|
|
83
|
+
const resolved = config(cwd);
|
|
84
|
+
// Capture is independent of `mode`: someone who turned quizzing off did not
|
|
85
|
+
// ask for their project history to stop being recorded (PRD CFG-01).
|
|
86
|
+
if (!resolved.config.memory.enabled)
|
|
87
|
+
return 0;
|
|
88
|
+
const tool = input.tool_name ?? '';
|
|
89
|
+
if (!tool)
|
|
90
|
+
return 0;
|
|
91
|
+
const sid = sessionId(input, db);
|
|
92
|
+
const identity = identityOf(input, cwd, sid);
|
|
93
|
+
const isError = failed(input.tool_response);
|
|
94
|
+
const body = bodyFor(input, isError);
|
|
95
|
+
if (!body.trim())
|
|
96
|
+
return 0;
|
|
97
|
+
record(db, resolved, identity, {
|
|
98
|
+
kind: kindFor(tool, isError),
|
|
99
|
+
tool,
|
|
100
|
+
title: tool,
|
|
101
|
+
body,
|
|
102
|
+
files: filesFrom(input.tool_input),
|
|
103
|
+
});
|
|
104
|
+
batchIfFull(db, resolved, identity);
|
|
105
|
+
return 0;
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=capture-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture-tool.js","sourceRoot":"","sources":["../../src/hooks/capture-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -140,12 +140,11 @@ Do exactly this, then get straight back to the task:
|
|
|
140
140
|
ONE question. Not two, not the whole plan. ${remaining} left in this session's budget, and the Stop hook spends whatever you do not.
|
|
141
141
|
${framing}
|
|
142
142
|
If they pick Other or say skip, record it as grade 0, teach the answer in two lines, and carry on. Do not ask again.`;
|
|
143
|
-
// exit 0 + JSON, not exit 2 + stderr
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
// something.
|
|
143
|
+
// exit 0 + JSON, not exit 2 + stderr: exit 2 renders to the developer as a hook
|
|
144
|
+
// warning -- an error face on a feature that is working. The Stop sweep reached
|
|
145
|
+
// the same conclusion later and by the same route. So: additionalContext
|
|
146
|
+
// carries the instruction to the model, systemMessage tells the human why their
|
|
147
|
+
// agent just stopped to ask them something.
|
|
149
148
|
process.stdout.write(`${JSON.stringify({
|
|
150
149
|
hookSpecificOutput: {
|
|
151
150
|
hookEventName: 'PostToolUse',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint-quiz.js","sourceRoot":"","sources":["../../src/hooks/checkpoint-quiz.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;IACxB,0EAA0E;IAC1E,8EAA8E;IAC9E,2EAA2E;IAC3E,gEAAgE;IAChE,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,CAAC,CAAC;IAE7B,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IAElB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACzB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,+BAA+B,EAAE,GAClG,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IAErB,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,CAAC,CAAC;IAC7B,+EAA+E;IAC/E,cAAc;IACd,IAAI,OAAO,KAAK,aAAa;QAAE,OAAO,CAAC,CAAC;IAExC,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,CAAC;IACnB,IAAI,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAEpC,kDAAkD;IAClD,EAAE;IACF,+EAA+E;IAC/E,+EAA+E;IAC/E,4EAA4E;IAC5E,wCAAwC;IACxC,MAAM,KAAK,GAAG,EAAE;SACb,OAAO,CACN;;;;;;;;;;;;;;;;;;mGAkB6F,CAC9F;SACA,GAAG,CAAC,EAAE,GAAG,EAAE,CAED,CAAC;IAEd,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC;IAErB,8EAA8E;IAC9E,8CAA8C;IAC9C,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAEpC,8EAA8E;IAC9E,IAAI,KAAK,CAAC,KAAK,IAAI,sBAAsB;QAAE,OAAO,CAAC,CAAC;IACpD,IAAI,YAAY,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,+BAA+B;QAAE,OAAO,CAAC,CAAC;IACpF,IAAI,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,+BAA+B;QAAE,OAAO,CAAC,CAAC;IAChF,8EAA8E;IAE9E,6EAA6E;IAC7E,gFAAgF;IAChF,gFAAgF;IAChF,aAAa;IACb,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CACN;;;;;;;;;;gBAUU,CACX;SACA,GAAG,CAAC,EAAE,GAAG,EAAE,CAAoC,CAAC;IAEnD,IAAI,CAAC,GAAG,EAAE,OAAO;QAAE,OAAO,CAAC,CAAC;IAE5B,4EAA4E;IAC5E,iFAAiF;IACjF,kEAAkE;IAClE,EAAE,CAAC,OAAO,CACR;;;;kDAI8C,CAC/C,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IAEf,MAAM,SAAS,GAAG,sBAAsB,GAAG,KAAK,CAAC,KAAK,CAAC;IACvD,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;IAE7D,MAAM,OAAO,GAAG;;WAEP,GAAG,CAAC,OAAO;;;;;OAKf,eAAe,EAAE;;;;6CAIqB,SAAS;EACpD,OAAO;qHAC4G,CAAC;IAEpH
|
|
1
|
+
{"version":3,"file":"checkpoint-quiz.js","sourceRoot":"","sources":["../../src/hooks/checkpoint-quiz.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;IACxB,0EAA0E;IAC1E,8EAA8E;IAC9E,2EAA2E;IAC3E,gEAAgE;IAChE,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,CAAC,CAAC;IAE7B,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IAElB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACzB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,+BAA+B,EAAE,GAClG,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IAErB,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,CAAC,CAAC;IAC7B,+EAA+E;IAC/E,cAAc;IACd,IAAI,OAAO,KAAK,aAAa;QAAE,OAAO,CAAC,CAAC;IAExC,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,CAAC;IACnB,IAAI,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAEpC,kDAAkD;IAClD,EAAE;IACF,+EAA+E;IAC/E,+EAA+E;IAC/E,4EAA4E;IAC5E,wCAAwC;IACxC,MAAM,KAAK,GAAG,EAAE;SACb,OAAO,CACN;;;;;;;;;;;;;;;;;;mGAkB6F,CAC9F;SACA,GAAG,CAAC,EAAE,GAAG,EAAE,CAED,CAAC;IAEd,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC;IAErB,8EAA8E;IAC9E,8CAA8C;IAC9C,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAEpC,8EAA8E;IAC9E,IAAI,KAAK,CAAC,KAAK,IAAI,sBAAsB;QAAE,OAAO,CAAC,CAAC;IACpD,IAAI,YAAY,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,+BAA+B;QAAE,OAAO,CAAC,CAAC;IACpF,IAAI,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,+BAA+B;QAAE,OAAO,CAAC,CAAC;IAChF,8EAA8E;IAE9E,6EAA6E;IAC7E,gFAAgF;IAChF,gFAAgF;IAChF,aAAa;IACb,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CACN;;;;;;;;;;gBAUU,CACX;SACA,GAAG,CAAC,EAAE,GAAG,EAAE,CAAoC,CAAC;IAEnD,IAAI,CAAC,GAAG,EAAE,OAAO;QAAE,OAAO,CAAC,CAAC;IAE5B,4EAA4E;IAC5E,iFAAiF;IACjF,kEAAkE;IAClE,EAAE,CAAC,OAAO,CACR;;;;kDAI8C,CAC/C,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IAEf,MAAM,SAAS,GAAG,sBAAsB,GAAG,KAAK,CAAC,KAAK,CAAC;IACvD,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;IAE7D,MAAM,OAAO,GAAG;;WAEP,GAAG,CAAC,OAAO;;;;;OAKf,eAAe,EAAE;;;;6CAIqB,SAAS;EACpD,OAAO;qHAC4G,CAAC;IAEpH,gFAAgF;IAChF,gFAAgF;IAChF,yEAAyE;IACzE,gFAAgF;IAChF,4CAA4C;IAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,IAAI,CAAC,SAAS,CAAC;QAChB,kBAAkB,EAAE;YAClB,aAAa,EAAE,aAAa;YAC5B,iBAAiB,EAAE,OAAO;YAC1B,aAAa,EAAE,gDAAgD;SAChE;KACF,CAAC,IAAI,CACP,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC,CAAC,CAAC"}
|
package/dist/hooks/lib.js
CHANGED
|
@@ -22,6 +22,10 @@ import { loadConfig } from '../config.js';
|
|
|
22
22
|
import { readStdinBounded, stripBom, HOOK_STDIN } from '../stdin.js';
|
|
23
23
|
import { withSurfaceNote } from '../surface.js';
|
|
24
24
|
import { getCurrentSession } from '../session.js';
|
|
25
|
+
import { minutesSince, NEVER, nowIso } from '../time.js';
|
|
26
|
+
// The clock policy moved to `time.ts` so the memory half shares it; hooks and
|
|
27
|
+
// tests still import these three from here.
|
|
28
|
+
export { minutesSince, NEVER, nowIso };
|
|
25
29
|
/**
|
|
26
30
|
* The JSON the host piped in, or `{}`.
|
|
27
31
|
*
|
|
@@ -126,36 +130,6 @@ export function sessionId(input, db) {
|
|
|
126
130
|
return null;
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
|
-
/** Minutes since a timestamp, or a number large enough to never gate. */
|
|
130
|
-
export const NEVER = 999_999;
|
|
131
|
-
/**
|
|
132
|
-
* Minutes since a timestamp written by SQLite.
|
|
133
|
-
*
|
|
134
|
-
* This schema stores two shapes, and the difference is a trap. `strftime(...Z)`
|
|
135
|
-
* is explicitly UTC, but `datetime('now')` — the default on `session_concepts.ts`
|
|
136
|
-
* and `attempts.ts` — produces "2026-09-05 18:04:09": UTC, with nothing saying
|
|
137
|
-
* so. `Date.parse` reads that as LOCAL time, so every cooldown came out wrong by
|
|
138
|
-
* the machine's UTC offset, and west of UTC the elapsed time was negative and no
|
|
139
|
-
* cooldown ever passed. The shell version never had this bug because `julianday`
|
|
140
|
-
* assumes UTC for exactly this format.
|
|
141
|
-
*
|
|
142
|
-
* So: normalise to UTC before parsing, and never return a negative — a clock
|
|
143
|
-
* that has moved backwards should read as "just now", not as "never".
|
|
144
|
-
*/
|
|
145
|
-
export function minutesSince(ts) {
|
|
146
|
-
if (!ts)
|
|
147
|
-
return NEVER;
|
|
148
|
-
const hasZone = /(?:Z|[+-]\d{2}:?\d{2})$/.test(ts);
|
|
149
|
-
const normalised = hasZone ? ts : `${ts.replace(' ', 'T')}Z`;
|
|
150
|
-
const then = Date.parse(normalised);
|
|
151
|
-
if (Number.isNaN(then))
|
|
152
|
-
return NEVER;
|
|
153
|
-
return Math.max(0, Math.floor((Date.now() - then) / 60_000));
|
|
154
|
-
}
|
|
155
|
-
/** The timestamp format every table in this schema stores. */
|
|
156
|
-
export function nowIso() {
|
|
157
|
-
return new Date().toISOString().replace(/(\.\d{3})Z$/, '$1Z');
|
|
158
|
-
}
|
|
159
133
|
/**
|
|
160
134
|
* The focus framing, stated by the hooks rather than left to the tutor skill.
|
|
161
135
|
*
|
|
@@ -195,9 +169,9 @@ function focusFraming(focus, topic, where) {
|
|
|
195
169
|
* Runs a hook body and guarantees the session survives it.
|
|
196
170
|
*
|
|
197
171
|
* Every failure path exits 0 with no output — a missed question is nothing, a
|
|
198
|
-
* hook that errors on every tool call is a plugin nobody keeps.
|
|
199
|
-
*
|
|
200
|
-
*
|
|
172
|
+
* hook that errors on every tool call is a plugin nobody keeps. Every hook here
|
|
173
|
+
* exits 0 and speaks through JSON on stdout, the Stop sweep included; anything
|
|
174
|
+
* thrown still lands here and still exits 0.
|
|
201
175
|
*/
|
|
202
176
|
export async function run(body) {
|
|
203
177
|
let code = 0;
|
package/dist/hooks/lib.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../../src/hooks/lib.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAuB,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../../src/hooks/lib.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { projectKey } from '../store.js';
|
|
2
|
+
import { identityFor } from '../memory/identity.js';
|
|
3
|
+
import { capture, drainSpool } from '../memory/capture.js';
|
|
4
|
+
import { batchSession, pendingEventCount } from '../memory/store.js';
|
|
5
|
+
import { processPending, writeSessionSummary } from '../memory/worker.js';
|
|
6
|
+
import { recall, recallForPrompt } from '../memory/recall.js';
|
|
7
|
+
import { notify, queuePausedAlert, sessionWrapUp } from '../memory/notify.js';
|
|
8
|
+
import { countEntries } from '../memory/store.js';
|
|
9
|
+
import { queueDepth } from '../memory/worker.js';
|
|
10
|
+
export function identityOf(input, cwd, sid) {
|
|
11
|
+
const identity = identityFor({
|
|
12
|
+
cwd,
|
|
13
|
+
sessionId: sid ?? 'default',
|
|
14
|
+
agentId: input.agent_id ?? null,
|
|
15
|
+
host: 'claude-code',
|
|
16
|
+
});
|
|
17
|
+
// `identityFor` resolves the project from the cwd; `projectKey` is the
|
|
18
|
+
// learning half's spelling of the same thing, and the two must not diverge or
|
|
19
|
+
// a memory and a mastery row disagree about which codebase they belong to.
|
|
20
|
+
return { ...identity, project: projectKey(identity.checkout) };
|
|
21
|
+
}
|
|
22
|
+
/** Records one event. Returns false on any failure, and never throws. */
|
|
23
|
+
export function record(db, resolved, identity, event) {
|
|
24
|
+
try {
|
|
25
|
+
return capture(db, resolved.config, identity, event) === 'stored';
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Closes a batch once enough evidence has accumulated. Batching is cheap SQL;
|
|
33
|
+
* summarising is not, so this never summarises — the seam does.
|
|
34
|
+
*/
|
|
35
|
+
export function batchIfFull(db, resolved, identity) {
|
|
36
|
+
try {
|
|
37
|
+
const max = resolved.config.memory.batch_max_events;
|
|
38
|
+
if (pendingEventCount(db, identity.project) < max)
|
|
39
|
+
return;
|
|
40
|
+
batchSession(db, {
|
|
41
|
+
project: identity.project,
|
|
42
|
+
sessionId: identity.sessionId,
|
|
43
|
+
reason: 'size',
|
|
44
|
+
maxEvents: max,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
/* A batch that did not close is one that closes at the seam instead. */
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The session seam: close what is open and summarise it.
|
|
53
|
+
*
|
|
54
|
+
* With a provider configured this only *queues* the work. Waiting on inference
|
|
55
|
+
* inside a Stop hook would make the developer wait for an API call to finish a
|
|
56
|
+
* turn, which PRD LRN-04 forbids; the next session start, or `eklavya memory
|
|
57
|
+
* process`, drains it.
|
|
58
|
+
*/
|
|
59
|
+
export async function flushAtSeam(db, resolved, identity) {
|
|
60
|
+
try {
|
|
61
|
+
batchSession(db, {
|
|
62
|
+
project: identity.project,
|
|
63
|
+
sessionId: identity.sessionId,
|
|
64
|
+
reason: 'session_seam',
|
|
65
|
+
maxEvents: resolved.config.memory.batch_max_events,
|
|
66
|
+
});
|
|
67
|
+
if (resolved.config.providers.observer)
|
|
68
|
+
return;
|
|
69
|
+
await processPending(db, resolved.config, { maxJobs: 2 });
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
/* Nothing summarised is evidence still on disk, not evidence lost. */
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Replays anything the spool holds. Idempotent; safe to call every session. */
|
|
76
|
+
export function replaySpool(db) {
|
|
77
|
+
try {
|
|
78
|
+
drainSpool(db);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* The spool keeps what it could not replay. */
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The recalled-evidence block for a session seam, or null.
|
|
86
|
+
*
|
|
87
|
+
* Model context, never the human display (PRD UX-02). Writing the receipt is
|
|
88
|
+
* part of producing it: a block delivered without one is a saving that cannot
|
|
89
|
+
* be checked later, so `recall` does both or neither.
|
|
90
|
+
*/
|
|
91
|
+
export function recallBlock(db, resolved, identity, scope) {
|
|
92
|
+
try {
|
|
93
|
+
if (!resolved.config.memory.enabled)
|
|
94
|
+
return null;
|
|
95
|
+
const result = recall(db, resolved.config, {
|
|
96
|
+
project: identity.project,
|
|
97
|
+
sessionId: identity.sessionId,
|
|
98
|
+
scope,
|
|
99
|
+
// The host adds this hook's stdout to the model's context and says so, so
|
|
100
|
+
// delivery is confirmed rather than merely prepared.
|
|
101
|
+
delivery: 'confirmed',
|
|
102
|
+
});
|
|
103
|
+
return result.block;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Recall for one prompt, mid-session, or null.
|
|
111
|
+
*
|
|
112
|
+
* Silent far more often than not: too short a prompt, nothing relevant, or
|
|
113
|
+
* nothing this session has not already been handed. That is the design — a
|
|
114
|
+
* recall on every turn is a tax on every turn.
|
|
115
|
+
*/
|
|
116
|
+
export function promptRecall(db, resolved, identity, prompt) {
|
|
117
|
+
try {
|
|
118
|
+
if (!resolved.config.memory.enabled)
|
|
119
|
+
return null;
|
|
120
|
+
const result = recallForPrompt(db, resolved.config, {
|
|
121
|
+
project: identity.project,
|
|
122
|
+
sessionId: identity.sessionId,
|
|
123
|
+
prompt,
|
|
124
|
+
});
|
|
125
|
+
return result?.block ?? null;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Everything that happens once the seam's work has been flushed: the session
|
|
133
|
+
* summary, the wrap-up, and the one alert worth interrupting for.
|
|
134
|
+
*
|
|
135
|
+
* The summary is written first and outside the notifications gate, because it
|
|
136
|
+
* is memory rather than an announcement — gating it on `notifications.enabled`,
|
|
137
|
+
* which is off by default, would mean nobody ever gets one. The wrap-up and the
|
|
138
|
+
* alert below stay no-ops unless a sink is configured, so a session that has
|
|
139
|
+
* not opted in pays one boolean. Failures are swallowed for the usual reason: a
|
|
140
|
+
* dead webhook must not be how a turn ends.
|
|
141
|
+
*/
|
|
142
|
+
export async function wrapUpAtSeam(db, resolved, identity) {
|
|
143
|
+
try {
|
|
144
|
+
writeSessionSummary(db, identity.project, identity.sessionId);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
/* A session without a summary still has its observations. */
|
|
148
|
+
}
|
|
149
|
+
if (!resolved.config.notifications.enabled)
|
|
150
|
+
return;
|
|
151
|
+
try {
|
|
152
|
+
const attempts = db
|
|
153
|
+
.prepare('SELECT COUNT(*) AS n, COALESCE(SUM(grade >= 3), 0) AS passed FROM attempts WHERE session_id = ?')
|
|
154
|
+
.get(identity.sessionId);
|
|
155
|
+
await notify(db, resolved.config, sessionWrapUp({
|
|
156
|
+
project: identity.project,
|
|
157
|
+
sessionId: identity.sessionId,
|
|
158
|
+
entries: countEntries(db, identity.project),
|
|
159
|
+
questions: attempts.n,
|
|
160
|
+
passed: attempts.passed,
|
|
161
|
+
}));
|
|
162
|
+
// A paused queue is capture that has stopped and will not restart by
|
|
163
|
+
// itself. Everything else about memory degrades quietly on purpose; this
|
|
164
|
+
// one is worth saying out loud, once per reason.
|
|
165
|
+
const queue = queueDepth(db);
|
|
166
|
+
if (queue.paused > 0) {
|
|
167
|
+
const reason = db
|
|
168
|
+
.prepare("SELECT error_class FROM memory_jobs WHERE status = 'paused' ORDER BY updated_at DESC LIMIT 1")
|
|
169
|
+
.get();
|
|
170
|
+
await notify(db, resolved.config, queuePausedAlert({
|
|
171
|
+
project: identity.project,
|
|
172
|
+
errorClass: reason?.error_class ?? 'unknown',
|
|
173
|
+
failed: queue.paused + queue.failed,
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
/* A wrap-up nobody received is a wrap-up. A thrown one is a broken session. */
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=memory-lib.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-lib.js","sourceRoot":"","sources":["../../src/hooks/memory-lib.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
import { run, openExisting, config, cwdOf, sessionId, minutesSince, NUDGE_KEY_PREFIX, } from './lib.js';
|
|
44
44
|
import { withSurfaceNote } from '../surface.js';
|
|
45
45
|
import { isSessionOff, setCurrentSession } from '../session.js';
|
|
46
|
+
import { batchIfFull, identityOf, promptRecall, record } from './memory-lib.js';
|
|
46
47
|
/**
|
|
47
48
|
* Long enough that the session-start directive has had a fair chance, short
|
|
48
49
|
* enough to still be the same piece of work. Not configurable on purpose: a
|
|
@@ -106,8 +107,13 @@ await run(async (input) => {
|
|
|
106
107
|
// prompt the developer types, so a dormant or quiet session should not pay to
|
|
107
108
|
// open SQLite before finding out it had nothing to do. Reading one or two
|
|
108
109
|
// small JSON files is the cheaper question, so it is asked first.
|
|
109
|
-
const
|
|
110
|
-
|
|
110
|
+
const cwd = cwdOf(input);
|
|
111
|
+
const resolved = config(cwd);
|
|
112
|
+
const { mode } = resolved.config;
|
|
113
|
+
// `mode: off` silences the learning half. It does not stop memory capture --
|
|
114
|
+
// someone who asked for no quizzes did not ask for their project history to
|
|
115
|
+
// stop being recorded (PRD CFG-01) -- so the early return needs both to be off.
|
|
116
|
+
if (mode === 'off' && !resolved.config.memory.enabled)
|
|
111
117
|
return 0;
|
|
112
118
|
// `quiet` is deliberately NOT consulted. It suppresses the banner and the
|
|
113
119
|
// status bar -- things the developer looks at -- and this is an
|
|
@@ -134,16 +140,36 @@ await run(async (input) => {
|
|
|
134
140
|
// one: a model churning for ten minutes while its developer works in another
|
|
135
141
|
// repo calls its tools long after that other window typed. `cwd` is what keeps
|
|
136
142
|
// the two apart — see `sessionKeyFor`.
|
|
137
|
-
setCurrentSession(db, sid,
|
|
143
|
+
setCurrentSession(db, sid, cwd);
|
|
144
|
+
// The prompt is the single most useful thing a session produces for recall:
|
|
145
|
+
// it is the only place the developer says what they were trying to do. It is
|
|
146
|
+
// captured before every learning gate below, for the reason above.
|
|
147
|
+
// Anything the model should be handed this turn. At most one JSON envelope
|
|
148
|
+
// leaves this hook, so the recall block and the nudge line share it.
|
|
149
|
+
const context = [];
|
|
150
|
+
if (resolved.config.memory.enabled && typeof input.prompt === 'string' && input.prompt.trim()) {
|
|
151
|
+
const identity = identityOf(input, cwd, sid);
|
|
152
|
+
record(db, resolved, identity, { kind: 'prompt', title: 'prompt', body: input.prompt });
|
|
153
|
+
batchIfFull(db, resolved, identity);
|
|
154
|
+
// The session seam answers "what is this project". This answers "what do
|
|
155
|
+
// we already know about the thing they just asked for", which is the one
|
|
156
|
+
// that catches a change of subject halfway through a session. It returns
|
|
157
|
+
// nothing far more often than not, on purpose.
|
|
158
|
+
const recalled = promptRecall(db, resolved, identity, input.prompt);
|
|
159
|
+
if (recalled)
|
|
160
|
+
context.push(recalled);
|
|
161
|
+
}
|
|
162
|
+
if (mode === 'off')
|
|
163
|
+
return emit(context);
|
|
138
164
|
if (isSessionOff(db, sid))
|
|
139
|
-
return
|
|
165
|
+
return emit(context);
|
|
140
166
|
// The fast path, and the one that runs on almost every prompt: a session that
|
|
141
167
|
// is logging needs nothing said to it.
|
|
142
168
|
const logged = db
|
|
143
169
|
.prepare('SELECT count(*) AS n FROM session_concepts WHERE session_id = ?')
|
|
144
170
|
.get(sid);
|
|
145
171
|
if ((logged?.n ?? 0) > 0)
|
|
146
|
-
return
|
|
172
|
+
return emit(context);
|
|
147
173
|
const key = `${NUDGE_KEY_PREFIX}${sid}`;
|
|
148
174
|
const now = new Date().toISOString();
|
|
149
175
|
const state = readState(db, key);
|
|
@@ -152,27 +178,37 @@ await run(async (input) => {
|
|
|
152
178
|
if (!state) {
|
|
153
179
|
prune(db);
|
|
154
180
|
writeState(db, key, now, null, 0);
|
|
155
|
-
return
|
|
181
|
+
return emit(context);
|
|
156
182
|
}
|
|
157
183
|
if (state.count >= MAX_NUDGES)
|
|
158
|
-
return
|
|
184
|
+
return emit(context);
|
|
159
185
|
if (minutesSince(state.first) < GRACE_MINUTES)
|
|
160
|
-
return
|
|
186
|
+
return emit(context);
|
|
161
187
|
if (state.nudged && minutesSince(state.nudged) < COOLDOWN_MINUTES)
|
|
162
|
-
return
|
|
188
|
+
return emit(context);
|
|
163
189
|
writeState(db, key, state.first, now, state.count + 1);
|
|
190
|
+
// Surface-noted like the two directives this restates. Cowork *does* fire
|
|
191
|
+
// `UserPromptSubmit`, and a session that has logged nothing is exactly the
|
|
192
|
+
// state this hook exists to catch — so without the note this is the one
|
|
193
|
+
// string still telling the model to name "the real code" in work that has
|
|
194
|
+
// none, on the only path that reaches a session already going wrong.
|
|
195
|
+
context.push(withSurfaceNote('[Eklavya] Nothing logged this session. Once you know what the current task involves, call log_session_concepts with the 3-8 concepts it genuinely exercises, each with a context line naming the real code — without it there is nothing to quiz on.', ' '));
|
|
196
|
+
return emit(context);
|
|
197
|
+
});
|
|
198
|
+
/**
|
|
199
|
+
* One envelope or silence.
|
|
200
|
+
*
|
|
201
|
+
* A hook may write a single JSON object, so every exit from the body above
|
|
202
|
+
* goes through here rather than printing its own — two writes would be one
|
|
203
|
+
* malformed document, and a malformed document is a hook that runs, exits 0
|
|
204
|
+
* and is ignored.
|
|
205
|
+
*/
|
|
206
|
+
function emit(context) {
|
|
207
|
+
if (!context.length)
|
|
208
|
+
return 0;
|
|
164
209
|
process.stdout.write(`${JSON.stringify({
|
|
165
|
-
hookSpecificOutput: {
|
|
166
|
-
hookEventName: 'UserPromptSubmit',
|
|
167
|
-
// Surface-noted like the two directives this restates. Cowork *does*
|
|
168
|
-
// fire `UserPromptSubmit`, and a session that has logged nothing is
|
|
169
|
-
// exactly the state this hook exists to catch — so without the note
|
|
170
|
-
// this is the one string still telling the model to name "the real
|
|
171
|
-
// code" in work that has none, on the only path that reaches a session
|
|
172
|
-
// already going wrong.
|
|
173
|
-
additionalContext: withSurfaceNote('[Eklavya] Nothing logged this session. Once you know what the current task involves, call log_session_concepts with the 3-8 concepts it genuinely exercises, each with a context line naming the real code — without it there is nothing to quiz on.', ' '),
|
|
174
|
-
},
|
|
210
|
+
hookSpecificOutput: { hookEventName: 'UserPromptSubmit', additionalContext: context.join('\n') },
|
|
175
211
|
})}\n`);
|
|
176
212
|
return 0;
|
|
177
|
-
}
|
|
213
|
+
}
|
|
178
214
|
//# sourceMappingURL=prompt-submit-nudge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-submit-nudge.js","sourceRoot":"","sources":["../../src/hooks/prompt-submit-nudge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,OAAO,EACL,GAAG,EACH,YAAY,EACZ,MAAM,EACN,KAAK,EACL,SAAS,EACT,YAAY,EACZ,gBAAgB,GAEjB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"prompt-submit-nudge.js","sourceRoot":"","sources":["../../src/hooks/prompt-submit-nudge.ts"],"names":[],"mappings":"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"}
|