@agimon-ai/doompi-runner 0.0.1-alpha.2 → 0.0.1-alpha.21
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 +25 -16
- package/dist/adapters/RunnerPaths.cjs +2 -0
- package/dist/adapters/RunnerPaths.cjs.map +1 -0
- package/dist/adapters/RunnerPaths.d.cts +35 -0
- package/dist/adapters/RunnerPaths.d.cts.map +1 -0
- package/dist/adapters/RunnerPaths.d.mts +35 -0
- package/dist/adapters/RunnerPaths.d.mts.map +1 -0
- package/dist/adapters/RunnerPaths.mjs +2 -0
- package/dist/adapters/RunnerPaths.mjs.map +1 -0
- package/dist/adapters/pi/extension.cjs +3 -0
- package/dist/adapters/pi/extension.cjs.map +1 -0
- package/dist/adapters/pi/extension.d.cts +10 -0
- package/dist/adapters/pi/extension.d.cts.map +1 -0
- package/dist/adapters/pi/extension.d.mts +10 -0
- package/dist/adapters/pi/extension.d.mts.map +1 -0
- package/dist/adapters/pi/extension.mjs +3 -0
- package/dist/adapters/pi/extension.mjs.map +1 -0
- package/dist/adapters/pty/ptyProvider.cjs +2 -0
- package/dist/adapters/pty/ptyProvider.cjs.map +1 -0
- package/dist/adapters/pty/ptyProvider.d.cts +13 -0
- package/dist/adapters/pty/ptyProvider.d.cts.map +1 -0
- package/dist/adapters/pty/ptyProvider.d.mts +13 -0
- package/dist/adapters/pty/ptyProvider.d.mts.map +1 -0
- package/dist/adapters/pty/ptyProvider.mjs +2 -0
- package/dist/adapters/pty/ptyProvider.mjs.map +1 -0
- package/dist/bin/cli.cjs +1 -1
- package/dist/bin/cli.cjs.map +1 -1
- package/dist/bin/cli.mjs +1 -1
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/bin/logSink.cjs.map +1 -1
- package/dist/bin/logSink.mjs.map +1 -1
- package/dist/bin/runnerHost.cjs.map +1 -1
- package/dist/bin/runnerHost.mjs.map +1 -1
- package/dist/cli/cliApp.cjs +1 -6
- package/dist/cli/cliApp.d.cts +2 -23
- package/dist/cli/cliApp.d.mts +2 -23
- package/dist/cli/cliApp.mjs +1 -6
- package/dist/commands/bash/bashTool.cjs +7 -0
- package/dist/commands/bash/bashTool.cjs.map +1 -0
- package/dist/commands/bash/bashTool.d.cts +25 -0
- package/dist/commands/bash/bashTool.d.cts.map +1 -0
- package/dist/commands/bash/bashTool.d.mts +25 -0
- package/dist/commands/bash/bashTool.d.mts.map +1 -0
- package/dist/commands/bash/bashTool.mjs +7 -0
- package/dist/commands/bash/bashTool.mjs.map +1 -0
- package/dist/commands/bash/responseEnvelope.cjs +10 -0
- package/dist/commands/bash/responseEnvelope.cjs.map +1 -0
- package/dist/commands/bash/responseEnvelope.d.cts +45 -0
- package/dist/commands/bash/responseEnvelope.d.cts.map +1 -0
- package/dist/commands/bash/responseEnvelope.d.mts +45 -0
- package/dist/commands/bash/responseEnvelope.d.mts.map +1 -0
- package/dist/commands/bash/responseEnvelope.mjs +10 -0
- package/dist/{tool/responseEnvelope.cjs.map → commands/bash/responseEnvelope.mjs.map} +1 -1
- package/dist/commands/cli/cliApp.cjs +6 -0
- package/dist/commands/cli/cliApp.cjs.map +1 -0
- package/dist/commands/cli/cliApp.d.cts +23 -0
- package/dist/commands/cli/cliApp.d.cts.map +1 -0
- package/dist/commands/cli/cliApp.d.mts +23 -0
- package/dist/commands/cli/cliApp.d.mts.map +1 -0
- package/dist/commands/cli/cliApp.mjs +6 -0
- package/dist/commands/cli/cliApp.mjs.map +1 -0
- package/dist/compaction.cjs +1 -4
- package/dist/compaction.d.cts +2 -14
- package/dist/compaction.d.mts +2 -14
- package/dist/compaction.mjs +1 -4
- package/dist/config.cjs +1 -2
- package/dist/config.d.cts +2 -32
- package/dist/config.d.mts +2 -32
- package/dist/config.mjs +1 -2
- package/dist/container/index.cjs +1 -1
- package/dist/container/index.cjs.map +1 -1
- package/dist/container/index.mjs +1 -1
- package/dist/container/index.mjs.map +1 -1
- package/dist/extension.cjs +1 -3
- package/dist/extension.d.cts +2 -10
- package/dist/extension.d.mts +2 -10
- package/dist/extension.mjs +1 -3
- package/dist/extensions/pi.cjs +1 -1
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.cts +1 -1
- package/dist/extensions/pi.d.mts +1 -1
- package/dist/extensions/pi.mjs +1 -1
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/ptyProvider.cjs +1 -2
- package/dist/ptyProvider.d.cts +2 -13
- package/dist/ptyProvider.d.mts +2 -13
- package/dist/ptyProvider.mjs +1 -2
- package/dist/reconcile.cjs +1 -2
- package/dist/reconcile.d.cts +2 -37
- package/dist/reconcile.d.mts +2 -37
- package/dist/reconcile.mjs +1 -2
- package/dist/runnerSpec.cjs +1 -2
- package/dist/runnerSpec.d.cts +2 -50
- package/dist/runnerSpec.d.mts +2 -50
- package/dist/runnerSpec.mjs +1 -2
- package/dist/schemas/bashTool.cjs +2 -0
- package/dist/schemas/bashTool.cjs.map +1 -0
- package/dist/schemas/bashTool.d.cts +25 -0
- package/dist/schemas/bashTool.d.cts.map +1 -0
- package/dist/schemas/bashTool.d.mts +25 -0
- package/dist/schemas/bashTool.d.mts.map +1 -0
- package/dist/schemas/bashTool.mjs +2 -0
- package/dist/schemas/bashTool.mjs.map +1 -0
- package/dist/schemas/runnerSpec.cjs +2 -0
- package/dist/schemas/runnerSpec.cjs.map +1 -0
- package/dist/schemas/runnerSpec.d.cts +50 -0
- package/dist/schemas/runnerSpec.d.cts.map +1 -0
- package/dist/schemas/runnerSpec.d.mts +50 -0
- package/dist/schemas/runnerSpec.d.mts.map +1 -0
- package/dist/schemas/runnerSpec.mjs +2 -0
- package/dist/schemas/runnerSpec.mjs.map +1 -0
- package/dist/services/AnsiScrub/ansiScrub.cjs +1 -1
- package/dist/services/AnsiScrub/ansiScrub.cjs.map +1 -1
- package/dist/services/AnsiScrub/ansiScrub.mjs +1 -1
- package/dist/services/AnsiScrub/ansiScrub.mjs.map +1 -1
- package/dist/services/BashRunService/BashRunService.cjs +1 -1
- package/dist/services/BashRunService/BashRunService.cjs.map +1 -1
- package/dist/services/BashRunService/BashRunService.mjs +1 -1
- package/dist/services/BashRunService/BashRunService.mjs.map +1 -1
- package/dist/services/Launcher/Launcher.cjs +1 -1
- package/dist/services/Launcher/Launcher.cjs.map +1 -1
- package/dist/services/Launcher/Launcher.mjs +1 -1
- package/dist/services/Launcher/Launcher.mjs.map +1 -1
- package/dist/services/Lifeline/NodeLifeline.cjs +1 -1
- package/dist/services/Lifeline/NodeLifeline.cjs.map +1 -1
- package/dist/services/Lifeline/NodeLifeline.mjs +1 -1
- package/dist/services/Lifeline/NodeLifeline.mjs.map +1 -1
- package/dist/services/LogFile/LogFile.cjs +1 -1
- package/dist/services/LogFile/LogFile.cjs.map +1 -1
- package/dist/services/LogFile/LogFile.mjs +1 -1
- package/dist/services/LogFile/LogFile.mjs.map +1 -1
- package/dist/services/PtyHost/PtyHost.cjs +1 -1
- package/dist/services/PtyHost/PtyHost.cjs.map +1 -1
- package/dist/services/PtyHost/PtyHost.mjs +1 -1
- package/dist/services/PtyHost/PtyHost.mjs.map +1 -1
- package/dist/services/RmuxBackend/RmuxBackend.cjs +1 -1
- package/dist/services/RmuxBackend/RmuxBackend.cjs.map +1 -1
- package/dist/services/RmuxBackend/RmuxBackend.mjs +1 -1
- package/dist/services/RmuxBackend/RmuxBackend.mjs.map +1 -1
- package/dist/services/RunnerNamer/RunnerNamer.cjs +1 -1
- package/dist/services/RunnerNamer/RunnerNamer.cjs.map +1 -1
- package/dist/services/RunnerNamer/RunnerNamer.mjs +1 -1
- package/dist/services/RunnerNamer/RunnerNamer.mjs.map +1 -1
- package/dist/services/RunnerPaths/RunnerPaths.cjs +1 -2
- package/dist/services/RunnerPaths/RunnerPaths.d.cts +2 -31
- package/dist/services/RunnerPaths/RunnerPaths.d.mts +2 -31
- package/dist/services/RunnerPaths/RunnerPaths.mjs +1 -2
- package/dist/services/RunnerPaths/index.cjs +1 -1
- package/dist/services/RunnerPaths/index.d.cts +2 -1
- package/dist/services/RunnerPaths/index.d.mts +2 -1
- package/dist/services/RunnerPaths/index.mjs +1 -1
- package/dist/services/RunnerPaths/types.d.cts +2 -0
- package/dist/services/RunnerPaths/types.d.cts.map +1 -1
- package/dist/services/RunnerPaths/types.d.mts +2 -0
- package/dist/services/RunnerPaths/types.d.mts.map +1 -1
- package/dist/services/RunnerRegistry/RunnerRegistry.cjs +1 -1
- package/dist/services/RunnerRegistry/RunnerRegistry.cjs.map +1 -1
- package/dist/services/RunnerRegistry/RunnerRegistry.mjs +1 -1
- package/dist/services/RunnerRegistry/RunnerRegistry.mjs.map +1 -1
- package/dist/services/runs/compaction.cjs +4 -0
- package/dist/services/runs/compaction.cjs.map +1 -0
- package/dist/services/runs/compaction.d.cts +14 -0
- package/dist/services/runs/compaction.d.cts.map +1 -0
- package/dist/services/runs/compaction.d.mts +14 -0
- package/dist/services/runs/compaction.d.mts.map +1 -0
- package/dist/services/runs/compaction.mjs +4 -0
- package/dist/services/runs/compaction.mjs.map +1 -0
- package/dist/services/runs/reconcile.cjs +2 -0
- package/dist/services/runs/reconcile.cjs.map +1 -0
- package/dist/services/runs/reconcile.d.cts +37 -0
- package/dist/services/runs/reconcile.d.cts.map +1 -0
- package/dist/services/runs/reconcile.d.mts +37 -0
- package/dist/services/runs/reconcile.d.mts.map +1 -0
- package/dist/services/runs/reconcile.mjs +2 -0
- package/dist/services/runs/reconcile.mjs.map +1 -0
- package/dist/services/runs/session.cjs +2 -0
- package/dist/services/runs/session.cjs.map +1 -0
- package/dist/services/runs/session.d.cts +10 -0
- package/dist/services/runs/session.d.cts.map +1 -0
- package/dist/services/runs/session.d.mts +10 -0
- package/dist/services/runs/session.d.mts.map +1 -0
- package/dist/services/runs/session.mjs +2 -0
- package/dist/services/runs/session.mjs.map +1 -0
- package/dist/session.cjs +1 -2
- package/dist/session.d.cts +2 -10
- package/dist/session.d.mts +2 -10
- package/dist/session.mjs +1 -2
- package/dist/tool/bashTool.cjs +1 -7
- package/dist/tool/bashTool.d.cts +2 -25
- package/dist/tool/bashTool.d.mts +2 -25
- package/dist/tool/bashTool.mjs +1 -7
- package/dist/tool/responseEnvelope.cjs +1 -10
- package/dist/tool/responseEnvelope.d.cts +2 -45
- package/dist/tool/responseEnvelope.d.mts +2 -45
- package/dist/tool/responseEnvelope.mjs +1 -10
- package/dist/tool/schema.cjs +1 -2
- package/dist/tool/schema.d.cts +2 -25
- package/dist/tool/schema.d.mts +2 -25
- package/dist/tool/schema.mjs +1 -2
- package/dist/tui/bashRender.cjs +4 -7
- package/dist/tui/bashRender.cjs.map +1 -1
- package/dist/tui/bashRender.d.cts +5 -5
- package/dist/tui/bashRender.d.cts.map +1 -1
- package/dist/tui/bashRender.d.mts +5 -5
- package/dist/tui/bashRender.d.mts.map +1 -1
- package/dist/tui/bashRender.mjs +4 -7
- package/dist/tui/bashRender.mjs.map +1 -1
- package/dist/tui/format.cjs +1 -1
- package/dist/tui/format.cjs.map +1 -1
- package/dist/tui/format.mjs +1 -1
- package/dist/tui/format.mjs.map +1 -1
- package/dist/tui/runnerSpace.cjs +4 -4
- package/dist/tui/runnerSpace.cjs.map +1 -1
- package/dist/tui/runnerSpace.d.cts.map +1 -1
- package/dist/tui/runnerSpace.d.mts.map +1 -1
- package/dist/tui/runnerSpace.mjs +4 -4
- package/dist/tui/runnerSpace.mjs.map +1 -1
- package/dist/types/config.cjs +2 -0
- package/dist/types/config.cjs.map +1 -0
- package/dist/types/config.d.cts +32 -0
- package/dist/types/config.d.cts.map +1 -0
- package/dist/types/config.d.mts +32 -0
- package/dist/types/config.d.mts.map +1 -0
- package/dist/types/config.mjs +2 -0
- package/dist/types/config.mjs.map +1 -0
- package/dist/types/index.cjs +2 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +28 -0
- package/dist/types/index.d.cts.map +1 -0
- package/dist/types/index.d.mts +28 -0
- package/dist/types/index.d.mts.map +1 -0
- package/dist/types/index.mjs +2 -0
- package/dist/types/index.mjs.map +1 -0
- package/dist/types.cjs +1 -2
- package/dist/types.d.cts +2 -28
- package/dist/types.d.mts +2 -28
- package/dist/types.mjs +1 -2
- package/package.json +20 -13
- package/dist/cli/cliApp.cjs.map +0 -1
- package/dist/cli/cliApp.d.cts.map +0 -1
- package/dist/cli/cliApp.d.mts.map +0 -1
- package/dist/cli/cliApp.mjs.map +0 -1
- package/dist/compaction.cjs.map +0 -1
- package/dist/compaction.d.cts.map +0 -1
- package/dist/compaction.d.mts.map +0 -1
- package/dist/compaction.mjs.map +0 -1
- package/dist/config.cjs.map +0 -1
- package/dist/config.d.cts.map +0 -1
- package/dist/config.d.mts.map +0 -1
- package/dist/config.mjs.map +0 -1
- package/dist/extension.cjs.map +0 -1
- package/dist/extension.d.cts.map +0 -1
- package/dist/extension.d.mts.map +0 -1
- package/dist/extension.mjs.map +0 -1
- package/dist/ptyProvider.cjs.map +0 -1
- package/dist/ptyProvider.d.cts.map +0 -1
- package/dist/ptyProvider.d.mts.map +0 -1
- package/dist/ptyProvider.mjs.map +0 -1
- package/dist/reconcile.cjs.map +0 -1
- package/dist/reconcile.d.cts.map +0 -1
- package/dist/reconcile.d.mts.map +0 -1
- package/dist/reconcile.mjs.map +0 -1
- package/dist/runnerSpec.cjs.map +0 -1
- package/dist/runnerSpec.d.cts.map +0 -1
- package/dist/runnerSpec.d.mts.map +0 -1
- package/dist/runnerSpec.mjs.map +0 -1
- package/dist/services/RunnerPaths/RunnerPaths.cjs.map +0 -1
- package/dist/services/RunnerPaths/RunnerPaths.d.cts.map +0 -1
- package/dist/services/RunnerPaths/RunnerPaths.d.mts.map +0 -1
- package/dist/services/RunnerPaths/RunnerPaths.mjs.map +0 -1
- package/dist/session.cjs.map +0 -1
- package/dist/session.d.cts.map +0 -1
- package/dist/session.d.mts.map +0 -1
- package/dist/session.mjs.map +0 -1
- package/dist/tool/bashTool.cjs.map +0 -1
- package/dist/tool/bashTool.d.cts.map +0 -1
- package/dist/tool/bashTool.d.mts.map +0 -1
- package/dist/tool/bashTool.mjs.map +0 -1
- package/dist/tool/responseEnvelope.d.cts.map +0 -1
- package/dist/tool/responseEnvelope.d.mts.map +0 -1
- package/dist/tool/responseEnvelope.mjs.map +0 -1
- package/dist/tool/schema.cjs.map +0 -1
- package/dist/tool/schema.d.cts.map +0 -1
- package/dist/tool/schema.d.mts.map +0 -1
- package/dist/tool/schema.mjs.map +0 -1
- package/dist/types.cjs.map +0 -1
- package/dist/types.d.cts.map +0 -1
- package/dist/types.d.mts.map +0 -1
- package/dist/types.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bashTool.cjs","names":["getBackgroundThresholdMs","BASH_TOOL_NAME","BASH_TOOL_LABEL","BashParamsSchema","textResult","renderBashCall","renderBashResult","summarizeLog","stripAnsi","formatSize"],"sources":["../../src/tool/bashTool.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { getBackgroundThresholdMs } from '../config.ts';\nimport { stripAnsi } from '../services/AnsiScrub/index.ts';\nimport type { BashRunResult, IBashRunService } from '../services/BashRunService/index.ts';\nimport { renderBashCall, renderBashResult } from '../tui/bashRender.ts';\nimport { formatSize, summarizeLog, textResult, type ToolResult } from './responseEnvelope.ts';\nimport { BASH_TOOL_LABEL, BASH_TOOL_NAME, type BashParams, BashParamsSchema } from './schema.ts';\n\nconst MS_PER_SECOND = 1000;\nconst ERROR_OPTIONS_HEADING = 'Options:';\n\nconst PROMOTION_REASONS: Record<'requested' | 'threshold' | 'interactive', string> = {\n requested: 'Started in the background',\n threshold: 'Still running after the background threshold, so it was moved to the background',\n interactive: 'Started on a terminal so it can prompt, which means it runs in the background',\n};\n\nexport const BASH_PROMPT_SNIPPET = 'Execute bash commands, with long-running ones supervised in the background';\n\n/** Written at registration time so the stated threshold matches the configured one. */\nexport function bashPromptGuidelines(thresholdMs = getBackgroundThresholdMs()): string[] {\n return [\n `A command still running after ${Math.round(thresholdMs / MS_PER_SECOND)} seconds remains active as a background runner. You get its unique id and streaming log path, then inspect it with the doom-runner CLI.`,\n 'Pass background: true for commands you already know will not finish on their own (dev servers, watchers, tails). Waiting the full threshold first wastes a turn.',\n 'Pass interactive: true only when the command will prompt for confirmation or input. Use Runner Space for terminal input. Interactive logs are noisier, so avoid it otherwise.',\n 'Do not re-run a command to recover output. Read its saved log with doom-runner logs <id>.',\n 'Stop runners you no longer need. Every runner is stopped automatically when the session ends.',\n ];\n}\n\nexport interface BashToolDependencies {\n bashRunService: IBashRunService;\n getSessionId(): string;\n /** Called after a runner is promoted, so UI state can refresh. */\n onRunnerStarted(id: string): void;\n}\n\n/**\n * Registers a tool named `bash`, replacing pi's built-in.\n *\n * The name is deliberate: hooks, guardrails and doom-pi's dispatcher all key on\n * `bash`, and they keep working only while the replacement keeps the name.\n */\nexport function registerBashTool(pi: ExtensionAPI, dependencies: BashToolDependencies): void {\n pi.registerTool({\n name: BASH_TOOL_NAME,\n label: BASH_TOOL_LABEL,\n description:\n 'Execute a bash command in the current working directory. A command that outlives the background threshold keeps running under doom-runner and returns a unique id plus a streaming log path. Completed commands return a bounded log tail with exact file metadata. Optionally provide a timeout in seconds, background: true to background it immediately, or interactive: true if it will prompt.',\n promptSnippet: BASH_PROMPT_SNIPPET,\n promptGuidelines: bashPromptGuidelines(),\n parameters: BashParamsSchema,\n\n async execute(_toolCallId, params, _signal, onUpdate, _ctx): Promise<ToolResult> {\n const { command, timeout, background, interactive, name } = params as BashParams;\n let onOutput: ((output: string) => void) | undefined;\n if (onUpdate) {\n const mode =\n interactive === true ? 'interactive runner' : background === true ? 'background runner' : 'command';\n onUpdate(textResult(`Starting ${mode}...`));\n }\n if (background !== true && interactive !== true && onUpdate) {\n onOutput = (output) => onUpdate(textResult(output));\n }\n let result: BashRunResult;\n try {\n result = await dependencies.bashRunService.run({\n command,\n timeoutMs: timeout === undefined ? undefined : timeout * MS_PER_SECOND,\n background,\n interactive,\n name,\n ...(onOutput ? { onOutput } : {}),\n sessionId: dependencies.getSessionId(),\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n [\n `Could not execute the command: ${message}`,\n '',\n ERROR_OPTIONS_HEADING,\n '- Check the command, runtime, and working directory, then retry once.',\n '- Use a read-only diagnostic to confirm the missing dependency or environment value.',\n '- Ask the user if recovery requires changing the requested approach.',\n ].join('\\n'),\n { cause: error },\n );\n }\n\n if (result.kind === 'promoted') dependencies.onRunnerStarted(result.id);\n return formatRunResult(result);\n },\n\n // Without these, pi falls back to echoing the raw command and the tail end of\n // the result text, which is the metadata footer rather than the log output.\n renderCall(args, theme, _context) {\n return renderBashCall(args as BashParams, theme);\n },\n\n renderResult(result, options, theme, _context) {\n return renderBashResult(result, options, theme);\n },\n });\n}\n\nexport function formatRunResult(result: BashRunResult): ToolResult {\n if (result.kind === 'failed') {\n throw new Error(\n [\n `Could not start runner \"${result.name}\": ${result.error}`,\n '',\n ERROR_OPTIONS_HEADING,\n '- Correct the command or missing executable, then retry once.',\n '- Use a read-only diagnostic to inspect the runtime environment.',\n '- Ask the user if a different execution approach is required.',\n ].join('\\n'),\n );\n }\n\n if (result.kind === 'promoted') {\n const reason = PROMOTION_REASONS[result.reason];\n const body = [\n `${reason} as runner \"${result.name}\".`,\n `Runner ID: ${result.id}`,\n `Backend: ${result.backend}`,\n `Log (streaming): ${result.logPath}`,\n `Inspect it with: doom-runner logs ${result.id}`,\n ]\n .filter((line) => line.length > 0)\n .join('\\n');\n\n return {\n ...textResult(body, {\n id: result.id,\n runner: result.name,\n pid: result.pid,\n logPath: result.logPath,\n promoted: true,\n reason: result.reason,\n }),\n };\n }\n\n const log = summarizeLog(result.logPath);\n const notes: string[] = [];\n if (result.timedOut) notes.push('Command stopped: it exceeded the requested timeout.');\n else if (result.exitCode !== null) notes.push(`Exit: completed with code ${result.exitCode}.`);\n else if (result.signal !== null) notes.push(`Terminated by ${result.signal}`);\n\n // The model reads plain text; only the renderer gets the coloured copy below.\n const plainTail = stripAnsi(log.tail);\n const text = [\n plainTail.length > 0 ? `Log tail (${log.tailLines} lines):\\n${plainTail}` : 'Log tail: (no output)',\n `Runner ID: ${result.id}`,\n ...notes,\n `Log: ${result.logPath}`,\n `File size: ${formatSize(log.bytes)}`,\n `Lines: ${log.lines.toLocaleString('en-US')}`,\n ].join('\\n');\n const details = {\n id: result.id,\n runner: result.name,\n exitCode: result.exitCode,\n logPath: result.logPath,\n backend: result.backend,\n fileSize: log.bytes,\n lines: log.lines,\n // Carried structurally so renderResult shows the output instead of the footer.\n tail: log.tail,\n tailLines: log.tailLines,\n ...(result.timedOut ? { timedOut: true } : {}),\n };\n if (result.timedOut || result.signal !== null || (result.exitCode !== null && result.exitCode !== 0)) {\n throw new Error(\n [\n text,\n '',\n ERROR_OPTIONS_HEADING,\n `- Inspect the full log at ${result.logPath}, correct the cause, then retry once.`,\n '- Run a read-only diagnostic if the output does not explain the failure.',\n '- Ask the user if the failure requires changing the requested approach.',\n ].join('\\n'),\n );\n }\n return textResult(text, details);\n}\n"],"mappings":"uSAQM,EAAgB,IAChB,EAAwB,WAExB,EAA+E,CACnF,UAAW,4BACX,UAAW,kFACX,YAAa,+EACf,EAEa,EAAsB,6EAGnC,SAAgB,EAAqB,EAAcA,EAAAA,yBAAyB,EAAa,CACvF,MAAO,CACL,iCAAiC,KAAK,MAAM,EAAc,CAAa,EAAE,yIACzE,mKACA,gLACA,4FACA,+FACF,CACF,CAeA,SAAgB,EAAiB,EAAkB,EAA0C,CAC3F,EAAG,aAAa,CACd,KAAMC,EAAAA,eACN,MAAOC,EAAAA,gBACP,YACE,sYACF,cAAe,EACf,iBAAkB,EAAqB,EACvC,WAAYC,EAAAA,iBAEZ,MAAM,QAAQ,EAAa,EAAQ,EAAS,EAAU,EAA2B,CAC/E,GAAM,CAAE,UAAS,UAAS,aAAY,cAAa,QAAS,EACxD,EACA,GAGF,EAASC,EAAAA,WAAW,YADlB,IAAgB,GAAO,qBAAuB,IAAe,GAAO,oBAAsB,UACvD,IAAI,CAAC,EAExC,IAAe,IAAQ,IAAgB,IAAQ,IACjD,EAAY,GAAW,EAASA,EAAAA,WAAW,CAAM,CAAC,GAEpD,IAAI,EACJ,GAAI,CACF,EAAS,MAAM,EAAa,eAAe,IAAI,CAC7C,UACA,UAAW,IAAY,IAAA,GAAY,IAAA,GAAY,EAAU,EACzD,aACA,cACA,OACA,GAAI,EAAW,CAAE,UAAS,EAAI,CAAC,EAC/B,UAAW,EAAa,aAAa,CACvC,CAAC,CACH,OAAS,EAAO,CACd,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACrE,MAAU,MACR,CACE,kCAAkC,IAClC,GACA,EACA,wEACA,uFACA,sEACF,CAAC,CAAC,KAAK;CAAI,EACX,CAAE,MAAO,CAAM,CACjB,CACF,CAGA,OADI,EAAO,OAAS,YAAY,EAAa,gBAAgB,EAAO,EAAE,EAC/D,EAAgB,CAAM,CAC/B,EAIA,WAAW,EAAM,EAAO,EAAU,CAChC,OAAOC,EAAAA,eAAe,EAAoB,CAAK,CACjD,EAEA,aAAa,EAAQ,EAAS,EAAO,EAAU,CAC7C,OAAOC,EAAAA,iBAAiB,EAAQ,EAAS,CAAK,CAChD,CACF,CAAC,CACH,CAEA,SAAgB,EAAgB,EAAmC,CACjE,GAAI,EAAO,OAAS,SAClB,MAAU,MACR,CACE,2BAA2B,EAAO,KAAK,KAAK,EAAO,QACnD,GACA,EACA,gEACA,mEACA,+DACF,CAAC,CAAC,KAAK;CAAI,CACb,EAGF,GAAI,EAAO,OAAS,WAAY,CAE9B,IAAM,EAAO,CACX,GAFa,EAAkB,EAAO,QAE5B,cAAc,EAAO,KAAK,IACpC,cAAc,EAAO,KACrB,YAAY,EAAO,UACnB,oBAAoB,EAAO,UAC3B,qCAAqC,EAAO,IAC9C,CAAC,CACE,OAAQ,GAAS,EAAK,OAAS,CAAC,CAAC,CACjC,KAAK;CAAI,EAEZ,MAAO,CACL,GAAGF,EAAAA,WAAW,EAAM,CAClB,GAAI,EAAO,GACX,OAAQ,EAAO,KACf,IAAK,EAAO,IACZ,QAAS,EAAO,QAChB,SAAU,GACV,OAAQ,EAAO,MACjB,CAAC,CACH,CACF,CAEA,IAAM,EAAMG,EAAAA,aAAa,EAAO,OAAO,EACjC,EAAkB,CAAC,EACrB,EAAO,SAAU,EAAM,KAAK,qDAAqD,EAC5E,EAAO,WAAa,KACpB,EAAO,SAAW,MAAM,EAAM,KAAK,iBAAiB,EAAO,QAAQ,EADzC,EAAM,KAAK,6BAA6B,EAAO,SAAS,EAAE,EAI7F,IAAM,EAAYC,EAAAA,UAAU,EAAI,IAAI,EAC9B,EAAO,CACX,EAAU,OAAS,EAAI,aAAa,EAAI,UAAU,YAAY,IAAc,wBAC5E,cAAc,EAAO,KACrB,GAAG,EACH,QAAQ,EAAO,UACf,cAAcC,EAAAA,WAAW,EAAI,KAAK,IAClC,UAAU,EAAI,MAAM,eAAe,OAAO,GAC5C,CAAC,CAAC,KAAK;CAAI,EACL,EAAU,CACd,GAAI,EAAO,GACX,OAAQ,EAAO,KACf,SAAU,EAAO,SACjB,QAAS,EAAO,QAChB,QAAS,EAAO,QAChB,SAAU,EAAI,MACd,MAAO,EAAI,MAEX,KAAM,EAAI,KACV,UAAW,EAAI,UACf,GAAI,EAAO,SAAW,CAAE,SAAU,EAAK,EAAI,CAAC,CAC9C,EACA,GAAI,EAAO,UAAY,EAAO,SAAW,MAAS,EAAO,WAAa,MAAQ,EAAO,WAAa,EAChG,MAAU,MACR,CACE,EACA,GACA,EACA,6BAA6B,EAAO,QAAQ,uCAC5C,2EACA,yEACF,CAAC,CAAC,KAAK;CAAI,CACb,EAEF,OAAOL,EAAAA,WAAW,EAAM,CAAO,CACjC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bashTool.d.cts","names":[],"sources":["../../src/tool/bashTool.ts"],"mappings":";;;;;cAiBa;;iBAGG,qBAAqB;UAUpB;EACf,gBAAgB;EAChB;;EAEA,gBAAgB;;;;;;;;iBASF,iBAAiB,IAAI,cAAc,cAAc;iBA+DjD,gBAAgB,QAAQ,gBAAgB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bashTool.d.mts","names":[],"sources":["../../src/tool/bashTool.ts"],"mappings":";;;;;cAiBa;;iBAGG,qBAAqB;UAUpB;EACf,gBAAgB;EAChB;;EAEA,gBAAgB;;;;;;;;iBASF,iBAAiB,IAAI,cAAc,cAAc;iBA+DjD,gBAAgB,QAAQ,gBAAgB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bashTool.mjs","names":[],"sources":["../../src/tool/bashTool.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { getBackgroundThresholdMs } from '../config.ts';\nimport { stripAnsi } from '../services/AnsiScrub/index.ts';\nimport type { BashRunResult, IBashRunService } from '../services/BashRunService/index.ts';\nimport { renderBashCall, renderBashResult } from '../tui/bashRender.ts';\nimport { formatSize, summarizeLog, textResult, type ToolResult } from './responseEnvelope.ts';\nimport { BASH_TOOL_LABEL, BASH_TOOL_NAME, type BashParams, BashParamsSchema } from './schema.ts';\n\nconst MS_PER_SECOND = 1000;\nconst ERROR_OPTIONS_HEADING = 'Options:';\n\nconst PROMOTION_REASONS: Record<'requested' | 'threshold' | 'interactive', string> = {\n requested: 'Started in the background',\n threshold: 'Still running after the background threshold, so it was moved to the background',\n interactive: 'Started on a terminal so it can prompt, which means it runs in the background',\n};\n\nexport const BASH_PROMPT_SNIPPET = 'Execute bash commands, with long-running ones supervised in the background';\n\n/** Written at registration time so the stated threshold matches the configured one. */\nexport function bashPromptGuidelines(thresholdMs = getBackgroundThresholdMs()): string[] {\n return [\n `A command still running after ${Math.round(thresholdMs / MS_PER_SECOND)} seconds remains active as a background runner. You get its unique id and streaming log path, then inspect it with the doom-runner CLI.`,\n 'Pass background: true for commands you already know will not finish on their own (dev servers, watchers, tails). Waiting the full threshold first wastes a turn.',\n 'Pass interactive: true only when the command will prompt for confirmation or input. Use Runner Space for terminal input. Interactive logs are noisier, so avoid it otherwise.',\n 'Do not re-run a command to recover output. Read its saved log with doom-runner logs <id>.',\n 'Stop runners you no longer need. Every runner is stopped automatically when the session ends.',\n ];\n}\n\nexport interface BashToolDependencies {\n bashRunService: IBashRunService;\n getSessionId(): string;\n /** Called after a runner is promoted, so UI state can refresh. */\n onRunnerStarted(id: string): void;\n}\n\n/**\n * Registers a tool named `bash`, replacing pi's built-in.\n *\n * The name is deliberate: hooks, guardrails and doom-pi's dispatcher all key on\n * `bash`, and they keep working only while the replacement keeps the name.\n */\nexport function registerBashTool(pi: ExtensionAPI, dependencies: BashToolDependencies): void {\n pi.registerTool({\n name: BASH_TOOL_NAME,\n label: BASH_TOOL_LABEL,\n description:\n 'Execute a bash command in the current working directory. A command that outlives the background threshold keeps running under doom-runner and returns a unique id plus a streaming log path. Completed commands return a bounded log tail with exact file metadata. Optionally provide a timeout in seconds, background: true to background it immediately, or interactive: true if it will prompt.',\n promptSnippet: BASH_PROMPT_SNIPPET,\n promptGuidelines: bashPromptGuidelines(),\n parameters: BashParamsSchema,\n\n async execute(_toolCallId, params, _signal, onUpdate, _ctx): Promise<ToolResult> {\n const { command, timeout, background, interactive, name } = params as BashParams;\n let onOutput: ((output: string) => void) | undefined;\n if (onUpdate) {\n const mode =\n interactive === true ? 'interactive runner' : background === true ? 'background runner' : 'command';\n onUpdate(textResult(`Starting ${mode}...`));\n }\n if (background !== true && interactive !== true && onUpdate) {\n onOutput = (output) => onUpdate(textResult(output));\n }\n let result: BashRunResult;\n try {\n result = await dependencies.bashRunService.run({\n command,\n timeoutMs: timeout === undefined ? undefined : timeout * MS_PER_SECOND,\n background,\n interactive,\n name,\n ...(onOutput ? { onOutput } : {}),\n sessionId: dependencies.getSessionId(),\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n [\n `Could not execute the command: ${message}`,\n '',\n ERROR_OPTIONS_HEADING,\n '- Check the command, runtime, and working directory, then retry once.',\n '- Use a read-only diagnostic to confirm the missing dependency or environment value.',\n '- Ask the user if recovery requires changing the requested approach.',\n ].join('\\n'),\n { cause: error },\n );\n }\n\n if (result.kind === 'promoted') dependencies.onRunnerStarted(result.id);\n return formatRunResult(result);\n },\n\n // Without these, pi falls back to echoing the raw command and the tail end of\n // the result text, which is the metadata footer rather than the log output.\n renderCall(args, theme, _context) {\n return renderBashCall(args as BashParams, theme);\n },\n\n renderResult(result, options, theme, _context) {\n return renderBashResult(result, options, theme);\n },\n });\n}\n\nexport function formatRunResult(result: BashRunResult): ToolResult {\n if (result.kind === 'failed') {\n throw new Error(\n [\n `Could not start runner \"${result.name}\": ${result.error}`,\n '',\n ERROR_OPTIONS_HEADING,\n '- Correct the command or missing executable, then retry once.',\n '- Use a read-only diagnostic to inspect the runtime environment.',\n '- Ask the user if a different execution approach is required.',\n ].join('\\n'),\n );\n }\n\n if (result.kind === 'promoted') {\n const reason = PROMOTION_REASONS[result.reason];\n const body = [\n `${reason} as runner \"${result.name}\".`,\n `Runner ID: ${result.id}`,\n `Backend: ${result.backend}`,\n `Log (streaming): ${result.logPath}`,\n `Inspect it with: doom-runner logs ${result.id}`,\n ]\n .filter((line) => line.length > 0)\n .join('\\n');\n\n return {\n ...textResult(body, {\n id: result.id,\n runner: result.name,\n pid: result.pid,\n logPath: result.logPath,\n promoted: true,\n reason: result.reason,\n }),\n };\n }\n\n const log = summarizeLog(result.logPath);\n const notes: string[] = [];\n if (result.timedOut) notes.push('Command stopped: it exceeded the requested timeout.');\n else if (result.exitCode !== null) notes.push(`Exit: completed with code ${result.exitCode}.`);\n else if (result.signal !== null) notes.push(`Terminated by ${result.signal}`);\n\n // The model reads plain text; only the renderer gets the coloured copy below.\n const plainTail = stripAnsi(log.tail);\n const text = [\n plainTail.length > 0 ? `Log tail (${log.tailLines} lines):\\n${plainTail}` : 'Log tail: (no output)',\n `Runner ID: ${result.id}`,\n ...notes,\n `Log: ${result.logPath}`,\n `File size: ${formatSize(log.bytes)}`,\n `Lines: ${log.lines.toLocaleString('en-US')}`,\n ].join('\\n');\n const details = {\n id: result.id,\n runner: result.name,\n exitCode: result.exitCode,\n logPath: result.logPath,\n backend: result.backend,\n fileSize: log.bytes,\n lines: log.lines,\n // Carried structurally so renderResult shows the output instead of the footer.\n tail: log.tail,\n tailLines: log.tailLines,\n ...(result.timedOut ? { timedOut: true } : {}),\n };\n if (result.timedOut || result.signal !== null || (result.exitCode !== null && result.exitCode !== 0)) {\n throw new Error(\n [\n text,\n '',\n ERROR_OPTIONS_HEADING,\n `- Inspect the full log at ${result.logPath}, correct the cause, then retry once.`,\n '- Run a read-only diagnostic if the output does not explain the failure.',\n '- Ask the user if the failure requires changing the requested approach.',\n ].join('\\n'),\n );\n }\n return textResult(text, details);\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"responseEnvelope.d.cts","names":[],"sources":["../../src/tool/responseEnvelope.ts"],"mappings":";;;UAOiB;EACf,SAAS;IAAQ;IAAc;;EAC/B,SAAS;;EAET;;iBAGc,WAAW,cAAc,UAAS,0BAA+B;iBAIjE,YAAY,kBAAkB;;iBAK9B,WAAW;iBAUX,WAAW;UAKV;EACf;EACA;;EAEA;;UAGe;EACf;EACA;EACA;EACA;;;iBAIc,aAAa,cAAc,mBAAgB,oBAAiC;;;;;;;;iBA8B5E,kBACd,cACA,wBACA,oBACC;;iBA6Ca,iBAAiB,QAAQ,cAAc;iBAKvC,aAAa,mBAAmB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"responseEnvelope.d.mts","names":[],"sources":["../../src/tool/responseEnvelope.ts"],"mappings":";;;UAOiB;EACf,SAAS;IAAQ;IAAc;;EAC/B,SAAS;;EAET;;iBAGc,WAAW,cAAc,UAAS,0BAA+B;iBAIjE,YAAY,kBAAkB;;iBAK9B,WAAW;iBAUX,WAAW;UAKV;EACf;EACA;;EAEA;;UAGe;EACf;EACA;EACA;EACA;;;iBAIc,aAAa,cAAc,mBAAgB,oBAAiC;;;;;;;;iBA8B5E,kBACd,cACA,wBACA,oBACC;;iBA6Ca,iBAAiB,QAAQ,cAAc;iBAKvC,aAAa,mBAAmB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"responseEnvelope.mjs","names":[],"sources":["../../src/tool/responseEnvelope.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { getResultMaxBytes } from '../config.ts';\nimport type { RunnerRecord } from '../services/RunnerRegistry/index.ts';\n\nconst BYTES_PER_KB = 1024;\nconst BYTES_PER_MB = BYTES_PER_KB * BYTES_PER_KB;\n\nexport interface ToolResult {\n content: Array<{ type: 'text'; text: string }>;\n details: Record<string, unknown>;\n /** Tools this result makes available from here on in the transcript. */\n addedToolNames?: string[];\n}\n\nexport function textResult(text: string, details: Record<string, unknown> = {}): ToolResult {\n return { content: [{ type: 'text', text }], details };\n}\n\nexport function errorResult(message: string): ToolResult {\n return textResult(`Error: ${message}`, { error: message });\n}\n\n/** Human-readable byte count, matching how pi reports output sizes. */\nexport function formatSize(bytes: number): string {\n if (bytes < BYTES_PER_KB) return `${bytes} B`;\n if (bytes < BYTES_PER_MB) return `${(bytes / BYTES_PER_KB).toFixed(1)} KB`;\n return `${(bytes / BYTES_PER_MB).toFixed(1)} MB`;\n}\n\nfunction formatCount(value: number): string {\n return value.toLocaleString('en-US');\n}\n\nexport function countLines(text: string): number {\n if (text.length === 0) return 0;\n return text.endsWith('\\n') ? text.split('\\n').length - 1 : text.split('\\n').length;\n}\n\nexport interface TruncatedOutput {\n text: string;\n truncated: boolean;\n /** Lines returned, which is what the model actually received. */\n outputLines: number;\n}\n\nexport interface LogSummary {\n tail: string;\n bytes: number;\n lines: number;\n tailLines: number;\n}\n\n/** Reads a bounded tail plus exact metadata after the writer has flushed. */\nexport function summarizeLog(path: string, maxLines = 200, maxBytes = getResultMaxBytes()): LogSummary {\n try {\n const contents = fs.readFileSync(path, 'utf8');\n const lines = countLines(contents);\n const lineTail = contents\n .split('\\n')\n .slice(-Math.max(1, maxLines) - (contents.endsWith('\\n') ? 1 : 0))\n .join('\\n');\n const bytes = Buffer.byteLength(lineTail, 'utf8');\n const byteTail =\n bytes > maxBytes\n ? Buffer.from(lineTail, 'utf8')\n .subarray(bytes - maxBytes)\n .toString('utf8')\n : lineTail;\n const firstNewline = bytes > maxBytes ? byteTail.indexOf('\\n') : -1;\n const tail = firstNewline >= 0 ? byteTail.slice(firstNewline + 1) : byteTail;\n return { tail, bytes: fs.statSync(path).size, lines, tailLines: countLines(tail) };\n } catch {\n return { tail: '', bytes: 0, lines: 0, tailLines: 0 };\n }\n}\n\n/**\n * Keeps the tail of an oversized result and points at the file holding the rest.\n *\n * The notice states the file's real size and line count so the model does not\n * guess at offsets when it goes on to read the file, which is the failure this\n * whole policy exists to prevent.\n */\nexport function truncateForResult(\n text: string,\n fullOutputPath: string,\n maxBytes = getResultMaxBytes(),\n): TruncatedOutput {\n const totalBytes = Buffer.byteLength(text, 'utf8');\n if (totalBytes <= maxBytes) return { text, truncated: false, outputLines: countLines(text) };\n\n const kept = Buffer.from(text, 'utf8')\n .subarray(totalBytes - maxBytes)\n .toString('utf8');\n // Drop the leading partial line rather than hand back a fragment.\n const newline = kept.indexOf('\\n');\n const tail = newline === -1 ? kept : kept.slice(newline + 1);\n\n return {\n text: `${tail}\\n${truncationNotice(tail, fullOutputPath, text, totalBytes)}`,\n truncated: true,\n outputLines: countLines(tail),\n };\n}\n\nfunction truncationNotice(tail: string, fullOutputPath: string, text: string, totalBytes: number): string {\n const shown = countLines(tail);\n // Counted from the file, never from `text`. What the caller holds in memory\n // is itself capped, so using it here would understate the file by orders of\n // magnitude and send the reader looking past the end of a much longer file.\n const file = measureFile(fullOutputPath);\n const totalLines = file?.lines ?? countLines(text);\n const fileSize = file?.bytes ?? totalBytes;\n\n return [\n `[output truncated: showing the last ${formatCount(shown)} lines.`,\n `Full output is at ${fullOutputPath} (${formatSize(fileSize)}, ${formatCount(totalLines)} lines).`,\n `Inspect it with doom-runner logs, or read the file with an offset near line ${formatCount(totalLines)}.]`,\n ].join(' ');\n}\n\n/** Real size and line count of the file the notice points at. */\nfunction measureFile(path: string): { bytes: number; lines: number } | undefined {\n try {\n const contents = fs.readFileSync(path, 'utf8');\n return { bytes: fs.statSync(path).size, lines: countLines(contents) };\n } catch {\n return undefined;\n }\n}\n\n/** `name pid 1234 up 3m sleep 60` — one runner per line. */\nexport function formatRunnerLine(record: RunnerRecord, now = Date.now()): string {\n const mode = record.interactive ? ' interactive' : '';\n return `${record.name} pid ${record.pid} up ${formatUptime(record.startedAt, now)}${mode} ${record.command}`;\n}\n\nexport function formatUptime(startedAt: string, now: number): string {\n const started = Date.parse(startedAt);\n if (Number.isNaN(started)) return 'unknown';\n const seconds = Math.max(0, Math.floor((now - started) / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;\n}\n"],"mappings":"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"}
|
package/dist/tool/schema.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.cjs","names":["Type"],"sources":["../../src/tool/schema.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/** Replaces pi's built-in tool of the same name, so hooks keyed on `bash` keep working. */\nexport const BASH_TOOL_NAME = 'bash';\nexport const BASH_TOOL_LABEL = 'bash';\n\n/** Floor for `alarm`, so a short interval cannot flood the conversation. */\nexport const MIN_ALARM_SECONDS = 10;\n\n/**\n * Built-in bash parameters plus the backgrounding controls.\n *\n * `command` and `timeout` keep their original names and wording so the tool is\n * a drop-in replacement. Every `description` is prompt copy the model reads.\n */\nexport const BashParamsSchema = Type.Object({\n command: Type.String({ description: 'Bash command to execute' }),\n timeout: Type.Optional(Type.Number({ description: 'Timeout in seconds (optional, no default timeout)' })),\n background: Type.Optional(\n Type.Boolean({\n description:\n 'Start the command in the background immediately instead of waiting. 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 under a pseudo terminal so the command can prompt. Use only when the command asks for confirmation or input; answer it with doom-runner input. Logs from interactive runs are noisier.',\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 alarm: Type.Optional(\n Type.Number({\n description: `Send you a snapshot of this runner every N seconds, so you never have to poll it. Implies background. Use it to watch a dev server or a long build, or to wake yourself on a schedule by backgrounding a sleep loop. Minimum ${MIN_ALARM_SECONDS} seconds. It stops on its own when the process exits, or early with doom-runner alarm stop <id>.`,\n }),\n ),\n});\n\nexport type BashParams = Static<typeof BashParamsSchema>;\n"],"mappings":"4FAGA,MAYa,EAAmBA,EAAAA,KAAK,OAAO,CAC1C,QAASA,EAAAA,KAAK,OAAO,CAAE,YAAa,yBAA0B,CAAC,EAC/D,QAASA,EAAAA,KAAK,SAASA,EAAAA,KAAK,OAAO,CAAE,YAAa,mDAAoD,CAAC,CAAC,EACxG,WAAYA,EAAAA,KAAK,SACfA,EAAAA,KAAK,QAAQ,CACX,YACE,wJACJ,CAAC,CACH,EACA,YAAaA,EAAAA,KAAK,SAChBA,EAAAA,KAAK,QAAQ,CACX,YACE,4LACJ,CAAC,CACH,EACA,KAAMA,EAAAA,KAAK,SACTA,EAAAA,KAAK,OAAO,CACV,YAAa,8FACf,CAAC,CACH,EACA,MAAOA,EAAAA,KAAK,SACVA,EAAAA,KAAK,OAAO,CACV,YAAa,iUACf,CAAC,CACH,CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.cts","names":[],"sources":["../../src/tool/schema.ts"],"mappings":";;;cAGa;cACA;;cAGA;;;;;;;cAQA,kBAAgB,KAAA;;;;;;;;KA2BjB,aAAa,cAAc"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.mts","names":[],"sources":["../../src/tool/schema.ts"],"mappings":";;;cAGa;cACA;;cAGA;;;;;;;cAQA,kBAAgB,KAAA;;;;;;;;KA2BjB,aAAa,cAAc"}
|
package/dist/tool/schema.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.mjs","names":[],"sources":["../../src/tool/schema.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/** Replaces pi's built-in tool of the same name, so hooks keyed on `bash` keep working. */\nexport const BASH_TOOL_NAME = 'bash';\nexport const BASH_TOOL_LABEL = 'bash';\n\n/** Floor for `alarm`, so a short interval cannot flood the conversation. */\nexport const MIN_ALARM_SECONDS = 10;\n\n/**\n * Built-in bash parameters plus the backgrounding controls.\n *\n * `command` and `timeout` keep their original names and wording so the tool is\n * a drop-in replacement. Every `description` is prompt copy the model reads.\n */\nexport const BashParamsSchema = Type.Object({\n command: Type.String({ description: 'Bash command to execute' }),\n timeout: Type.Optional(Type.Number({ description: 'Timeout in seconds (optional, no default timeout)' })),\n background: Type.Optional(\n Type.Boolean({\n description:\n 'Start the command in the background immediately instead of waiting. 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 under a pseudo terminal so the command can prompt. Use only when the command asks for confirmation or input; answer it with doom-runner input. Logs from interactive runs are noisier.',\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 alarm: Type.Optional(\n Type.Number({\n description: `Send you a snapshot of this runner every N seconds, so you never have to poll it. Implies background. Use it to watch a dev server or a long build, or to wake yourself on a schedule by backgrounding a sleep loop. Minimum ${MIN_ALARM_SECONDS} seconds. It stops on its own when the process exits, or early with doom-runner alarm stop <id>.`,\n }),\n ),\n});\n\nexport type BashParams = Static<typeof BashParamsSchema>;\n"],"mappings":"+BAGA,MAAa,EAAiB,OACjB,EAAkB,OAGlB,EAAoB,GAQpB,EAAmB,EAAK,OAAO,CAC1C,QAAS,EAAK,OAAO,CAAE,YAAa,yBAA0B,CAAC,EAC/D,QAAS,EAAK,SAAS,EAAK,OAAO,CAAE,YAAa,mDAAoD,CAAC,CAAC,EACxG,WAAY,EAAK,SACf,EAAK,QAAQ,CACX,YACE,wJACJ,CAAC,CACH,EACA,YAAa,EAAK,SAChB,EAAK,QAAQ,CACX,YACE,4LACJ,CAAC,CACH,EACA,KAAM,EAAK,SACT,EAAK,OAAO,CACV,YAAa,8FACf,CAAC,CACH,EACA,MAAO,EAAK,SACV,EAAK,OAAO,CACV,YAAa,iUACf,CAAC,CACH,CACF,CAAC"}
|
package/dist/types.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["/**\n * Inversify binding keys.\n *\n * `Symbol.for` is a process-global registry, so every key is namespaced to\n * avoid colliding with the containers of other extensions loaded into the same\n * pi process.\n */\nexport const TYPES = {\n Clock: Symbol.for('doom-runner:Clock'),\n Spawner: Symbol.for('doom-runner:Spawner'),\n ProcessControl: Symbol.for('doom-runner:ProcessControl'),\n PtySpawner: Symbol.for('doom-runner:PtySpawner'),\n ProcessRegistry: Symbol.for('doom-runner:ProcessRegistry'),\n RunnerPaths: Symbol.for('doom-runner:RunnerPaths'),\n Lifeline: Symbol.for('doom-runner:Lifeline'),\n RunnerRegistry: Symbol.for('doom-runner:RunnerRegistry'),\n RunnerNamer: Symbol.for('doom-runner:RunnerNamer'),\n LogFile: Symbol.for('doom-runner:LogFile'),\n LogReader: Symbol.for('doom-runner:LogReader'),\n Launcher: Symbol.for('doom-runner:Launcher'),\n RmuxBackend: Symbol.for('doom-runner:RmuxBackend'),\n PtyHost: Symbol.for('doom-runner:PtyHost'),\n BashRunService: Symbol.for('doom-runner:BashRunService'),\n} as const;\n"],"mappings":"mEAOA,MAAa,EAAQ,CACnB,MAAO,OAAO,IAAI,mBAAmB,EACrC,QAAS,OAAO,IAAI,qBAAqB,EACzC,eAAgB,OAAO,IAAI,4BAA4B,EACvD,WAAY,OAAO,IAAI,wBAAwB,EAC/C,gBAAiB,OAAO,IAAI,6BAA6B,EACzD,YAAa,OAAO,IAAI,yBAAyB,EACjD,SAAU,OAAO,IAAI,sBAAsB,EAC3C,eAAgB,OAAO,IAAI,4BAA4B,EACvD,YAAa,OAAO,IAAI,yBAAyB,EACjD,QAAS,OAAO,IAAI,qBAAqB,EACzC,UAAW,OAAO,IAAI,uBAAuB,EAC7C,SAAU,OAAO,IAAI,sBAAsB,EAC3C,YAAa,OAAO,IAAI,yBAAyB,EACjD,QAAS,OAAO,IAAI,qBAAqB,EACzC,eAAgB,OAAO,IAAI,4BAA4B,CACzD"}
|
package/dist/types.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;cAOa"}
|
package/dist/types.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;cAOa"}
|
package/dist/types.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.mjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["/**\n * Inversify binding keys.\n *\n * `Symbol.for` is a process-global registry, so every key is namespaced to\n * avoid colliding with the containers of other extensions loaded into the same\n * pi process.\n */\nexport const TYPES = {\n Clock: Symbol.for('doom-runner:Clock'),\n Spawner: Symbol.for('doom-runner:Spawner'),\n ProcessControl: Symbol.for('doom-runner:ProcessControl'),\n PtySpawner: Symbol.for('doom-runner:PtySpawner'),\n ProcessRegistry: Symbol.for('doom-runner:ProcessRegistry'),\n RunnerPaths: Symbol.for('doom-runner:RunnerPaths'),\n Lifeline: Symbol.for('doom-runner:Lifeline'),\n RunnerRegistry: Symbol.for('doom-runner:RunnerRegistry'),\n RunnerNamer: Symbol.for('doom-runner:RunnerNamer'),\n LogFile: Symbol.for('doom-runner:LogFile'),\n LogReader: Symbol.for('doom-runner:LogReader'),\n Launcher: Symbol.for('doom-runner:Launcher'),\n RmuxBackend: Symbol.for('doom-runner:RmuxBackend'),\n PtyHost: Symbol.for('doom-runner:PtyHost'),\n BashRunService: Symbol.for('doom-runner:BashRunService'),\n} as const;\n"],"mappings":"AAOA,MAAa,EAAQ,CACnB,MAAO,OAAO,IAAI,mBAAmB,EACrC,QAAS,OAAO,IAAI,qBAAqB,EACzC,eAAgB,OAAO,IAAI,4BAA4B,EACvD,WAAY,OAAO,IAAI,wBAAwB,EAC/C,gBAAiB,OAAO,IAAI,6BAA6B,EACzD,YAAa,OAAO,IAAI,yBAAyB,EACjD,SAAU,OAAO,IAAI,sBAAsB,EAC3C,eAAgB,OAAO,IAAI,4BAA4B,EACvD,YAAa,OAAO,IAAI,yBAAyB,EACjD,QAAS,OAAO,IAAI,qBAAqB,EACzC,UAAW,OAAO,IAAI,uBAAuB,EAC7C,SAAU,OAAO,IAAI,sBAAsB,EAC3C,YAAa,OAAO,IAAI,yBAAyB,EACjD,QAAS,OAAO,IAAI,qBAAqB,EACzC,eAAgB,OAAO,IAAI,4BAA4B,CACzD"}
|