@comput/pi-intercom 0.5.2 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -15
- package/dist/config.d.ts +18 -1
- package/dist/config.js +141 -27
- package/dist/config.js.map +1 -1
- package/dist/handoff.d.ts +87 -0
- package/dist/handoff.js +327 -0
- package/dist/handoff.js.map +1 -0
- package/dist/index.js +92 -17
- package/dist/index.js.map +1 -1
- package/dist/launcher.js +11 -1
- package/dist/launcher.js.map +1 -1
- package/dist/monitor-view.d.ts +1 -1
- package/dist/monitor-view.js +31 -2
- package/dist/monitor-view.js.map +1 -1
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +1 -1
- package/dist/observability.js.map +1 -1
- package/dist/pane-close.d.ts +22 -0
- package/dist/pane-close.js +166 -0
- package/dist/pane-close.js.map +1 -0
- package/dist/reminders.d.ts +28 -0
- package/dist/reminders.js +81 -0
- package/dist/reminders.js.map +1 -0
- package/dist/runtime.d.ts +19 -2
- package/dist/runtime.js +163 -16
- package/dist/runtime.js.map +1 -1
- package/dist/snapshot.d.ts +9 -0
- package/dist/snapshot.js +23 -1
- package/dist/snapshot.js.map +1 -1
- package/dist/transport.d.ts +2 -1
- package/dist/transport.js +4 -1
- package/dist/transport.js.map +1 -1
- package/dist/worker-status.d.ts +1 -1
- package/dist/worker-status.js +9 -1
- package/dist/worker-status.js.map +1 -1
- package/package.json +12 -6
- package/references/implementation-blocker.md +1 -1
- package/references/observability.md +13 -3
- package/references/releasing.md +90 -0
- package/references/v1-specification.md +4 -4
- package/src/config.ts +107 -19
- package/src/handoff.ts +280 -0
- package/src/index.ts +75 -15
- package/src/launcher.ts +9 -1
- package/src/monitor-view.ts +30 -3
- package/src/observability.ts +1 -1
- package/src/pane-close.ts +138 -0
- package/src/reminders.ts +69 -0
- package/src/runtime.ts +138 -18
- package/src/snapshot.ts +22 -1
- package/src/transport.ts +4 -2
- package/src/worker-status.ts +9 -2
package/README.md
CHANGED
|
@@ -25,6 +25,12 @@ The value is the loop: **delegate → report back → evaluate → decide the ne
|
|
|
25
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
26
|
>
|
|
27
27
|
> **0.5.1:** manually closed workers remain registered and sort last as disconnected in the monitor. Optional JSON health checks and guarded resume preserve the distinction between connectivity and saved session identity.
|
|
28
|
+
>
|
|
29
|
+
> **0.8.0:** Config is restricted to the session working directory. No parent search or explicit-parent override; shared-config subfolder launches are refused.
|
|
30
|
+
|
|
31
|
+
> **0.7.0:** Coordinator-local five-minute reminders follow worker calls. Use `intercom_stop_reminders` when nothing needs follow-up. Busy periods are skipped; shutdown/reload clears the timer.
|
|
32
|
+
|
|
33
|
+
> **0.6.1:** Linux Herdr background save-handoff-and-close workflow, with saved public summaries in config and monitor/JSON details. Empty rosters no longer open a monitor; coordinator session/tab names are preserved.
|
|
28
34
|
|
|
29
35
|
For potential next steps, see [Improvement topics](references/roadmap.md). These are proposals for discussion, not implemented features or release commitments.
|
|
30
36
|
|
|
@@ -64,7 +70,7 @@ Open Pi inside a Herdr workspace at the project root you want to coordinate, or
|
|
|
64
70
|
|
|
65
71
|
### Know the boundaries
|
|
66
72
|
|
|
67
|
-
- **
|
|
73
|
+
- **Graceful stop remains disabled.** Pi 0.84.4's cancellation behavior leaves retry continuations alive; newer versions are not assumed safe without verification. The Linux Herdr `close_worker` in 0.6.1 has a different contract: request/save a handoff, await final settlement, then attempt an identity-checked external pane close. It does not use Pi abort/shutdown or promise all descendants terminate. Manual closure remains available. See the [cancellation blocker](references/implementation-blocker.md).
|
|
68
74
|
- **No silent recovery.** Intercom does not automatically retry messages, replace workers, switch launchers, commit changes, or roll them back.
|
|
69
75
|
- **Local, not remote.** Messaging binds to loopback. Local processes are trusted; this is not an authenticated service for untrusted clients.
|
|
70
76
|
|
|
@@ -94,17 +100,21 @@ Replace the final path with your checkout's absolute path (use a Windows path on
|
|
|
94
100
|
|
|
95
101
|
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.
|
|
96
102
|
|
|
97
|
-
Linux `multiplexer: none` is explicitly unsupported: no terminal guessing, headless fallback, or automatic cleanup.
|
|
103
|
+
Linux `multiplexer: none` is explicitly unsupported: no terminal guessing, headless fallback, or automatic cleanup. Graceful stop remains disabled on both platforms; external pane closure is Linux Herdr only. 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.
|
|
98
104
|
|
|
99
105
|
### Startup and launchers
|
|
100
106
|
|
|
101
|
-
|
|
107
|
+
**Strict root isolation (0.8.0):** The session's starting working directory is its config root. An explicit flag cannot widen this boundary. Only `<root>/.pi-intercom/config.json` is considered: there is no upward search, Git-root inference, or home-directory fallback. If that exact config is absent, startup creates a local coordinator config, opens a loopback listener, preserves the session/tab name, and waits for user input (no model turn). Invalid/unreadable local config is an error and is not overwritten. A session ID absent from an existing selected config, including a fork, is a worker, never a replacement coordinator.
|
|
108
|
+
|
|
109
|
+
Created/resumed workers receive `--intercom-root /absolute/session/root` explicitly as a same-directory assertion, **not permission to read a parent config**. The supplied root must canonically equal the session working directory, and its exact config must already exist. A mismatched root is rejected before reading its config or creating startup resources. No environment variable selects a parent root. Shared-roster workers must start in the coordinator's root; create/resume requests for subfolders are rejected before launch instead of silently changing the working directory. Linked metadata/config paths that escape the root and stable redirects of an already validated root are rejected. Monitor/logging readers retain stricter rules and may reject even internal links. These guards cover config access and temporary-config cleanup. They do not sandbox all filesystem I/O, pin an already-running telemetry writer after filesystem changes, or provide an atomic defense against concurrent filesystem replacement.
|
|
110
|
+
|
|
111
|
+
**Upgrade note:** Existing subfolder workers cannot rejoin a parent roster by supplying a flag. Their saved history/config entries are retained, but launching them in a subfolder with the parent's config is refused. Use workers whose configured directory is the coordinator root, and explicitly describe any subfolder work in their assignment. Independent sessions started in subfolders use only their own local config; ancestor files are left untouched.
|
|
102
112
|
|
|
103
113
|
Default launcher `herdr` requires the coordinator to be inside Herdr (`HERDR_ENV=1` and workspace context), with `herdr` on PATH. Windows needs `powershell.exe` plus `pi.ps1` in the worker pane; Linux needs `sh` plus `pi`. Each worker gets **one tab, one pane, no split, no focus change**. The Windows-only `none` launcher requires `pi.cmd` and Windows PowerShell on PATH and opens a separate visible PowerShell terminal. Missing launcher is an error, not fallback. Launch acknowledgment means command submission/terminal creation, not Pi readiness. A failed launch can leave a tab or process behind; no automatic cleanup occurs. See the scoped live evidence below.
|
|
104
114
|
|
|
105
115
|
## Explicit workflow
|
|
106
116
|
|
|
107
|
-
1. Coordinator calls `intercom_create_worker({projectDirectory:"."})`.
|
|
117
|
+
1. Coordinator calls `intercom_create_worker({projectDirectory:"."})`. The launcher passes the same-directory root assertion; no worker identity, responsibility or callback address is passed.
|
|
108
118
|
2. Anonymous worker opens its own endpoint and sends its session ID, actual port and root-relative project directory to coordinator Pi. Registration starts a normal coordinator turn when idle or queues steering when busy. It creates **no config entry or hidden pending-registration map**.
|
|
109
119
|
3. Coordinator decides and calls `intercom_configure_worker` with **all five explicit fields**: `sessionId`, `port`, `projectDirectory`, `name`, `description`. This only writes config.
|
|
110
120
|
4. Coordinator separately calls `intercom_reload_worker({to:"Builder"})`. Worker rereads responsibility and synchronizes Pi/Herdr tab names. **This is not Pi `/reload`, a restart, cancellation, or work assignment.** No model turn starts.
|
|
@@ -115,28 +125,52 @@ Existing workers restore responsibility by session ID, bind their saved port or,
|
|
|
115
125
|
|
|
116
126
|
## Tools and permissions
|
|
117
127
|
|
|
118
|
-
Every tool rereads current config and checks the live Pi session ID. Names are case-insensitive for lookup/uniqueness; display capitalization is preserved. `Coordinator` is reserved.
|
|
128
|
+
Every tool rereads current config and checks the live Pi session ID. Names are case-insensitive for lookup/uniqueness; display capitalization is preserved. `Coordinator` is reserved for internal configuration/routing. The coordinator's existing Pi session name and Herdr tab title are preserved; only worker sessions are synchronized to their configured names.
|
|
119
129
|
|
|
120
130
|
| Tool | Arguments | Permission / effect |
|
|
121
131
|
|---|---|---|
|
|
122
|
-
| `intercom_create_worker` | `projectDirectory?` (default `.`) | Coordinator; launch anonymous worker |
|
|
132
|
+
| `intercom_create_worker` | `projectDirectory?` (default `.`) | Coordinator; launch anonymous worker at the same root only |
|
|
123
133
|
| `intercom_configure_worker` | `sessionId`, `port`, `projectDirectory`, `name`, `description` | Coordinator; all five explicit fields, writes only |
|
|
124
134
|
| `intercom_reload_worker` | `to` (worker name) | Coordinator; passive config/name reload |
|
|
125
135
|
| `intercom_send` | `to` (name), `message` | Configured, responsibility-loaded sessions; asynchronous message |
|
|
126
136
|
| `intercom_list` | None | Configured coordinator/workers; saved roster, never live health |
|
|
127
137
|
| `intercom_worker_status` | `name?`, `offset?`, `limit?`, `probe?` | Configured sessions; local JSON by default, optional bounded endpoint checks for returned page |
|
|
128
138
|
| `intercom_request_status` | `to` (worker name) | Coordinator; independent extension report |
|
|
139
|
+
| `intercom_stop_reminders` | None | Coordinator; disable reminder timer until another qualifying worker call, without cancelling work |
|
|
129
140
|
| `intercom_report_status` | None | Workers including anonymous; shared report function, never registration |
|
|
130
141
|
| `intercom_report_work` | `status`, `summary?` | Configured, responsibility-loaded workers; save a public report and notify coordinator, never approve/complete work |
|
|
131
|
-
| `intercom_stop_worker
|
|
142
|
+
| `intercom_stop_worker` | `to` | Unsupported graceful cancellation; no side effects |
|
|
143
|
+
| `intercom_close_worker` | `to` | Linux Herdr coordinator; request background handoff/save/settle/pane-close job, retain registration |
|
|
144
|
+
| `intercom_report_handoff` | `jobId`, `summary` | Requested worker only; save concise public handoff, then finish the turn and wait |
|
|
132
145
|
| `intercom_resume_worker` | `to`, `confirmClosed` | Coordinator; user-confirmed old-session closure, saved session/launcher/directory, guarded launch |
|
|
133
146
|
| `intercom_remove_worker` | `to` (worker name) | Coordinator; config entry only, no shutdown/session deletion |
|
|
134
147
|
| `intercom_set_multiplexer` | `multiplexer`: `herdr` or `none` | Coordinator; future launches only |
|
|
135
148
|
|
|
136
|
-
**Removal precondition:**
|
|
149
|
+
**Removal precondition:** close a running worker before removing its entry. Removal forgets the registration; it is not how to park a worker for later resume. Active/uncertain close jobs fence removal and other lifecycle/work operations. Saved IDs/ports alone do not prove closure; no force-kill fallback occurs.
|
|
137
150
|
|
|
138
151
|
Anonymous `send`/`list` and all coordinator operations fail explicitly. Anonymous registration and status remain available. A dedicated repeat-registration operation and broader anonymous permissions remain **unresolved contract TODOs**, not silently added tools. If initial registration fails, the worker remains reachable and reports the error locally. Explicit user Pi `/reload` restarts this extension and repeats startup registration; status is not a substitute and there is no automatic retry.
|
|
139
152
|
|
|
153
|
+
### Coordinator reminders (0.7.0)
|
|
154
|
+
|
|
155
|
+
A coordinator-local timer wakes an idle agent to review delegated work. It is **not** an endpoint health ping, task assignment, worker retry, or crashed-process watchdog. It starts disarmed and does not change shared config or the wire protocol.
|
|
156
|
+
|
|
157
|
+
- Valid coordinator calls to create, configure, resume, reload, request status from, message, or close a worker start/reset the timer **before the attempted operation**. A subsequent operation failure can still need follow-up, so it does not automatically cancel the timer.
|
|
158
|
+
- Every five minutes, recheck coordinator identity and whether Pi is idle. Busy ticks are skipped, not queued. Worker replies, incoming reports, list/JSON status reads (including probes), and worker-to-worker/coordinator messages do not reset it.
|
|
159
|
+
- `intercom_stop_reminders({})` disables reminders until the next qualifying call. It does not cancel workers, close jobs or model work. There is no automatic reminder-count cutoff.
|
|
160
|
+
- Timers are in memory only. Shutdown, Pi `/reload`, or session replacement disposes them; startup does not restore or replay them. Reset/stop invalidates stale callbacks and older in-flight calls cannot re-arm after a later stop.
|
|
161
|
+
- Aborting the owning tool's Pi run also disarms its reminder generation when that AbortSignal is available. This is **not universal Escape/Stop detection**: the host may later be in a separate retry/compaction run whose abort does not reach the original signal. Use the explicit stop tool to disable reminders reliably.
|
|
162
|
+
- Reminder delivery uses Pi's existing user-message path. Host input rejection remains possible (including the documented compaction gap); reminders are not immediately retried. The next normal tick is a new periodic check, not proof of prior delivery.
|
|
163
|
+
|
|
164
|
+
The reminder contains only this fixed public text, never task payloads or private reasoning:
|
|
165
|
+
|
|
166
|
+
> Intercom reminder: Review outstanding delegated work and worker reports. If follow-up is needed, take the next appropriate action. Do not assume workers have finished or stopped.
|
|
167
|
+
>
|
|
168
|
+
> If there is genuinely nothing to follow up on, call `intercom_stop_reminders`. Otherwise, reminders continue every five minutes; a new worker call resets the timer.
|
|
169
|
+
>
|
|
170
|
+
> This reminder does not authorize new work, retries, worker closure, or publication.
|
|
171
|
+
|
|
172
|
+
Reload the coordinator's extension to register the new tool and timer logic. No existing live session is armed merely by installing the change.
|
|
173
|
+
|
|
140
174
|
## Config and wire contracts
|
|
141
175
|
|
|
142
176
|
Shared, source-controlled file: `<root>/.pi-intercom/config.json`. Do not ignore it or split IDs/ports into runtime config. Example **schema only** (not automatically installed placeholder data):
|
|
@@ -168,7 +202,9 @@ HTTP binds **127.0.0.1 only**. `POST /intercom` accepts UTF-8 JSON, at most 64 K
|
|
|
168
202
|
{"version":1,"kind":"message","from":"sender-session-id","to":"expected-recipient-session-id","payload":{"message":"explicit message"}}
|
|
169
203
|
```
|
|
170
204
|
|
|
171
|
-
|
|
205
|
+
Handoff wire kinds (0.6.1): `close_prepare`, `close_identity`, `close_request`, `handoff_report`, `close_ready`, `close_commit`. These require configured roles, matching job/runtime identity and bounded validated payloads. Pane/process identity is ephemeral protocol data, never stored in public config or summaries.
|
|
206
|
+
|
|
207
|
+
Other 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.
|
|
172
208
|
|
|
173
209
|
`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.
|
|
174
210
|
|
|
@@ -178,7 +214,7 @@ Tool text output is bounded to 50 KiB/2000 lines. The full saved roster remains
|
|
|
178
214
|
|
|
179
215
|
## Standalone terminal status monitor
|
|
180
216
|
|
|
181
|
-
|
|
217
|
+
When at least one worker is registered, 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. With no workers, it does not create/check the monitor. Configuring the first worker triggers the check; disconnected saved workers still count. This does not automatically close an already-existing monitor when the final worker is removed. 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.
|
|
182
218
|
|
|
183
219
|
The table uses aligned **Worker | Connection | Report | Activity | Seen | Last activity** columns (activity age/detail give way first on narrow panes). Report is explicitly worker-authored and separate from host activity. Activity 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. Version 0.5.2 adds a small footer label for the Intercom package version loaded by the monitor at startup; restart the monitor after updating to load the new version. Narrow panes use a compact version label and preserve the quit hint. No read-only banner or busy/idle count summary is shown. It reads the bounded config/log snapshot and performs read-only loopback health checks, then refreshes roughly three seconds after completion, without worker prompts or model calls. Checks are bounded by 750 ms per endpoint, a four-second batch budget, 16 concurrent requests and 256 workers; no overlapping batches or retries. Closing the monitor aborts checks. 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.
|
|
184
220
|
|
|
@@ -196,7 +232,24 @@ Connection is separate from historical activity and public reports. A recent mat
|
|
|
196
232
|
|
|
197
233
|
After the user confirms the previous session is closed, call `intercom_resume_worker({ to: "Builder", confirmClosed: true })`. It launches the **same saved Pi session**, restores configured identity/responsibility, and does not automatically start an old assignment. A matching connected endpoint blocks resume. Concurrent/submitted/uncertain attempts are fenced locally until a subsequent configured worker status arrives. On uncertain launch with no status, inspect the actual worker process; only after verifying closure should you reload the coordinator and consider an explicit retry. The fence is not persistent or a cross-process uniqueness guarantee. Resume failures do not remove/replace saved identity.
|
|
198
234
|
|
|
199
|
-
`intercom_remove_worker` is only for forgetting the saved registration, not parking a worker.
|
|
235
|
+
`intercom_remove_worker` is only for forgetting the saved registration, not parking a worker. Graceful stop remains disabled; see the background close workflow below. Reload coordinator/workers and restart the standalone monitor to use the new health protocol/UI; these additions require 0.5.1.
|
|
236
|
+
|
|
237
|
+
### Background save-and-close (0.6.1)
|
|
238
|
+
|
|
239
|
+
On supported **Linux + Herdr**, `intercom_close_worker({to:"Builder"})` returns a persisted job ID/state promptly. It does not hold the coordinator model turn open waiting for the worker. The extension performs these steps in the background:
|
|
240
|
+
|
|
241
|
+
1. Obtain and independently verify the worker's current pane, session header, terminal identity and Linux PID/start identity. Never infer ownership from a title/name alone.
|
|
242
|
+
2. Ask that worker to call `intercom_report_handoff({jobId,summary})` with a concise public summary (up to 4000 characters): completed work, unfinished items, blockers, validation and relevant project files. No credentials, private reasoning, raw tool output or private session paths.
|
|
243
|
+
3. Save `Agent.handoff` and `Agent.closeJob` atomically in config; only then acknowledge the worker's report tool. No pane closes at this step.
|
|
244
|
+
4. Wait for a successful matching tool result in the current branch and the worker's final `agent_settled` notification. New input/activity invalidates readiness.
|
|
245
|
+
5. Persist closing intent, recheck pane identity, and make a final nonce-bound worker settlement challenge immediately before issuing one exact `herdr pane close` command.
|
|
246
|
+
6. Observe pane absence and the original worker process's exit. Record `closed` only when both are verified; otherwise retain an explicit failure/uncertainty state. Name, responsibility, session ID and saved handoff remain registered.
|
|
247
|
+
|
|
248
|
+
The latest handoff/job are visible in `intercom_list`, bounded `intercom_worker_status` JSON and monitor details—even while the worker is disconnected. A handoff is worker-authored context, not acceptance of its findings. Config may be source-controlled: keep these summaries non-secret.
|
|
249
|
+
|
|
250
|
+
Jobs have a 120-second deadline and at most 16 simultaneous coordinator jobs. Unsupported hosts, missing identity, missing summary, save failure or absent final settlement never authorize a pane close. Old workers must reload the updated extension first. Active/uncertain jobs fence new Intercom work and conflicting lifecycle/config changes. On coordinator reload, pending jobs become interrupted and closing intent becomes uncertain; no job is automatically replayed. An uncertain persisted job requires explicit operator inspection/recovery of config before a new close/resume/removal—do not erase its fence or retry blindly.
|
|
251
|
+
|
|
252
|
+
**Scope of guarantees:** this is external pane closure, not graceful Pi cancellation. Herdr's pane-ID-only API has no atomic compare-and-close operation; independent local/Telegram input or pane replacement can still race the final check. No guarantee covers escaped child processes or transcript fsync/power-loss durability. Windows/non-Herdr close is unsupported. A disposable ordinary Node process was verified to exit on pane closure in local Linux Herdr 0.9.1; that is not a full live Pi handoff/history test. No existing project worker was closed during validation.
|
|
200
253
|
|
|
201
254
|
### JSON worker status for agents and chat integrations
|
|
202
255
|
|
|
@@ -241,6 +294,7 @@ Run these commands from a source checkout; tests and workflows are not shipped i
|
|
|
241
294
|
npm ci
|
|
242
295
|
npm run typecheck
|
|
243
296
|
npm test
|
|
297
|
+
npm audit --audit-level=low
|
|
244
298
|
npm run check:package
|
|
245
299
|
# Optional installed-host compatibility probe (confirms the known defect):
|
|
246
300
|
PI_INTERCOM_PI_ROOT='C:/path/to/pi-coding-agent' npm run test:host
|
|
@@ -250,11 +304,51 @@ The extension source runs through Pi's TypeScript loader; `npm run build` genera
|
|
|
250
304
|
|
|
251
305
|
## Publishing
|
|
252
306
|
|
|
253
|
-
[`.github/workflows/publish.yml`](https://github.com/
|
|
307
|
+
[`.github/workflows/publish.yml`](https://github.com/mbundgaard/pi-intercom/blob/main/.github/workflows/publish.yml) publishes **only on pushed version tags**. Ordinary commits, GitHub Release publication and manual dispatch do not publish. It checks out the triggering SHA, requires an annotated stable `vX.Y.Z` tag, and verifies the tag matches the package version and both lockfile version fields before installing dependencies.
|
|
308
|
+
|
|
309
|
+
Windows/Linux validation includes a clean install, typecheck, tests, full-tree security audit and package checks. The publisher packs and preserves an exact archive, publishes it with npm Trusted Publishing/OIDC and provenance (no stored npm token), then verifies the registry archive and decoded provenance linkage. Configure/check npm's trusted publisher as owner `mbundgaard`, repository `pi-intercom`, workflow `publish.yml`, no environment, with direct `npm publish` allowed.
|
|
310
|
+
|
|
311
|
+
Follow the [release procedure](references/releasing.md): review → choose an unused version/tag → update versions and changelog → validate → obtain explicit authorization → commit/push main → verify CI → create an annotated tag on that exact commit → push only that tag. Never trigger a second publisher, move tags, reuse published versions or blindly retry uncertain publication. Report success only after registry/artifact/linkage verification. Publishing does not install the extension or reload running sessions.
|
|
312
|
+
|
|
313
|
+
The tag-only workflow is a source change for future releases; historical tags retain their original workflow snapshots. Any security findings must be resolved before the audit gate can pass.
|
|
314
|
+
|
|
315
|
+
### 0.8.1 Tag-only releases and dependency security updates
|
|
316
|
+
|
|
317
|
+
- Publish only from pushed, annotated stable version tags, with exact-commit and package/lockfile version checks. GitHub Release and manual-dispatch publication triggers are removed.
|
|
318
|
+
- Add full-tree security audit gates to main/PR CI and release validation.
|
|
319
|
+
- Upgrade the development SDK to Pi 1.4.0 with a scoped `undici` 8.12.2 override and patched `brace-expansion` 5.0.12. Verify actual installed dependency versions as well as a clean audit; Pi 0.84.4's shrinkwrap prevented effective overrides. The runtime TUI alias stays at 0.84.4 and the Node minimum remains 22.19.0. This does not upgrade users' installed Pi.
|
|
320
|
+
- Keep handoff reporting model-only on newer SDKs: nested calls lack the transcript tool-result evidence required for closure. Existing final-settlement and persistence checks remain unchanged.
|
|
321
|
+
- Preserve and publish one archive using npm Trusted Publishing/OIDC, then compare the registry download and decoded provenance linkage against the release build.
|
|
322
|
+
- Document explicit release authorization, immutable tags, uncertain-publication handling, and installation/reload separation in [the release procedure](references/releasing.md).
|
|
323
|
+
- Includes the coordinator reminders and strict session-root isolation from the preserved, unpublished 0.7.0/0.8.0 tags. Shared-roster subfolder worker launches are refused rather than redirected to parent configuration.
|
|
324
|
+
|
|
325
|
+
### 0.8.0 Strict session-root isolation
|
|
326
|
+
|
|
327
|
+
- Never search parent folders for config, even when a local config is missing or malformed. An explicit root must canonically equal the session working directory; it cannot permit a parent config.
|
|
328
|
+
- Validate before startup resources, reject escaping/dangling config links and stable root redirects, and guard temporary-config cleanup. These are config protections, not a filesystem sandbox or atomic TOCTOU guarantee.
|
|
329
|
+
- Created/resumed workers receive an explicit same-directory root assertion. Shared-config subfolder launches are now rejected, not silently relocated. Existing registrations/history remain intact.
|
|
330
|
+
- Includes the coordinator reminders from the preserved 0.7.0 GitHub release, whose npm publication was blocked by authorization after the repository transfer.
|
|
331
|
+
- Local validation: 205 tests, typecheck and isolated package-install checks passed. Native Windows/Linux CI gates publication.
|
|
332
|
+
|
|
333
|
+
### 0.7.0 Coordinator reminders
|
|
334
|
+
|
|
335
|
+
- Valid coordinator worker calls arm/reset a five-minute reminder using fixed public text. Failed attempted operations can still need follow-up; incoming reports and read-only status queries do not reset the timer.
|
|
336
|
+
- New coordinator-only `intercom_stop_reminders` disables reminders until the next qualifying worker call. No automatic reminder-count cutoff, worker retry, closure or publication is authorized.
|
|
337
|
+
- Busy ticks are skipped without a backlog; stale callbacks and older in-flight calls are fenced. Shutdown/reload/session replacement clears ephemeral timer state.
|
|
338
|
+
- Owning-run AbortSignal cancellation is supported where available, but is not universal detection of later Escape/Stop during separate retry/compaction runs.
|
|
339
|
+
- Local validation: 183 tests, typecheck and isolated package-install checks. Update and reload the coordinator to activate the new tool; startup itself does not arm reminders.
|
|
340
|
+
|
|
341
|
+
### 0.6.1 Background handoff-and-close and quiet startup
|
|
254
342
|
|
|
255
|
-
|
|
343
|
+
- First npm release of these features: the preserved 0.6.0 GitHub tag failed Windows validation and was not published to npm.
|
|
344
|
+
- Windows config publication handles transient `EPERM` replacement failures with bounded filesystem-only attempts and lifecycle/deadline checks before each attempt. Worker close commands, messages and jobs are never retried by this safeguard. Persistent contention can still prevent publication; an unpersisted terminal close outcome retains the existing intent/fence for operator inspection and reload recovery.
|
|
256
345
|
|
|
257
|
-
|
|
346
|
+
- Explicit Linux Herdr close jobs request and save a public worker handoff, await final settlement, then attempt one identity-checked pane close in the background. Worker registration, responsibility and session ID remain saved.
|
|
347
|
+
- Persist latest handoff and close-job status in config; show them in monitor details and JSON worker status. Correlation, deadlines, lifecycle guards and uncertainty fences prevent automatic replay.
|
|
348
|
+
- Empty rosters do not open/check the monitor; configuring the first worker triggers setup. Disconnected saved workers still count.
|
|
349
|
+
- Preserve the coordinator's existing Pi session name and Herdr tab title; worker naming remains synchronized.
|
|
350
|
+
- Validation includes typecheck, workflow/platform regression tests and isolated package installation. An isolated ordinary-process pane-close check passed on Linux Herdr 0.9.1; full live Pi handoff/history and Windows pane termination are not claimed.
|
|
351
|
+
- Upgrade coordinator/workers and restart the monitor. Close is Linux Herdr only, not graceful Pi abort or an all-descendants termination guarantee. Config-root discovery and connectivity polling architecture are unchanged.
|
|
258
352
|
|
|
259
353
|
### 0.5.2 Monitor version footer
|
|
260
354
|
|
|
@@ -344,5 +438,5 @@ The release/session evidence reported during the 0.1.2 validation establishes th
|
|
|
344
438
|
- Windows visible terminal/Pi process startup. Success only proves terminal creation, **not Pi readiness**; startup failures remain visible in that terminal. No live readiness handshake was added.
|
|
345
439
|
- Actual persisted-session lookup and resumed worker startup; never-used session failure.
|
|
346
440
|
- Cross-process/network-drive atomicity and Windows ACL/sharing failures (same-process temp-filesystem races are tested).
|
|
347
|
-
-
|
|
441
|
+
- Graceful stop remains disabled until a verified cancellation API covers retries, compaction continuations and queues. The Linux Herdr pane-close workflow is a separately authorized best-effort contract, not a claim that graceful cancellation was fixed.
|
|
348
442
|
- Explicit repeat-registration tool and broad anonymous permissions require a contract decision. Duplicate-session locks, takeover, durable logging, non-Herdr Linux launchers and macOS support are deferred.
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Handoff, type CloseJob } from './handoff.js';
|
|
1
2
|
export interface Agent {
|
|
2
3
|
sessionId: string;
|
|
3
4
|
name: string;
|
|
@@ -7,6 +8,8 @@ export interface Agent {
|
|
|
7
8
|
/** Legacy browser dashboard field, accepted for migration only; removed at coordinator startup. */
|
|
8
9
|
dashboardPort?: number;
|
|
9
10
|
projectDirectory: string;
|
|
11
|
+
handoff?: Handoff;
|
|
12
|
+
closeJob?: CloseJob;
|
|
10
13
|
}
|
|
11
14
|
export interface Config {
|
|
12
15
|
version: 1;
|
|
@@ -24,16 +27,30 @@ export declare const coordinator: (c: Config) => Agent;
|
|
|
24
27
|
export declare function named(c: Config, name: string): Agent;
|
|
25
28
|
export declare function requireCoordinator(c: Config, id: string): Agent;
|
|
26
29
|
export declare function directory(root: string, requested: string): Promise<string>;
|
|
30
|
+
export interface ConfigStoreOptions {
|
|
31
|
+
/** Publication seams for deterministic platform/race tests. */
|
|
32
|
+
platform?: NodeJS.Platform;
|
|
33
|
+
rename?: (from: string, to: string) => Promise<void>;
|
|
34
|
+
delay?: (milliseconds: number) => Promise<void>;
|
|
35
|
+
now?: () => number;
|
|
36
|
+
}
|
|
27
37
|
export declare class ConfigStore {
|
|
28
38
|
readonly root: string;
|
|
39
|
+
private readonly options;
|
|
29
40
|
readonly file: string;
|
|
30
41
|
private tail;
|
|
31
|
-
|
|
42
|
+
private canonicalRoot?;
|
|
43
|
+
constructor(root: string, options?: ConfigStoreOptions);
|
|
44
|
+
private assertLocalPaths;
|
|
45
|
+
validateRoot(expectedCanonicalRoot: string): Promise<void>;
|
|
32
46
|
read(): Promise<Config>;
|
|
33
47
|
static discover(cwd: string): Promise<ConfigStore | undefined>;
|
|
48
|
+
static workspace(cwd: string, workspaceRoot: string): Promise<ConfigStore>;
|
|
34
49
|
protected openTemporary(file: string): Promise<import("fs/promises").FileHandle>;
|
|
50
|
+
private cleanupTemporary;
|
|
35
51
|
private temporary;
|
|
36
52
|
initialize(id: string, boundPort: number, assertValid?: () => void): Promise<boolean>;
|
|
53
|
+
private publish;
|
|
37
54
|
update(id: string, mutate: (config: Config) => void | Promise<void>, assertValid?: () => void): Promise<Config>;
|
|
38
55
|
configure(id: string, values: Omit<Agent, 'coordinator'>, assertValid?: () => void): Promise<Config>;
|
|
39
56
|
}
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { mkdir, readFile, realpath, rename, unlink, open, link, stat } from 'node:fs/promises';
|
|
1
|
+
import { mkdir, readFile, realpath, rename, unlink, open, link, stat, lstat } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { fencedClose, validateHandoff, validateCloseJob } from './handoff.js';
|
|
4
5
|
export const DEFAULT_DESCRIPTION = 'Coordinate workers, delegate work, and manage shared configuration.';
|
|
5
6
|
export const key = (name) => name.toLowerCase();
|
|
6
7
|
export function fail(message) { throw new Error(`PiIntercom: ${message}`); }
|
|
@@ -32,6 +33,16 @@ export function validateConfig(value) {
|
|
|
32
33
|
fail('invalid name');
|
|
33
34
|
port(a.port);
|
|
34
35
|
relativeDirectory(a.projectDirectory);
|
|
36
|
+
if (a.handoff !== undefined) {
|
|
37
|
+
if (a.coordinator)
|
|
38
|
+
fail('handoff is worker-only');
|
|
39
|
+
validateHandoff(a.handoff);
|
|
40
|
+
}
|
|
41
|
+
if (a.closeJob !== undefined) {
|
|
42
|
+
if (a.coordinator)
|
|
43
|
+
fail('closeJob is worker-only');
|
|
44
|
+
validateCloseJob(a.closeJob);
|
|
45
|
+
}
|
|
35
46
|
if (a.dashboardPort !== undefined) {
|
|
36
47
|
if (!a.coordinator)
|
|
37
48
|
fail('dashboardPort is coordinator-only');
|
|
@@ -67,40 +78,104 @@ export async function directory(root, requested) {
|
|
|
67
78
|
fail('projectDirectory is not a directory');
|
|
68
79
|
return rel.split(path.sep).join('/') || '.';
|
|
69
80
|
}
|
|
81
|
+
const RENAME_DELAYS = [10, 20, 40, 80];
|
|
82
|
+
const RENAME_BUDGET_MS = 250;
|
|
70
83
|
export class ConfigStore {
|
|
71
84
|
root;
|
|
85
|
+
options;
|
|
72
86
|
file;
|
|
73
87
|
tail = Promise.resolve();
|
|
74
|
-
|
|
88
|
+
canonicalRoot;
|
|
89
|
+
constructor(root, options = {}) {
|
|
75
90
|
this.root = root;
|
|
91
|
+
this.options = options;
|
|
76
92
|
this.file = path.join(root, '.pi-intercom', 'config.json');
|
|
77
93
|
}
|
|
78
|
-
async
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
for
|
|
85
|
-
|
|
94
|
+
async assertLocalPaths() {
|
|
95
|
+
const root = await realpath(this.root);
|
|
96
|
+
if (this.canonicalRoot === undefined)
|
|
97
|
+
this.canonicalRoot = root;
|
|
98
|
+
else if (root !== this.canonicalRoot)
|
|
99
|
+
fail('config root canonical location changed');
|
|
100
|
+
// Reject existing escaping links/junctions before following them for any
|
|
101
|
+
// config access. These path checks are best effort, not TOCTOU protection.
|
|
102
|
+
for (const [location, directory] of [[path.dirname(this.file), true], [this.file, false]]) {
|
|
86
103
|
try {
|
|
87
|
-
await
|
|
88
|
-
return store;
|
|
104
|
+
await lstat(location);
|
|
89
105
|
}
|
|
90
106
|
catch (error) {
|
|
91
|
-
if (error.code
|
|
92
|
-
|
|
107
|
+
if (error.code === 'ENOENT')
|
|
108
|
+
continue;
|
|
109
|
+
throw error;
|
|
93
110
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
let resolved;
|
|
112
|
+
try {
|
|
113
|
+
resolved = await realpath(location);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
fail('local config path cannot be resolved safely');
|
|
117
|
+
}
|
|
118
|
+
const relative = path.relative(root, resolved);
|
|
119
|
+
if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))
|
|
120
|
+
fail('local config path escapes session root');
|
|
121
|
+
const metadata = await stat(resolved);
|
|
122
|
+
if (directory ? !metadata.isDirectory() : !metadata.isFile())
|
|
123
|
+
fail('invalid local config path type');
|
|
98
124
|
}
|
|
99
125
|
}
|
|
126
|
+
async validateRoot(expectedCanonicalRoot) {
|
|
127
|
+
await this.assertLocalPaths();
|
|
128
|
+
if (this.canonicalRoot !== expectedCanonicalRoot)
|
|
129
|
+
fail('config root canonical location changed');
|
|
130
|
+
}
|
|
131
|
+
async read() {
|
|
132
|
+
// Missing, malformed and unreadable local files propagate; no fallback.
|
|
133
|
+
await this.assertLocalPaths();
|
|
134
|
+
return validateConfig(JSON.parse(await readFile(this.file, 'utf8')));
|
|
135
|
+
}
|
|
136
|
+
static async discover(cwd) {
|
|
137
|
+
const store = new ConfigStore(await realpath(cwd));
|
|
138
|
+
try {
|
|
139
|
+
await store.read();
|
|
140
|
+
return store;
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
if (error.code !== 'ENOENT')
|
|
144
|
+
throw error;
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
static async workspace(cwd, workspaceRoot) {
|
|
149
|
+
text(workspaceRoot, 'workspaceRoot');
|
|
150
|
+
if (!path.isAbsolute(workspaceRoot))
|
|
151
|
+
fail('workspaceRoot must be absolute');
|
|
152
|
+
const root = await realpath(workspaceRoot);
|
|
153
|
+
if (!(await stat(root)).isDirectory())
|
|
154
|
+
fail('workspaceRoot is not a directory');
|
|
155
|
+
const current = await realpath(cwd);
|
|
156
|
+
if (path.relative(root, current) !== '')
|
|
157
|
+
fail('workspaceRoot must equal the session working directory; parent configs are forbidden');
|
|
158
|
+
const store = new ConfigStore(root);
|
|
159
|
+
await store.read(); // Explicit worker mode must never create a replacement coordinator.
|
|
160
|
+
return store;
|
|
161
|
+
}
|
|
100
162
|
openTemporary(file) { return open(file, 'wx'); }
|
|
163
|
+
async cleanupTemporary(temp) {
|
|
164
|
+
// A moved root may leave an unpublished temp behind. Never follow a
|
|
165
|
+
// replacement parent outside the pinned root just to clean up. This guard
|
|
166
|
+
// is independent of lifecycle/deadline expiry so ordinary failures clean up.
|
|
167
|
+
await this.assertLocalPaths();
|
|
168
|
+
const resolved = await realpath(temp);
|
|
169
|
+
const relative = path.relative(this.canonicalRoot, resolved);
|
|
170
|
+
if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))
|
|
171
|
+
fail('temporary config path escapes session root');
|
|
172
|
+
await unlink(temp);
|
|
173
|
+
}
|
|
101
174
|
async temporary(config) {
|
|
102
175
|
validateConfig(config);
|
|
176
|
+
await this.assertLocalPaths();
|
|
103
177
|
await mkdir(path.dirname(this.file), { recursive: true });
|
|
178
|
+
await this.assertLocalPaths();
|
|
104
179
|
const temp = `${this.file}.${randomUUID()}.tmp`;
|
|
105
180
|
const handle = await this.openTemporary(temp);
|
|
106
181
|
try {
|
|
@@ -112,7 +187,7 @@ export class ConfigStore {
|
|
|
112
187
|
catch (error) {
|
|
113
188
|
// Cleanup failures must not replace the original write/sync/close error.
|
|
114
189
|
await handle.close().catch(() => { });
|
|
115
|
-
await
|
|
190
|
+
await this.cleanupTemporary(temp).catch(() => { });
|
|
116
191
|
throw error;
|
|
117
192
|
}
|
|
118
193
|
}
|
|
@@ -122,6 +197,7 @@ export class ConfigStore {
|
|
|
122
197
|
assertValid();
|
|
123
198
|
const temp = await this.temporary({ version: 1, multiplexer: 'herdr', agents: [{ sessionId: id, name: 'Coordinator', coordinator: true, description: DEFAULT_DESCRIPTION, port: boundPort, projectDirectory: '.' }] });
|
|
124
199
|
try {
|
|
200
|
+
await this.assertLocalPaths();
|
|
125
201
|
assertValid();
|
|
126
202
|
try {
|
|
127
203
|
await link(temp, this.file);
|
|
@@ -130,17 +206,47 @@ export class ConfigStore {
|
|
|
130
206
|
if (e.code !== 'EEXIST')
|
|
131
207
|
throw e;
|
|
132
208
|
await this.read();
|
|
133
|
-
await
|
|
209
|
+
await this.cleanupTemporary(temp);
|
|
134
210
|
return false;
|
|
135
211
|
}
|
|
136
|
-
await
|
|
212
|
+
await this.cleanupTemporary(temp);
|
|
137
213
|
return true;
|
|
138
214
|
}
|
|
139
215
|
catch (error) {
|
|
140
|
-
await
|
|
216
|
+
await this.cleanupTemporary(temp).catch(() => { });
|
|
141
217
|
throw error;
|
|
142
218
|
}
|
|
143
219
|
}
|
|
220
|
+
async publish(temp, assertValid) {
|
|
221
|
+
const replace = this.options.rename ?? rename;
|
|
222
|
+
const now = this.options.now ?? (() => performance.now());
|
|
223
|
+
const delay = this.options.delay ?? (milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds)));
|
|
224
|
+
const started = now();
|
|
225
|
+
let originalError;
|
|
226
|
+
for (let attempt = 0;; attempt++) {
|
|
227
|
+
// Windows readers can briefly deny replace-rename. Retry only publication
|
|
228
|
+
// of this already synced/closed temp, never the mutation or any OS action
|
|
229
|
+
// outside config persistence. The elapsed budget bounds retry initiation,
|
|
230
|
+
// not the duration of an already-submitted OS rename.
|
|
231
|
+
await this.assertLocalPaths();
|
|
232
|
+
assertValid();
|
|
233
|
+
if (attempt > 0 && now() - started >= RENAME_BUDGET_MS)
|
|
234
|
+
throw originalError;
|
|
235
|
+
try {
|
|
236
|
+
await replace(temp, this.file);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
if ((this.options.platform ?? process.platform) !== 'win32' || error.code !== 'EPERM')
|
|
241
|
+
throw error;
|
|
242
|
+
originalError ??= error;
|
|
243
|
+
const backoff = RENAME_DELAYS[attempt];
|
|
244
|
+
if (backoff === undefined || now() - started + backoff >= RENAME_BUDGET_MS)
|
|
245
|
+
throw originalError;
|
|
246
|
+
await delay(backoff);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
144
250
|
async update(id, mutate, assertValid = () => { }) {
|
|
145
251
|
const operation = this.tail.then(async () => {
|
|
146
252
|
assertValid();
|
|
@@ -152,12 +258,12 @@ export class ConfigStore {
|
|
|
152
258
|
validateConfig(c);
|
|
153
259
|
const temp = await this.temporary(c);
|
|
154
260
|
try {
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
await
|
|
261
|
+
// Every publication attempt checks the lifecycle/deadline guard; an
|
|
262
|
+
// already submitted OS rename still cannot be undone.
|
|
263
|
+
await this.publish(temp, assertValid);
|
|
158
264
|
}
|
|
159
265
|
catch (error) {
|
|
160
|
-
await
|
|
266
|
+
await this.cleanupTemporary(temp).catch(() => { });
|
|
161
267
|
throw error;
|
|
162
268
|
}
|
|
163
269
|
return c;
|
|
@@ -174,8 +280,16 @@ export class ConfigStore {
|
|
|
174
280
|
const index = c.agents.findIndex(old => old.sessionId === a.sessionId);
|
|
175
281
|
if (index < 0)
|
|
176
282
|
c.agents.push(a);
|
|
177
|
-
else
|
|
283
|
+
else {
|
|
284
|
+
const old = c.agents[index];
|
|
285
|
+
if (fencedClose(old.closeJob))
|
|
286
|
+
fail('worker close is active or uncertain; configuration is fenced');
|
|
287
|
+
if (old.handoff)
|
|
288
|
+
a.handoff = old.handoff;
|
|
289
|
+
if (old.closeJob)
|
|
290
|
+
a.closeJob = old.closeJob;
|
|
178
291
|
c.agents[index] = a;
|
|
292
|
+
}
|
|
179
293
|
}, assertValid);
|
|
180
294
|
}
|
|
181
295
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|