@claude-flow/cli 3.57.2 → 3.58.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.claude/helpers/helpers.manifest.json +2 -2
  2. package/README.md +1 -0
  3. package/catalog-manifest.json +2 -2
  4. package/dist/src/commands/agent.js +4 -1
  5. package/dist/src/commands/mcp.js +66 -6
  6. package/dist/src/commands/memory.js +53 -2
  7. package/dist/src/mcp-server.d.ts +5 -0
  8. package/dist/src/mcp-server.js +39 -0
  9. package/dist/src/mcp-tools/agent-tools.js +28 -0
  10. package/dist/src/mcp-tools/claims-tools.js +25 -15
  11. package/dist/src/mcp-tools/hooks-tools.js +13 -3
  12. package/dist/src/memory/memory-initializer.js +43 -4
  13. package/dist/src/memory/memory-peek.d.ts +28 -0
  14. package/dist/src/memory/memory-peek.js +222 -0
  15. package/dist/src/memory/model-cache-dir.d.ts +11 -0
  16. package/dist/src/memory/model-cache-dir.js +17 -0
  17. package/dist/src/parser.js +3 -2
  18. package/dist/src/ruvector/task-embedder.js +38 -4
  19. package/node_modules/@claude-flow/codex/README.md +78 -0
  20. package/node_modules/@claude-flow/codex/dist/activity/cli.d.ts +3 -0
  21. package/node_modules/@claude-flow/codex/dist/activity/cli.d.ts.map +1 -0
  22. package/node_modules/@claude-flow/codex/dist/activity/cli.js +115 -0
  23. package/node_modules/@claude-flow/codex/dist/activity/cli.js.map +1 -0
  24. package/node_modules/@claude-flow/codex/dist/activity/files.d.ts +14 -0
  25. package/node_modules/@claude-flow/codex/dist/activity/files.d.ts.map +1 -0
  26. package/node_modules/@claude-flow/codex/dist/activity/files.js +142 -0
  27. package/node_modules/@claude-flow/codex/dist/activity/files.js.map +1 -0
  28. package/node_modules/@claude-flow/codex/dist/activity/parser.d.ts +21 -0
  29. package/node_modules/@claude-flow/codex/dist/activity/parser.d.ts.map +1 -0
  30. package/node_modules/@claude-flow/codex/dist/activity/parser.js +179 -0
  31. package/node_modules/@claude-flow/codex/dist/activity/parser.js.map +1 -0
  32. package/node_modules/@claude-flow/codex/dist/activity/reader.d.ts +20 -0
  33. package/node_modules/@claude-flow/codex/dist/activity/reader.d.ts.map +1 -0
  34. package/node_modules/@claude-flow/codex/dist/activity/reader.js +106 -0
  35. package/node_modules/@claude-flow/codex/dist/activity/reader.js.map +1 -0
  36. package/node_modules/@claude-flow/codex/dist/activity/sanitize.d.ts +4 -0
  37. package/node_modules/@claude-flow/codex/dist/activity/sanitize.d.ts.map +1 -0
  38. package/node_modules/@claude-flow/codex/dist/activity/sanitize.js +27 -0
  39. package/node_modules/@claude-flow/codex/dist/activity/sanitize.js.map +1 -0
  40. package/node_modules/@claude-flow/codex/dist/activity/types.d.ts +31 -0
  41. package/node_modules/@claude-flow/codex/dist/activity/types.d.ts.map +1 -0
  42. package/node_modules/@claude-flow/codex/dist/activity/types.js +5 -0
  43. package/node_modules/@claude-flow/codex/dist/activity/types.js.map +1 -0
  44. package/node_modules/@claude-flow/codex/dist/activity/viewer.d.ts +21 -0
  45. package/node_modules/@claude-flow/codex/dist/activity/viewer.d.ts.map +1 -0
  46. package/node_modules/@claude-flow/codex/dist/activity/viewer.js +168 -0
  47. package/node_modules/@claude-flow/codex/dist/activity/viewer.js.map +1 -0
  48. package/node_modules/@claude-flow/codex/dist/cli.js +3 -0
  49. package/node_modules/@claude-flow/codex/dist/cli.js.map +1 -1
  50. package/node_modules/@claude-flow/mcp/dist/server.d.ts.map +1 -1
  51. package/node_modules/@claude-flow/mcp/dist/server.js +5 -3
  52. package/node_modules/@claude-flow/mcp/dist/server.js.map +1 -1
  53. package/node_modules/@claude-flow/mcp/dist/types.d.ts +11 -0
  54. package/node_modules/@claude-flow/mcp/dist/types.d.ts.map +1 -1
  55. package/node_modules/@claude-flow/mcp/dist/types.js.map +1 -1
  56. package/package.json +1 -1
  57. package/plugins/ruflo-console/dist/tui.mjs +124 -124
@@ -0,0 +1,115 @@
1
+ import { Command, InvalidArgumentError } from 'commander';
2
+ import { realpath } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { emitKeypressEvents } from 'node:readline';
5
+ import { ActivityViewer } from './viewer.js';
6
+ import { sanitize } from './sanitize.js';
7
+ export function createActivityCommand() {
8
+ return new Command('activity')
9
+ .description('Inspect helpers from an existing Codex session (read-only)')
10
+ .requiredOption('--session-file <file>', 'Parent CLI rollout JSONL file')
11
+ .requiredOption('--sessions-dir <directory>', 'Directory containing parent and helper rollouts')
12
+ .option('--agent <id>', 'Open a particular helper thread ID')
13
+ .option('--once', 'Print one bounded snapshot and exit (no interactive terminal needed)')
14
+ .option('--interval <seconds>', 'Refresh interval, 0.2 to 60 seconds', interval, 2)
15
+ .action(async (options) => {
16
+ try {
17
+ const root = await realpath(path.resolve(options.sessionsDir));
18
+ // Canonicalize the directory only. A selected file through a symlink is rejected.
19
+ const file = path.resolve(root, path.relative(path.resolve(options.sessionsDir), path.resolve(options.sessionFile)));
20
+ const viewer = new ActivityViewer(root, file);
21
+ await viewer.refresh();
22
+ if (viewer.list.error)
23
+ throw new Error(viewer.list.error);
24
+ if (options.agent) {
25
+ if (!viewer.list.helpers.some(item => item.id === options.agent))
26
+ throw new Error('Agent is not an attributable helper of this session.');
27
+ viewer.selected = options.agent;
28
+ viewer.detail = true;
29
+ await viewer.refresh();
30
+ }
31
+ if (options.once)
32
+ console.log(viewer.render(100, 200));
33
+ else
34
+ await runTerminal(viewer, options.interval * 1000);
35
+ }
36
+ catch (error) {
37
+ console.error(`Activity viewer: ${sanitize(error instanceof Error ? error.message : 'Unable to read session.', 300)}`);
38
+ process.exitCode = 1;
39
+ }
40
+ });
41
+ }
42
+ function interval(value) {
43
+ const parsed = Number(value);
44
+ if (!Number.isFinite(parsed) || parsed < 0.2 || parsed > 60)
45
+ throw new InvalidArgumentError('Choose 0.2 to 60 seconds.');
46
+ return parsed;
47
+ }
48
+ async function runTerminal(viewer, intervalMs) {
49
+ const input = process.stdin;
50
+ const output = process.stdout;
51
+ if (!input.isTTY || !output.isTTY)
52
+ throw new Error('Use --once when input or output is not a terminal.');
53
+ const wasRaw = input.isRaw;
54
+ let stopped = false;
55
+ let busy = false;
56
+ let finish = () => { };
57
+ const done = new Promise(resolve => { finish = resolve; });
58
+ const draw = () => {
59
+ if (!stopped)
60
+ output.write(`\x1b[H\x1b[2J${viewer.render(output.columns || 80, output.rows || 24)}`);
61
+ };
62
+ const close = () => { stopped = true; finish(); };
63
+ const update = async () => {
64
+ if (busy || stopped)
65
+ return;
66
+ busy = true;
67
+ try {
68
+ await viewer.refresh();
69
+ draw();
70
+ }
71
+ catch {
72
+ close();
73
+ process.exitCode = 1;
74
+ }
75
+ finally {
76
+ busy = false;
77
+ }
78
+ };
79
+ const keypress = (text, key) => {
80
+ if (key?.name === 'q' || key?.ctrl && key.name === 'c') {
81
+ close();
82
+ return;
83
+ }
84
+ viewer.key(text === 'G' ? 'G' : key?.name ?? text);
85
+ draw();
86
+ if (key?.name === 'return')
87
+ void update();
88
+ };
89
+ emitKeypressEvents(input);
90
+ const timer = setInterval(() => { void update(); }, intervalMs);
91
+ try {
92
+ input.setRawMode(true);
93
+ input.resume();
94
+ input.on('keypress', keypress);
95
+ output.on('resize', draw);
96
+ process.on('SIGINT', close);
97
+ process.on('SIGTERM', close);
98
+ output.write('\x1b[?1049h\x1b[?25l');
99
+ draw();
100
+ await done;
101
+ }
102
+ finally {
103
+ stopped = true;
104
+ clearInterval(timer);
105
+ input.off('keypress', keypress);
106
+ output.off('resize', draw);
107
+ process.off('SIGINT', close);
108
+ process.off('SIGTERM', close);
109
+ input.setRawMode(wasRaw);
110
+ // This command owns stdin. A resumed stream would keep Node alive after q.
111
+ input.pause();
112
+ output.write('\x1b[?25h\x1b[?1049l');
113
+ }
114
+ }
115
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/activity/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { FileHandle } from 'node:fs/promises';
2
+ import { type SessionIdentity } from './types.js';
3
+ export declare const MAX_LINE: number;
4
+ /** Only regular files whose resolved path stays inside the selected directory. */
5
+ export declare function openSession(root: string, file: string): Promise<FileHandle>;
6
+ export declare function readIdentity(root: string, file: string): Promise<SessionIdentity | null>;
7
+ export interface SessionList {
8
+ root: SessionIdentity | null;
9
+ helpers: SessionIdentity[];
10
+ partial: boolean;
11
+ error: string;
12
+ }
13
+ export declare function listSessions(root: string, rootFile: string, expectedId?: string): Promise<SessionList>;
14
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/activity/files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAU,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAG1D,eAAO,MAAM,QAAQ,QAAY,CAAC;AAGlC,kFAAkF;AAClF,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBjF;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAyB9F;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;IAC7B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAsD5G"}
@@ -0,0 +1,142 @@
1
+ import { constants } from 'node:fs';
2
+ import { lstat, open, opendir, realpath } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { object } from './types.js';
5
+ import { sanitize } from './sanitize.js';
6
+ export const MAX_LINE = 64 * 1024;
7
+ const MAX_ENTRIES = 4000;
8
+ /** Only regular files whose resolved path stays inside the selected directory. */
9
+ export async function openSession(root, file) {
10
+ const absolute = path.resolve(file);
11
+ const relative = path.relative(root, absolute);
12
+ if (!relative || relative === '..' || relative.startsWith(`..${path.sep}`)
13
+ || path.isAbsolute(relative) || await realpath(absolute) !== absolute) {
14
+ throw new Error('Session file is outside the selected directory or uses a symlink.');
15
+ }
16
+ const before = await lstat(absolute);
17
+ if (!before.isFile())
18
+ throw new Error('Session is not a regular file.');
19
+ const handle = await open(absolute, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
20
+ try {
21
+ const after = await handle.stat();
22
+ if (!after.isFile() || after.ino !== before.ino || after.dev !== before.dev
23
+ || await realpath(absolute) !== absolute)
24
+ throw new Error('Session changed while opening.');
25
+ return handle;
26
+ }
27
+ catch (error) {
28
+ await handle.close();
29
+ throw error;
30
+ }
31
+ }
32
+ export async function readIdentity(root, file) {
33
+ const handle = await openSession(root, file);
34
+ try {
35
+ const buffer = Buffer.alloc(MAX_LINE);
36
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
37
+ const newline = buffer.subarray(0, bytesRead).indexOf(10);
38
+ // A valid JSON prefix is not enough: require the complete metadata line.
39
+ if (newline < 0)
40
+ return null;
41
+ const record = object(JSON.parse(buffer.subarray(0, newline).toString('utf8')));
42
+ const meta = object(record.payload);
43
+ if (record.type !== 'session_meta' || typeof meta.id !== 'string' || !meta.id
44
+ || meta.id.length > 300)
45
+ return null;
46
+ const spawn = object(object(object(meta.source).subagent).thread_spawn);
47
+ const parent = typeof spawn.parent_thread_id === 'string' ? spawn.parent_thread_id : null;
48
+ const rootSession = meta.source === 'cli' && !meta.forked_from_id
49
+ && !meta.parent_thread_id && (!meta.thread_source || meta.thread_source === 'user');
50
+ if (!parent && !rootSession)
51
+ return null; // Excludes guardians and unknown sources.
52
+ return {
53
+ id: meta.id, parent, file,
54
+ name: sanitize(meta.agent_nickname ?? spawn.agent_nickname ?? '', 120),
55
+ path: sanitize(meta.agent_path ?? spawn.agent_path ?? meta.id, 200),
56
+ };
57
+ }
58
+ finally {
59
+ await handle.close();
60
+ }
61
+ }
62
+ export async function listSessions(root, rootFile, expectedId) {
63
+ const empty = { root: null, helpers: [], partial: false, error: '' };
64
+ let selected;
65
+ try {
66
+ selected = await readIdentity(root, rootFile);
67
+ }
68
+ catch {
69
+ return { ...empty, error: 'The selected session file is unavailable.' };
70
+ }
71
+ if (!selected || selected.parent || (expectedId && selected.id !== expectedId)) {
72
+ return { ...empty, error: 'Select a root CLI session with an unchanged identity.' };
73
+ }
74
+ const sessions = new Map([[selected.id, selected]]);
75
+ const duplicates = new Set();
76
+ const queue = [{ directory: root, depth: 0 }];
77
+ let entries = 0;
78
+ let partial = false;
79
+ while (queue.length && entries < MAX_ENTRIES) {
80
+ const current = queue.shift();
81
+ try {
82
+ // Revalidate directories too; never recurse through a symlink.
83
+ if (await realpath(current.directory) !== current.directory) {
84
+ partial = true;
85
+ continue;
86
+ }
87
+ const directory = await opendir(current.directory);
88
+ for await (const entry of directory) {
89
+ if (++entries > MAX_ENTRIES) {
90
+ partial = true;
91
+ break;
92
+ }
93
+ const file = path.join(current.directory, entry.name);
94
+ if (entry.isDirectory()) {
95
+ if (current.depth < 8)
96
+ queue.push({ directory: file, depth: current.depth + 1 });
97
+ else
98
+ partial = true;
99
+ }
100
+ else if (entry.isFile() && entry.name.endsWith('.jsonl') && file !== rootFile) {
101
+ try {
102
+ const identity = await readIdentity(root, file);
103
+ if (!identity)
104
+ continue;
105
+ if (sessions.has(identity.id))
106
+ duplicates.add(identity.id);
107
+ else
108
+ sessions.set(identity.id, identity);
109
+ }
110
+ catch {
111
+ partial = true;
112
+ }
113
+ }
114
+ }
115
+ }
116
+ catch {
117
+ partial = true;
118
+ }
119
+ }
120
+ partial ||= queue.length > 0;
121
+ if (duplicates.has(selected.id))
122
+ return { ...empty, partial: true, error: 'Root session identity is ambiguous.' };
123
+ const belongs = (identity) => {
124
+ const seen = new Set();
125
+ let node = identity;
126
+ while (node?.parent && seen.size < 64) {
127
+ if (seen.has(node.id) || duplicates.has(node.id))
128
+ return false;
129
+ seen.add(node.id);
130
+ if (node.parent === selected.id)
131
+ return true;
132
+ node = sessions.get(node.parent);
133
+ }
134
+ return false;
135
+ };
136
+ return {
137
+ root: selected,
138
+ helpers: [...sessions.values()].filter(belongs).sort((a, b) => a.path.localeCompare(b.path)),
139
+ partial: partial || duplicates.size > 0, error: '',
140
+ };
141
+ }
142
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/activity/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAwB,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC;AAClC,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,IAAY;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;WACrE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,MAAM,QAAQ,CAAC,QAAQ,CAAC,KAAK,QAAQ,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,QAAQ,GAAG,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC;IACtF,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG;eACtE,MAAM,QAAQ,CAAC,QAAQ,CAAC,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAC9F,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,IAAY;IAC3D,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACrE,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1D,yEAAyE;QACzE,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAChF,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,EAAE;eACxE,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,GAAG;YAAE,OAAO,IAAI,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC;QACxE,MAAM,MAAM,GAAG,OAAO,KAAK,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1F,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,cAAc;eAC5D,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,KAAK,MAAM,CAAC,CAAC;QACtF,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC,CAAC,0CAA0C;QACpF,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI;YACzB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC,cAAc,IAAI,EAAE,EAAE,GAAG,CAAC;YACtE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,IAAI,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC;SACpE,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,QAAgB,EAAE,UAAmB;IACpF,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAClF,IAAI,QAAgC,CAAC;IACrC,IAAI,CAAC;QAAC,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAAC,CAAC;IACtD,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,2CAA2C,EAAE,CAAC;IAAC,CAAC;IAClF,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,UAAU,IAAI,QAAQ,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC;QAC/E,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,uDAAuD,EAAE,CAAC;IACtF,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAA0B,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC7E,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,MAAM,KAAK,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,OAAO,KAAK,CAAC,MAAM,IAAI,OAAO,GAAG,WAAW,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;QAC/B,IAAI,CAAC;YACH,+DAA+D;YAC/D,IAAI,MAAM,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;gBAAC,OAAO,GAAG,IAAI,CAAC;gBAAC,SAAS;YAAC,CAAC;YAC1F,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACnD,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;gBACpC,IAAI,EAAE,OAAO,GAAG,WAAW,EAAE,CAAC;oBAAC,OAAO,GAAG,IAAI,CAAC;oBAAC,MAAM;gBAAC,CAAC;gBACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACtD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACxB,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC;wBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;;wBAC5E,OAAO,GAAG,IAAI,CAAC;gBACtB,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAChF,IAAI,CAAC;wBACH,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;wBAChD,IAAI,CAAC,QAAQ;4BAAE,SAAS;wBACxB,IAAI,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;4BAAE,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;;4BACtD,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;oBAC3C,CAAC;oBAAC,MAAM,CAAC;wBAAC,OAAO,GAAG,IAAI,CAAC;oBAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,GAAG,IAAI,CAAC;QAAC,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7B,IAAI,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,qCAAqC,EAAE,CAAC;IAClH,MAAM,OAAO,GAAG,CAAC,QAAyB,EAAW,EAAE;QACrD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,IAAI,IAAI,GAAgC,QAAQ,CAAC;QACjD,OAAO,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC/D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAClB,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YAC7C,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5F,OAAO,EAAE,OAAO,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE;KACnD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type ActivitySnapshot } from './types.js';
2
+ /** An allowlist parser. Helper logs may begin with a complete copy of parent history. */
3
+ export declare class ActivityParser {
4
+ private readonly identity;
5
+ private readonly agentPath;
6
+ readonly snapshot: ActivitySnapshot;
7
+ private first;
8
+ private verified;
9
+ private own;
10
+ private calls;
11
+ constructor(identity: string, agentPath: string);
12
+ invalidate(): void;
13
+ consume(value: unknown): void;
14
+ private append;
15
+ private message;
16
+ private tool;
17
+ private result;
18
+ private event;
19
+ private response;
20
+ }
21
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/activity/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,gBAAgB,EAAqB,MAAM,YAAY,CAAC;AAMlG,yFAAyF;AACzF,qBAAa,cAAc;IAUb,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAAU,OAAO,CAAC,QAAQ,CAAC,SAAS;IATzE,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAGjC;IACF,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAoC;gBAEpB,QAAQ,EAAE,MAAM,EAAmB,SAAS,EAAE,MAAM;IAEjF,UAAU,IAAI,IAAI;IAOlB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IA2B7B,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,KAAK;IA0Bb,OAAO,CAAC,QAAQ;CAiBjB"}
@@ -0,0 +1,179 @@
1
+ import { object } from './types.js';
2
+ import { publicText, sanitize } from './sanitize.js';
3
+ const MAX_EVENTS = 80;
4
+ const CALL_ID = /^[\w.:/-]{1,300}$/;
5
+ /** An allowlist parser. Helper logs may begin with a complete copy of parent history. */
6
+ export class ActivityParser {
7
+ identity;
8
+ agentPath;
9
+ snapshot = {
10
+ available: false, status: 'unknown', assignment: '', events: [], updatedAt: '',
11
+ bytesRead: 0, fileSize: 0, partial: false, limited: false, attributed: false, error: '',
12
+ };
13
+ first = true;
14
+ verified = false;
15
+ own = false;
16
+ calls = new Map();
17
+ constructor(identity, agentPath) {
18
+ this.identity = identity;
19
+ this.agentPath = agentPath;
20
+ }
21
+ invalidate() {
22
+ this.own = false;
23
+ this.calls.clear();
24
+ this.snapshot.limited = true;
25
+ if (this.first) {
26
+ this.first = false;
27
+ this.snapshot.error = 'Invalid first session record.';
28
+ }
29
+ }
30
+ consume(value) {
31
+ const record = object(value);
32
+ if (!Object.keys(object(record.payload)).length) {
33
+ this.invalidate();
34
+ return;
35
+ }
36
+ const payload = object(record.payload);
37
+ if (this.first) {
38
+ this.first = false;
39
+ if (record.type !== 'session_meta' || payload.id !== this.identity) {
40
+ this.snapshot.error = 'Session identity does not match the selected agent.';
41
+ return;
42
+ }
43
+ this.verified = true;
44
+ this.snapshot.available = true;
45
+ return; // A helper's first header never opens the attribution boundary.
46
+ }
47
+ if (!this.verified)
48
+ return;
49
+ if (record.type === 'session_meta') {
50
+ this.own = false;
51
+ this.calls.clear();
52
+ return;
53
+ }
54
+ if (payload.thread_id !== undefined) {
55
+ this.own = payload.thread_id === this.identity;
56
+ if (!this.own)
57
+ this.calls.clear();
58
+ }
59
+ if (!this.own)
60
+ return;
61
+ this.snapshot.attributed = true;
62
+ const time = sanitize(record.timestamp ?? '', 80);
63
+ if (record.type === 'event_msg')
64
+ this.event(payload, time);
65
+ if (record.type === 'response_item')
66
+ this.response(payload, time);
67
+ }
68
+ append(event) {
69
+ this.snapshot.events.push(event);
70
+ if (this.snapshot.events.length > MAX_EVENTS) {
71
+ const removed = this.snapshot.events.shift();
72
+ for (const [id, item] of this.calls)
73
+ if (item === removed)
74
+ this.calls.delete(id);
75
+ this.snapshot.limited = true;
76
+ }
77
+ this.snapshot.updatedAt = event.time;
78
+ }
79
+ message(text, label, time) {
80
+ if (!text)
81
+ return;
82
+ const preview = sanitize(text);
83
+ if (label === 'Assignment')
84
+ this.snapshot.assignment = preview;
85
+ if (this.snapshot.events.at(-1)?.text === preview)
86
+ return;
87
+ this.append({ kind: 'message', time, label, text: preview, output: '', status: '' });
88
+ }
89
+ tool(id, name, input, time) {
90
+ if (typeof id !== 'string' || !CALL_ID.test(id) || this.calls.has(id))
91
+ return;
92
+ const event = {
93
+ kind: 'tool', time, label: sanitize(name ?? 'tool', 200), text: sanitize(input), output: '', status: 'running',
94
+ };
95
+ this.append(event);
96
+ this.calls.set(id, event);
97
+ this.snapshot.status = 'running';
98
+ }
99
+ result(id, output, time, status) {
100
+ const call = typeof id === 'string' ? this.calls.get(id) : undefined;
101
+ if (!call)
102
+ return;
103
+ call.output = sanitize(output);
104
+ call.status = status ?? resultStatus(output);
105
+ this.snapshot.updatedAt = time;
106
+ }
107
+ event(payload, time) {
108
+ const states = {
109
+ task_started: 'running', task_complete: 'completed', task_failed: 'failed',
110
+ turn_failed: 'failed', turn_aborted: 'interrupted', task_aborted: 'interrupted',
111
+ };
112
+ const state = typeof payload.type === 'string' ? states[payload.type] : undefined;
113
+ if (state) {
114
+ this.snapshot.status = state;
115
+ this.snapshot.updatedAt = time;
116
+ }
117
+ if (payload.type === 'user_message')
118
+ this.message(publicText(payload.message), 'Assignment', time);
119
+ if (payload.type === 'agent_message')
120
+ this.message(publicText(payload.message), 'Assistant', time);
121
+ if (payload.type !== 'item_started' && payload.type !== 'item_completed')
122
+ return;
123
+ const item = object(payload.item);
124
+ if (item.type === 'AgentMessage' && ['commentary', 'final', 'final_answer'].includes(String(item.phase))) {
125
+ this.message(publicText(item.content), 'Assistant', time);
126
+ this.snapshot.status = item.phase === 'commentary' ? 'running' : 'completed';
127
+ return;
128
+ }
129
+ if (item.type !== 'CommandExecution' && item.type !== 'McpToolCall')
130
+ return;
131
+ this.tool(item.id, item.type === 'CommandExecution' ? 'command' : `${String(item.server)}.${String(item.tool)}`, item.command ?? item.arguments ?? '', time);
132
+ if (payload.type === 'item_completed') {
133
+ const status = ['failed', 'error', 'declined'].includes(String(item.status))
134
+ || (item.exit_code !== undefined && item.exit_code !== null && item.exit_code !== 0) ? 'failed' : 'completed';
135
+ this.result(item.id, item.aggregated_output ?? item.result ?? '', time, status);
136
+ }
137
+ }
138
+ response(payload, time) {
139
+ if (payload.type === 'message') {
140
+ const phase = payload.channel ?? payload.phase;
141
+ if (payload.role === 'user')
142
+ this.message(publicText(payload.content), 'Assignment', time);
143
+ else if (payload.role === 'assistant' && ['commentary', 'final', 'final_answer'].includes(String(phase))) {
144
+ this.message(publicText(payload.content), 'Assistant', time);
145
+ this.snapshot.status = phase === 'commentary' ? 'running' : 'completed';
146
+ }
147
+ }
148
+ else if (payload.type === 'agent_message') {
149
+ const incoming = !payload.recipient || payload.recipient === this.agentPath || payload.recipient === this.identity;
150
+ this.message(publicText(payload.content), incoming ? 'Assignment' : 'Assistant', time);
151
+ }
152
+ else if (payload.type === 'function_call' || payload.type === 'custom_tool_call') {
153
+ this.tool(payload.call_id, payload.name, payload.arguments ?? payload.input ?? '', time);
154
+ }
155
+ else if (payload.type === 'function_call_output' || payload.type === 'custom_tool_call_output') {
156
+ this.result(payload.call_id, payload.output ?? '', time);
157
+ }
158
+ }
159
+ }
160
+ function resultStatus(output) {
161
+ if (typeof output === 'string') {
162
+ try {
163
+ return resultStatus(JSON.parse(output));
164
+ }
165
+ catch {
166
+ if (/(?:Script running with cell ID|Process running with session ID)/.test(output))
167
+ return 'running';
168
+ const code = /(?:Process exited with code|exit_code["']?\s*:)\s*(-?\d+)/.exec(output);
169
+ return code && Number(code[1]) !== 0 ? 'failed' : 'returned';
170
+ }
171
+ }
172
+ const value = object(output);
173
+ if (value.isError === true || (value.exit_code != null && value.exit_code !== 0))
174
+ return 'failed';
175
+ if (value.session_id != null && value.exit_code == null)
176
+ return 'running';
177
+ return value.exit_code === 0 ? 'completed' : 'returned';
178
+ }
179
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/activity/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ActivitySnapshot, SessionIdentity } from './types.js';
2
+ /** Incremental reads keep UI refreshes bounded even when a helper inherits a large log. */
3
+ export declare class ActivityReader {
4
+ private readonly root;
5
+ private readonly identity;
6
+ private readonly budget;
7
+ private parser;
8
+ private offset;
9
+ private signature;
10
+ private mtime;
11
+ private head;
12
+ private anchor;
13
+ private pending;
14
+ private skipping;
15
+ constructor(root: string, identity: SessionIdentity, budget?: number);
16
+ private reset;
17
+ read(): Promise<ActivitySnapshot>;
18
+ private feed;
19
+ }
20
+ //# sourceMappingURL=reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../src/activity/reader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIpE,2FAA2F;AAC3F,qBAAa,cAAc;IAUb,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAU,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAClE,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,QAAQ,CAAS;gBAEI,IAAI,EAAE,MAAM,EAAmB,QAAQ,EAAE,eAAe,EAClE,MAAM,SAAc;IAIvC,OAAO,CAAC,KAAK;IASP,IAAI,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAwCvC,OAAO,CAAC,IAAI;CAuBb"}
@@ -0,0 +1,106 @@
1
+ import { MAX_LINE, openSession } from './files.js';
2
+ import { ActivityParser } from './parser.js';
3
+ const READ_BUDGET = 1024 * 1024;
4
+ /** Incremental reads keep UI refreshes bounded even when a helper inherits a large log. */
5
+ export class ActivityReader {
6
+ root;
7
+ identity;
8
+ budget;
9
+ parser;
10
+ offset = 0;
11
+ signature = '';
12
+ mtime = 0;
13
+ head = Buffer.alloc(0);
14
+ anchor = Buffer.alloc(0);
15
+ pending = Buffer.alloc(0);
16
+ skipping = false;
17
+ constructor(root, identity, budget = READ_BUDGET) {
18
+ this.root = root;
19
+ this.identity = identity;
20
+ this.budget = budget;
21
+ this.parser = new ActivityParser(identity.id, identity.path);
22
+ }
23
+ reset() {
24
+ this.parser = new ActivityParser(this.identity.id, this.identity.path);
25
+ this.offset = 0;
26
+ this.pending = Buffer.alloc(0);
27
+ this.skipping = false;
28
+ this.head = Buffer.alloc(0);
29
+ this.anchor = Buffer.alloc(0);
30
+ }
31
+ async read() {
32
+ try {
33
+ const handle = await openSession(this.root, this.identity.file);
34
+ try {
35
+ const stat = await handle.stat();
36
+ const signature = `${stat.dev}:${stat.ino}`;
37
+ const unchanged = async (expected, position) => {
38
+ const buffer = Buffer.alloc(expected.length);
39
+ await handle.read(buffer, 0, buffer.length, position);
40
+ return buffer.equals(expected);
41
+ };
42
+ if (signature !== this.signature || stat.size < this.offset
43
+ || (this.mtime !== stat.mtimeMs && stat.size === this.offset)
44
+ || !await unchanged(this.head, 0)
45
+ || !await unchanged(this.anchor, Math.max(0, this.offset - this.anchor.length)))
46
+ this.reset();
47
+ this.signature = signature;
48
+ this.mtime = stat.mtimeMs;
49
+ const buffer = Buffer.alloc(Math.min(this.budget, Math.max(0, stat.size - this.offset)));
50
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, this.offset);
51
+ const data = buffer.subarray(0, bytesRead);
52
+ this.offset += bytesRead;
53
+ this.feed(data);
54
+ this.head = Buffer.alloc(Math.min(256, this.offset));
55
+ await handle.read(this.head, 0, this.head.length, 0);
56
+ this.anchor = Buffer.alloc(Math.min(128, this.offset));
57
+ await handle.read(this.anchor, 0, this.anchor.length, this.offset - this.anchor.length);
58
+ const state = this.parser.snapshot;
59
+ state.bytesRead = this.offset;
60
+ state.fileSize = stat.size;
61
+ state.partial = this.offset < stat.size || this.pending.length > 0 || this.skipping;
62
+ // Do not expose stale previews after an identity failure.
63
+ return structuredClone(state);
64
+ }
65
+ finally {
66
+ await handle.close();
67
+ }
68
+ }
69
+ catch {
70
+ this.reset();
71
+ this.signature = '';
72
+ return { ...this.parser.snapshot, error: 'Agent log unavailable; no cached activity is shown.' };
73
+ }
74
+ }
75
+ feed(data) {
76
+ let start = 0;
77
+ while (start < data.length) {
78
+ const newline = data.indexOf(10, start);
79
+ const end = newline < 0 ? data.length : newline;
80
+ const part = data.subarray(start, end);
81
+ if (!this.skipping) {
82
+ if (this.pending.length + part.length > MAX_LINE) {
83
+ this.pending = Buffer.alloc(0);
84
+ this.skipping = true;
85
+ this.parser.invalidate();
86
+ }
87
+ else
88
+ this.pending = Buffer.concat([this.pending, part]);
89
+ }
90
+ if (newline < 0)
91
+ break;
92
+ if (!this.skipping) {
93
+ try {
94
+ this.parser.consume(JSON.parse(this.pending.toString('utf8')));
95
+ }
96
+ catch {
97
+ this.parser.invalidate();
98
+ }
99
+ }
100
+ this.pending = Buffer.alloc(0);
101
+ this.skipping = false;
102
+ start = newline + 1;
103
+ }
104
+ }
105
+ }
106
+ //# sourceMappingURL=reader.js.map