@agimon-ai/po-runner 0.0.0-alpha.31 → 0.0.0-alpha.32

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 (82) hide show
  1. package/README.md +10 -8
  2. package/dist/{bashRunService-DQeetQzV.mjs → bashRunService-CmjnipLE.mjs} +2 -2
  3. package/dist/bashRunService-CmjnipLE.mjs.map +1 -0
  4. package/dist/{bashRunService-DGZZGWLL.cjs → bashRunService-DLpFoP81.cjs} +2 -2
  5. package/dist/bashRunService-DLpFoP81.cjs.map +1 -0
  6. package/dist/bashRunService.cjs +1 -1
  7. package/dist/bashRunService.d.mts.map +1 -1
  8. package/dist/bashRunService.mjs +1 -1
  9. package/dist/bashSchema.cjs +1 -1
  10. package/dist/bashSchema.d.mts +1 -1
  11. package/dist/bashSchema.mjs +1 -1
  12. package/dist/{bashTool-Bahf40vt.cjs → bashTool-CfNNdq62.cjs} +7 -13
  13. package/dist/bashTool-CfNNdq62.cjs.map +1 -0
  14. package/dist/bashTool-DRW3lseL.mjs +26 -0
  15. package/dist/bashTool-DRW3lseL.mjs.map +1 -0
  16. package/dist/bashTool-Dc1ld2E3.d.mts +14 -0
  17. package/dist/bashTool-Dc1ld2E3.d.mts.map +1 -0
  18. package/dist/bashTool.cjs +2 -2
  19. package/dist/bashTool.d.mts +1 -1
  20. package/dist/bashTool.mjs +2 -2
  21. package/dist/bin/cli.cjs +1 -1
  22. package/dist/bin/cli.mjs +1 -1
  23. package/dist/cliApp.d.mts +1 -1
  24. package/dist/extensions/mcp.cjs +6 -6
  25. package/dist/extensions/mcp.cjs.map +1 -1
  26. package/dist/extensions/mcp.mjs +6 -6
  27. package/dist/extensions/mcp.mjs.map +1 -1
  28. package/dist/extensions/server.cjs +27 -32
  29. package/dist/extensions/server.cjs.map +1 -1
  30. package/dist/extensions/server.mjs +27 -32
  31. package/dist/extensions/server.mjs.map +1 -1
  32. package/dist/{headless-as3Q6ucs.cjs → headless-BlgjJiv0.cjs} +10 -27
  33. package/dist/headless-BlgjJiv0.cjs.map +1 -0
  34. package/dist/{headless-VzfNzuEv.mjs → headless-kp9-KBp3.mjs} +11 -28
  35. package/dist/headless-kp9-KBp3.mjs.map +1 -0
  36. package/dist/{index-Df58fJ3b.d.mts → index-BhS6r6Eq.d.mts} +4 -6
  37. package/dist/index-BhS6r6Eq.d.mts.map +1 -0
  38. package/dist/{index-DM7yJpMs.d.mts → index-DBQPUAC3.d.mts} +2 -2
  39. package/dist/index-DBQPUAC3.d.mts.map +1 -0
  40. package/dist/{index-COFsd7Mb.d.mts → index-W2PLbgCR.d.mts} +2 -2
  41. package/dist/{index-COFsd7Mb.d.mts.map → index-W2PLbgCR.d.mts.map} +1 -1
  42. package/dist/index.cjs +2 -2
  43. package/dist/index.d.mts +2 -2
  44. package/dist/index.mjs +2 -2
  45. package/dist/{logReader-BEneVvSC.cjs → logReader-3RzQjCs4.cjs} +76 -29
  46. package/dist/logReader-3RzQjCs4.cjs.map +1 -0
  47. package/dist/{logReader-D1xSM6uE.mjs → logReader-DpO_fcDj.mjs} +76 -29
  48. package/dist/logReader-DpO_fcDj.mjs.map +1 -0
  49. package/dist/{logReader-MdW9ffvV.d.mts → logReader-wZC8OH3h.d.mts} +3 -1
  50. package/dist/{logReader-MdW9ffvV.d.mts.map → logReader-wZC8OH3h.d.mts.map} +1 -1
  51. package/dist/logReader.cjs +1 -1
  52. package/dist/logReader.d.mts +2 -2
  53. package/dist/logReader.mjs +1 -1
  54. package/dist/responseEnvelope.cjs +1 -1
  55. package/dist/responseEnvelope.d.mts +1 -1
  56. package/dist/responseEnvelope.mjs +1 -1
  57. package/dist/{runnerDependencies-DRtNq2hj.mjs → runnerDependencies-C6K2P-ID.mjs} +3 -3
  58. package/dist/{runnerDependencies-DRtNq2hj.mjs.map → runnerDependencies-C6K2P-ID.mjs.map} +1 -1
  59. package/dist/{runnerDependencies-D7v_k-sz.cjs → runnerDependencies-DOY30X-w.cjs} +3 -3
  60. package/dist/{runnerDependencies-D7v_k-sz.cjs.map → runnerDependencies-DOY30X-w.cjs.map} +1 -1
  61. package/dist/runnerDependencies.cjs +1 -1
  62. package/dist/runnerDependencies.d.mts +1 -1
  63. package/dist/runnerDependencies.mjs +1 -1
  64. package/dist/{type-BrjS0_wq.d.mts → type-DmfWxPZQ.d.mts} +2 -2
  65. package/dist/{type-BrjS0_wq.d.mts.map → type-DmfWxPZQ.d.mts.map} +1 -1
  66. package/dist/types.d.mts +1 -1
  67. package/package.json +16 -16
  68. package/src/prompts/codemode-how-to-runner/SKILL.md +6 -4
  69. package/src/prompts/help-how-to-runner/SKILL.md +5 -4
  70. package/dist/bashRunService-DGZZGWLL.cjs.map +0 -1
  71. package/dist/bashRunService-DQeetQzV.mjs.map +0 -1
  72. package/dist/bashTool-Bahf40vt.cjs.map +0 -1
  73. package/dist/bashTool-DAhPY4ID.d.mts +0 -20
  74. package/dist/bashTool-DAhPY4ID.d.mts.map +0 -1
  75. package/dist/bashTool-gjIKvJQ-.mjs +0 -32
  76. package/dist/bashTool-gjIKvJQ-.mjs.map +0 -1
  77. package/dist/headless-VzfNzuEv.mjs.map +0 -1
  78. package/dist/headless-as3Q6ucs.cjs.map +0 -1
  79. package/dist/index-DM7yJpMs.d.mts.map +0 -1
  80. package/dist/index-Df58fJ3b.d.mts.map +0 -1
  81. package/dist/logReader-BEneVvSC.cjs.map +0 -1
  82. package/dist/logReader-D1xSM6uE.mjs.map +0 -1
package/README.md CHANGED
@@ -40,7 +40,7 @@ it to a named layer to enable it only in selected major modes.
40
40
 
41
41
  ```json
42
42
  {
43
- "command": "pnpm test",
43
+ "command": ["pnpm test"],
44
44
  "timeout": 60
45
45
  }
46
46
  ```
@@ -49,7 +49,7 @@ Commands crossing the promotion threshold move to a supervised runner. The defau
49
49
  seconds. Set `background: true` to detach immediately, or `interactive: true` only when a command
50
50
  needs terminal input.
51
51
 
52
- Pass an array to run dependent commands in separate fresh shells, sequentially and fail-fast:
52
+ Always pass `command` as an array, including for one command. Dependent commands run in separate fresh shells, sequentially and fail-fast:
53
53
 
54
54
  ```json
55
55
  {
@@ -59,9 +59,11 @@ Pass an array to run dependent commands in separate fresh shells, sequentially a
59
59
  }
60
60
  ```
61
61
 
62
- Arrays are noninteractive. Each command gets its own timeout and complete log. The result lists all
63
- attempted log paths and only the last executed command's trimmed output. Shell state such as `cd` and
64
- `export` does not carry between entries. Keep repository mutations separate from verification.
62
+ With `interactive: true`, only the last command gets a pseudo terminal. Runner returns control when
63
+ that stage starts; inspect its stage runner ID and logs, then use that ID for input, not the sequence ID.
64
+ Each command gets its own timeout and complete log. The result lists all attempted log paths and only
65
+ the last executed command's trimmed output. Shell state such as `cd` and `export` does not carry
66
+ between entries. Keep repository mutations separate from verification.
65
67
  A promoted array remains one supervised sequence, and its next command waits for the current process
66
68
  to actually exit. Native sessions receive one aggregate completion; remote MCP callers poll.
67
69
 
@@ -119,9 +121,9 @@ Session removal, restart, or termination stops its runner processes and removes
119
121
  and registry entries. An external observer handles owner hard-kill cleanup. Compaction and ordinary
120
122
  activity changes do not remove evidence. Save important deliverables to the session artifact folder.
121
123
 
122
- Runner automatically saves complete command output, so do not add redirects just to preserve it.
123
- Inspect saved logs when an excerpt is truncated instead of rerunning the command. Result limits and
124
- the promotion threshold remain environment-configurable.
124
+ Do not pipe or redirect command output to a file, `head`, or `tail`. Runner automatically saves full
125
+ logs and bounds returned output. Inspect saved logs when an excerpt is truncated instead of rerunning
126
+ the command. Result limits and the promotion threshold remain environment-configurable.
125
127
 
126
128
  ### Result excerpts
127
129
 
@@ -225,7 +225,7 @@ var BashRunService = class {
225
225
  error: "Operation aborted"
226
226
  };
227
227
  }
228
- if (request.background === true || interactive) return this.promote(handle, request.background === true ? "requested" : "interactive", request.signal);
228
+ if (request.waitForExit !== true && (request.background === true || interactive)) return this.promote(handle, request.background === true ? "requested" : "interactive", request.signal);
229
229
  const outputUpdates = request.onOutput ? this.followOutput(handle, request.onOutput) : void 0;
230
230
  try {
231
231
  const outcome = await this.race(handle, request.timeoutMs, request.signal, request.waitForExit !== true);
@@ -446,4 +446,4 @@ var BashRunService = class {
446
446
  //#endregion
447
447
  export { BashRunService as t };
448
448
 
449
- //# sourceMappingURL=bashRunService-DQeetQzV.mjs.map
449
+ //# sourceMappingURL=bashRunService-CmjnipLE.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashRunService-CmjnipLE.mjs","names":[],"sources":["../src/constants/bashRunService.ts","../src/services/bashRunService/resources.ts","../src/services/bashRunService/index.ts"],"sourcesContent":["export const RUNNER_ID_RANDOM_BYTES = 3;\nexport const OUTPUT_UPDATE_POLL_MS = 100;\nexport const COMPLETED = 'completed';\nexport const FAILED = 'failed';\nexport const LAUNCHER_ERROR = 'launcher_error';\nexport const SIGNALED = 'signaled';\n/** An interactive launch found neither multiplexer. */\nexport const TERMINAL_UNAVAILABLE = 'A terminal needs rmux or tmux, and neither is available on this machine.';\n","/** Split shell words without mistaking quoted examples for executed commands. */\nfunction commandInvocations(command: string): string[][] {\n const invocations: string[][] = [];\n let words: string[] = [];\n let word = '';\n let quote = '';\n let escaped = false;\n const flushWord = (): void => {\n if (word) words.push(word);\n word = '';\n };\n for (const character of command) {\n if (escaped) {\n word += character;\n escaped = false;\n } else if (character === '\\\\' && quote !== \"'\") {\n escaped = true;\n } else if (quote) {\n if (character === quote) quote = '';\n else word += character;\n } else if (character === '\"' || character === \"'\") {\n quote = character;\n } else if (';&|\\n'.includes(character)) {\n flushWord();\n if (words.length) invocations.push(words);\n words = [];\n } else if (/\\s/.test(character)) {\n flushWord();\n } else {\n word += character;\n }\n }\n flushWord();\n if (words.length) invocations.push(words);\n return invocations;\n}\n\nfunction executableName(word: string): string {\n return word.replace(/\\\\/g, '/').split('/').pop() ?? word;\n}\n\n/** Admission policy, not a shell security boundary. Opaque scripts still need explicit ownership. */\nexport function isHeavyCommand(command: string): boolean {\n const heavyTarget =\n /(?:^|[\\s:,=])(?:build(?:-[\\w-]+)?|test(?:-[\\w-]+)?|lint|fixcode|typecheck|check|bundle)(?:[\\s:,=]|$)/;\n const expensiveBinary =\n /^(?:vitest|jest|tsc|tsgo|tsdown|webpack|rollup|esbuild|oxlint|oxfmt|pytest|maestro|xcodebuild|gradle|gradlew)$/;\n return commandInvocations(command).some((words) => {\n while (words.length) {\n const first = words[0]!;\n if (/^[A-Za-z_][A-Za-z_0-9]*=/.test(first) || /^(?:env|command|exec|time)$/.test(executableName(first))) {\n words.shift();\n } else break;\n }\n let executable = executableName(words.shift() ?? '');\n if (words.includes('--help') || words.includes('--version')) return false;\n if (/^(?:pnpm|npm|npx|yarn|bun)$/.test(executable)) {\n while (words[0]?.startsWith('-')) {\n const option = words.shift()!;\n if (/^(?:--filter|--dir|-C|--cwd|--prefix)$/.test(option)) words.shift();\n }\n if (words[0] === 'exec' || words[0] === 'run') words.shift();\n const invocation = words.shift() ?? '';\n if (/^(?:build|test|lint|fixcode|typecheck|check)(?::[\\w-]+)?$/.test(invocation)) return true;\n executable = executableName(invocation);\n }\n if (expensiveBinary.test(executable)) return true;\n if (executable === 'nx') {\n if (/^(?:show|graph|daemon|reset|report|list)$/.test(words[0] ?? '')) return false;\n return heavyTarget.test(words.join(' '));\n }\n if (/^(?:playwright|vite|cargo|go)$/.test(executable)) return heavyTarget.test(words.join(' '));\n if (/^(?:python|python3)$/.test(executable)) return words[0] === '-m' && words[1] === 'pytest';\n if (/^(?:node|bun|tsx)$/.test(executable)) {\n executable = executableName(words.find((word) => !word.startsWith('-')) ?? '');\n }\n const script = executable.replace(/\\.(?:[cm]?[jt]s)$/, '');\n return (\n script !== executable &&\n (expensiveBinary.test(script) || /^(?:build|test|lint|fixcode|typecheck|dev)(?:[-:]|$)/.test(script))\n );\n });\n}\n","import { randomBytes } from 'node:crypto';\n\nimport type { PoHostExecutionBudget, PoHostExecutionPermit } from '@agimon-ai/po-core/packageApi';\n\nimport {\n COMPLETED,\n FAILED,\n LAUNCHER_ERROR,\n OUTPUT_UPDATE_POLL_MS,\n RUNNER_ID_RANDOM_BYTES,\n SIGNALED,\n TERMINAL_UNAVAILABLE,\n} from '../../constants/bashRunService';\nimport type {\n BashRunRequest,\n BashRunResult,\n CompletedRun,\n IBashRunService,\n PromotedRun,\n} from '../../types/bashRunService';\nimport type { IClock } from '../../types/clock';\nimport type { ILauncher, RunHandle } from '../../types/launcher';\nimport type { IRmuxBackend } from '../../types/rmuxBackend';\nimport { type IRtkProcessor, RTK_FAILED_WARNING } from '../../types/rtkProcessor';\nimport type { IRunnerRegistry } from '../../types/runnerRegistry';\nimport { getBackgroundThresholdMs } from '../runnerConfig';\nimport type { IRunnerNamer } from '../runnerNamer/type';\nimport { isHeavyCommand } from './resources';\n\n/** The command outlived the background threshold and should be promoted. */\nconst TIMED_OUT = Symbol('threshold-reached');\n/** The command outlived the caller's explicit timeout and should be stopped. */\nconst DEADLINE = Symbol('deadline-reached');\n/** The caller cancelled the command and its owned runner should be stopped. */\nconst ABORTED = Symbol('aborted');\n\nfunction runnerId(): string {\n const timestamp = Date.now().toString(36);\n const random = randomBytes(RUNNER_ID_RANDOM_BYTES).toString('base64url');\n return `${timestamp}-${random}`;\n}\n\nexport class BashRunService implements IBashRunService {\n constructor(\n private readonly launcher: ILauncher,\n private readonly rmuxBackend: IRmuxBackend,\n private readonly namer: IRunnerNamer,\n private readonly registry: IRunnerRegistry,\n private readonly clock: IClock,\n private readonly rtkProcessor: IRtkProcessor,\n private readonly cwd: string = process.cwd(),\n private readonly env: Readonly<Record<string, string | undefined>> = process.env,\n private readonly executionBudget?: PoHostExecutionBudget,\n ) {}\n\n async run(request: BashRunRequest): Promise<BashRunResult> {\n const id = runnerId();\n const name = await this.namer.allocate(request.command, request.sessionId, request.name);\n const cwd = request.cwd ?? this.cwd;\n // Reassigned once the launch shows whether a pane was actually available.\n let interactive = request.interactive === true;\n const wantsPane = interactive || request.preferInteractive === true;\n if (request.signal?.aborted) return { kind: FAILED, id, name, error: 'Operation aborted' };\n\n let handle: RunHandle;\n let releaseSlot: PoHostExecutionPermit | undefined;\n try {\n if (this.executionBudget && isHeavyCommand(request.command)) {\n releaseSlot = await this.executionBudget.acquire(request.signal);\n }\n request.signal?.throwIfAborted();\n const rmuxHandle = await this.rmuxBackend.launch({\n id,\n name,\n command: request.command,\n cwd,\n sessionId: request.sessionId,\n interactive: wantsPane,\n });\n if (interactive && !rmuxHandle) {\n releaseSlot?.();\n return { kind: FAILED, id, name, error: TERMINAL_UNAVAILABLE };\n }\n interactive = wantsPane && rmuxHandle !== undefined;\n handle =\n rmuxHandle ?? this.launcher.launch({ id, name, command: request.command, cwd, sessionId: request.sessionId });\n } catch (error) {\n releaseSlot?.();\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n if (handle.pid === undefined) {\n releaseSlot?.();\n return { kind: FAILED, id, name, error: 'The command did not start, so it cannot be supervised' };\n }\n // A background promotion is not process completion. Keep the slot until actual exit.\n if (releaseSlot) void handle.completion().then(releaseSlot, releaseSlot);\n // Register first so a process that survives PID attachment failure remains discoverable.\n try {\n await this.registry.register({\n id,\n name,\n pid: handle.pid,\n command: request.command,\n cwd,\n logPath: handle.logPath,\n interactive,\n sessionId: request.sessionId,\n backend: handle.backend,\n ...(handle.backendTarget ? { backendTarget: handle.backendTarget } : {}),\n });\n await request.onStarted?.({ id, name, logPath: handle.logPath });\n } catch (error) {\n await handle.stop();\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n if (releaseSlot) {\n try {\n await releaseSlot.attachProcess?.(handle.pid);\n } catch (error) {\n if (!(await handle.stop())) {\n return this.promote(handle, 'requested', undefined);\n }\n await this.registry.complete(id, { reason: 'stopped', code: null, signal: 'SIGTERM' });\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n }\n if (request.signal?.aborted) {\n if (!(await handle.stop())) return this.promote(handle, 'requested', undefined);\n await this.registry.complete(id, { reason: 'stopped', code: null, signal: 'SIGTERM' });\n return { kind: FAILED, id, name, error: 'Operation aborted' };\n }\n\n // A sequence owns the wait and hands control back as soon as its interactive stage starts.\n if (request.waitForExit !== true && (request.background === true || interactive))\n return this.promote(handle, request.background === true ? 'requested' : 'interactive', request.signal);\n\n const outputUpdates = request.onOutput ? this.followOutput(handle, request.onOutput) : undefined;\n try {\n const outcome = await this.race(handle, request.timeoutMs, request.signal, request.waitForExit !== true);\n outputUpdates?.flush();\n if (outcome === TIMED_OUT) {\n return this.promote(handle, 'threshold', request.signal);\n }\n if (outcome === ABORTED) {\n await this.registry.requestTermination(id, { reason: 'stopped', terminationReason: 'request_cancelled' });\n const stopped = await handle.stop();\n if (!stopped && request.waitForExit) return this.promote(handle, 'requested', undefined);\n outputUpdates?.flush();\n await this.registry.complete(id, { reason: 'stopped', code: null, signal: 'SIGTERM' });\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: null,\n signal: 'SIGTERM',\n logPath: handle.logPath,\n backend: handle.backend,\n aborted: true,\n };\n }\n if (outcome === DEADLINE) {\n // An explicit timeout means the caller wants the command dead, not\n // supervised, so it is stopped rather than promoted.\n await this.registry.requestTermination(id, { reason: 'timed_out', terminationReason: 'timeout' });\n const stopped = await handle.stop();\n if (!stopped && request.waitForExit) return this.promote(handle, 'requested', undefined);\n outputUpdates?.flush();\n await this.registry.complete(id, { reason: 'timed_out', code: null, signal: 'SIGTERM' });\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: null,\n signal: 'SIGTERM',\n logPath: handle.logPath,\n backend: handle.backend,\n timedOut: true,\n };\n }\n if (outcome instanceof Error) {\n await this.registry.complete(id, { reason: LAUNCHER_ERROR, code: null, signal: null });\n return { kind: FAILED, id, name, error: outcome.message };\n }\n\n await this.registry.complete(id, {\n reason: outcome.reason ?? (outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED),\n code: outcome.code,\n signal: outcome.signal,\n ...(outcome.terminationReason ? { terminationReason: outcome.terminationReason } : {}),\n ...(outcome.stopReason ? { stopReason: outcome.stopReason } : {}),\n });\n\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: outcome.code,\n signal: outcome.signal,\n logPath: handle.logPath,\n backend: handle.backend,\n ...(await this.processLog(request.command, handle.logPath)),\n };\n } finally {\n outputUpdates?.dispose();\n }\n }\n\n private async processLog(command: string, logPath: string): Promise<Pick<CompletedRun, 'rtkOutput' | 'rtkWarning'>> {\n try {\n const result = await this.rtkProcessor.process({ command, logPath });\n if (result.kind === 'processed') return { rtkOutput: result.result };\n if (result.kind === 'fallback') return { rtkWarning: result.warning };\n return {};\n } catch {\n return { rtkWarning: RTK_FAILED_WARNING };\n }\n }\n\n private followOutput(\n handle: RunHandle,\n onOutput: NonNullable<BashRunRequest['onOutput']>,\n ): { flush(): void; dispose(): void } {\n let active = true;\n let previous = '';\n let cancelPoll: (() => void) | undefined;\n const flush = (): void => {\n if (!active) return;\n const output = handle.output();\n if (output === previous) return;\n previous = output;\n onOutput(output);\n };\n const poll = (): void => {\n if (!active) return;\n flush();\n if (active) cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n };\n cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n return {\n flush,\n dispose: () => {\n active = false;\n cancelPoll?.();\n cancelPoll = undefined;\n },\n };\n }\n\n /**\n * Waits for the command, giving up at the background threshold or at the\n * caller's timeout, whichever comes first.\n *\n * A rejected completion is returned rather than thrown so the caller can\n * report a start failure as a tool result instead of an exception.\n */\n private async race(\n handle: RunHandle,\n timeoutMs: number | undefined,\n signal: AbortSignal | undefined,\n promoteAtThreshold = true,\n ): Promise<\n Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT | typeof DEADLINE | typeof ABORTED\n > {\n const cancels: Array<() => void> = [];\n const racers: Array<Promise<unknown>> = [handle.completion().catch((error: Error) => error)];\n\n if (promoteAtThreshold)\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(getBackgroundThresholdMs(this.env), () => resolve(TIMED_OUT)));\n }),\n );\n if (timeoutMs !== undefined && timeoutMs > 0) {\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(timeoutMs, () => resolve(DEADLINE)));\n }),\n );\n }\n if (signal) {\n racers.push(\n new Promise((resolve) => {\n if (signal.aborted) {\n resolve(ABORTED);\n return;\n }\n const abort = (): void => resolve(ABORTED);\n signal.addEventListener('abort', abort, { once: true });\n cancels.push(() => signal.removeEventListener('abort', abort));\n }),\n );\n }\n\n try {\n return (await Promise.race(racers)) as\n | Awaited<ReturnType<RunHandle['completion']>>\n | Error\n | typeof TIMED_OUT\n | typeof DEADLINE\n | typeof ABORTED;\n } finally {\n for (const cancel of cancels) cancel();\n }\n }\n\n private async promote(\n handle: RunHandle,\n reason: PromotedRun['reason'],\n signal: AbortSignal | undefined,\n ): Promise<BashRunResult> {\n if (handle.pid === undefined)\n return { kind: FAILED, id: handle.id, name: handle.name, error: 'The command did not start' };\n await this.registry.markPromoted(handle.id);\n // Registration first: an unregistered runner is invisible, and the handle\n // stops buffering the moment it is detached.\n handle.detach();\n let abortStop: Promise<boolean> | undefined;\n const abort = (): void => {\n abortStop = this.registry\n .requestTermination(handle.id, { reason: 'stopped', terminationReason: 'request_cancelled' })\n .then(() => handle.stop())\n .then(async () => {\n await this.registry.complete(handle.id, { reason: 'stopped', code: null, signal: 'SIGTERM' });\n return true;\n })\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.emitWarning(`Failed to stop aborted runner ${handle.id}: ${message}`);\n return false;\n });\n };\n // The signal belongs to the tool call, which ends when this returns, and\n // Pi aborts it at that point. A promoted runner outlives the call, so only\n // an abort that landed before the handoff stops it.\n if (signal?.aborted) abort();\n void handle\n .completion()\n .then(\n async (outcome) => {\n if (await abortStop) return;\n await this.registry.complete(handle.id, {\n reason: outcome.reason ?? (outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED),\n code: outcome.code,\n signal: outcome.signal,\n ...(outcome.terminationReason ? { terminationReason: outcome.terminationReason } : {}),\n ...(outcome.stopReason ? { stopReason: outcome.stopReason } : {}),\n });\n },\n async () => {\n if (await abortStop) return;\n await this.registry.complete(handle.id, { reason: LAUNCHER_ERROR, code: null, signal: null });\n },\n )\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.emitWarning(`Failed to complete runner ${handle.id}: ${message}`);\n });\n\n return {\n kind: 'promoted',\n id: handle.id,\n name: handle.name,\n pid: handle.pid,\n logPath: handle.logPath,\n backend: handle.backend,\n reason,\n };\n }\n}\n"],"mappings":"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"}
@@ -225,7 +225,7 @@ var BashRunService = class {
225
225
  error: "Operation aborted"
226
226
  };
227
227
  }
228
- if (request.background === true || interactive) return this.promote(handle, request.background === true ? "requested" : "interactive", request.signal);
228
+ if (request.waitForExit !== true && (request.background === true || interactive)) return this.promote(handle, request.background === true ? "requested" : "interactive", request.signal);
229
229
  const outputUpdates = request.onOutput ? this.followOutput(handle, request.onOutput) : void 0;
230
230
  try {
231
231
  const outcome = await this.race(handle, request.timeoutMs, request.signal, request.waitForExit !== true);
@@ -451,4 +451,4 @@ Object.defineProperty(exports, "BashRunService", {
451
451
  }
452
452
  });
453
453
 
454
- //# sourceMappingURL=bashRunService-DGZZGWLL.cjs.map
454
+ //# sourceMappingURL=bashRunService-DLpFoP81.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashRunService-DLpFoP81.cjs","names":["randomBytes","RTK_FAILED_WARNING","getBackgroundThresholdMs"],"sources":["../src/constants/bashRunService.ts","../src/services/bashRunService/resources.ts","../src/services/bashRunService/index.ts"],"sourcesContent":["export const RUNNER_ID_RANDOM_BYTES = 3;\nexport const OUTPUT_UPDATE_POLL_MS = 100;\nexport const COMPLETED = 'completed';\nexport const FAILED = 'failed';\nexport const LAUNCHER_ERROR = 'launcher_error';\nexport const SIGNALED = 'signaled';\n/** An interactive launch found neither multiplexer. */\nexport const TERMINAL_UNAVAILABLE = 'A terminal needs rmux or tmux, and neither is available on this machine.';\n","/** Split shell words without mistaking quoted examples for executed commands. */\nfunction commandInvocations(command: string): string[][] {\n const invocations: string[][] = [];\n let words: string[] = [];\n let word = '';\n let quote = '';\n let escaped = false;\n const flushWord = (): void => {\n if (word) words.push(word);\n word = '';\n };\n for (const character of command) {\n if (escaped) {\n word += character;\n escaped = false;\n } else if (character === '\\\\' && quote !== \"'\") {\n escaped = true;\n } else if (quote) {\n if (character === quote) quote = '';\n else word += character;\n } else if (character === '\"' || character === \"'\") {\n quote = character;\n } else if (';&|\\n'.includes(character)) {\n flushWord();\n if (words.length) invocations.push(words);\n words = [];\n } else if (/\\s/.test(character)) {\n flushWord();\n } else {\n word += character;\n }\n }\n flushWord();\n if (words.length) invocations.push(words);\n return invocations;\n}\n\nfunction executableName(word: string): string {\n return word.replace(/\\\\/g, '/').split('/').pop() ?? word;\n}\n\n/** Admission policy, not a shell security boundary. Opaque scripts still need explicit ownership. */\nexport function isHeavyCommand(command: string): boolean {\n const heavyTarget =\n /(?:^|[\\s:,=])(?:build(?:-[\\w-]+)?|test(?:-[\\w-]+)?|lint|fixcode|typecheck|check|bundle)(?:[\\s:,=]|$)/;\n const expensiveBinary =\n /^(?:vitest|jest|tsc|tsgo|tsdown|webpack|rollup|esbuild|oxlint|oxfmt|pytest|maestro|xcodebuild|gradle|gradlew)$/;\n return commandInvocations(command).some((words) => {\n while (words.length) {\n const first = words[0]!;\n if (/^[A-Za-z_][A-Za-z_0-9]*=/.test(first) || /^(?:env|command|exec|time)$/.test(executableName(first))) {\n words.shift();\n } else break;\n }\n let executable = executableName(words.shift() ?? '');\n if (words.includes('--help') || words.includes('--version')) return false;\n if (/^(?:pnpm|npm|npx|yarn|bun)$/.test(executable)) {\n while (words[0]?.startsWith('-')) {\n const option = words.shift()!;\n if (/^(?:--filter|--dir|-C|--cwd|--prefix)$/.test(option)) words.shift();\n }\n if (words[0] === 'exec' || words[0] === 'run') words.shift();\n const invocation = words.shift() ?? '';\n if (/^(?:build|test|lint|fixcode|typecheck|check)(?::[\\w-]+)?$/.test(invocation)) return true;\n executable = executableName(invocation);\n }\n if (expensiveBinary.test(executable)) return true;\n if (executable === 'nx') {\n if (/^(?:show|graph|daemon|reset|report|list)$/.test(words[0] ?? '')) return false;\n return heavyTarget.test(words.join(' '));\n }\n if (/^(?:playwright|vite|cargo|go)$/.test(executable)) return heavyTarget.test(words.join(' '));\n if (/^(?:python|python3)$/.test(executable)) return words[0] === '-m' && words[1] === 'pytest';\n if (/^(?:node|bun|tsx)$/.test(executable)) {\n executable = executableName(words.find((word) => !word.startsWith('-')) ?? '');\n }\n const script = executable.replace(/\\.(?:[cm]?[jt]s)$/, '');\n return (\n script !== executable &&\n (expensiveBinary.test(script) || /^(?:build|test|lint|fixcode|typecheck|dev)(?:[-:]|$)/.test(script))\n );\n });\n}\n","import { randomBytes } from 'node:crypto';\n\nimport type { PoHostExecutionBudget, PoHostExecutionPermit } from '@agimon-ai/po-core/packageApi';\n\nimport {\n COMPLETED,\n FAILED,\n LAUNCHER_ERROR,\n OUTPUT_UPDATE_POLL_MS,\n RUNNER_ID_RANDOM_BYTES,\n SIGNALED,\n TERMINAL_UNAVAILABLE,\n} from '../../constants/bashRunService';\nimport type {\n BashRunRequest,\n BashRunResult,\n CompletedRun,\n IBashRunService,\n PromotedRun,\n} from '../../types/bashRunService';\nimport type { IClock } from '../../types/clock';\nimport type { ILauncher, RunHandle } from '../../types/launcher';\nimport type { IRmuxBackend } from '../../types/rmuxBackend';\nimport { type IRtkProcessor, RTK_FAILED_WARNING } from '../../types/rtkProcessor';\nimport type { IRunnerRegistry } from '../../types/runnerRegistry';\nimport { getBackgroundThresholdMs } from '../runnerConfig';\nimport type { IRunnerNamer } from '../runnerNamer/type';\nimport { isHeavyCommand } from './resources';\n\n/** The command outlived the background threshold and should be promoted. */\nconst TIMED_OUT = Symbol('threshold-reached');\n/** The command outlived the caller's explicit timeout and should be stopped. */\nconst DEADLINE = Symbol('deadline-reached');\n/** The caller cancelled the command and its owned runner should be stopped. */\nconst ABORTED = Symbol('aborted');\n\nfunction runnerId(): string {\n const timestamp = Date.now().toString(36);\n const random = randomBytes(RUNNER_ID_RANDOM_BYTES).toString('base64url');\n return `${timestamp}-${random}`;\n}\n\nexport class BashRunService implements IBashRunService {\n constructor(\n private readonly launcher: ILauncher,\n private readonly rmuxBackend: IRmuxBackend,\n private readonly namer: IRunnerNamer,\n private readonly registry: IRunnerRegistry,\n private readonly clock: IClock,\n private readonly rtkProcessor: IRtkProcessor,\n private readonly cwd: string = process.cwd(),\n private readonly env: Readonly<Record<string, string | undefined>> = process.env,\n private readonly executionBudget?: PoHostExecutionBudget,\n ) {}\n\n async run(request: BashRunRequest): Promise<BashRunResult> {\n const id = runnerId();\n const name = await this.namer.allocate(request.command, request.sessionId, request.name);\n const cwd = request.cwd ?? this.cwd;\n // Reassigned once the launch shows whether a pane was actually available.\n let interactive = request.interactive === true;\n const wantsPane = interactive || request.preferInteractive === true;\n if (request.signal?.aborted) return { kind: FAILED, id, name, error: 'Operation aborted' };\n\n let handle: RunHandle;\n let releaseSlot: PoHostExecutionPermit | undefined;\n try {\n if (this.executionBudget && isHeavyCommand(request.command)) {\n releaseSlot = await this.executionBudget.acquire(request.signal);\n }\n request.signal?.throwIfAborted();\n const rmuxHandle = await this.rmuxBackend.launch({\n id,\n name,\n command: request.command,\n cwd,\n sessionId: request.sessionId,\n interactive: wantsPane,\n });\n if (interactive && !rmuxHandle) {\n releaseSlot?.();\n return { kind: FAILED, id, name, error: TERMINAL_UNAVAILABLE };\n }\n interactive = wantsPane && rmuxHandle !== undefined;\n handle =\n rmuxHandle ?? this.launcher.launch({ id, name, command: request.command, cwd, sessionId: request.sessionId });\n } catch (error) {\n releaseSlot?.();\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n if (handle.pid === undefined) {\n releaseSlot?.();\n return { kind: FAILED, id, name, error: 'The command did not start, so it cannot be supervised' };\n }\n // A background promotion is not process completion. Keep the slot until actual exit.\n if (releaseSlot) void handle.completion().then(releaseSlot, releaseSlot);\n // Register first so a process that survives PID attachment failure remains discoverable.\n try {\n await this.registry.register({\n id,\n name,\n pid: handle.pid,\n command: request.command,\n cwd,\n logPath: handle.logPath,\n interactive,\n sessionId: request.sessionId,\n backend: handle.backend,\n ...(handle.backendTarget ? { backendTarget: handle.backendTarget } : {}),\n });\n await request.onStarted?.({ id, name, logPath: handle.logPath });\n } catch (error) {\n await handle.stop();\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n if (releaseSlot) {\n try {\n await releaseSlot.attachProcess?.(handle.pid);\n } catch (error) {\n if (!(await handle.stop())) {\n return this.promote(handle, 'requested', undefined);\n }\n await this.registry.complete(id, { reason: 'stopped', code: null, signal: 'SIGTERM' });\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n }\n if (request.signal?.aborted) {\n if (!(await handle.stop())) return this.promote(handle, 'requested', undefined);\n await this.registry.complete(id, { reason: 'stopped', code: null, signal: 'SIGTERM' });\n return { kind: FAILED, id, name, error: 'Operation aborted' };\n }\n\n // A sequence owns the wait and hands control back as soon as its interactive stage starts.\n if (request.waitForExit !== true && (request.background === true || interactive))\n return this.promote(handle, request.background === true ? 'requested' : 'interactive', request.signal);\n\n const outputUpdates = request.onOutput ? this.followOutput(handle, request.onOutput) : undefined;\n try {\n const outcome = await this.race(handle, request.timeoutMs, request.signal, request.waitForExit !== true);\n outputUpdates?.flush();\n if (outcome === TIMED_OUT) {\n return this.promote(handle, 'threshold', request.signal);\n }\n if (outcome === ABORTED) {\n await this.registry.requestTermination(id, { reason: 'stopped', terminationReason: 'request_cancelled' });\n const stopped = await handle.stop();\n if (!stopped && request.waitForExit) return this.promote(handle, 'requested', undefined);\n outputUpdates?.flush();\n await this.registry.complete(id, { reason: 'stopped', code: null, signal: 'SIGTERM' });\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: null,\n signal: 'SIGTERM',\n logPath: handle.logPath,\n backend: handle.backend,\n aborted: true,\n };\n }\n if (outcome === DEADLINE) {\n // An explicit timeout means the caller wants the command dead, not\n // supervised, so it is stopped rather than promoted.\n await this.registry.requestTermination(id, { reason: 'timed_out', terminationReason: 'timeout' });\n const stopped = await handle.stop();\n if (!stopped && request.waitForExit) return this.promote(handle, 'requested', undefined);\n outputUpdates?.flush();\n await this.registry.complete(id, { reason: 'timed_out', code: null, signal: 'SIGTERM' });\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: null,\n signal: 'SIGTERM',\n logPath: handle.logPath,\n backend: handle.backend,\n timedOut: true,\n };\n }\n if (outcome instanceof Error) {\n await this.registry.complete(id, { reason: LAUNCHER_ERROR, code: null, signal: null });\n return { kind: FAILED, id, name, error: outcome.message };\n }\n\n await this.registry.complete(id, {\n reason: outcome.reason ?? (outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED),\n code: outcome.code,\n signal: outcome.signal,\n ...(outcome.terminationReason ? { terminationReason: outcome.terminationReason } : {}),\n ...(outcome.stopReason ? { stopReason: outcome.stopReason } : {}),\n });\n\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: outcome.code,\n signal: outcome.signal,\n logPath: handle.logPath,\n backend: handle.backend,\n ...(await this.processLog(request.command, handle.logPath)),\n };\n } finally {\n outputUpdates?.dispose();\n }\n }\n\n private async processLog(command: string, logPath: string): Promise<Pick<CompletedRun, 'rtkOutput' | 'rtkWarning'>> {\n try {\n const result = await this.rtkProcessor.process({ command, logPath });\n if (result.kind === 'processed') return { rtkOutput: result.result };\n if (result.kind === 'fallback') return { rtkWarning: result.warning };\n return {};\n } catch {\n return { rtkWarning: RTK_FAILED_WARNING };\n }\n }\n\n private followOutput(\n handle: RunHandle,\n onOutput: NonNullable<BashRunRequest['onOutput']>,\n ): { flush(): void; dispose(): void } {\n let active = true;\n let previous = '';\n let cancelPoll: (() => void) | undefined;\n const flush = (): void => {\n if (!active) return;\n const output = handle.output();\n if (output === previous) return;\n previous = output;\n onOutput(output);\n };\n const poll = (): void => {\n if (!active) return;\n flush();\n if (active) cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n };\n cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n return {\n flush,\n dispose: () => {\n active = false;\n cancelPoll?.();\n cancelPoll = undefined;\n },\n };\n }\n\n /**\n * Waits for the command, giving up at the background threshold or at the\n * caller's timeout, whichever comes first.\n *\n * A rejected completion is returned rather than thrown so the caller can\n * report a start failure as a tool result instead of an exception.\n */\n private async race(\n handle: RunHandle,\n timeoutMs: number | undefined,\n signal: AbortSignal | undefined,\n promoteAtThreshold = true,\n ): Promise<\n Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT | typeof DEADLINE | typeof ABORTED\n > {\n const cancels: Array<() => void> = [];\n const racers: Array<Promise<unknown>> = [handle.completion().catch((error: Error) => error)];\n\n if (promoteAtThreshold)\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(getBackgroundThresholdMs(this.env), () => resolve(TIMED_OUT)));\n }),\n );\n if (timeoutMs !== undefined && timeoutMs > 0) {\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(timeoutMs, () => resolve(DEADLINE)));\n }),\n );\n }\n if (signal) {\n racers.push(\n new Promise((resolve) => {\n if (signal.aborted) {\n resolve(ABORTED);\n return;\n }\n const abort = (): void => resolve(ABORTED);\n signal.addEventListener('abort', abort, { once: true });\n cancels.push(() => signal.removeEventListener('abort', abort));\n }),\n );\n }\n\n try {\n return (await Promise.race(racers)) as\n | Awaited<ReturnType<RunHandle['completion']>>\n | Error\n | typeof TIMED_OUT\n | typeof DEADLINE\n | typeof ABORTED;\n } finally {\n for (const cancel of cancels) cancel();\n }\n }\n\n private async promote(\n handle: RunHandle,\n reason: PromotedRun['reason'],\n signal: AbortSignal | undefined,\n ): Promise<BashRunResult> {\n if (handle.pid === undefined)\n return { kind: FAILED, id: handle.id, name: handle.name, error: 'The command did not start' };\n await this.registry.markPromoted(handle.id);\n // Registration first: an unregistered runner is invisible, and the handle\n // stops buffering the moment it is detached.\n handle.detach();\n let abortStop: Promise<boolean> | undefined;\n const abort = (): void => {\n abortStop = this.registry\n .requestTermination(handle.id, { reason: 'stopped', terminationReason: 'request_cancelled' })\n .then(() => handle.stop())\n .then(async () => {\n await this.registry.complete(handle.id, { reason: 'stopped', code: null, signal: 'SIGTERM' });\n return true;\n })\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.emitWarning(`Failed to stop aborted runner ${handle.id}: ${message}`);\n return false;\n });\n };\n // The signal belongs to the tool call, which ends when this returns, and\n // Pi aborts it at that point. A promoted runner outlives the call, so only\n // an abort that landed before the handoff stops it.\n if (signal?.aborted) abort();\n void handle\n .completion()\n .then(\n async (outcome) => {\n if (await abortStop) return;\n await this.registry.complete(handle.id, {\n reason: outcome.reason ?? (outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED),\n code: outcome.code,\n signal: outcome.signal,\n ...(outcome.terminationReason ? { terminationReason: outcome.terminationReason } : {}),\n ...(outcome.stopReason ? { stopReason: outcome.stopReason } : {}),\n });\n },\n async () => {\n if (await abortStop) return;\n await this.registry.complete(handle.id, { reason: LAUNCHER_ERROR, code: null, signal: null });\n },\n )\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.emitWarning(`Failed to complete runner ${handle.id}: ${message}`);\n });\n\n return {\n kind: 'promoted',\n id: handle.id,\n name: handle.name,\n pid: handle.pid,\n logPath: handle.logPath,\n backend: handle.backend,\n reason,\n };\n }\n}\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_bashRunService = require("./bashRunService-DGZZGWLL.cjs");
2
+ const require_bashRunService = require("./bashRunService-DLpFoP81.cjs");
3
3
  exports.BashRunService = require_bashRunService.BashRunService;
@@ -1 +1 @@
1
- {"version":3,"file":"bashRunService.d.mts","names":[],"sources":["../src/services/bashRunService/index.ts"],"mappings":";;;;;;;;;qBA0Ca,0BAA0B;mBAElB;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;EATnB,YACmB,UAAU,WACV,aAAa,cACb,OAAO,cACP,UAAU,iBACV,OAAO,QACP,cAAc,eACd,cACA,MAAK,SAAS,qCACd,kBAAkB;EAG/B,IAAI,SAAS,iBAAiB,QAAQ;UA+J9B;UAWN;;;;;;;;UAqCM;UAkDA"}
1
+ {"version":3,"file":"bashRunService.d.mts","names":[],"sources":["../src/services/bashRunService/index.ts"],"mappings":";;;;;;;;;qBA0Ca,0BAA0B;mBAElB;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;EATnB,YACmB,UAAU,WACV,aAAa,cACb,OAAO,cACP,UAAU,iBACV,OAAO,QACP,cAAc,eACd,cACA,MAAK,SAAS,qCACd,kBAAkB;EAG/B,IAAI,SAAS,iBAAiB,QAAQ;UA6J9B;UAWN;;;;;;;;UAqCM;UAkDA"}
@@ -1 +1 @@
1
- export { t as BashRunService } from "./bashRunService-DQeetQzV.mjs";
1
+ export { t as BashRunService } from "./bashRunService-CmjnipLE.mjs";
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_bashTool = require("./bashTool-Bahf40vt.cjs");
2
+ const require_bashTool = require("./bashTool-CfNNdq62.cjs");
3
3
  exports.BASH_TOOL_LABEL = require_bashTool.BASH_TOOL_LABEL;
4
4
  exports.BASH_TOOL_NAME = require_bashTool.BASH_TOOL_NAME;
5
5
  exports.BashParamsSchema = require_bashTool.BashParamsSchema;
@@ -1,4 +1,4 @@
1
- import { n as BashParamsSchema, t as BashParams } from "./bashTool-DAhPY4ID.mjs";
1
+ import { n as BashParamsSchema, t as BashParams } from "./bashTool-Dc1ld2E3.mjs";
2
2
  //#region src/constants/bashTool.d.ts
3
3
  export declare const BASH_TOOL_NAME = "bash";
4
4
  export declare const BASH_TOOL_LABEL = "bash";
@@ -1 +1 @@
1
- export { t as BASH_TOOL_LABEL, n as BASH_TOOL_NAME, r as BashParamsSchema } from "./bashTool-gjIKvJQ-.mjs";
1
+ export { t as BASH_TOOL_LABEL, n as BASH_TOOL_NAME, r as BashParamsSchema } from "./bashTool-DRW3lseL.mjs";
@@ -1,25 +1,19 @@
1
1
  const require_runnerSequence = require("./runnerSequence-ZTYgZ_2W.cjs");
2
2
  let typebox = require("typebox");
3
3
  //#region src/schemas/bashTool.ts
4
- /** Replaces pi's built-in tool of the same name, so hooks keyed on `bash` keep working. */
5
- /**
6
- * Built-in bash parameters plus the backgrounding controls.
7
- *
8
- * `command` and `timeout` keep their original names and wording so the tool is
9
- * a drop-in replacement. Every `description` is prompt copy the model reads.
10
- */
4
+ /** Replaces pi's built-in `bash` tool. Descriptions are agent-facing prompt copy. */
11
5
  const BashParamsSchema = typebox.Type.Object({
12
- command: typebox.Type.Union([typebox.Type.String({ description: "Bash command to execute" }), typebox.Type.Array(typebox.Type.String({
6
+ command: typebox.Type.Array(typebox.Type.String({
13
7
  minLength: 1,
14
8
  maxLength: require_runnerSequence.MAX_SEQUENCE_COMMAND_LENGTH
15
9
  }), {
16
10
  minItems: 1,
17
11
  maxItems: 32,
18
- description: "Run separate noninteractive Bash commands in sequence, stopping on first failure. Each command gets a full log. Return all log paths and only the last executed command result."
19
- })]),
12
+ description: "Bash commands to run in order, stopping on first failure. Use a one-item array for one command. Each command gets a full log; return all log paths and only the last executed result. Do not pipe or redirect output to a file, head, or tail. Logs are saved automatically and returned output is bounded."
13
+ }),
20
14
  timeout: typebox.Type.Optional(typebox.Type.Number({ description: "Timeout in seconds for each command (optional, no default timeout)" })),
21
- background: typebox.Type.Optional(typebox.Type.Boolean({ description: "Start the command in the background immediately instead of waiting. Use for dev servers, watchers and other commands you already know will not finish." })),
22
- interactive: typebox.Type.Optional(typebox.Type.Boolean({ description: "Run a single command under a pseudo terminal when it needs input. Answer with runner.input in code mode, or po-runner input without code mode. Command arrays are noninteractive." })),
15
+ background: typebox.Type.Optional(typebox.Type.Boolean({ description: "Start the command sequence in the background immediately. Use for dev servers, watchers and other commands you already know will not finish." })),
16
+ interactive: typebox.Type.Optional(typebox.Type.Boolean({ description: "Run only the last command under a pseudo terminal when it needs input. Earlier commands are noninteractive. Send input to the last stage runner ID with runner.input in code mode, or po-runner input without code mode." })),
23
17
  name: typebox.Type.Optional(typebox.Type.String({ description: "Preferred runner name if the command ends up in the background. A name in use gets a suffix." }))
24
18
  });
25
19
  //#endregion
@@ -46,4 +40,4 @@ Object.defineProperty(exports, "BashParamsSchema", {
46
40
  }
47
41
  });
48
42
 
49
- //# sourceMappingURL=bashTool-Bahf40vt.cjs.map
43
+ //# sourceMappingURL=bashTool-CfNNdq62.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashTool-CfNNdq62.cjs","names":["Type","MAX_SEQUENCE_COMMAND_LENGTH"],"sources":["../src/schemas/bashTool.ts","../src/constants/bashTool.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\nimport { MAX_SEQUENCE_COMMANDS, MAX_SEQUENCE_COMMAND_LENGTH } from '../constants/runnerSequence';\n\n/** Replaces pi's built-in `bash` tool. Descriptions are agent-facing prompt copy. */\nexport const BashParamsSchema = Type.Object({\n command: Type.Array(Type.String({ minLength: 1, maxLength: MAX_SEQUENCE_COMMAND_LENGTH }), {\n minItems: 1,\n maxItems: MAX_SEQUENCE_COMMANDS,\n description:\n 'Bash commands to run in order, stopping on first failure. Use a one-item array for one command. Each command gets a full log; return all log paths and only the last executed result. Do not pipe or redirect output to a file, head, or tail. Logs are saved automatically and returned output is bounded.',\n }),\n timeout: Type.Optional(\n Type.Number({ description: 'Timeout in seconds for each command (optional, no default timeout)' }),\n ),\n background: Type.Optional(\n Type.Boolean({\n description:\n 'Start the command sequence in the background immediately. Use for dev servers, watchers and other commands you already know will not finish.',\n }),\n ),\n interactive: Type.Optional(\n Type.Boolean({\n description:\n 'Run only the last command under a pseudo terminal when it needs input. Earlier commands are noninteractive. Send input to the last stage runner ID with runner.input in code mode, or po-runner input without code mode.',\n }),\n ),\n name: Type.Optional(\n Type.String({\n description: 'Preferred runner name if the command ends up in the background. A name in use gets a suffix.',\n }),\n ),\n});\n\nexport type BashParams = Static<typeof BashParamsSchema>;\n","export const BASH_TOOL_NAME = 'bash';\nexport const BASH_TOOL_LABEL = 'bash';\n\nexport const MS_PER_SECOND = 1000;\n"],"mappings":";;;;AAKA,MAAa,mBAAmBA,QAAAA,KAAK,OAAO;CAC1C,SAASA,QAAAA,KAAK,MAAMA,QAAAA,KAAK,OAAO;EAAE,WAAW;EAAG,WAAWC,uBAAAA;CAA4B,CAAC,GAAG;EACzF,UAAU;EACV,UAAA;EACA,aACE;CACJ,CAAC;CACD,SAASD,QAAAA,KAAK,SACZA,QAAAA,KAAK,OAAO,EAAE,aAAa,qEAAqE,CAAC,CACnG;CACA,YAAYA,QAAAA,KAAK,SACfA,QAAAA,KAAK,QAAQ,EACX,aACE,+IACJ,CAAC,CACH;CACA,aAAaA,QAAAA,KAAK,SAChBA,QAAAA,KAAK,QAAQ,EACX,aACE,2NACJ,CAAC,CACH;CACA,MAAMA,QAAAA,KAAK,SACTA,QAAAA,KAAK,OAAO,EACV,aAAa,+FACf,CAAC,CACH;AACF,CAAC;;;AChCD,MAAa,iBAAiB;AAC9B,MAAa,kBAAkB"}
@@ -0,0 +1,26 @@
1
+ import { t as MAX_SEQUENCE_COMMAND_LENGTH } from "./runnerSequence-k-_Fd77y.mjs";
2
+ import { Type } from "typebox";
3
+ //#region src/schemas/bashTool.ts
4
+ /** Replaces pi's built-in `bash` tool. Descriptions are agent-facing prompt copy. */
5
+ const BashParamsSchema = Type.Object({
6
+ command: Type.Array(Type.String({
7
+ minLength: 1,
8
+ maxLength: MAX_SEQUENCE_COMMAND_LENGTH
9
+ }), {
10
+ minItems: 1,
11
+ maxItems: 32,
12
+ description: "Bash commands to run in order, stopping on first failure. Use a one-item array for one command. Each command gets a full log; return all log paths and only the last executed result. Do not pipe or redirect output to a file, head, or tail. Logs are saved automatically and returned output is bounded."
13
+ }),
14
+ timeout: Type.Optional(Type.Number({ description: "Timeout in seconds for each command (optional, no default timeout)" })),
15
+ background: Type.Optional(Type.Boolean({ description: "Start the command sequence in the background immediately. Use for dev servers, watchers and other commands you already know will not finish." })),
16
+ interactive: Type.Optional(Type.Boolean({ description: "Run only the last command under a pseudo terminal when it needs input. Earlier commands are noninteractive. Send input to the last stage runner ID with runner.input in code mode, or po-runner input without code mode." })),
17
+ name: Type.Optional(Type.String({ description: "Preferred runner name if the command ends up in the background. A name in use gets a suffix." }))
18
+ });
19
+ //#endregion
20
+ //#region src/constants/bashTool.ts
21
+ const BASH_TOOL_NAME = "bash";
22
+ const BASH_TOOL_LABEL = "bash";
23
+ //#endregion
24
+ export { BASH_TOOL_NAME as n, BashParamsSchema as r, BASH_TOOL_LABEL as t };
25
+
26
+ //# sourceMappingURL=bashTool-DRW3lseL.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashTool-DRW3lseL.mjs","names":[],"sources":["../src/schemas/bashTool.ts","../src/constants/bashTool.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\nimport { MAX_SEQUENCE_COMMANDS, MAX_SEQUENCE_COMMAND_LENGTH } from '../constants/runnerSequence';\n\n/** Replaces pi's built-in `bash` tool. Descriptions are agent-facing prompt copy. */\nexport const BashParamsSchema = Type.Object({\n command: Type.Array(Type.String({ minLength: 1, maxLength: MAX_SEQUENCE_COMMAND_LENGTH }), {\n minItems: 1,\n maxItems: MAX_SEQUENCE_COMMANDS,\n description:\n 'Bash commands to run in order, stopping on first failure. Use a one-item array for one command. Each command gets a full log; return all log paths and only the last executed result. Do not pipe or redirect output to a file, head, or tail. Logs are saved automatically and returned output is bounded.',\n }),\n timeout: Type.Optional(\n Type.Number({ description: 'Timeout in seconds for each command (optional, no default timeout)' }),\n ),\n background: Type.Optional(\n Type.Boolean({\n description:\n 'Start the command sequence in the background immediately. Use for dev servers, watchers and other commands you already know will not finish.',\n }),\n ),\n interactive: Type.Optional(\n Type.Boolean({\n description:\n 'Run only the last command under a pseudo terminal when it needs input. Earlier commands are noninteractive. Send input to the last stage runner ID with runner.input in code mode, or po-runner input without code mode.',\n }),\n ),\n name: Type.Optional(\n Type.String({\n description: 'Preferred runner name if the command ends up in the background. A name in use gets a suffix.',\n }),\n ),\n});\n\nexport type BashParams = Static<typeof BashParamsSchema>;\n","export const BASH_TOOL_NAME = 'bash';\nexport const BASH_TOOL_LABEL = 'bash';\n\nexport const MS_PER_SECOND = 1000;\n"],"mappings":";;;;AAKA,MAAa,mBAAmB,KAAK,OAAO;CAC1C,SAAS,KAAK,MAAM,KAAK,OAAO;EAAE,WAAW;EAAG,WAAW;CAA4B,CAAC,GAAG;EACzF,UAAU;EACV,UAAA;EACA,aACE;CACJ,CAAC;CACD,SAAS,KAAK,SACZ,KAAK,OAAO,EAAE,aAAa,qEAAqE,CAAC,CACnG;CACA,YAAY,KAAK,SACf,KAAK,QAAQ,EACX,aACE,+IACJ,CAAC,CACH;CACA,aAAa,KAAK,SAChB,KAAK,QAAQ,EACX,aACE,2NACJ,CAAC,CACH;CACA,MAAM,KAAK,SACT,KAAK,OAAO,EACV,aAAa,+FACf,CAAC,CACH;AACF,CAAC;;;AChCD,MAAa,iBAAiB;AAC9B,MAAa,kBAAkB"}
@@ -0,0 +1,14 @@
1
+ import { Static, Type } from "typebox";
2
+ //#region src/schemas/bashTool.d.ts
3
+ /** Replaces pi's built-in `bash` tool. Descriptions are agent-facing prompt copy. */
4
+ declare const BashParamsSchema: Type.TObject<{
5
+ command: Type.TArray<Type.TString>;
6
+ timeout: Type.TOptional<Type.TNumber>;
7
+ background: Type.TOptional<Type.TBoolean>;
8
+ interactive: Type.TOptional<Type.TBoolean>;
9
+ name: Type.TOptional<Type.TString>;
10
+ }>;
11
+ type BashParams = Static<typeof BashParamsSchema>;
12
+ //#endregion
13
+ export { BashParamsSchema as n, BashParams as t };
14
+ //# sourceMappingURL=bashTool-Dc1ld2E3.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashTool-Dc1ld2E3.d.mts","names":[],"sources":["../src/schemas/bashTool.ts"],"mappings":";;;cAKa,kBAAgB,KAAA;;;;;;;KA6BjB,aAAa,cAAc"}
package/dist/bashTool.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_bashResult = require("./bashResult-CxttmwR5.cjs");
3
- const require_logReader = require("./logReader-BEneVvSC.cjs");
4
- const require_headless = require("./headless-as3Q6ucs.cjs");
3
+ const require_logReader = require("./logReader-3RzQjCs4.cjs");
4
+ const require_headless = require("./headless-BlgjJiv0.cjs");
5
5
  //#region src/services/runnerResult/index.ts
6
6
  function formatRunnerResult(result, budget = {}) {
7
7
  return require_bashResult.formatRunResult(result, budget, require_logReader.summarizeLog);
@@ -1,6 +1,6 @@
1
1
  import { n as BashRunResult } from "./bashRunService-CmdDhaTn.mjs";
2
2
  import { a as ResultBudget, s as ToolResult } from "./bashResult-DcrRaBLv.mjs";
3
- import { t as createHeadlessBashTool } from "./index-Df58fJ3b.mjs";
3
+ import { t as createHeadlessBashTool } from "./index-BhS6r6Eq.mjs";
4
4
  //#region src/services/runnerResult/index.d.ts
5
5
  declare function formatRunnerResult(result: BashRunResult, budget?: ResultBudget): ToolResult;
6
6
  //#endregion
package/dist/bashTool.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { c as formatRunResult } from "./bashResult-sEZrlBz3.mjs";
2
- import { r as summarizeLog } from "./logReader-D1xSM6uE.mjs";
3
- import { t as createHeadlessBashTool } from "./headless-VzfNzuEv.mjs";
2
+ import { r as summarizeLog } from "./logReader-DpO_fcDj.mjs";
3
+ import { t as createHeadlessBashTool } from "./headless-kp9-KBp3.mjs";
4
4
  //#region src/services/runnerResult/index.ts
5
5
  function formatRunnerResult(result, budget = {}) {
6
6
  return formatRunResult(result, budget, summarizeLog);
package/dist/bin/cli.cjs CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_runnerSequenceStore = require("../runnerSequenceStore-BtwVilKx.cjs");
4
4
  const require_cliApp = require("../cliApp-DonQNLT8.cjs");
5
5
  const require_session = require("../session-BvqzhXZY.cjs");
6
- const require_runnerDependencies = require("../runnerDependencies-D7v_k-sz.cjs");
6
+ const require_runnerDependencies = require("../runnerDependencies-DOY30X-w.cjs");
7
7
  let node_fs = require("node:fs");
8
8
  let node_url = require("node:url");
9
9
  let _agimon_ai_po_core_telemetry = require("@agimon-ai/po-core/telemetry");
package/dist/bin/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { t as createRunnerSequenceStore } from "../runnerSequenceStore-CaY7S_Sd.mjs";
3
3
  import { n as runnerCliHelp, t as runCli } from "../cliApp-BDJl6JPc.mjs";
4
4
  import { t as inheritedSessionId } from "../session-BKYnH4R6.mjs";
5
- import { t as createRunnerDependencies } from "../runnerDependencies-DRtNq2hj.mjs";
5
+ import { t as createRunnerDependencies } from "../runnerDependencies-C6K2P-ID.mjs";
6
6
  import { existsSync, realpathSync } from "node:fs";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { createPoTelemetry } from "@agimon-ai/po-core/telemetry";
package/dist/cliApp.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as ILauncher } from "./launcher-BG5t9nvG.mjs";
2
2
  import { t as IRmuxBackend } from "./rmuxBackend-CaEWooWn.mjs";
3
3
  import { n as IRunnerRegistry } from "./runnerRegistry-V-Ocaf4N.mjs";
4
- import { t as ILogReader } from "./logReader-MdW9ffvV.mjs";
4
+ import { t as ILogReader } from "./logReader-wZC8OH3h.mjs";
5
5
  import { t as RunnerSequenceStore } from "./index-CpeSnckG.mjs";
6
6
  //#region src/services/cliApp/index.d.ts
7
7
  export interface CliDependencies {
@@ -52,17 +52,17 @@ var help_how_to_runner_mcp_default = (0, _agimon_ai_po_core_mcpFacet.defineMcpSk
52
52
  //#region src/constants/runnerSettings.ts
53
53
  const RATIO_KEYS = ["headRatio", "errorBudgetRatio"];
54
54
  typebox.Type.Object({
55
- command: typebox.Type.Union([typebox.Type.String({ description: "Bash command to execute" }), typebox.Type.Array(typebox.Type.String({
55
+ command: typebox.Type.Array(typebox.Type.String({
56
56
  minLength: 1,
57
57
  maxLength: 65536
58
58
  }), {
59
59
  minItems: 1,
60
60
  maxItems: 32,
61
- description: "Run separate noninteractive Bash commands in sequence, stopping on first failure. Each command gets a full log. Return all log paths and only the last executed command result."
62
- })]),
61
+ description: "Bash commands to run in order, stopping on first failure. Use a one-item array for one command. Each command gets a full log; return all log paths and only the last executed result. Do not pipe or redirect output to a file, head, or tail. Logs are saved automatically and returned output is bounded."
62
+ }),
63
63
  timeout: typebox.Type.Optional(typebox.Type.Number({ description: "Timeout in seconds for each command (optional, no default timeout)" })),
64
- background: typebox.Type.Optional(typebox.Type.Boolean({ description: "Start the command in the background immediately instead of waiting. Use for dev servers, watchers and other commands you already know will not finish." })),
65
- interactive: typebox.Type.Optional(typebox.Type.Boolean({ description: "Run a single command under a pseudo terminal when it needs input. Answer with runner.input in code mode, or po-runner input without code mode. Command arrays are noninteractive." })),
64
+ background: typebox.Type.Optional(typebox.Type.Boolean({ description: "Start the command sequence in the background immediately. Use for dev servers, watchers and other commands you already know will not finish." })),
65
+ interactive: typebox.Type.Optional(typebox.Type.Boolean({ description: "Run only the last command under a pseudo terminal when it needs input. Earlier commands are noninteractive. Send input to the last stage runner ID with runner.input in code mode, or po-runner input without code mode." })),
66
66
  name: typebox.Type.Optional(typebox.Type.String({ description: "Preferred runner name if the command ends up in the background. A name in use gets a suffix." }))
67
67
  });
68
68
  new RegExp([
@@ -105,7 +105,7 @@ var bash_mcp_default = (0, _agimon_ai_po_core_mcpFacet.defineMcpTool)((context)
105
105
  if (!scope) throw new Error("Runner session service is unavailable.");
106
106
  return {
107
107
  ...scope.remoteTool,
108
- description: "Run a shell command (bash, terminal, CLI) in the Po session's repository on the host machine, not on your local machine. Use it for tests, builds, linters, git, and package scripts. Short commands return bounded output. Long-running ones return a runner id. No completion notice reaches you, so check them with `po-runner status <id>` and `po-runner logs <id> --lines 100` instead of relaunching.",
108
+ description: "Run an array of shell commands (bash, terminal, CLI) in the Po session's repository on the host machine, not on your local machine. Use a one-item array for one command. Commands run in order and stop on first failure. Only the last command may be interactive. Do not pipe or redirect output to a file, head, or tail: full logs are saved automatically and returned output is bounded. Long-running commands return a sequence id. No completion notice reaches you, so check with `po-runner status <id>` and `po-runner logs <id> --lines 100` instead of relaunching.",
109
109
  async execute(toolCallId, parameters, signal, onUpdate, execution) {
110
110
  const result = await scope.remoteTool.execute(toolCallId, parameters, AbortSignal.any([context.signal, signal ?? context.signal]), onUpdate, execution);
111
111
  const details = result.details;