@vibe-commit/capture 0.6.1 → 0.8.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/README.md +191 -9
- package/dist/account_not_here.d.ts +15 -0
- package/dist/account_not_here.js +25 -0
- package/dist/account_not_here.js.map +1 -0
- package/dist/agent_hooks.d.ts +8 -0
- package/dist/agent_hooks.js +31 -1
- package/dist/agent_hooks.js.map +1 -1
- package/dist/agents/claude_code.d.ts +34 -0
- package/dist/agents/claude_code.js +141 -8
- package/dist/agents/claude_code.js.map +1 -1
- package/dist/agents/codex_cli.d.ts +13 -0
- package/dist/agents/codex_cli.js +241 -2
- package/dist/agents/codex_cli.js.map +1 -1
- package/dist/agents/cursor.d.ts +34 -0
- package/dist/agents/cursor.js +115 -1
- package/dist/agents/cursor.js.map +1 -1
- package/dist/agents/session_listing.d.ts +29 -0
- package/dist/agents/session_listing.js +49 -0
- package/dist/agents/session_listing.js.map +1 -0
- package/dist/agents/types.d.ts +118 -8
- package/dist/agents/types.js +17 -3
- package/dist/agents/types.js.map +1 -1
- package/dist/commands/approval_pending.d.ts +9 -0
- package/dist/commands/approval_pending.js +23 -0
- package/dist/commands/approval_pending.js.map +1 -0
- package/dist/commands/auth.d.ts +7 -0
- package/dist/commands/auth.js +52 -11
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/backfill.d.ts +160 -0
- package/dist/commands/backfill.js +748 -0
- package/dist/commands/backfill.js.map +1 -0
- package/dist/commands/browser_credential.d.ts +6 -2
- package/dist/commands/browser_credential.js +34 -14
- package/dist/commands/browser_credential.js.map +1 -1
- package/dist/commands/connect.d.ts +146 -0
- package/dist/commands/connect.js +216 -117
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/connect_account.d.ts +135 -0
- package/dist/commands/connect_account.js +321 -0
- package/dist/commands/connect_account.js.map +1 -0
- package/dist/commands/connect_picker.d.ts +27 -0
- package/dist/commands/connect_picker.js +549 -0
- package/dist/commands/connect_picker.js.map +1 -0
- package/dist/commands/context.d.ts +16 -0
- package/dist/commands/context.js +27 -0
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/credential_problem.d.ts +15 -4
- package/dist/commands/credential_problem.js +29 -22
- package/dist/commands/credential_problem.js.map +1 -1
- package/dist/commands/device_credential.d.ts +5 -1
- package/dist/commands/device_credential.js +17 -14
- package/dist/commands/device_credential.js.map +1 -1
- package/dist/commands/finalize.d.ts +95 -0
- package/dist/commands/finalize.js +249 -74
- package/dist/commands/finalize.js.map +1 -1
- package/dist/commands/finish_mint.d.ts +30 -6
- package/dist/commands/finish_mint.js +26 -6
- package/dist/commands/finish_mint.js.map +1 -1
- package/dist/commands/report.js +38 -30
- package/dist/commands/report.js.map +1 -1
- package/dist/commands/scan.d.ts +162 -0
- package/dist/commands/scan.js +507 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/status.d.ts +19 -1
- package/dist/commands/status.js +232 -26
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/status_hooks.d.ts +14 -0
- package/dist/commands/status_hooks.js +81 -0
- package/dist/commands/status_hooks.js.map +1 -0
- package/dist/commands/status_machine.d.ts +27 -0
- package/dist/commands/status_machine.js +210 -0
- package/dist/commands/status_machine.js.map +1 -0
- package/dist/commands/sync_reason.d.ts +17 -0
- package/dist/commands/sync_reason.js +25 -0
- package/dist/commands/sync_reason.js.map +1 -0
- package/dist/commands/why.js +44 -31
- package/dist/commands/why.js.map +1 -1
- package/dist/consent.d.ts +217 -0
- package/dist/consent.js +400 -1
- package/dist/consent.js.map +1 -1
- package/dist/copy/error_codes.d.ts +222 -0
- package/dist/copy/error_codes.js +105 -0
- package/dist/copy/error_codes.js.map +1 -0
- package/dist/copy/index.d.ts +2 -2
- package/dist/copy/index.js +2 -2
- package/dist/copy/index.js.map +1 -1
- package/dist/copy/strings.d.ts +617 -30
- package/dist/copy/strings.js +741 -36
- package/dist/copy/strings.js.map +1 -1
- package/dist/copy/time.d.ts +11 -0
- package/dist/copy/time.js +18 -0
- package/dist/copy/time.js.map +1 -1
- package/dist/credential.d.ts +5 -1
- package/dist/credential.js +2 -2
- package/dist/credential.js.map +1 -1
- package/dist/git.d.ts +43 -0
- package/dist/git.js +95 -0
- package/dist/git.js.map +1 -1
- package/dist/grants_sync.d.ts +165 -0
- package/dist/grants_sync.js +289 -0
- package/dist/grants_sync.js.map +1 -0
- package/dist/grants_verb.d.ts +70 -0
- package/dist/grants_verb.js +121 -0
- package/dist/grants_verb.js.map +1 -0
- package/dist/hooks/entry.d.ts +18 -1
- package/dist/hooks/entry.js +117 -14
- package/dist/hooks/entry.js.map +1 -1
- package/dist/hooks/post_commit.js +3 -3
- package/dist/hooks/post_commit.js.map +1 -1
- package/dist/hooks/post_rewrite.js +6 -4
- package/dist/hooks/post_rewrite.js.map +1 -1
- package/dist/hooks/session_grants.d.ts +59 -0
- package/dist/hooks/session_grants.js +91 -0
- package/dist/hooks/session_grants.js.map +1 -0
- package/dist/hooks/session_start.d.ts +114 -0
- package/dist/hooks/session_start.js +243 -0
- package/dist/hooks/session_start.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +76 -11
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +57 -0
- package/dist/install.js +54 -20
- package/dist/install.js.map +1 -1
- package/dist/json.d.ts +32 -9
- package/dist/json.js +35 -8
- package/dist/json.js.map +1 -1
- package/dist/machine_state.d.ts +52 -0
- package/dist/machine_state.js +63 -0
- package/dist/machine_state.js.map +1 -0
- package/dist/oauth/retire.d.ts +10 -0
- package/dist/oauth/retire.js +13 -0
- package/dist/oauth/retire.js.map +1 -1
- package/dist/oauth/session.d.ts +1 -0
- package/dist/org_pending.d.ts +52 -0
- package/dist/org_pending.js +109 -0
- package/dist/org_pending.js.map +1 -0
- package/dist/paths.d.ts +70 -0
- package/dist/paths.js +90 -0
- package/dist/paths.js.map +1 -1
- package/dist/pending_revoke.d.ts +117 -0
- package/dist/pending_revoke.js +233 -0
- package/dist/pending_revoke.js.map +1 -0
- package/dist/pending_revoke_file.d.ts +55 -0
- package/dist/pending_revoke_file.js +74 -0
- package/dist/pending_revoke_file.js.map +1 -0
- package/dist/picker.d.ts +208 -0
- package/dist/picker.js +526 -0
- package/dist/picker.js.map +1 -0
- package/dist/picker_checklist.d.ts +141 -0
- package/dist/picker_checklist.js +411 -0
- package/dist/picker_checklist.js.map +1 -0
- package/dist/policy.d.ts +70 -1
- package/dist/policy.js +68 -2
- package/dist/policy.js.map +1 -1
- package/dist/post.d.ts +91 -18
- package/dist/post.js +259 -27
- package/dist/post.js.map +1 -1
- package/dist/state.d.ts +6 -0
- package/dist/state.js +38 -1
- package/dist/state.js.map +1 -1
- package/dist/system_message.d.ts +32 -2
- package/dist/system_message.js +47 -5
- package/dist/system_message.js.map +1 -1
- package/dist/term.d.ts +28 -2
- package/dist/term.js +23 -2
- package/dist/term.js.map +1 -1
- package/dist/verb_help.d.ts +13 -0
- package/dist/verb_help.js +40 -0
- package/dist/verb_help.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -9
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
* `commands/connect.ts`'s own `findCurrentTranscript` verbatim except for the
|
|
8
8
|
* confinement call, which now runs against the registry's union.
|
|
9
9
|
*/
|
|
10
|
-
import { readdirSync, statSync } from "node:fs";
|
|
10
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
11
11
|
import { basename, join } from "node:path";
|
|
12
|
-
import { claudeSettingsPath, isInside, isTranscriptFile, transcriptRoot } from "../paths.js";
|
|
12
|
+
import { claudeConfigPath, claudeSettingsPath, isInside, isTranscriptFile, transcriptRoot, } from "../paths.js";
|
|
13
|
+
import { readEntries, sessionFile, subdirectories } from "./session_listing.js";
|
|
13
14
|
/**
|
|
14
15
|
* The client-side backstop, per event.
|
|
15
16
|
*
|
|
@@ -38,16 +39,66 @@ const CLAUDE_CLIENT_BUDGET_MS = 5_000;
|
|
|
38
39
|
const CLAUDE_REGISTERED_STOP_MS = 8_000;
|
|
39
40
|
const CLAUDE_REGISTERED_PRECOMPACT_MS = 8_000;
|
|
40
41
|
const CLAUDE_REGISTERED_SESSION_END_MS = 10_000;
|
|
42
|
+
/**
|
|
43
|
+
* `SessionStart` reuses `Stop`'s two clocks and has no fast path of its own.
|
|
44
|
+
*
|
|
45
|
+
* ⛔ **A logged shortcut** — gstack-shortcut(dec-e650afbf), eng review D7 · B,
|
|
46
|
+
* Alexander's choice over a 1.5 s cap. The ceiling: a hung `SessionStart` can
|
|
47
|
+
* hold a session's start up by as long as the REGISTERED timeout (8 s here).
|
|
48
|
+
* Upgrade when a measurement or a user report shows session-start delay, or
|
|
49
|
+
* before slice 2's grants fetch is built into this handler.
|
|
50
|
+
*/
|
|
51
|
+
const CLAUDE_REGISTERED_SESSION_START_MS = CLAUDE_REGISTERED_STOP_MS; // gstack-shortcut(dec-e650afbf)
|
|
52
|
+
/**
|
|
53
|
+
* The longest folder name Claude Code writes verbatim.
|
|
54
|
+
*
|
|
55
|
+
* ⛔ **MEASURED (Open Question 3, VS, 2026-10-24).** An encoded path that would
|
|
56
|
+
* pass 200 characters is cut to 200, then `-`, then 6 hash characters (a
|
|
57
|
+
* measured name was 207 long, `…-x911fg`). The hash is not invertible from here,
|
|
58
|
+
* so such a folder cannot be matched to a path — and so a name LONGER than this
|
|
59
|
+
* is always a hashed one, since a verbatim name never exceeds it.
|
|
60
|
+
*/
|
|
61
|
+
export const CLAUDE_NAME_LIMIT = 200;
|
|
62
|
+
/**
|
|
63
|
+
* The folder name Claude Code gives a project path — Open Question 3.
|
|
64
|
+
*
|
|
65
|
+
* ⛔ **EVERY UTF-16 CODE UNIT OUTSIDE `[A-Za-z0-9]` BECOMES ONE `-`.** Measured by
|
|
66
|
+
* running throwaway sessions in folders named with `. _`, a space, `@ + ~ ( ) ' =
|
|
67
|
+
* , # % &`, `é` and an emoji: all of them, and the emoji TWICE, because the
|
|
68
|
+
* regular expression below runs over code units (no `u` flag) and an emoji is
|
|
69
|
+
* two. Runs do NOT collapse (`501/-Users` gave `501--Users`), a literal `-` stays
|
|
70
|
+
* itself, case is kept, and a leading `/` gives a leading `-`.
|
|
71
|
+
*
|
|
72
|
+
* ⚠ **This replaces `/[/.]/g`, which was the rule the first version of
|
|
73
|
+
* `locateCurrentTranscript` derived from 17 folders none of which held anything
|
|
74
|
+
* else.** For a repo whose path held an `_` or a space, `connect`'s test capture
|
|
75
|
+
* looked in a folder that does not exist and skipped the beat (a 0.6.x defect;
|
|
76
|
+
* `test/scan-encodings.test.ts` carries its regression cell).
|
|
77
|
+
*
|
|
78
|
+
* ⚠ **It returns the FULL encoding even past the limit**, and the callers decide
|
|
79
|
+
* what that means: `locateCurrentTranscript` cannot find a hashed folder, and the
|
|
80
|
+
* scan's walk compares PREFIXES of a name that is itself at most the limit, so a
|
|
81
|
+
* longer prefix simply never matches. One function, no second spelling of the rule.
|
|
82
|
+
*/
|
|
83
|
+
export function encodeProjectPath(path) {
|
|
84
|
+
return path.replace(/[^A-Za-z0-9]/g, "-");
|
|
85
|
+
}
|
|
86
|
+
/** Is this folder name one Claude Code cut and hashed? See `CLAUDE_NAME_LIMIT`. */
|
|
87
|
+
export function isHashedProjectName(name) {
|
|
88
|
+
return name.length > CLAUDE_NAME_LIMIT;
|
|
89
|
+
}
|
|
41
90
|
/**
|
|
42
91
|
* The transcript for the session running right now.
|
|
43
92
|
*
|
|
44
93
|
* A hook is HANDED `transcript_path` on stdin. `connect` is typed by a human and
|
|
45
94
|
* gets nothing, so it has to find one: Claude Code stores transcripts at
|
|
46
95
|
* `<transcriptRoot>/<encoded-project-path>/<session-id>.jsonl`, where the
|
|
47
|
-
* encoding
|
|
48
|
-
* directory on this machine against the `cwd` its transcripts
|
|
49
|
-
* matched exactly, and both misses were sessions whose `cwd`
|
|
50
|
-
* not a different encoding.
|
|
96
|
+
* encoding is `encodeProjectPath` above. The first version of that was derived
|
|
97
|
+
* by comparing every directory on this machine against the `cwd` its transcripts
|
|
98
|
+
* record — 15 of 17 matched exactly, and both misses were sessions whose `cwd`
|
|
99
|
+
* MOVED mid-session, not a different encoding. ⚠ Seventeen folders cannot
|
|
100
|
+
* contain a character none of them had: see `encodeProjectPath` for what that
|
|
101
|
+
* assumption cost.
|
|
51
102
|
*
|
|
52
103
|
* Which is also why this looks up the directory for THIS project rather than
|
|
53
104
|
* taking the newest transcript anywhere: a session that started in another
|
|
@@ -70,7 +121,13 @@ const CLAUDE_REGISTERED_SESSION_END_MS = 10_000;
|
|
|
70
121
|
*/
|
|
71
122
|
function locateCurrentTranscript(home, env, projectKey) {
|
|
72
123
|
const root = transcriptRoot(home, env);
|
|
73
|
-
const
|
|
124
|
+
const name = encodeProjectPath(projectKey);
|
|
125
|
+
// A hashed folder name cannot be derived from the path, so there is nothing to
|
|
126
|
+
// look in. `connect` then skips the test-capture beat, as it does for an agent
|
|
127
|
+
// with no locator, rather than guessing a sibling.
|
|
128
|
+
if (isHashedProjectName(name))
|
|
129
|
+
return null;
|
|
130
|
+
const dir = join(root, name);
|
|
74
131
|
let entries;
|
|
75
132
|
try {
|
|
76
133
|
entries = readdirSync(dir);
|
|
@@ -129,6 +186,70 @@ function claudeSessionIdFromEnv(env) {
|
|
|
129
186
|
const value = raw.trim();
|
|
130
187
|
return value === "" ? null : value;
|
|
131
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* The folders Claude Code has recorded running in: the KEYS of `~/.claude.json`'s
|
|
191
|
+
* `projects` map, and nothing else.
|
|
192
|
+
*
|
|
193
|
+
* ⛔ **Keys only.** The file also holds account and onboarding state, none of
|
|
194
|
+
* which this client has any use for. Nothing but the key strings leaves this
|
|
195
|
+
* function, and a failure of any kind is an empty list: the signal then simply
|
|
196
|
+
* does not fire, which skips less. ⚠ **No error is ever surfaced or logged** — Node
|
|
197
|
+
* 22's `JSON.parse` message quotes the text it failed on, and this file is not
|
|
198
|
+
* one whose text belongs on a screen.
|
|
199
|
+
*/
|
|
200
|
+
function recordedProjectPaths(home, env) {
|
|
201
|
+
try {
|
|
202
|
+
const parsed = JSON.parse(readFileSync(claudeConfigPath(home, env), "utf8"));
|
|
203
|
+
const projects = typeof parsed === "object" && parsed !== null
|
|
204
|
+
? parsed.projects
|
|
205
|
+
: undefined;
|
|
206
|
+
return typeof projects === "object" && projects !== null ? Object.keys(projects) : [];
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Claude Code's sessions, by folder — `D11 · A`, `scan`.
|
|
214
|
+
*
|
|
215
|
+
* `<root>/<encoded path>/<session-id>.jsonl`. Only the files DIRECTLY in a
|
|
216
|
+
* project folder are sessions: `<session-id>/subagents/…` holds delegated work
|
|
217
|
+
* that belongs to a parent session (`CR-124`), and counting it would turn one
|
|
218
|
+
* session into several. A legacy `agent-*.jsonl` sidechain at this level is
|
|
219
|
+
* excluded for the same reason.
|
|
220
|
+
*
|
|
221
|
+
* ⛔ **Names and times only.** The folder name is returned still ENCODED; whether
|
|
222
|
+
* it resolves to a path is the scan engine's walk, against the filesystem, never
|
|
223
|
+
* against a transcript's own `cwd` record (D60 §D6).
|
|
224
|
+
*/
|
|
225
|
+
function claudeSessionSource(home, env) {
|
|
226
|
+
const root = transcriptRoot(home, env);
|
|
227
|
+
const folders = [];
|
|
228
|
+
try {
|
|
229
|
+
for (const folder of subdirectories(root)) {
|
|
230
|
+
const sessions = [];
|
|
231
|
+
for (const entry of readEntries(folder.path) ?? []) {
|
|
232
|
+
if (!entry.name.endsWith(".jsonl") || entry.name.startsWith("agent-"))
|
|
233
|
+
continue;
|
|
234
|
+
const session = sessionFile(join(folder.path, entry.name));
|
|
235
|
+
if (session !== null)
|
|
236
|
+
sessions.push(session);
|
|
237
|
+
}
|
|
238
|
+
if (sessions.length > 0)
|
|
239
|
+
folders.push({ name: folder.name, sessions });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
return { kind: "unreadable", reason: "unreadable" };
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
kind: "folders",
|
|
247
|
+
folders,
|
|
248
|
+
encode: encodeProjectPath,
|
|
249
|
+
isHashed: isHashedProjectName,
|
|
250
|
+
recorded: recordedProjectPaths(home, env),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
132
253
|
export const CLAUDE_CODE = {
|
|
133
254
|
id: "claude-code",
|
|
134
255
|
transport: "ndjson",
|
|
@@ -143,7 +264,12 @@ export const CLAUDE_CODE = {
|
|
|
143
264
|
// agent the client was built for. Declared explicitly rather than defaulted so
|
|
144
265
|
// that a dialect added later must ANSWER the question; a default would let a
|
|
145
266
|
// camelCase agent inherit Claude's spellings and match nothing (`CR-195`).
|
|
146
|
-
eventNames: {
|
|
267
|
+
eventNames: {
|
|
268
|
+
Stop: "Stop",
|
|
269
|
+
PreCompact: "PreCompact",
|
|
270
|
+
SessionEnd: "SessionEnd",
|
|
271
|
+
SessionStart: "SessionStart",
|
|
272
|
+
},
|
|
147
273
|
// ⛔ `~/.claude/settings.json`, honouring `CLAUDE_CONFIG_DIR`. ⚠ This is the
|
|
148
274
|
// file the PLUGIN path does not need — the plugin ships its own `hooks.json`
|
|
149
275
|
// — and the npm path had no writer at all, which is the defect `/install`
|
|
@@ -162,12 +288,19 @@ export const CLAUDE_CODE = {
|
|
|
162
288
|
registeredTimeoutMs: CLAUDE_REGISTERED_SESSION_END_MS,
|
|
163
289
|
clientBudgetMs: CLAUDE_CLIENT_BUDGET_MS,
|
|
164
290
|
},
|
|
291
|
+
// MEASURED (Open Question 1, 2.1.309): fires before the first prompt in `-p`
|
|
292
|
+
// and the TUI, and accepts `systemMessage`. gstack-shortcut(dec-e650afbf).
|
|
293
|
+
SessionStart: {
|
|
294
|
+
registeredTimeoutMs: CLAUDE_REGISTERED_SESSION_START_MS,
|
|
295
|
+
clientBudgetMs: CLAUDE_CLIENT_BUDGET_MS,
|
|
296
|
+
},
|
|
165
297
|
},
|
|
166
298
|
// `<session>/subagents/agent-*.jsonl`, globbed — the paths are never handed
|
|
167
299
|
// over. `CR-124`, D76.
|
|
168
300
|
delegatedTranscripts: "discover",
|
|
169
301
|
redaction: "claude-code",
|
|
170
302
|
sessionIdFromEnv: claudeSessionIdFromEnv,
|
|
303
|
+
sessionSource: claudeSessionSource,
|
|
171
304
|
locateCurrentTranscript,
|
|
172
305
|
};
|
|
173
306
|
//# sourceMappingURL=claude_code.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude_code.js","sourceRoot":"","sources":["../../src/agents/claude_code.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"claude_code.js","sourceRoot":"","sources":["../../src/agents/claude_code.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,4 +12,17 @@
|
|
|
12
12
|
* reader can check them against the product rather than against this file.
|
|
13
13
|
*/
|
|
14
14
|
import type { TranscriptDialect } from "./types.js";
|
|
15
|
+
/**
|
|
16
|
+
* ⛔ **THE FOUR COLUMNS, AND NO OTHER — `D11 · A`, Alexander's approved read.**
|
|
17
|
+
*
|
|
18
|
+
* The thread index also holds `first_user_message`, `title`, `preview` and more,
|
|
19
|
+
* which are CONTENT. Selecting one would turn a metadata read into a transcript
|
|
20
|
+
* read, so the statement names exactly these four and `test/scan-codex-index.test.ts`
|
|
21
|
+
* asserts the SQL carries nothing else. ⚠ **`archived` is not here either, on
|
|
22
|
+
* purpose** (VQ, 2026-10-24): an archived thread's `rollout_path` is decided by
|
|
23
|
+
* the admission below, and a fifth column would change the approved read surface.
|
|
24
|
+
*/
|
|
25
|
+
export declare const CODEX_INDEX_COLUMNS: readonly ["cwd", "git_origin_url", "rollout_path", "created_at"];
|
|
26
|
+
/** The one statement the adapter runs against a thread row. */
|
|
27
|
+
export declare const CODEX_INDEX_SQL: string;
|
|
15
28
|
export declare const CODEX_CLI: TranscriptDialect;
|
package/dist/agents/codex_cli.js
CHANGED
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
* measured by this task.** They are recorded as the brief stated them so a later
|
|
12
12
|
* reader can check them against the product rather than against this file.
|
|
13
13
|
*/
|
|
14
|
-
import {
|
|
14
|
+
import { readdirSync, realpathSync } from "node:fs";
|
|
15
|
+
import { createRequire } from "node:module";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { CODEX_INDEX_FILE, codexHooksPath, codexIndexDir, codexTranscriptRoot, isInside, isTranscriptFile, } from "../paths.js";
|
|
18
|
+
import { readEntries, sessionFile } from "./session_listing.js";
|
|
15
19
|
/**
|
|
16
20
|
* `SessionEnd` is the tight one — 3 s registered, 2.2 s client.
|
|
17
21
|
*
|
|
@@ -24,6 +28,226 @@ const CODEX_SESSION_END_CLIENT_MS = 2_200;
|
|
|
24
28
|
/** `Stop` and `PreCompact` are registered far wider — 30 s, client 8 s. */
|
|
25
29
|
const CODEX_TURN_REGISTERED_MS = 30_000;
|
|
26
30
|
const CODEX_TURN_CLIENT_MS = 8_000;
|
|
31
|
+
/**
|
|
32
|
+
* `SessionStart` takes the turn clocks, with no fast path of its own.
|
|
33
|
+
*
|
|
34
|
+
* ⛔ **A logged shortcut** — gstack-shortcut(dec-e650afbf), eng review D7 · B.
|
|
35
|
+
* The ceiling: a hung `SessionStart` can hold a session's start up by as long as
|
|
36
|
+
* the REGISTERED timeout (30 s here). Upgrade when a measurement or a user report
|
|
37
|
+
* shows session-start delay, or before slice 2's grants fetch lands in this handler.
|
|
38
|
+
*/
|
|
39
|
+
const CODEX_SESSION_START_REGISTERED_MS = CODEX_TURN_REGISTERED_MS; // gstack-shortcut(dec-e650afbf)
|
|
40
|
+
const CODEX_SESSION_START_CLIENT_MS = CODEX_TURN_CLIENT_MS; // gstack-shortcut(dec-e650afbf)
|
|
41
|
+
/**
|
|
42
|
+
* ⛔ **THE FOUR COLUMNS, AND NO OTHER — `D11 · A`, Alexander's approved read.**
|
|
43
|
+
*
|
|
44
|
+
* The thread index also holds `first_user_message`, `title`, `preview` and more,
|
|
45
|
+
* which are CONTENT. Selecting one would turn a metadata read into a transcript
|
|
46
|
+
* read, so the statement names exactly these four and `test/scan-codex-index.test.ts`
|
|
47
|
+
* asserts the SQL carries nothing else. ⚠ **`archived` is not here either, on
|
|
48
|
+
* purpose** (VQ, 2026-10-24): an archived thread's `rollout_path` is decided by
|
|
49
|
+
* the admission below, and a fifth column would change the approved read surface.
|
|
50
|
+
*/
|
|
51
|
+
export const CODEX_INDEX_COLUMNS = ["cwd", "git_origin_url", "rollout_path", "created_at"];
|
|
52
|
+
/** The one statement the adapter runs against a thread row. */
|
|
53
|
+
export const CODEX_INDEX_SQL = `SELECT ${CODEX_INDEX_COLUMNS.join(", ")} FROM threads`;
|
|
54
|
+
/** How long a locked index is waited for before the adapter gives up (eng review D2). */
|
|
55
|
+
const CODEX_BUSY_TIMEOUT_MS = 1_000;
|
|
56
|
+
/**
|
|
57
|
+
* `node:sqlite`, loaded here and nowhere else, with ITS warning and only its
|
|
58
|
+
* warning dropped — eng review D2 · A.
|
|
59
|
+
*
|
|
60
|
+
* Node 22 prints `ExperimentalWarning: SQLite is an experimental feature…` to
|
|
61
|
+
* stderr the first time the module loads, which would land mid-screen in the
|
|
62
|
+
* picker and breaks DESIGN.md §13's output rules. `process.emitWarning` is
|
|
63
|
+
* wrapped for the duration of the one `require` and restored in a `finally`;
|
|
64
|
+
* any OTHER warning, in that window or after it, still prints. Measured on
|
|
65
|
+
* node 22.17.0.
|
|
66
|
+
*
|
|
67
|
+
* ⚠ **A `require` and not a dynamic `import()`**, so the whole adapter stays
|
|
68
|
+
* synchronous like every other lister (`scan` is a chain of `execFileSync`
|
|
69
|
+
* anyway) and the wrapped window is exactly the load, not a promise turn that
|
|
70
|
+
* something else could emit a warning inside. Lazy: a machine with no Codex
|
|
71
|
+
* never loads the module at all.
|
|
72
|
+
*/
|
|
73
|
+
function loadSqlite() {
|
|
74
|
+
const original = process.emitWarning;
|
|
75
|
+
process.emitWarning = ((warning, ...rest) => {
|
|
76
|
+
const type = typeof warning === "string" ? rest[0] : warning.name;
|
|
77
|
+
const message = typeof warning === "string" ? warning : warning.message;
|
|
78
|
+
if (type === "ExperimentalWarning" && message.startsWith("SQLite"))
|
|
79
|
+
return;
|
|
80
|
+
return original.call(process, warning, ...rest);
|
|
81
|
+
});
|
|
82
|
+
try {
|
|
83
|
+
return createRequire(import.meta.url)("node:sqlite");
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
process.emitWarning = original;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Does the `threads` table carry all four columns? A bare name test, nothing deeper. */
|
|
90
|
+
function hasIndexColumns(db) {
|
|
91
|
+
const present = new Set(db.prepare("PRAGMA table_info(threads)").all().map((c) => String(c.name)));
|
|
92
|
+
return CODEX_INDEX_COLUMNS.every((column) => present.has(column));
|
|
93
|
+
}
|
|
94
|
+
/** A locked database is a different line from an unrecognised one. */
|
|
95
|
+
function readFailure(err) {
|
|
96
|
+
return /locked|busy/i.test(err instanceof Error ? err.message : "")
|
|
97
|
+
? "index locked"
|
|
98
|
+
: "unreadable";
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Rollout files under `sessions/` that NO index row names — counted, never opened.
|
|
102
|
+
*
|
|
103
|
+
* Open Question 6's text, as VQ ruled (PR 1 ruling 5c): an index which cannot see a
|
|
104
|
+
* session is a thing to REPORT, not to guess about. The walk lists directory entries — names
|
|
105
|
+
* and file types, nothing else — and counts each regular `.jsonl`; a symlink is
|
|
106
|
+
* not a file here (`Dirent.isFile` is false for it).
|
|
107
|
+
*
|
|
108
|
+
* Compared as REALPATHS on both sides, because the index stores the path Codex
|
|
109
|
+
* wrote and the walk builds its own from `home`; a symlinked home would otherwise
|
|
110
|
+
* make every rollout look unindexed. A row whose rollout has gone cannot be
|
|
111
|
+
* resolved and names nothing, which is correct: it is not on disk to be matched.
|
|
112
|
+
*/
|
|
113
|
+
function countUnindexed(root, rolloutPaths) {
|
|
114
|
+
const named = new Set();
|
|
115
|
+
for (const path of rolloutPaths) {
|
|
116
|
+
try {
|
|
117
|
+
named.add(realpathSync(path));
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Gone from disk: it names no file that the walk could find.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
let base;
|
|
124
|
+
try {
|
|
125
|
+
base = realpathSync(root);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
let count = 0;
|
|
131
|
+
const visit = (dir) => {
|
|
132
|
+
let entries;
|
|
133
|
+
try {
|
|
134
|
+
entries = readEntries(dir);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
for (const entry of entries ?? []) {
|
|
140
|
+
const path = join(dir, entry.name);
|
|
141
|
+
if (entry.isDirectory())
|
|
142
|
+
visit(path);
|
|
143
|
+
else if (entry.isFile() && entry.name.endsWith(".jsonl") && !named.has(path))
|
|
144
|
+
count += 1;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
visit(base);
|
|
148
|
+
return count;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Codex's sessions, from its thread index — `D11 · A`, eng review D2, `scan`.
|
|
152
|
+
*
|
|
153
|
+
* Codex keeps rollouts DATE-keyed (`sessions/YYYY/MM/DD/`), so a folder walk
|
|
154
|
+
* cannot say which repo one belongs to; its `threads` table can, because it
|
|
155
|
+
* records the real `cwd`. That row is the whole reason this adapter exists and
|
|
156
|
+
* the reason a Codex row is never ambiguous.
|
|
157
|
+
*
|
|
158
|
+
* ## ⛔ What is read, and how
|
|
159
|
+
*
|
|
160
|
+
* - **exactly `state_5.sqlite`**, and any other `state_N` is `unrecognised
|
|
161
|
+
* index` (Open Question 6; see `codexIndexDir`).
|
|
162
|
+
* - **`readOnly`, never `immutable`.** Codex keeps everything since its last
|
|
163
|
+
* checkpoint in the `-wal` file (on the author's machine, every thread since
|
|
164
|
+
* Sep 30), and an `immutable` open ignores it.
|
|
165
|
+
* - **the four columns only** (`CODEX_INDEX_SQL`), after a `PRAGMA table_info`
|
|
166
|
+
* check, and a 1000 ms busy timeout. Any failure is this agent's
|
|
167
|
+
* `unreadable` answer, so the other two agents' rows are untouched.
|
|
168
|
+
*
|
|
169
|
+
* ## ⛔ The rollout file is `lstat`ed, never opened
|
|
170
|
+
*
|
|
171
|
+
* A row is admitted only if its `rollout_path` lies under the sessions root and
|
|
172
|
+
* is a regular file there. That is also what decides an ARCHIVED thread, whose
|
|
173
|
+
* rollout is not under `sessions/`. The row's `git_origin_url` is carried but is
|
|
174
|
+
* not the slug source: the scan names a repo from the CLONE (`resolveRepoSlug`),
|
|
175
|
+
* so there is one normalisation and not two.
|
|
176
|
+
*/
|
|
177
|
+
function codexSessionSource(home, env) {
|
|
178
|
+
const dir = codexIndexDir(home, env);
|
|
179
|
+
const file = join(dir, CODEX_INDEX_FILE);
|
|
180
|
+
let present;
|
|
181
|
+
try {
|
|
182
|
+
present = readdirSync(dir);
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
const code = err.code;
|
|
186
|
+
return code === "ENOENT" || code === "ENOTDIR"
|
|
187
|
+
? { kind: "rows", rows: [], unindexed: 0 }
|
|
188
|
+
: { kind: "unreadable", reason: "unreadable" };
|
|
189
|
+
}
|
|
190
|
+
if (!present.includes(CODEX_INDEX_FILE)) {
|
|
191
|
+
// A Codex that keeps its index under another generation's name is a store
|
|
192
|
+
// this client was not checked against. One with no index at all has simply
|
|
193
|
+
// never recorded a thread — and its rollouts, if any, are all unindexed.
|
|
194
|
+
return present.some((name) => /^state_\d+\.sqlite$/.test(name))
|
|
195
|
+
? { kind: "unreadable", reason: "unrecognised index" }
|
|
196
|
+
: { kind: "rows", rows: [], unindexed: countUnindexed(codexTranscriptRoot(home, env), []) };
|
|
197
|
+
}
|
|
198
|
+
let sqlite;
|
|
199
|
+
try {
|
|
200
|
+
sqlite = loadSqlite();
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return { kind: "unreadable", reason: "unreadable" };
|
|
204
|
+
}
|
|
205
|
+
let db = null;
|
|
206
|
+
try {
|
|
207
|
+
// ⚠ `readOnly` stops THIS CODE writing the index and does not stop SQLite creating its own
|
|
208
|
+
// `-wal`/`-shm` files beside it, which any reader of a WAL database whose writer has closed does
|
|
209
|
+
// (measured by VQ on node 22.17, PR 1 F1). Nothing is written to `state_5.sqlite` itself.
|
|
210
|
+
db = new sqlite.DatabaseSync(file, { readOnly: true });
|
|
211
|
+
db.exec(`PRAGMA busy_timeout = ${CODEX_BUSY_TIMEOUT_MS}`);
|
|
212
|
+
if (!hasIndexColumns(db))
|
|
213
|
+
return { kind: "unreadable", reason: "unrecognised index" };
|
|
214
|
+
const root = codexTranscriptRoot(home, env);
|
|
215
|
+
const rows = [];
|
|
216
|
+
const named = [];
|
|
217
|
+
for (const row of db.prepare(CODEX_INDEX_SQL).all()) {
|
|
218
|
+
const { cwd, git_origin_url: origin, rollout_path: rollout, created_at: created } = row;
|
|
219
|
+
if (typeof cwd !== "string" || typeof rollout !== "string")
|
|
220
|
+
continue;
|
|
221
|
+
// Every path an index row names counts as INDEXED, admitted or not: an archived thread's rollout
|
|
222
|
+
// is not "missing from the index", it is simply not capturable (`D11 · A`).
|
|
223
|
+
named.push(rollout);
|
|
224
|
+
if (!isInside(root, rollout) || !isTranscriptFile(root, rollout))
|
|
225
|
+
continue;
|
|
226
|
+
const session = sessionFile(rollout);
|
|
227
|
+
if (session === null)
|
|
228
|
+
continue;
|
|
229
|
+
rows.push({
|
|
230
|
+
cwd,
|
|
231
|
+
origin: typeof origin === "string" ? origin : null,
|
|
232
|
+
// `created_at` is whole SECONDS (measured), the rest of this client's
|
|
233
|
+
// times are milliseconds.
|
|
234
|
+
session: typeof created === "number" ? { ...session, startedMs: created * 1000 } : session,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return { kind: "rows", rows, unindexed: countUnindexed(root, named) };
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
return { kind: "unreadable", reason: readFailure(err) };
|
|
241
|
+
}
|
|
242
|
+
finally {
|
|
243
|
+
try {
|
|
244
|
+
db?.close();
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// Closing a read-only handle that failed to open is not a second finding.
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
27
251
|
export const CODEX_CLI = {
|
|
28
252
|
id: "codex-cli",
|
|
29
253
|
transport: "ndjson",
|
|
@@ -46,7 +270,17 @@ export const CODEX_CLI = {
|
|
|
46
270
|
// against three throwaway `CODEX_HOME`s settled it: `SessionEnd` is recognised
|
|
47
271
|
// and says so by clamping, while `session_end` and a bogus key produce NO
|
|
48
272
|
// diagnostic — a file that parses, registers nothing, and reports success.
|
|
49
|
-
|
|
273
|
+
// `SessionStart` is in that schema list too, spelled the same way, and MEASURED
|
|
274
|
+
// live (Open Question 1, Codex 0.148.0): it fires before the first prompt — in
|
|
275
|
+
// the TUI lazily, when the first prompt is submitted — and accepts a
|
|
276
|
+
// `systemMessage`. ⚠ Those runs were under cmux's `--dangerously-bypass-hook-trust`;
|
|
277
|
+
// stock Codex >= 0.131.0 runs a user-level hook only after the user trusts it.
|
|
278
|
+
eventNames: {
|
|
279
|
+
Stop: "Stop",
|
|
280
|
+
PreCompact: "PreCompact",
|
|
281
|
+
SessionEnd: "SessionEnd",
|
|
282
|
+
SessionStart: "SessionStart",
|
|
283
|
+
},
|
|
50
284
|
// ⛔ `~/.codex/hooks.json`, honouring `CODEX_HOME` — MEASURED, since every
|
|
51
285
|
// probe in this unit drove a real `codex` through a throwaway `CODEX_HOME`
|
|
52
286
|
// and it read the `hooks.json` there. The NESTED shape, also measured: a
|
|
@@ -66,6 +300,10 @@ export const CODEX_CLI = {
|
|
|
66
300
|
registeredTimeoutMs: CODEX_SESSION_END_REGISTERED_MS,
|
|
67
301
|
clientBudgetMs: CODEX_SESSION_END_CLIENT_MS,
|
|
68
302
|
},
|
|
303
|
+
SessionStart: {
|
|
304
|
+
registeredTimeoutMs: CODEX_SESSION_START_REGISTERED_MS,
|
|
305
|
+
clientBudgetMs: CODEX_SESSION_START_CLIENT_MS,
|
|
306
|
+
},
|
|
69
307
|
},
|
|
70
308
|
// The delegated path ARRIVES on stdin as `agent_transcript_path` — there is no
|
|
71
309
|
// directory to glob. Nothing parses it yet; the discriminator is here so the
|
|
@@ -79,6 +317,7 @@ export const CODEX_CLI = {
|
|
|
79
317
|
// of a measurement, not as a fact about the agent. Measuring it is a change to
|
|
80
318
|
// this line and nothing else.
|
|
81
319
|
sessionIdFromEnv: () => null,
|
|
320
|
+
sessionSource: codexSessionSource,
|
|
82
321
|
// ⛔ NO `locateCurrentTranscript`, and the omission is the decision. Finding
|
|
83
322
|
// the repository would mean reading a `cwd` out of the transcript's own
|
|
84
323
|
// records — ANALYSIS, which D60 §D6 forbids this client. `connect` therefore
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex_cli.js","sourceRoot":"","sources":["../../src/agents/codex_cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"codex_cli.js","sourceRoot":"","sources":["../../src/agents/codex_cli.ts"],"names":[],"mappings":"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"}
|
package/dist/agents/cursor.d.ts
CHANGED
|
@@ -18,4 +18,38 @@
|
|
|
18
18
|
* difference is marked on each member below rather than left to a reader.
|
|
19
19
|
*/
|
|
20
20
|
import type { TranscriptDialect } from "./types.js";
|
|
21
|
+
/**
|
|
22
|
+
* The longest folder name Cursor writes verbatim.
|
|
23
|
+
*
|
|
24
|
+
* ⛔ **MEASURED (Open Question 3, VS, 2026-10-24), with `cursor-agent`, which
|
|
25
|
+
* creates the project folder even when it is not logged in.** A name up to 61
|
|
26
|
+
* characters is kept; a longer one becomes its first 53 characters, `-`, and 7
|
|
27
|
+
* hex characters (the hash varied with the input, so it is not a constant).
|
|
28
|
+
*/
|
|
29
|
+
export declare const CURSOR_NAME_LIMIT = 61;
|
|
30
|
+
/**
|
|
31
|
+
* The folder name Cursor gives a workspace path — Open Question 3.
|
|
32
|
+
*
|
|
33
|
+
* ⛔ **THIS IS NOT CLAUDE CODE'S RULE, and the difference is the measurement.**
|
|
34
|
+
* Every RUN of non-alphanumerics, a literal `--` included, collapses to ONE `-`;
|
|
35
|
+
* leading and trailing separators are dropped (so `/tmp/q/trail.` is `…-trail`
|
|
36
|
+
* and there is no leading `-`); case is kept. An emoji and `é'` each gave a single
|
|
37
|
+
* dash where Claude Code gives two.
|
|
38
|
+
*
|
|
39
|
+
* ⚠ **Which makes Cursor's names collide far more:** `a-b`, `a.b`, `a--b` and
|
|
40
|
+
* `a.b.` are all one folder. The scan's walk encodes every directory entry with
|
|
41
|
+
* THIS function and matches on the result, so the collapsing applies to every
|
|
42
|
+
* candidate rather than being assumed away.
|
|
43
|
+
*/
|
|
44
|
+
export declare function encodeProjectPath(path: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Is this folder name one Cursor cut and hashed? See `CURSOR_NAME_LIMIT`.
|
|
47
|
+
*
|
|
48
|
+
* ⚠ **A hashed name is always exactly 61 long, and so is a verbatim name that
|
|
49
|
+
* happens to be 61 long** — length alone cannot tell them apart. The test is the
|
|
50
|
+
* hash's shape too (`-` and 7 hex). A verbatim 61-character name that ends the
|
|
51
|
+
* same way is read as hashed, which is the safe error: it is skipped and
|
|
52
|
+
* counted, never matched to a path it might not be.
|
|
53
|
+
*/
|
|
54
|
+
export declare function isHashedProjectName(name: string): boolean;
|
|
21
55
|
export declare const CURSOR: TranscriptDialect;
|