@liy/agent-runner 0.1.0 → 0.2.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
@@ -191,8 +191,10 @@ pi --mode rpc --provider deepseek --model deepseek-v4-flash --thinking high --no
191
191
  ```
192
192
 
193
193
  The driver writes one Pi RPC `prompt` command to stdin, parses Pi stdout as
194
- byte-buffered JSONL, forwards Pi events as `task.progress`, and cancels with
195
- Pi `abort`, then `SIGTERM`, then `SIGKILL` after five seconds.
194
+ byte-buffered JSONL, forwards native Pi records as `pi.event` or
195
+ `pi.extension_ui_request`, routes malformed stdout/stderr as
196
+ `harness.stdout`/`harness.stderr`, and cancels with Pi `abort`, then
197
+ `SIGTERM`, then `SIGKILL` after five seconds.
196
198
 
197
199
  Direct DeepSeek token example:
198
200
 
@@ -32,3 +32,11 @@ export declare function shouldPrintHelp(argv: string[]): boolean;
32
32
  * @returns Help text.
33
33
  */
34
34
  export declare function formatHelp(): string;
35
+ /**
36
+ * Check whether this module is executing as the Node entrypoint.
37
+ *
38
+ * @param moduleUrl - Current module URL.
39
+ * @param argvPath - Process entrypoint path, defaulting to `process.argv[1]`.
40
+ * @returns Whether the module should run the CLI.
41
+ */
42
+ export declare function isEntrypoint(moduleUrl: string, argvPath?: string | undefined): boolean;
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as ___liy_agent_runnerCreateRequire } from "node:module";var require = ___liy_agent_runnerCreateRequire(import.meta.url);
2
3
  var __defProp = Object.defineProperty;
3
4
  var __export = (target, all) => {
4
5
  for (var name in all)
@@ -6,6 +7,7 @@ var __export = (target, all) => {
6
7
  };
7
8
 
8
9
  // src/bin/agent-runner.ts
10
+ import { realpathSync } from "node:fs";
9
11
  import { resolve } from "node:path";
10
12
  import { fileURLToPath } from "node:url";
11
13
 
@@ -15334,25 +15336,17 @@ function forwardJsonlByteStream(stream, onLine) {
15334
15336
  });
15335
15337
  });
15336
15338
  }
15337
- function forwardHarnessLine(channel, line, streamName, sanitizer, driver) {
15339
+ function forwardHarnessLine(channel, taskId, harness, line, streamName, sanitizer) {
15338
15340
  const trimmed = sanitizer.redactText(line.trim());
15339
15341
  if (!trimmed) {
15340
15342
  return;
15341
15343
  }
15342
- try {
15343
- const parsed = JSON.parse(trimmed);
15344
- channel.send(createExecuteTaskRpcNotification("task.progress", {
15345
- ...driver ? { driver } : {},
15346
- stream: streamName,
15347
- event: sanitizer.redactJson(parsed)
15348
- }));
15349
- } catch {
15350
- channel.send(createExecuteTaskRpcNotification("task.log", {
15351
- ...driver ? { driver } : {},
15352
- stream: streamName,
15353
- message: trimmed
15354
- }));
15355
- }
15344
+ channel.send(createExecuteTaskRpcNotification(`harness.${streamName}`, {
15345
+ taskId,
15346
+ harness,
15347
+ stream: streamName,
15348
+ message: trimmed
15349
+ }));
15356
15350
  }
15357
15351
  function waitForChildClose(child) {
15358
15352
  return new Promise((resolve2, reject) => {
@@ -15432,10 +15426,10 @@ function startCodexJsonlHarness(input, spawnProcess) {
15432
15426
  let cleanupTermination = () => void 0;
15433
15427
  child.stdin.end(input.prompt);
15434
15428
  const stdoutDone = forwardHarnessLines(child.stdout, (line) => {
15435
- forwardHarnessLine(input.channel, line, "stdout", sanitizer);
15429
+ forwardHarnessLine(input.channel, input.spec.taskId, "codex-jsonl", line, "stdout", sanitizer);
15436
15430
  });
15437
15431
  const stderrDone = forwardHarnessLines(child.stderr, (line) => {
15438
- forwardHarnessLine(input.channel, line, "stderr", sanitizer);
15432
+ forwardHarnessLine(input.channel, input.spec.taskId, "codex-jsonl", line, "stderr", sanitizer);
15439
15433
  });
15440
15434
  const result = waitForChildClose(child).then(async (closeResult) => {
15441
15435
  cleanupTermination();
@@ -15585,11 +15579,11 @@ function startPiRpcHarness(input, spawnProcess) {
15585
15579
  cleanupTermination();
15586
15580
  await Promise.all([stdoutDone, stderrDone]);
15587
15581
  if (!agentEndReached && terminal.exitCode !== 0) {
15588
- input.channel.send(createExecuteTaskRpcNotification("task.log", {
15589
- driver: "pi-rpc",
15590
- stream: "stderr",
15591
- message: `pi-rpc process closed before agent_end with ${formatHarnessExit(terminal)}`
15592
- }));
15582
+ forwardPiHarnessStreamLine(
15583
+ input,
15584
+ "stderr",
15585
+ `pi-rpc process closed before agent_end with ${formatHarnessExit(terminal)}`
15586
+ );
15593
15587
  }
15594
15588
  return terminal;
15595
15589
  })();
@@ -15611,37 +15605,57 @@ function handlePiRpcStdoutLine(input) {
15611
15605
  try {
15612
15606
  parsed = JSON.parse(trimmed);
15613
15607
  } catch {
15614
- input.input.channel.send(createExecuteTaskRpcNotification("task.log", {
15615
- driver: "pi-rpc",
15616
- stream: "stdout",
15617
- message: input.sanitizer.redactText(trimmed)
15618
- }));
15608
+ forwardPiHarnessStreamLine(input.input, "stdout", input.sanitizer.redactText(trimmed));
15619
15609
  return;
15620
15610
  }
15621
- input.input.channel.send(createExecuteTaskRpcNotification("task.progress", {
15622
- driver: "pi-rpc",
15623
- stream: "stdout",
15624
- event: input.sanitizer.redactJson(parsed)
15625
- }));
15626
- if (parsed.type === "response" && parsed.command === "prompt" && parsed.success === false) {
15627
- input.onPromptRejected(new Error(`Pi RPC prompt was rejected: ${formatPiRpcError(parsed, input.sanitizer.redactText)}`));
15611
+ if (isPiRpcResponse(parsed)) {
15612
+ if (parsed.command === "prompt" && parsed.success === false) {
15613
+ input.onPromptRejected(new Error(`Pi RPC prompt was rejected: ${formatPiRpcError(parsed, input.sanitizer.redactText)}`));
15614
+ }
15628
15615
  return;
15629
15616
  }
15617
+ if (isPiExtensionUiRequest(parsed)) {
15618
+ forwardPiExtensionUiRequest(input.input, input.sanitizer.redactJson(parsed));
15619
+ return;
15620
+ }
15621
+ forwardPiEvent(input.input, input.sanitizer.redactJson(parsed));
15630
15622
  if (parsed.type === "agent_end") {
15631
15623
  input.onAgentEnd();
15632
15624
  }
15633
15625
  }
15634
- function forwardPiStderrLine(input, line, sanitizer) {
15635
- const trimmed = sanitizer.redactText(line.trim());
15626
+ function forwardPiEvent(input, event) {
15627
+ input.channel.send(createExecuteTaskRpcNotification("pi.event", {
15628
+ taskId: input.spec.taskId,
15629
+ event
15630
+ }));
15631
+ }
15632
+ function forwardPiExtensionUiRequest(input, request) {
15633
+ input.channel.send(createExecuteTaskRpcNotification("pi.extension_ui_request", {
15634
+ taskId: input.spec.taskId,
15635
+ request
15636
+ }));
15637
+ }
15638
+ function isPiRpcResponse(parsed) {
15639
+ return parsed.type === "response" && typeof parsed.command === "string";
15640
+ }
15641
+ function isPiExtensionUiRequest(parsed) {
15642
+ return parsed.type === "extension_ui_request" && typeof parsed.id === "string";
15643
+ }
15644
+ function forwardPiHarnessStreamLine(input, stream, message) {
15645
+ const trimmed = message.trim();
15636
15646
  if (!trimmed) {
15637
15647
  return;
15638
15648
  }
15639
- input.channel.send(createExecuteTaskRpcNotification("task.log", {
15640
- driver: "pi-rpc",
15641
- stream: "stderr",
15649
+ input.channel.send(createExecuteTaskRpcNotification(`harness.${stream}`, {
15650
+ taskId: input.spec.taskId,
15651
+ harness: "pi-rpc",
15652
+ stream,
15642
15653
  message: trimmed
15643
15654
  }));
15644
15655
  }
15656
+ function forwardPiStderrLine(input, line, sanitizer) {
15657
+ forwardPiHarnessStreamLine(input, "stderr", sanitizer.redactText(line));
15658
+ }
15645
15659
  function writePiRpcCommand(child, command) {
15646
15660
  child.stdin.write(`${JSON.stringify(command)}
15647
15661
  `);
@@ -15768,30 +15782,40 @@ async function runTaskAgentRunner(spec, options = {}) {
15768
15782
  const harness = resolveAgentRunnerHarness(config2, spec.agentRunner);
15769
15783
  const channel = await openControlChannel(spec.rpcUrl);
15770
15784
  try {
15771
- channel.send(createExecuteTaskRpcNotification("task.started", {
15785
+ sendTaskStatus(channel, {
15772
15786
  taskId: spec.taskId,
15773
- workspaceDir: spec.workspaceDir
15774
- }));
15787
+ status: "running"
15788
+ });
15775
15789
  const completion = await runHarnessAndReadCompletion({
15776
15790
  spec,
15777
15791
  harness,
15778
15792
  channel,
15779
15793
  ...options.env ? { env: options.env } : {}
15780
15794
  });
15781
- channel.send(createExecuteTaskRpcNotification(`task.${completion.status}`, {
15795
+ sendTaskStatus(channel, {
15782
15796
  taskId: spec.taskId,
15783
15797
  ...completion
15784
- }));
15798
+ });
15785
15799
  return completion;
15800
+ } catch (error48) {
15801
+ const completion = createFailedCompletion(error48);
15802
+ await writeTaskCompletion({
15803
+ paths,
15804
+ completion
15805
+ }).catch(() => void 0);
15806
+ try {
15807
+ sendTaskStatus(channel, {
15808
+ taskId: spec.taskId,
15809
+ ...completion
15810
+ });
15811
+ } catch {
15812
+ }
15813
+ throw error48;
15786
15814
  } finally {
15787
15815
  channel.close();
15788
15816
  }
15789
15817
  } catch (error48) {
15790
- const completion = {
15791
- status: "failed",
15792
- summary: error48 instanceof Error ? error48.message : String(error48),
15793
- artifactIds: []
15794
- };
15818
+ const completion = createFailedCompletion(error48);
15795
15819
  await writeTaskCompletion({
15796
15820
  paths,
15797
15821
  completion
@@ -15799,6 +15823,16 @@ async function runTaskAgentRunner(spec, options = {}) {
15799
15823
  throw error48;
15800
15824
  }
15801
15825
  }
15826
+ function sendTaskStatus(channel, params) {
15827
+ channel.send(createExecuteTaskRpcNotification("task.status", params));
15828
+ }
15829
+ function createFailedCompletion(error48) {
15830
+ return {
15831
+ status: "failed",
15832
+ summary: error48 instanceof Error ? error48.message : String(error48),
15833
+ artifactIds: []
15834
+ };
15835
+ }
15802
15836
  function createHarnessEnvironment(input) {
15803
15837
  const baseEnv = input.env ?? process.env;
15804
15838
  const harnessEnv = {};
@@ -15906,7 +15940,14 @@ async function runHarnessAndReadCompletion(input) {
15906
15940
  });
15907
15941
  return completion2;
15908
15942
  }
15909
- const completion = await readTaskCompletion(paths);
15943
+ const completion = await readTaskCompletion(paths).catch(async (error48) => {
15944
+ const fallback = createMissingCompletionFailure(error48);
15945
+ await writeTaskCompletion({
15946
+ paths,
15947
+ completion: fallback
15948
+ });
15949
+ return fallback;
15950
+ });
15910
15951
  await validateTaskArtifactFiles({
15911
15952
  paths,
15912
15953
  completion
@@ -15916,6 +15957,14 @@ async function runHarnessAndReadCompletion(input) {
15916
15957
  }
15917
15958
  return completion;
15918
15959
  }
15960
+ function createMissingCompletionFailure(error48) {
15961
+ const detail = error48 instanceof Error ? error48.message : String(error48);
15962
+ return {
15963
+ status: "failed",
15964
+ summary: `harness ended without writing state/completion.json: ${detail}`,
15965
+ artifactIds: []
15966
+ };
15967
+ }
15919
15968
  function validateRunnerSpec(spec) {
15920
15969
  if ("harness" in spec) {
15921
15970
  throw new Error("task spec harness is no longer supported; use task spec agentRunner");
@@ -16063,11 +16112,20 @@ if (isEntrypoint(import.meta.url)) {
16063
16112
  process.exitCode = 1;
16064
16113
  });
16065
16114
  }
16066
- function isEntrypoint(moduleUrl) {
16067
- return process.argv[1] ? fileURLToPath(moduleUrl) === resolve(process.argv[1]) : false;
16115
+ function isEntrypoint(moduleUrl, argvPath = process.argv[1]) {
16116
+ return argvPath ? realpathEntrypointPath(fileURLToPath(moduleUrl)) === realpathEntrypointPath(argvPath) : false;
16117
+ }
16118
+ function realpathEntrypointPath(path) {
16119
+ const resolved = resolve(path);
16120
+ try {
16121
+ return realpathSync.native(resolved);
16122
+ } catch {
16123
+ return resolved;
16124
+ }
16068
16125
  }
16069
16126
  export {
16070
16127
  formatHelp,
16128
+ isEntrypoint,
16071
16129
  main,
16072
16130
  readConfigPathArg,
16073
16131
  readTaskSpecArg,