@comput/pi-intercom 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # PiIntercom (V1 supported core)
2
2
 
3
- One Windows interactive Pi extension for coordinator and workers. **Intercom communicates; Pi orchestrates.** No automatic assignment, retry, removal, replacement, launcher fallback, commit, or rollback.
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.
4
4
 
5
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.
6
6
 
7
7
  ## Use
8
8
 
9
- Requires Windows, 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
+ 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:
10
10
 
11
11
  ```powershell
12
12
  cd D:\Source\YourProject
@@ -29,11 +29,21 @@ Then start a new Pi session or run Pi `/reload`. `pi install` records the packag
29
29
 
30
30
  The 0.1.2 update/reload and subsequent worker creation were observed live; comprehensive reload/session-replacement lifecycle coverage remains pending.
31
31
 
32
+ ### Linux source installation
33
+
34
+ ```sh
35
+ pi install /absolute/path/to/pi-intercom
36
+ ```
37
+
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.
39
+
40
+ 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
+
32
42
  ### Startup and launchers
33
43
 
34
44
  Without shared config, the current working directory becomes the coordinator root. Startup creates `.pi-intercom/config.json`, opens a loopback listener, synchronizes the name `Coordinator`, and waits for user input (no model turn). Existing config is found by walking upward. Invalid/unreadable config is an error and is not overwritten. Unknown session IDs, including forks, are workers, never replacement coordinators.
35
45
 
36
- Default launcher `herdr` requires the coordinator to be inside Herdr (`HERDR_ENV=1` and workspace context), with `herdr` on PATH and `powershell.exe` plus `pi.ps1` available in the worker pane. Each worker gets **one tab, one pane, no split, no focus change**. The `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.
46
+ 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.
37
47
 
38
48
  ## Explicit workflow
39
49
 
@@ -134,18 +144,25 @@ Production source runs through Pi's TypeScript loader; `npm run build` generates
134
144
 
135
145
  ## Publishing
136
146
 
137
- [`.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. After the repository migration, configure the npm trusted publisher as owner `comput-sh`, repository `pi-intercom`, workflow `publish.yml`, with no environment. The owner confirmed updating this npm mapping after migration. The GitHub transfer alone does not configure it; successful publishing must be verified through the release workflow. Historical release and workflow links below retain the original owner as provenance.
147
+ [`.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.
138
148
 
139
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>`.
140
150
 
141
151
  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.
142
152
 
153
+ ### 0.3.0 Linux support
154
+
155
+ - Interactive startup, messaging and dashboard support on Linux.
156
+ - Herdr worker launch/resume command generation uses quoted POSIX shell arguments; Windows behavior is retained. Linux `none` fails explicitly without fallback.
157
+ - Linux validation: typecheck and 67/67 tests passed, with no skips. Live source-loaded Herdr launch, registration, configure/reload and round-trip messaging passed with two workers.
158
+ - CI and release validation now run on Windows and Linux. Stop/close remain disabled; live Linux resume is not yet verified.
159
+
143
160
  ### Release evidence
144
161
 
145
- - [v0.1.1](https://github.com/mbundgaard/PiIntercom/releases/tag/v0.1.1): successful npm OIDC [run 35466923379](https://github.com/mbundgaard/PiIntercom/actions/runs/35466923379).
146
- - [v0.1.2](https://github.com/mbundgaard/PiIntercom/releases/tag/v0.1.2): successful npm OIDC [run 35467586052](https://github.com/mbundgaard/PiIntercom/actions/runs/35467586052). Fixes Windows Herdr launching by using `herdr pane run` on the returned pane ID with encoded PowerShell invoking `pi.ps1`, instead of the failing `Start-Process pi` wrapper. No Herdr agent alias is needed.
162
+ - [v0.1.1](https://github.com/comput-sh/pi-intercom/releases/tag/v0.1.1): successful npm OIDC [run 35466923379](https://github.com/comput-sh/pi-intercom/actions/runs/35466923379).
163
+ - [v0.1.2](https://github.com/comput-sh/pi-intercom/releases/tag/v0.1.2): successful npm OIDC [run 35467586052](https://github.com/comput-sh/pi-intercom/actions/runs/35467586052). Fixes Windows Herdr launching by using `herdr pane run` on the returned pane ID with encoded PowerShell invoking `pi.ps1`, instead of the failing `Start-Process pi` wrapper. No Herdr agent alias is needed.
147
164
 
148
- - [v0.1.3](https://github.com/mbundgaard/PiIntercom/releases/tag/v0.1.3): successful npm OIDC [run 35474304380](https://github.com/mbundgaard/PiIntercom/actions/runs/35474304380). Contains the fixes below, not the observability feature added in 0.2.0.
165
+ - [v0.1.3](https://github.com/comput-sh/pi-intercom/releases/tag/v0.1.3): successful npm OIDC [run 35474304380](https://github.com/comput-sh/pi-intercom/actions/runs/35474304380). Contains the fixes below, not the observability feature added in 0.2.0.
149
166
 
150
167
  ### 0.1.3 changes and verification
151
168
 
@@ -187,4 +204,4 @@ The release/session evidence reported during the 0.1.2 validation establishes th
187
204
  - Actual persisted-session lookup and resumed worker startup; never-used session failure.
188
205
  - Cross-process/network-drive atomicity and Windows ACL/sharing failures (same-process temp-filesystem races are tested).
189
206
  - Stop/close remain disabled on all hosts until a verified cancellation API covers retries, compaction continuations and queues. No workaround or weakened guarantee.
190
- - Explicit repeat-registration tool and broad anonymous permissions require a contract decision. Duplicate-session locks, takeover, durable logging and non-Windows support are deferred.
207
+ - 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/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "bugs": {
13
13
  "url": "https://github.com/comput-sh/pi-intercom/issues"
14
14
  },
15
- "version": "0.2.2",
15
+ "version": "0.3.0",
16
16
  "description": "Explicit local communication between Pi sessions; Pi orchestrates.",
17
17
  "type": "module",
18
18
  "keywords": [
@@ -39,15 +39,15 @@
39
39
  "typebox": "*"
40
40
  },
41
41
  "devDependencies": {
42
- "typescript": "^5.9.3",
43
- "@types/node": "^22.0.0",
44
42
  "@earendil-works/pi-coding-agent": "0.84.4",
45
- "typebox": "1.3.7"
43
+ "@types/node": "^22.0.0",
44
+ "typebox": "1.3.7",
45
+ "typescript": "^5.9.3"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "tsc",
49
49
  "typecheck": "tsc --noEmit",
50
- "test": "npm run build && node --test tests/core.test.mjs tests/integration.test.mjs tests/launcher.test.mjs tests/extension.test.mjs tests/runtime-http.test.mjs tests/resume-storage.test.mjs tests/observability.test.mjs tests/dashboard.test.mjs tests/dashboard-security.test.mjs tests/observability-integration.test.mjs",
50
+ "test": "npm run build && node --test tests/core.test.mjs tests/integration.test.mjs tests/launcher.test.mjs tests/linux-launcher.test.mjs tests/extension.test.mjs tests/runtime-http.test.mjs tests/resume-storage.test.mjs tests/observability.test.mjs tests/dashboard.test.mjs tests/dashboard-security.test.mjs tests/observability-integration.test.mjs",
51
51
  "test:host": "node --test tests/pi-cancellation-probe.test.mjs",
52
52
  "check:package": "npm pack --dry-run --ignore-scripts"
53
53
  }
package/src/index.ts CHANGED
@@ -20,7 +20,7 @@ const tools: [string, string, TSchema][] = [
20
20
  ['close_worker', UNSUPPORTED_CANCELLATION, to],
21
21
  ['resume_worker', 'Coordinator only. Launch saved session by ID in configured directory. No replacement/removal on failure; no old assignment is automatically started.', to],
22
22
  ['remove_worker', 'Coordinator only. Remove config entry only; never stop process or delete session files. A running worker must be explicitly closed before removal. Stop/close are disabled on current host: arrange explicit user closure first.', to],
23
- ['set_multiplexer', 'Coordinator only. Set herdr (default) or none (separate visible Windows terminals) for future launches. Never move/restart existing workers or fall back.', Type.Object({ multiplexer: Type.String({ enum: ['herdr', 'none'] }) })],
23
+ ['set_multiplexer', 'Coordinator only. Set herdr (default, Windows/Linux) or none (separate visible Windows terminals; unsupported on Linux) for future launches. Never move/restart existing workers or fall back.', Type.Object({ multiplexer: Type.String({ enum: ['herdr', 'none'] }) })],
24
24
  ];
25
25
 
26
26
  // Launchers pass no --session-dir. Match child Pi's env > per-cwd settings >
@@ -53,7 +53,7 @@ export default function intercomExtension(pi: ExtensionAPI): void {
53
53
  const started = ++generation;
54
54
  await dashboard?.close(); dashboard = undefined;
55
55
  await runtime?.close(); context = ctx;
56
- if (process.platform !== 'win32' || ctx.mode !== 'tui') throw new Error('PiIntercom V1 requires Windows interactive Pi. No resources started.');
56
+ if (!['win32', 'linux'].includes(process.platform) || ctx.mode !== 'tui') throw new Error('PiIntercom requires Windows or Linux interactive Pi. No resources started.');
57
57
  if (!ctx.isProjectTrusted()) throw new Error('PiIntercom requires project trust before honoring shared project configuration.');
58
58
  runtime = new Intercom({
59
59
  cwd: ctx.cwd,
package/src/launcher.ts CHANGED
@@ -9,6 +9,7 @@ export const run: Run = async (file, args) => {
9
9
  return stdout;
10
10
  };
11
11
  export const psQuote = (value: string) => `'${value.replaceAll("'", "''")}'`;
12
+ export const shQuote = (value: string) => `'${value.replaceAll("'", "'\"'\"'")}'`;
12
13
  export const encoded = (script: string) => Buffer.from(script, 'utf16le').toString('base64');
13
14
  export interface LauncherOptions {
14
15
  extension: string;
@@ -20,7 +21,9 @@ export interface LauncherOptions {
20
21
  export function launchers(options: LauncherOptions) {
21
22
  const exec = options.run ?? run, env = options.env ?? process.env;
22
23
  async function launch(request: LaunchRequest): Promise<unknown> {
23
- if ((options.platform ?? process.platform) !== 'win32') fail('V1 launchers support Windows only');
24
+ const platform = options.platform ?? process.platform;
25
+ if (platform !== 'win32' && platform !== 'linux') fail('launchers support Windows and Linux only');
26
+ if (platform === 'linux' && request.multiplexer === 'none') fail('Linux worker launching requires Herdr; none is Windows-only. No terminal fallback');
24
27
  if (request.sessionId && !await options.sessionExists(request.cwd, request.sessionId)) fail('saved Pi session not found in project directory; never-used sessions may not be persisted. Config unchanged; no replacement launched');
25
28
  const args = ['-e', options.extension, ...(request.sessionId ? ['--session', request.sessionId] : [])];
26
29
  if (request.multiplexer === 'herdr') {
@@ -35,7 +38,9 @@ export function launchers(options: LauncherOptions) {
35
38
  // Run an explicit PowerShell command in the returned shell pane instead.
36
39
  // This acknowledges command submission only, not Pi readiness/registration.
37
40
  const script = `$ErrorActionPreference='Stop'; Set-Location -LiteralPath ${psQuote(request.cwd)}; & (Get-Command pi.ps1 -ErrorAction Stop).Source ${args.map(psQuote).join(' ')}; if ($LASTEXITCODE -ne 0) { Write-Error ('Pi exited with code ' + $LASTEXITCODE) }`;
38
- const command = `powershell.exe -NoProfile -ExecutionPolicy Bypass -EncodedCommand ${encoded(script)}`;
41
+ const command = platform === 'win32'
42
+ ? `powershell.exe -NoProfile -ExecutionPolicy Bypass -EncodedCommand ${encoded(script)}`
43
+ : `sh -c ${shQuote(`cd ${shQuote(request.cwd)} && exec pi ${args.map(shQuote).join(' ')}`)}`;
39
44
  try { await exec('herdr', ['pane', 'run', pane, command]); }
40
45
  catch (e) { fail(`Herdr Pi command submission failed in tab ${tab}, pane ${pane}: ${String(e)}. Tab/process may remain; no automatic cleanup/retry/replacement`); }
41
46
  return { commandSubmitted: true, tab, pane, piReadiness: 'not observed; inspect pane for startup failures', registrationAwaited: false };