@sapiom/harness 0.1.1 → 0.1.2

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 (135) hide show
  1. package/CHANGELOG.md +162 -0
  2. package/README.md +36 -0
  3. package/dist/cli/bin.js +26 -2
  4. package/dist/cli/bin.js.map +1 -1
  5. package/dist/cli/consent.d.ts +29 -1
  6. package/dist/cli/consent.d.ts.map +1 -1
  7. package/dist/cli/consent.js +33 -11
  8. package/dist/cli/consent.js.map +1 -1
  9. package/dist/core/adapters/adapter.d.ts +72 -0
  10. package/dist/core/adapters/adapter.d.ts.map +1 -0
  11. package/dist/core/adapters/adapter.js +18 -0
  12. package/dist/core/adapters/adapter.js.map +1 -0
  13. package/dist/core/adapters/claude-code-info.d.ts +11 -0
  14. package/dist/core/adapters/claude-code-info.d.ts.map +1 -0
  15. package/dist/core/adapters/claude-code-info.js +27 -0
  16. package/dist/core/adapters/claude-code-info.js.map +1 -0
  17. package/dist/core/adapters/claude-code.d.ts.map +1 -1
  18. package/dist/core/adapters/claude-code.js +9 -8
  19. package/dist/core/adapters/claude-code.js.map +1 -1
  20. package/dist/core/adapters/codex-info.d.ts +10 -0
  21. package/dist/core/adapters/codex-info.d.ts.map +1 -0
  22. package/dist/core/adapters/codex-info.js +32 -0
  23. package/dist/core/adapters/codex-info.js.map +1 -0
  24. package/dist/core/adapters/conductor.d.ts +8 -0
  25. package/dist/core/adapters/conductor.d.ts.map +1 -0
  26. package/dist/core/adapters/conductor.js +57 -0
  27. package/dist/core/adapters/conductor.js.map +1 -0
  28. package/dist/core/adapters/detect.d.ts +15 -0
  29. package/dist/core/adapters/detect.d.ts.map +1 -0
  30. package/dist/core/adapters/detect.js +62 -0
  31. package/dist/core/adapters/detect.js.map +1 -0
  32. package/dist/core/adapters/opencode.d.ts +8 -0
  33. package/dist/core/adapters/opencode.d.ts.map +1 -0
  34. package/dist/core/adapters/opencode.js +35 -0
  35. package/dist/core/adapters/opencode.js.map +1 -0
  36. package/dist/core/adapters/pi.d.ts +8 -0
  37. package/dist/core/adapters/pi.d.ts.map +1 -0
  38. package/dist/core/adapters/pi.js +24 -0
  39. package/dist/core/adapters/pi.js.map +1 -0
  40. package/dist/core/adapters/registry.d.ts +42 -0
  41. package/dist/core/adapters/registry.d.ts.map +1 -0
  42. package/dist/core/adapters/registry.js +67 -0
  43. package/dist/core/adapters/registry.js.map +1 -0
  44. package/dist/core/canvas-enrich.d.ts +9 -0
  45. package/dist/core/canvas-enrich.d.ts.map +1 -1
  46. package/dist/core/canvas-enrich.js +8 -0
  47. package/dist/core/canvas-enrich.js.map +1 -1
  48. package/dist/core/collector/analytics-emitter.d.ts +57 -0
  49. package/dist/core/collector/analytics-emitter.d.ts.map +1 -0
  50. package/dist/core/collector/analytics-emitter.js +131 -0
  51. package/dist/core/collector/analytics-emitter.js.map +1 -0
  52. package/dist/core/collector/identity-migration.d.ts +25 -0
  53. package/dist/core/collector/identity-migration.d.ts.map +1 -0
  54. package/dist/core/collector/identity-migration.js +68 -0
  55. package/dist/core/collector/identity-migration.js.map +1 -0
  56. package/dist/core/collector/store-retention.d.ts +51 -0
  57. package/dist/core/collector/store-retention.d.ts.map +1 -0
  58. package/dist/core/collector/store-retention.js +117 -0
  59. package/dist/core/collector/store-retention.js.map +1 -0
  60. package/dist/core/collector/store.d.ts +17 -1
  61. package/dist/core/collector/store.d.ts.map +1 -1
  62. package/dist/core/collector/store.js +24 -3
  63. package/dist/core/collector/store.js.map +1 -1
  64. package/dist/core/errors.d.ts +71 -0
  65. package/dist/core/errors.d.ts.map +1 -0
  66. package/dist/core/errors.js +86 -0
  67. package/dist/core/errors.js.map +1 -0
  68. package/dist/core/inject/claude-settings.d.ts +3 -1
  69. package/dist/core/inject/claude-settings.d.ts.map +1 -1
  70. package/dist/core/inject/claude-settings.js +3 -1
  71. package/dist/core/inject/claude-settings.js.map +1 -1
  72. package/dist/core/inject/skills-plugin.d.ts +44 -0
  73. package/dist/core/inject/skills-plugin.d.ts.map +1 -0
  74. package/dist/core/inject/skills-plugin.js +146 -0
  75. package/dist/core/inject/skills-plugin.js.map +1 -0
  76. package/dist/core/macro-runner.d.ts.map +1 -1
  77. package/dist/core/macro-runner.js +20 -1
  78. package/dist/core/macro-runner.js.map +1 -1
  79. package/dist/core/macros.d.ts.map +1 -1
  80. package/dist/core/macros.js +3 -0
  81. package/dist/core/macros.js.map +1 -1
  82. package/dist/core/session-manager.d.ts +37 -18
  83. package/dist/core/session-manager.d.ts.map +1 -1
  84. package/dist/core/session-manager.js +85 -34
  85. package/dist/core/session-manager.js.map +1 -1
  86. package/dist/core/task-manager.d.ts +25 -4
  87. package/dist/core/task-manager.d.ts.map +1 -1
  88. package/dist/core/task-manager.js +118 -6
  89. package/dist/core/task-manager.js.map +1 -1
  90. package/dist/core/workflow-registry.d.ts +7 -0
  91. package/dist/core/workflow-registry.d.ts.map +1 -1
  92. package/dist/core/workflow-registry.js +74 -50
  93. package/dist/core/workflow-registry.js.map +1 -1
  94. package/dist/core/workspace-watcher.d.ts +13 -1
  95. package/dist/core/workspace-watcher.d.ts.map +1 -1
  96. package/dist/core/workspace-watcher.js +78 -4
  97. package/dist/core/workspace-watcher.js.map +1 -1
  98. package/dist/index.d.ts +3 -0
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +2 -0
  101. package/dist/index.js.map +1 -1
  102. package/dist/server/index.d.ts +16 -1
  103. package/dist/server/index.d.ts.map +1 -1
  104. package/dist/server/index.js +0 -0
  105. package/dist/server/index.js.map +1 -1
  106. package/dist/server/ingest.d.ts +8 -0
  107. package/dist/server/ingest.d.ts.map +1 -1
  108. package/dist/server/ingest.js +4 -0
  109. package/dist/server/ingest.js.map +1 -1
  110. package/dist/server/macros.d.ts +5 -2
  111. package/dist/server/macros.d.ts.map +1 -1
  112. package/dist/server/macros.js +5 -2
  113. package/dist/server/macros.js.map +1 -1
  114. package/dist/server/rest.d.ts +26 -1
  115. package/dist/server/rest.d.ts.map +1 -1
  116. package/dist/server/rest.js +139 -6
  117. package/dist/server/rest.js.map +1 -1
  118. package/dist/server/skills.d.ts +45 -0
  119. package/dist/server/skills.d.ts.map +1 -0
  120. package/dist/server/skills.js +286 -0
  121. package/dist/server/skills.js.map +1 -0
  122. package/dist/shared/types.d.ts +75 -2
  123. package/dist/shared/types.d.ts.map +1 -1
  124. package/dist/shared/types.js +12 -1
  125. package/dist/shared/types.js.map +1 -1
  126. package/dist/web/assets/index-BTm-QNRt.css +32 -0
  127. package/dist/web/assets/index-CvNiFngP.js +204 -0
  128. package/dist/web/index.html +2 -2
  129. package/package.json +19 -7
  130. package/dist/core/collector/batcher.d.ts +0 -57
  131. package/dist/core/collector/batcher.d.ts.map +0 -1
  132. package/dist/core/collector/batcher.js +0 -143
  133. package/dist/core/collector/batcher.js.map +0 -1
  134. package/dist/web/assets/index-B9R4TzH7.css +0 -32
  135. package/dist/web/assets/index-Dh97QAgq.js +0 -192
package/CHANGELOG.md ADDED
@@ -0,0 +1,162 @@
1
+ # @sapiom/harness
2
+
3
+ ## 0.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 0cc7cd5: Fix two canvas v0 bugs:
8
+
9
+ **UI (CanvasPane)**: While an enrichment task runs, the activity strip now overlays the iframe instead of replacing it. The deterministic SVG render is visible immediately after binding; the spinner appears on top during the LLM annotation pass and disappears on completion. Failure state (Retry/Dismiss) remains full-screen and is unchanged.
10
+
11
+ **Server (forceRefresh)**: The already-running check for a workflow's enrichment task is now performed before any cache invalidation or re-render. A double-clicked Visualize correctly rejects with a 409 and leaves the enrichment cache and render files exactly as the still-running task will need them.
12
+
13
+ - a318f0b: HarnessAdapter registry with embedded/external modes
14
+
15
+ - Introduces `HarnessAdapterInfo` union type (`EmbeddedHarnessAdapterInfo` | `ExternalHarnessAdapterInfo`) with a `mode` field distinguishing harnesses spawned by the harness server from companion-app harnesses that own their own sessions.
16
+ - Adds a data-driven registry (`createHarnessAdapterRegistry`, `listHarnessAdapters`, `getHarnessAdapter`) backed by five built-in adapters: claude-code, codex (both embedded), pi, opencode (embedded, experimental), and conductor (external).
17
+ - Each adapter entry carries an `installMcpPrompt()` method with per-harness MCP install guidance — the skills-panel Install MCP modal reads these from the registry rather than embedding its own copy.
18
+ - Adds `GET /api/harnesses` endpoint returning all adapters with `id`, `label`, `mode`, `experimental`, and `installed` fields. Embedded entries are session-createable today; external entries expose `mode:"external"` for future UI rendering.
19
+ - Adds `ExternalHarnessError` (code `HARNESS_EXTERNAL`, HTTP 409) thrown from `SessionManager.getAdapter()` (resume path) and `SessionManager.submitInput()` (input path) when a session's harness id resolves to an external-mode adapter. A `sessions.json` entry written by an earlier build, hand-edited, or imported with `harness="conductor"` now surfaces a clear "managed by the Conductor app" 409 instead of a generic adapter-not-found error or a silent 404.
20
+ - Exports `SPAWNABLE_HARNESS_KINDS` as a const tuple from `shared/types.ts` — the single source of truth that both derives the `HarnessKind` type and supplies the values to `z.enum()` in the session-creation schema, preventing drift between the two.
21
+ - Routes the codex-tailer branching in server/index.ts through `adapter.eventSource` instead of a hardcoded `session.harness !== "codex"` check.
22
+ - `UnknownHarnessAdapterError` (code `UNKNOWN_HARNESS_ADAPTER`) is thrown by registry lookups for unknown ids, listing known ids in the message for self-correction.
23
+ - claude-code and codex behavior is byte-identical — no changes to their existing runtime adapter implementations (launch/resume/doctor/listPastSessions).
24
+
25
+ - c8c4746: Remote telemetry now reaches the hosted collector.
26
+
27
+ The bespoke `CollectorBatcher` (which posted to a non-existent `/v1/harness/events` endpoint) has been replaced by `@sapiom/analytics-core`. Events are now delivered to `POST /v1/analytics/collector` — the same endpoint used by all other Sapiom SDK packages.
28
+
29
+ **What changes for users:**
30
+ - Remote telemetry (consent-gated, as before) now actually works. Previously all remote traffic was silently dropped because the target endpoint did not exist.
31
+ - The local `~/.sapiom/harness/events.ndjson` sink continues to be written on every event regardless of consent, unchanged.
32
+ - Consent behavior (stored settings toggle, `--no-telemetry` flag, `SAPIOM_TELEMETRY_DISABLED=1`, `DO_NOT_TRACK=1`) is unchanged.
33
+ - Anonymous identity migrates: on first boot after upgrade, the install's existing `~/.sapiom/harness/machine-id` value is seeded into `~/.sapiom/analytics.json` so the longitudinal join key survives across versions.
34
+
35
+ - 97e8259: Awaitable kill for harness sessions and tasks with liveness-fallback resolution.
36
+
37
+ `SessionManager.kill()` now returns `Promise<boolean>` that resolves once the
38
+ process is **actually gone** — not fire-and-forget. Existing callers that do not
39
+ await the return value keep working unchanged.
40
+
41
+ Resolution is driven by whichever path fires first: node-pty's real `onExit`
42
+ event, or a synthesized exit from `kill()`'s own escalation path. The escalation
43
+ path is genuinely bounded:
44
+
45
+ 1. SIGTERM sent immediately.
46
+ 2. After `KILL_ESCALATION_MS` (2000 ms): if still alive, send SIGKILL.
47
+ 3. After a further `KILL_ESCALATION_CONFIRM_MS` (500 ms): `markExited()` is
48
+ called **unconditionally** — SIGKILL has been sent and the window has
49
+ elapsed, so the session is over regardless of any liveness probe. This
50
+ prevents an EPERM zombie (a process that `isPidAlive` still reports as alive
51
+ after SIGKILL) from leaving the promise pending forever.
52
+
53
+ `SessionManager.killAll()` is now `async` and resolves when all concurrent kills
54
+ have confirmed death via `markExited()` — the single convergence point for real
55
+ and synthesized exits alike.
56
+
57
+ `TaskManager.killAll()` gains the same awaitable treatment with SIGTERM→SIGKILL
58
+ escalation and per-task exit promises wired through the existing `finish()`
59
+ convergence point. After the SIGKILL confirm window, `finish(id, null)` is
60
+ synthesized for any still-registered process — a zombie that never emits an exit
61
+ event is declared dead rather than leaving `killAll()` pending forever.
62
+ `finish()`'s idempotence guard prevents a double-fire if the real exit event
63
+ arrives concurrently.
64
+
65
+ Server shutdown (`close()` in server/index.ts) now awaits both `killAll()` calls
66
+ with a 5-second outer timeout, so the process actually exits cleanly instead of
67
+ leaving orphaned agent children.
68
+
69
+ - 1ff8d3c: Document that the harness is also launchable via `sapiom dev [dir]` from `@sapiom/cli`.
70
+ - 6d7ccd8: Packaging polish: LICENSE file, explicit exports map, and pack-contents audit.
71
+
72
+ Adds a per-package LICENSE file (MIT, matching repo root) so published tarballs include it. Adds an explicit `exports` map with a main entry (`"."`) and `"./package.json"` sub-path — the latter is required by `@sapiom/cli`'s `createRequire().resolve('@sapiom/harness/package.json')` resolution path; without it a conditional-exports package would fire `ERR_PACKAGE_PATH_NOT_EXPORTED` and break `sapiom dev`. Updates `files` to include `LICENSE`, `CHANGELOG.md`, and `README.md` alongside `dist`. Excludes `src/test-setup.ts` from the build tsconfig so `dist/test-setup.*` no longer appears in the published tarball. Stays ESM-only (`"type": "module"`) — the harness is an app-style bin package, not a library; a dual CJS+ESM build would introduce the dual-package hazard for the typed error hierarchy (`instanceof` dispatch) with no user benefit.
73
+
74
+ - e0334ca: Terminal-only center pane for v0
75
+
76
+ The center pane renders the xterm terminal as the sole content when a session
77
+ is live, and the exited-session overlay (resume / close) when the session has
78
+ exited. The first-run welcome panel continues to appear when no session exists
79
+ on a fresh install.
80
+
81
+ - Analytics hook pipeline (SessionStart / UserPromptSubmit / PreToolUse /
82
+ PostToolUse / Stop / SessionEnd → /ingest → normalizer → store + emitter →
83
+ collector) is fully intact and independent of the center-pane shape
84
+ - Skills panel, canvas, consent chip, telemetry, adapter registry, session
85
+ kill/resume, and typed errors are all preserved
86
+
87
+ - 6c64501: Internal robustness fixes (no behavior change for users):
88
+
89
+ - Serialize WorkflowRegistry writes through a promise queue so concurrent prune/scan/connectPath calls can't interleave and drop entries from workflows.json.
90
+ - Thread the resolved workflow path from the macros router into background task requests so TaskManager can dedupe per-workflow across sessions, not just per-session.
91
+ - Make the workspace-watcher polling fallback walk async (fs/promises) to avoid blocking the event loop on wide directories; lengthen the poll interval to 2 s.
92
+
93
+ - 58ec57f: Fix Sapiom skill registration in harness sessions. `@sapiom/agent-core` now
94
+ exposes its `package.json` through the `exports` map so consumers can resolve
95
+ its bundled `skills/` directory; previously `require.resolve` threw
96
+ `ERR_PACKAGE_PATH_NOT_EXPORTED` and the skill silently never loaded. The harness
97
+ skill-plugin resolver also gains a fallback that locates the skills directory by
98
+ resolving the package's main entry when the `package.json` subpath isn't
99
+ exported. Skills register under the `sapiom` plugin namespace, so the
100
+ agent-authoring skill is available as `/sapiom:sapiom-agent-authoring`.
101
+ - 1b355a4: Typed error codes on session and spawn failures; HTTP status mappings unchanged.
102
+
103
+ Adds a `HarnessError` base class and five typed subclasses — `UnknownSessionError`, `SessionNotReadyError`, `SessionNotResumeableError`, `SessionAlreadyLiveError`, `AdapterNotFoundError` — each carrying a stable machine-readable `code` property. Server routes now dispatch on `instanceof` rather than parsing `error.message` text, so future message rewordings cannot silently alter the HTTP status they produce. Wire responses and response body shapes are unchanged.
104
+
105
+ - a686143: Skills panel Use button populates the terminal (no auto-submit); Sapiom skills registered as session slash commands via --plugin-dir.
106
+
107
+ - Re-adds the "Use skill" button to the skill detail view. Clicking it calls
108
+ `injectInput` with `submit:false`, writing the text to Claude's input line
109
+ without sending Enter — the user edits and presses Enter themselves.
110
+ - Package skills populate `/<id> ` (slash command with trailing space for args);
111
+ user skills populate a natural-language invocation `Use the "<name>" skill: <desc>`.
112
+ - Button is disabled with a visible reason when there is no ready session.
113
+ - On success, a toast confirms "Typed into the terminal — edit and press Enter."
114
+ - Adds `generateSkillsPlugin` in `core/inject/skills-plugin.ts`: creates a
115
+ per-session `--plugin-dir` from the Sapiom skills bundled in `@sapiom/agent-core`.
116
+ claude-code auto-discovers `<plugin-dir>/skills/<name>/SKILL.md` and registers
117
+ `/<name>` as a slash command. Gracefully no-ops when agent-core's skills dir is
118
+ absent or unresolvable — the session still launches normally without the flag.
119
+ - `LaunchOpts.pluginDir` added; `ClaudeCodeAdapter.buildConfigArgs` emits
120
+ `--plugin-dir <path>` when set. Codex adapter ignores the field (unchanged).
121
+
122
+ - Updated dependencies [696f111]
123
+ - Updated dependencies [48fb35c]
124
+ - Updated dependencies [95bfcd1]
125
+ - Updated dependencies [bf44229]
126
+ - Updated dependencies [dab6d44]
127
+ - Updated dependencies [ebfa0bc]
128
+ - Updated dependencies [58ec57f]
129
+ - Updated dependencies [5e9659a]
130
+ - @sapiom/agent-core@0.9.2
131
+ - @sapiom/analytics-core@0.2.1
132
+ - @sapiom/mcp@0.11.2
133
+
134
+ ## 0.1.1
135
+
136
+ ### Patch Changes
137
+
138
+ - Updated dependencies [5f73ae7]
139
+ - Updated dependencies [d661d57]
140
+ - @sapiom/mcp@0.11.0
141
+ - @sapiom/agent-core@0.9.0
142
+ - @sapiom/agent@0.6.2
143
+
144
+ ## 0.1.0
145
+
146
+ ### Minor Changes
147
+
148
+ - 020139a: Canvas serving, macro engine, and dev-server port detection — the backend half of the canvas/action-rail/preview workstream:
149
+
150
+ - `GET /canvas/:harnessSessionId/*` serves whatever a session's agent wrote to its `.sapiom/canvas/` directory, with a friendly HTML empty-state when nothing's been rendered yet.
151
+ - `GET /api/macros` / `POST /api/macros/:id/run` resolve and execute the action-rail macros (`{{workflow.path}}`-style placeholder substitution, missing-value validation).
152
+ - Per-session canvas file watching (`canvas.reload` on change) and streaming `localhost:<port>` detection (`port.detected`) for the Preview pane's port chip.
153
+
154
+ ### Patch Changes
155
+
156
+ - Updated dependencies [020139a]
157
+ - Updated dependencies [020139a]
158
+ - Updated dependencies [c0fef6d]
159
+ - Updated dependencies [3dfbd10]
160
+ - @sapiom/agent@0.6.1
161
+ - @sapiom/agent-core@0.8.0
162
+ - @sapiom/mcp@0.10.0
package/README.md CHANGED
@@ -4,6 +4,8 @@ A local web app for building on Sapiom with your own coding agent.
4
4
 
5
5
  ```bash
6
6
  npx @sapiom/harness [dir]
7
+ # also available via the Sapiom CLI (npm i -g @sapiom/cli @sapiom/harness):
8
+ sapiom dev [dir]
7
9
  ```
8
10
 
9
11
  One command: checks your environment, signs you in, and opens a browser app
@@ -44,3 +46,37 @@ pnpm --filter @sapiom/harness build # server (tsc) + SPA (vite) → dist/
44
46
  Architecture: a single Node process (Express + ws + node-pty) serves the built
45
47
  SPA, a small REST API, terminal WebSocket streams, and the local telemetry
46
48
  ingest endpoint. The interface contract lives in `src/shared/types.ts`.
49
+
50
+ ## Testing
51
+
52
+ Three tiers — run whatever fits your change:
53
+
54
+ **Unit tier** (vitest, no browser, no agent): covers server logic, adapters,
55
+ analytics, and canvas rendering. Runs in CI on every PR.
56
+
57
+ ```bash
58
+ pnpm --filter @sapiom/harness test
59
+ ```
60
+
61
+ **Playwright mock tier** (chromium, Vite dev server with `VITE_MOCK=1`, no
62
+ harness server or agent process). The full `web/e2e/` suite against the SPA in
63
+ mock mode. Runs in CI on every PR. For a fast watch loop locally, use UI mode:
64
+
65
+ ```bash
66
+ # One-time browser install (not included in pnpm install):
67
+ pnpm --filter @sapiom/harness exec playwright install chromium
68
+
69
+ # Watch/UI mode — re-runs affected specs on save:
70
+ pnpm --filter @sapiom/harness exec playwright test \
71
+ --config web/e2e/playwright.config.ts --ui
72
+
73
+ # Or run the full suite once (same command CI uses):
74
+ pnpm --filter @sapiom/harness test:ui
75
+ ```
76
+
77
+ **E2E live tier** (real agent binaries, real pty, no CI). Requires Claude Code
78
+ or Codex installed and a valid `SAPIOM_API_KEY` in your environment.
79
+
80
+ ```bash
81
+ pnpm --filter @sapiom/harness e2e:live
82
+ ```
package/dist/cli/bin.js CHANGED
@@ -112,7 +112,8 @@ const main = async () => {
112
112
  if (identity?.source === "cached") {
113
113
  console.log(`\nSigned in as ${identity.organizationName} (cached credential).`);
114
114
  }
115
- const telemetryOptIn = await ensureConsent({ noTelemetry: options.noTelemetry });
115
+ const consentResult = await ensureConsent({ noTelemetry: options.noTelemetry });
116
+ const { telemetryOptIn } = consentResult;
116
117
  // First run = no recent directories recorded before this boot. Must be read
117
118
  // BEFORE recordRecentDir below stamps the launch dir in — after that the
118
119
  // signal is gone for good. Drives the SPA's welcome panel (AppState.firstRun)
@@ -128,6 +129,8 @@ const main = async () => {
128
129
  port: options.port,
129
130
  bootToken,
130
131
  telemetryOptIn,
132
+ consentSource: consentResult.source,
133
+ consentEnvReason: consentResult.envReason,
131
134
  identity,
132
135
  machineId,
133
136
  launchDir: options.dir,
@@ -149,12 +152,33 @@ const main = async () => {
149
152
  port: server?.port ?? options.port,
150
153
  bootToken,
151
154
  identity,
152
- telemetryOptIn,
155
+ telemetryOptIn: consentResult.telemetryOptIn,
153
156
  serverStarted: server !== null,
154
157
  });
155
158
  if (server && !options.noOpen) {
156
159
  await open(`http://localhost:${server.port}/?token=${bootToken}`);
157
160
  }
161
+ if (server) {
162
+ // Wire SIGINT (Ctrl+C) and SIGTERM so the awaitable close() path actually
163
+ // runs, which kills all live claude/codex ptys before the process exits.
164
+ // Without this, server.close() is never called from the CLI and the pty
165
+ // orphan problem the awaitable-kill feature was built to fix remains inert
166
+ // in the primary usage path.
167
+ // Guard against double-fire: once is enough; a second signal gets default
168
+ // handling (immediate termination) which is the correct behavior anyway.
169
+ let closing = false;
170
+ const handleSignal = (signal) => {
171
+ if (closing)
172
+ return;
173
+ closing = true;
174
+ // server.close() is already race-bounded to 5s internally.
175
+ void server.close().finally(() => {
176
+ process.exit(signal === "SIGINT" ? 130 : 143);
177
+ });
178
+ };
179
+ process.once("SIGINT", () => handleSignal("SIGINT"));
180
+ process.once("SIGTERM", () => handleSignal("SIGTERM"));
181
+ }
158
182
  };
159
183
  main().catch((err) => {
160
184
  console.error(err);
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AACH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAwB,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAsB,MAAM,oBAAoB,CAAC;AAYrE,SAAS,SAAS,CAAC,IAAc;IAC/B,IAAI,GAAuB,CAAC;IAC5B,IAAI,IAAI,GAAG,YAAY,CAAC;IACxB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,GAAG,GAAG,KAAK,CAAC;IAEhB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBACxB,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;oBAC1C,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;gBACrD,CAAC;gBACD,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBACrB,MAAM;YACR,CAAC;YACD,KAAK,WAAW;gBACd,MAAM,GAAG,IAAI,CAAC;gBACd,MAAM;YACR,KAAK,gBAAgB;gBACnB,WAAW,GAAG,IAAI,CAAC;gBACnB,MAAM;YACR,KAAK,WAAW;gBACd,MAAM,GAAG,IAAI,CAAC;gBACd,MAAM;YACR,KAAK,cAAc;gBACjB,SAAS,GAAG,IAAI,CAAC;gBACjB,MAAM;YACR,KAAK,OAAO;gBACV,GAAG,GAAG,IAAI,CAAC;gBACX,MAAM;YACR;gBACE,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzB,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC;gBAC1C,CAAC;gBACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;oBACtB,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAC;gBACvD,CAAC;gBACD,GAAG,GAAG,GAAG,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACvC,IAAI;QACJ,MAAM;QACN,WAAW;QACX,MAAM;QACN,SAAS;QACT,GAAG;KACJ,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAOpB;IACC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ;QAC5B,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,IACxD,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EACpD,EAAE;QACJ,CAAC,CAAC,mBAAmB,CAAC;IAExB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IACnE,yEAAyE;IACzE,qEAAqE;IACrE,6DAA6D;IAC7D,OAAO,CAAC,GAAG,CACT,iBACE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,oBAAoB,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,sBAClF,EAAE,CACH,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;IACrC,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjD,MAAM,YAAY,GAAG,MAAM,SAAS,EAAE,CAAC;IACvC,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAChC,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CACX,+EAA+E;YAC7E,mBAAmB,sBAAsB,IAAI;YAC7C,mBAAmB,qBAAqB,IAAI;YAC5C,qCAAqC,CACxC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAC5D,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CACT,6CAA6C,sBAAsB,IAAI;YACrE,sCAAsC,CACzC,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAE/C,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1F,2EAA2E;IAC3E,oEAAoE;IACpE,qEAAqE;IACrE,IAAI,QAAQ,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,kBAAkB,QAAQ,CAAC,gBAAgB,uBAAuB,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAChF,MAAM,EAAE,cAAc,EAAE,GAAG,aAAa,CAAC;IACzC,4EAA4E;IAC5E,yEAAyE;IACzE,8EAA8E;IAC9E,6EAA6E;IAC7E,2EAA2E;IAC3E,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,CAAC,MAAM,YAAY,EAAE,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;IAChE,MAAM,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAEnC,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEzD,IAAI,MAAM,GAAyB,IAAI,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,WAAW,CAAC;YACzB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,SAAS;YACT,cAAc;YACd,aAAa,EAAE,aAAa,CAAC,MAAM;YACnC,gBAAgB,EAAE,aAAa,CAAC,SAAS;YACzC,QAAQ;YACR,SAAS;YACT,SAAS,EAAE,OAAO,CAAC,GAAG;YACtB,iBAAiB,EAAE,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,QAAQ;YAClD,kBAAkB;YAClB,kBAAkB,EAAE,YAAY,CAAC,kBAAkB;YACnD,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,CAAC,GAAG;YAAE,MAAM,GAAG,CAAC;QAC5B,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,KAAK,CAAC,2CAA2C,OAAO,EAAE,CAAC,CAAC;QACpE,OAAO,CAAC,KAAK,CACX,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED,WAAW,CAAC;QACV,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,OAAO,CAAC,IAAI;QAClC,SAAS;QACT,QAAQ;QACR,cAAc,EAAE,aAAa,CAAC,cAAc;QAC5C,aAAa,EAAE,MAAM,KAAK,IAAI;KAC/B,CAAC,CAAC;IAEH,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,IAAI,CAAC,oBAAoB,MAAM,CAAC,IAAI,WAAW,SAAS,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,0EAA0E;QAC1E,yEAAyE;QACzE,wEAAwE;QACxE,2EAA2E;QAC3E,6BAA6B;QAC7B,0EAA0E;QAC1E,yEAAyE;QACzE,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,YAAY,GAAG,CAAC,MAA4B,EAAQ,EAAE;YAC1D,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,2DAA2D;YAC3D,KAAK,MAAO,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;gBAChC,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAChD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC;IACzD,CAAC;AACH,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -2,6 +2,30 @@ export interface EnsureConsentOptions {
2
2
  /** The `--no-telemetry` flag — forces telemetry off without prompting. */
3
3
  noTelemetry: boolean;
4
4
  }
5
+ /**
6
+ * How the telemetry consent state was determined for this boot.
7
+ * Exposed to the server so the UI can show a first-run notice when
8
+ * consent was implicitly set by the non-TTY default rather than explicitly
9
+ * answered by the user.
10
+ */
11
+ export type ConsentSource =
12
+ /** `--no-telemetry` flag or SAPIOM_TELEMETRY_DISABLED/DO_NOT_TRACK env var. */
13
+ "env-forced-off"
14
+ /** Stored consent from a previous first-run prompt — user answered explicitly. */
15
+ | "stored-explicit"
16
+ /** User answered the Y/n prompt just now (interactive TTY). */
17
+ | "prompted"
18
+ /** Non-TTY first run: the silent default was applied and persisted. */
19
+ | "default-silent";
20
+ export interface ConsentResult {
21
+ telemetryOptIn: boolean;
22
+ /**
23
+ * Which env var (if any) is forcing telemetry off this run.
24
+ * Only set when source === "env-forced-off".
25
+ */
26
+ envReason: string | null;
27
+ source: ConsentSource;
28
+ }
5
29
  /**
6
30
  * Resolves the telemetry opt-in state. Prompts once on first run and persists
7
31
  * the answer; subsequent runs reuse the stored value silently. `--no-telemetry`
@@ -10,6 +34,10 @@ export interface EnsureConsentOptions {
10
34
  * skipping the prompt entirely — without touching what's actually stored, so
11
35
  * a later run without the env var set sees whatever the user answered (or
12
36
  * will still be asked, if this env-vetoed run was their first).
37
+ *
38
+ * Returns a ConsentResult that includes the source of the decision — the UI
39
+ * uses this to show a first-run notice when the user never explicitly answered
40
+ * (source === "default-silent"), skipping it when they did.
13
41
  */
14
- export declare function ensureConsent(options: EnsureConsentOptions): Promise<boolean>;
42
+ export declare function ensureConsent(options: EnsureConsentOptions): Promise<ConsentResult>;
15
43
  //# sourceMappingURL=consent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/cli/consent.ts"],"names":[],"mappings":"AAqCA,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,WAAW,EAAE,OAAO,CAAC;CACtB;AAuBD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBnF"}
1
+ {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/cli/consent.ts"],"names":[],"mappings":"AAoDA,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa;AACvB,+EAA+E;AAC7E,gBAAgB;AAClB,kFAAkF;GAChF,iBAAiB;AACnB,+DAA+D;GAC7D,UAAU;AACZ,uEAAuE;GACrE,gBAAgB,CAAC;AAErB,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,aAAa,CAAC;CACvB;AAuBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAwBzF"}
@@ -1,11 +1,20 @@
1
1
  import * as readline from "node:readline/promises";
2
2
  import { hasStoredSettings, loadSettings, saveSettings } from "./settings.js";
3
- // Internal/friendlies phase: default to opted in (matches the on-by-default
4
- // prompt below and the non-TTY fallback) — flip this the other way for a
5
- // wider release.
3
+ // Early-access phase: default to opted in (matches the on-by-default prompt
4
+ // below and the non-TTY fallback) — intentional for the early-access phase;
5
+ // flip for a wider release.
6
+ //
7
+ // Pre-wider-release checklist: revisit the non-TTY silent opt-in below.
8
+ // The current default (true) is intentional for the early-access phase;
9
+ // for a wider/public release the conservative choice is false (opt-out by
10
+ // default) so users who never see a TTY (CI, Docker, headless environments)
11
+ // are not silently opted in.
12
+ // See also the first-run UI notice wiring in web/src/components/TelemetryNotice.tsx,
13
+ // which surfaces this path to interactive users who did get the default.
6
14
  const DEFAULT_TELEMETRY_OPT_IN = true;
7
15
  const CONSENT_COPY = `
8
- Sapiom Harness collects local usage analytics to improve the product:
16
+ Sapiom Harness collects usage analytics locally and, with telemetry on,
17
+ sends them to Sapiom to improve the product:
9
18
  - the prompts you send and the tool calls your agent makes
10
19
  - session start/stop lifecycle events
11
20
  This is always written locally to ~/.sapiom/harness/events.ndjson for your
@@ -17,7 +26,11 @@ gear, or run with --no-telemetry).
17
26
  async function promptConsent() {
18
27
  console.log(`\n${CONSENT_COPY}\n`);
19
28
  if (!process.stdin.isTTY) {
20
- console.log(`Non-interactive session defaulting telemetry to ${DEFAULT_TELEMETRY_OPT_IN ? "on" : "off"}.\n`);
29
+ // The full consent copy (what's collected, local store, and opt-out path)
30
+ // was already printed above. Make the default explicit so non-TTY users
31
+ // reviewing logs see it clearly.
32
+ console.log(`Non-interactive session — telemetry is defaulting to ${DEFAULT_TELEMETRY_OPT_IN ? "on" : "off"}` +
33
+ ` per the notice above. Run with --no-telemetry or set SAPIOM_TELEMETRY_DISABLED=1 to opt out.\n`);
21
34
  return DEFAULT_TELEMETRY_OPT_IN;
22
35
  }
23
36
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -61,21 +74,30 @@ function envDisableReason() {
61
74
  * skipping the prompt entirely — without touching what's actually stored, so
62
75
  * a later run without the env var set sees whatever the user answered (or
63
76
  * will still be asked, if this env-vetoed run was their first).
77
+ *
78
+ * Returns a ConsentResult that includes the source of the decision — the UI
79
+ * uses this to show a first-run notice when the user never explicitly answered
80
+ * (source === "default-silent"), skipping it when they did.
64
81
  */
65
82
  export async function ensureConsent(options) {
66
- if (options.noTelemetry)
67
- return false;
83
+ if (options.noTelemetry) {
84
+ return { telemetryOptIn: false, envReason: null, source: "env-forced-off" };
85
+ }
68
86
  const envReason = envDisableReason();
69
87
  if (envReason) {
70
88
  console.log(`Telemetry disabled via ${envReason} — skipping the consent prompt.\n`);
71
- return false;
89
+ return { telemetryOptIn: false, envReason, source: "env-forced-off" };
72
90
  }
73
91
  const isFirstRun = !(await hasStoredSettings());
74
92
  const settings = await loadSettings();
75
- if (!isFirstRun)
76
- return settings.telemetryOptIn;
93
+ if (!isFirstRun) {
94
+ return { telemetryOptIn: settings.telemetryOptIn, envReason: null, source: "stored-explicit" };
95
+ }
96
+ // First run: prompt the user (TTY) or apply the silent default (non-TTY).
97
+ const isTTY = process.stdin.isTTY;
77
98
  const telemetryOptIn = await promptConsent();
78
99
  await saveSettings({ ...settings, telemetryOptIn });
79
- return telemetryOptIn;
100
+ const source = isTTY ? "prompted" : "default-silent";
101
+ return { telemetryOptIn, envReason: null, source };
80
102
  }
81
103
  //# sourceMappingURL=consent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/cli/consent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE9E,4EAA4E;AAC5E,yEAAyE;AACzE,iBAAiB;AACjB,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAEtC,MAAM,YAAY,GAAG;;;;;;;;;CASpB,CAAC,IAAI,EAAE,CAAC;AAET,KAAK,UAAU,aAAa;IAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,YAAY,IAAI,CAAC,CAAC;IAEnC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,qDAAqD,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC;QAC/G,OAAO,wBAAwB,CAAC;IAClC,CAAC;IAED,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC9E,IAAI,MAAM,KAAK,EAAE;YAAE,OAAO,wBAAwB,CAAC;QACnD,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,CAAC;IAC5C,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAOD;;;;;;;GAOG;AACH,SAAS,YAAY,CAAC,KAAyB;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,MAAM,CAAC;AACrD,CAAC;AAED,oFAAoF;AACpF,SAAS,gBAAgB;IACvB,IAAI,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;QAAE,OAAO,2BAA2B,CAAC;IAC5F,IAAI,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAAE,OAAO,cAAc,CAAC;IAClE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B;IAC/D,IAAI,OAAO,CAAC,WAAW;QAAE,OAAO,KAAK,CAAC;IAEtC,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;IACrC,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,0BAA0B,SAAS,mCAAmC,CAAC,CAAC;QACpF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,iBAAiB,EAAE,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IAEtC,IAAI,CAAC,UAAU;QAAE,OAAO,QAAQ,CAAC,cAAc,CAAC;IAEhD,MAAM,cAAc,GAAG,MAAM,aAAa,EAAE,CAAC;IAC7C,MAAM,YAAY,CAAC,EAAE,GAAG,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;IACpD,OAAO,cAAc,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/cli/consent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE9E,4EAA4E;AAC5E,4EAA4E;AAC5E,4BAA4B;AAC5B,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,0EAA0E;AAC1E,4EAA4E;AAC5E,6BAA6B;AAC7B,qFAAqF;AACrF,yEAAyE;AACzE,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAEtC,MAAM,YAAY,GAAG;;;;;;;;;;CAUpB,CAAC,IAAI,EAAE,CAAC;AAET,KAAK,UAAU,aAAa;IAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,YAAY,IAAI,CAAC,CAAC;IAEnC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACzB,0EAA0E;QAC1E,wEAAwE;QACxE,iCAAiC;QACjC,OAAO,CAAC,GAAG,CACT,wDAAwD,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;YACjG,iGAAiG,CAClG,CAAC;QACF,OAAO,wBAAwB,CAAC;IAClC,CAAC;IAED,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC9E,IAAI,MAAM,KAAK,EAAE;YAAE,OAAO,wBAAwB,CAAC;QACnD,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,CAAC;IAC5C,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAiCD;;;;;;;GAOG;AACH,SAAS,YAAY,CAAC,KAAyB;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,MAAM,CAAC;AACrD,CAAC;AAED,oFAAoF;AACpF,SAAS,gBAAgB;IACvB,IAAI,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;QAAE,OAAO,2BAA2B,CAAC;IAC5F,IAAI,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAAE,OAAO,cAAc,CAAC;IAClE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B;IAC/D,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC9E,CAAC;IAED,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;IACrC,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,0BAA0B,SAAS,mCAAmC,CAAC,CAAC;QACpF,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACxE,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,iBAAiB,EAAE,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IAEtC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,cAAc,EAAE,QAAQ,CAAC,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACjG,CAAC;IAED,0EAA0E;IAC1E,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAClC,MAAM,cAAc,GAAG,MAAM,aAAa,EAAE,CAAC;IAC7C,MAAM,YAAY,CAAC,EAAE,GAAG,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;IACpD,MAAM,MAAM,GAAkB,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACpE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * HarnessAdapter union type — the shape every adapter (embedded or external)
3
+ * must satisfy.
4
+ *
5
+ * "embedded" adapters are spawned inside a pty session by the harness.
6
+ * "external" adapters run in their own companion app and have no spawn path —
7
+ * the type makes calling spawn/send on them a compile error, not just a
8
+ * convention.
9
+ *
10
+ * Adding an external harness = one descriptor file + one HARNESS_ADAPTER_INFOS
11
+ * line. An embedded harness that can be spawned as a session additionally
12
+ * requires: a runtime adapter (launch/resume/doctor/listPastSessions) in
13
+ * core/adapters/, a new id in SPAWNABLE_HARNESS_KINDS (shared/types.ts —
14
+ * which widens HarnessKind and the z.enum gate automatically), and a real
15
+ * e2e suite confirming the lifecycle works end-to-end.
16
+ */
17
+ /** Stable identifier for every harness the registry knows about. */
18
+ export type HarnessAdapterId = "claude-code" | "codex" | "pi" | "opencode" | "conductor";
19
+ /** Whether the harness is spawned by the harness (embedded) or managed by its
20
+ * own companion app (external). */
21
+ export type HarnessAdapterMode = "embedded" | "external";
22
+ /** Fields shared by every adapter regardless of mode. */
23
+ export interface HarnessAdapterBase {
24
+ /** Stable identifier used in APIs and the session registry. */
25
+ id: HarnessAdapterId;
26
+ /** Human-readable name for pickers and logs. */
27
+ label: string;
28
+ /** Spawn mode — narrow on this before calling any spawn-path methods. */
29
+ mode: HarnessAdapterMode;
30
+ /**
31
+ * Per-agent prompt text guiding the user through installing and
32
+ * configuring the Sapiom MCP server (`@sapiom/mcp`) for this harness.
33
+ * Consumed by the skills-panel Install MCP modal. Returns the text string
34
+ * directly — callers may render it as preformatted text.
35
+ */
36
+ installMcpPrompt(): string;
37
+ /**
38
+ * Best-effort detection of whether the harness is installed on this
39
+ * machine. Never throws.
40
+ */
41
+ detectInstalled(): Promise<boolean>;
42
+ /**
43
+ * Marks adapters whose launch behavior is best-effort and not yet
44
+ * hardened by an end-to-end suite. Absent (or false) for fully
45
+ * supported harnesses.
46
+ */
47
+ experimental?: boolean;
48
+ }
49
+ /**
50
+ * An adapter the harness spawns inside a pty session.
51
+ * The existing `HarnessAdapter` interface (shared/types.ts) carries the actual
52
+ * launch/resume/doctor/listPastSessions contract consumed by SessionManager;
53
+ * this is the registry-level description used for enumeration and the
54
+ * harnesses listing endpoint.
55
+ */
56
+ export interface EmbeddedHarnessAdapterInfo extends HarnessAdapterBase {
57
+ mode: "embedded";
58
+ }
59
+ /**
60
+ * An adapter for a harness that runs in its own companion app.
61
+ * There is deliberately no spawn path — `launchCommand` is absent so a
62
+ * spawn attempt is a compile error rather than a runtime surprise.
63
+ */
64
+ export interface ExternalHarnessAdapterInfo extends HarnessAdapterBase {
65
+ mode: "external";
66
+ }
67
+ /**
68
+ * Every registry entry satisfies this union. Narrow on `mode` before
69
+ * attempting any spawn-path operation — external adapters have none.
70
+ */
71
+ export type HarnessAdapterInfo = EmbeddedHarnessAdapterInfo | ExternalHarnessAdapterInfo;
72
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,OAAO,GACP,IAAI,GACJ,UAAU,GACV,WAAW,CAAC;AAEhB;oCACoC;AACpC,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,UAAU,CAAC;AAEzD,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,EAAE,EAAE,gBAAgB,CAAC;IACrB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,IAAI,EAAE,kBAAkB,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,IAAI,MAAM,CAAC;IAC3B;;;OAGG;IACH,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,0BAA0B,GAAG,0BAA0B,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * HarnessAdapter union type — the shape every adapter (embedded or external)
3
+ * must satisfy.
4
+ *
5
+ * "embedded" adapters are spawned inside a pty session by the harness.
6
+ * "external" adapters run in their own companion app and have no spawn path —
7
+ * the type makes calling spawn/send on them a compile error, not just a
8
+ * convention.
9
+ *
10
+ * Adding an external harness = one descriptor file + one HARNESS_ADAPTER_INFOS
11
+ * line. An embedded harness that can be spawned as a session additionally
12
+ * requires: a runtime adapter (launch/resume/doctor/listPastSessions) in
13
+ * core/adapters/, a new id in SPAWNABLE_HARNESS_KINDS (shared/types.ts —
14
+ * which widens HarnessKind and the z.enum gate automatically), and a real
15
+ * e2e suite confirming the lifecycle works end-to-end.
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/core/adapters/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Registry descriptor for the Claude Code adapter.
3
+ *
4
+ * The runtime adapter implementation (launch/resume/doctor/listPastSessions)
5
+ * lives in claude-code.ts. This file carries only the registry-level metadata
6
+ * consumed by the harness listing endpoint and the skills panel Install MCP
7
+ * modal: the human label, spawn mode, MCP install guidance, and PATH detection.
8
+ */
9
+ import type { EmbeddedHarnessAdapterInfo } from "./adapter.js";
10
+ export declare const claudeCodeAdapterInfo: EmbeddedHarnessAdapterInfo;
11
+ //# sourceMappingURL=claude-code-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-info.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/claude-code-info.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAkB/D,eAAO,MAAM,qBAAqB,EAAE,0BAUnC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { isExecutableOnPath } from "./detect.js";
2
+ const INSTALL_MCP_PROMPT = [
3
+ "Set up the Sapiom MCP server for Claude Code.",
4
+ "",
5
+ "1. Register it under the server name `sapiom-dev`:",
6
+ "",
7
+ " claude mcp add sapiom-dev -- npx -y @sapiom/mcp",
8
+ "",
9
+ " The `@sapiom/mcp` npm package ships the `sapiom-mcp` binary, a local",
10
+ " MCP server that speaks stdio — no global install or daemon needed.",
11
+ "2. Verify the registration: `claude mcp list` should show `sapiom-dev`.",
12
+ "3. Restart Claude Code (or start a new session) so the server is loaded.",
13
+ "4. Networked Sapiom tools need an API key: run the `sapiom_authenticate`",
14
+ " tool once and complete the browser login it opens.",
15
+ ].join("\n");
16
+ export const claudeCodeAdapterInfo = {
17
+ id: "claude-code",
18
+ label: "Claude Code",
19
+ mode: "embedded",
20
+ installMcpPrompt() {
21
+ return INSTALL_MCP_PROMPT;
22
+ },
23
+ detectInstalled() {
24
+ return isExecutableOnPath("claude");
25
+ },
26
+ };
27
+ //# sourceMappingURL=claude-code-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-info.js","sourceRoot":"","sources":["../../../src/core/adapters/claude-code-info.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,kBAAkB,GAAG;IACzB,+CAA+C;IAC/C,EAAE;IACF,oDAAoD;IACpD,EAAE;IACF,oDAAoD;IACpD,EAAE;IACF,yEAAyE;IACzE,uEAAuE;IACvE,yEAAyE;IACzE,0EAA0E;IAC1E,0EAA0E;IAC1E,uDAAuD;CACxD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,qBAAqB,GAA+B;IAC/D,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,aAAa;IACpB,IAAI,EAAE,UAAU;IAChB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,eAAe;QACb,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/claude-code.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,UAAU,EACV,cAAc,EACd,SAAS,EACV,MAAM,uBAAuB,CAAC;AAQ/B,MAAM,WAAW,wBAAwB;IACvC,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuGD,qBAAa,iBAAkB,YAAW,cAAc;IACtD,QAAQ,CAAC,EAAE,EAAG,aAAa,CAAU;IACrC,QAAQ,CAAC,WAAW,EAAG,OAAO,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,GAAE,wBAA6B;IAK5C,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAetC,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS;IAgBnC,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,SAAS;IAa3D;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS;IAmBjC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CA8B/D;AAcD,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,cAAc,CAE1F"}
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/claude-code.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,UAAU,EACV,cAAc,EACd,SAAS,EACV,MAAM,uBAAuB,CAAC;AAiB/B,MAAM,WAAW,wBAAwB;IACvC,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA8FD,qBAAa,iBAAkB,YAAW,cAAc;IACtD,QAAQ,CAAC,EAAE,EAAG,aAAa,CAAU;IACrC,QAAQ,CAAC,WAAW,EAAG,OAAO,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,GAAE,wBAA6B;IAK5C,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAetC,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS;IAgBnC,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,SAAS;IAa3D;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS;IAmBjC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CA8B/D;AAcD,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,cAAc,CAE1F"}
@@ -10,20 +10,19 @@ import { readFile, readdir, stat, open } from "node:fs/promises";
10
10
  import { homedir } from "node:os";
11
11
  import { basename, join } from "node:path";
12
12
  import { promisify } from "node:util";
13
- const execFileAsync = promisify(execFile);
14
- /** Bytes read from the tail of a transcript file. Files can be 100MB+; the
15
- * summary/title we need is always near the end. */
16
- const TRANSCRIPT_TAIL_BYTES = 65536;
17
13
  /**
18
- * Claude Code stores transcripts at `~/.claude/projects/<encoded-cwd>/*.jsonl`.
19
- * The encoding strips the leading `/` and replaces `/` and `.` with `-`.
20
- * If Claude Code changes this scheme, discovery silently returns no history
21
- * (listPastSessions degrades to an empty list, not an error).
14
+ * Maps a project cwd to the directory name Claude Code uses for its transcript
15
+ * store under `~/.claude/projects/`. Claude Code applies this encoding before
16
+ * creating the directory see its own source for the canonical definition.
22
17
  */
23
18
  function encodeProjectPath(cwd) {
24
19
  const normalized = cwd.replace(/\\/g, "/");
25
20
  return normalized.replace(/:/g, "").replace(/[/.]/g, "-");
26
21
  }
22
+ const execFileAsync = promisify(execFile);
23
+ /** Bytes read from the tail of a transcript file. Files can be 100MB+; the
24
+ * summary/title we need is always near the end. */
25
+ const TRANSCRIPT_TAIL_BYTES = 65536;
27
26
  function extractTextFromContent(content) {
28
27
  if (typeof content === "string")
29
28
  return content;
@@ -105,6 +104,8 @@ function buildConfigArgs(opts) {
105
104
  args.push("--settings", opts.settingsFile);
106
105
  if (opts.mcpConfigFile)
107
106
  args.push("--mcp-config", opts.mcpConfigFile);
107
+ if (opts.pluginDir)
108
+ args.push("--plugin-dir", opts.pluginDir);
108
109
  return args;
109
110
  }
110
111
  export class ClaudeCodeAdapter {