@comput/pi-intercom 0.3.0 → 0.4.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 (58) hide show
  1. package/README.md +137 -25
  2. package/dist/activity.d.ts +12 -0
  3. package/dist/activity.js +73 -0
  4. package/dist/activity.js.map +1 -0
  5. package/dist/config.d.ts +39 -0
  6. package/dist/config.js +182 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/index.d.ts +3 -0
  9. package/dist/index.js +186 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/launcher.d.ts +17 -0
  12. package/dist/launcher.js +77 -0
  13. package/dist/launcher.js.map +1 -0
  14. package/dist/monitor-launcher.d.ts +17 -0
  15. package/dist/monitor-launcher.js +136 -0
  16. package/dist/monitor-launcher.js.map +1 -0
  17. package/dist/monitor-view.d.ts +6 -0
  18. package/dist/monitor-view.js +134 -0
  19. package/dist/monitor-view.js.map +1 -0
  20. package/dist/monitor.d.ts +22 -0
  21. package/dist/monitor.js +171 -0
  22. package/dist/monitor.js.map +1 -0
  23. package/dist/observability.d.ts +79 -0
  24. package/dist/observability.js +208 -0
  25. package/dist/observability.js.map +1 -0
  26. package/dist/reports.d.ts +12 -0
  27. package/dist/reports.js +160 -0
  28. package/dist/reports.js.map +1 -0
  29. package/dist/runtime.d.ts +59 -0
  30. package/dist/runtime.js +458 -0
  31. package/dist/runtime.js.map +1 -0
  32. package/dist/snapshot.d.ts +15 -0
  33. package/dist/snapshot.js +128 -0
  34. package/dist/snapshot.js.map +1 -0
  35. package/dist/transport.d.ts +24 -0
  36. package/dist/transport.js +122 -0
  37. package/dist/transport.js.map +1 -0
  38. package/dist/worker-status.d.ts +26 -0
  39. package/dist/worker-status.js +76 -0
  40. package/dist/worker-status.js.map +1 -0
  41. package/package.json +13 -7
  42. package/references/observability.md +66 -60
  43. package/references/roadmap.md +68 -0
  44. package/src/activity.ts +66 -0
  45. package/src/config.ts +1 -1
  46. package/src/index.ts +51 -23
  47. package/src/monitor-launcher.ts +110 -0
  48. package/src/monitor-view.ts +123 -0
  49. package/src/monitor.ts +143 -0
  50. package/src/observability.ts +6 -1
  51. package/src/reports.ts +122 -0
  52. package/src/runtime.ts +45 -7
  53. package/src/{dashboard.ts → snapshot.ts} +9 -60
  54. package/src/transport.ts +11 -2
  55. package/src/worker-status.ts +66 -0
  56. package/dashboard/app.js +0 -182
  57. package/dashboard/index.html +0 -41
  58. package/dashboard/style.css +0 -82
package/README.md CHANGED
@@ -1,41 +1,96 @@
1
- # PiIntercom (V1 supported core)
1
+ # Pi Intercom
2
2
 
3
- One Windows/Linux interactive Pi extension for coordinator and workers. **Intercom communicates; Pi orchestrates.** No automatic assignment, retry, removal, replacement, launcher fallback, commit, or rollback.
3
+ **A coordinator-led workspace for Pi.**
4
4
 
5
- **`intercom_stop_worker` and `intercom_close_worker` are disabled.** They throw an unsupported-host error before sending control or calling cancellation/shutdown. Incoming stop/close controls also fail. Pi 0.84.4 leaves retry continuation alive after extension abort. See [blocker](references/implementation-blocker.md). Newer versions are not automatically assumed safe; a verified supported lifecycle API and tests are required before enabling these capabilities.
5
+ Delegate into separate worker contexts, evaluate their reports, and keep the main conversation focused—with the team visible alongside it.
6
6
 
7
- ## Use
7
+ Pi Intercom lets your main Pi session orchestrate work across a team of worker sessions. You describe the goal; the coordinator breaks it into focused assignments and delegates them to workers, each with its own conversation and model context. Workers report back, and the coordinator evaluates their results, decides what to do next, and brings the outcome back to you.
8
8
 
9
- Requires Windows or Linux, Node 22+, interactive Pi with project trust, and this package's peer dependencies supplied by Pi (`@earendil-works/pi-coding-agent`, `typebox`). Launch the coordinator explicitly from the intended root:
9
+ A core objective is to **keep the coordinator's context clean and concise, and the main conversation responsive**. Delegate implementation details, lengthy investigations, and tool-heavy work to worker contexts; bring back focused findings for the coordinator to evaluate. That helps the main session stay available for your questions and decisions instead of getting bogged down in implementation. It is a workflow goal, not a guarantee of latency or context size—the quality of delegation and reports still matters.
10
10
 
11
- ```powershell
12
- cd D:\Source\YourProject
13
- pi -e D:\Source\PiIntercom\src\index.ts
11
+ The value is the loop: **delegate → report back → evaluate → decide the next step**. The coordinator can ask for clarification, request a review, assign follow-up work, or summarize the result—within the scope of your request. You stay in one conversation while the detailed work happens in separate worker contexts.
12
+
13
+ ## At a glance
14
+
15
+ - **Keep the main conversation focused.** Workers handle implementation detail in their own contexts and return concise reports, helping the coordinator stay responsive and focused on decisions.
16
+ - **Your main session leads.** The coordinator keeps track of your request, delegates focused work, and evaluates what comes back before deciding the next step.
17
+ - **Each worker has its own context.** Implementation, investigation, and review can happen in separate Pi conversations. The coordinator supplies the brief; workers return findings rather than automatically merging their full conversation histories.
18
+ - **Delegation is a conversation.** Ask for progress, clarify a finding, or send a follow-up assignment. Configured workers can also communicate directly when useful.
19
+ - **Visible terminals.** With [Herdr](https://herdr.dev), workers open in their own tabs without taking your focus. Windows also supports separate terminal windows.
20
+ - **A status pane above your conversation.** A lightweight terminal monitor shows each worker's last-observed status and activity. It is a display process, not another agent or model call.
21
+ - **Explicit control.** Intercom supplies the communication tools; Pi decides how to use them in response to your instructions. Creating a worker does not silently assign it work.
22
+
23
+ **Intercom communicates; Pi orchestrates.** It is a local coordination layer, not an autonomous scheduler or a task-completion guarantee.
24
+
25
+ > **0.4.1:** The terminal monitor replaces the browser dashboard. Public worker reports and the read-only JSON worker-status tool keep coordinator decisions separate from observed activity.
26
+
27
+ For potential next steps, see [Improvement topics](references/roadmap.md). These are proposals for discussion, not implemented features or release commitments.
28
+
29
+ ## What a session can look like
30
+
31
+ Ask your coordinator:
32
+
33
+ > Review the launcher and its tests for reliability issues. Delegate focused reviews to workers, evaluate their findings, and bring me a proposed fix plan before changing code.
34
+
35
+ The coordinator can give one worker the launcher review and another the test review. Each investigates in its own context and reports back. The coordinator then checks the findings, resolves overlaps or disagreements, and decides whether to ask for more evidence or present the plan to you. Because you asked for a plan first, it stops before making changes.
36
+
37
+ You direct the goal and boundaries—not every message between workers. Separate worker terminals remain available whenever you want to inspect their conversations.
38
+
39
+ The monitor provides a compact view alongside that workflow. Example observations:
40
+
41
+ ```text
42
+ Worker Seen Status Last activity
43
+ Reviewer 3s ago working Reading files
44
+ Tester 12s ago idle Running command
14
45
  ```
15
46
 
16
- Alternatively install from npm:
47
+ Status is **last reported**, not proof of a live connection. An idle worker's last activity can remain visible after it finishes a turn; neither idle nor a delivered message proves an assignment is complete. Old observations are marked explicitly.
17
48
 
18
- ```powershell
49
+ ## Quick start
50
+
51
+ **Requirements:** Windows or Linux, Node 22.19+, interactive [Pi](https://github.com/earendil-works/pi), and project trust. Use Herdr for worker tabs on either platform; Linux worker launching requires it. Pi supplies the extension's host peers (`@earendil-works/pi-coding-agent`, `typebox`). The separate Node monitor uses its own pinned runtime dependency, `pi-intercom-tui` (an npm alias of `@earendil-works/pi-tui`), installed even when Pi disables peer installation. It does not depend on Pi's extension loader or a machine-specific host installation path.
52
+
53
+ ### Install the published extension
54
+
55
+ ```sh
19
56
  pi install npm:@comput/pi-intercom
20
57
  ```
21
58
 
22
- Then start a new Pi session or run Pi `/reload`. `pi install` records the package in user settings by default; add `-l` for project settings. The Intercom extension itself does not change Pi settings. Load only one copy: do not enable the installed package alongside an explicit source checkout, or load both source and built output.
59
+ Open Pi inside a Herdr workspace at the project root you want to coordinate, or run `/reload` in an existing session there. Then ask it to create workers and give them a bounded task.
60
+
61
+ `pi install` uses your personal settings by default; add `-l` for project settings. Load only one copy: do not enable the npm package alongside a source checkout, or both source and built output. Use `pi list` to check your configured packages.
62
+
63
+ ### Know the boundaries
64
+
65
+ - **Stop/close tools are disabled.** Close workers explicitly in their terminals. Pi 0.84.4's cancellation behavior leaves retry continuations alive; newer versions are not assumed safe without verification. See the [cancellation blocker](references/implementation-blocker.md).
66
+ - **No silent recovery.** Intercom does not automatically retry messages, replace workers, switch launchers, commit changes, or roll them back.
67
+ - **Local, not remote.** Messaging binds to loopback. Local processes are trusted; this is not an authenticated service for untrusted clients.
68
+
69
+ For the exact steps and tool contracts, see [Explicit workflow](#explicit-workflow), [Tools and permissions](#tools-and-permissions), and [Config and wire contracts](#config-and-wire-contracts).
23
70
 
24
71
  ### Updating the loaded copy
25
72
 
26
73
  - **npm installation:** update the installed package, not this checkout: `pi update npm:@comput/pi-intercom`. A pinned version must be explicitly changed (for example, `pi install npm:@comput/pi-intercom@0.1.2`, using the same settings scope as the original installation). `pi list` shows configured package sources; inspect that installation's `package.json` to confirm its version.
27
- - **Source loading (`pi -e .../src/index.ts`):** update that checkout. `npm run build` produces test output; it does not update a separate npm installation.
74
+ - **Source loading:** update that checkout and run `npm ci && npm run build` to rebuild the standalone monitor. This does not update a separate npm installation.
28
75
  - After obtaining the intended code, start a new session or use Pi `/reload` in each affected running host. **`intercom_reload_worker` only reads shared configuration; it cannot load extension-code fixes.** Workers launched by a coordinator receive the coordinator extension's actual file path. Updating a different copy does not change that path, and existing workers do not automatically reload.
29
76
 
30
77
  The 0.1.2 update/reload and subsequent worker creation were observed live; comprehensive reload/session-replacement lifecycle coverage remains pending.
31
78
 
32
- ### Linux source installation
79
+ ### Install from source
80
+
81
+ To develop or run a source checkout, build and register it:
33
82
 
34
83
  ```sh
84
+ git clone https://github.com/comput-sh/pi-intercom.git
85
+ cd pi-intercom
86
+ npm ci
87
+ npm run build
35
88
  pi install /absolute/path/to/pi-intercom
36
89
  ```
37
90
 
38
- Run Pi `/reload` (or start a new interactive session) after installing or changing source. Linux supports messaging, configuration, the dashboard, and Herdr worker launch/resume. Launch the coordinator inside a Herdr workspace; `herdr`, `sh`, and `pi` must be on PATH in worker panes. Workers run a quoted POSIX shell command in the returned pane, with the coordinator's actual extension path. Project trust remains required.
91
+ Replace the final path with your checkout's absolute path (use a Windows path on Windows). Remove or disable a separately installed npm copy before loading source. Then open Pi in the project you want to coordinate—not necessarily the extension's checkout.
92
+
93
+ Run Pi `/reload` (or start a new interactive session) after installing or changing source; reload workers too when changing their extension code. A standalone monitor already running in its pane needs an explicit restart to load rebuilt display code. Linux supports messaging, configuration, the terminal monitor, and Herdr worker launch/resume. Launch the coordinator inside a Herdr workspace; `herdr`, `sh`, and `pi` must be on PATH in worker panes. Workers run a quoted POSIX shell command in the returned pane, with the coordinator's actual extension path. Project trust remains required.
39
94
 
40
95
  Linux `multiplexer: none` is explicitly unsupported: no terminal guessing, headless fallback, or automatic cleanup. Stop/close remain disabled on both platforms. Automated Linux tests cover shell argument preservation and adapter/HTTP behavior. A live source-loaded Linux Herdr smoke test launched two workers: both registered, loaded their configured names/responsibilities, and acknowledged coordinator messages through Intercom. This verifies launch and round-trip messaging, not resume or cancellation.
41
96
 
@@ -66,9 +121,11 @@ Every tool rereads current config and checks the live Pi session ID. Names are c
66
121
  | `intercom_configure_worker` | `sessionId`, `port`, `projectDirectory`, `name`, `description` | Coordinator; all five explicit fields, writes only |
67
122
  | `intercom_reload_worker` | `to` (worker name) | Coordinator; passive config/name reload |
68
123
  | `intercom_send` | `to` (name), `message` | Configured, responsibility-loaded sessions; asynchronous message |
69
- | `intercom_list` | None | Configured coordinator/workers; saved roster and derived `dashboardUrl`, never live health |
124
+ | `intercom_list` | None | Configured coordinator/workers; saved roster, never live health |
125
+ | `intercom_worker_status` | `name?`, `offset?`, `limit?` | Configured sessions; bounded JSON observations/public reports, no live probing |
70
126
  | `intercom_request_status` | `to` (worker name) | Coordinator; independent extension report |
71
127
  | `intercom_report_status` | None | Workers including anonymous; shared report function, never registration |
128
+ | `intercom_report_work` | `status`, `summary?` | Configured, responsibility-loaded workers; save a public report and notify coordinator, never approve/complete work |
72
129
  | `intercom_stop_worker`, `intercom_close_worker` | `to` (worker name) | Coordinator role checked, then **unsupported-host error**, no side effects |
73
130
  | `intercom_resume_worker` | `to` (worker name) | Coordinator; saved session, configured launcher/directory |
74
131
  | `intercom_remove_worker` | `to` (worker name) | Coordinator; config entry only, no shutdown/session deletion |
@@ -97,7 +154,7 @@ Shared, source-controlled file: `<root>/.pi-intercom/config.json`. Do not ignore
97
154
  }
98
155
  ```
99
156
 
100
- Version 0.2.0 dashboard support adds optional `dashboardPort` (integer 1–65535) on the **coordinator entry only**. Older config without it remains valid; workers cannot have it. This is separate from each agent's messaging `port`. `intercom_list` keeps `version`, `multiplexer` and `agents`, and adds top-level `dashboardUrl`: `http://127.0.0.1:<saved dashboardPort>/`, or `null` when no dashboard port is saved. It reads saved config without probing or starting a dashboard; the URL is last-known, not a liveness claim.
157
+ Legacy coordinator-only `dashboardPort` values are accepted for migration, but the browser dashboard has been retired in 0.4.1. Coordinator startup removes this field through the guarded config-write path. `intercom_list` returns the saved roster without `dashboardPort` or `dashboardUrl`; it does not probe live availability. The agent messaging `port` is unchanged.
101
158
 
102
159
  Workers have `coordinator:false` and an existing project directory equal to root or below it. Writes canonicalize directories and check real paths (including symlink escapes). Only coordinator extension operations write config; ordinary Pi file/shell tools are not restricted.
103
160
 
@@ -109,23 +166,60 @@ HTTP binds **127.0.0.1 only**, `POST /intercom`, UTF-8 JSON, at most 64 KiB. Env
109
166
  {"version":1,"kind":"message","from":"sender-session-id","to":"expected-recipient-session-id","payload":{"message":"explicit message"}}
110
167
  ```
111
168
 
112
- Kinds: `message`, `registration` (`port`, `projectDirectory`), `status` (`port`, `busy`), `request_status`, `reload`, `stop`, `close` (empty control payload). Sender session identity is the envelope `from`; registration/status agent notifications include an explicit `sessionId` field. Agent messages require configured sender and recipient; controls require the current coordinator's sender ID and a worker recipient. Registration/unknown status are intentional exceptions to configured-sender checks, accepted only by coordinator. All receivers verify expected recipient ID, protecting against stale ports reaching another session. Local processes are trusted: this is role validation, **not authentication**. No remote networking/proxies/redirects or credentials.
169
+ Kinds: `message`, `report` (`status`, `summary`; configured worker → coordinator only), `registration` (`port`, `projectDirectory`), `status` (`port`, `busy`), `request_status`, `reload`, `stop`, `close` (empty control payload). Sender session identity is the envelope `from`; registration/status agent notifications include an explicit `sessionId` field. Agent messages require configured sender and recipient; controls require the current coordinator's sender ID and a worker recipient. Registration/unknown status are intentional exceptions to configured-sender checks, accepted only by coordinator. All receivers verify expected recipient ID, protecting against stale ports reaching another session. Local processes are trusted: this is role validation, **not authentication**. No remote networking/proxies/redirects or credentials.
113
170
 
114
171
  `202 {"accepted":true}` means Intercom extension receipt/dispatch, **not guaranteed Pi input acceptance, queueing, or model completion**. In Pi 0.84.4, `sendUserMessage` can reject during manual compaction after Intercom has acknowledged receipt: its void extension API reports the asynchronous rejection only as a local host error. Intercom has no delivery queue or retry to repair this gap; inspect the recipient's local error and arrange an explicit resend after compaction if needed. Replacing it with `sendMessage` is not a safe workaround because that path can start a concurrent run. Invalid/unsupported requests return an error; excessive bodies return 413. Request-status sends its report separately after accepting control. Starting in 0.2.1, Intercom always supplies `deliverAs: 'steer'`: Pi starts normally when idle and steers when busy. This avoids the idle-snapshot-to-busy race that caused “Agent is already processing” errors; it does not fix manual-compaction rejection. It does not hard-interrupt an executing tool. Each send resolves the recipient again from config; 5-second receipt deadline, **no retries**. Timeout means unknown outcome, not proof of nondelivery. No durable inbox, deduplication or replay log in V1.
115
172
 
116
173
  Version 0.2.0 telemetry adds an optional envelope `correlationId` for one transport attempt; legacy envelopes without it remain accepted. It is not agent identity, deduplication, a task ID, or a reply/completion guarantee.
117
174
 
118
- Tool text output is bounded to 50 KiB/2000 lines. The full saved roster remains in the shared config file; `dashboardUrl` is derived for list output. Name sync errors are surfaced; startup retains the useful endpoint, and explicit reload reports failure (Pi name/responsibility may already have changed before a Herdr tab rename fails).
175
+ Tool text output is bounded to 50 KiB/2000 lines. The full saved roster remains in the shared config file. Name sync errors are surfaced; startup retains the useful endpoint, and explicit reload reports failure (Pi name/responsibility may already have changed before a Herdr tab rename fails).
119
176
 
120
- ## Local observation dashboard (0.2.0)
177
+ ## Standalone terminal status monitor
121
178
 
122
- Current source adds metadata-only event logs and a coordinator-only, read-only localhost dashboard. Startup binds an OS-assigned port, then saves the actual port as the coordinator's `dashboardPort` and prints the local URL. Configured coordinator and worker sessions can retrieve the saved URL using `intercom_list`—no new dashboard tool or control. Open that URL in a local browser. The saved address can remain stale after shutdown or failure; it is not proof of reachability. Workers log metadata but do not start a dashboard. No browser opens automatically, and no agent controls, assignments or automatic recovery are added.
179
+ The coordinator automatically checks for its monitor pane on startup inside Herdr. If missing, it creates a small pane **above the coordinator**, preserving coordinator focus. This is a standalone Node/pi-tui program, **not another Pi instance**. The old inline widget implementation has been removed. Source installations must run `npm run build` before reloading Pi; published packages include the compiled `dist/monitor.js` entry.
123
180
 
124
- The roster shows saved names/responsibilities/endpoints plus **last-observed** busy/idle, timestamp and age. Evidence older than 60 seconds is marked stale, never offline; missing evidence is unknown. The timeline refreshes approximately every three seconds and can be filtered by agent, event type and errors. Expand events for safe metadata/correlation, not prompt bodies. A disconnected dashboard retains old data with an explicit warning.
181
+ The table uses aligned **Worker | Seen | Status | Report | Last activity** columns (activity detail gives way first on narrow panes). Report is explicitly worker-authored and separate from host activity. Status is the last reported `working`, `thinking`, `idle`, `closed`, or `unknown` state. Seen marks evidence older than 60 seconds with `(old)`; this is not a live connection indicator. Last activity uses fixed public labels such as Reading files, Running command or Writing response and can persist after the worker settles. Recent working/thinking/idle observations use restrained colors; old evidence remains neutral and explicitly marked. `NO_COLOR` disables styling. No read-only banner or busy/idle count summary is shown. It passively reads the same bounded config/log snapshot as the web dashboard about every three seconds, without worker prompts, probing or model calls. Only observed activity is shown, not inferred assignments/completion. Evidence over 60 seconds old is stale; missing evidence is unknown. The number of worker rows adapts to the pane height, with an omitted count when needed. The display is clipped to pane dimensions. In the monitor pane, use **↑/↓** to select a worker and **Enter** to toggle its details (configured responsibility and observed status). Selection follows the worker across roster reorder and scrolls the visible window. **Escape** closes details first, then quits; **q** or **Ctrl+C** always quits only the display process, never agents or their panes.
125
182
 
126
- Logs under `.pi-intercom/logs/` exclude message bodies and raw errors; roster responsibility text still comes from shared config, so do not put secrets there. `writerId` identifies an ephemeral log writer, not an agent; Pi session ID remains agent identity. Transport `correlationId` identifies one send attempt, not a task or completion. Logging is bounded/best effort and does not change HTTP receipt semantics or repair manual-compaction rejection. Never interpret a quiet timeline as completed work.
183
+ Detailed phase reports require reloading participating Pi sessions. `thinking` is emitted only when the provider supplies thinking events; missing thinking events do not imply that no reasoning occurred. Streaming content, reasoning text, command arguments and tool outputs are never read or logged for status. Repeated streaming events are deduplicated; concurrent tools are tracked without recording their arguments. Legacy busy observations display as working without invented detail. No task completion is inferred from settlement.
127
184
 
128
- See [observability reference](references/observability.md) for privacy, rotation/retention limits, partial-error semantics and the HTTP boundary. This feature requires **version 0.2.0 or later**; update the package and reload each participating Pi session to activate it. The dashboard is not a durable inbox, replay log or task journal.
185
+ The pane's display name is simply `Intercom monitor`. Ownership uses saved pane/workspace/coordinator identities in machine-local `.pi-intercom/monitor-*.json` records; the generic display name alone is never proof of ownership. Older session-bearing labels are migrated when their pane is identified. Reload reuses an existing pane without injecting commands into it; pane existence is not proof the monitor is running. If the owner closes the pane, a subsequent coordinator startup can create its replacement. If the monitor program exits but its pane remains, restart it explicitly in that shell: `node /absolute/package/path/dist/monitor.js --root /absolute/project/path`. Moved/ambiguous panes and partial launches require inspection, not blind duplicate creation. A crash can leave a launch lock/pending record: inspect Herdr's panes and these records before manually recovering them. No automatic pane cleanup, focus stealing, or retry is performed.
186
+
187
+ Outside Herdr, messaging continues without a status pane. The browser dashboard is retired; no dashboard listener or browser assets are started/shipped in 0.4.1. A monitor or legacy-metadata cleanup failure does not disable messaging. Reload an older running coordinator to close its former dashboard listener. These features replace the browser dashboard from 0.3.0.
188
+
189
+ ### JSON worker status for agents and chat integrations
190
+
191
+ `intercom_worker_status({})` returns a bounded JSON page of configured workers, or use `{ name: "Builder" }` for one worker. Each entry includes `observedStatus`, `lastActivity`, `observedAt`, `observationAgeSeconds`, `stale`, `evidence`, and an optional public `report` with its independent timestamp/age. Unknown ages/staleness are `null`; conflicting/future observations remain unknown, not healthy. A null report means no readable active report, not proof there are no blockers.
192
+
193
+ The tool uses the **same observation interpretation as the terminal monitor**, reads local files only, and never prompts/probes workers. It has no Telegram dependency: an agent can read the JSON and use its existing chat tools to present a summary. `intercom_list` remains saved configuration; `intercom_request_status` remains an explicit asynchronous live status request.
194
+
195
+ Results include `errors`, `truncated`, `totalInSnapshot`, and `nextOffset`. Use `{ offset: nextOffset }` until it is null. Default page size is 10; `limit` accepts 1–20, with an additional byte budget to keep JSON complete. The snapshot retains at most 256 configured agents; truncation and unavailable observations are explicit. No result is proof of current liveness, coordinator approval, or task completion.
196
+
197
+ ### Worker reports and decisions
198
+
199
+ A configured worker that has loaded its responsibility can call `intercom_report_work`:
200
+
201
+ ```typescript
202
+ intercom_report_work({ status: "blocked", summary: "The test database is unavailable; please provide a test environment or approve using a fixture." })
203
+ intercom_report_work({ status: "needs_decision", summary: "Should the endpoint keep backward compatibility or adopt the new response format?" })
204
+ intercom_report_work({ status: "ready_for_review", summary: "Updated the parser and added three edge-case tests; all pass. Please review before accepting the change." })
205
+ intercom_report_work({ status: "clear" })
206
+ ```
207
+
208
+ There is one latest report per worker. A new report replaces it; clear saves an empty tombstone and removes the report indicator. Summaries are explicitly public, non-secret text (up to 2000 characters). They are sent to the coordinator, may enter its conversation history, and are saved in machine-local `.pi-intercom/reports/`—not in the metadata logs. Do not include private reasoning, credentials or raw tool payloads.
209
+
210
+ The coordinator validates the configured worker identity, saves the report, then submits a notification through the normal message path. Receipt does not prove the coordinator evaluated it. Reports do not automatically approve changes, assign follow-up work, resume a worker, or declare a task complete. Ready for review means **the worker is asking for review**, not that validation has been independently accepted.
211
+
212
+ The monitor shows Report alongside observed Status. Enter opens the worker's current report, age and summary. Reports persist until replaced/cleared and may outlive a process restart; their timestamps are separate from activity age. Missing/unreadable reports show no report indicator, not proof there are no blockers. Removed workers' report files are not shown or automatically deleted. No automatic resend or recovery is added; if saving succeeds but notification fails, inspect the saved report before deciding whether to resend.
213
+
214
+ Reload the coordinator and participating worker Pi sessions to register the tool and new wire handler. Older versions reject the new report kind rather than silently treating it as an ordinary message.
215
+
216
+ ## Local observation data
217
+
218
+ The terminal monitor reads bounded metadata logs from `.pi-intercom/logs/` and names/responsibilities from shared configuration. It does not expose a web server. Logs exclude message bodies, reasoning text, tool payloads and raw errors. Keep sensitive information out of responsibility text.
219
+
220
+ Observations remain best effort: an old record is not a current heartbeat, a quiet log is not task completion, and transport receipt is not proof that Pi accepted or acted on a message. See the [observability reference](references/observability.md) for privacy, retention, snapshot bounds and legacy-dashboard migration.
221
+
222
+ The browser dashboard was part of published 0.2.x/0.3.0. Historical validation notes below refer to those releases, not the current terminal-only monitor.
129
223
 
130
224
  ## Development and validation
131
225
 
@@ -140,16 +234,34 @@ npm run check:package
140
234
  PI_INTERCOM_PI_ROOT='C:/path/to/pi-coding-agent' npm run test:host
141
235
  ```
142
236
 
143
- Production source runs through Pi's TypeScript loader; `npm run build` generates `dist` for tests. Pi core/typebox are peer dependencies, not bundled; pinned development copies are included in the lockfile for reproducible CI without local junctions.
237
+ The extension source runs through Pi's TypeScript loader; `npm run build` generates `dist` for tests and the standalone terminal monitor. Build output is included in releases; the publish job builds it explicitly before publishing with scripts disabled. `npm run check:package` also installs the tarball in an isolated directory with peer installation disabled (matching Pi's managed npm installs), verifies the standalone monitor imports without host packages, and checks its non-TTY error path. This network-dependent regression runs on both CI platforms; it does not claim a live terminal/Herdr smoke test. Pi core/typebox are peer dependencies, not bundled; pinned development copies are included in the lockfile for reproducible CI without local junctions.
144
238
 
145
239
  ## Publishing
146
240
 
147
241
  [`.github/workflows/publish.yml`](https://github.com/comput-sh/pi-intercom/blob/main/.github/workflows/publish.yml) publishes through npm Trusted Publishing (GitHub OIDC), without an npm token secret. Configure the npm trusted publisher as owner `comput-sh`, repository `pi-intercom`, workflow `publish.yml`, with no environment.
148
242
 
149
- The workflow validates on Windows, then publishes with provenance from a GitHub-hosted Ubuntu runner. It runs when a GitHub release is published or when manually dispatched. Release tags must be `v<package.json version>`.
243
+ The workflow validates on Windows and Linux, then publishes with provenance from a GitHub-hosted Ubuntu runner. It runs when a GitHub release is published or when manually dispatched. Release tags must be `v<package.json version>`.
150
244
 
151
245
  Published versions are immutable. For a new release, bump package and lockfile versions, commit/push, then publish a matching GitHub release. Manual dispatch publishes the selected ref and is **not a dry run**; the release-tag check only applies when a release tag is present. Do not dispatch publishing for an already published version. CI validates pushes to `main` and pull requests separately without publishing.
152
246
 
247
+ ### 0.4.2 Standalone monitor dependency fix
248
+
249
+ - Install a pinned TUI runtime dependency for the standalone monitor, independent of Pi's host-provided extension peers. Fixes `ERR_MODULE_NOT_FOUND` after managed Pi installs that disable peer installation.
250
+ - Add isolated tarball-install validation with peers disabled, module-import checks and the non-TTY CLI check to Windows/Linux package CI.
251
+ - Require Node 22.19+ to match the monitor dependency. Config-root discovery is unchanged by this patch.
252
+ - Upgrade the npm package, reload Pi sessions, and restart an existing monitor process to load the fix.
253
+
254
+ ### 0.4.1 Coordinator workspace
255
+
256
+ The 0.4.0 GitHub release did not reach npm because a Windows-specific test expectation failed. 0.4.1 corrects that assertion without changing parser behavior; the 0.4.0 tag remains unchanged.
257
+
258
+ - Standalone Herdr terminal monitor replaces the browser dashboard; automatic pane ownership/reuse, keyboard selection and worker details.
259
+ - Explicit public worker reports: blocked, needs decision, ready for review and clear; no automatic approvals or assignments.
260
+ - Read-only, paginated `intercom_worker_status` JSON shares observation interpretation with the monitor. No chat integration dependency.
261
+ - Detailed public activity phases, bounded local snapshots and report storage, packaged monitor build output.
262
+ - Typecheck and 112 tests passed locally. Stop/close remain disabled; no new cancellation guarantee.
263
+ - Upgrade: update the package and reload coordinator/workers. Restart an existing standalone monitor to load new display code. Legacy dashboard metadata is migrated on coordinator startup.
264
+
153
265
  ### 0.3.0 Linux support
154
266
 
155
267
  - Interactive startup, messaging and dashboard support on Linux.
@@ -0,0 +1,12 @@
1
+ /** Public event categories only: never accept content, arguments, or results. */
2
+ export type ActivityPhase = 'working' | 'thinking' | 'responding' | 'tool' | 'idle';
3
+ export type ActivityDetail = 'processing' | 'thinking' | 'responding' | 'reading_files' | 'editing_files' | 'running_command' | 'using_tool' | 'multiple_tools' | 'settled';
4
+ /** Stores only opaque active tool IDs, public categories, and the last emitted state. */
5
+ export declare function createActivityTracker(record: (phase: ActivityPhase, detail: ActivityDetail) => void): {
6
+ start(): void;
7
+ settled(): void;
8
+ message(type: string): void;
9
+ toolStart(id: string, name: string): void;
10
+ toolEnd(id: string): void;
11
+ reset(): void;
12
+ };
@@ -0,0 +1,73 @@
1
+ function toolDetail(name) {
2
+ switch (name) {
3
+ case 'read': return 'reading_files';
4
+ case 'edit':
5
+ case 'write': return 'editing_files';
6
+ case 'bash':
7
+ case 'powershell': return 'running_command';
8
+ default: return 'using_tool';
9
+ }
10
+ }
11
+ /** Stores only opaque active tool IDs, public categories, and the last emitted state. */
12
+ export function createActivityTracker(record) {
13
+ const tools = new Map();
14
+ let lastPhase;
15
+ let lastDetail;
16
+ function emit(phase, detail) {
17
+ if (lastPhase === phase && lastDetail === detail)
18
+ return;
19
+ lastPhase = phase;
20
+ lastDetail = detail;
21
+ record(phase, detail);
22
+ }
23
+ function emitTools() {
24
+ const detail = tools.size > 1 ? 'multiple_tools' : tools.values().next().value;
25
+ if (detail)
26
+ emit('tool', detail);
27
+ }
28
+ return {
29
+ start() {
30
+ tools.clear();
31
+ emit('working', 'processing');
32
+ },
33
+ settled() {
34
+ tools.clear();
35
+ emit('idle', 'settled');
36
+ },
37
+ message(type) {
38
+ if (tools.size)
39
+ return;
40
+ switch (type) {
41
+ case 'thinking_start':
42
+ case 'thinking_delta':
43
+ emit('thinking', 'thinking');
44
+ break;
45
+ case 'thinking_end':
46
+ emit('working', 'processing');
47
+ break;
48
+ case 'text_start':
49
+ case 'text_delta':
50
+ emit('responding', 'responding');
51
+ break;
52
+ }
53
+ },
54
+ toolStart(id, name) {
55
+ tools.set(id, toolDetail(name));
56
+ emitTools();
57
+ },
58
+ toolEnd(id) {
59
+ if (!tools.delete(id))
60
+ return;
61
+ if (tools.size)
62
+ emitTools();
63
+ else
64
+ emit('working', 'processing');
65
+ },
66
+ reset() {
67
+ tools.clear();
68
+ lastPhase = undefined;
69
+ lastDetail = undefined;
70
+ },
71
+ };
72
+ }
73
+ //# sourceMappingURL=activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.js","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAKA,SAAS,UAAU,CAAC,IAAY;IAC9B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM,CAAC,CAAC,OAAO,eAAe,CAAC;QACpC,KAAK,MAAM,CAAC;QACZ,KAAK,OAAO,CAAC,CAAC,OAAO,eAAe,CAAC;QACrC,KAAK,MAAM,CAAC;QACZ,KAAK,YAAY,CAAC,CAAC,OAAO,iBAAiB,CAAC;QAC5C,OAAO,CAAC,CAAC,OAAO,YAAY,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,qBAAqB,CAAC,MAA8D;IAClG,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAChD,IAAI,SAAoC,CAAC;IACzC,IAAI,UAAsC,CAAC;IAC3C,SAAS,IAAI,CAAC,KAAoB,EAAE,MAAsB;QACxD,IAAI,SAAS,KAAK,KAAK,IAAI,UAAU,KAAK,MAAM;YAAE,OAAO;QACzD,SAAS,GAAG,KAAK,CAAC;QAClB,UAAU,GAAG,MAAM,CAAC;QACpB,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACxB,CAAC;IACD,SAAS,SAAS;QAChB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC/E,IAAI,MAAM;YAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IACD,OAAO;QACL,KAAK;YACH,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAChC,CAAC;QACD,OAAO;YACL,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,CAAC,IAAY;YAClB,IAAI,KAAK,CAAC,IAAI;gBAAE,OAAO;YACvB,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,gBAAgB,CAAC;gBACtB,KAAK,gBAAgB;oBAAE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;oBAAC,MAAM;gBAC3D,KAAK,cAAc;oBAAE,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;oBAAC,MAAM;gBAC1D,KAAK,YAAY,CAAC;gBAClB,KAAK,YAAY;oBAAE,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;oBAAC,MAAM;YAC7D,CAAC;QACH,CAAC;QACD,SAAS,CAAC,EAAU,EAAE,IAAY;YAChC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;YAChC,SAAS,EAAE,CAAC;QACd,CAAC;QACD,OAAO,CAAC,EAAU;YAChB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;gBAAE,OAAO;YAC9B,IAAI,KAAK,CAAC,IAAI;gBAAE,SAAS,EAAE,CAAC;;gBACvB,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACrC,CAAC;QACD,KAAK;YACH,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,SAAS,GAAG,SAAS,CAAC;YACtB,UAAU,GAAG,SAAS,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,39 @@
1
+ export interface Agent {
2
+ sessionId: string;
3
+ name: string;
4
+ coordinator: boolean;
5
+ description: string;
6
+ port: number;
7
+ /** Legacy browser dashboard field, accepted for migration only; removed at coordinator startup. */
8
+ dashboardPort?: number;
9
+ projectDirectory: string;
10
+ }
11
+ export interface Config {
12
+ version: 1;
13
+ multiplexer: 'herdr' | 'none';
14
+ agents: Agent[];
15
+ }
16
+ export declare const DEFAULT_DESCRIPTION = "Coordinate workers, delegate work, and manage shared configuration.";
17
+ export declare const key: (name: string) => string;
18
+ export declare function fail(message: string): never;
19
+ export declare function text(value: unknown, field: string, max?: number): asserts value is string;
20
+ export declare function port(value: unknown): asserts value is number;
21
+ export declare function relativeDirectory(value: unknown): asserts value is string;
22
+ export declare function validateConfig(value: unknown): Config;
23
+ export declare const coordinator: (c: Config) => Agent;
24
+ export declare function named(c: Config, name: string): Agent;
25
+ export declare function requireCoordinator(c: Config, id: string): Agent;
26
+ export declare function directory(root: string, requested: string): Promise<string>;
27
+ export declare class ConfigStore {
28
+ readonly root: string;
29
+ readonly file: string;
30
+ private tail;
31
+ constructor(root: string);
32
+ read(): Promise<Config>;
33
+ static discover(cwd: string): Promise<ConfigStore | undefined>;
34
+ protected openTemporary(file: string): Promise<import("fs/promises").FileHandle>;
35
+ private temporary;
36
+ initialize(id: string, boundPort: number, assertValid?: () => void): Promise<boolean>;
37
+ update(id: string, mutate: (config: Config) => void | Promise<void>, assertValid?: () => void): Promise<Config>;
38
+ configure(id: string, values: Omit<Agent, 'coordinator'>, assertValid?: () => void): Promise<Config>;
39
+ }
package/dist/config.js ADDED
@@ -0,0 +1,182 @@
1
+ import { mkdir, readFile, realpath, rename, unlink, open, link, stat } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ export const DEFAULT_DESCRIPTION = 'Coordinate workers, delegate work, and manage shared configuration.';
5
+ export const key = (name) => name.toLowerCase();
6
+ export function fail(message) { throw new Error(`PiIntercom: ${message}`); }
7
+ export function text(value, field, max = 4096) {
8
+ if (typeof value !== 'string' || !value.trim() || value.length > max || value.includes('\0'))
9
+ fail(`invalid ${field}`);
10
+ }
11
+ export function port(value) {
12
+ if (!Number.isInteger(value) || Number(value) < 1 || Number(value) > 65535)
13
+ fail('invalid port');
14
+ }
15
+ export function relativeDirectory(value) {
16
+ text(value, 'projectDirectory');
17
+ if (path.isAbsolute(value) || path.win32.isAbsolute(value) || value.split(/[\\/]/).includes('..'))
18
+ fail('projectDirectory must be root-relative, without ..');
19
+ }
20
+ export function validateConfig(value) {
21
+ const c = value;
22
+ if (!c || c.version !== 1 || !['herdr', 'none'].includes(c.multiplexer) || !Array.isArray(c.agents))
23
+ fail('invalid config schema/version');
24
+ const names = new Set(), ids = new Set();
25
+ for (const a of c.agents) {
26
+ if (!a || typeof a.coordinator !== 'boolean')
27
+ fail('invalid agent');
28
+ text(a.sessionId, 'sessionId', 256);
29
+ text(a.name, 'name', 128);
30
+ text(a.description, 'description');
31
+ if (a.name !== a.name.trim() || /[\r\n\x00-\x1f]/.test(a.name))
32
+ fail('invalid name');
33
+ port(a.port);
34
+ relativeDirectory(a.projectDirectory);
35
+ if (a.dashboardPort !== undefined) {
36
+ if (!a.coordinator)
37
+ fail('dashboardPort is coordinator-only');
38
+ port(a.dashboardPort);
39
+ }
40
+ if (names.has(key(a.name)) || ids.has(a.sessionId))
41
+ fail('duplicate name or session ID');
42
+ names.add(key(a.name));
43
+ ids.add(a.sessionId);
44
+ if (a.coordinator ? (a.name !== 'Coordinator' || a.projectDirectory !== '.') : key(a.name) === 'coordinator')
45
+ fail('reserved Coordinator identity');
46
+ }
47
+ if (c.agents.filter(a => a.coordinator).length !== 1)
48
+ fail('config requires exactly one coordinator');
49
+ return c;
50
+ }
51
+ export const coordinator = (c) => c.agents.find(a => a.coordinator);
52
+ export function named(c, name) {
53
+ text(name, 'to', 128);
54
+ return c.agents.find(a => key(a.name) === key(name)) ?? fail(`unknown recipient ${name}`);
55
+ }
56
+ export function requireCoordinator(c, id) {
57
+ const a = c.agents.find(a => a.sessionId === id);
58
+ return a?.coordinator ? a : fail('coordinator permission required');
59
+ }
60
+ export async function directory(root, requested) {
61
+ text(requested, 'projectDirectory');
62
+ const base = await realpath(root), target = await realpath(path.resolve(root, requested));
63
+ const rel = path.relative(base, target);
64
+ if (rel === '..' || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel))
65
+ fail('project directory must be coordinator root or descendant (including symlinks)');
66
+ if (!(await stat(target)).isDirectory())
67
+ fail('projectDirectory is not a directory');
68
+ return rel.split(path.sep).join('/') || '.';
69
+ }
70
+ export class ConfigStore {
71
+ root;
72
+ file;
73
+ tail = Promise.resolve();
74
+ constructor(root) {
75
+ this.root = root;
76
+ this.file = path.join(root, '.pi-intercom', 'config.json');
77
+ }
78
+ async read() {
79
+ // Missing, malformed and unreadable files propagate; never overwrite them.
80
+ return validateConfig(JSON.parse(await readFile(this.file, 'utf8')));
81
+ }
82
+ static async discover(cwd) {
83
+ let at = path.resolve(cwd);
84
+ for (;;) {
85
+ const store = new ConfigStore(at);
86
+ try {
87
+ await store.read();
88
+ return store;
89
+ }
90
+ catch (error) {
91
+ if (error.code !== 'ENOENT')
92
+ throw error;
93
+ }
94
+ const parent = path.dirname(at);
95
+ if (parent === at)
96
+ return undefined;
97
+ at = parent;
98
+ }
99
+ }
100
+ openTemporary(file) { return open(file, 'wx'); }
101
+ async temporary(config) {
102
+ validateConfig(config);
103
+ await mkdir(path.dirname(this.file), { recursive: true });
104
+ const temp = `${this.file}.${randomUUID()}.tmp`;
105
+ const handle = await this.openTemporary(temp);
106
+ try {
107
+ await handle.writeFile(JSON.stringify(config, null, 2) + '\n');
108
+ await handle.sync();
109
+ await handle.close();
110
+ return temp;
111
+ }
112
+ catch (error) {
113
+ // Cleanup failures must not replace the original write/sync/close error.
114
+ await handle.close().catch(() => { });
115
+ await unlink(temp).catch(() => { });
116
+ throw error;
117
+ }
118
+ }
119
+ async initialize(id, boundPort, assertValid = () => { }) {
120
+ // Publish an already complete file using an atomic, no-replace hard link.
121
+ // Losers only ever see complete JSON; unsupported filesystems fail explicitly.
122
+ assertValid();
123
+ const temp = await this.temporary({ version: 1, multiplexer: 'herdr', agents: [{ sessionId: id, name: 'Coordinator', coordinator: true, description: DEFAULT_DESCRIPTION, port: boundPort, projectDirectory: '.' }] });
124
+ try {
125
+ assertValid();
126
+ try {
127
+ await link(temp, this.file);
128
+ }
129
+ catch (e) {
130
+ if (e.code !== 'EEXIST')
131
+ throw e;
132
+ await this.read();
133
+ await unlink(temp);
134
+ return false;
135
+ }
136
+ await unlink(temp);
137
+ return true;
138
+ }
139
+ catch (error) {
140
+ await unlink(temp).catch(() => { });
141
+ throw error;
142
+ }
143
+ }
144
+ async update(id, mutate, assertValid = () => { }) {
145
+ const operation = this.tail.then(async () => {
146
+ assertValid();
147
+ const c = await this.read();
148
+ assertValid();
149
+ requireCoordinator(c, id);
150
+ await mutate(c);
151
+ assertValid();
152
+ validateConfig(c);
153
+ const temp = await this.temporary(c);
154
+ try {
155
+ // Last check before publication; an already submitted OS rename cannot be undone.
156
+ assertValid();
157
+ await rename(temp, this.file);
158
+ }
159
+ catch (error) {
160
+ await unlink(temp).catch(() => { });
161
+ throw error;
162
+ }
163
+ return c;
164
+ });
165
+ this.tail = operation.catch(() => { });
166
+ return operation;
167
+ }
168
+ async configure(id, values, assertValid = () => { }) {
169
+ return this.update(id, async (c) => {
170
+ if (values.sessionId === coordinator(c).sessionId)
171
+ fail('cannot configure coordinator as worker');
172
+ const projectDirectory = await directory(this.root, values.projectDirectory);
173
+ const a = { sessionId: values.sessionId, name: values.name, description: values.description, port: values.port, projectDirectory, coordinator: false };
174
+ const index = c.agents.findIndex(old => old.sessionId === a.sessionId);
175
+ if (index < 0)
176
+ c.agents.push(a);
177
+ else
178
+ c.agents[index] = a;
179
+ }, assertValid);
180
+ }
181
+ }
182
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAazC,MAAM,CAAC,MAAM,mBAAmB,GAAG,qEAAqE,CAAC;AACzG,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;AACxD,MAAM,UAAU,IAAI,CAAC,OAAe,IAAW,MAAM,IAAI,KAAK,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3F,MAAM,UAAU,IAAI,CAAC,KAAc,EAAE,KAAa,EAAE,GAAG,GAAG,IAAI;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,IAAI,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;AACzH,CAAC;AACD,MAAM,UAAU,IAAI,CAAC,KAAc;IACjC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK;QAAE,IAAI,CAAC,cAAc,CAAC,CAAC;AACnG,CAAC;AACD,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAChC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,IAAI,CAAC,oDAAoD,CAAC,CAAC;AAChK,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,MAAM,CAAC,GAAG,KAAe,CAAC;IAC1B,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QAAE,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC3I,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,EAAE,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,SAAS;YAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QACpE,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QACnG,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QACrF,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAAC,iBAAiB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;QACpD,IAAI,CAAC,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC,CAAC,CAAC,WAAW;gBAAE,IAAI,CAAC,mCAAmC,CAAC,CAAC;YAC9D,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;QACxB,CAAC;QACD,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;YAAE,IAAI,CAAC,8BAA8B,CAAC,CAAC;QACzF,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,gBAAgB,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,aAAa;YAAE,IAAI,CAAC,+BAA+B,CAAC,CAAC;IACtJ,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,IAAI,CAAC,yCAAyC,CAAC,CAAC;IACtG,OAAO,CAAC,CAAC;AACX,CAAC;AACD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAE,CAAC;AAC7E,MAAM,UAAU,KAAK,CAAC,CAAS,EAAE,IAAY;IAC3C,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACtB,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;AAC5F,CAAC;AACD,MAAM,UAAU,kBAAkB,CAAC,CAAS,EAAE,EAAU;IACtD,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;AACtE,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,SAAiB;IAC7D,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IAC1F,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,IAAI,CAAC,+EAA+E,CAAC,CAAC;IACnK,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE;QAAE,IAAI,CAAC,qCAAqC,CAAC,CAAC;IACrF,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;AAC9C,CAAC;AACD,MAAM,OAAO,WAAW;IAGD;IAFZ,IAAI,CAAS;IACd,IAAI,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IACnD,YAAqB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;IAAC,CAAC;IAClG,KAAK,CAAC,IAAI;QACR,2EAA2E;QAC3E,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAW;QAC/B,IAAI,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3B,SAAS,CAAC;YACR,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC;YAClC,IAAI,CAAC;gBAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;gBAAC,OAAO,KAAK,CAAC;YAAC,CAAC;YACzC,OAAO,KAAK,EAAE,CAAC;gBAAC,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;oBAAE,MAAM,KAAK,CAAC;YAAC,CAAC;YACtF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAAC,IAAI,MAAM,KAAK,EAAE;gBAAE,OAAO,SAAS,CAAC;YAAC,EAAE,GAAG,MAAM,CAAC;QACpF,CAAC;IACH,CAAC;IACS,aAAa,CAAC,IAAY,IAAI,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1D,KAAK,CAAC,SAAS,CAAC,MAAc;QACpC,cAAc,CAAC,MAAM,CAAC,CAAC;QACvB,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,UAAU,EAAE,MAAM,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;YAC/D,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yEAAyE;YACzE,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACrC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACnC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,SAAiB,EAAE,cAA0B,GAAG,EAAE,GAAE,CAAC;QAChF,0EAA0E;QAC1E,+EAA+E;QAC/E,WAAW,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACvN,IAAI,CAAC;YACH,WAAW,EAAE,CAAC;YACd,IAAI,CAAC;gBAAC,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAAC,CAAC;YACpC,OAAO,CAAC,EAAE,CAAC;gBACT,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ;oBAAE,MAAM,CAAC,CAAC;gBAC5D,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gBAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;gBAAC,OAAO,KAAK,CAAC;YACtD,CAAC;YACD,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAAC,MAAM,KAAK,CAAC;QAAC,CAAC;IACtE,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,MAAgD,EAAE,cAA0B,GAAG,EAAE,GAAE,CAAC;QAC3G,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YAC1C,WAAW,EAAE,CAAC;YACd,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,WAAW,EAAE,CAAC;YAAC,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACtE,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC;YAAC,WAAW,EAAE,CAAC;YAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACrC,IAAI,CAAC;gBACH,kFAAkF;gBAClF,WAAW,EAAE,CAAC;gBAAC,MAAM,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBAAC,MAAM,KAAK,CAAC;YAAC,CAAC;YACpE,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAAC,OAAO,SAAS,CAAC;IAC1D,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,EAAU,EAAE,MAAkC,EAAE,cAA0B,GAAG,EAAE,GAAE,CAAC;QAChG,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;YAC/B,IAAI,MAAM,CAAC,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS;gBAAE,IAAI,CAAC,wCAAwC,CAAC,CAAC;YAClG,MAAM,gBAAgB,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAC7E,MAAM,CAAC,GAAU,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;YAC9J,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC;YACvE,IAAI,KAAK,GAAG,CAAC;gBAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;gBAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5D,CAAC,EAAE,WAAW,CAAC,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ import { type ExtensionAPI } from '@earendil-works/pi-coding-agent';
2
+ export declare function resumeSessionDirectory(cwd: string, envSessionDir?: string | undefined, agentDir?: string): string | undefined;
3
+ export default function intercomExtension(pi: ExtensionAPI): void;