@optimuslabs/runtime 0.3.4 → 0.3.12

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 (84) hide show
  1. package/dist/index.js +36 -70
  2. package/dist/index.js.map +1 -1
  3. package/dist/lib/client-event.d.ts.map +1 -1
  4. package/dist/lib/client-event.js +35 -25
  5. package/dist/lib/client-event.js.map +1 -1
  6. package/dist/lib/login.d.ts +15 -0
  7. package/dist/lib/login.d.ts.map +1 -0
  8. package/dist/lib/login.js +109 -0
  9. package/dist/lib/login.js.map +1 -0
  10. package/dist/lib/pii-scrub.d.ts +9 -0
  11. package/dist/lib/pii-scrub.d.ts.map +1 -0
  12. package/dist/lib/pii-scrub.js +17 -0
  13. package/dist/lib/pii-scrub.js.map +1 -0
  14. package/dist/lib/prompt-collection-policy.d.ts +10 -0
  15. package/dist/lib/prompt-collection-policy.d.ts.map +1 -1
  16. package/dist/lib/prompt-collection-policy.js +42 -6
  17. package/dist/lib/prompt-collection-policy.js.map +1 -1
  18. package/dist/lib/startup-sync.d.ts.map +1 -1
  19. package/dist/lib/startup-sync.js +78 -56
  20. package/dist/lib/startup-sync.js.map +1 -1
  21. package/dist/lib/telemetry/build-event.d.ts.map +1 -1
  22. package/dist/lib/telemetry/build-event.js +73 -6
  23. package/dist/lib/telemetry/build-event.js.map +1 -1
  24. package/dist/lib/telemetry/canonical.d.ts +1 -1
  25. package/dist/lib/telemetry/canonical.d.ts.map +1 -1
  26. package/dist/lib/telemetry/canonical.js +23 -14
  27. package/dist/lib/telemetry/canonical.js.map +1 -1
  28. package/dist/lib/telemetry/index.d.ts +1 -1
  29. package/dist/lib/telemetry/index.d.ts.map +1 -1
  30. package/dist/lib/telemetry/index.js +1 -1
  31. package/dist/lib/telemetry/index.js.map +1 -1
  32. package/dist/lib/telemetry/prompt-privacy.d.ts +7 -1
  33. package/dist/lib/telemetry/prompt-privacy.d.ts.map +1 -1
  34. package/dist/lib/telemetry/prompt-privacy.js +13 -3
  35. package/dist/lib/telemetry/prompt-privacy.js.map +1 -1
  36. package/dist/lib/telemetry/types.d.ts +18 -0
  37. package/dist/lib/telemetry/types.d.ts.map +1 -1
  38. package/dist/lib/telemetry/wire-metadata.d.ts +21 -6
  39. package/dist/lib/telemetry/wire-metadata.d.ts.map +1 -1
  40. package/dist/lib/telemetry/wire-metadata.js +51 -19
  41. package/dist/lib/telemetry/wire-metadata.js.map +1 -1
  42. package/dist/lib/tofu.d.ts +1 -0
  43. package/dist/lib/tofu.d.ts.map +1 -1
  44. package/dist/lib/tofu.js +1 -1
  45. package/dist/lib/tofu.js.map +1 -1
  46. package/dist/lib/transcript.d.ts +33 -0
  47. package/dist/lib/transcript.d.ts.map +1 -0
  48. package/dist/lib/transcript.js +217 -0
  49. package/dist/lib/transcript.js.map +1 -0
  50. package/dist/test/canonical.test.js +40 -0
  51. package/dist/test/canonical.test.js.map +1 -1
  52. package/dist/test/client-event-scrub.test.d.ts +2 -0
  53. package/dist/test/client-event-scrub.test.d.ts.map +1 -0
  54. package/dist/test/client-event-scrub.test.js +36 -0
  55. package/dist/test/client-event-scrub.test.js.map +1 -0
  56. package/dist/test/login.test.d.ts +2 -0
  57. package/dist/test/login.test.d.ts.map +1 -0
  58. package/dist/test/login.test.js +60 -0
  59. package/dist/test/login.test.js.map +1 -0
  60. package/dist/test/org-fingerprint-key.test.d.ts +2 -0
  61. package/dist/test/org-fingerprint-key.test.d.ts.map +1 -0
  62. package/dist/test/org-fingerprint-key.test.js +39 -0
  63. package/dist/test/org-fingerprint-key.test.js.map +1 -0
  64. package/dist/test/org-scrub-setting.test.d.ts +2 -0
  65. package/dist/test/org-scrub-setting.test.d.ts.map +1 -0
  66. package/dist/test/org-scrub-setting.test.js +42 -0
  67. package/dist/test/org-scrub-setting.test.js.map +1 -0
  68. package/dist/test/prompt-privacy.test.js +19 -2
  69. package/dist/test/prompt-privacy.test.js.map +1 -1
  70. package/dist/test/startup-sync-scrub.test.d.ts +2 -0
  71. package/dist/test/startup-sync-scrub.test.d.ts.map +1 -0
  72. package/dist/test/startup-sync-scrub.test.js +36 -0
  73. package/dist/test/startup-sync-scrub.test.js.map +1 -0
  74. package/dist/test/telemetry.test.js +62 -0
  75. package/dist/test/telemetry.test.js.map +1 -1
  76. package/dist/test/transcript.test.d.ts +2 -0
  77. package/dist/test/transcript.test.d.ts.map +1 -0
  78. package/dist/test/transcript.test.js +162 -0
  79. package/dist/test/transcript.test.js.map +1 -0
  80. package/dist/test/wire-metadata.test.d.ts +2 -0
  81. package/dist/test/wire-metadata.test.d.ts.map +1 -0
  82. package/dist/test/wire-metadata.test.js +110 -0
  83. package/dist/test/wire-metadata.test.js.map +1 -0
  84. package/package.json +3 -2
@@ -1,28 +1,60 @@
1
+ import { SCRUBBER_VERSION, scrubText, scrubValue } from "../pii-scrub.js";
2
+ import { readFingerprintKey } from "../prompt-collection-policy.js";
1
3
  /**
2
- * Tool-call metadata keys owned by the Django ingest layer (`enrich_tool_call_metadata`).
3
- * Keep in sync with the keys popped at the start of ``enrich_tool_call_metadata``.
4
- * The sensor sends raw hook fields only; strip these before HTTP so spoofed values
5
- * cannot influence the API.
4
+ * The tool-call metadata fields sent to the backend, and nothing else. An allowlist, so a field
5
+ * added to the event later stays on the Mac until someone decides it should be sent (and adds it
6
+ * here, and to docs/pii-scrubbing/TOOL_CALL_FIELDS.md). Fields the backend works out itself (the
7
+ * classification, the MCP split, the machine's user profile) are not on it, so a Mac cannot set
8
+ * them.
6
9
  */
7
- export const SERVER_OWNED_TOOL_CALL_METADATA_KEYS = [
8
- "user_profile",
9
- "hardware_uuid",
10
- "action_type",
11
- "command_components",
12
- "file_path",
13
- "pattern",
14
- "mcp_server",
15
- "mcp_tool",
10
+ export const WIRE_TOOL_CALL_METADATA_KEYS = [
11
+ "tool_name",
12
+ "tool_input",
13
+ "user_prompt",
14
+ "user_prompt_hash",
15
+ "raw_event",
16
+ "hook_hash",
17
+ "hook_manifest",
18
+ "login",
19
+ "os_user",
20
+ "agent_product",
16
21
  ];
17
- /** Return a shallow copy of metadata with server-owned keys removed. */
22
+ /**
23
+ * The fields of the agent's own hook payload (`raw_event`) the backend reads: the hook's name, in
24
+ * each agent's spelling (it tells a Cursor event from a Claude one), the tool name (MCP calls) and
25
+ * the shell command Cursor sends outside `tool_input`. The rest of the payload (the tool's output,
26
+ * the transcript path, the agent's own copy of the input) stays on the Mac.
27
+ */
28
+ export const WIRE_RAW_EVENT_KEYS = ["hook_event_name", "hookEventName", "hook_event", "tool_name", "command"];
29
+ function pick(source, keys) {
30
+ return Object.fromEntries(keys.filter((k) => source[k] !== undefined).map((k) => [k, source[k]]));
31
+ }
32
+ function isRecord(value) {
33
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
34
+ }
35
+ /**
36
+ * Return the metadata the backend receives: only the allowlisted fields, with the content
37
+ * scrubbed. Secrets in `tool_input`, `raw_event` and the prompt are redacted to typed
38
+ * placeholders before the event leaves the machine; emails and paths stay as they are, since the
39
+ * backend matches tool calls to people and to the folders the inventory holds. Each event carries
40
+ * the scrubber's version, so the backend can tell what the sensor already ran. Identity (`login`,
41
+ * `os_user`) is sent as it is.
42
+ */
18
43
  export function cloneToolCallMetadataForWire(meta) {
19
- if (!meta || typeof meta !== "object" || Array.isArray(meta)) {
44
+ if (!isRecord(meta)) {
20
45
  return undefined;
21
46
  }
22
- const m = { ...meta };
23
- for (const k of SERVER_OWNED_TOOL_CALL_METADATA_KEYS) {
24
- delete m[k];
25
- }
47
+ const m = pick(meta, WIRE_TOOL_CALL_METADATA_KEYS);
48
+ const content = { fingerprintKey: readFingerprintKey() };
49
+ if (m.tool_input !== undefined)
50
+ m.tool_input = scrubValue(m.tool_input, content);
51
+ if (isRecord(m.raw_event))
52
+ m.raw_event = scrubValue(pick(m.raw_event, WIRE_RAW_EVENT_KEYS), content);
53
+ else
54
+ delete m.raw_event;
55
+ if (typeof m.user_prompt === "string")
56
+ m.user_prompt = scrubText(m.user_prompt, content);
57
+ m.scrubber_version = SCRUBBER_VERSION;
26
58
  return m;
27
59
  }
28
60
  //# sourceMappingURL=wire-metadata.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wire-metadata.js","sourceRoot":"","sources":["../../../src/lib/telemetry/wire-metadata.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG;IAClD,cAAc;IACd,eAAe;IACf,aAAa;IACb,oBAAoB;IACpB,WAAW;IACX,SAAS;IACT,YAAY;IACZ,UAAU;CACF,CAAC;AAEX,wEAAwE;AACxE,MAAM,UAAU,4BAA4B,CAAC,IAAa;IACxD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,CAAC,GAAG,EAAE,GAAI,IAAgC,EAAE,CAAC;IACnD,KAAK,MAAM,CAAC,IAAI,oCAAoC,EAAE,CAAC;QACrD,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
1
+ {"version":3,"file":"wire-metadata.js","sourceRoot":"","sources":["../../../src/lib/telemetry/wire-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,WAAW;IACX,YAAY;IACZ,aAAa;IACb,kBAAkB;IAClB,WAAW;IACX,WAAW;IACX,eAAe;IACf,OAAO;IACP,SAAS;IACT,eAAe;CACP,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,iBAAiB,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,CAAU,CAAC;AAEvH,SAAS,IAAI,CAAC,MAA+B,EAAE,IAAuB;IACpE,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpG,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAa;IACxD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,CAAC;IACzD,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS;QAAE,CAAC,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACjF,IAAI,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QAAE,CAAC,CAAC,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,EAAE,OAAO,CAAC,CAAC;;QAChG,OAAO,CAAC,CAAC,SAAS,CAAC;IACxB,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ;QAAE,CAAC,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACzF,CAAC,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;IACtC,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -11,6 +11,7 @@
11
11
  * "@optimuslabs/tofu", so the conditional lives in exactly one place.
12
12
  */
13
13
  import type * as TofuTypes from "@optimuslabs/tofu";
14
+ export declare const isDevelopment: boolean;
14
15
  export declare const loadEndpointBase: typeof TofuTypes.loadEndpointBase, buildStartupEndpointUrl: typeof TofuTypes.buildStartupEndpointUrl, createSignature: typeof TofuTypes.createSignature, persistAuthKey: typeof TofuTypes.persistAuthKey, readStoredAuthKey: typeof TofuTypes.readStoredAuthKey, ensureAuthentication: typeof TofuTypes.ensureAuthentication, getEndpointSource: typeof TofuTypes.getEndpointSource, canonicalizePayload: typeof TofuTypes.canonicalizePayload, getAuthKeyPath: typeof TofuTypes.getAuthKeyPath;
15
16
  export type { EndpointResponse, StoredAuthKey } from "@optimuslabs/tofu";
16
17
  //# sourceMappingURL=tofu.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tofu.d.ts","sourceRoot":"","sources":["../../src/lib/tofu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAiCpD,eAAO,MACL,gBAAgB,qCAChB,uBAAuB,4CACvB,eAAe,oCACf,cAAc,mCACd,iBAAiB,sCACjB,oBAAoB,yCACpB,iBAAiB,sCACjB,mBAAmB,wCACnB,cAAc,iCACR,CAAC;AAET,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"tofu.d.ts","sourceRoot":"","sources":["../../src/lib/tofu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAqBpD,eAAO,MAAM,aAAa,SAAsC,CAAC;AAYjE,eAAO,MACL,gBAAgB,qCAChB,uBAAuB,4CACvB,eAAe,oCACf,cAAc,mCACd,iBAAiB,sCACjB,oBAAoB,yCACpB,iBAAiB,sCACjB,mBAAmB,wCACnB,cAAc,iCACR,CAAC;AAET,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/lib/tofu.js CHANGED
@@ -33,7 +33,7 @@ function readEnvironment() {
33
33
  return "production";
34
34
  }
35
35
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
36
- const isDevelopment = readEnvironment() === "development";
36
+ export const isDevelopment = readEnvironment() === "development";
37
37
  // In development: resolve local tofu dist relative to this file.
38
38
  // dist/lib/tofu.js → ../../.. → optimuslabs/tofu/dist/index.js
39
39
  const localTofuPath = path.join(__dirname, "../../../tofu/dist/index.js");
@@ -1 +1 @@
1
- {"version":3,"file":"tofu.js","sourceRoot":"","sources":["../../src/lib/tofu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAGpC,SAAS,eAAe;IACtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,CAAC,CAAC;IACtF,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;QAC7E,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CACzB,8DAA8D,CAC/D,CAAC;IACF,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACtE,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,aAAa,GAAG,eAAe,EAAE,KAAK,aAAa,CAAC;AAE1D,iEAAiE;AACjE,+DAA+D;AAC/D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,6BAA6B,CAAC,CAAC;AAE1E,MAAM,IAAI,GAAG,CACX,aAAa;IACX,CAAC,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC;IAC7B,CAAC,CAAC,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAClB,CAAC;AAEtB,MAAM,CAAC,MAAM,EACX,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,GACf,GAAG,IAAI,CAAC"}
1
+ {"version":3,"file":"tofu.js","sourceRoot":"","sources":["../../src/lib/tofu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAGpC,SAAS,eAAe;IACtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,CAAC,CAAC;IACtF,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;QAC7E,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CACzB,8DAA8D,CAC/D,CAAC;IACF,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACtE,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,EAAE,KAAK,aAAa,CAAC;AAEjE,iEAAiE;AACjE,+DAA+D;AAC/D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,6BAA6B,CAAC,CAAC;AAE1E,MAAM,IAAI,GAAG,CACX,aAAa;IACX,CAAC,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC;IAC7B,CAAC,CAAC,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAClB,CAAC;AAEtB,MAAM,CAAC,MAAM,EACX,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,GACf,GAAG,IAAI,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The last prompt the person typed. Read from the end, because the latest prompt is near it: the
3
+ * cost stays the same however large the transcript grows. Reading the whole file into one string
4
+ * failed outright past Node's string limit (about 512 MB) and took seconds on every tool call well
5
+ * before that.
6
+ */
7
+ export declare function readLastUserPrompt(transcriptPath: string): string | null;
8
+ /** Which product of an agent family wrote a transcript, and that product's engine version. */
9
+ export interface AgentProduct {
10
+ originator: string;
11
+ version?: string;
12
+ }
13
+ /**
14
+ * The product that wrote this Codex session (OPT-1488), from its `session_meta` line: `originator`
15
+ * is `codex-tui` (CLI), `Codex Desktop`, `codex_work_desktop` (ChatGPT Work) or `codex_vscode`, and
16
+ * `cli_version` is that product's engine. Inventory lists ChatGPT Work from it, since Work has no
17
+ * install of its own. Only the start is read, by pattern: the first line also carries Codex's
18
+ * instructions and runs to tens of KB, so it is not parsed whole. Null for any other transcript.
19
+ */
20
+ export declare function readAgentProduct(transcriptPath: string): AgentProduct | null;
21
+ /**
22
+ * The events file of a Copilot CLI or Copilot app session, where the person's prompts are kept.
23
+ * These products send no `transcript_path`, so this is where their prompt is read from.
24
+ */
25
+ export declare function copilotSessionEventsPath(sessionId: string | null | undefined, home?: string): string | null;
26
+ /**
27
+ * Which GitHub Copilot product ran the tool (OPT-1488). VS Code's Copilot Chat keeps its sessions
28
+ * in VS Code's own storage and names it in `transcript_path`. The CLI and the GitHub Copilot app
29
+ * share `~/.copilot/session-state/<session id>/`, whose `workspace.yaml` names the client:
30
+ * `github/cli` or `github/autopilot` (the app). Null when neither can be read.
31
+ */
32
+ export declare function readCopilotProduct(sessionId: string | null | undefined, transcriptPath: string | null | undefined, home?: string): AgentProduct | null;
33
+ //# sourceMappingURL=transcript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../src/lib/transcript.ts"],"names":[],"mappings":"AA0GA;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYxE;AAKD,8FAA8F;AAC9F,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAoB5E;AA+BD;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,IAAI,GAAE,MAA+B,GACpC,MAAM,GAAG,IAAI,CAGf;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,IAAI,GAAE,MAA+B,GACpC,YAAY,GAAG,IAAI,CAWrB"}
@@ -0,0 +1,217 @@
1
+ import fs from "fs";
2
+ /** Context Codex injects as "user" messages; never what the person typed. */
3
+ const CODEX_INJECTED_PREFIXES = ["# AGENTS.md instructions", "<environment_context>", "<user_instructions>"];
4
+ /** The `text` of every block of this type, joined by newlines and trimmed. */
5
+ function joinTextBlocks(blocks, type) {
6
+ return (Array.isArray(blocks) ? blocks : [])
7
+ .filter((c) => c.type === type && typeof c.text === "string")
8
+ .map((c) => c.text)
9
+ .join("\n")
10
+ .trim();
11
+ }
12
+ /** A Codex user message's text, or null for Codex's injected context (AGENTS.md, <environment_context>). */
13
+ function codexPrompt(payload) {
14
+ const text = joinTextBlocks(payload.content, "input_text");
15
+ return text && !CODEX_INJECTED_PREFIXES.some((prefix) => text.startsWith(prefix)) ? text : null;
16
+ }
17
+ /** A Claude user message's text, or null for an empty one or a tool_result turn. */
18
+ function claudePrompt(msg) {
19
+ const content = msg.content;
20
+ if (typeof content === "string")
21
+ return content.trim() || null;
22
+ if (!Array.isArray(content))
23
+ return null;
24
+ const blocks = content;
25
+ // Skip tool_result turns — those are API feedback, not user-typed messages
26
+ if (blocks.some((c) => c.type === "tool_result"))
27
+ return null;
28
+ return joinTextBlocks(blocks, "text") || null;
29
+ }
30
+ /** What the person typed in this transcript entry, or null when it is not a typed user message. */
31
+ function promptFromEntry(entry) {
32
+ // Codex rollout: {"type":"response_item","payload":{"type":"message","role":"user",
33
+ // "content":[{"type":"input_text","text":...}]}}.
34
+ const payload = entry.payload;
35
+ if (entry.type === "response_item" && payload?.type === "message" && payload.role === "user") {
36
+ return codexPrompt(payload);
37
+ }
38
+ // Copilot CLI and Copilot app session events: {"type":"user.message","data":{"content":...}}.
39
+ if (entry.type === "user.message") {
40
+ const content = entry.data?.content;
41
+ return typeof content === "string" ? content.trim() || null : null;
42
+ }
43
+ const msg = entry.message;
44
+ if (entry.type !== "user" || !msg || msg.role !== "user")
45
+ return null;
46
+ return claudePrompt(msg);
47
+ }
48
+ function promptFromLine(line) {
49
+ try {
50
+ return promptFromEntry(JSON.parse(line));
51
+ }
52
+ catch {
53
+ // skip malformed lines
54
+ return null;
55
+ }
56
+ }
57
+ /** Bytes read from the end of a transcript at a time. */
58
+ const TAIL_CHUNK_BYTES = 2 * 1024 * 1024;
59
+ const NEWLINE = 0x0a;
60
+ /** The prompt on this JSONL line, if it is one the person typed. */
61
+ function promptFromBytes(bytes) {
62
+ const line = bytes.toString("utf-8").trim();
63
+ return line ? promptFromLine(line) : null;
64
+ }
65
+ /** Where the last newline before `end` is in `chunk`, or -1. */
66
+ function lastNewline(chunk, end) {
67
+ return end > 0 ? chunk.lastIndexOf(NEWLINE, end - 1) : -1;
68
+ }
69
+ /**
70
+ * The transcript's lines, last first, read backwards a chunk at a time. Lines are split on newline
71
+ * bytes, which never occur inside a multi-byte character, so a character is never cut.
72
+ */
73
+ function* linesFromEnd(fd) {
74
+ let position = fs.fstatSync(fd).size;
75
+ // The end of the line being read, whose start is further back in the file.
76
+ let tail = [];
77
+ while (position > 0) {
78
+ const length = Math.min(TAIL_CHUNK_BYTES, position);
79
+ position -= length;
80
+ const chunk = Buffer.alloc(length);
81
+ let end = fs.readSync(fd, chunk, 0, length, position);
82
+ for (let newline = lastNewline(chunk, end); newline >= 0; newline = lastNewline(chunk, end)) {
83
+ yield Buffer.concat([chunk.subarray(newline + 1, end), ...tail]);
84
+ tail = [];
85
+ end = newline;
86
+ }
87
+ tail.unshift(chunk.subarray(0, end));
88
+ }
89
+ yield Buffer.concat(tail);
90
+ }
91
+ /** The first line from the end that the person typed. */
92
+ function lastPromptIn(fd) {
93
+ for (const line of linesFromEnd(fd)) {
94
+ const prompt = promptFromBytes(line);
95
+ if (prompt)
96
+ return prompt;
97
+ }
98
+ return null;
99
+ }
100
+ /**
101
+ * The last prompt the person typed. Read from the end, because the latest prompt is near it: the
102
+ * cost stays the same however large the transcript grows. Reading the whole file into one string
103
+ * failed outright past Node's string limit (about 512 MB) and took seconds on every tool call well
104
+ * before that.
105
+ */
106
+ export function readLastUserPrompt(transcriptPath) {
107
+ let fd;
108
+ try {
109
+ fd = fs.openSync(transcriptPath, "r");
110
+ return lastPromptIn(fd);
111
+ }
112
+ catch (error) {
113
+ // A missing or unreadable transcript is non-fatal: the tool call goes out without a prompt.
114
+ if (process.env.OPTIMUS_DEBUG)
115
+ console.error("[optimus-tool-call] Could not read the transcript:", error);
116
+ return null;
117
+ }
118
+ finally {
119
+ if (fd !== undefined)
120
+ fs.closeSync(fd);
121
+ }
122
+ }
123
+ /** Bytes read from the start of a Codex session file, where its session metadata sits. */
124
+ const SESSION_HEAD_BYTES = 8 * 1024;
125
+ /**
126
+ * The product that wrote this Codex session (OPT-1488), from its `session_meta` line: `originator`
127
+ * is `codex-tui` (CLI), `Codex Desktop`, `codex_work_desktop` (ChatGPT Work) or `codex_vscode`, and
128
+ * `cli_version` is that product's engine. Inventory lists ChatGPT Work from it, since Work has no
129
+ * install of its own. Only the start is read, by pattern: the first line also carries Codex's
130
+ * instructions and runs to tens of KB, so it is not parsed whole. Null for any other transcript.
131
+ */
132
+ export function readAgentProduct(transcriptPath) {
133
+ let fd;
134
+ try {
135
+ fd = fs.openSync(transcriptPath, "r");
136
+ const head = Buffer.alloc(SESSION_HEAD_BYTES);
137
+ const read = fs.readSync(fd, head, 0, SESSION_HEAD_BYTES, 0);
138
+ const text = head.subarray(0, read).toString("utf8");
139
+ const firstLine = text.split("\n", 1)[0];
140
+ if (!/"type"\s*:\s*"session_meta"/.test(firstLine))
141
+ return null;
142
+ const originator = firstLine.match(/"originator"\s*:\s*"([^"\\]{1,100})"/)?.[1];
143
+ if (!originator)
144
+ return null;
145
+ const version = firstLine.match(/"cli_version"\s*:\s*"([^"\\]{1,100})"/)?.[1];
146
+ return version ? { originator, version } : { originator };
147
+ }
148
+ catch (error) {
149
+ // A missing or unreadable transcript is non-fatal: the tool call goes out without a product.
150
+ if (process.env.OPTIMUS_DEBUG)
151
+ console.error("[optimus-tool-call] Could not read the session head:", error);
152
+ return null;
153
+ }
154
+ finally {
155
+ if (fd !== undefined)
156
+ fs.closeSync(fd);
157
+ }
158
+ }
159
+ /** A Copilot product's first event and settings files, read from the start only. */
160
+ const COPILOT_HEAD_BYTES = 8 * 1024;
161
+ function readFileHead(filePath) {
162
+ let fd;
163
+ try {
164
+ fd = fs.openSync(filePath, "r");
165
+ const head = Buffer.alloc(COPILOT_HEAD_BYTES);
166
+ return head.subarray(0, fs.readSync(fd, head, 0, COPILOT_HEAD_BYTES, 0)).toString("utf8");
167
+ }
168
+ catch (error) {
169
+ // A missing or unreadable file is non-fatal: the tool call goes out without a product.
170
+ if (process.env.OPTIMUS_DEBUG)
171
+ console.error("[optimus-tool-call] Could not read the Copilot session:", error);
172
+ return "";
173
+ }
174
+ finally {
175
+ if (fd !== undefined)
176
+ fs.closeSync(fd);
177
+ }
178
+ }
179
+ /** `copilotVersion` from a Copilot session's first event (`session.start`). */
180
+ function copilotVersion(eventsPath) {
181
+ return readFileHead(eventsPath).match(/"copilotVersion"\s*:\s*"([^"\\]{1,100})"/)?.[1];
182
+ }
183
+ /** `~/.copilot/session-state/<session id>`, shared by the CLI and the Copilot app, or null for an id that is not one. */
184
+ function copilotSessionDir(sessionId, home) {
185
+ if (!sessionId || !/^[A-Za-z0-9-]{8,64}$/.test(sessionId) || !home)
186
+ return null;
187
+ return `${home}/.copilot/session-state/${sessionId}`;
188
+ }
189
+ /**
190
+ * The events file of a Copilot CLI or Copilot app session, where the person's prompts are kept.
191
+ * These products send no `transcript_path`, so this is where their prompt is read from.
192
+ */
193
+ export function copilotSessionEventsPath(sessionId, home = process.env.HOME || "") {
194
+ const sessionDir = copilotSessionDir(sessionId, home);
195
+ return sessionDir ? `${sessionDir}/events.jsonl` : null;
196
+ }
197
+ /**
198
+ * Which GitHub Copilot product ran the tool (OPT-1488). VS Code's Copilot Chat keeps its sessions
199
+ * in VS Code's own storage and names it in `transcript_path`. The CLI and the GitHub Copilot app
200
+ * share `~/.copilot/session-state/<session id>/`, whose `workspace.yaml` names the client:
201
+ * `github/cli` or `github/autopilot` (the app). Null when neither can be read.
202
+ */
203
+ export function readCopilotProduct(sessionId, transcriptPath, home = process.env.HOME || "") {
204
+ if (typeof transcriptPath === "string" && transcriptPath.includes("/GitHub.copilot-chat/")) {
205
+ const version = copilotVersion(transcriptPath);
206
+ return version ? { originator: "vscode", version } : { originator: "vscode" };
207
+ }
208
+ const sessionDir = copilotSessionDir(sessionId, home);
209
+ if (!sessionDir)
210
+ return null;
211
+ const originator = readFileHead(`${sessionDir}/workspace.yaml`).match(/^client_name:\s*(\S{1,100})\s*$/m)?.[1];
212
+ if (!originator)
213
+ return null;
214
+ const version = copilotVersion(`${sessionDir}/events.jsonl`);
215
+ return version ? { originator, version } : { originator };
216
+ }
217
+ //# sourceMappingURL=transcript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.js","sourceRoot":"","sources":["../../src/lib/transcript.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,9 @@ beforeEach(() => {
9
9
  CLAUDE_CODE_SESSION_ID: process.env.CLAUDE_CODE_SESSION_ID,
10
10
  CURSOR_SESSION_ID: process.env.CURSOR_SESSION_ID,
11
11
  CURSOR: process.env.CURSOR,
12
+ OPTIMUS_AGENT: process.env.OPTIMUS_AGENT,
12
13
  };
14
+ delete process.env.OPTIMUS_AGENT;
13
15
  delete process.env.CLAUDE_CODE_SESSION_ID;
14
16
  delete process.env.CURSOR_SESSION_ID;
15
17
  delete process.env.CURSOR;
@@ -136,4 +138,42 @@ test("normalizeToCanonical - Handles missing fields gracefully", () => {
136
138
  assert.strictEqual(canonical.session_id, null);
137
139
  assert.strictEqual(canonical.user_prompt, null);
138
140
  });
141
+ test("normalizeToCanonical - Copilot PreToolUse is Copilot, though shaped like Claude's", () => {
142
+ process.env.OPTIMUS_AGENT = "copilot";
143
+ process.env.CLAUDE_CODE_SESSION_ID = "inherited";
144
+ // As the Copilot CLI sends it under the PreToolUse key (OPT-1488).
145
+ const raw = {
146
+ hook_event_name: "PreToolUse",
147
+ session_id: "a4825a9b-e723-47a9-a07d-8a3cf1bf77f3",
148
+ timestamp: "2026-11-03T17:46:00.131Z",
149
+ cwd: "/repo",
150
+ tool_name: "Bash",
151
+ tool_input: { command: "echo CAPTURE-CLI", description: "Echo CAPTURE-CLI" },
152
+ };
153
+ const canonical = normalizeToCanonical(raw);
154
+ assert.strictEqual(canonical.agent, "copilot");
155
+ assert.strictEqual(canonical.tool_name, "Bash");
156
+ assert.strictEqual(canonical.tool_input.command, "echo CAPTURE-CLI");
157
+ assert.strictEqual(canonical.session_id, "a4825a9b-e723-47a9-a07d-8a3cf1bf77f3");
158
+ });
159
+ test("normalizeToCanonical - Codex PreToolUse is Codex, though shaped like Claude's", () => {
160
+ process.env.OPTIMUS_AGENT = "codex";
161
+ // Codex started from a Claude Code terminal inherits this; it must not win.
162
+ process.env.CLAUDE_CODE_SESSION_ID = "inherited";
163
+ const raw = {
164
+ hook_event_name: "PreToolUse",
165
+ tool_name: "Bash",
166
+ tool_use_id: "call_1",
167
+ turn_id: "turn_1",
168
+ tool_input: { command: "rm -rf build" },
169
+ session_id: "codex-session-1",
170
+ cwd: "/repo",
171
+ };
172
+ const canonical = normalizeToCanonical(raw);
173
+ assert.strictEqual(canonical.agent, "codex");
174
+ assert.strictEqual(canonical.hook_event_name, "PreToolUse");
175
+ assert.strictEqual(canonical.tool_name, "Bash");
176
+ assert.deepStrictEqual(canonical.tool_input, { command: "rm -rf build" });
177
+ assert.strictEqual(canonical.tool_use_id, "call_1");
178
+ });
139
179
  //# sourceMappingURL=canonical.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"canonical.test.js","sourceRoot":"","sources":["../../src/test/canonical.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canonical.test.js","sourceRoot":"","sources":["../../src/test/canonical.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client-event-scrub.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-event-scrub.test.d.ts","sourceRoot":"","sources":["../../src/test/client-event-scrub.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert";
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { reportToolCallRun } from "../lib/client-event.js";
7
+ test("reportToolCallRun - the run record's command and log are scrubbed, with the scrubber version", async () => {
8
+ const token = `ghp_${"C".repeat(36)}`;
9
+ const saved = { home: process.env.HOME, uuid: process.env.OPTIMUS_HARDWARE_UUID, fetch: globalThis.fetch };
10
+ process.env.HOME = fs.mkdtempSync(path.join(os.tmpdir(), "client-event-"));
11
+ process.env.OPTIMUS_HARDWARE_UUID = "hw-client-event-test";
12
+ let sent;
13
+ globalThis.fetch = (async (_url, init) => {
14
+ sent = JSON.parse(String(init?.body));
15
+ return new Response("{}");
16
+ });
17
+ try {
18
+ await reportToolCallRun({
19
+ outcome: "failed",
20
+ command: `GH_TOKEN=${token} npx optimus-tool-call`,
21
+ message: "npx exited 1",
22
+ detail: `export GITHUB_TOKEN=${token}\nreported to ada@gmail.com`,
23
+ });
24
+ }
25
+ finally {
26
+ process.env.HOME = saved.home;
27
+ process.env.OPTIMUS_HARDWARE_UUID = saved.uuid;
28
+ globalThis.fetch = saved.fetch;
29
+ }
30
+ const event = sent?.events[0] ?? {};
31
+ assert.strictEqual(event.command, "GH_TOKEN=ghp_[OL_REDACTED:GITHUB_TOKEN] npx optimus-tool-call");
32
+ assert.strictEqual(event.detail, "export GITHUB_TOKEN=ghp_[OL_REDACTED:GITHUB_TOKEN]\nreported to ada@gmail.com");
33
+ assert.match(String(event.metadata.scrubber_version), /^\d+\.\d+\.\d+$/);
34
+ assert.ok(!JSON.stringify(sent).includes(token));
35
+ });
36
+ //# sourceMappingURL=client-event-scrub.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-event-scrub.test.js","sourceRoot":"","sources":["../../src/test/client-event-scrub.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,IAAI,CAAC,8FAA8F,EAAE,KAAK,IAAI,EAAE;IAC9G,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,CAAC;IAC3G,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,sBAAsB,CAAC;IAC3D,IAAI,IAAuD,CAAC;IAC5D,UAAU,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,IAAa,EAAE,IAAyB,EAAE,EAAE;QACrE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAiB,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,iBAAiB,CAAC;YACtB,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE,YAAY,KAAK,wBAAwB;YAClD,OAAO,EAAE,cAAc;YACvB,MAAM,EAAE,uBAAuB,KAAK,6BAA6B;SAClE,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,KAAK,CAAC,IAAI,CAAC;QAC/C,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACjC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,+DAA+D,CAAC,CAAC;IACnG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,+EAA+E,CAAC,CAAC;IAClH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAE,KAAK,CAAC,QAAmC,CAAC,gBAAgB,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACrG,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=login.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.test.d.ts","sourceRoot":"","sources":["../../src/test/login.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ import { test, beforeEach, afterEach } from "node:test";
2
+ import assert from "node:assert";
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { readLogin } from "../lib/login.js";
7
+ import { buildTelemetryEvent } from "../lib/telemetry/build-event.js";
8
+ let home = "";
9
+ const saved = {};
10
+ beforeEach(() => {
11
+ home = fs.mkdtempSync(path.join(os.tmpdir(), "optimus-login-"));
12
+ saved.HOME = process.env.HOME;
13
+ saved.CLAUDE_CONFIG_DIR = process.env.CLAUDE_CONFIG_DIR;
14
+ process.env.HOME = home;
15
+ delete process.env.CLAUDE_CONFIG_DIR;
16
+ });
17
+ afterEach(() => {
18
+ for (const [k, v] of Object.entries(saved)) {
19
+ if (v === undefined)
20
+ delete process.env[k];
21
+ else
22
+ process.env[k] = v;
23
+ }
24
+ fs.rmSync(home, { recursive: true, force: true });
25
+ });
26
+ const writeClaude = (account) => fs.writeFileSync(path.join(home, ".claude.json"), JSON.stringify({ oauthAccount: account }));
27
+ test("reads Claude's tenant and email", () => {
28
+ writeClaude({ organizationUuid: "org-1", organizationName: "Acme", emailAddress: "ada@acme.com" });
29
+ assert.deepStrictEqual(readLogin("claude"), {
30
+ tenant_id: "org-1",
31
+ tenant_name: "Acme",
32
+ email: "ada@acme.com",
33
+ });
34
+ });
35
+ test("leaves out what the agent does not say", () => {
36
+ writeClaude({ emailAddress: "ada@acme.com" });
37
+ assert.deepStrictEqual(readLogin("claude"), { email: "ada@acme.com" });
38
+ });
39
+ test("reads Codex's ChatGPT workspace and email from the ID token, never the token itself", () => {
40
+ const claims = { email: "ada@acme.com", "https://api.openai.com/auth": { chatgpt_account_id: "ws-1" } };
41
+ const idToken = `x.${Buffer.from(JSON.stringify(claims)).toString("base64url")}.sig`;
42
+ fs.mkdirSync(path.join(home, ".codex"));
43
+ fs.writeFileSync(path.join(home, ".codex", "auth.json"), JSON.stringify({ tokens: { id_token: idToken } }));
44
+ const login = readLogin("codex");
45
+ assert.deepStrictEqual(login, { tenant_id: "ws-1", email: "ada@acme.com" });
46
+ assert.ok(!JSON.stringify(login).includes("sig"));
47
+ });
48
+ test("is null with no login, or for an agent it cannot read", () => {
49
+ assert.strictEqual(readLogin("claude"), null);
50
+ assert.strictEqual(readLogin("opencode"), null);
51
+ });
52
+ test("every tool-call event carries the login in its metadata", () => {
53
+ writeClaude({ organizationUuid: "org-1", emailAddress: "ada@acme.com" });
54
+ const event = buildTelemetryEvent({ tool_name: "Bash", tool_input: {} }, "claude", "s1");
55
+ assert.deepStrictEqual((event?.tool_call_metadata).login, {
56
+ tenant_id: "org-1",
57
+ email: "ada@acme.com",
58
+ });
59
+ });
60
+ //# sourceMappingURL=login.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.test.js","sourceRoot":"","sources":["../../src/test/login.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=org-fingerprint-key.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-fingerprint-key.test.d.ts","sourceRoot":"","sources":["../../src/test/org-fingerprint-key.test.ts"],"names":[],"mappings":""}