@samuelho-dev/coordinator 0.3.0-beta.3 → 0.3.0-beta.4

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
@@ -9,7 +9,7 @@ There are two parts: **one inspector service**, plus **native integrations on ea
9
9
  The API and setup CLI require Node >=22.19. Install the version-pinned release:
10
10
 
11
11
  ```sh
12
- npm install --global @samuelho-dev/coordinator@0.3.0-beta.3
12
+ npm install --global @samuelho-dev/coordinator@0.3.0-beta.4
13
13
  ```
14
14
 
15
15
  For source development only, use a reviewed checkout with `pnpm install --frozen-lockfile && pnpm build` (pnpm 11.9.0). `coordinator-install --source` deliberately activates that exact local package; never source-link a native package manager's own `node_modules` directory.
@@ -100,8 +100,8 @@ The installer validates prerequisites and creates launchers/config fragments. `-
100
100
 
101
101
  | Target | Activation | Presence publisher |
102
102
  | --- | --- | --- |
103
- | OMP | `omp plugin install @samuelho-dev/coordinator@0.3.0-beta.3`; merge only the generated `mcp.json` coordinator entry into native MCP settings. `/coordinator list` needs no MCP registration. | In-session extension. |
104
- | Pi | `pi install npm:@samuelho-dev/coordinator@0.3.0-beta.3`; directly registers `coordinator_session_list` / `coordinator_session_inspect`, without an MCP bridge. | In-session extension. |
103
+ | OMP | `omp plugin install @samuelho-dev/coordinator@0.3.0-beta.4`; merge only the generated `mcp.json` coordinator entry into native MCP settings. `/coordinator list` needs no MCP registration. | In-session extension. |
104
+ | Pi | `pi install npm:@samuelho-dev/coordinator@0.3.0-beta.4`; directly registers `coordinator_session_list` / `coordinator_session_inspect`, without an MCP bridge. | In-session extension. |
105
105
  | Claude Code | `claude --plugin-dir "$PRIVATE/claude-host"`; approve generated hooks/MCP tools; preserve existing status-line configuration. | Separate `connector.sh`. |
106
106
  | Codex CLI | Merge generated `hooks/hooks.json` and coordinator `mcp.toml`; trust only Coordinator's handlers in native `/hooks`. | Separate `connector.sh`. |
107
107
  | Hermes | Merge generated hook entries and `mcp_servers.coordinator` from `mcp.yaml` into the selected profile; no Python plugin installation. | Separate `connector.sh`. |
@@ -118,7 +118,7 @@ Hook/status-line/notification capture is local and can initialize identity/cache
118
118
 
119
119
  ### Native session commands and Rex
120
120
 
121
- Pi/OMP register `/coordinator list`. It follows every API page visible to the owner key and displays full native session/agent IDs, machine names/installation IDs, harness and all reported metadata: model/provider, workspace, activity, connection liveness, process identity and Rex association. Missing metadata is omitted. It reads the API directly, with no model turn, per-session resource sampling or separate MCP registration.
121
+ Pi/OMP register `/coordinator list`. It follows every API page visible to the owner key and returns pretty JSON (`{ "sessions": [...] }`) using Effect's JSON formatter, with native JSON syntax highlighting in the terminal. Each session preserves full native session/agent IDs, machine names/installation IDs, harness and all reported metadata: model/provider, workspace, activity, connection liveness, process identity and Rex association. Missing metadata is omitted; an empty listing returns `{ "sessions": [] }`. It reads the API directly, with no model turn, per-session resource sampling or separate MCP registration.
122
122
 
123
123
  Session JSON is Coordinator's fleet model, not an OSC wire payload. `rex` preserves `REX_SERVER` as `serverAddress` and the actual full `REX_SESSION`/`REX_BLOCK` IDs; these are separate from native agent IDs. Optional `programStatus` uses [Rex Program Status Protocol](https://www.superlogical.com/rex/docs/build/program-status) semantics: idle/working/done/error, or blocked with permission/question/auth kind. Agent `kind` remains separate. Tool/API waits are working; unknown outcomes are omitted, not inferred from disconnects or generic stops. API connection leases do not expire terminal status records.
124
124
 
@@ -133,13 +133,13 @@ This is a clean schema cutover, with no legacy aliases or compatibility shims. B
133
133
 
134
134
  ## Plugin publication
135
135
 
136
- The version-pinned beta is `@samuelho-dev/coordinator@0.3.0-beta.3`. The [npm workflow](.github/workflows/npm-release.yaml) promotes the exact-source CI-accepted tarball with owner authorization; [first-publication authentication and trust setup](#first-npm-publication) are prerequisites for a new publisher. The existing [release workflow](.github/workflows/release.yaml) publishes server/chart/GitHub artifacts, not native marketplace listings. Generated per-machine configuration is not a portable marketplace package.
136
+ The version-pinned beta is `@samuelho-dev/coordinator@0.3.0-beta.4`. The [npm workflow](.github/workflows/npm-release.yaml) promotes the exact-source CI-accepted tarball with owner authorization; [first-publication authentication and trust setup](#first-npm-publication) are prerequisites for a new publisher. The existing [release workflow](.github/workflows/release.yaml) publishes server/chart/GitHub artifacts, not native marketplace listings. Generated per-machine configuration is not a portable marketplace package.
137
137
 
138
138
  For a version-pinned install, use your native package manager, then follow [configuration](#configuration) and [native host setup](#native-host-setup):
139
139
 
140
140
  ```sh
141
- omp plugin install @samuelho-dev/coordinator@0.3.0-beta.3
142
- pi install npm:@samuelho-dev/coordinator@0.3.0-beta.3
141
+ omp plugin install @samuelho-dev/coordinator@0.3.0-beta.4
142
+ pi install npm:@samuelho-dev/coordinator@0.3.0-beta.4
143
143
  ```
144
144
 
145
145
  Stock OMP 18.12.6 does not automatically update npm plugins. Until upstream fixes its channel handling and dry-run behavior, use explicit versioned installs for updates; avoid `omp plugin upgrade` and `upgrade --dry-run` for beta releases.
@@ -148,6 +148,8 @@ Stock OMP 18.12.6 does not automatically update npm plugins. Until upstream fixe
148
148
 
149
149
  `0.3.0-beta.3` adds native `/coordinator list`, secure self-host bootstrap/authenticated client setup, and Rex references/status normalization without an OMP fork. Runtime dependency pins are unchanged.
150
150
 
151
+ `0.3.0-beta.4` fixes `/coordinator list` output: Effect-formatted, indented JSON with native syntax highlighting instead of hand-built text and literal fences. Native UI imports are static and selected at build time; the renderer registers once at startup. The session wire format and runtime dependencies are unchanged, so the existing beta.3 API needs no redeployment.
152
+
151
153
  | Host | Publication route |
152
154
  | --- | --- |
153
155
  | [OMP](https://github.com/can1357/oh-my-pi/blob/main/docs/marketplace.md) | Publish a Git-backed `.omp-plugin/marketplace.json` catalog and runnable plugin tree with `package.json` `omp.extensions`. Claude-compatible `.claude-plugin/marketplace.json` is a fallback. npm catalog sources are not supported; ordinary `omp plugin install PACKAGE` is a separate npm route. |
@@ -72327,6 +72327,8 @@ var Cache = Schema_exports.Struct({ version: Schema_exports.Literal(2), kind: Sc
72327
72327
  var ClaudeRoster = Schema_exports.Array(Schema_exports.Struct({ sessionId: Schema_exports.optional(Id2), id: Schema_exports.optional(Id2), pid: Schema_exports.optional(Schema_exports.Int), cwd: Schema_exports.optional(Schema_exports.String), kind: Schema_exports.optional(Id2), status: Schema_exports.optional(Schema_exports.Literals(["busy", "waiting", "idle"])), waitingFor: Schema_exports.optional(Schema_exports.String) })).check(Schema_exports.isMaxLength(256));
72328
72328
 
72329
72329
  // src/plugin.ts
72330
+ import { highlightCode } from "@oh-my-pi/pi-coding-agent";
72331
+ import { Text } from "@oh-my-pi/pi-tui";
72330
72332
  var provenance = (source, scope3, scopeDescription, observedAt, nativeUpdatedAt = null) => ({
72331
72333
  source,
72332
72334
  scope: scope3,
@@ -72550,23 +72552,6 @@ var registerCoordinateKeyword = Effect_exports.gen(function* () {
72550
72552
  const { isMagicKeyword, setMagicKeywords } = yield* Effect_exports.tryPromise({ try: () => import("@oh-my-pi/pi-tui/prompt/magic-keywords"), catch: () => new NativeError({ operation: "Load native keyword highlighter" }) });
72551
72553
  setMagicKeywords([...MAGIC_KEYWORDS.filter(({ word }) => isMagicKeyword(word)), { word: "coordinate", hue: [190, 260] }]);
72552
72554
  });
72553
- var formatSessionList = (sessions) => {
72554
- if (sessions.length === 0) return "No sessions are currently visible to this API key.";
72555
- const lines = [`Coordinator: ${sessions.length} sessions visible to this API key.`, "", "~~~text"];
72556
- for (const session of sessions) {
72557
- lines.push(
72558
- `Machine: ${JSON.stringify(session.machineName ?? "unavailable")} (${JSON.stringify(session.ref.machineId)})`,
72559
- `Session: ${session.ref.harness} ${JSON.stringify(session.ref.nativeSessionId)}`
72560
- );
72561
- if (session.ref.nativeAgentId !== void 0) lines.push(`Agent ID: ${JSON.stringify(session.ref.nativeAgentId)}`);
72562
- for (const [field, value5] of Object.entries(session)) {
72563
- if (field !== "ref" && field !== "machineName" && value5 !== void 0) lines.push(`${field}: ${JSON.stringify(value5)}`);
72564
- }
72565
- lines.push("");
72566
- }
72567
- lines.push("~~~");
72568
- return lines.join("\n");
72569
- };
72570
72555
  function plugin(host) {
72571
72556
  const harness = "omp";
72572
72557
  const runtime2 = ManagedRuntime_exports.make(Layer_exports.mergeAll(NodeServices_exports.layer, Host2.layer, Mcp.layer, Layer_exports.succeed(Logger_exports.LogToStderr, true)));
@@ -72576,6 +72561,10 @@ function plugin(host) {
72576
72561
  let stopped = false;
72577
72562
  const rexReporter = harness === "pi" ? createRexReporter((sequence) => process.stdout.write(sequence)) : void 0;
72578
72563
  let terminal = false;
72564
+ host.registerMessageRenderer("coordinator-list", (message) => {
72565
+ if (typeof message.content !== "string") return void 0;
72566
+ return new Text(message.details === void 0 ? message.content : highlightCode(message.content, "json").join("\n"), 0, 0);
72567
+ });
72579
72568
  host.registerCommand("coordinator", {
72580
72569
  description: "List visible sessions, their machines, and native metadata",
72581
72570
  handler: async (args2) => {
@@ -72608,11 +72597,12 @@ function plugin(host) {
72608
72597
  }, { triggerTurn: false });
72609
72598
  return;
72610
72599
  }
72600
+ const result5 = { sessions: exit3.value };
72611
72601
  host.sendMessage({
72612
72602
  customType: "coordinator-list",
72613
- content: formatSessionList(exit3.value),
72603
+ content: Formatter_exports.formatJson(result5, { space: 2 }),
72614
72604
  display: true,
72615
- details: { sessions: exit3.value }
72605
+ details: result5
72616
72606
  }, { triggerTurn: false });
72617
72607
  }
72618
72608
  });
@@ -1,6 +1,6 @@
1
1
  // src/plugin.ts
2
2
  import { NodeServices } from "@effect/platform-node";
3
- import { Cause as Cause3, Clock as Clock3, Console as Console2, Effect as Effect7, Layer as Layer3, Logger, ManagedRuntime, Schema as Schema5 } from "effect";
3
+ import { Cause as Cause3, Clock as Clock3, Console as Console2, Effect as Effect7, Formatter as Formatter2, Layer as Layer3, Logger, ManagedRuntime, Schema as Schema5 } from "effect";
4
4
 
5
5
  // src/inspection.ts
6
6
  import { Effect, Option, Path as PlatformPath, Schema, SchemaParser } from "effect";
@@ -1191,6 +1191,8 @@ var Cache = Schema4.Struct({ version: Schema4.Literal(2), kind: Schema4.Literal(
1191
1191
  var ClaudeRoster = Schema4.Array(Schema4.Struct({ sessionId: Schema4.optional(Id2), id: Schema4.optional(Id2), pid: Schema4.optional(Schema4.Int), cwd: Schema4.optional(Schema4.String), kind: Schema4.optional(Id2), status: Schema4.optional(Schema4.Literals(["busy", "waiting", "idle"])), waitingFor: Schema4.optional(Schema4.String) })).check(Schema4.isMaxLength(256));
1192
1192
 
1193
1193
  // src/plugin.ts
1194
+ import { highlightCode } from "@earendil-works/pi-coding-agent";
1195
+ import { Text } from "@earendil-works/pi-tui";
1194
1196
  var provenance = (source, scope, scopeDescription, observedAt, nativeUpdatedAt = null) => ({
1195
1197
  source,
1196
1198
  scope,
@@ -1414,23 +1416,6 @@ var registerCoordinateKeyword = Effect7.gen(function* () {
1414
1416
  const { isMagicKeyword, setMagicKeywords } = yield* Effect7.tryPromise({ try: () => import("@oh-my-pi/pi-tui/prompt/magic-keywords"), catch: () => new NativeError({ operation: "Load native keyword highlighter" }) });
1415
1417
  setMagicKeywords([...MAGIC_KEYWORDS.filter(({ word }) => isMagicKeyword(word)), { word: "coordinate", hue: [190, 260] }]);
1416
1418
  });
1417
- var formatSessionList = (sessions) => {
1418
- if (sessions.length === 0) return "No sessions are currently visible to this API key.";
1419
- const lines = [`Coordinator: ${sessions.length} sessions visible to this API key.`, "", "~~~text"];
1420
- for (const session of sessions) {
1421
- lines.push(
1422
- `Machine: ${JSON.stringify(session.machineName ?? "unavailable")} (${JSON.stringify(session.ref.machineId)})`,
1423
- `Session: ${session.ref.harness} ${JSON.stringify(session.ref.nativeSessionId)}`
1424
- );
1425
- if (session.ref.nativeAgentId !== void 0) lines.push(`Agent ID: ${JSON.stringify(session.ref.nativeAgentId)}`);
1426
- for (const [field, value] of Object.entries(session)) {
1427
- if (field !== "ref" && field !== "machineName" && value !== void 0) lines.push(`${field}: ${JSON.stringify(value)}`);
1428
- }
1429
- lines.push("");
1430
- }
1431
- lines.push("~~~");
1432
- return lines.join("\n");
1433
- };
1434
1419
  function plugin(host) {
1435
1420
  const harness = "pi";
1436
1421
  const runtime = ManagedRuntime.make(Layer3.mergeAll(NodeServices.layer, Host.layer, Mcp.layer, Layer3.succeed(Logger.LogToStderr, true)));
@@ -1440,6 +1425,10 @@ function plugin(host) {
1440
1425
  let stopped = false;
1441
1426
  const rexReporter = harness === "pi" ? createRexReporter((sequence) => process.stdout.write(sequence)) : void 0;
1442
1427
  let terminal = false;
1428
+ host.registerMessageRenderer("coordinator-list", (message) => {
1429
+ if (typeof message.content !== "string") return void 0;
1430
+ return new Text(message.details === void 0 ? message.content : highlightCode(message.content, "json").join("\n"), 0, 0);
1431
+ });
1443
1432
  host.registerCommand("coordinator", {
1444
1433
  description: "List visible sessions, their machines, and native metadata",
1445
1434
  handler: async (args) => {
@@ -1472,11 +1461,12 @@ function plugin(host) {
1472
1461
  }, { triggerTurn: false });
1473
1462
  return;
1474
1463
  }
1464
+ const result = { sessions: exit.value };
1475
1465
  host.sendMessage({
1476
1466
  customType: "coordinator-list",
1477
- content: formatSessionList(exit.value),
1467
+ content: Formatter2.formatJson(result, { space: 2 }),
1478
1468
  display: true,
1479
- details: { sessions: exit.value }
1469
+ details: result
1480
1470
  }, { triggerTurn: false });
1481
1471
  }
1482
1472
  });
@@ -1,11 +1,13 @@
1
1
  import { NodeServices } from "@effect/platform-node";
2
- import { Cause, Clock, Console, Effect, Layer, Logger, ManagedRuntime, Schema } from "effect";
2
+ import { Cause, Clock, Console, Effect, Formatter, Layer, Logger, ManagedRuntime, Schema } from "effect";
3
3
  import { createInspection, HttpError, InspectionTools, metric, sessionRefKey, unavailableMetric } from "./inspection.js";
4
4
  import { Mcp } from "./mcp.js";
5
5
  import { connectNative, loadConnectorConfig, NativeError, readConnectorToken, resolveNativeConfig, withProcessResources } from "./native.js";
6
6
  import { identifyProcess } from "./resources.js";
7
7
  import { Host as PlatformHost } from "./platform.js";
8
8
  import { createRexReporter, readRexContext } from "./rex.js";
9
+ import { highlightCode } from "@earendil-works/pi-coding-agent";
10
+ import { Text } from "@earendil-works/pi-tui";
9
11
  const provenance = (source, scope, scopeDescription, observedAt, nativeUpdatedAt = null) => ({
10
12
  source, scope, scopeDescription, observedAt, nativeUpdatedAt, estimated: false, derived: false, shared: false, partial: false, stale: false,
11
13
  });
@@ -197,23 +199,6 @@ export const registerCoordinateKeyword = Effect.gen(function* () {
197
199
  // ponytail: native exposes no registry getter/append; only known core keywords can be preserved.
198
200
  setMagicKeywords([...MAGIC_KEYWORDS.filter(({ word }) => isMagicKeyword(word)), { word: "coordinate", hue: [190, 260] }]);
199
201
  });
200
- const formatSessionList = (sessions) => {
201
- if (sessions.length === 0)
202
- return "No sessions are currently visible to this API key.";
203
- const lines = [`Coordinator: ${sessions.length} sessions visible to this API key.`, "", "~~~text"];
204
- for (const session of sessions) {
205
- lines.push(`Machine: ${JSON.stringify(session.machineName ?? "unavailable")} (${JSON.stringify(session.ref.machineId)})`, `Session: ${session.ref.harness} ${JSON.stringify(session.ref.nativeSessionId)}`);
206
- if (session.ref.nativeAgentId !== undefined)
207
- lines.push(`Agent ID: ${JSON.stringify(session.ref.nativeAgentId)}`);
208
- for (const [field, value] of Object.entries(session)) {
209
- if (field !== "ref" && field !== "machineName" && value !== undefined)
210
- lines.push(`${field}: ${JSON.stringify(value)}`);
211
- }
212
- lines.push("");
213
- }
214
- lines.push("~~~");
215
- return lines.join("\n");
216
- };
217
202
  export default function plugin(host) {
218
203
  const harness = COORDINATOR_HARNESS;
219
204
  const runtime = ManagedRuntime.make(Layer.mergeAll(NodeServices.layer, PlatformHost.layer, Mcp.layer, Layer.succeed(Logger.LogToStderr, true)));
@@ -224,6 +209,11 @@ export default function plugin(host) {
224
209
  // Stock OMP owns OSC 7501 (terminal.programStatus); never duplicate or override it.
225
210
  const rexReporter = harness === "pi" ? createRexReporter((sequence) => process.stdout.write(sequence)) : undefined;
226
211
  let terminal = false;
212
+ host.registerMessageRenderer("coordinator-list", (message) => {
213
+ if (typeof message.content !== "string")
214
+ return undefined;
215
+ return new Text(message.details === undefined ? message.content : highlightCode(message.content, "json").join("\n"), 0, 0);
216
+ });
227
217
  host.registerCommand("coordinator", {
228
218
  description: "List visible sessions, their machines, and native metadata",
229
219
  handler: async (args) => {
@@ -259,9 +249,10 @@ export default function plugin(host) {
259
249
  }, { triggerTurn: false });
260
250
  return;
261
251
  }
252
+ const result = { sessions: exit.value };
262
253
  host.sendMessage({
263
- customType: "coordinator-list", content: formatSessionList(exit.value), display: true,
264
- details: { sessions: exit.value },
254
+ customType: "coordinator-list", content: Formatter.formatJson(result, { space: 2 }), display: true,
255
+ details: result,
265
256
  }, { triggerTurn: false });
266
257
  },
267
258
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samuelho-dev/coordinator",
3
- "version": "0.3.0-beta.3",
3
+ "version": "0.3.0-beta.4",
4
4
  "type": "module",
5
5
  "description": "Read-only native agent session inspection across self-hosted machines",
6
6
  "license": "MIT",
@@ -53,6 +53,7 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@earendil-works/pi-coding-agent": "1.0.4",
56
+ "@earendil-works/pi-tui": "1.0.4",
56
57
  "@effect/tsgo": "0.49.0",
57
58
  "@effect/vitest": "4.0.3",
58
59
  "@oh-my-pi/pi-coding-agent": "18.6.1",