coolhand-cli 0.7.0 → 0.9.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 +23 -2
- package/dist/api/feedback-client.d.ts +17 -0
- package/dist/api/feedback-client.d.ts.map +1 -0
- package/dist/api/feedback-client.js +40 -0
- package/dist/api/feedback-client.js.map +1 -0
- package/dist/api/last-sync.d.ts +8 -6
- package/dist/api/last-sync.d.ts.map +1 -1
- package/dist/api/last-sync.js +27 -16
- package/dist/api/last-sync.js.map +1 -1
- package/dist/api/log-client.d.ts +17 -0
- package/dist/api/log-client.d.ts.map +1 -0
- package/dist/api/log-client.js +40 -0
- package/dist/api/log-client.js.map +1 -0
- package/dist/bin.js +0 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +326 -10
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze-claude-sessions.d.ts +6 -0
- package/dist/commands/analyze-claude-sessions.d.ts.map +1 -1
- package/dist/commands/analyze-claude-sessions.js +60 -9
- package/dist/commands/analyze-claude-sessions.js.map +1 -1
- package/dist/commands/clients.d.ts.map +1 -1
- package/dist/commands/clients.js +2 -1
- package/dist/commands/clients.js.map +1 -1
- package/dist/commands/close-optimization.js +1 -1
- package/dist/commands/close-optimization.js.map +1 -1
- package/dist/commands/fetch-log.d.ts +3 -0
- package/dist/commands/fetch-log.d.ts.map +1 -0
- package/dist/commands/{create-optimization.js → fetch-log.js} +14 -10
- package/dist/commands/fetch-log.js.map +1 -0
- package/dist/commands/get-feedback.d.ts +3 -0
- package/dist/commands/get-feedback.d.ts.map +1 -0
- package/dist/commands/get-feedback.js +70 -0
- package/dist/commands/get-feedback.js.map +1 -0
- package/dist/commands/get-optimization.d.ts.map +1 -1
- package/dist/commands/get-optimization.js +61 -10
- package/dist/commands/get-optimization.js.map +1 -1
- package/dist/commands/mcp-call.d.ts.map +1 -1
- package/dist/commands/mcp-call.js +14 -50
- package/dist/commands/mcp-call.js.map +1 -1
- package/dist/commands/search-feedback.d.ts +3 -0
- package/dist/commands/search-feedback.d.ts.map +1 -0
- package/dist/commands/search-feedback.js +71 -0
- package/dist/commands/search-feedback.js.map +1 -0
- package/dist/commands/search-logs.d.ts +3 -0
- package/dist/commands/search-logs.d.ts.map +1 -0
- package/dist/commands/search-logs.js +77 -0
- package/dist/commands/search-logs.js.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +2 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -1
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/parse-when.d.ts +17 -0
- package/dist/parse-when.d.ts.map +1 -0
- package/dist/parse-when.js +49 -0
- package/dist/parse-when.js.map +1 -0
- package/dist/sessions/claude-scanner.d.ts +14 -1
- package/dist/sessions/claude-scanner.d.ts.map +1 -1
- package/dist/sessions/claude-scanner.js +205 -41
- package/dist/sessions/claude-scanner.js.map +1 -1
- package/dist/sessions/cowork-scanner.d.ts +2 -0
- package/dist/sessions/cowork-scanner.d.ts.map +1 -1
- package/dist/sessions/cowork-scanner.js +22 -9
- package/dist/sessions/cowork-scanner.js.map +1 -1
- package/dist/sessions/redact-secrets.d.ts +14 -0
- package/dist/sessions/redact-secrets.d.ts.map +1 -0
- package/dist/sessions/redact-secrets.js +47 -0
- package/dist/sessions/redact-secrets.js.map +1 -0
- package/dist/sessions/session-filter.d.ts +28 -0
- package/dist/sessions/session-filter.d.ts.map +1 -0
- package/dist/sessions/session-filter.js +38 -0
- package/dist/sessions/session-filter.js.map +1 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/package.json +6 -6
- package/dist/commands/accounts.d.ts +0 -3
- package/dist/commands/accounts.d.ts.map +0 -1
- package/dist/commands/accounts.js +0 -59
- package/dist/commands/accounts.js.map +0 -1
- package/dist/commands/add-optimization-comment.d.ts +0 -3
- package/dist/commands/add-optimization-comment.d.ts.map +0 -1
- package/dist/commands/add-optimization-comment.js +0 -28
- package/dist/commands/add-optimization-comment.js.map +0 -1
- package/dist/commands/capture-sessions.d.ts +0 -3
- package/dist/commands/capture-sessions.d.ts.map +0 -1
- package/dist/commands/capture-sessions.js +0 -79
- package/dist/commands/capture-sessions.js.map +0 -1
- package/dist/commands/create-optimization.d.ts +0 -3
- package/dist/commands/create-optimization.d.ts.map +0 -1
- package/dist/commands/create-optimization.js.map +0 -1
|
@@ -1,40 +1,169 @@
|
|
|
1
1
|
import { promises as fs } from 'fs';
|
|
2
2
|
import * as os from 'os';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
+
import { redactSecrets } from './redact-secrets.js';
|
|
5
|
+
/** Cap on a single serialised tool input/output. Edit/Write inputs carry whole file bodies. */
|
|
6
|
+
const MAX_BLOCK_CHARS = 2000;
|
|
4
7
|
export function defaultProjectsDir() {
|
|
5
8
|
return path.join(os.homedir(), '.claude', 'projects');
|
|
6
9
|
}
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
function toCount(value) {
|
|
11
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : 0;
|
|
12
|
+
}
|
|
13
|
+
/** JSON.stringify that yields a placeholder instead of throwing on circular structures. */
|
|
14
|
+
function safeStringify(value) {
|
|
15
|
+
let json;
|
|
16
|
+
try {
|
|
17
|
+
json = JSON.stringify(value);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return '[unserializable]';
|
|
21
|
+
}
|
|
22
|
+
if (typeof json !== 'string') {
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
return json;
|
|
26
|
+
}
|
|
27
|
+
function truncate(text) {
|
|
28
|
+
return text.length > MAX_BLOCK_CHARS ? `${text.slice(0, MAX_BLOCK_CHARS)}…[truncated]` : text;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Render one content block as plain text. `thinking`/`redacted_thinking` are dropped for now
|
|
32
|
+
* (highest-sensitivity; restored once redaction is proven) and unknown types render empty. Never throws.
|
|
33
|
+
*/
|
|
34
|
+
function blockToText(block) {
|
|
35
|
+
if (!block || typeof block !== 'object') {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
const type = block.type;
|
|
39
|
+
if (type === 'text') {
|
|
40
|
+
const text = block.text;
|
|
41
|
+
return typeof text === 'string' ? text : '';
|
|
42
|
+
}
|
|
43
|
+
if (type === 'tool_use') {
|
|
44
|
+
const name = block.name;
|
|
45
|
+
const toolName = typeof name === 'string' ? name : 'unknown';
|
|
46
|
+
const input = block.input;
|
|
47
|
+
const rendered = input === undefined ? '' : ` ${truncate(redactSecrets(safeStringify(input)))}`;
|
|
48
|
+
return `[tool_use: ${toolName}]${rendered}`;
|
|
49
|
+
}
|
|
50
|
+
if (type === 'tool_result') {
|
|
51
|
+
const isError = block.is_error === true;
|
|
52
|
+
const label = isError ? '[tool_result:error]' : '[tool_result]';
|
|
53
|
+
const body = toolResultToText(block.content);
|
|
54
|
+
return body ? `${label} ${body}` : label;
|
|
55
|
+
}
|
|
56
|
+
if (type === 'image') {
|
|
57
|
+
return '[image]';
|
|
58
|
+
}
|
|
59
|
+
return '';
|
|
60
|
+
}
|
|
61
|
+
/** A tool_result's `content` is a string OR an array of blocks; render either to text. */
|
|
62
|
+
function toolResultToText(content) {
|
|
63
|
+
if (typeof content === 'string') {
|
|
64
|
+
return truncate(redactSecrets(content));
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(content)) {
|
|
67
|
+
return truncate(redactSecrets(content.map(blockToText).filter((part) => part.length > 0).join('\n')));
|
|
68
|
+
}
|
|
69
|
+
return '';
|
|
70
|
+
}
|
|
71
|
+
/** A user message's `content` is a plain string OR an array of blocks (e.g. tool_result). */
|
|
72
|
+
function userContentToText(content) {
|
|
9
73
|
if (typeof content === 'string') {
|
|
10
74
|
return content;
|
|
11
75
|
}
|
|
12
76
|
if (Array.isArray(content)) {
|
|
13
|
-
return content
|
|
14
|
-
.filter((block) => Boolean(block) &&
|
|
15
|
-
typeof block === 'object' &&
|
|
16
|
-
block.type === 'text' &&
|
|
17
|
-
typeof block.text === 'string')
|
|
18
|
-
.map((block) => block.text)
|
|
19
|
-
.join('\n');
|
|
77
|
+
return content.map(blockToText).filter((part) => part.length > 0).join('\n');
|
|
20
78
|
}
|
|
21
79
|
return '';
|
|
22
80
|
}
|
|
23
|
-
|
|
24
|
-
|
|
81
|
+
/** Deep-redact secret-looking strings while preserving object/array structure. */
|
|
82
|
+
function redactDeep(value) {
|
|
83
|
+
if (typeof value === 'string') {
|
|
84
|
+
return redactSecrets(value);
|
|
85
|
+
}
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
return value.map(redactDeep);
|
|
88
|
+
}
|
|
89
|
+
if (value && typeof value === 'object') {
|
|
90
|
+
const out = {};
|
|
91
|
+
for (const [key, inner] of Object.entries(value)) {
|
|
92
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
out[key] = redactDeep(inner);
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The final assistant turn's raw blocks, prepared for `response_body.content`: thinking is dropped
|
|
103
|
+
* (as in the message text) and every string is run through the secret scrubber so nothing sensitive
|
|
104
|
+
* rides along in the structured half of the envelope.
|
|
105
|
+
*/
|
|
106
|
+
function sanitizeResponseBlocks(blocks) {
|
|
107
|
+
const out = [];
|
|
108
|
+
for (const block of blocks) {
|
|
109
|
+
if (!block || typeof block !== 'object') {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const type = block.type;
|
|
113
|
+
if (type === 'thinking' || type === 'redacted_thinking') {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
out.push(redactDeep(block));
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
/** The stable identity of an assistant turn. One turn is split across multiple JSONL lines. */
|
|
121
|
+
function turnKey(event, message, sessionId) {
|
|
122
|
+
const requestId = event.requestId;
|
|
123
|
+
if (typeof requestId === 'string' && requestId) {
|
|
124
|
+
return requestId;
|
|
125
|
+
}
|
|
126
|
+
const messageId = message.id;
|
|
127
|
+
if (typeof messageId === 'string' && messageId) {
|
|
128
|
+
return messageId;
|
|
129
|
+
}
|
|
130
|
+
return sessionId;
|
|
25
131
|
}
|
|
26
132
|
/**
|
|
27
133
|
* Parse one transcript's raw text (newline-delimited JSON) into a SINGLE session envelope holding
|
|
28
134
|
* the whole conversation — one log per session, not one per turn. Returns `null` when the transcript
|
|
29
135
|
* contains no assistant turns. Pure function (no filesystem) so it is easy to unit test.
|
|
136
|
+
*
|
|
137
|
+
* Real transcripts split a single assistant API call across MULTIPLE lines — one per content block
|
|
138
|
+
* (thinking / text / tool_use) — and repeat the identical `usage` on every line. We therefore merge
|
|
139
|
+
* lines that share a `requestId` into one assistant message and count each turn (and its tokens)
|
|
140
|
+
* exactly once, matching benchmark/lib/transcript.mjs.
|
|
30
141
|
*/
|
|
31
142
|
export function parseTranscript(content, sessionId) {
|
|
32
143
|
const messages = [];
|
|
33
|
-
const usage = {
|
|
144
|
+
const usage = {
|
|
145
|
+
input_tokens: 0,
|
|
146
|
+
output_tokens: 0,
|
|
147
|
+
cache_read_input_tokens: 0,
|
|
148
|
+
cache_creation_input_tokens: 0,
|
|
149
|
+
};
|
|
34
150
|
let sawUsage = false;
|
|
35
151
|
let sessionModel;
|
|
36
152
|
let lastAssistant = null;
|
|
37
153
|
let turnCount = 0;
|
|
154
|
+
const countedTurns = new Set();
|
|
155
|
+
let pending = null;
|
|
156
|
+
const flushPending = () => {
|
|
157
|
+
if (!pending) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const text = redactSecrets(pending.blocks.map(blockToText).filter((part) => part.length > 0).join('\n')).trim();
|
|
161
|
+
if (text) {
|
|
162
|
+
messages.push({ role: 'assistant', content: text });
|
|
163
|
+
}
|
|
164
|
+
lastAssistant = { id: pending.key, content: pending.blocks, model: pending.model };
|
|
165
|
+
pending = null;
|
|
166
|
+
};
|
|
38
167
|
for (const line of content.split('\n')) {
|
|
39
168
|
const trimmed = line.trim();
|
|
40
169
|
if (!trimmed) {
|
|
@@ -51,47 +180,54 @@ export function parseTranscript(content, sessionId) {
|
|
|
51
180
|
continue;
|
|
52
181
|
}
|
|
53
182
|
const message = event.message;
|
|
54
|
-
if (!message) {
|
|
183
|
+
if (!message || typeof message !== 'object') {
|
|
55
184
|
continue;
|
|
56
185
|
}
|
|
57
186
|
if (event.type === 'user') {
|
|
58
|
-
//
|
|
59
|
-
|
|
187
|
+
// A user turn ends any in-progress assistant turn (e.g. a tool_use awaiting its result).
|
|
188
|
+
flushPending();
|
|
189
|
+
const text = redactSecrets(userContentToText(message.content)).trim();
|
|
60
190
|
if (text) {
|
|
61
191
|
messages.push({ role: 'user', content: text });
|
|
62
192
|
}
|
|
63
193
|
continue;
|
|
64
194
|
}
|
|
65
195
|
if (event.type === 'assistant' && message.role === 'assistant') {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
196
|
+
const key = turnKey(event, message, sessionId);
|
|
197
|
+
if (!pending || pending.key !== key) {
|
|
198
|
+
flushPending();
|
|
199
|
+
pending = { key, blocks: [], model: undefined };
|
|
200
|
+
}
|
|
201
|
+
const blocks = Array.isArray(message.content) ? message.content : [];
|
|
202
|
+
for (const block of blocks) {
|
|
203
|
+
pending.blocks.push(block);
|
|
204
|
+
}
|
|
73
205
|
const model = typeof message.model === 'string' ? message.model : undefined;
|
|
74
206
|
if (model) {
|
|
75
207
|
sessionModel = model;
|
|
208
|
+
pending.model = model;
|
|
76
209
|
}
|
|
77
|
-
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
210
|
+
// Count each turn — and sum its usage — exactly once, no matter how many lines it spans.
|
|
211
|
+
if (!countedTurns.has(key)) {
|
|
212
|
+
countedTurns.add(key);
|
|
213
|
+
turnCount += 1;
|
|
214
|
+
const turnUsage = message.usage;
|
|
215
|
+
if (turnUsage && typeof turnUsage === 'object') {
|
|
216
|
+
sawUsage = true;
|
|
217
|
+
usage.input_tokens += toCount(turnUsage.input_tokens);
|
|
218
|
+
usage.output_tokens += toCount(turnUsage.output_tokens);
|
|
219
|
+
usage.cache_read_input_tokens += toCount(turnUsage.cache_read_input_tokens);
|
|
220
|
+
usage.cache_creation_input_tokens += toCount(turnUsage.cache_creation_input_tokens);
|
|
221
|
+
}
|
|
83
222
|
}
|
|
84
|
-
lastAssistant = {
|
|
85
|
-
id: requestId ?? sessionId,
|
|
86
|
-
content: Array.isArray(message.content) ? message.content : [],
|
|
87
|
-
model,
|
|
88
|
-
};
|
|
89
223
|
}
|
|
90
224
|
}
|
|
225
|
+
flushPending();
|
|
91
226
|
// A session with no assistant turns has nothing to log.
|
|
92
227
|
if (!lastAssistant) {
|
|
93
228
|
return null;
|
|
94
229
|
}
|
|
230
|
+
const finalTurn = lastAssistant;
|
|
95
231
|
return {
|
|
96
232
|
url: `claudecode://session/${sessionId}`,
|
|
97
233
|
method: 'POST',
|
|
@@ -101,11 +237,11 @@ export function parseTranscript(content, sessionId) {
|
|
|
101
237
|
messages,
|
|
102
238
|
},
|
|
103
239
|
response_body: {
|
|
104
|
-
id:
|
|
240
|
+
id: finalTurn.id,
|
|
105
241
|
type: 'message',
|
|
106
242
|
role: 'assistant',
|
|
107
|
-
model:
|
|
108
|
-
content:
|
|
243
|
+
model: finalTurn.model ?? sessionModel,
|
|
244
|
+
content: sanitizeResponseBlocks(finalTurn.content),
|
|
109
245
|
usage: sawUsage ? usage : undefined,
|
|
110
246
|
},
|
|
111
247
|
turnCount,
|
|
@@ -118,26 +254,32 @@ export function parseTranscript(content, sessionId) {
|
|
|
118
254
|
* When `sinceTime` is given, files whose last-modified time is older than it are skipped entirely
|
|
119
255
|
* (not even read) — they cannot have grown since the last sync. `sessionCount` therefore counts only
|
|
120
256
|
* the files actually examined this run, so it reflects the work done rather than the whole corpus.
|
|
257
|
+
*
|
|
258
|
+
* When `preFilter` is given it runs on each file's metadata (id, project folder, mtime) BEFORE the
|
|
259
|
+
* file is read; a rejected file is counted in `filteredOut` and its content never leaves disk.
|
|
121
260
|
*/
|
|
122
261
|
export async function scanSessions(options = {}) {
|
|
123
262
|
const dir = options.projectsDir ?? defaultProjectsDir();
|
|
124
263
|
const sinceMs = options.sinceTime?.getTime();
|
|
264
|
+
const preFilter = options.preFilter;
|
|
125
265
|
let names;
|
|
126
266
|
try {
|
|
127
267
|
names = await fs.readdir(dir, { recursive: true });
|
|
128
268
|
}
|
|
129
269
|
catch (err) {
|
|
130
270
|
if (err.code === 'ENOENT') {
|
|
131
|
-
return { envelopes: [], sessionCount: 0, ok: true };
|
|
271
|
+
return { envelopes: [], sessionCount: 0, filteredOut: 0, ok: true };
|
|
132
272
|
}
|
|
133
273
|
throw err;
|
|
134
274
|
}
|
|
135
275
|
const files = names.filter((name) => name.endsWith('.jsonl'));
|
|
136
276
|
const envelopes = [];
|
|
137
277
|
let sessionCount = 0;
|
|
278
|
+
let filteredOut = 0;
|
|
138
279
|
for (const relativePath of files) {
|
|
139
280
|
const fullPath = path.join(dir, relativePath);
|
|
140
|
-
|
|
281
|
+
let mtimeMs = 0;
|
|
282
|
+
if (sinceMs !== undefined || preFilter !== undefined) {
|
|
141
283
|
let stat;
|
|
142
284
|
try {
|
|
143
285
|
stat = await fs.stat(fullPath);
|
|
@@ -146,9 +288,24 @@ export async function scanSessions(options = {}) {
|
|
|
146
288
|
// Unreadable transcript — skip it rather than failing the whole scan.
|
|
147
289
|
continue;
|
|
148
290
|
}
|
|
291
|
+
mtimeMs = stat.mtimeMs;
|
|
149
292
|
// Skip files unchanged since the cutoff. Use `>=` so a file touched exactly at the cutoff
|
|
150
293
|
// is still examined.
|
|
151
|
-
if (
|
|
294
|
+
if (sinceMs !== undefined && mtimeMs < sinceMs) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (preFilter !== undefined) {
|
|
299
|
+
// readdir({recursive}) yields platform separators; split on both to find the project folder.
|
|
300
|
+
const parts = relativePath.split(/[\\/]/);
|
|
301
|
+
const meta = {
|
|
302
|
+
sessionId: path.basename(relativePath, '.jsonl'),
|
|
303
|
+
project: parts.length > 1 ? parts[0] : null,
|
|
304
|
+
mtimeMs,
|
|
305
|
+
source: 'claude-code',
|
|
306
|
+
};
|
|
307
|
+
if (!preFilter(meta)) {
|
|
308
|
+
filteredOut += 1;
|
|
152
309
|
continue;
|
|
153
310
|
}
|
|
154
311
|
}
|
|
@@ -162,12 +319,19 @@ export async function scanSessions(options = {}) {
|
|
|
162
319
|
}
|
|
163
320
|
sessionCount += 1;
|
|
164
321
|
const sessionId = path.basename(relativePath, '.jsonl');
|
|
165
|
-
|
|
322
|
+
let envelope;
|
|
323
|
+
try {
|
|
324
|
+
envelope = parseTranscript(content, sessionId);
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
// A single malformed transcript must never abort the whole scan.
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
166
330
|
if (envelope) {
|
|
167
331
|
envelopes.push(envelope);
|
|
168
332
|
}
|
|
169
333
|
}
|
|
170
|
-
return { envelopes, sessionCount, ok: true };
|
|
334
|
+
return { envelopes, sessionCount, filteredOut, ok: true };
|
|
171
335
|
}
|
|
172
336
|
/** The session id this envelope represents — used as the local dedup key. */
|
|
173
337
|
export function sessionIdOf(envelope) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-scanner.js","sourceRoot":"","sources":["../../src/sessions/claude-scanner.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"claude-scanner.js","sourceRoot":"","sources":["../../src/sessions/claude-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ScanResult } from './claude-scanner.js';
|
|
2
|
+
import type { SessionFileMeta } from './session-filter.js';
|
|
2
3
|
export declare function defaultCoworkSessionsDir(): string;
|
|
3
4
|
/**
|
|
4
5
|
* Scan Claude Cowork sessions stored under `~/Library/Application Support/Claude/local-agent-mode-sessions/`.
|
|
@@ -16,5 +17,6 @@ export declare function defaultCoworkSessionsDir(): string;
|
|
|
16
17
|
export declare function scanCoworkSessions(options?: {
|
|
17
18
|
sessionsDir?: string;
|
|
18
19
|
sinceTime?: Date;
|
|
20
|
+
preFilter?: (meta: SessionFileMeta) => boolean;
|
|
19
21
|
}): Promise<ScanResult>;
|
|
20
22
|
//# sourceMappingURL=cowork-scanner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cowork-scanner.d.ts","sourceRoot":"","sources":["../../src/sessions/cowork-scanner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyC,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"cowork-scanner.d.ts","sourceRoot":"","sources":["../../src/sessions/cowork-scanner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyC,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,wBAAgB,wBAAwB,IAAI,MAAM,CAQjD;AAQD;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,OAAO,CAAC;CAC3C,GACL,OAAO,CAAC,UAAU,CAAC,CAkErB"}
|
|
@@ -26,6 +26,7 @@ const LOCAL_AUDIT_RE = /[/\\]local_([^/\\]+)[/\\]audit\.jsonl$/;
|
|
|
26
26
|
export async function scanCoworkSessions(options = {}) {
|
|
27
27
|
const dir = options.sessionsDir ?? defaultCoworkSessionsDir();
|
|
28
28
|
const sinceMs = options.sinceTime?.getTime();
|
|
29
|
+
const preFilter = options.preFilter;
|
|
29
30
|
let names;
|
|
30
31
|
try {
|
|
31
32
|
names = await fs.readdir(dir, { recursive: true });
|
|
@@ -34,14 +35,23 @@ export async function scanCoworkSessions(options = {}) {
|
|
|
34
35
|
// Treat any readdir failure (ENOENT, EACCES, ENOTDIR, …) as an empty result. Cowork scanning
|
|
35
36
|
// is best-effort and macOS-only; an error here must not abort the Claude Code capture running
|
|
36
37
|
// in parallel inside Promise.all.
|
|
37
|
-
return { envelopes: [], sessionCount: 0, ok: false };
|
|
38
|
+
return { envelopes: [], sessionCount: 0, filteredOut: 0, ok: false };
|
|
38
39
|
}
|
|
39
40
|
const files = names.filter((name) => LOCAL_AUDIT_RE.test(name));
|
|
40
41
|
const envelopes = [];
|
|
41
42
|
let sessionCount = 0;
|
|
43
|
+
let filteredOut = 0;
|
|
42
44
|
for (const relativePath of files) {
|
|
43
45
|
const fullPath = path.join(dir, relativePath);
|
|
44
|
-
|
|
46
|
+
// The id lives in the path (already matched by LOCAL_AUDIT_RE above), so it is known
|
|
47
|
+
// before the file is read — which is what lets preFilter reject without reading.
|
|
48
|
+
const m = relativePath.match(LOCAL_AUDIT_RE);
|
|
49
|
+
if (!m) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const sessionUuid = m[1];
|
|
53
|
+
let mtimeMs = 0;
|
|
54
|
+
if (sinceMs !== undefined || preFilter !== undefined) {
|
|
45
55
|
let stat;
|
|
46
56
|
try {
|
|
47
57
|
stat = await fs.stat(fullPath);
|
|
@@ -49,7 +59,15 @@ export async function scanCoworkSessions(options = {}) {
|
|
|
49
59
|
catch {
|
|
50
60
|
continue;
|
|
51
61
|
}
|
|
52
|
-
|
|
62
|
+
mtimeMs = stat.mtimeMs;
|
|
63
|
+
if (sinceMs !== undefined && mtimeMs < sinceMs) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (preFilter !== undefined) {
|
|
68
|
+
const meta = { sessionId: sessionUuid, project: null, mtimeMs, source: 'cowork' };
|
|
69
|
+
if (!preFilter(meta)) {
|
|
70
|
+
filteredOut += 1;
|
|
53
71
|
continue;
|
|
54
72
|
}
|
|
55
73
|
}
|
|
@@ -60,17 +78,12 @@ export async function scanCoworkSessions(options = {}) {
|
|
|
60
78
|
catch {
|
|
61
79
|
continue;
|
|
62
80
|
}
|
|
63
|
-
const m = relativePath.match(LOCAL_AUDIT_RE);
|
|
64
|
-
if (!m) {
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
const sessionUuid = m[1];
|
|
68
81
|
sessionCount += 1;
|
|
69
82
|
const envelope = parseTranscript(content, sessionUuid);
|
|
70
83
|
if (envelope) {
|
|
71
84
|
envelopes.push({ ...envelope, url: `cowork://session/${sessionUuid}` });
|
|
72
85
|
}
|
|
73
86
|
}
|
|
74
|
-
return { envelopes, sessionCount, ok: true };
|
|
87
|
+
return { envelopes, sessionCount, filteredOut, ok: true };
|
|
75
88
|
}
|
|
76
89
|
//# sourceMappingURL=cowork-scanner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cowork-scanner.js","sourceRoot":"","sources":["../../src/sessions/cowork-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAyC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"cowork-scanner.js","sourceRoot":"","sources":["../../src/sessions/cowork-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrub likely secrets out of captured session text before it leaves the machine.
|
|
3
|
+
*
|
|
4
|
+
* Session transcripts now carry tool inputs (file contents from Edit/Write) and tool outputs
|
|
5
|
+
* (command output, `cat .env`, printed environment), so the upload body can contain credentials.
|
|
6
|
+
* `logger.redact` only covers stderr and only Coolhand's own token shape, so this is a separate,
|
|
7
|
+
* broader scrubber applied to every message's content string in `parseTranscript`.
|
|
8
|
+
*
|
|
9
|
+
* This is best-effort defence in depth, not a guarantee: it targets common, well-shaped secret
|
|
10
|
+
* formats. It deliberately errs toward over-redaction (e.g. long hex strings) rather than leaking.
|
|
11
|
+
*/
|
|
12
|
+
/** Return `text` with recognised secrets replaced by `[REDACTED]`. Safe on empty input. */
|
|
13
|
+
export declare function redactSecrets(text: string): string;
|
|
14
|
+
//# sourceMappingURL=redact-secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact-secrets.d.ts","sourceRoot":"","sources":["../../src/sessions/redact-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA6BH,2FAA2F;AAC3F,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWlD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrub likely secrets out of captured session text before it leaves the machine.
|
|
3
|
+
*
|
|
4
|
+
* Session transcripts now carry tool inputs (file contents from Edit/Write) and tool outputs
|
|
5
|
+
* (command output, `cat .env`, printed environment), so the upload body can contain credentials.
|
|
6
|
+
* `logger.redact` only covers stderr and only Coolhand's own token shape, so this is a separate,
|
|
7
|
+
* broader scrubber applied to every message's content string in `parseTranscript`.
|
|
8
|
+
*
|
|
9
|
+
* This is best-effort defence in depth, not a guarantee: it targets common, well-shaped secret
|
|
10
|
+
* formats. It deliberately errs toward over-redaction (e.g. long hex strings) rather than leaking.
|
|
11
|
+
*/
|
|
12
|
+
/** Well-known token shapes replaced wholesale wherever they appear. */
|
|
13
|
+
const TOKEN_PATTERNS = [
|
|
14
|
+
/ch_pub_[A-Za-z0-9_-]{8,}/g, // Coolhand public token
|
|
15
|
+
/ch_priv_[A-Za-z0-9_-]{8,}/g, // Coolhand private token
|
|
16
|
+
/sk-[A-Za-z0-9_-]{16,}/g, // OpenAI / Anthropic style secret key
|
|
17
|
+
/ghp_[A-Za-z0-9]{20,}/g, // GitHub personal access token
|
|
18
|
+
/gho_[A-Za-z0-9]{20,}/g, // GitHub OAuth token
|
|
19
|
+
/github_pat_[A-Za-z0-9_]{20,}/g, // GitHub fine-grained PAT
|
|
20
|
+
/AKIA[0-9A-Z]{16}/g, // AWS access key id
|
|
21
|
+
/xox[baprs]-[A-Za-z0-9-]{10,}/g, // Slack token (bot/user/app/refresh/config)
|
|
22
|
+
/AIza[0-9A-Za-z_-]{35}/g, // Google API key
|
|
23
|
+
/sk_live_[0-9A-Za-z]{16,}/g, // Stripe live secret key
|
|
24
|
+
/sk_test_[0-9A-Za-z]{16,}/g, // Stripe test secret key
|
|
25
|
+
/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g, // JWT (three base64url segments)
|
|
26
|
+
/\bBearer\s+[A-Za-z0-9._~+/-]{12,}=*/gi, // Authorization: Bearer <token>
|
|
27
|
+
/\b[A-Fa-f0-9]{40,}\b/g, // long hex blobs (generic tokens / hashes)
|
|
28
|
+
];
|
|
29
|
+
// Two variants: a QUOTED value may contain spaces ("my secret value"); a BARE value stops at
|
|
30
|
+
// whitespace. Splitting them closes the gap where a spaced quoted secret was only partly redacted.
|
|
31
|
+
const ASSIGNMENT_QUOTED = /((?:api[_-]?key|secret|token|password|passwd|access[_-]?key|private[_-]?key)\b\s*[:=]\s*)(['"])[^'"]*\2/gi;
|
|
32
|
+
const ASSIGNMENT_BARE = /((?:api[_-]?key|secret|token|password|passwd|access[_-]?key|private[_-]?key)\b\s*[:=]\s*)[^\s'"]+/gi;
|
|
33
|
+
const REDACTED = '[REDACTED]';
|
|
34
|
+
/** Return `text` with recognised secrets replaced by `[REDACTED]`. Safe on empty input. */
|
|
35
|
+
export function redactSecrets(text) {
|
|
36
|
+
if (!text) {
|
|
37
|
+
return text;
|
|
38
|
+
}
|
|
39
|
+
let out = text
|
|
40
|
+
.replace(ASSIGNMENT_QUOTED, `$1$2${REDACTED}$2`)
|
|
41
|
+
.replace(ASSIGNMENT_BARE, `$1${REDACTED}`);
|
|
42
|
+
for (const pattern of TOKEN_PATTERNS) {
|
|
43
|
+
out = out.replace(pattern, REDACTED);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=redact-secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact-secrets.js","sourceRoot":"","sources":["../../src/sessions/redact-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,uEAAuE;AACvE,MAAM,cAAc,GAAsB;IACxC,2BAA2B,EAAE,wBAAwB;IACrD,4BAA4B,EAAE,yBAAyB;IACvD,wBAAwB,EAAE,sCAAsC;IAChE,uBAAuB,EAAE,+BAA+B;IACxD,uBAAuB,EAAE,qBAAqB;IAC9C,+BAA+B,EAAE,0BAA0B;IAC3D,mBAAmB,EAAE,oBAAoB;IACzC,+BAA+B,EAAE,4CAA4C;IAC7E,wBAAwB,EAAE,iBAAiB;IAC3C,2BAA2B,EAAE,yBAAyB;IACtD,2BAA2B,EAAE,yBAAyB;IACtD,sDAAsD,EAAE,iCAAiC;IACzF,uCAAuC,EAAE,gCAAgC;IACzE,uBAAuB,EAAE,2CAA2C;CACrE,CAAC;AAEF,6FAA6F;AAC7F,mGAAmG;AACnG,MAAM,iBAAiB,GACrB,2GAA2G,CAAC;AAC9G,MAAM,eAAe,GACnB,qGAAqG,CAAC;AAExG,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B,2FAA2F;AAC3F,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAG,GAAG,IAAI;SACX,OAAO,CAAC,iBAAiB,EAAE,OAAO,QAAQ,IAAI,CAAC;SAC/C,OAAO,CAAC,eAAe,EAAE,KAAK,QAAQ,EAAE,CAAC,CAAC;IAC7C,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;QACrC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, pre-read session filtering. The predicate built here runs on metadata knowable
|
|
3
|
+
* BEFORE a transcript is read (filename, project folder, file mtime) so excluded sessions
|
|
4
|
+
* are never loaded from disk — the compliance guarantee behind --project/--until.
|
|
5
|
+
*/
|
|
6
|
+
/** What a scanner knows about a session file before reading its content. */
|
|
7
|
+
export interface SessionFileMeta {
|
|
8
|
+
sessionId: string;
|
|
9
|
+
/** Encoded project folder under ~/.claude/projects; null for Cowork sessions. */
|
|
10
|
+
project: string | null;
|
|
11
|
+
mtimeMs: number;
|
|
12
|
+
source: 'claude-code' | 'cowork';
|
|
13
|
+
}
|
|
14
|
+
export interface FilterCriteria {
|
|
15
|
+
sinceMs?: number;
|
|
16
|
+
untilMs?: number;
|
|
17
|
+
includeProjects?: string[];
|
|
18
|
+
excludeProjects?: string[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Normalise a project name for matching: lowercase with every non-alphanumeric run
|
|
22
|
+
* collapsed to a single dash, so user input ("Coolhand CLI") and the encoded folder
|
|
23
|
+
* name ("C--Users-...-coolhand-cli") compare on the same footing.
|
|
24
|
+
*/
|
|
25
|
+
export declare function sanitizeProjectKey(value: string): string;
|
|
26
|
+
/** Build a predicate deciding whether a session file may be read and considered for upload. */
|
|
27
|
+
export declare function buildSessionFilter(criteria: FilterCriteria): (meta: SessionFileMeta) => boolean;
|
|
28
|
+
//# sourceMappingURL=session-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-filter.d.ts","sourceRoot":"","sources":["../../src/sessions/session-filter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,GAAG,QAAQ,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,+FAA+F;AAC/F,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,CAAC,IAAI,EAAE,eAAe,KAAK,OAAO,CA4B/F"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, pre-read session filtering. The predicate built here runs on metadata knowable
|
|
3
|
+
* BEFORE a transcript is read (filename, project folder, file mtime) so excluded sessions
|
|
4
|
+
* are never loaded from disk — the compliance guarantee behind --project/--until.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Normalise a project name for matching: lowercase with every non-alphanumeric run
|
|
8
|
+
* collapsed to a single dash, so user input ("Coolhand CLI") and the encoded folder
|
|
9
|
+
* name ("C--Users-...-coolhand-cli") compare on the same footing.
|
|
10
|
+
*/
|
|
11
|
+
export function sanitizeProjectKey(value) {
|
|
12
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
|
13
|
+
}
|
|
14
|
+
/** Build a predicate deciding whether a session file may be read and considered for upload. */
|
|
15
|
+
export function buildSessionFilter(criteria) {
|
|
16
|
+
const includes = (criteria.includeProjects ?? []).map(sanitizeProjectKey);
|
|
17
|
+
const excludes = (criteria.excludeProjects ?? []).map(sanitizeProjectKey);
|
|
18
|
+
return (meta) => {
|
|
19
|
+
const projectKey = meta.project === null ? null : sanitizeProjectKey(meta.project);
|
|
20
|
+
if (includes.length > 0) {
|
|
21
|
+
// A session with no project (Cowork) cannot match an include list.
|
|
22
|
+
if (projectKey === null || !includes.some((needle) => projectKey.includes(needle))) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (projectKey !== null && excludes.some((needle) => projectKey.includes(needle))) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (criteria.sinceMs !== undefined && meta.mtimeMs < criteria.sinceMs) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (criteria.untilMs !== undefined && meta.mtimeMs > criteria.untilMs) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=session-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-filter.js","sourceRoot":"","sources":["../../src/sessions/session-filter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;AACzD,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,kBAAkB,CAAC,QAAwB;IACzD,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAE1E,OAAO,CAAC,IAAqB,EAAW,EAAE;QACxC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEnF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,mEAAmE;YACnE,IAAI,UAAU,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBACnF,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,IAAI,UAAU,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YAClF,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}
|