@bastani/atomic 0.9.4-alpha.10 → 0.9.4-alpha.11

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 (70) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/builtin/cursor/package.json +2 -2
  3. package/dist/builtin/intercom/package.json +1 -1
  4. package/dist/builtin/mcp/package.json +1 -1
  5. package/dist/builtin/subagents/CHANGELOG.md +7 -0
  6. package/dist/builtin/subagents/package.json +1 -1
  7. package/dist/builtin/subagents/src/slash/slash-commands.ts +2 -2
  8. package/dist/builtin/subagents/src/tui/render-result-compact.ts +3 -2
  9. package/dist/builtin/subagents/src/tui/render-result.ts +3 -3
  10. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +4 -3
  11. package/dist/builtin/subagents/src/tui/render-widget.ts +10 -4
  12. package/dist/builtin/web-access/package.json +1 -1
  13. package/dist/builtin/workflows/CHANGELOG.md +6 -0
  14. package/dist/builtin/workflows/package.json +1 -1
  15. package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +4 -0
  16. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +4 -0
  17. package/dist/builtin/workflows/src/tui/stage-chat-view-input.ts +12 -1
  18. package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +2 -0
  19. package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +6 -0
  20. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +4 -0
  21. package/dist/builtin/workflows/src/tui/workflow-attach-pane-types.ts +4 -0
  22. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +8 -9
  23. package/dist/core/agent-session-events.d.ts.map +1 -1
  24. package/dist/core/agent-session-events.js +2 -0
  25. package/dist/core/agent-session-events.js.map +1 -1
  26. package/dist/core/agent-session-methods.d.ts +4 -1
  27. package/dist/core/agent-session-methods.d.ts.map +1 -1
  28. package/dist/core/agent-session-methods.js.map +1 -1
  29. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  30. package/dist/core/agent-session-tool-registry.js +4 -0
  31. package/dist/core/agent-session-tool-registry.js.map +1 -1
  32. package/dist/core/agent-session.d.ts +4 -1
  33. package/dist/core/agent-session.d.ts.map +1 -1
  34. package/dist/core/agent-session.js +4 -0
  35. package/dist/core/agent-session.js.map +1 -1
  36. package/dist/core/async/format.d.ts +3 -0
  37. package/dist/core/async/format.d.ts.map +1 -0
  38. package/dist/core/async/format.js +50 -0
  39. package/dist/core/async/format.js.map +1 -0
  40. package/dist/core/async/job-manager.d.ts +39 -0
  41. package/dist/core/async/job-manager.d.ts.map +1 -0
  42. package/dist/core/async/job-manager.js +254 -0
  43. package/dist/core/async/job-manager.js.map +1 -0
  44. package/dist/core/async/session-manager.d.ts +18 -0
  45. package/dist/core/async/session-manager.d.ts.map +1 -0
  46. package/dist/core/async/session-manager.js +61 -0
  47. package/dist/core/async/session-manager.js.map +1 -0
  48. package/dist/core/async/types.d.ts +23 -0
  49. package/dist/core/async/types.d.ts.map +1 -0
  50. package/dist/core/async/types.js +2 -0
  51. package/dist/core/async/types.js.map +1 -0
  52. package/dist/core/tools/bash-async-execution.d.ts +25 -0
  53. package/dist/core/tools/bash-async-execution.d.ts.map +1 -0
  54. package/dist/core/tools/bash-async-execution.js +71 -0
  55. package/dist/core/tools/bash-async-execution.js.map +1 -0
  56. package/dist/core/tools/bash-async-jobs.d.ts +10 -0
  57. package/dist/core/tools/bash-async-jobs.d.ts.map +1 -1
  58. package/dist/core/tools/bash-async-jobs.js +18 -2
  59. package/dist/core/tools/bash-async-jobs.js.map +1 -1
  60. package/dist/core/tools/bash-async-output.d.ts +3 -1
  61. package/dist/core/tools/bash-async-output.d.ts.map +1 -1
  62. package/dist/core/tools/bash-async-output.js +4 -1
  63. package/dist/core/tools/bash-async-output.js.map +1 -1
  64. package/dist/core/tools/bash.d.ts +10 -4
  65. package/dist/core/tools/bash.d.ts.map +1 -1
  66. package/dist/core/tools/bash.js +20 -38
  67. package/dist/core/tools/bash.js.map +1 -1
  68. package/docs/tools.md +4 -2
  69. package/npm-shrinkwrap.json +23 -23
  70. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAO5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAKtF,OAAO,EAAmE,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAMlI,OAAO,EAAiC,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGrF,QAAA,MAAM,UAAU;;;;;;;EAAkK,CAAC;AACnL,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AACtD,MAAM,WAAW,eAAe;IAAG,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAA;KAAE,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE;AACxV,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,CACL,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QACR,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;QACxB,GAAG,CAAC,EAAE,OAAO,CAAC;KACd,KACG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC1C;AACD,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,cAAc,CAyD1F;AACD,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACvB;AACD,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;AAK5E,MAAM,WAAW,qBAAqB;IACrC,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC;CACpB;AACD,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,GAAG,qBAAqB,GAAG,SAAS,CAAC;AAC5I,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,kBAAkB,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC;IAC/C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB;AAgBD,KAAK,eAAe,GAAG;IACtB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;CACrC,CAAC;AAyGF,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAyOjF;AACD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG","sourcesContent":["import { constants } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { access as fsAccess, stat as fsStat } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../config.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport { getShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid } from \"../../utils/shell.ts\";\nimport type { BashResult } from \"../bash-executor.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { createAsyncOutputAppender } from \"./bash-async-output.ts\";\nimport { abortManagedBashJob, createManagedBashJob, formatAsyncJobError, getManagedBashJob } from \"./bash-async-jobs.ts\";\nimport { stripLeadingCdCommand } from \"./bash-leading-cd.ts\";\nimport { executeNativePty } from \"./bash-pty-native.ts\";\nimport { checkBashInterceptionCandidates, DEFAULT_BASH_INTERCEPTOR_RULES, type BashInterceptorRule } from \"./bash-interceptor.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { expandShellInternalUrls, type InternalResourceContext } from \"./resource-selectors.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { invalidateNativeSearchCache } from \"./search-native.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult } from \"./truncate.ts\";\nconst envSchema = Type.Unsafe<Record<string, string>>({ type: \"object\", description: \"Environment variables to add or override.\", additionalProperties: { type: \"string\" }, propertyNames: { pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\" } });\nconst bashBaseSchema = Type.Object({ command: Type.String({ description: \"Shell command to execute.\" }), env: Type.Optional(envSchema), timeout: Type.Optional(Type.Number({ description: \"Timeout in seconds.\" })), cwd: Type.Optional(Type.String({ description: \"Working directory for the command.\" })), pty: Type.Optional(Type.Boolean({ description: \"Run with PTY handling.\" })) }, { additionalProperties: false });\nconst bashSchema = Type.Object({ ...bashBaseSchema.properties, async: Type.Optional(Type.Boolean({ description: \"Run as a background job.\" })) }, { additionalProperties: false });\nexport type BashToolInput = Static<typeof bashSchema>;\nexport interface BashToolDetails { truncation?: TruncationResult; fullOutputPath?: string; exitCode?: number | null; async?: { jobId: string; type: \"bash\"; state: \"running\" | \"completed\" | \"failed\"; command?: string; status?: \"running\" | \"completed\" | \"failed\" }; timeoutSeconds?: number; requestedTimeoutSeconds?: number; wallTimeMs?: number }\nexport interface BashOperations {\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t\tpty?: boolean;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env, pty }) => {\n\t\t\tif (pty && process.env.PI_NO_PTY !== \"1\" && process.env.ATOMIC_NO_PTY !== \"1\") {\n\t\t\t\ttry { return await executeNativePty(command, cwd, { onData, signal, timeout, env, shellPath: options?.shellPath }); }\n\t\t\t\tcatch (error) { const message = String(error instanceof Error ? error.message : error); if (!message.includes(\"Native PTY\") && !message.includes(\"PtySession\")) throw error; }\n\t\t\t}\n\t\t\tconst shellConfig = getShellConfig(options?.shellPath);\n\t\t\ttry { const cwdStat = await fsStat(cwd); if (!cwdStat.isDirectory()) throw new Error(`Working directory is not a directory: ${cwd}`); await fsAccess(cwd, constants.F_OK); } catch (error) {\n\t\t\t\tif (error instanceof Error && error.message.startsWith(\"Working directory is not a directory\")) throw error;\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst commandFromStdin = shellConfig.commandTransport === \"stdin\";\n\t\t\tconst child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [commandFromStdin ? \"pipe\" : \"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (commandFromStdin) {\n\t\t\t\tchild.stdin?.on(\"error\", () => {});\n\t\t\t\tchild.stdin?.end(command);\n\t\t\t}\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = { command, cwd, env: { ...getShellEnv() } };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\nexport interface BashInterceptorResult {\n\toperations?: BashOperations;\n\tresult?: BashResult;\n}\nexport type BashInterceptor = (context: BashSpawnContext) => Promise<BashInterceptorResult | undefined> | BashInterceptorResult | undefined;\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n\tinterceptor?: BashInterceptor;\n\tinterceptorEnabled?: boolean | (() => boolean);\n\tavailableTools?: string[];\n\tinterceptorRules?: BashInterceptorRule[];\n\tasyncEnabled?: boolean;\n}\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\nconst DEFAULT_TIMEOUT_SECONDS = 300;\nconst MIN_TIMEOUT_SECONDS = 1;\nconst MAX_TIMEOUT_SECONDS = 3600;\nfunction normalizeTimeoutSeconds(timeout: number | undefined): number {\n\tif (timeout === undefined || !Number.isFinite(timeout)) return DEFAULT_TIMEOUT_SECONDS;\n\treturn Math.max(MIN_TIMEOUT_SECONDS, Math.min(MAX_TIMEOUT_SECONDS, Math.floor(timeout)));\n}\nfunction bashResultToToolResult(result: BashResult): { content: Array<{ type: \"text\"; text: string }>; details: BashToolDetails | undefined } {\n\tconst details: BashToolDetails | undefined = result.truncated ? { fullOutputPath: result.fullOutputPath } : undefined;\n\tconst status = result.cancelled ? \"Command aborted\" : result.exitCode && result.exitCode !== 0 ? `Command exited with code ${result.exitCode}` : undefined;\n\tconst text = `${result.output || \"(no output)\"}${status ? `\\n\\n${status}` : \"\"}`;\n\treturn { content: [{ type: \"text\", text }], details };\n}\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\nfunction formatDuration(ms: number): string {\n\tconst totalSeconds = Math.floor(Math.max(0, ms) / 1000);\n\tconst hours = Math.floor(totalSeconds / 3600);\n\tconst minutes = Math.floor((totalSeconds % 3600) / 60);\n\tconst seconds = totalSeconds % 60;\n\tif (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;\n\tif (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n\treturn `${seconds}s`;\n}\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"Expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst defaultOps = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\tconst interceptor = options?.interceptor;\n\tconst isInterceptorEnabled = (): boolean => typeof options?.interceptorEnabled === \"function\" ? options.interceptorEnabled() : options?.interceptorEnabled ?? !!interceptor;\n\tconst availableTools = options?.availableTools ?? [\"read\", \"search\", \"find\", \"edit\", \"write\"];\n\tconst interceptorRules = options?.interceptorRules ?? DEFAULT_BASH_INTERCEPTOR_RULES;\n\tconst asyncEnabled = options?.asyncEnabled ?? false;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: \"Execute a shell command in the session workspace, with optional PTY or background-job handling.\",\n\t\tpromptSnippet: \"Execute a shell command.\",\n\t\tparameters: asyncEnabled ? bashSchema : bashBaseSchema as typeof bashSchema,\n\t\tmaxResultSizeChars: Infinity,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tbashCommand: BashToolInput,\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst { command } = bashCommand;\n\t\t\tconst jobStatusMatch = command.match(/^__atomic_bash_job\\s+(\\S+)$/);\n\t\t\tif (jobStatusMatch) {\n\t\t\t\tconst job = getManagedBashJob(jobStatusMatch[1]!);\n\t\t\t\tif (!job) throw new Error(`Unknown bash async job: ${jobStatusMatch[1]}`);\n\t\t\t\tconst text = [`Job ${job.jobId}: ${job.status}`, `Command: ${job.command}`, job.error ? `Error: ${job.error}` : undefined, job.output].filter(Boolean).join(\"\\n\");\n\t\t\t\treturn { content: [{ type: \"text\", text }], details: { async: { jobId: job.jobId, type: \"bash\", state: job.status, command: job.command, status: job.status }, exitCode: job.exitCode, timeoutSeconds: job.timeoutSeconds, ...(job.requestedTimeoutSeconds !== undefined ? { requestedTimeoutSeconds: job.requestedTimeoutSeconds } : {}), ...(job.fullOutputPath ? { fullOutputPath: job.fullOutputPath } : {}), wallTimeMs: (job.endedAt ?? Date.now()) - job.startedAt } };\n\t\t\t}\n\t\t\tconst jobCancelMatch = command.match(/^__atomic_bash_job_cancel\\s+(\\S+)$/);\n\t\t\tif (jobCancelMatch) {\n\t\t\t\tconst job = abortManagedBashJob(jobCancelMatch[1]!);\n\t\t\t\tif (!job) throw new Error(`Unknown bash async job: ${jobCancelMatch[1]}`);\n\t\t\t\treturn { content: [{ type: \"text\", text: `Cancellation requested for bash job ${job.jobId}` }], details: { async: { jobId: job.jobId, type: \"bash\", state: job.status, command: job.command, status: job.status } } };\n\t\t\t}\n\t\t\tconst timeout = normalizeTimeoutSeconds(bashCommand.timeout);\n\t\t\tconst resourceCtx = _ctx as InternalResourceContext | undefined;\n\t\t\tconst hasExplicitCwd = typeof bashCommand.cwd === \"string\";\n\t\t\tconst rawStrippedContext = hasExplicitCwd ? undefined : stripLeadingCdCommand(command, cwd);\n\t\t\tconst interceptorEnabled = isInterceptorEnabled();\n\t\t\tif (interceptorEnabled) checkBashInterceptionCandidates([command, rawStrippedContext?.command], availableTools, interceptorRules);\n\t\t\tconst cwdInput = hasExplicitCwd ? await expandShellInternalUrls(bashCommand.cwd!, cwd, resourceCtx) : cwd, requestedCwd = resolvePath(cwd, cwdInput);\n\t\t\tconst expandedCommand = await expandShellInternalUrls(command, cwd, resourceCtx, true);\n\t\t\tconst strippedExpandedContext = hasExplicitCwd ? undefined : stripLeadingCdCommand(expandedCommand, requestedCwd);\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${expandedCommand}` : expandedCommand;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, requestedCwd, spawnHook);\n\t\t\tconst strippedCdContext = strippedExpandedContext ? resolveSpawnContext(commandPrefix ? `${commandPrefix}\\n${strippedExpandedContext.command}` : strippedExpandedContext.command, strippedExpandedContext.cwd, spawnHook) : undefined;\n\t\t\tif (interceptorEnabled) checkBashInterceptionCandidates([expandedCommand, strippedExpandedContext?.command, resolvedCommand, spawnContext.command, strippedCdContext?.command], availableTools, interceptorRules);\n\t\t\tlet expandedEnv: NodeJS.ProcessEnv | undefined;\n\t\t\tif (bashCommand.env) {\n\t\t\t\texpandedEnv = {};\n\t\t\t\tfor (const [key, value] of Object.entries(bashCommand.env)) {\n\t\t\t\t\tif (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new Error(`Invalid bash env name: ${key}`);\n\t\t\t\t\texpandedEnv[key] = await expandShellInternalUrls(value, cwd, resourceCtx);\n\t\t\t\t}\n\t\t\t\tspawnContext.env = { ...spawnContext.env, ...expandedEnv };\n\t\t\t}\n\t\t\tif (strippedCdContext && expandedEnv) strippedCdContext.env = { ...strippedCdContext.env, ...expandedEnv };\n\t\t\tconst primaryInterception = interceptorEnabled && interceptor ? await interceptor(spawnContext) : undefined;\n\t\t\tconst fallbackInterception = !primaryInterception && strippedCdContext && interceptorEnabled && interceptor ? await interceptor(strippedCdContext) : undefined;\n\t\t\tconst intercepted = primaryInterception ?? fallbackInterception;\n\t\t\tif (intercepted?.result) return bashResultToToolResult(intercepted.result);\n\t\t\tconst ops = intercepted?.operations ?? defaultOps;\n\t\t\tconst executionContext = primaryInterception ? spawnContext : (strippedCdContext ?? spawnContext);\n\t\t\tif (bashCommand.async) {\n\t\t\t\tif (!asyncEnabled) throw new Error(\"bash async execution is disabled\");\n\t\t\t\tconst job = createManagedBashJob(executionContext.command, executionContext.cwd, timeout, bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? bashCommand.timeout : undefined);\n\t\t\t\tconst appendAsyncOutput = createAsyncOutputAppender(job);\n\t\t\t\tconst onParentAbort = () => job.abortController?.abort();\n\t\t\t\tif (signal?.aborted) onParentAbort(); else signal?.addEventListener(\"abort\", onParentAbort, { once: true });\n\t\t\t\tvoid (async () => {\n\t\t\t\t\tlet error: unknown, exitCode: number | null | undefined;\n\t\t\t\t\ttry {\n\t\t\t\t\t\texitCode = (await ops.exec(executionContext.command, executionContext.cwd, { onData: appendAsyncOutput.append, timeout, env: executionContext.env, pty: bashCommand.pty, signal: job.abortController?.signal })).exitCode;\n\t\t\t\t\t} catch (execError: unknown) { error = execError; }\n\t\t\t\t\ttry { await appendAsyncOutput.close(); } catch (closeError: unknown) { error ??= closeError; }\n\t\t\t\t\tif (error !== undefined) {\n\t\t\t\t\t\tjob.status = \"failed\";\n\t\t\t\t\t\tjob.error = job.abortController?.signal.aborted ? \"aborted\" : formatAsyncJobError(error);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjob.exitCode = exitCode;\n\t\t\t\t\t\tjob.status = exitCode && exitCode !== 0 ? \"failed\" : \"completed\";\n\t\t\t\t\t}\n\t\t\t\t\tjob.endedAt = Date.now(); invalidateNativeSearchCache(); signal?.removeEventListener(\"abort\", onParentAbort);\n\t\t\t\t})();\n\t\t\t\treturn { content: [{ type: \"text\", text: `Started async bash command ${job.jobId}: ${executionContext.command}\\nPoll with bash({ command: \"__atomic_bash_job ${job.jobId}\" }); cancel with bash({ command: \"__atomic_bash_job_cancel ${job.jobId}\" })` }], details: { async: { jobId: job.jobId, type: \"bash\", state: \"running\", command: executionContext.command, status: \"running\" }, timeoutSeconds: timeout, ...(job.requestedTimeoutSeconds !== undefined ? { requestedTimeoutSeconds: job.requestedTimeoutSeconds } : {}) } };\n\t\t\t}\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });\n\t\t\tlet acceptingOutput = true;\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\tif (!acceptingOutput) return;\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\t\t\tconst finishOutput = async () => {\n\t\t\t\tacceptingOutput = false;\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\t\t\tconst startedAt = Date.now();\n\t\t\tconst withTiming = (details: BashToolDetails | undefined): BashToolDetails => ({ ...details, timeoutSeconds: timeout, ...(bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? { requestedTimeoutSeconds: bashCommand.timeout } : {}), wallTimeMs: Date.now() - startedAt });\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(executionContext.command, executionContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: executionContext.env,\n\t\t\t\t\t\tpty: bashCommand.pty,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\treturn { content: [{ type: \"text\", text: appendStatus(outputText, `Command exited with code ${exitCode}`) }], details: { ...withTiming(details), exitCode }, isError: true };\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details: withTiming(details) };\n\t\t\t} finally { invalidateNativeSearchCache(); clearUpdateTimer(); }\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { access as fsAccess, stat as fsStat } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../config.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport { getShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid } from \"../../utils/shell.ts\";\nimport type { AsyncJobManager } from \"../async/job-manager.js\";\nimport type { AsyncJobDeliveryMessage } from \"../async/types.js\";\nimport type { BashResult } from \"../bash-executor.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { startAsyncBashCommand } from \"./bash-async-execution.js\";\nimport { abortManagedBashJob, getManagedBashJob } from \"./bash-async-jobs.ts\";\nimport { stripLeadingCdCommand } from \"./bash-leading-cd.ts\";\nimport { executeNativePty } from \"./bash-pty-native.ts\";\nimport { checkBashInterceptionCandidates, DEFAULT_BASH_INTERCEPTOR_RULES, type BashInterceptorRule } from \"./bash-interceptor.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { expandShellInternalUrls, type InternalResourceContext } from \"./resource-selectors.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { invalidateNativeSearchCache } from \"./search-native.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult } from \"./truncate.ts\";\nconst envSchema = Type.Unsafe<Record<string, string>>({ type: \"object\", description: \"Environment variables to add or override.\", additionalProperties: { type: \"string\" }, propertyNames: { pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\" } });\nconst bashBaseSchema = Type.Object({ command: Type.String({ description: \"Shell command to execute.\" }), env: Type.Optional(envSchema), timeout: Type.Optional(Type.Number({ description: \"Timeout in seconds.\" })), cwd: Type.Optional(Type.String({ description: \"Working directory for the command.\" })), pty: Type.Optional(Type.Boolean({ description: \"Run with PTY handling.\" })) }, { additionalProperties: false });\nconst bashSchema = Type.Object({ ...bashBaseSchema.properties, async: Type.Optional(Type.Boolean({ description: \"Run as a background job.\" })) }, { additionalProperties: false });\nexport type BashToolInput = Static<typeof bashSchema>;\nexport interface BashToolDetails { truncation?: TruncationResult; fullOutputPath?: string; exitCode?: number | null; async?: { jobId: string; type: \"bash\"; state: \"running\" | \"completed\" | \"failed\"; command?: string; status?: \"running\" | \"completed\" | \"failed\" }; timeoutSeconds?: number; requestedTimeoutSeconds?: number; wallTimeMs?: number }\nexport interface BashOperations {\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t\tpty?: boolean;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env, pty }) => {\n\t\t\tif (pty && process.env.PI_NO_PTY !== \"1\" && process.env.ATOMIC_NO_PTY !== \"1\") {\n\t\t\t\ttry { return await executeNativePty(command, cwd, { onData, signal, timeout, env, shellPath: options?.shellPath }); }\n\t\t\t\tcatch (error) { const message = String(error instanceof Error ? error.message : error); if (!message.includes(\"Native PTY\") && !message.includes(\"PtySession\")) throw error; }\n\t\t\t}\n\t\t\tconst shellConfig = getShellConfig(options?.shellPath);\n\t\t\ttry { const cwdStat = await fsStat(cwd); if (!cwdStat.isDirectory()) throw new Error(`Working directory is not a directory: ${cwd}`); await fsAccess(cwd, constants.F_OK); } catch (error) {\n\t\t\t\tif (error instanceof Error && error.message.startsWith(\"Working directory is not a directory\")) throw error;\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst commandFromStdin = shellConfig.commandTransport === \"stdin\";\n\t\t\tconst child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [commandFromStdin ? \"pipe\" : \"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (commandFromStdin) {\n\t\t\t\tchild.stdin?.on(\"error\", () => {});\n\t\t\t\tchild.stdin?.end(command);\n\t\t\t}\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = { command, cwd, env: { ...getShellEnv() } };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\nexport interface BashInterceptorResult {\n\toperations?: BashOperations;\n\tresult?: BashResult;\n}\nexport type BashInterceptor = (context: BashSpawnContext) => Promise<BashInterceptorResult | undefined> | BashInterceptorResult | undefined;\nexport interface BashToolOptions {\n\toperations?: BashOperations;\n\t/** Prefix prepended to every shell command before execution. */\n\tcommandPrefix?: string;\n\t/** Override shell executable resolution for local bash operations. */\n\tshellPath?: string;\n\t/** Last-mile hook for rewriting the command/cwd/env spawn context. */\n\tspawnHook?: BashSpawnHook;\n\t/** Optional command interceptor used by extensions and parity tests. */\n\tinterceptor?: BashInterceptor;\n\tinterceptorEnabled?: boolean | (() => boolean);\n\tavailableTools?: string[];\n\tinterceptorRules?: BashInterceptorRule[];\n\t/** Enable background bash jobs and session-managed async result delivery. */\n\tasyncEnabled?: boolean;\n\tasyncJobManager?: AsyncJobManager;\n\tasyncJobDeliveryHandler?: (message: AsyncJobDeliveryMessage) => void | Promise<void>;\n\tasyncJobSessionId?: symbol;\n}\nconst BASH_PREVIEW_LINES = 5, BASH_UPDATE_THROTTLE_MS = 100;\nconst DEFAULT_TIMEOUT_SECONDS = 300;\nconst MIN_TIMEOUT_SECONDS = 1;\nconst MAX_TIMEOUT_SECONDS = 3600;\nfunction normalizeTimeoutSeconds(timeout: number | undefined): number {\n\tif (timeout === undefined || !Number.isFinite(timeout)) return DEFAULT_TIMEOUT_SECONDS;\n\treturn Math.max(MIN_TIMEOUT_SECONDS, Math.min(MAX_TIMEOUT_SECONDS, Math.floor(timeout)));\n}\nfunction bashResultToToolResult(result: BashResult): { content: Array<{ type: \"text\"; text: string }>; details: BashToolDetails | undefined } {\n\tconst details: BashToolDetails | undefined = result.truncated ? { fullOutputPath: result.fullOutputPath } : undefined;\n\tconst status = result.cancelled ? \"Command aborted\" : result.exitCode && result.exitCode !== 0 ? `Command exited with code ${result.exitCode}` : undefined;\n\tconst text = `${result.output || \"(no output)\"}${status ? `\\n\\n${status}` : \"\"}`;\n\treturn { content: [{ type: \"text\", text }], details };\n}\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\nfunction formatDuration(ms: number): string {\n\tconst totalSeconds = Math.floor(Math.max(0, ms) / 1000);\n\tconst hours = Math.floor(totalSeconds / 3600);\n\tconst minutes = Math.floor((totalSeconds % 3600) / 60);\n\tconst seconds = totalSeconds % 60;\n\tif (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;\n\tif (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n\treturn `${seconds}s`;\n}\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"Expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst defaultOps = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\tconst interceptor = options?.interceptor;\n\tconst isInterceptorEnabled = (): boolean => typeof options?.interceptorEnabled === \"function\" ? options.interceptorEnabled() : options?.interceptorEnabled ?? !!interceptor;\n\tconst availableTools = options?.availableTools ?? [\"read\", \"search\", \"find\", \"edit\", \"write\"];\n\tconst interceptorRules = options?.interceptorRules ?? DEFAULT_BASH_INTERCEPTOR_RULES;\n\tconst asyncEnabled = options?.asyncEnabled ?? false;\n\tconst asyncJobManager = options?.asyncJobManager, asyncJobDeliveryHandler = options?.asyncJobDeliveryHandler, asyncJobSessionId = options?.asyncJobSessionId;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: \"Execute a shell command in the session workspace, with optional PTY or background-job handling.\",\n\t\tpromptSnippet: \"Execute a shell command.\",\n\t\tparameters: asyncEnabled ? bashSchema : bashBaseSchema as typeof bashSchema,\n\t\tmaxResultSizeChars: Infinity,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tbashCommand: BashToolInput,\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst { command } = bashCommand;\n\t\t\tconst jobStatusMatch = command.match(/^__atomic_bash_job\\s+(\\S+)$/);\n\t\t\tif (jobStatusMatch) {\n\t\t\t\tconst job = getManagedBashJob(jobStatusMatch[1]!);\n\t\t\t\tif (!job) throw new Error(`Unknown bash async job: ${jobStatusMatch[1]}`);\n\t\t\t\tif (job.status !== \"running\") asyncJobManager?.acknowledgeDeliveries([job.jobId]);\n\t\t\t\tconst text = [`Job ${job.jobId}: ${job.status}`, `Command: ${job.command}`, job.error ? `Error: ${job.error}` : undefined, job.output].filter(Boolean).join(\"\\n\");\n\t\t\t\treturn { content: [{ type: \"text\", text }], details: { async: { jobId: job.jobId, type: \"bash\", state: job.status, command: job.command, status: job.status }, exitCode: job.exitCode, timeoutSeconds: job.timeoutSeconds, ...(job.requestedTimeoutSeconds !== undefined ? { requestedTimeoutSeconds: job.requestedTimeoutSeconds } : {}), ...(job.fullOutputPath ? { fullOutputPath: job.fullOutputPath } : {}), wallTimeMs: (job.endedAt ?? Date.now()) - job.startedAt } };\n\t\t\t}\n\t\t\tconst jobCancelMatch = command.match(/^__atomic_bash_job_cancel\\s+(\\S+)$/);\n\t\t\tif (jobCancelMatch) {\n\t\t\t\tconst job = abortManagedBashJob(jobCancelMatch[1]!);\n\t\t\t\tif (!job) throw new Error(`Unknown bash async job: ${jobCancelMatch[1]}`);\n\t\t\t\tasyncJobManager?.acknowledgeDeliveries([job.jobId]);\n\t\t\t\treturn { content: [{ type: \"text\", text: `Cancellation requested for bash job ${job.jobId}` }], details: { async: { jobId: job.jobId, type: \"bash\", state: job.status, command: job.command, status: job.status } } };\n\t\t\t}\n\t\t\tconst timeout = normalizeTimeoutSeconds(bashCommand.timeout);\n\t\t\tconst resourceCtx = _ctx as InternalResourceContext | undefined;\n\t\t\tconst hasExplicitCwd = typeof bashCommand.cwd === \"string\";\n\t\t\tconst rawStrippedContext = hasExplicitCwd ? undefined : stripLeadingCdCommand(command, cwd);\n\t\t\tconst interceptorEnabled = isInterceptorEnabled();\n\t\t\tif (interceptorEnabled) checkBashInterceptionCandidates([command, rawStrippedContext?.command], availableTools, interceptorRules);\n\t\t\tconst cwdInput = hasExplicitCwd ? await expandShellInternalUrls(bashCommand.cwd!, cwd, resourceCtx) : cwd, requestedCwd = resolvePath(cwd, cwdInput);\n\t\t\tconst expandedCommand = await expandShellInternalUrls(command, cwd, resourceCtx, true);\n\t\t\tconst strippedExpandedContext = hasExplicitCwd ? undefined : stripLeadingCdCommand(expandedCommand, requestedCwd);\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${expandedCommand}` : expandedCommand;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, requestedCwd, spawnHook);\n\t\t\tconst strippedCdContext = strippedExpandedContext ? resolveSpawnContext(commandPrefix ? `${commandPrefix}\\n${strippedExpandedContext.command}` : strippedExpandedContext.command, strippedExpandedContext.cwd, spawnHook) : undefined;\n\t\t\tif (interceptorEnabled) checkBashInterceptionCandidates([expandedCommand, strippedExpandedContext?.command, resolvedCommand, spawnContext.command, strippedCdContext?.command], availableTools, interceptorRules);\n\t\t\tlet expandedEnv: NodeJS.ProcessEnv | undefined;\n\t\t\tif (bashCommand.env) {\n\t\t\t\texpandedEnv = {};\n\t\t\t\tfor (const [key, value] of Object.entries(bashCommand.env)) {\n\t\t\t\t\tif (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new Error(`Invalid bash env name: ${key}`);\n\t\t\t\t\texpandedEnv[key] = await expandShellInternalUrls(value, cwd, resourceCtx);\n\t\t\t\t}\n\t\t\t\tspawnContext.env = { ...spawnContext.env, ...expandedEnv };\n\t\t\t}\n\t\t\tif (strippedCdContext && expandedEnv) strippedCdContext.env = { ...strippedCdContext.env, ...expandedEnv };\n\t\t\tconst primaryInterception = interceptorEnabled && interceptor ? await interceptor(spawnContext) : undefined;\n\t\t\tconst fallbackInterception = !primaryInterception && strippedCdContext && interceptorEnabled && interceptor ? await interceptor(strippedCdContext) : undefined;\n\t\t\tconst intercepted = primaryInterception ?? fallbackInterception;\n\t\t\tif (intercepted?.result) return bashResultToToolResult(intercepted.result);\n\t\t\tconst ops = intercepted?.operations ?? defaultOps;\n\t\t\tconst executionContext = primaryInterception ? spawnContext : (strippedCdContext ?? spawnContext);\n\t\t\tif (bashCommand.async) {\n\t\t\t\tif (!asyncEnabled) throw new Error(\"bash async execution is disabled\");\n\t\t\t\treturn startAsyncBashCommand({\n\t\t\t\t\tcommand: executionContext.command,\n\t\t\t\t\tcwd: executionContext.cwd,\n\t\t\t\t\tenv: executionContext.env,\n\t\t\t\t\tpty: bashCommand.pty,\n\t\t\t\t\ttimeoutSeconds: timeout,\n\t\t\t\t\trequestedTimeoutSeconds: bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? bashCommand.timeout : undefined,\n\t\t\t\t\tsignal,\n\t\t\t\t\toperations: ops,\n\t\t\t\t\tmanager: asyncJobManager,\n\t\t\t\t\tdeliveryHandler: asyncJobDeliveryHandler,\n\t\t\t\t\tsessionId: asyncJobSessionId,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });\n\t\t\tlet acceptingOutput = true;\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\tif (!acceptingOutput) return;\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\t\t\tconst finishOutput = async () => {\n\t\t\t\tacceptingOutput = false;\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\t\t\tconst startedAt = Date.now();\n\t\t\tconst withTiming = (details: BashToolDetails | undefined): BashToolDetails => ({ ...details, timeoutSeconds: timeout, ...(bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? { requestedTimeoutSeconds: bashCommand.timeout } : {}), wallTimeMs: Date.now() - startedAt });\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(executionContext.command, executionContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: executionContext.env,\n\t\t\t\t\t\tpty: bashCommand.pty,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\treturn { content: [{ type: \"text\", text: appendStatus(outputText, `Command exited with code ${exitCode}`) }], details: { ...withTiming(details), exitCode }, isError: true };\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details: withTiming(details) };\n\t\t\t} finally { invalidateNativeSearchCache(); clearUpdateTimer(); }\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}
@@ -10,8 +10,8 @@ import { truncateToVisualLines } from "../../modes/interactive/components/visual
10
10
  import { theme } from "../../modes/interactive/theme/theme.js";
11
11
  import { waitForChildProcess } from "../../utils/child-process.js";
12
12
  import { getShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid } from "../../utils/shell.js";
13
- import { createAsyncOutputAppender } from "./bash-async-output.js";
14
- import { abortManagedBashJob, createManagedBashJob, formatAsyncJobError, getManagedBashJob } from "./bash-async-jobs.js";
13
+ import { startAsyncBashCommand } from "./bash-async-execution.js";
14
+ import { abortManagedBashJob, getManagedBashJob } from "./bash-async-jobs.js";
15
15
  import { stripLeadingCdCommand } from "./bash-leading-cd.js";
16
16
  import { executeNativePty } from "./bash-pty-native.js";
17
17
  import { checkBashInterceptionCandidates, DEFAULT_BASH_INTERCEPTOR_RULES } from "./bash-interceptor.js";
@@ -110,8 +110,7 @@ function resolveSpawnContext(command, cwd, spawnHook) {
110
110
  const baseContext = { command, cwd, env: { ...getShellEnv() } };
111
111
  return spawnHook ? spawnHook(baseContext) : baseContext;
112
112
  }
113
- const BASH_PREVIEW_LINES = 5;
114
- const BASH_UPDATE_THROTTLE_MS = 100;
113
+ const BASH_PREVIEW_LINES = 5, BASH_UPDATE_THROTTLE_MS = 100;
115
114
  const DEFAULT_TIMEOUT_SECONDS = 300;
116
115
  const MIN_TIMEOUT_SECONDS = 1;
117
116
  const MAX_TIMEOUT_SECONDS = 3600;
@@ -228,6 +227,7 @@ export function createBashToolDefinition(cwd, options) {
228
227
  const availableTools = options?.availableTools ?? ["read", "search", "find", "edit", "write"];
229
228
  const interceptorRules = options?.interceptorRules ?? DEFAULT_BASH_INTERCEPTOR_RULES;
230
229
  const asyncEnabled = options?.asyncEnabled ?? false;
230
+ const asyncJobManager = options?.asyncJobManager, asyncJobDeliveryHandler = options?.asyncJobDeliveryHandler, asyncJobSessionId = options?.asyncJobSessionId;
231
231
  return {
232
232
  name: "bash",
233
233
  label: "bash",
@@ -242,6 +242,8 @@ export function createBashToolDefinition(cwd, options) {
242
242
  const job = getManagedBashJob(jobStatusMatch[1]);
243
243
  if (!job)
244
244
  throw new Error(`Unknown bash async job: ${jobStatusMatch[1]}`);
245
+ if (job.status !== "running")
246
+ asyncJobManager?.acknowledgeDeliveries([job.jobId]);
245
247
  const text = [`Job ${job.jobId}: ${job.status}`, `Command: ${job.command}`, job.error ? `Error: ${job.error}` : undefined, job.output].filter(Boolean).join("\n");
246
248
  return { content: [{ type: "text", text }], details: { async: { jobId: job.jobId, type: "bash", state: job.status, command: job.command, status: job.status }, exitCode: job.exitCode, timeoutSeconds: job.timeoutSeconds, ...(job.requestedTimeoutSeconds !== undefined ? { requestedTimeoutSeconds: job.requestedTimeoutSeconds } : {}), ...(job.fullOutputPath ? { fullOutputPath: job.fullOutputPath } : {}), wallTimeMs: (job.endedAt ?? Date.now()) - job.startedAt } };
247
249
  }
@@ -250,6 +252,7 @@ export function createBashToolDefinition(cwd, options) {
250
252
  const job = abortManagedBashJob(jobCancelMatch[1]);
251
253
  if (!job)
252
254
  throw new Error(`Unknown bash async job: ${jobCancelMatch[1]}`);
255
+ asyncJobManager?.acknowledgeDeliveries([job.jobId]);
253
256
  return { content: [{ type: "text", text: `Cancellation requested for bash job ${job.jobId}` }], details: { async: { jobId: job.jobId, type: "bash", state: job.status, command: job.command, status: job.status } } };
254
257
  }
255
258
  const timeout = normalizeTimeoutSeconds(bashCommand.timeout);
@@ -289,40 +292,19 @@ export function createBashToolDefinition(cwd, options) {
289
292
  if (bashCommand.async) {
290
293
  if (!asyncEnabled)
291
294
  throw new Error("bash async execution is disabled");
292
- const job = createManagedBashJob(executionContext.command, executionContext.cwd, timeout, bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? bashCommand.timeout : undefined);
293
- const appendAsyncOutput = createAsyncOutputAppender(job);
294
- const onParentAbort = () => job.abortController?.abort();
295
- if (signal?.aborted)
296
- onParentAbort();
297
- else
298
- signal?.addEventListener("abort", onParentAbort, { once: true });
299
- void (async () => {
300
- let error, exitCode;
301
- try {
302
- exitCode = (await ops.exec(executionContext.command, executionContext.cwd, { onData: appendAsyncOutput.append, timeout, env: executionContext.env, pty: bashCommand.pty, signal: job.abortController?.signal })).exitCode;
303
- }
304
- catch (execError) {
305
- error = execError;
306
- }
307
- try {
308
- await appendAsyncOutput.close();
309
- }
310
- catch (closeError) {
311
- error ??= closeError;
312
- }
313
- if (error !== undefined) {
314
- job.status = "failed";
315
- job.error = job.abortController?.signal.aborted ? "aborted" : formatAsyncJobError(error);
316
- }
317
- else {
318
- job.exitCode = exitCode;
319
- job.status = exitCode && exitCode !== 0 ? "failed" : "completed";
320
- }
321
- job.endedAt = Date.now();
322
- invalidateNativeSearchCache();
323
- signal?.removeEventListener("abort", onParentAbort);
324
- })();
325
- return { content: [{ type: "text", text: `Started async bash command ${job.jobId}: ${executionContext.command}\nPoll with bash({ command: "__atomic_bash_job ${job.jobId}" }); cancel with bash({ command: "__atomic_bash_job_cancel ${job.jobId}" })` }], details: { async: { jobId: job.jobId, type: "bash", state: "running", command: executionContext.command, status: "running" }, timeoutSeconds: timeout, ...(job.requestedTimeoutSeconds !== undefined ? { requestedTimeoutSeconds: job.requestedTimeoutSeconds } : {}) } };
295
+ return startAsyncBashCommand({
296
+ command: executionContext.command,
297
+ cwd: executionContext.cwd,
298
+ env: executionContext.env,
299
+ pty: bashCommand.pty,
300
+ timeoutSeconds: timeout,
301
+ requestedTimeoutSeconds: bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? bashCommand.timeout : undefined,
302
+ signal,
303
+ operations: ops,
304
+ manager: asyncJobManager,
305
+ deliveryHandler: asyncJobDeliveryHandler,
306
+ sessionId: asyncJobSessionId,
307
+ });
326
308
  }
327
309
  const output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });
328
310
  let acceptingOutput = true;
@@ -1 +1 @@
1
- {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { access as fsAccess, stat as fsStat } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../config.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport { getShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid } from \"../../utils/shell.ts\";\nimport type { BashResult } from \"../bash-executor.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { createAsyncOutputAppender } from \"./bash-async-output.ts\";\nimport { abortManagedBashJob, createManagedBashJob, formatAsyncJobError, getManagedBashJob } from \"./bash-async-jobs.ts\";\nimport { stripLeadingCdCommand } from \"./bash-leading-cd.ts\";\nimport { executeNativePty } from \"./bash-pty-native.ts\";\nimport { checkBashInterceptionCandidates, DEFAULT_BASH_INTERCEPTOR_RULES, type BashInterceptorRule } from \"./bash-interceptor.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { expandShellInternalUrls, type InternalResourceContext } from \"./resource-selectors.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { invalidateNativeSearchCache } from \"./search-native.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult } from \"./truncate.ts\";\nconst envSchema = Type.Unsafe<Record<string, string>>({ type: \"object\", description: \"Environment variables to add or override.\", additionalProperties: { type: \"string\" }, propertyNames: { pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\" } });\nconst bashBaseSchema = Type.Object({ command: Type.String({ description: \"Shell command to execute.\" }), env: Type.Optional(envSchema), timeout: Type.Optional(Type.Number({ description: \"Timeout in seconds.\" })), cwd: Type.Optional(Type.String({ description: \"Working directory for the command.\" })), pty: Type.Optional(Type.Boolean({ description: \"Run with PTY handling.\" })) }, { additionalProperties: false });\nconst bashSchema = Type.Object({ ...bashBaseSchema.properties, async: Type.Optional(Type.Boolean({ description: \"Run as a background job.\" })) }, { additionalProperties: false });\nexport type BashToolInput = Static<typeof bashSchema>;\nexport interface BashToolDetails { truncation?: TruncationResult; fullOutputPath?: string; exitCode?: number | null; async?: { jobId: string; type: \"bash\"; state: \"running\" | \"completed\" | \"failed\"; command?: string; status?: \"running\" | \"completed\" | \"failed\" }; timeoutSeconds?: number; requestedTimeoutSeconds?: number; wallTimeMs?: number }\nexport interface BashOperations {\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t\tpty?: boolean;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env, pty }) => {\n\t\t\tif (pty && process.env.PI_NO_PTY !== \"1\" && process.env.ATOMIC_NO_PTY !== \"1\") {\n\t\t\t\ttry { return await executeNativePty(command, cwd, { onData, signal, timeout, env, shellPath: options?.shellPath }); }\n\t\t\t\tcatch (error) { const message = String(error instanceof Error ? error.message : error); if (!message.includes(\"Native PTY\") && !message.includes(\"PtySession\")) throw error; }\n\t\t\t}\n\t\t\tconst shellConfig = getShellConfig(options?.shellPath);\n\t\t\ttry { const cwdStat = await fsStat(cwd); if (!cwdStat.isDirectory()) throw new Error(`Working directory is not a directory: ${cwd}`); await fsAccess(cwd, constants.F_OK); } catch (error) {\n\t\t\t\tif (error instanceof Error && error.message.startsWith(\"Working directory is not a directory\")) throw error;\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst commandFromStdin = shellConfig.commandTransport === \"stdin\";\n\t\t\tconst child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [commandFromStdin ? \"pipe\" : \"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (commandFromStdin) {\n\t\t\t\tchild.stdin?.on(\"error\", () => {});\n\t\t\t\tchild.stdin?.end(command);\n\t\t\t}\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = { command, cwd, env: { ...getShellEnv() } };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\nexport interface BashInterceptorResult {\n\toperations?: BashOperations;\n\tresult?: BashResult;\n}\nexport type BashInterceptor = (context: BashSpawnContext) => Promise<BashInterceptorResult | undefined> | BashInterceptorResult | undefined;\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n\tinterceptor?: BashInterceptor;\n\tinterceptorEnabled?: boolean | (() => boolean);\n\tavailableTools?: string[];\n\tinterceptorRules?: BashInterceptorRule[];\n\tasyncEnabled?: boolean;\n}\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\nconst DEFAULT_TIMEOUT_SECONDS = 300;\nconst MIN_TIMEOUT_SECONDS = 1;\nconst MAX_TIMEOUT_SECONDS = 3600;\nfunction normalizeTimeoutSeconds(timeout: number | undefined): number {\n\tif (timeout === undefined || !Number.isFinite(timeout)) return DEFAULT_TIMEOUT_SECONDS;\n\treturn Math.max(MIN_TIMEOUT_SECONDS, Math.min(MAX_TIMEOUT_SECONDS, Math.floor(timeout)));\n}\nfunction bashResultToToolResult(result: BashResult): { content: Array<{ type: \"text\"; text: string }>; details: BashToolDetails | undefined } {\n\tconst details: BashToolDetails | undefined = result.truncated ? { fullOutputPath: result.fullOutputPath } : undefined;\n\tconst status = result.cancelled ? \"Command aborted\" : result.exitCode && result.exitCode !== 0 ? `Command exited with code ${result.exitCode}` : undefined;\n\tconst text = `${result.output || \"(no output)\"}${status ? `\\n\\n${status}` : \"\"}`;\n\treturn { content: [{ type: \"text\", text }], details };\n}\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\nfunction formatDuration(ms: number): string {\n\tconst totalSeconds = Math.floor(Math.max(0, ms) / 1000);\n\tconst hours = Math.floor(totalSeconds / 3600);\n\tconst minutes = Math.floor((totalSeconds % 3600) / 60);\n\tconst seconds = totalSeconds % 60;\n\tif (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;\n\tif (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n\treturn `${seconds}s`;\n}\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"Expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst defaultOps = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\tconst interceptor = options?.interceptor;\n\tconst isInterceptorEnabled = (): boolean => typeof options?.interceptorEnabled === \"function\" ? options.interceptorEnabled() : options?.interceptorEnabled ?? !!interceptor;\n\tconst availableTools = options?.availableTools ?? [\"read\", \"search\", \"find\", \"edit\", \"write\"];\n\tconst interceptorRules = options?.interceptorRules ?? DEFAULT_BASH_INTERCEPTOR_RULES;\n\tconst asyncEnabled = options?.asyncEnabled ?? false;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: \"Execute a shell command in the session workspace, with optional PTY or background-job handling.\",\n\t\tpromptSnippet: \"Execute a shell command.\",\n\t\tparameters: asyncEnabled ? bashSchema : bashBaseSchema as typeof bashSchema,\n\t\tmaxResultSizeChars: Infinity,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tbashCommand: BashToolInput,\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst { command } = bashCommand;\n\t\t\tconst jobStatusMatch = command.match(/^__atomic_bash_job\\s+(\\S+)$/);\n\t\t\tif (jobStatusMatch) {\n\t\t\t\tconst job = getManagedBashJob(jobStatusMatch[1]!);\n\t\t\t\tif (!job) throw new Error(`Unknown bash async job: ${jobStatusMatch[1]}`);\n\t\t\t\tconst text = [`Job ${job.jobId}: ${job.status}`, `Command: ${job.command}`, job.error ? `Error: ${job.error}` : undefined, job.output].filter(Boolean).join(\"\\n\");\n\t\t\t\treturn { content: [{ type: \"text\", text }], details: { async: { jobId: job.jobId, type: \"bash\", state: job.status, command: job.command, status: job.status }, exitCode: job.exitCode, timeoutSeconds: job.timeoutSeconds, ...(job.requestedTimeoutSeconds !== undefined ? { requestedTimeoutSeconds: job.requestedTimeoutSeconds } : {}), ...(job.fullOutputPath ? { fullOutputPath: job.fullOutputPath } : {}), wallTimeMs: (job.endedAt ?? Date.now()) - job.startedAt } };\n\t\t\t}\n\t\t\tconst jobCancelMatch = command.match(/^__atomic_bash_job_cancel\\s+(\\S+)$/);\n\t\t\tif (jobCancelMatch) {\n\t\t\t\tconst job = abortManagedBashJob(jobCancelMatch[1]!);\n\t\t\t\tif (!job) throw new Error(`Unknown bash async job: ${jobCancelMatch[1]}`);\n\t\t\t\treturn { content: [{ type: \"text\", text: `Cancellation requested for bash job ${job.jobId}` }], details: { async: { jobId: job.jobId, type: \"bash\", state: job.status, command: job.command, status: job.status } } };\n\t\t\t}\n\t\t\tconst timeout = normalizeTimeoutSeconds(bashCommand.timeout);\n\t\t\tconst resourceCtx = _ctx as InternalResourceContext | undefined;\n\t\t\tconst hasExplicitCwd = typeof bashCommand.cwd === \"string\";\n\t\t\tconst rawStrippedContext = hasExplicitCwd ? undefined : stripLeadingCdCommand(command, cwd);\n\t\t\tconst interceptorEnabled = isInterceptorEnabled();\n\t\t\tif (interceptorEnabled) checkBashInterceptionCandidates([command, rawStrippedContext?.command], availableTools, interceptorRules);\n\t\t\tconst cwdInput = hasExplicitCwd ? await expandShellInternalUrls(bashCommand.cwd!, cwd, resourceCtx) : cwd, requestedCwd = resolvePath(cwd, cwdInput);\n\t\t\tconst expandedCommand = await expandShellInternalUrls(command, cwd, resourceCtx, true);\n\t\t\tconst strippedExpandedContext = hasExplicitCwd ? undefined : stripLeadingCdCommand(expandedCommand, requestedCwd);\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${expandedCommand}` : expandedCommand;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, requestedCwd, spawnHook);\n\t\t\tconst strippedCdContext = strippedExpandedContext ? resolveSpawnContext(commandPrefix ? `${commandPrefix}\\n${strippedExpandedContext.command}` : strippedExpandedContext.command, strippedExpandedContext.cwd, spawnHook) : undefined;\n\t\t\tif (interceptorEnabled) checkBashInterceptionCandidates([expandedCommand, strippedExpandedContext?.command, resolvedCommand, spawnContext.command, strippedCdContext?.command], availableTools, interceptorRules);\n\t\t\tlet expandedEnv: NodeJS.ProcessEnv | undefined;\n\t\t\tif (bashCommand.env) {\n\t\t\t\texpandedEnv = {};\n\t\t\t\tfor (const [key, value] of Object.entries(bashCommand.env)) {\n\t\t\t\t\tif (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new Error(`Invalid bash env name: ${key}`);\n\t\t\t\t\texpandedEnv[key] = await expandShellInternalUrls(value, cwd, resourceCtx);\n\t\t\t\t}\n\t\t\t\tspawnContext.env = { ...spawnContext.env, ...expandedEnv };\n\t\t\t}\n\t\t\tif (strippedCdContext && expandedEnv) strippedCdContext.env = { ...strippedCdContext.env, ...expandedEnv };\n\t\t\tconst primaryInterception = interceptorEnabled && interceptor ? await interceptor(spawnContext) : undefined;\n\t\t\tconst fallbackInterception = !primaryInterception && strippedCdContext && interceptorEnabled && interceptor ? await interceptor(strippedCdContext) : undefined;\n\t\t\tconst intercepted = primaryInterception ?? fallbackInterception;\n\t\t\tif (intercepted?.result) return bashResultToToolResult(intercepted.result);\n\t\t\tconst ops = intercepted?.operations ?? defaultOps;\n\t\t\tconst executionContext = primaryInterception ? spawnContext : (strippedCdContext ?? spawnContext);\n\t\t\tif (bashCommand.async) {\n\t\t\t\tif (!asyncEnabled) throw new Error(\"bash async execution is disabled\");\n\t\t\t\tconst job = createManagedBashJob(executionContext.command, executionContext.cwd, timeout, bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? bashCommand.timeout : undefined);\n\t\t\t\tconst appendAsyncOutput = createAsyncOutputAppender(job);\n\t\t\t\tconst onParentAbort = () => job.abortController?.abort();\n\t\t\t\tif (signal?.aborted) onParentAbort(); else signal?.addEventListener(\"abort\", onParentAbort, { once: true });\n\t\t\t\tvoid (async () => {\n\t\t\t\t\tlet error: unknown, exitCode: number | null | undefined;\n\t\t\t\t\ttry {\n\t\t\t\t\t\texitCode = (await ops.exec(executionContext.command, executionContext.cwd, { onData: appendAsyncOutput.append, timeout, env: executionContext.env, pty: bashCommand.pty, signal: job.abortController?.signal })).exitCode;\n\t\t\t\t\t} catch (execError: unknown) { error = execError; }\n\t\t\t\t\ttry { await appendAsyncOutput.close(); } catch (closeError: unknown) { error ??= closeError; }\n\t\t\t\t\tif (error !== undefined) {\n\t\t\t\t\t\tjob.status = \"failed\";\n\t\t\t\t\t\tjob.error = job.abortController?.signal.aborted ? \"aborted\" : formatAsyncJobError(error);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjob.exitCode = exitCode;\n\t\t\t\t\t\tjob.status = exitCode && exitCode !== 0 ? \"failed\" : \"completed\";\n\t\t\t\t\t}\n\t\t\t\t\tjob.endedAt = Date.now(); invalidateNativeSearchCache(); signal?.removeEventListener(\"abort\", onParentAbort);\n\t\t\t\t})();\n\t\t\t\treturn { content: [{ type: \"text\", text: `Started async bash command ${job.jobId}: ${executionContext.command}\\nPoll with bash({ command: \"__atomic_bash_job ${job.jobId}\" }); cancel with bash({ command: \"__atomic_bash_job_cancel ${job.jobId}\" })` }], details: { async: { jobId: job.jobId, type: \"bash\", state: \"running\", command: executionContext.command, status: \"running\" }, timeoutSeconds: timeout, ...(job.requestedTimeoutSeconds !== undefined ? { requestedTimeoutSeconds: job.requestedTimeoutSeconds } : {}) } };\n\t\t\t}\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });\n\t\t\tlet acceptingOutput = true;\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\tif (!acceptingOutput) return;\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\t\t\tconst finishOutput = async () => {\n\t\t\t\tacceptingOutput = false;\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\t\t\tconst startedAt = Date.now();\n\t\t\tconst withTiming = (details: BashToolDetails | undefined): BashToolDetails => ({ ...details, timeoutSeconds: timeout, ...(bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? { requestedTimeoutSeconds: bashCommand.timeout } : {}), wallTimeMs: Date.now() - startedAt });\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(executionContext.command, executionContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: executionContext.env,\n\t\t\t\t\t\tpty: bashCommand.pty,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\treturn { content: [{ type: \"text\", text: appendStatus(outputText, `Command exited with code ${exitCode}`) }], details: { ...withTiming(details), exitCode }, isError: true };\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details: withTiming(details) };\n\t\t\t} finally { invalidateNativeSearchCache(); clearUpdateTimer(); }\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEtE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,wDAAwD,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uDAAuD,CAAC;AAC9F,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAKpI,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,+BAA+B,EAAE,8BAA8B,EAA4B,MAAM,uBAAuB,CAAC;AAClI,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAgC,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAyB,MAAM,eAAe,CAAC;AACrF,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAyB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2CAA2C,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,0BAA0B,EAAE,EAAE,CAAC,CAAC;AACtO,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC,CAAC;AAC7Z,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,cAAc,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC,CAAC;AAgBnL,MAAM,UAAU,yBAAyB,CAAC,OAAgC;IACzE,OAAO;QACN,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE;YACnE,IAAI,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,GAAG,EAAE,CAAC;gBAC/E,IAAI,CAAC;oBAAC,OAAO,MAAM,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;gBAAC,CAAC;gBACrH,OAAO,KAAK,EAAE,CAAC;oBAAC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;oBAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;wBAAE,MAAM,KAAK,CAAC;gBAAC,CAAC;YAC/K,CAAC;YACD,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACvD,IAAI,CAAC;gBAAC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;oBAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;gBAAC,MAAM,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YAAC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAC3L,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,sCAAsC,CAAC;oBAAE,MAAM,KAAK,CAAC;gBAC5G,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,iCAAiC,CAAC,CAAC;YAC5F,CAAC;YACD,IAAI,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;YAChD,MAAM,gBAAgB,GAAG,WAAW,CAAC,gBAAgB,KAAK,OAAO,CAAC;YAClE,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;gBAC5G,GAAG;gBACH,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;gBACtC,GAAG,EAAE,GAAG,IAAI,WAAW,EAAE;gBACzB,KAAK,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;gBAC7D,WAAW,EAAE,IAAI;aACjB,CAAC,CAAC;YACH,IAAI,gBAAgB,EAAE,CAAC;gBACtB,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBACnC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;YACD,IAAI,KAAK,CAAC,GAAG;gBAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAChD,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,IAAI,aAAyC,CAAC;YAC9C,MAAM,OAAO,GAAG,GAAG,EAAE;gBACpB,IAAI,KAAK,CAAC,GAAG;oBAAE,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC3C,CAAC,CAAC;YACF,IAAI,CAAC;gBACJ,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;oBAC1C,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;wBAC/B,QAAQ,GAAG,IAAI,CAAC;wBAChB,IAAI,KAAK,CAAC,GAAG;4BAAE,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC3C,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC;gBACpB,CAAC;gBACD,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBACjC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBACjC,IAAI,MAAM,EAAE,CAAC;oBACZ,IAAI,MAAM,CAAC,OAAO;wBAAE,OAAO,EAAE,CAAC;;wBACzB,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAChE,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,CAAC;gBAClD,IAAI,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;gBAChD,IAAI,QAAQ,EAAE,CAAC;oBACd,MAAM,IAAI,KAAK,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;gBACvC,CAAC;gBACD,OAAO,EAAE,QAAQ,EAAE,CAAC;YACrB,CAAC;oBAAS,CAAC;gBACV,IAAI,KAAK,CAAC,GAAG;oBAAE,uBAAuB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClD,IAAI,aAAa;oBAAE,YAAY,CAAC,aAAa,CAAC,CAAC;gBAC/C,IAAI,MAAM;oBAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC1D,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC;AAOD,SAAS,mBAAmB,CAAC,OAAe,EAAE,GAAW,EAAE,SAAyB;IACnF,MAAM,WAAW,GAAqB,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,WAAW,EAAE,EAAE,EAAE,CAAC;IAClF,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;AACzD,CAAC;AAyBD,MAAM,kBAAkB,GAAG,CAAC,EAAE,uBAAuB,GAAG,GAAG,CAAC;AAC5D,MAAM,uBAAuB,GAAG,GAAG,CAAC;AACpC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACjC,SAAS,uBAAuB,CAAC,OAA2B;IAC3D,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,uBAAuB,CAAC;IACvF,OAAO,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC;AACD,SAAS,sBAAsB,CAAC,MAAkB;IACjD,MAAM,OAAO,GAAgC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACtH,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,4BAA4B,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3J,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,IAAI,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACjF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AACvD,CAAC;AAWD,MAAM,yBAA0B,SAAQ,SAAS;IAAjD;;QACC,UAAK,GAA0B;YAC9B,WAAW,EAAE,SAAS;YACtB,WAAW,EAAE,SAAS;YACtB,aAAa,EAAE,SAAS;SACxB,CAAC;IACH,CAAC;CAAA;AACD,SAAS,cAAc,CAAC,EAAU;IACjC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAClC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC;IAC1E,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC;IAChF,OAAO,GAAG,OAAO,GAAG,CAAC;AACtB,CAAC;AACD,SAAS,cAAc,CAAC,IAAwD;IAC/E,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,EAAE,OAA6B,CAAC;IACpD,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,MAAM,cAAc,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACpH,OAAO,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,cAAc,EAAE,CAAC,CAAC,GAAG,aAAa,CAAC;AACjF,CAAC;AACD,SAAS,gCAAgC,CACxC,SAAoC,EACpC,MAGC,EACD,OAAgC,EAChC,UAAmB,EACnB,SAA6B,EAC7B,OAA2B;IAE3B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;IAC9B,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,IAAI,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9C,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC;IACtD,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,UAAU,EAAE,SAAS,IAAI,cAAc,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3F,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,WAAW,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAC9E,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;QACjD,CAAC;IACF,CAAC;IACD,IAAI,MAAM,EAAE,CAAC;QACZ,MAAM,YAAY,GAAG,MAAM;aACzB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;aAC3C,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACtB,SAAS,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,CAAC;YACP,SAAS,CAAC,QAAQ,CAAC;gBAClB,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;oBACzB,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;wBACpE,MAAM,OAAO,GAAG,qBAAqB,CAAC,YAAY,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC;wBAC/E,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;wBACxC,KAAK,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;wBAC3C,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC;oBAC3B,CAAC;oBACD,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;wBACpD,MAAM,IAAI,GACT,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,CAAC,aAAa,iBAAiB,CAAC;4BAC/D,IAAI,OAAO,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;wBACtE,OAAO,CAAC,EAAE,EAAE,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;oBAChF,CAAC;oBACD,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC3C,CAAC;gBACD,UAAU,EAAE,GAAG,EAAE;oBAChB,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC;oBAC9B,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC;oBAC9B,KAAK,CAAC,aAAa,GAAG,SAAS,CAAC;gBACjC,CAAC;aACD,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IACD,IAAI,UAAU,EAAE,SAAS,IAAI,cAAc,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,cAAc,EAAE,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,gBAAgB,cAAc,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,UAAU,EAAE,SAAS,EAAE,CAAC;YAC3B,IAAI,UAAU,CAAC,WAAW,KAAK,OAAO,EAAE,CAAC;gBACxC,QAAQ,CAAC,IAAI,CAAC,sBAAsB,UAAU,CAAC,WAAW,OAAO,UAAU,CAAC,UAAU,QAAQ,CAAC,CAAC;YACjG,CAAC;iBAAM,CAAC;gBACP,QAAQ,CAAC,IAAI,CACZ,cAAc,UAAU,CAAC,WAAW,iBAAiB,UAAU,CAAC,UAAU,CAAC,QAAQ,IAAI,iBAAiB,CAAC,SAAS,CAClH,CAAC;YACH,CAAC;QACF,CAAC;QACD,SAAS,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QACrD,MAAM,OAAO,GAAG,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACtC,SAAS,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACjH,CAAC;AACF,CAAC;AACD,MAAM,UAAU,wBAAwB,CACvC,GAAW,EACX,OAAyB;IAEzB,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,yBAAyB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IACvG,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,CAAC;IAC7C,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,CAAC;IACrC,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,CAAC;IACzC,MAAM,oBAAoB,GAAG,GAAY,EAAE,CAAC,OAAO,OAAO,EAAE,kBAAkB,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,kBAAkB,IAAI,CAAC,CAAC,WAAW,CAAC;IAC5K,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9F,MAAM,gBAAgB,GAAG,OAAO,EAAE,gBAAgB,IAAI,8BAA8B,CAAC;IACrF,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,KAAK,CAAC;IACpD,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,EAAE,uBAAuB,GAAG,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,GAAG,OAAO,EAAE,iBAAiB,CAAC;IAC7J,OAAO;QACN,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;QACb,WAAW,EAAE,iGAAiG;QAC9G,aAAa,EAAE,0BAA0B;QACzC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAmC;QAC3E,kBAAkB,EAAE,QAAQ;QAC5B,KAAK,CAAC,OAAO,CACZ,WAAW,EACX,WAA0B,EAC1B,MAAoB,EACpB,QAAS,EACT,IAAK;YAEL,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC;YAChC,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACpE,IAAI,cAAc,EAAE,CAAC;gBACpB,MAAM,GAAG,GAAG,iBAAiB,CAAC,cAAc,CAAC,CAAC,CAAE,CAAC,CAAC;gBAClD,IAAI,CAAC,GAAG;oBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC1E,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;oBAAE,eAAe,EAAE,qBAAqB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;gBAClF,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,EAAE,YAAY,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClK,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,GAAG,CAAC,uBAAuB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,uBAAuB,EAAE,GAAG,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC;YAC/c,CAAC;YACD,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;YAC3E,IAAI,cAAc,EAAE,CAAC;gBACpB,MAAM,GAAG,GAAG,mBAAmB,CAAC,cAAc,CAAC,CAAC,CAAE,CAAC,CAAC;gBACpD,IAAI,CAAC,GAAG;oBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC1E,eAAe,EAAE,qBAAqB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;gBACpD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uCAAuC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;YACvN,CAAC;YACD,MAAM,OAAO,GAAG,uBAAuB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC7D,MAAM,WAAW,GAAG,IAA2C,CAAC;YAChE,MAAM,cAAc,GAAG,OAAO,WAAW,CAAC,GAAG,KAAK,QAAQ,CAAC;YAC3D,MAAM,kBAAkB,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC5F,MAAM,kBAAkB,GAAG,oBAAoB,EAAE,CAAC;YAClD,IAAI,kBAAkB;gBAAE,+BAA+B,CAAC,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;YAClI,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,MAAM,uBAAuB,CAAC,WAAW,CAAC,GAAI,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACrJ,MAAM,eAAe,GAAG,MAAM,uBAAuB,CAAC,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;YACvF,MAAM,uBAAuB,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;YAClH,MAAM,eAAe,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,KAAK,eAAe,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC;YACjG,MAAM,YAAY,GAAG,mBAAmB,CAAC,eAAe,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YACnF,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,CAAC,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,KAAK,uBAAuB,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,uBAAuB,CAAC,OAAO,EAAE,uBAAuB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACtO,IAAI,kBAAkB;gBAAE,+BAA+B,CAAC,CAAC,eAAe,EAAE,uBAAuB,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;YAClN,IAAI,WAA0C,CAAC;YAC/C,IAAI,WAAW,CAAC,GAAG,EAAE,CAAC;gBACrB,WAAW,GAAG,EAAE,CAAC;gBACjB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC5D,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC;wBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,EAAE,CAAC,CAAC;oBAC5F,WAAW,CAAC,GAAG,CAAC,GAAG,MAAM,uBAAuB,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;gBAC3E,CAAC;gBACD,YAAY,CAAC,GAAG,GAAG,EAAE,GAAG,YAAY,CAAC,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;YAC5D,CAAC;YACD,IAAI,iBAAiB,IAAI,WAAW;gBAAE,iBAAiB,CAAC,GAAG,GAAG,EAAE,GAAG,iBAAiB,CAAC,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;YAC3G,MAAM,mBAAmB,GAAG,kBAAkB,IAAI,WAAW,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC5G,MAAM,oBAAoB,GAAG,CAAC,mBAAmB,IAAI,iBAAiB,IAAI,kBAAkB,IAAI,WAAW,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC/J,MAAM,WAAW,GAAG,mBAAmB,IAAI,oBAAoB,CAAC;YAChE,IAAI,WAAW,EAAE,MAAM;gBAAE,OAAO,sBAAsB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAC3E,MAAM,GAAG,GAAG,WAAW,EAAE,UAAU,IAAI,UAAU,CAAC;YAClD,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,iBAAiB,IAAI,YAAY,CAAC,CAAC;YAClG,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;gBACvB,IAAI,CAAC,YAAY;oBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBACvE,OAAO,qBAAqB,CAAC;oBAC5B,OAAO,EAAE,gBAAgB,CAAC,OAAO;oBACjC,GAAG,EAAE,gBAAgB,CAAC,GAAG;oBACzB,GAAG,EAAE,gBAAgB,CAAC,GAAG;oBACzB,GAAG,EAAE,WAAW,CAAC,GAAG;oBACpB,cAAc,EAAE,OAAO;oBACvB,uBAAuB,EAAE,WAAW,CAAC,OAAO,KAAK,SAAS,IAAI,WAAW,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;oBAC/H,MAAM;oBACN,UAAU,EAAE,GAAG;oBACf,OAAO,EAAE,eAAe;oBACxB,eAAe,EAAE,uBAAuB;oBACxC,SAAS,EAAE,iBAAiB;iBAC5B,CAAC,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,EAAE,cAAc,EAAE,GAAG,QAAQ,OAAO,EAAE,CAAC,CAAC;YAC7E,IAAI,eAAe,GAAG,IAAI,CAAC;YAC3B,IAAI,WAAuC,CAAC;YAC5C,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,IAAI,YAAY,GAAG,CAAC,CAAC;YACrB,MAAM,gBAAgB,GAAG,GAAG,EAAE;gBAC7B,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW;oBAAE,OAAO;gBACtC,WAAW,GAAG,KAAK,CAAC;gBACpB,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/D,QAAQ,CAAC;oBACR,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;oBACzD,OAAO,EAAE;wBACR,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;wBAC3E,cAAc,EAAE,QAAQ,CAAC,cAAc;qBACvC;iBACD,CAAC,CAAC;YACJ,CAAC,CAAC;YACF,MAAM,gBAAgB,GAAG,GAAG,EAAE;gBAC7B,IAAI,WAAW,EAAE,CAAC;oBACjB,YAAY,CAAC,WAAW,CAAC,CAAC;oBAC1B,WAAW,GAAG,SAAS,CAAC;gBACzB,CAAC;YACF,CAAC,CAAC;YACF,MAAM,oBAAoB,GAAG,GAAG,EAAE;gBACjC,IAAI,CAAC,QAAQ;oBAAE,OAAO;gBACtB,WAAW,GAAG,IAAI,CAAC;gBACnB,MAAM,KAAK,GAAG,uBAAuB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC;gBACpE,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;oBAChB,gBAAgB,EAAE,CAAC;oBACnB,gBAAgB,EAAE,CAAC;oBACnB,OAAO;gBACR,CAAC;gBACD,WAAW,KAAK,UAAU,CAAC,GAAG,EAAE;oBAC/B,WAAW,GAAG,SAAS,CAAC;oBACxB,gBAAgB,EAAE,CAAC;gBACpB,CAAC,EAAE,KAAK,CAAC,CAAC;YACX,CAAC,CAAC;YACF,IAAI,QAAQ,EAAE,CAAC;gBACd,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;YAC/C,CAAC;YACD,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE;gBACnC,IAAI,CAAC,eAAe;oBAAE,OAAO;gBAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpB,oBAAoB,EAAE,CAAC;YACxB,CAAC,CAAC;YACF,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;gBAC/B,eAAe,GAAG,KAAK,CAAC;gBACxB,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChB,gBAAgB,EAAE,CAAC;gBACnB,gBAAgB,EAAE,CAAC;gBACnB,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/D,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;gBAC7B,OAAO,QAAQ,CAAC;YACjB,CAAC,CAAC;YACF,MAAM,YAAY,GAAG,CAAC,QAAkD,EAAE,SAAS,GAAG,aAAa,EAAE,EAAE;gBACtG,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;gBACvC,IAAI,IAAI,GAAG,QAAQ,CAAC,OAAO,IAAI,SAAS,CAAC;gBACzC,IAAI,OAAoC,CAAC;gBACzC,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;oBAC1B,OAAO,GAAG,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,CAAC,cAAc,EAAE,CAAC;oBAClE,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC,WAAW,GAAG,CAAC,CAAC;oBACrE,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC;oBACtC,IAAI,UAAU,CAAC,eAAe,EAAE,CAAC;wBAChC,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;wBAC3D,IAAI,IAAI,qBAAqB,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,YAAY,OAAO,aAAa,YAAY,mBAAmB,QAAQ,CAAC,cAAc,GAAG,CAAC;oBAC1J,CAAC;yBAAM,IAAI,UAAU,CAAC,WAAW,KAAK,OAAO,EAAE,CAAC;wBAC/C,IAAI,IAAI,sBAAsB,SAAS,IAAI,OAAO,OAAO,UAAU,CAAC,UAAU,kBAAkB,QAAQ,CAAC,cAAc,GAAG,CAAC;oBAC5H,CAAC;yBAAM,CAAC;wBACP,IAAI,IAAI,sBAAsB,SAAS,IAAI,OAAO,OAAO,UAAU,CAAC,UAAU,KAAK,UAAU,CAAC,iBAAiB,CAAC,yBAAyB,QAAQ,CAAC,cAAc,GAAG,CAAC;oBACrK,CAAC;gBACF,CAAC;gBACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YAC1B,CAAC,CAAC;YACF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,CAAC,OAAoC,EAAmB,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC,OAAO,KAAK,SAAS,IAAI,WAAW,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,uBAAuB,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;YAC/R,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,MAAc,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;YAC/F,IAAI,CAAC;gBACJ,IAAI,QAAuB,CAAC;gBAC5B,IAAI,CAAC;oBACJ,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,CAAC,GAAG,EAAE;wBAC7E,MAAM,EAAE,UAAU;wBAClB,MAAM;wBACN,OAAO;wBACP,GAAG,EAAE,gBAAgB,CAAC,GAAG;wBACzB,GAAG,EAAE,WAAW,CAAC,GAAG;qBACpB,CAAC,CAAC;oBACH,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;gBAC5B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACd,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;oBACtC,MAAM,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;oBAC5C,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;wBACvD,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC;oBACxD,CAAC;oBACD,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;wBAChE,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC9C,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,2BAA2B,WAAW,UAAU,CAAC,CAAC,CAAC;oBACvF,CAAC;oBACD,MAAM,GAAG,CAAC;gBACX,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;gBACtC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAC7D,IAAI,QAAQ,KAAK,CAAC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;oBACzC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,UAAU,EAAE,4BAA4B,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBAC9K,CAAC;gBACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxF,CAAC;oBAAS,CAAC;gBAAC,2BAA2B,EAAE,CAAC;gBAAC,gBAAgB,EAAE,CAAC;YAAC,CAAC;QACjE,CAAC;QACD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC5B,IAAI,OAAO,CAAC,gBAAgB,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC/D,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC7B,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;YAC3B,CAAC;YACD,MAAM,IAAI,GAAI,OAAO,CAAC,aAAkC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC;QACb,CAAC;QACD,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO;YAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC5B,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC3E,KAAK,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,CAAC;YAChE,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBAC3C,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC7B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACpB,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;oBAC9B,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC;gBAC5B,CAAC;YACF,CAAC;YACD,MAAM,SAAS,GACb,OAAO,CAAC,aAAuD,IAAI,IAAI,yBAAyB,EAAE,CAAC;YACrG,gCAAgC,CAC/B,SAAS,EACT,MAAM,EACN,OAAO,EACP,OAAO,CAAC,UAAU,EAClB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,OAAO,CACb,CAAC;YACF,SAAS,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QAClB,CAAC;KACD,CAAC;AACH,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,OAAyB;IACpE,OAAO,kBAAkB,CAAC,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import { constants } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { access as fsAccess, stat as fsStat } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../config.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport { getShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid } from \"../../utils/shell.ts\";\nimport type { AsyncJobManager } from \"../async/job-manager.js\";\nimport type { AsyncJobDeliveryMessage } from \"../async/types.js\";\nimport type { BashResult } from \"../bash-executor.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { startAsyncBashCommand } from \"./bash-async-execution.js\";\nimport { abortManagedBashJob, getManagedBashJob } from \"./bash-async-jobs.ts\";\nimport { stripLeadingCdCommand } from \"./bash-leading-cd.ts\";\nimport { executeNativePty } from \"./bash-pty-native.ts\";\nimport { checkBashInterceptionCandidates, DEFAULT_BASH_INTERCEPTOR_RULES, type BashInterceptorRule } from \"./bash-interceptor.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { expandShellInternalUrls, type InternalResourceContext } from \"./resource-selectors.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { invalidateNativeSearchCache } from \"./search-native.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult } from \"./truncate.ts\";\nconst envSchema = Type.Unsafe<Record<string, string>>({ type: \"object\", description: \"Environment variables to add or override.\", additionalProperties: { type: \"string\" }, propertyNames: { pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\" } });\nconst bashBaseSchema = Type.Object({ command: Type.String({ description: \"Shell command to execute.\" }), env: Type.Optional(envSchema), timeout: Type.Optional(Type.Number({ description: \"Timeout in seconds.\" })), cwd: Type.Optional(Type.String({ description: \"Working directory for the command.\" })), pty: Type.Optional(Type.Boolean({ description: \"Run with PTY handling.\" })) }, { additionalProperties: false });\nconst bashSchema = Type.Object({ ...bashBaseSchema.properties, async: Type.Optional(Type.Boolean({ description: \"Run as a background job.\" })) }, { additionalProperties: false });\nexport type BashToolInput = Static<typeof bashSchema>;\nexport interface BashToolDetails { truncation?: TruncationResult; fullOutputPath?: string; exitCode?: number | null; async?: { jobId: string; type: \"bash\"; state: \"running\" | \"completed\" | \"failed\"; command?: string; status?: \"running\" | \"completed\" | \"failed\" }; timeoutSeconds?: number; requestedTimeoutSeconds?: number; wallTimeMs?: number }\nexport interface BashOperations {\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t\tpty?: boolean;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env, pty }) => {\n\t\t\tif (pty && process.env.PI_NO_PTY !== \"1\" && process.env.ATOMIC_NO_PTY !== \"1\") {\n\t\t\t\ttry { return await executeNativePty(command, cwd, { onData, signal, timeout, env, shellPath: options?.shellPath }); }\n\t\t\t\tcatch (error) { const message = String(error instanceof Error ? error.message : error); if (!message.includes(\"Native PTY\") && !message.includes(\"PtySession\")) throw error; }\n\t\t\t}\n\t\t\tconst shellConfig = getShellConfig(options?.shellPath);\n\t\t\ttry { const cwdStat = await fsStat(cwd); if (!cwdStat.isDirectory()) throw new Error(`Working directory is not a directory: ${cwd}`); await fsAccess(cwd, constants.F_OK); } catch (error) {\n\t\t\t\tif (error instanceof Error && error.message.startsWith(\"Working directory is not a directory\")) throw error;\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst commandFromStdin = shellConfig.commandTransport === \"stdin\";\n\t\t\tconst child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [commandFromStdin ? \"pipe\" : \"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (commandFromStdin) {\n\t\t\t\tchild.stdin?.on(\"error\", () => {});\n\t\t\t\tchild.stdin?.end(command);\n\t\t\t}\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = { command, cwd, env: { ...getShellEnv() } };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\nexport interface BashInterceptorResult {\n\toperations?: BashOperations;\n\tresult?: BashResult;\n}\nexport type BashInterceptor = (context: BashSpawnContext) => Promise<BashInterceptorResult | undefined> | BashInterceptorResult | undefined;\nexport interface BashToolOptions {\n\toperations?: BashOperations;\n\t/** Prefix prepended to every shell command before execution. */\n\tcommandPrefix?: string;\n\t/** Override shell executable resolution for local bash operations. */\n\tshellPath?: string;\n\t/** Last-mile hook for rewriting the command/cwd/env spawn context. */\n\tspawnHook?: BashSpawnHook;\n\t/** Optional command interceptor used by extensions and parity tests. */\n\tinterceptor?: BashInterceptor;\n\tinterceptorEnabled?: boolean | (() => boolean);\n\tavailableTools?: string[];\n\tinterceptorRules?: BashInterceptorRule[];\n\t/** Enable background bash jobs and session-managed async result delivery. */\n\tasyncEnabled?: boolean;\n\tasyncJobManager?: AsyncJobManager;\n\tasyncJobDeliveryHandler?: (message: AsyncJobDeliveryMessage) => void | Promise<void>;\n\tasyncJobSessionId?: symbol;\n}\nconst BASH_PREVIEW_LINES = 5, BASH_UPDATE_THROTTLE_MS = 100;\nconst DEFAULT_TIMEOUT_SECONDS = 300;\nconst MIN_TIMEOUT_SECONDS = 1;\nconst MAX_TIMEOUT_SECONDS = 3600;\nfunction normalizeTimeoutSeconds(timeout: number | undefined): number {\n\tif (timeout === undefined || !Number.isFinite(timeout)) return DEFAULT_TIMEOUT_SECONDS;\n\treturn Math.max(MIN_TIMEOUT_SECONDS, Math.min(MAX_TIMEOUT_SECONDS, Math.floor(timeout)));\n}\nfunction bashResultToToolResult(result: BashResult): { content: Array<{ type: \"text\"; text: string }>; details: BashToolDetails | undefined } {\n\tconst details: BashToolDetails | undefined = result.truncated ? { fullOutputPath: result.fullOutputPath } : undefined;\n\tconst status = result.cancelled ? \"Command aborted\" : result.exitCode && result.exitCode !== 0 ? `Command exited with code ${result.exitCode}` : undefined;\n\tconst text = `${result.output || \"(no output)\"}${status ? `\\n\\n${status}` : \"\"}`;\n\treturn { content: [{ type: \"text\", text }], details };\n}\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\nfunction formatDuration(ms: number): string {\n\tconst totalSeconds = Math.floor(Math.max(0, ms) / 1000);\n\tconst hours = Math.floor(totalSeconds / 3600);\n\tconst minutes = Math.floor((totalSeconds % 3600) / 60);\n\tconst seconds = totalSeconds % 60;\n\tif (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;\n\tif (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n\treturn `${seconds}s`;\n}\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"Expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst defaultOps = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\tconst interceptor = options?.interceptor;\n\tconst isInterceptorEnabled = (): boolean => typeof options?.interceptorEnabled === \"function\" ? options.interceptorEnabled() : options?.interceptorEnabled ?? !!interceptor;\n\tconst availableTools = options?.availableTools ?? [\"read\", \"search\", \"find\", \"edit\", \"write\"];\n\tconst interceptorRules = options?.interceptorRules ?? DEFAULT_BASH_INTERCEPTOR_RULES;\n\tconst asyncEnabled = options?.asyncEnabled ?? false;\n\tconst asyncJobManager = options?.asyncJobManager, asyncJobDeliveryHandler = options?.asyncJobDeliveryHandler, asyncJobSessionId = options?.asyncJobSessionId;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: \"Execute a shell command in the session workspace, with optional PTY or background-job handling.\",\n\t\tpromptSnippet: \"Execute a shell command.\",\n\t\tparameters: asyncEnabled ? bashSchema : bashBaseSchema as typeof bashSchema,\n\t\tmaxResultSizeChars: Infinity,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tbashCommand: BashToolInput,\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst { command } = bashCommand;\n\t\t\tconst jobStatusMatch = command.match(/^__atomic_bash_job\\s+(\\S+)$/);\n\t\t\tif (jobStatusMatch) {\n\t\t\t\tconst job = getManagedBashJob(jobStatusMatch[1]!);\n\t\t\t\tif (!job) throw new Error(`Unknown bash async job: ${jobStatusMatch[1]}`);\n\t\t\t\tif (job.status !== \"running\") asyncJobManager?.acknowledgeDeliveries([job.jobId]);\n\t\t\t\tconst text = [`Job ${job.jobId}: ${job.status}`, `Command: ${job.command}`, job.error ? `Error: ${job.error}` : undefined, job.output].filter(Boolean).join(\"\\n\");\n\t\t\t\treturn { content: [{ type: \"text\", text }], details: { async: { jobId: job.jobId, type: \"bash\", state: job.status, command: job.command, status: job.status }, exitCode: job.exitCode, timeoutSeconds: job.timeoutSeconds, ...(job.requestedTimeoutSeconds !== undefined ? { requestedTimeoutSeconds: job.requestedTimeoutSeconds } : {}), ...(job.fullOutputPath ? { fullOutputPath: job.fullOutputPath } : {}), wallTimeMs: (job.endedAt ?? Date.now()) - job.startedAt } };\n\t\t\t}\n\t\t\tconst jobCancelMatch = command.match(/^__atomic_bash_job_cancel\\s+(\\S+)$/);\n\t\t\tif (jobCancelMatch) {\n\t\t\t\tconst job = abortManagedBashJob(jobCancelMatch[1]!);\n\t\t\t\tif (!job) throw new Error(`Unknown bash async job: ${jobCancelMatch[1]}`);\n\t\t\t\tasyncJobManager?.acknowledgeDeliveries([job.jobId]);\n\t\t\t\treturn { content: [{ type: \"text\", text: `Cancellation requested for bash job ${job.jobId}` }], details: { async: { jobId: job.jobId, type: \"bash\", state: job.status, command: job.command, status: job.status } } };\n\t\t\t}\n\t\t\tconst timeout = normalizeTimeoutSeconds(bashCommand.timeout);\n\t\t\tconst resourceCtx = _ctx as InternalResourceContext | undefined;\n\t\t\tconst hasExplicitCwd = typeof bashCommand.cwd === \"string\";\n\t\t\tconst rawStrippedContext = hasExplicitCwd ? undefined : stripLeadingCdCommand(command, cwd);\n\t\t\tconst interceptorEnabled = isInterceptorEnabled();\n\t\t\tif (interceptorEnabled) checkBashInterceptionCandidates([command, rawStrippedContext?.command], availableTools, interceptorRules);\n\t\t\tconst cwdInput = hasExplicitCwd ? await expandShellInternalUrls(bashCommand.cwd!, cwd, resourceCtx) : cwd, requestedCwd = resolvePath(cwd, cwdInput);\n\t\t\tconst expandedCommand = await expandShellInternalUrls(command, cwd, resourceCtx, true);\n\t\t\tconst strippedExpandedContext = hasExplicitCwd ? undefined : stripLeadingCdCommand(expandedCommand, requestedCwd);\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${expandedCommand}` : expandedCommand;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, requestedCwd, spawnHook);\n\t\t\tconst strippedCdContext = strippedExpandedContext ? resolveSpawnContext(commandPrefix ? `${commandPrefix}\\n${strippedExpandedContext.command}` : strippedExpandedContext.command, strippedExpandedContext.cwd, spawnHook) : undefined;\n\t\t\tif (interceptorEnabled) checkBashInterceptionCandidates([expandedCommand, strippedExpandedContext?.command, resolvedCommand, spawnContext.command, strippedCdContext?.command], availableTools, interceptorRules);\n\t\t\tlet expandedEnv: NodeJS.ProcessEnv | undefined;\n\t\t\tif (bashCommand.env) {\n\t\t\t\texpandedEnv = {};\n\t\t\t\tfor (const [key, value] of Object.entries(bashCommand.env)) {\n\t\t\t\t\tif (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new Error(`Invalid bash env name: ${key}`);\n\t\t\t\t\texpandedEnv[key] = await expandShellInternalUrls(value, cwd, resourceCtx);\n\t\t\t\t}\n\t\t\t\tspawnContext.env = { ...spawnContext.env, ...expandedEnv };\n\t\t\t}\n\t\t\tif (strippedCdContext && expandedEnv) strippedCdContext.env = { ...strippedCdContext.env, ...expandedEnv };\n\t\t\tconst primaryInterception = interceptorEnabled && interceptor ? await interceptor(spawnContext) : undefined;\n\t\t\tconst fallbackInterception = !primaryInterception && strippedCdContext && interceptorEnabled && interceptor ? await interceptor(strippedCdContext) : undefined;\n\t\t\tconst intercepted = primaryInterception ?? fallbackInterception;\n\t\t\tif (intercepted?.result) return bashResultToToolResult(intercepted.result);\n\t\t\tconst ops = intercepted?.operations ?? defaultOps;\n\t\t\tconst executionContext = primaryInterception ? spawnContext : (strippedCdContext ?? spawnContext);\n\t\t\tif (bashCommand.async) {\n\t\t\t\tif (!asyncEnabled) throw new Error(\"bash async execution is disabled\");\n\t\t\t\treturn startAsyncBashCommand({\n\t\t\t\t\tcommand: executionContext.command,\n\t\t\t\t\tcwd: executionContext.cwd,\n\t\t\t\t\tenv: executionContext.env,\n\t\t\t\t\tpty: bashCommand.pty,\n\t\t\t\t\ttimeoutSeconds: timeout,\n\t\t\t\t\trequestedTimeoutSeconds: bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? bashCommand.timeout : undefined,\n\t\t\t\t\tsignal,\n\t\t\t\t\toperations: ops,\n\t\t\t\t\tmanager: asyncJobManager,\n\t\t\t\t\tdeliveryHandler: asyncJobDeliveryHandler,\n\t\t\t\t\tsessionId: asyncJobSessionId,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });\n\t\t\tlet acceptingOutput = true;\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\tif (!acceptingOutput) return;\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\t\t\tconst finishOutput = async () => {\n\t\t\t\tacceptingOutput = false;\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\t\t\tconst startedAt = Date.now();\n\t\t\tconst withTiming = (details: BashToolDetails | undefined): BashToolDetails => ({ ...details, timeoutSeconds: timeout, ...(bashCommand.timeout !== undefined && bashCommand.timeout !== timeout ? { requestedTimeoutSeconds: bashCommand.timeout } : {}), wallTimeMs: Date.now() - startedAt });\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(executionContext.command, executionContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: executionContext.env,\n\t\t\t\t\t\tpty: bashCommand.pty,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\treturn { content: [{ type: \"text\", text: appendStatus(outputText, `Command exited with code ${exitCode}`) }], details: { ...withTiming(details), exitCode }, isError: true };\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details: withTiming(details) };\n\t\t\t} finally { invalidateNativeSearchCache(); clearUpdateTimer(); }\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}
package/docs/tools.md CHANGED
@@ -28,9 +28,11 @@ Before writing, Atomic verifies the current file against the tagged snapshot. If
28
28
 
29
29
  ## `bash` and `bashInterceptor`
30
30
 
31
- The `bash` tool executes shell commands in the session workspace, with optional PTY or background-job handling. When `pty: true` is requested, local execution uses the bundled Rust-backed PTY session so commands see a real terminal, including headless/tool-only and async job calls; if the native PTY package is unavailable, Atomic degrades to normal pipe execution. Set `PI_NO_PTY=1` or `ATOMIC_NO_PTY=1` to force normal pipe execution. Completed foreground results include oh-my-pi-style `timeoutSeconds`, `requestedTimeoutSeconds`, `wallTimeMs`, and non-zero `exitCode` metadata; background jobs use `details.async: { state, jobId, type: "bash" }`, can be polled with `bash({"command":"__atomic_bash_job <id>"})`, can be cancelled with `bash({"command":"__atomic_bash_job_cancel <id>"})`, and preserve overflow output in a temporary `fullOutputPath` when polling output is truncated. `bashInterceptor.enabled` defaults to `false`; interception is not auto-enabled.
31
+ The `bash` tool executes shell commands in the session workspace, with optional PTY or background-job handling. When `pty: true` is requested, local execution uses the bundled Rust-backed PTY session so commands see a real terminal, including headless/tool-only and async job calls; if the native PTY package is unavailable, Atomic degrades to normal pipe execution. Set `PI_NO_PTY=1` or `ATOMIC_NO_PTY=1` to force normal pipe execution. Completed foreground results include oh-my-pi-style `timeoutSeconds`, `requestedTimeoutSeconds`, `wallTimeMs`, and non-zero `exitCode` metadata; background jobs use `details.async: { state, jobId, type: "bash" }`, can be polled with `bash({"command":"__atomic_bash_job <id>"})`, can be cancelled with `bash({"command":"__atomic_bash_job_cancel <id>"})`, and preserve overflow output in a temporary `fullOutputPath` when polling output is truncated.
32
32
 
33
- When explicitly enabled in settings, built-in bash interceptor rules block common shell substitutes for first-class tools (`cat`/`grep`/`find`/in-place `sed`/redirection, etc.) only when the corresponding tool is available. Enabled bash tool calls are also offered to `user_bash` extension handlers before local execution. Atomic checks the original command, the internal-URL-expanded command, configured-prefix forms, `spawnHook`-rewritten commands, and a leading `cd path && command` or `cd path; command`-stripped form only when structured `cwd` was omitted, so interceptors can route commands by effective working directory without overriding explicit `cwd`. The bash schema accepts `cwd`, `env`, `timeout`, `pty`, and `async`; `cwd` and `env` are honored by the local executor, `timeout` defaults to 300s and is clamped to 1..3600s, and normal sessions enable tracked async jobs with bounded retention.
33
+ When a session-managed background bash job completes or fails, Atomic sends an `async-job-result` custom follow-up into the conversation automatically (`display: true`, delivered as a follow-up turn). Small results are inlined, and results whose raw output stays below the persistence threshold remain fully inline even if the formatted follow-up header pushes the message over the preview limit; persisted large results include a preview plus the retained `fullOutputPath` (persisted before the normal polling truncation limit so 12KB–50KB outputs remain recoverable). If the model explicitly polls a completed job with `__atomic_bash_job <id>` before the queued follow-up is delivered, or cancels a job with `__atomic_bash_job_cancel <id>`, Atomic acknowledges the result and suppresses duplicate auto-delivery while keeping the job pollable until normal bounded retention/TTL cleanup. Suppression is tied to the retained job rather than a short timer, so disposed-session jobs cannot later fall back into another session after a long-running command completes. Session delivery attempts are non-blocking across sessions: a live streaming session can defer its own follow-up until the stream boundary without delaying unrelated completed jobs. Session disposal removes that session's pending async delivery handlers; a shared manager remains alive while other live sessions still own active jobs, then cleans up when the last session is disposed. Direct SDK/tool-factory uses only get automatic delivery when they provide an async job manager/delivery handler; otherwise async jobs remain manually pollable.
34
+
35
+ When explicitly enabled in settings, built-in bash interceptor rules block common shell substitutes for first-class tools (`cat`/`grep`/`find`/in-place `sed`/redirection, etc.) only when the corresponding tool is available. Enabled bash tool calls are also offered to `user_bash` extension handlers before local execution. Atomic checks the original command, the internal-URL-expanded command, configured-prefix forms, `spawnHook`-rewritten commands, and a leading `cd path && command` or `cd path; command`-stripped form only when structured `cwd` was omitted, so interceptors can route commands by effective working directory without overriding explicit `cwd`. The bash schema accepts `cwd`, `env`, `timeout`, `pty`, and `async`; `cwd` and `env` are honored by the local executor, `timeout` defaults to 300s and is clamped to 1..3600s, and normal sessions enable tracked async jobs with bounded retention. `bashInterceptor.enabled` defaults to `false`; interception is not auto-enabled.
34
36
 
35
37
  ```json
36
38
  {