coolhand-cli 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -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/bin.js +0 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +194 -4
- 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/claude.d.ts +3 -22
- package/dist/commands/claude.d.ts.map +1 -1
- package/dist/commands/claude.js +3 -142
- package/dist/commands/claude.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/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/monitor.d.ts +9 -0
- package/dist/commands/monitor.d.ts.map +1 -0
- package/dist/commands/monitor.js +10 -0
- package/dist/commands/monitor.js.map +1 -0
- 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/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/proxy/proxy.d.ts +2 -0
- package/dist/proxy/proxy.d.ts.map +1 -1
- package/dist/proxy/proxy.js +1 -0
- package/dist/proxy/proxy.js.map +1 -1
- package/dist/proxy/sender.d.ts +1 -0
- package/dist/proxy/sender.d.ts.map +1 -1
- package/dist/proxy/sender.js +1 -1
- package/dist/proxy/sender.js.map +1 -1
- package/dist/proxy/wrap-runner.d.ts +36 -0
- package/dist/proxy/wrap-runner.d.ts.map +1 -0
- package/dist/proxy/wrap-runner.js +153 -0
- package/dist/proxy/wrap-runner.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 +40 -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 +2 -2
- 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 +0 -38
- package/dist/commands/create-optimization.js.map +0 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CliError } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a user-supplied point in time for --since/--until style flags.
|
|
4
|
+
*
|
|
5
|
+
* Accepted forms:
|
|
6
|
+
* - `Nh` / `Nd` / `Nw` — N hours/days/weeks before `now` (e.g. `7d`).
|
|
7
|
+
* - `YYYY-MM-DD` — a local calendar day; `boundary` picks its start (00:00:00.000)
|
|
8
|
+
* or end (23:59:59.999) so `--until 2026-06-30` includes the whole day.
|
|
9
|
+
* - anything `new Date()` accepts, e.g. a full ISO datetime.
|
|
10
|
+
*
|
|
11
|
+
* `now` is injected rather than read from the clock so callers share one reference
|
|
12
|
+
* instant per run and tests are deterministic.
|
|
13
|
+
*/
|
|
14
|
+
export function parseWhen(input, opts) {
|
|
15
|
+
const trimmed = input.trim();
|
|
16
|
+
const duration = trimmed.match(/^(\d+)([hdw])$/);
|
|
17
|
+
if (duration) {
|
|
18
|
+
const count = Number(duration[1]);
|
|
19
|
+
const unitMs = { h: 3600000, d: 86400000, w: 604800000 }[duration[2]];
|
|
20
|
+
return new Date(opts.now.getTime() - count * unitMs);
|
|
21
|
+
}
|
|
22
|
+
const day = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
23
|
+
if (day) {
|
|
24
|
+
const [, year, month, dayOfMonth] = day;
|
|
25
|
+
// Construct via local components (not the ISO string, which Date parses as UTC)
|
|
26
|
+
// so the day boundary matches the user's timezone.
|
|
27
|
+
const parsed = opts.boundary === 'start'
|
|
28
|
+
? new Date(Number(year), Number(month) - 1, Number(dayOfMonth), 0, 0, 0, 0)
|
|
29
|
+
: new Date(Number(year), Number(month) - 1, Number(dayOfMonth), 23, 59, 59, 999);
|
|
30
|
+
// Date silently rolls invalid components over into the next day/month (e.g. 2026-02-30
|
|
31
|
+
// becomes March 2nd) instead of rejecting them, so confirm the parsed date's components
|
|
32
|
+
// still match what was typed before accepting it.
|
|
33
|
+
const rolledOver = parsed.getFullYear() !== Number(year) ||
|
|
34
|
+
parsed.getMonth() !== Number(month) - 1 ||
|
|
35
|
+
parsed.getDate() !== Number(dayOfMonth);
|
|
36
|
+
if (Number.isNaN(parsed.getTime()) || rolledOver) {
|
|
37
|
+
throw new CliError('INVALID_ARGS', `Invalid date "${input}". Use YYYY-MM-DD, an ISO datetime, or a duration like 12h, 7d, 2w.`);
|
|
38
|
+
}
|
|
39
|
+
return parsed;
|
|
40
|
+
}
|
|
41
|
+
if (trimmed) {
|
|
42
|
+
const parsed = new Date(trimmed);
|
|
43
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
44
|
+
return parsed;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
throw new CliError('INVALID_ARGS', `Invalid date "${input}". Use YYYY-MM-DD, an ISO datetime, or a duration like 12h, 7d, 2w.`);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=parse-when.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-when.js","sourceRoot":"","sources":["../src/parse-when.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,IAA8C;IACrF,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE7B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACjD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,OAAS,EAAE,CAAC,EAAE,QAAU,EAAE,CAAC,EAAE,SAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAoB,CAAC,CAAC;QAC/F,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACvD,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,GAAG,GAAG,CAAC;QACxC,gFAAgF;QAChF,mDAAmD;QACnD,MAAM,MAAM,GACV,IAAI,CAAC,QAAQ,KAAK,OAAO;YACvB,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC3E,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QACrF,uFAAuF;QACvF,wFAAwF;QACxF,kDAAkD;QAClD,MAAM,UAAU,GACd,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,IAAI,CAAC;YACrC,MAAM,CAAC,QAAQ,EAAE,KAAK,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;YACvC,MAAM,CAAC,OAAO,EAAE,KAAK,MAAM,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;YACjD,MAAM,IAAI,QAAQ,CAChB,cAAc,EACd,iBAAiB,KAAK,qEAAqE,CAC5F,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YACpC,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,QAAQ,CAChB,cAAc,EACd,iBAAiB,KAAK,qEAAqE,CAC5F,CAAC;AACJ,CAAC"}
|
package/dist/proxy/proxy.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface ProxyOptions {
|
|
|
5
5
|
apiKey: string;
|
|
6
6
|
apiEndpoint?: string;
|
|
7
7
|
silent?: boolean;
|
|
8
|
+
/** Overrides the default `<package>/claude` collector label sent with each captured request. */
|
|
9
|
+
collector?: string;
|
|
8
10
|
}
|
|
9
11
|
export interface ProxyInstance {
|
|
10
12
|
port: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/proxy.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/proxy.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAWD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,aAAa,EACjB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC,CA8GxB"}
|
package/dist/proxy/proxy.js
CHANGED
package/dist/proxy/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/proxy/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,cAAc,EAA4B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/proxy/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,cAAc,EAA4B,MAAM,aAAa,CAAC;AA2BvE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,EAAiB,EACjB,OAAqB;IAErB,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC9B,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;KACtC,CAAC,CAAC;IAEH,0DAA0D;IAC1D,MAAM,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC1D,+EAA+E;IAC/E,MAAM,aAAa,GAAG,IAAI,GAAG,EAAiB,CAAC;IAE/C,MAAM,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAqB,EAAE,EAAE;QACnD,gFAAgF;QAChF,gFAAgF;QAChF,IAAI,OAAgB,CAAC;QACrB,IAAI,CAAC;YAAC,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO;QAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QACzB,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE;YAC1B,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,OAAwD,CAAC;YACrF,WAAW,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7D,cAAc,EAAE,GAAG,CAAC,YAAY,EAAE,cAAc,IAAI,WAAW,CAAC,GAAG,EAAE;YACrE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAmB,EAAE,EAAE;QAC/C,sEAAsE;QACtE,uEAAuE;QACvE,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,GAAsB,EAAE,EAAE;QACrD,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QACrB,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAE/B,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,EAAE,qBAAqB,IAAI,WAAW,CAAC,GAAG,EAAE,CAAC;QAClF,MAAM,UAAU,GAAG,YAAY,GAAG,GAAG,CAAC,cAAc,CAAC;QAErD,0EAA0E;QAC1E,yEAAyE;QACzE,gEAAgE;QAChE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,EAAE,eAAe,CAAC,EAAE,EAAE;YAC3G,MAAM,QAAQ,GAAwB;gBACpC,OAAO,EAAE;oBACP,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,GAAG,EAAE,GAAG,CAAC,GAAG;oBACZ,OAAO,EAAE,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC;oBACrC,IAAI,EAAE,eAAe;iBACtB;gBACD,QAAQ,EAAE;oBACR,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,OAAO,EAAE,eAAe,CAAC,cAAc,CAAC,GAAG,CAAC,OAAwD,CAAC,CAAC;oBACtG,IAAI,EAAE,gBAAgB;iBACvB;gBACD,SAAS,EAAE,GAAG,CAAC,SAAS;aACzB,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CACX,6BAA6B,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,UAAU,KAAK,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CACxG,CAAC;YACJ,CAAC;YAED,OAAO,cAAc,CAAC,QAAQ,EAAE;gBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B,CAAC,CAAC;QACL,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACf,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,uDAAuD;IACvD,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC,eAAe,EAAE,CAAC;IAC/C,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IAEtC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,0CAA0C,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,sEAAsE;YACtE,kEAAkE;YAClE,uEAAuE;YACvE,uEAAuE;YACvE,4DAA4D;YAC5D,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,sEAAsE;YACtE,gEAAgE;YAChE,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAM,CAAC;YAC1C,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,EAAE,CAAC;gBAC5D,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;YAC/C,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/proxy/sender.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ interface SendOptions {
|
|
|
16
16
|
apiKey: string;
|
|
17
17
|
apiEndpoint?: string;
|
|
18
18
|
silent?: boolean;
|
|
19
|
+
collector?: string;
|
|
19
20
|
}
|
|
20
21
|
/** @internal Reset the call ID counter. Exposed for test isolation only.
|
|
21
22
|
* Call in beforeEach in any test file that imports sendToCoolhand — Jest
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sender.d.ts","sourceRoot":"","sources":["../../src/proxy/sender.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B,CAAC;IACF,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"sender.d.ts","sourceRoot":"","sources":["../../src/proxy/sender.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B,CAAC;IACF,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAAiB;AAE9D;;;GAGG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAuDf"}
|
package/dist/proxy/sender.js
CHANGED
|
@@ -31,7 +31,7 @@ export async function sendToCoolhand(captured, options) {
|
|
|
31
31
|
timestamp: captured.timestamp,
|
|
32
32
|
protocol: new URL(captured.request.url).protocol.replace(":", ""),
|
|
33
33
|
},
|
|
34
|
-
collector: `${PACKAGE_IDENTIFIER}/claude`,
|
|
34
|
+
collector: options.collector ?? `${PACKAGE_IDENTIFIER}/claude`,
|
|
35
35
|
},
|
|
36
36
|
};
|
|
37
37
|
const response = await fetch(endpoint, {
|
package/dist/proxy/sender.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sender.js","sourceRoot":"","sources":["../../src/proxy/sender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"sender.js","sourceRoot":"","sources":["../../src/proxy/sender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAwBnD,MAAM,gBAAgB,GAAG,kDAAkD,CAAC;AAE5E,IAAI,OAAO,GAAG,CAAC,CAAC;AAEhB;;;GAGG;AACH,MAAM,UAAU,qBAAqB,KAAW,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;AAE9D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAA6B,EAC7B,OAAoB;IAEpB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,IAAI,gBAAgB,CAAC;IAEzD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAM,CAAC,CAAC;IAE7D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG;YACd,eAAe,EAAE;gBACf,WAAW,EAAE;oBACX,EAAE,EAAE,EAAE,OAAO;oBACb,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM;oBAC/B,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG;oBACzB,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO;oBACjC,YAAY,EAAE,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;oBAC9C,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAChD,gBAAgB,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO;oBAC3C,WAAW,EAAE,QAAQ,CAAC,QAAQ,CAAC,UAAU;oBACzC,SAAS,EAAE,QAAQ,CAAC,SAAS;oBAC7B,QAAQ,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;iBAClE;gBACD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,GAAG,kBAAkB,SAAS;aAC/D;SACF,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;YACrC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,MAAM;aACpB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YAC7B,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,wEAAwE;QACxE,kEAAkE;QAClE,YAAY,CAAC,OAAO,CAAC,CAAC;QAEtB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,OAAO,CAAC,KAAK,CACX,gDAAgD,QAAQ,CAAC,MAAM,MAAM,IAAI,EAAE,CAC5E,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,2BAA2B,QAAQ,CAAC,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,KAAK,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { startProxy, type ProxyInstance } from './proxy.js';
|
|
3
|
+
import { getOrCreateCA } from './certs.js';
|
|
4
|
+
export interface WrapDeps {
|
|
5
|
+
spawnFn?: typeof spawn;
|
|
6
|
+
startProxyFn?: (ca: Awaited<ReturnType<typeof getOrCreateCA>>, opts: Parameters<typeof startProxy>[1]) => Promise<ProxyInstance>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* On Windows, .cmd shims cannot be spawned without a shell. Rather than using
|
|
10
|
+
* shell:true (which forwards args as an unquoted string to cmd.exe, enabling
|
|
11
|
+
* metacharacter injection), we invoke cmd.exe /d /s /c directly with each arg
|
|
12
|
+
* double-quoted and windowsVerbatimArguments:true so Node does not re-quote them.
|
|
13
|
+
*
|
|
14
|
+
* Quoting rules applied per arg:
|
|
15
|
+
* 1. Double trailing backslashes (a trailing \ would escape the closing ")
|
|
16
|
+
* 2. Escape embedded " as ""
|
|
17
|
+
* 3. Escape % as %% to prevent cmd.exe environment-variable expansion
|
|
18
|
+
* 4. Wrap in double quotes unconditionally
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveWrapSpawn(cmd: string, args: string[], platform?: NodeJS.Platform): {
|
|
21
|
+
cmd: string;
|
|
22
|
+
spawnArgs: string[];
|
|
23
|
+
windowsVerbatimArguments?: true;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Build the full ingest endpoint for a given client's base_url.
|
|
27
|
+
* The CLI stores only the site base_url, so append the ingest path here.
|
|
28
|
+
* Returns undefined for the default base_url (the proxy already uses the right endpoint).
|
|
29
|
+
*/
|
|
30
|
+
export declare function endpointForBaseUrl(baseUrl: string): string | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Run an arbitrary child command behind the Coolhand proxy with the stored API key
|
|
33
|
+
* filled in. Starts an in-process HTTPS MITM proxy and spawns `cmd` with proxy env vars.
|
|
34
|
+
*/
|
|
35
|
+
export declare function runWrapped(cmd: string, args: string[], clientId: string | undefined, deps?: WrapDeps): Promise<number>;
|
|
36
|
+
//# sourceMappingURL=wrap-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap-runner.d.ts","sourceRoot":"","sources":["../../src/proxy/wrap-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAKtC,OAAO,EAAE,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AAGxD,MAAM,WAAW,QAAQ;IACvB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;CAClI;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,kBAAmB,GAC1B;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,wBAAwB,CAAC,EAAE,IAAI,CAAA;CAAE,CAgBvE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKtE;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,IAAI,GAAE,QAAa,GAClB,OAAO,CAAC,MAAM,CAAC,CA4FjB"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { ExitCode, CliError } from '../errors.js';
|
|
3
|
+
import { logger, redact } from '../logger.js';
|
|
4
|
+
import { loadConfig, resolveClient } from '../config.js';
|
|
5
|
+
import { DEFAULT_BASE_URL } from '../types.js';
|
|
6
|
+
import { startProxy } from './proxy.js';
|
|
7
|
+
import { getOrCreateCA, getCertPath } from './certs.js';
|
|
8
|
+
import { PACKAGE_IDENTIFIER } from '../version.js';
|
|
9
|
+
/**
|
|
10
|
+
* On Windows, .cmd shims cannot be spawned without a shell. Rather than using
|
|
11
|
+
* shell:true (which forwards args as an unquoted string to cmd.exe, enabling
|
|
12
|
+
* metacharacter injection), we invoke cmd.exe /d /s /c directly with each arg
|
|
13
|
+
* double-quoted and windowsVerbatimArguments:true so Node does not re-quote them.
|
|
14
|
+
*
|
|
15
|
+
* Quoting rules applied per arg:
|
|
16
|
+
* 1. Double trailing backslashes (a trailing \ would escape the closing ")
|
|
17
|
+
* 2. Escape embedded " as ""
|
|
18
|
+
* 3. Escape % as %% to prevent cmd.exe environment-variable expansion
|
|
19
|
+
* 4. Wrap in double quotes unconditionally
|
|
20
|
+
*/
|
|
21
|
+
export function resolveWrapSpawn(cmd, args, platform = process.platform) {
|
|
22
|
+
if (platform !== 'win32') {
|
|
23
|
+
return { cmd, spawnArgs: args };
|
|
24
|
+
}
|
|
25
|
+
const escaped = args.map((a) => {
|
|
26
|
+
const s = a
|
|
27
|
+
.replace(/(\\+)$/, '$1$1') // double trailing backslashes
|
|
28
|
+
.replace(/"/g, '""') // escape embedded quotes
|
|
29
|
+
.replace(/%/g, '%%'); // prevent env-var expansion
|
|
30
|
+
return `"${s}"`;
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
cmd: process.env['ComSpec'] ?? 'cmd.exe',
|
|
34
|
+
spawnArgs: ['/d', '/s', '/c', [`"${cmd}"`, ...escaped].join(' ')],
|
|
35
|
+
windowsVerbatimArguments: true,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build the full ingest endpoint for a given client's base_url.
|
|
40
|
+
* The CLI stores only the site base_url, so append the ingest path here.
|
|
41
|
+
* Returns undefined for the default base_url (the proxy already uses the right endpoint).
|
|
42
|
+
*/
|
|
43
|
+
export function endpointForBaseUrl(baseUrl) {
|
|
44
|
+
if (!baseUrl || baseUrl === DEFAULT_BASE_URL) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
return `${baseUrl.replace(/\/+$/, '')}/api/v2/llm_request_logs`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run an arbitrary child command behind the Coolhand proxy with the stored API key
|
|
51
|
+
* filled in. Starts an in-process HTTPS MITM proxy and spawns `cmd` with proxy env vars.
|
|
52
|
+
*/
|
|
53
|
+
export async function runWrapped(cmd, args, clientId, deps = {}) {
|
|
54
|
+
const spawnFn = deps.spawnFn ?? spawn;
|
|
55
|
+
try {
|
|
56
|
+
const cfg = await loadConfig();
|
|
57
|
+
const entry = await resolveClient(cfg, clientId);
|
|
58
|
+
if (!entry.api_key) {
|
|
59
|
+
throw new CliError('NOT_CONFIGURED', 'This client has no public API key — LLM capture requires the public key. Run `coolhand login` to re-authenticate.');
|
|
60
|
+
}
|
|
61
|
+
const ca = await getOrCreateCA();
|
|
62
|
+
const certPath = getCertPath();
|
|
63
|
+
const apiEndpoint = endpointForBaseUrl(entry.base_url);
|
|
64
|
+
const proxy = await (deps.startProxyFn ?? startProxy)(ca, {
|
|
65
|
+
apiKey: entry.api_key,
|
|
66
|
+
apiEndpoint,
|
|
67
|
+
silent: true,
|
|
68
|
+
collector: `${PACKAGE_IDENTIFIER}/${cmd}`,
|
|
69
|
+
});
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
let stopped = false;
|
|
72
|
+
// stopped is set synchronously before the first await so concurrent
|
|
73
|
+
// callers (error + close can both fire) see it immediately and skip.
|
|
74
|
+
const stopOnce = () => {
|
|
75
|
+
if (stopped) {
|
|
76
|
+
return Promise.resolve();
|
|
77
|
+
}
|
|
78
|
+
stopped = true;
|
|
79
|
+
return proxy.stop();
|
|
80
|
+
};
|
|
81
|
+
let child;
|
|
82
|
+
try {
|
|
83
|
+
const { cmd: spawnCmd, spawnArgs, windowsVerbatimArguments } = resolveWrapSpawn(cmd, args);
|
|
84
|
+
child = spawnFn(spawnCmd, spawnArgs, {
|
|
85
|
+
stdio: 'inherit',
|
|
86
|
+
windowsVerbatimArguments,
|
|
87
|
+
env: {
|
|
88
|
+
...process.env,
|
|
89
|
+
COOLHAND_API_KEY: entry.api_key,
|
|
90
|
+
HTTP_PROXY: `http://127.0.0.1:${proxy.port}`,
|
|
91
|
+
HTTPS_PROXY: `http://127.0.0.1:${proxy.port}`,
|
|
92
|
+
NO_PROXY: 'localhost,127.0.0.1,::1',
|
|
93
|
+
SSL_CERT_FILE: certPath,
|
|
94
|
+
NODE_EXTRA_CA_CERTS: certPath,
|
|
95
|
+
REQUESTS_CA_BUNDLE: certPath,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch (spawnErr) {
|
|
100
|
+
if (spawnErr instanceof Error) {
|
|
101
|
+
logger.info(`Error: ${redact(spawnErr.message)}`);
|
|
102
|
+
}
|
|
103
|
+
// Chain .catch → .then so resolve() is called only after stop() drains,
|
|
104
|
+
// mirroring the error/close handler pattern and avoiding abandoned sends.
|
|
105
|
+
stopOnce()
|
|
106
|
+
.catch((e) => {
|
|
107
|
+
const msg = e instanceof Error ? redact(e.message) : String(e);
|
|
108
|
+
logger.info(`Error: ${msg}`);
|
|
109
|
+
})
|
|
110
|
+
.then(() => resolve(ExitCode.INTERNAL));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
child.on('error', async (err) => {
|
|
114
|
+
try {
|
|
115
|
+
await stopOnce();
|
|
116
|
+
}
|
|
117
|
+
catch (stopErr) {
|
|
118
|
+
if (stopErr instanceof Error) {
|
|
119
|
+
logger.info(`Error: ${redact(stopErr.message)}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
logger.info(`Error: ${redact(err.message)}`);
|
|
124
|
+
resolve(ExitCode.INTERNAL);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
child.on('close', async (code) => {
|
|
128
|
+
try {
|
|
129
|
+
await stopOnce();
|
|
130
|
+
}
|
|
131
|
+
catch (stopErr) {
|
|
132
|
+
if (stopErr instanceof Error) {
|
|
133
|
+
logger.info(`Error: ${redact(stopErr.message)}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
resolve(code ?? ExitCode.INTERNAL);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
if (err instanceof CliError) {
|
|
144
|
+
logger.info(`Error: ${redact(err.message)} [${err.code}]`);
|
|
145
|
+
return err.exitCode;
|
|
146
|
+
}
|
|
147
|
+
if (err instanceof Error) {
|
|
148
|
+
logger.info(`Error: ${redact(err.message)}`);
|
|
149
|
+
}
|
|
150
|
+
return ExitCode.INTERNAL;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=wrap-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap-runner.js","sourceRoot":"","sources":["../../src/proxy/wrap-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SessionFileMeta } from './session-filter.js';
|
|
1
2
|
/** One message in the reconstructed conversation. */
|
|
2
3
|
export interface ConversationMessage {
|
|
3
4
|
role: string;
|
|
@@ -7,7 +8,8 @@ export interface ConversationMessage {
|
|
|
7
8
|
* An Anthropic-shaped envelope for ONE whole Claude Code session (a conversation). The server's
|
|
8
9
|
* `claude_code` ingestor recognises it by the synthetic `claudecode://session/<sessionId>` url,
|
|
9
10
|
* stores the full back-and-forth (the server already treats a multi-message request as one "chat"
|
|
10
|
-
* log), and deduplicates on the session id. `request_body.messages` is the conversation
|
|
11
|
+
* log), and deduplicates on the session id. `request_body.messages` is the conversation — including
|
|
12
|
+
* tool calls and tool results, serialised into each message's text so nothing is lost;
|
|
11
13
|
* `response_body` is the final assistant turn; `response_body.usage` is the session's summed tokens.
|
|
12
14
|
*/
|
|
13
15
|
export interface CaptureEnvelope {
|
|
@@ -32,6 +34,8 @@ export interface CaptureEnvelope {
|
|
|
32
34
|
export interface ScanResult {
|
|
33
35
|
envelopes: CaptureEnvelope[];
|
|
34
36
|
sessionCount: number;
|
|
37
|
+
/** Number of session files rejected by the caller's preFilter — skipped without being read. */
|
|
38
|
+
filteredOut: number;
|
|
35
39
|
/** False when the scan directory could not be read and the error was swallowed. The caller must
|
|
36
40
|
* not advance its mtime cutoff in this case — doing so would permanently hide pre-existing files
|
|
37
41
|
* whose mtimes predate the new cutoff, since the turn-count guard never sees them if they are
|
|
@@ -43,6 +47,11 @@ export declare function defaultProjectsDir(): string;
|
|
|
43
47
|
* Parse one transcript's raw text (newline-delimited JSON) into a SINGLE session envelope holding
|
|
44
48
|
* the whole conversation — one log per session, not one per turn. Returns `null` when the transcript
|
|
45
49
|
* contains no assistant turns. Pure function (no filesystem) so it is easy to unit test.
|
|
50
|
+
*
|
|
51
|
+
* Real transcripts split a single assistant API call across MULTIPLE lines — one per content block
|
|
52
|
+
* (thinking / text / tool_use) — and repeat the identical `usage` on every line. We therefore merge
|
|
53
|
+
* lines that share a `requestId` into one assistant message and count each turn (and its tokens)
|
|
54
|
+
* exactly once, matching benchmark/lib/transcript.mjs.
|
|
46
55
|
*/
|
|
47
56
|
export declare function parseTranscript(content: string, sessionId: string): CaptureEnvelope | null;
|
|
48
57
|
/**
|
|
@@ -52,10 +61,14 @@ export declare function parseTranscript(content: string, sessionId: string): Cap
|
|
|
52
61
|
* When `sinceTime` is given, files whose last-modified time is older than it are skipped entirely
|
|
53
62
|
* (not even read) — they cannot have grown since the last sync. `sessionCount` therefore counts only
|
|
54
63
|
* the files actually examined this run, so it reflects the work done rather than the whole corpus.
|
|
64
|
+
*
|
|
65
|
+
* When `preFilter` is given it runs on each file's metadata (id, project folder, mtime) BEFORE the
|
|
66
|
+
* file is read; a rejected file is counted in `filteredOut` and its content never leaves disk.
|
|
55
67
|
*/
|
|
56
68
|
export declare function scanSessions(options?: {
|
|
57
69
|
projectsDir?: string;
|
|
58
70
|
sinceTime?: Date;
|
|
71
|
+
preFilter?: (meta: SessionFileMeta) => boolean;
|
|
59
72
|
}): Promise<ScanResult>;
|
|
60
73
|
/** The session id this envelope represents — used as the local dedup key. */
|
|
61
74
|
export declare function sessionIdOf(envelope: CaptureEnvelope): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-scanner.d.ts","sourceRoot":"","sources":["../../src/sessions/claude-scanner.ts"],"names":[],"mappings":"AAIA,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"claude-scanner.d.ts","sourceRoot":"","sources":["../../src/sessions/claude-scanner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,mBAAmB,EAAE,CAAC;KACjC,CAAC;IACF,aAAa,EAAE;QACb,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,2FAA2F;IAC3F,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,WAAW,EAAE,MAAM,CAAC;IACpB;;;sBAGkB;IAClB,EAAE,EAAE,OAAO,CAAC;CACb;AAKD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAsJD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAyH1F;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,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,CA8ErB;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAG7D"}
|