@itsaplan/runner 0.5.0 → 0.5.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.
Files changed (3) hide show
  1. package/README.md +10 -6
  2. package/dist/cli.js +85 -1
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -7,8 +7,8 @@ This package runs such agents on your own machine — one, or several at once.
7
7
 
8
8
  - Polls your instance for the agent's queued runs. Runs each one with a coding agent CLI.
9
9
  Reports the result.
10
- - Has presets for Claude Code, Codex, opencode, Antigravity CLI and GitHub Copilot CLI.
11
- Each preset sets the unattended flags and the session resume.
10
+ - Has presets for Claude Code, Codex, opencode, Antigravity CLI, GitHub Copilot CLI,
11
+ Pi, and Oh My Pi (`omp`). Each preset sets the unattended flags and the session resume.
12
12
  - Runs your own `command` instead, if you prefer. The command takes the task on stdin.
13
13
  - Answers the agent's chat. Sends the text and the tool calls while the CLI prints them.
14
14
 
@@ -20,8 +20,9 @@ of kind External. The key appears one time only, at creation.
20
20
  **2. Enable MCP** for the project, in Settings, MCP Server. MCP is off by default. The
21
21
  agent reads the issue and writes its result through it.
22
22
 
23
- **3. Give the coding agent the address of that server.** Claude Code reads `.mcp.json`
24
- from the folder it runs in. For the other four CLIs, see
23
+ **3. Give the coding agent the address of that server.** Claude Code, Oh My Pi, and Pi
24
+ (through `pi-mcp-adapter`) read `.mcp.json` from the folder they run in. For the other
25
+ CLIs, see
25
26
  [Coding agent setup](https://github.com/croffasia/itsaplan/blob/main/docs/runner.md).
26
27
 
27
28
  ```json
@@ -70,6 +71,8 @@ flags for an unattended run, and the session resume. Every preset keeps a chat s
70
71
  | `opencode` | opencode |
71
72
  | `antigravity` | Antigravity CLI |
72
73
  | `copilot` | GitHub Copilot CLI |
74
+ | `pi` | Pi |
75
+ | `omp` | Oh My Pi |
73
76
 
74
77
  Each preset needs the CLI's own MCP config.
75
78
  [Coding agent setup](https://github.com/croffasia/itsaplan/blob/main/docs/runner.md) holds
@@ -188,7 +191,7 @@ npx -y @itsaplan/runner --agent claude
188
191
  The server writes the task text. The text states what occurred, what to do, and to post
189
192
  the result as a comment on the issue. Your own `command` receives the text on **stdin**. A
190
193
  preset gives it to its CLI in the way that CLI accepts it: on stdin for `claude` and
191
- `codex`, as an argument for `antigravity`, `copilot` and `opencode`.
194
+ `codex`, as an argument for `antigravity`, `copilot`, `opencode`, `pi` and `omp`.
192
195
 
193
196
  The agent reads all other data through the MCP server at `$ITSAPLAN_URL/mcp`. The agent
194
197
  sends `$ITSAPLAN_API_KEY` as a bearer token, and acts as its own user with its role.
@@ -235,7 +238,8 @@ calls with the answer. `outputFormat` tells the runner how to read the output:
235
238
 
236
239
  - `text` — all the output is the answer.
237
240
  - `claude-stream-json`, `codex-jsonl`, `opencode-json`, `antigravity-stream-json`,
238
- `copilot-json` — the event stream of that CLI.
241
+ `copilot-json`, `pi-json` — the event stream of that CLI. `pi` and `omp` both use
242
+ `pi-json`.
239
243
 
240
244
  A preset sets `outputFormat` for you. Set it yourself only with your own `command`. If the
241
245
  output does not agree with the format, the runner sends the output as plain text.
package/dist/cli.js CHANGED
@@ -149,6 +149,43 @@ class AnswerStream {
149
149
  case "copilot-json":
150
150
  this.readCopilotLine(parsed);
151
151
  break;
152
+ case "pi-json":
153
+ this.readPiLine(parsed);
154
+ break;
155
+ }
156
+ }
157
+ readPiLine(message) {
158
+ if (message.type === "session" && message.id)
159
+ this.sessionId ??= message.id;
160
+ switch (message.type) {
161
+ case "message_update": {
162
+ const event = message.assistantMessageEvent;
163
+ if (event?.type === "text_delta" && event.delta) {
164
+ this.sawPartialText = true;
165
+ this.appendText(event.delta);
166
+ }
167
+ return;
168
+ }
169
+ case "tool_execution_start":
170
+ if (message.toolCallId && !this.openToolCalls.has(message.toolCallId)) {
171
+ this.openToolCalls.add(message.toolCallId);
172
+ this.pushToolCall(message.toolCallId, message.toolName ?? "tool", JSON.stringify(message.args ?? {}));
173
+ }
174
+ return;
175
+ case "tool_execution_end": {
176
+ if (!message.toolCallId || this.closedToolCalls.has(message.toolCallId))
177
+ return;
178
+ this.closedToolCalls.add(message.toolCallId);
179
+ this.pushToolResult(message.toolCallId, piResultText(message.result));
180
+ return;
181
+ }
182
+ case "message_end":
183
+ if (message.message?.role === "assistant" && !this.sawAnyText && message.message.content) {
184
+ const body = textOfResult(message.message.content);
185
+ if (body)
186
+ this.appendText(body);
187
+ }
188
+ return;
152
189
  }
153
190
  }
154
191
  readCopilotLine(message) {
@@ -374,6 +411,9 @@ class UsageReader {
374
411
  case "antigravity-stream-json":
375
412
  this.readAntigravity(parsed);
376
413
  return;
414
+ case "pi-json":
415
+ this.readPi(parsed);
416
+ return;
377
417
  }
378
418
  }
379
419
  readClaude(message) {
@@ -422,6 +462,15 @@ class UsageReader {
422
462
  outputTokens: (usage.output_tokens ?? 0) + (usage.thinking_tokens ?? 0)
423
463
  };
424
464
  }
465
+ readPi(message) {
466
+ const usage = message.usage;
467
+ if (!usage)
468
+ return;
469
+ this.last = {
470
+ inputTokens: (usage.input ?? usage.input_tokens ?? 0) + (usage.cacheRead ?? 0),
471
+ outputTokens: usage.output ?? usage.output_tokens ?? 0
472
+ };
473
+ }
425
474
  }
426
475
  function tail(text, limit) {
427
476
  return text.length <= limit ? text : `…${text.slice(-limit)}`;
@@ -434,6 +483,13 @@ function textOfResult(content) {
434
483
  }
435
484
  return "";
436
485
  }
486
+ function piResultText(result) {
487
+ if (result && typeof result === "object" && !Array.isArray(result) && "content" in result) {
488
+ return textOfResult(result.content);
489
+ }
490
+ const text = textOfResult(result);
491
+ return text || (result == null ? "" : JSON.stringify(result));
492
+ }
437
493
 
438
494
  // src/execute.ts
439
495
  import { spawn } from "node:child_process";
@@ -510,6 +566,33 @@ var PRESETS = {
510
566
  ...sessionId ? ["--session-id", sessionId] : []
511
567
  ],
512
568
  tail: ["-p"]
569
+ },
570
+ pi: {
571
+ bin: "pi",
572
+ outputFormat: "pi-json",
573
+ promptVia: "arg",
574
+ systemPromptFlag: "--append-system-prompt",
575
+ head: (sessionId) => [
576
+ "-p",
577
+ "--mode",
578
+ "json",
579
+ ...sessionId ? ["--session-id", sessionId] : []
580
+ ],
581
+ tail: []
582
+ },
583
+ omp: {
584
+ bin: "omp",
585
+ outputFormat: "pi-json",
586
+ promptVia: "arg",
587
+ systemPromptFlag: "--append-system-prompt",
588
+ head: (sessionId) => [
589
+ "-p",
590
+ "--mode",
591
+ "json",
592
+ "--auto-approve",
593
+ ...sessionId ? ["--resume", sessionId] : []
594
+ ],
595
+ tail: []
513
596
  }
514
597
  };
515
598
  var PRESET_NAMES = Object.keys(PRESETS);
@@ -540,7 +623,8 @@ var OUTPUT_FORMATS = [
540
623
  "codex-jsonl",
541
624
  "opencode-json",
542
625
  "antigravity-stream-json",
543
- "copilot-json"
626
+ "copilot-json",
627
+ "pi-json"
544
628
  ];
545
629
  function presetOf(config) {
546
630
  if (config.command || !config.agent)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itsaplan/runner",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Runs an Itsaplan external agent's queued tasks and answers its chat on your own machine",
5
5
  "keywords": [
6
6
  "itsaplan",
@@ -18,7 +18,9 @@
18
18
  "claude-code",
19
19
  "codex",
20
20
  "antigravity",
21
- "opencode"
21
+ "opencode",
22
+ "pi",
23
+ "omp"
22
24
  ],
23
25
  "homepage": "https://github.com/croffasia/itsaplan/tree/main/packages/runner#readme",
24
26
  "repository": {