@mnemonik/shared 7.140.1 → 7.140.3
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/codeScanner.d.ts +46 -1
- package/dist/codeScanner.d.ts.map +1 -1
- package/dist/codeScanner.js +100 -12
- package/dist/codeScanner.js.map +1 -1
- package/dist/contextBudget.d.ts +2 -2
- package/dist/contextBudget.d.ts.map +1 -1
- package/dist/contextBudget.js +3 -4
- package/dist/contextBudget.js.map +1 -1
- package/dist/gitEditDetector.d.ts +11 -6
- package/dist/gitEditDetector.d.ts.map +1 -1
- package/dist/gitEditDetector.js +119 -9
- package/dist/gitEditDetector.js.map +1 -1
- package/dist/hookRuntime.d.ts +18 -8
- package/dist/hookRuntime.d.ts.map +1 -1
- package/dist/hookRuntime.js +31 -20
- package/dist/hookRuntime.js.map +1 -1
- package/dist/hookTrace.d.ts +149 -0
- package/dist/hookTrace.d.ts.map +1 -0
- package/dist/hookTrace.js +483 -0
- package/dist/hookTrace.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +1 -1
- package/dist/projectIdentityFile.d.ts +13 -0
- package/dist/projectIdentityFile.d.ts.map +1 -1
- package/dist/projectIdentityFile.js +31 -18
- package/dist/projectIdentityFile.js.map +1 -1
- package/dist/protectedPaths.d.ts +6 -0
- package/dist/protectedPaths.d.ts.map +1 -1
- package/dist/protectedPaths.js +15 -6
- package/dist/protectedPaths.js.map +1 -1
- package/dist/repositoryRoot.d.ts +20 -8
- package/dist/repositoryRoot.d.ts.map +1 -1
- package/dist/repositoryRoot.js +167 -79
- package/dist/repositoryRoot.js.map +1 -1
- package/dist/runtimeReader.d.ts +1 -1
- package/dist/runtimeReader.d.ts.map +1 -1
- package/dist/runtimeReader.js.map +1 -1
- package/package.json +2 -2
- package/src/codeScanner.ts +115 -9
- package/src/contextBudget.ts +3 -4
- package/src/gitEditDetector.ts +113 -8
- package/src/hookRuntime.ts +39 -27
- package/src/hookTrace.ts +588 -0
- package/src/index.ts +4 -0
- package/src/instructions.ts +1 -1
- package/src/projectIdentityFile.ts +34 -20
- package/src/protectedPaths.ts +18 -7
- package/src/repositoryRoot.ts +188 -82
- package/src/runtimeReader.ts +6 -1
- package/test-fixtures/identity/runner.d.mts +1 -1
- package/test-fixtures/identity/runner.mjs +299 -25
- package/tests/hookTrace.test.ts +350 -0
- package/tests/nearestProjectIdentity.test.ts +253 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
export type HookTraceHost = 'cursor' | 'claude-code' | 'codex' | 'copilot';
|
|
2
|
+
/** Past this size the file is renamed to `<host>.jsonl.1` (replacing any older one). */
|
|
3
|
+
export declare const HOOK_TRACE_MAX_BYTES: number;
|
|
4
|
+
export declare const HOOK_TRACE_ENV = "MNEMONIK_HOOK_TRACE";
|
|
5
|
+
export interface HookTraceCall {
|
|
6
|
+
/** URL path only; id-like segments become `:id`, never a query string. */
|
|
7
|
+
path: string;
|
|
8
|
+
status?: number;
|
|
9
|
+
/** `timeout`, `aborted`, a system code such as `ECONNREFUSED`, or an error name. */
|
|
10
|
+
error?: string;
|
|
11
|
+
/** Still waiting for an answer when the process exited. */
|
|
12
|
+
pending?: true;
|
|
13
|
+
ms: number;
|
|
14
|
+
}
|
|
15
|
+
export interface HookTraceOutput {
|
|
16
|
+
bytes: number;
|
|
17
|
+
/** Byte size of each output field set; nested host fields as `hookSpecificOutput.<name>`. */
|
|
18
|
+
sizes: Record<string, number>;
|
|
19
|
+
permission?: string;
|
|
20
|
+
decision?: string;
|
|
21
|
+
continue?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Written as the recorder starts, before stdin is read. */
|
|
24
|
+
export interface HookTraceStart {
|
|
25
|
+
v: 1;
|
|
26
|
+
phase: 'start';
|
|
27
|
+
ts: string;
|
|
28
|
+
host: HookTraceHost;
|
|
29
|
+
hookVersion?: string;
|
|
30
|
+
pid: number;
|
|
31
|
+
id: string;
|
|
32
|
+
/** From process start, including Node start-up and module load. */
|
|
33
|
+
processMs: number;
|
|
34
|
+
}
|
|
35
|
+
/** Written once stdin is read and the event is known. */
|
|
36
|
+
export interface HookTraceInput {
|
|
37
|
+
v: 1;
|
|
38
|
+
phase: 'input';
|
|
39
|
+
ts: string;
|
|
40
|
+
host: HookTraceHost;
|
|
41
|
+
pid: number;
|
|
42
|
+
id: string;
|
|
43
|
+
event: string | null;
|
|
44
|
+
hostVersion?: string;
|
|
45
|
+
sessionId?: string;
|
|
46
|
+
conversationId?: string;
|
|
47
|
+
generationId?: string;
|
|
48
|
+
agentId?: string;
|
|
49
|
+
turnId?: string;
|
|
50
|
+
tool?: string;
|
|
51
|
+
cwd?: string;
|
|
52
|
+
inputBytes: number;
|
|
53
|
+
/** Byte size of each top-level input field's JSON value. Values are never recorded. */
|
|
54
|
+
fields: Record<string, number>;
|
|
55
|
+
/** Time from the recorder starting to the event being known (mostly the stdin read). */
|
|
56
|
+
readMs: number;
|
|
57
|
+
}
|
|
58
|
+
export interface HookTraceEnd {
|
|
59
|
+
v: 1;
|
|
60
|
+
phase: 'end';
|
|
61
|
+
ts: string;
|
|
62
|
+
host: HookTraceHost;
|
|
63
|
+
pid: number;
|
|
64
|
+
id: string;
|
|
65
|
+
event: string | null;
|
|
66
|
+
projectId?: string;
|
|
67
|
+
output: HookTraceOutput | null;
|
|
68
|
+
calls: HookTraceCall[];
|
|
69
|
+
/** From the recorder starting (after module load) to exit. */
|
|
70
|
+
durationMs: number;
|
|
71
|
+
/** From process start, including Node start-up and module load. */
|
|
72
|
+
processMs: number;
|
|
73
|
+
exitCode: number;
|
|
74
|
+
/** Name or system code of the error the hook failed open on. */
|
|
75
|
+
errorKind?: string;
|
|
76
|
+
/** Its message, scrubbed and cut to 80 characters. */
|
|
77
|
+
error?: string;
|
|
78
|
+
}
|
|
79
|
+
export type HookTraceRecord = HookTraceStart | HookTraceInput | HookTraceEnd;
|
|
80
|
+
export declare function hookTraceEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
81
|
+
export declare function hookTraceDirectory(stateDir?: string): string;
|
|
82
|
+
export declare function hookTraceFile(host: HookTraceHost, stateDir?: string): string;
|
|
83
|
+
/** Append one line, rotating first when the file is full. Throws; callers swallow. */
|
|
84
|
+
export declare function appendHookTraceLine(file: string, record: HookTraceRecord): void;
|
|
85
|
+
/** Field names and sizes, the decision fields' short enum values, never text. */
|
|
86
|
+
export declare function summarizeHookOutput(text: string): HookTraceOutput;
|
|
87
|
+
export declare function errorKind(error: unknown): string;
|
|
88
|
+
/** The message, whitespace folded, secrets scrubbed, cut to 80 characters. */
|
|
89
|
+
export declare function scrubHookTraceMessage(error: unknown): string;
|
|
90
|
+
export interface HookTraceCallToken {
|
|
91
|
+
input: unknown;
|
|
92
|
+
startedAt: number;
|
|
93
|
+
}
|
|
94
|
+
export interface HookTraceOptions {
|
|
95
|
+
host: HookTraceHost;
|
|
96
|
+
hookVersion?: string;
|
|
97
|
+
env?: NodeJS.ProcessEnv;
|
|
98
|
+
stateDir?: string;
|
|
99
|
+
}
|
|
100
|
+
export declare class HookTrace {
|
|
101
|
+
private readonly host;
|
|
102
|
+
private readonly file;
|
|
103
|
+
private readonly hookVersion?;
|
|
104
|
+
private readonly id;
|
|
105
|
+
private readonly startedAt;
|
|
106
|
+
private opened;
|
|
107
|
+
private started;
|
|
108
|
+
private ended;
|
|
109
|
+
private event;
|
|
110
|
+
private outputSummary;
|
|
111
|
+
private error?;
|
|
112
|
+
private errorKind?;
|
|
113
|
+
private projectId?;
|
|
114
|
+
private readonly calls;
|
|
115
|
+
private readonly inFlight;
|
|
116
|
+
constructor(host: HookTraceHost, file: string | undefined, hookVersion?: string | undefined);
|
|
117
|
+
get enabled(): boolean;
|
|
118
|
+
private write;
|
|
119
|
+
/**
|
|
120
|
+
* Write the `start` line: pid, run id and time since process start, nothing
|
|
121
|
+
* from the editor. Runs before stdin is read, so a run killed while the
|
|
122
|
+
* editor is still sending its event leaves this line.
|
|
123
|
+
*/
|
|
124
|
+
open(): void;
|
|
125
|
+
/** Write the `input` line. `input` is the parsed payload, or null when none parsed. */
|
|
126
|
+
begin(input: unknown, event?: string | null): void;
|
|
127
|
+
/** The exact text the hook wrote to stdout (or nothing). */
|
|
128
|
+
output(text: string | null | undefined): void;
|
|
129
|
+
/** The error the hook failed open on. */
|
|
130
|
+
fail(error: unknown): void;
|
|
131
|
+
project(projectId: string | undefined): void;
|
|
132
|
+
/** A call has gone out; {@link settle} records it, {@link finish} records it as pending. */
|
|
133
|
+
callStarted(input: unknown): HookTraceCallToken;
|
|
134
|
+
settle(token: HookTraceCallToken, status?: number, error?: unknown): void;
|
|
135
|
+
call(input: unknown, startedAt: number, status?: number, error?: unknown): void;
|
|
136
|
+
/** Write the `end` line once. Runs from the process `exit` event. */
|
|
137
|
+
finish(exitCode?: number): void;
|
|
138
|
+
}
|
|
139
|
+
/** Resolved project ids reach the trace from the shared identity cache. */
|
|
140
|
+
export declare function noteHookTraceProject(projectId: string | undefined): void;
|
|
141
|
+
/**
|
|
142
|
+
* Start this process's recorder: one per hook process. Writes the `start`
|
|
143
|
+
* line at once (so call it before reading stdin), times every `fetch` the
|
|
144
|
+
* process makes (path, status or error kind, duration; `pending` when still
|
|
145
|
+
* waiting at exit) and writes the `end` line from the process `exit` event,
|
|
146
|
+
* so every exit path is covered.
|
|
147
|
+
*/
|
|
148
|
+
export declare function startHookTrace(options: HookTraceOptions): HookTrace;
|
|
149
|
+
//# sourceMappingURL=hookTrace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hookTrace.d.ts","sourceRoot":"","sources":["../src/hookTrace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook flight recorder: a bounded, local, append-only record of every hook
|
|
3
|
+
* invocation on this machine, so an agent or support can see what a real
|
|
4
|
+
* editor sent to the hooks and what they answered.
|
|
5
|
+
*
|
|
6
|
+
* One JSON Lines file per host under the Mnemonik state folder
|
|
7
|
+
* (`<state>/hook-trace/<host>.jsonl`, directory 0700, file 0600), rotated to a
|
|
8
|
+
* single `.1` file past {@link HOOK_TRACE_MAX_BYTES}. Each invocation writes
|
|
9
|
+
* up to three lines sharing one run `id`: `start` as soon as the recorder
|
|
10
|
+
* starts (before stdin is read, so a run the editor kills while it is still
|
|
11
|
+
* sending the event leaves a trace), `input` once the event is known, and
|
|
12
|
+
* `end` when the process exits. A run with no `end` is one the editor killed
|
|
13
|
+
* (a signal ends the process without Node's `exit` event); one with only
|
|
14
|
+
* `start` was killed before its event arrived.
|
|
15
|
+
*
|
|
16
|
+
* The record holds identifiers, field names and sizes only. It never holds
|
|
17
|
+
* prompt text, tool input or output bodies, file contents, transcript
|
|
18
|
+
* contents, credentials or the environment: payload values are reduced to
|
|
19
|
+
* their byte size, and the one free-text field (an error message) passes
|
|
20
|
+
* through `scrubSecrets`.
|
|
21
|
+
*
|
|
22
|
+
* Every write is synchronous and short (one line), and every failure is
|
|
23
|
+
* swallowed: the recorder can never throw into a hook or change its output.
|
|
24
|
+
* Being synchronous, a write to a hung network home directory would block the
|
|
25
|
+
* hook. `MNEMONIK_HOOK_TRACE=off` disables it.
|
|
26
|
+
*/
|
|
27
|
+
import { randomBytes } from 'node:crypto';
|
|
28
|
+
import { closeSync, constants, fstatSync, lstatSync, mkdirSync, openSync, renameSync, statSync, unlinkSync, writeSync, } from 'node:fs';
|
|
29
|
+
import { dirname, join } from 'node:path';
|
|
30
|
+
import { mnemonikStateDirectory } from './protectedPaths.js';
|
|
31
|
+
import { ensureWindowsPrivateDirectorySync } from './runtimeSigners.js';
|
|
32
|
+
import { scrubSecrets } from './secretPatterns.js';
|
|
33
|
+
/** Past this size the file is renamed to `<host>.jsonl.1` (replacing any older one). */
|
|
34
|
+
export const HOOK_TRACE_MAX_BYTES = 2 * 1024 * 1024;
|
|
35
|
+
export const HOOK_TRACE_ENV = 'MNEMONIK_HOOK_TRACE';
|
|
36
|
+
const MAX_FIELDS = 64;
|
|
37
|
+
const MAX_CALLS = 64;
|
|
38
|
+
const MAX_ERROR_CHARS = 80;
|
|
39
|
+
const SAFE_ID = /^[A-Za-z0-9@._+:-]{1,128}$/;
|
|
40
|
+
const SAFE_NAME = /^[A-Za-z0-9@._+:/-]{1,120}$/;
|
|
41
|
+
const SAFE_ENUM = /^[A-Za-z_]{1,24}$/;
|
|
42
|
+
export function hookTraceEnabled(env = process.env) {
|
|
43
|
+
const value = env[HOOK_TRACE_ENV]?.trim().toLowerCase();
|
|
44
|
+
return !value || !['off', '0', 'false', 'no', 'disabled'].includes(value);
|
|
45
|
+
}
|
|
46
|
+
export function hookTraceDirectory(stateDir = mnemonikStateDirectory()) {
|
|
47
|
+
return join(stateDir, 'hook-trace');
|
|
48
|
+
}
|
|
49
|
+
export function hookTraceFile(host, stateDir) {
|
|
50
|
+
return join(hookTraceDirectory(stateDir), `${host}.jsonl`);
|
|
51
|
+
}
|
|
52
|
+
const preparedDirectories = new Set();
|
|
53
|
+
function ensurePrivateDirectory(directory) {
|
|
54
|
+
if (preparedDirectories.has(directory))
|
|
55
|
+
return;
|
|
56
|
+
if (process.platform === 'win32')
|
|
57
|
+
ensureWindowsPrivateDirectorySync(directory);
|
|
58
|
+
else {
|
|
59
|
+
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
60
|
+
const stat = lstatSync(directory);
|
|
61
|
+
if (!stat.isDirectory() ||
|
|
62
|
+
stat.isSymbolicLink() ||
|
|
63
|
+
(process.getuid && stat.uid !== process.getuid()) ||
|
|
64
|
+
stat.mode & 0o077)
|
|
65
|
+
throw new Error('hook trace directory is not private');
|
|
66
|
+
}
|
|
67
|
+
preparedDirectories.add(directory);
|
|
68
|
+
}
|
|
69
|
+
function openTrace(file) {
|
|
70
|
+
return openSync(file, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | (constants.O_NOFOLLOW ?? 0), 0o600);
|
|
71
|
+
}
|
|
72
|
+
/** Whether `file` still names the file `fd` has open: no other writer rotated it away. */
|
|
73
|
+
function sameFile(file, fd) {
|
|
74
|
+
try {
|
|
75
|
+
const opened = fstatSync(fd, { bigint: true });
|
|
76
|
+
const named = statSync(file, { bigint: true });
|
|
77
|
+
return opened.ino === named.ino && opened.dev === named.dev;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** A rotation lock older than this was left by a killed writer. */
|
|
84
|
+
const STALE_LOCK_MS = 10_000;
|
|
85
|
+
function takeLock(lock) {
|
|
86
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
87
|
+
try {
|
|
88
|
+
closeSync(openSync(lock, 'wx', 0o600));
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
try {
|
|
93
|
+
if (attempt > 0 || Date.now() - lstatSync(lock).mtimeMs < STALE_LOCK_MS)
|
|
94
|
+
return false;
|
|
95
|
+
unlinkSync(lock);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
/* Gone already: try once more. */
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Rotate the full file `fd` has open to `.1`. Hooks run concurrently, so
|
|
106
|
+
* rotation is serialised by an exclusive lock file and, while holding it,
|
|
107
|
+
* happens only when the path still names the file `fd` has open: a writer
|
|
108
|
+
* that finds another already rotated (or rotating) appends to the fresh file
|
|
109
|
+
* instead of rotating again and replacing the full file in `.1`.
|
|
110
|
+
*/
|
|
111
|
+
function rotate(file, fd) {
|
|
112
|
+
const lock = `${file}.lock`;
|
|
113
|
+
if (!takeLock(lock))
|
|
114
|
+
return;
|
|
115
|
+
try {
|
|
116
|
+
if (sameFile(file, fd))
|
|
117
|
+
renameSync(file, `${file}.1`);
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
try {
|
|
121
|
+
unlinkSync(lock);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
/* Already removed as stale: nothing to release. */
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/** Append one line, rotating first when the file is full. Throws; callers swallow. */
|
|
129
|
+
export function appendHookTraceLine(file, record) {
|
|
130
|
+
ensurePrivateDirectory(dirname(file));
|
|
131
|
+
const line = `${JSON.stringify(record)}\n`;
|
|
132
|
+
let fd = openTrace(file);
|
|
133
|
+
try {
|
|
134
|
+
const stat = fstatSync(fd);
|
|
135
|
+
if (!stat.isFile() || (process.getuid && stat.uid !== process.getuid()))
|
|
136
|
+
throw new Error('hook trace file is not ours');
|
|
137
|
+
if (stat.size > 0 && stat.size + Buffer.byteLength(line) > HOOK_TRACE_MAX_BYTES) {
|
|
138
|
+
try {
|
|
139
|
+
rotate(file, fd);
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
closeSync(fd);
|
|
143
|
+
fd = -1;
|
|
144
|
+
}
|
|
145
|
+
fd = openTrace(file);
|
|
146
|
+
}
|
|
147
|
+
writeSync(fd, line);
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
if (fd >= 0)
|
|
151
|
+
closeSync(fd);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function byteSize(value) {
|
|
155
|
+
if (typeof value === 'string')
|
|
156
|
+
return Buffer.byteLength(value);
|
|
157
|
+
try {
|
|
158
|
+
return Buffer.byteLength(JSON.stringify(value) ?? '');
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function safe(value, pattern) {
|
|
165
|
+
return typeof value === 'string' && pattern.test(value) ? value : undefined;
|
|
166
|
+
}
|
|
167
|
+
function sizesOf(object, prefix = '') {
|
|
168
|
+
const sizes = {};
|
|
169
|
+
for (const key of Object.keys(object).slice(0, MAX_FIELDS))
|
|
170
|
+
if (SAFE_NAME.test(key))
|
|
171
|
+
sizes[prefix + key] = byteSize(object[key]);
|
|
172
|
+
return sizes;
|
|
173
|
+
}
|
|
174
|
+
const isObject = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
175
|
+
/** Field names and sizes, the decision fields' short enum values, never text. */
|
|
176
|
+
export function summarizeHookOutput(text) {
|
|
177
|
+
const output = { bytes: Buffer.byteLength(text), sizes: {} };
|
|
178
|
+
let value;
|
|
179
|
+
try {
|
|
180
|
+
value = JSON.parse(text);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return output;
|
|
184
|
+
}
|
|
185
|
+
if (!isObject(value))
|
|
186
|
+
return output;
|
|
187
|
+
const nested = isObject(value.hookSpecificOutput) ? value.hookSpecificOutput : undefined;
|
|
188
|
+
const { hookSpecificOutput: _nested, ...top } = value;
|
|
189
|
+
output.sizes = { ...sizesOf(top), ...(nested ? sizesOf(nested, 'hookSpecificOutput.') : {}) };
|
|
190
|
+
const permission = safe(value.permission ?? nested?.permissionDecision, SAFE_ENUM);
|
|
191
|
+
const decision = safe(value.decision, SAFE_ENUM);
|
|
192
|
+
if (permission)
|
|
193
|
+
output.permission = permission;
|
|
194
|
+
if (decision)
|
|
195
|
+
output.decision = decision;
|
|
196
|
+
if (typeof value.continue === 'boolean')
|
|
197
|
+
output.continue = value.continue;
|
|
198
|
+
return output;
|
|
199
|
+
}
|
|
200
|
+
function routeOf(input) {
|
|
201
|
+
try {
|
|
202
|
+
const href = typeof input === 'string'
|
|
203
|
+
? input
|
|
204
|
+
: input instanceof URL
|
|
205
|
+
? input.href
|
|
206
|
+
: input.url;
|
|
207
|
+
return new URL(String(href)).pathname
|
|
208
|
+
.split('/')
|
|
209
|
+
.map((segment) => (segment.length >= 16 && /\d/.test(segment)) || /[%@]/.test(segment) ? ':id' : segment)
|
|
210
|
+
.join('/')
|
|
211
|
+
.slice(0, 200);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return 'unknown';
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
export function errorKind(error) {
|
|
218
|
+
const failure = error;
|
|
219
|
+
if (failure?.name === 'TimeoutError')
|
|
220
|
+
return 'timeout';
|
|
221
|
+
if (failure?.name === 'AbortError')
|
|
222
|
+
return 'aborted';
|
|
223
|
+
const code = failure?.cause?.code ?? failure?.code;
|
|
224
|
+
if (typeof code === 'string' && /^[A-Z0-9_]{2,40}$/.test(code))
|
|
225
|
+
return code;
|
|
226
|
+
return safe(failure?.name, /^\w{1,40}$/) ?? 'error';
|
|
227
|
+
}
|
|
228
|
+
/** The message, whitespace folded, secrets scrubbed, cut to 80 characters. */
|
|
229
|
+
export function scrubHookTraceMessage(error) {
|
|
230
|
+
const text = error instanceof Error ? error.message : String(error);
|
|
231
|
+
return scrubSecrets(text.replace(/\s+/g, ' ').trim()).slice(0, MAX_ERROR_CHARS);
|
|
232
|
+
}
|
|
233
|
+
export class HookTrace {
|
|
234
|
+
host;
|
|
235
|
+
file;
|
|
236
|
+
hookVersion;
|
|
237
|
+
id = randomBytes(8).toString('hex');
|
|
238
|
+
startedAt = performance.now();
|
|
239
|
+
opened = false;
|
|
240
|
+
started = false;
|
|
241
|
+
ended = false;
|
|
242
|
+
event = null;
|
|
243
|
+
outputSummary = null;
|
|
244
|
+
error;
|
|
245
|
+
errorKind;
|
|
246
|
+
projectId;
|
|
247
|
+
calls = [];
|
|
248
|
+
inFlight = new Set();
|
|
249
|
+
constructor(host, file, hookVersion) {
|
|
250
|
+
this.host = host;
|
|
251
|
+
this.file = file;
|
|
252
|
+
this.hookVersion = hookVersion;
|
|
253
|
+
}
|
|
254
|
+
get enabled() {
|
|
255
|
+
return this.file !== undefined;
|
|
256
|
+
}
|
|
257
|
+
write(record) {
|
|
258
|
+
if (!this.file)
|
|
259
|
+
return;
|
|
260
|
+
try {
|
|
261
|
+
appendHookTraceLine(this.file, record);
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
/* A diagnostic record never costs the hook anything. */
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Write the `start` line: pid, run id and time since process start, nothing
|
|
269
|
+
* from the editor. Runs before stdin is read, so a run killed while the
|
|
270
|
+
* editor is still sending its event leaves this line.
|
|
271
|
+
*/
|
|
272
|
+
open() {
|
|
273
|
+
if (!this.file || this.opened)
|
|
274
|
+
return;
|
|
275
|
+
this.opened = true;
|
|
276
|
+
this.write({
|
|
277
|
+
v: 1,
|
|
278
|
+
phase: 'start',
|
|
279
|
+
ts: new Date().toISOString(),
|
|
280
|
+
host: this.host,
|
|
281
|
+
...(this.hookVersion ? { hookVersion: this.hookVersion } : {}),
|
|
282
|
+
pid: process.pid,
|
|
283
|
+
id: this.id,
|
|
284
|
+
processMs: Math.round(process.uptime() * 1000),
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/** Write the `input` line. `input` is the parsed payload, or null when none parsed. */
|
|
288
|
+
begin(input, event) {
|
|
289
|
+
if (!this.file || this.started)
|
|
290
|
+
return;
|
|
291
|
+
this.open();
|
|
292
|
+
this.started = true;
|
|
293
|
+
try {
|
|
294
|
+
const payload = isObject(input) ? input : {};
|
|
295
|
+
this.event =
|
|
296
|
+
safe(event, SAFE_NAME) ??
|
|
297
|
+
safe(payload.hook_event_name, SAFE_NAME) ??
|
|
298
|
+
safe(payload.hookEventName, SAFE_NAME) ??
|
|
299
|
+
null;
|
|
300
|
+
const roots = Array.isArray(payload.workspace_roots) ? payload.workspace_roots : [];
|
|
301
|
+
const cwd = typeof payload.cwd === 'string' && payload.cwd
|
|
302
|
+
? payload.cwd
|
|
303
|
+
: typeof roots[0] === 'string'
|
|
304
|
+
? roots[0]
|
|
305
|
+
: process.cwd();
|
|
306
|
+
const record = {
|
|
307
|
+
v: 1,
|
|
308
|
+
phase: 'input',
|
|
309
|
+
ts: new Date().toISOString(),
|
|
310
|
+
host: this.host,
|
|
311
|
+
pid: process.pid,
|
|
312
|
+
id: this.id,
|
|
313
|
+
event: this.event,
|
|
314
|
+
inputBytes: isObject(input) ? byteSize(input) : 0,
|
|
315
|
+
fields: sizesOf(payload),
|
|
316
|
+
readMs: Math.round(performance.now() - this.startedAt),
|
|
317
|
+
};
|
|
318
|
+
const hostVersion = safe(payload.cursor_version ?? payload.version, /^[\w.+-]{1,40}$/);
|
|
319
|
+
if (hostVersion)
|
|
320
|
+
record.hostVersion = hostVersion;
|
|
321
|
+
const ids = [
|
|
322
|
+
['sessionId', 'session_id'],
|
|
323
|
+
['conversationId', 'conversation_id'],
|
|
324
|
+
['generationId', 'generation_id'],
|
|
325
|
+
['agentId', 'agent_id'],
|
|
326
|
+
['agentId', 'subagent_id'],
|
|
327
|
+
['turnId', 'turn_id'],
|
|
328
|
+
];
|
|
329
|
+
for (const [name, key] of ids) {
|
|
330
|
+
const id = safe(payload[key], SAFE_ID);
|
|
331
|
+
if (id && record[name] === undefined)
|
|
332
|
+
record[name] = id;
|
|
333
|
+
}
|
|
334
|
+
const tool = safe(payload.tool_name, SAFE_NAME);
|
|
335
|
+
if (tool)
|
|
336
|
+
record.tool = tool;
|
|
337
|
+
if (cwd.length <= 1024)
|
|
338
|
+
record.cwd = cwd;
|
|
339
|
+
this.write(record);
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
/* Never into the hook. */
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/** The exact text the hook wrote to stdout (or nothing). */
|
|
346
|
+
output(text) {
|
|
347
|
+
if (!this.file || text === null || text === undefined)
|
|
348
|
+
return;
|
|
349
|
+
try {
|
|
350
|
+
this.outputSummary = summarizeHookOutput(text);
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
/* Never into the hook. */
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/** The error the hook failed open on. */
|
|
357
|
+
fail(error) {
|
|
358
|
+
if (!this.file)
|
|
359
|
+
return;
|
|
360
|
+
try {
|
|
361
|
+
this.errorKind = errorKind(error);
|
|
362
|
+
this.error = scrubHookTraceMessage(error);
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
this.errorKind = 'error';
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
project(projectId) {
|
|
369
|
+
if (projectId && !this.projectId && SAFE_ID.test(projectId))
|
|
370
|
+
this.projectId = projectId;
|
|
371
|
+
}
|
|
372
|
+
/** A call has gone out; {@link settle} records it, {@link finish} records it as pending. */
|
|
373
|
+
callStarted(input) {
|
|
374
|
+
const token = { input, startedAt: performance.now() };
|
|
375
|
+
if (this.file)
|
|
376
|
+
this.inFlight.add(token);
|
|
377
|
+
return token;
|
|
378
|
+
}
|
|
379
|
+
settle(token, status, error) {
|
|
380
|
+
this.inFlight.delete(token);
|
|
381
|
+
this.call(token.input, token.startedAt, status, error);
|
|
382
|
+
}
|
|
383
|
+
call(input, startedAt, status, error) {
|
|
384
|
+
if (!this.file || this.calls.length >= MAX_CALLS)
|
|
385
|
+
return;
|
|
386
|
+
try {
|
|
387
|
+
this.calls.push({
|
|
388
|
+
path: routeOf(input),
|
|
389
|
+
...(status !== undefined ? { status } : { error: errorKind(error) }),
|
|
390
|
+
ms: Math.round(performance.now() - startedAt),
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
catch {
|
|
394
|
+
/* Never into the hook. */
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
/** Write the `end` line once. Runs from the process `exit` event. */
|
|
398
|
+
finish(exitCode = 0) {
|
|
399
|
+
if (!this.file || this.ended)
|
|
400
|
+
return;
|
|
401
|
+
this.open();
|
|
402
|
+
this.ended = true;
|
|
403
|
+
for (const { input, startedAt } of this.inFlight) {
|
|
404
|
+
if (this.calls.length >= MAX_CALLS)
|
|
405
|
+
break;
|
|
406
|
+
try {
|
|
407
|
+
this.calls.push({
|
|
408
|
+
path: routeOf(input),
|
|
409
|
+
pending: true,
|
|
410
|
+
ms: Math.round(performance.now() - startedAt),
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
catch {
|
|
414
|
+
/* Never into the hook. */
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
this.inFlight.clear();
|
|
418
|
+
this.write({
|
|
419
|
+
v: 1,
|
|
420
|
+
phase: 'end',
|
|
421
|
+
ts: new Date().toISOString(),
|
|
422
|
+
host: this.host,
|
|
423
|
+
pid: process.pid,
|
|
424
|
+
id: this.id,
|
|
425
|
+
event: this.event,
|
|
426
|
+
...(this.projectId ? { projectId: this.projectId } : {}),
|
|
427
|
+
output: this.outputSummary,
|
|
428
|
+
calls: this.calls,
|
|
429
|
+
durationMs: Math.round(performance.now() - this.startedAt),
|
|
430
|
+
processMs: Math.round(process.uptime() * 1000),
|
|
431
|
+
exitCode,
|
|
432
|
+
...(this.errorKind ? { errorKind: this.errorKind } : {}),
|
|
433
|
+
...(this.error ? { error: this.error } : {}),
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
let active;
|
|
438
|
+
/** Resolved project ids reach the trace from the shared identity cache. */
|
|
439
|
+
export function noteHookTraceProject(projectId) {
|
|
440
|
+
active?.project(projectId);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Start this process's recorder: one per hook process. Writes the `start`
|
|
444
|
+
* line at once (so call it before reading stdin), times every `fetch` the
|
|
445
|
+
* process makes (path, status or error kind, duration; `pending` when still
|
|
446
|
+
* waiting at exit) and writes the `end` line from the process `exit` event,
|
|
447
|
+
* so every exit path is covered.
|
|
448
|
+
*/
|
|
449
|
+
export function startHookTrace(options) {
|
|
450
|
+
if (active)
|
|
451
|
+
return active;
|
|
452
|
+
let file;
|
|
453
|
+
try {
|
|
454
|
+
if (hookTraceEnabled(options.env))
|
|
455
|
+
file = hookTraceFile(options.host, options.stateDir ?? mnemonikStateDirectory(process.platform, options.env ?? process.env));
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
file = undefined;
|
|
459
|
+
}
|
|
460
|
+
const trace = new HookTrace(options.host, file, options.hookVersion);
|
|
461
|
+
active = trace;
|
|
462
|
+
if (!file)
|
|
463
|
+
return trace;
|
|
464
|
+
const original = globalThis.fetch;
|
|
465
|
+
if (typeof original === 'function') {
|
|
466
|
+
globalThis.fetch = async (input, init) => {
|
|
467
|
+
const token = trace.callStarted(input);
|
|
468
|
+
try {
|
|
469
|
+
const response = await original.call(globalThis, input, init);
|
|
470
|
+
trace.settle(token, response.status);
|
|
471
|
+
return response;
|
|
472
|
+
}
|
|
473
|
+
catch (error) {
|
|
474
|
+
trace.settle(token, undefined, error);
|
|
475
|
+
throw error;
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
process.once('exit', (code) => trace.finish(typeof code === 'number' ? code : 0));
|
|
480
|
+
trace.open();
|
|
481
|
+
return trace;
|
|
482
|
+
}
|
|
483
|
+
//# sourceMappingURL=hookTrace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hookTrace.js","sourceRoot":"","sources":["../src/hookTrace.ts"],"names":[],"mappings":"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"}
|