@gajae-code/coding-agent 0.16.3 → 0.16.6

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 (277) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/dist/types/capability/types.d.ts +4 -0
  3. package/dist/types/cli/args.d.ts +2 -2
  4. package/dist/types/cli/customize-doctor.d.ts +22 -0
  5. package/dist/types/cli/root-flags.d.ts +4 -2
  6. package/dist/types/cli.d.ts +1 -1
  7. package/dist/types/commands/launch.d.ts +1 -1
  8. package/dist/types/config/autorouting-tier-map.d.ts +3 -0
  9. package/dist/types/config/file-lock.d.ts +31 -3
  10. package/dist/types/config/model-registry.d.ts +4 -0
  11. package/dist/types/config/model-resolver.d.ts +9 -0
  12. package/dist/types/config/settings-schema.d.ts +29 -1
  13. package/dist/types/coordinator-mcp/question-state.d.ts +7 -0
  14. package/dist/types/coordinator-mcp/server.d.ts +7 -0
  15. package/dist/types/discovery/claude-plugins.d.ts +3 -1
  16. package/dist/types/discovery/helpers.d.ts +35 -0
  17. package/dist/types/exec/bash-executor.d.ts +17 -1
  18. package/dist/types/exec/bash-shell-guardian.d.ts +15 -0
  19. package/dist/types/exec/bash-shell-runtime-entry.d.ts +2 -0
  20. package/dist/types/exec/bash-shell-signals.d.ts +2 -0
  21. package/dist/types/exec/bash-shell-supervisor-entry.d.ts +1 -0
  22. package/dist/types/exec/bash-shell-supervisor.d.ts +10 -0
  23. package/dist/types/exec/bash-shell-worker-entry.d.ts +2 -0
  24. package/dist/types/exec/bash-shell-worker-protocol.d.ts +63 -0
  25. package/dist/types/exec/bash-shell-worker.d.ts +1 -0
  26. package/dist/types/exec/isolated-shell.d.ts +19 -0
  27. package/dist/types/extensibility/extensions/function-hooks-internal.d.ts +9 -0
  28. package/dist/types/extensibility/extensions/function-hooks.d.ts +169 -0
  29. package/dist/types/extensibility/extensions/index.d.ts +1 -0
  30. package/dist/types/extensibility/extensions/runner.d.ts +46 -6
  31. package/dist/types/extensibility/extensions/types.d.ts +16 -0
  32. package/dist/types/extensibility/extensions/wrapper.d.ts +3 -1
  33. package/dist/types/extensibility/gjc-plugins/constrained-hooks.d.ts +35 -2
  34. package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +16 -0
  35. package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -0
  36. package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
  37. package/dist/types/extensibility/hooks/types.d.ts +4 -0
  38. package/dist/types/extensibility/runtime-skill-discovery.d.ts +5 -2
  39. package/dist/types/extensibility/shared-events.d.ts +1 -1
  40. package/dist/types/extensibility/skill-management.d.ts +9 -4
  41. package/dist/types/extensibility/skills.d.ts +2 -0
  42. package/dist/types/gjc-runtime/empty-delete-gc.d.ts +4 -1
  43. package/dist/types/gjc-runtime/linux-proc.d.ts +2 -0
  44. package/dist/types/gjc-runtime/session-state-lock.d.ts +14 -0
  45. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +41 -3
  46. package/dist/types/gjc-runtime/ultragoal-succession.d.ts +251 -0
  47. package/dist/types/modes/components/assistant-message.d.ts +1 -2
  48. package/dist/types/modes/components/bash-execution.d.ts +1 -0
  49. package/dist/types/modes/components/execution-shared.d.ts +1 -0
  50. package/dist/types/modes/components/settings-selector.d.ts +6 -1
  51. package/dist/types/modes/components/status-line/command.d.ts +35 -0
  52. package/dist/types/modes/components/status-line/index.d.ts +1 -0
  53. package/dist/types/modes/components/status-line/types.d.ts +5 -0
  54. package/dist/types/modes/components/tool-status-header.d.ts +14 -0
  55. package/dist/types/modes/controllers/event-controller.d.ts +6 -0
  56. package/dist/types/modes/interactive-mode.d.ts +3 -0
  57. package/dist/types/modes/types.d.ts +7 -0
  58. package/dist/types/runtime-mcp/client.d.ts +9 -1
  59. package/dist/types/runtime-mcp/manager.d.ts +7 -1
  60. package/dist/types/runtime-mcp/pool.d.ts +22 -3
  61. package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
  62. package/dist/types/runtime-mcp/types.d.ts +22 -0
  63. package/dist/types/sdk/broker/ensure.d.ts +32 -0
  64. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +0 -1
  65. package/dist/types/sdk/broker/lifecycle.d.ts +6 -0
  66. package/dist/types/sdk/broker/startup-failure.d.ts +4 -1
  67. package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -0
  68. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +12 -0
  69. package/dist/types/sdk/bus/chat-effect-journal.d.ts +17 -2
  70. package/dist/types/sdk/bus/conversation-store.d.ts +11 -0
  71. package/dist/types/sdk/bus/lifecycle-commands.d.ts +8 -8
  72. package/dist/types/sdk/bus/slack-daemon.d.ts +1 -1
  73. package/dist/types/sdk/bus/slack-live-provider.d.ts +6 -0
  74. package/dist/types/sdk/bus/slack-provider.d.ts +12 -0
  75. package/dist/types/sdk/bus/topic-registry.d.ts +8 -0
  76. package/dist/types/sdk/client/client.d.ts +6 -0
  77. package/dist/types/sdk/host/host.d.ts +3 -1
  78. package/dist/types/sdk/host/session-runtime.d.ts +26 -1
  79. package/dist/types/sdk/lifecycle/service.d.ts +1 -0
  80. package/dist/types/sdk/router/session-router.d.ts +10 -2
  81. package/dist/types/sdk/session-api-key.d.ts +26 -0
  82. package/dist/types/sdk/session.d.ts +5 -1
  83. package/dist/types/sdk/transport/serve-cli.d.ts +1 -1
  84. package/dist/types/session/agent-session.d.ts +11 -0
  85. package/dist/types/session/fallback-chain-controller.d.ts +15 -0
  86. package/dist/types/session/internal/managed-session-storage.d.ts +7 -0
  87. package/dist/types/session/messages.d.ts +1 -0
  88. package/dist/types/session/session-manager.d.ts +3 -1
  89. package/dist/types/setup/paseo/announce.d.ts +112 -0
  90. package/dist/types/setup/paseo/setup-deps.d.ts +2 -1
  91. package/dist/types/skill-state/canonical-skills.d.ts +4 -0
  92. package/dist/types/system-prompt.d.ts +10 -0
  93. package/dist/types/task/executor.d.ts +5 -1
  94. package/dist/types/tools/bash.d.ts +1 -0
  95. package/dist/types/tools/fetch.d.ts +7 -0
  96. package/dist/types/tools/github-cache.d.ts +2 -1
  97. package/dist/types/tools/index.d.ts +10 -0
  98. package/dist/types/tools/path-utils.d.ts +2 -0
  99. package/dist/types/tools/search.d.ts +6 -0
  100. package/package.json +9 -7
  101. package/scripts/capture-status-line-custom-editor-showcase.ts +151 -0
  102. package/scripts/generate-sdk-operation-inventory.ts +11 -0
  103. package/scripts/verify-status-line-custom-editor-showcase.ts +309 -0
  104. package/src/capability/index.ts +14 -2
  105. package/src/capability/types.ts +4 -0
  106. package/src/cli/args.ts +20 -9
  107. package/src/cli/customize-doctor.ts +155 -12
  108. package/src/cli/root-flags.ts +5 -3
  109. package/src/cli.ts +22 -0
  110. package/src/commands/sdk.ts +74 -31
  111. package/src/config/autorouting-tier-map.ts +1 -0
  112. package/src/config/file-lock-gc.ts +40 -2
  113. package/src/config/file-lock.ts +379 -31
  114. package/src/config/model-preset-registry.ts +120 -19
  115. package/src/config/model-profiles.ts +40 -0
  116. package/src/config/model-registry.ts +73 -23
  117. package/src/config/model-resolver.ts +48 -0
  118. package/src/config/settings-schema.ts +33 -1
  119. package/src/config/settings.ts +1 -0
  120. package/src/coordinator-mcp/question-state.ts +33 -2
  121. package/src/coordinator-mcp/server.ts +477 -101
  122. package/src/crash/sanitize.ts +1 -1
  123. package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +11 -11
  124. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +13 -2
  125. package/src/defaults/gjc/skills/ultragoal/SKILL.md +22 -0
  126. package/src/discovery/builtin.ts +52 -55
  127. package/src/discovery/claude-plugins.ts +12 -4
  128. package/src/discovery/helpers.ts +307 -34
  129. package/src/exec/bash-executor.ts +330 -50
  130. package/src/exec/bash-shell-guardian.ts +388 -0
  131. package/src/exec/bash-shell-runtime-entry.ts +5 -0
  132. package/src/exec/bash-shell-signals.ts +29 -0
  133. package/src/exec/bash-shell-supervisor-entry.ts +3 -0
  134. package/src/exec/bash-shell-supervisor.ts +359 -0
  135. package/src/exec/bash-shell-worker-entry.ts +5 -0
  136. package/src/exec/bash-shell-worker-protocol.ts +36 -0
  137. package/src/exec/bash-shell-worker.ts +116 -0
  138. package/src/exec/isolated-shell.ts +393 -0
  139. package/src/extensibility/extensions/function-hooks-internal.ts +73 -0
  140. package/src/extensibility/extensions/function-hooks.ts +959 -0
  141. package/src/extensibility/extensions/index.ts +22 -0
  142. package/src/extensibility/extensions/loader.ts +53 -2
  143. package/src/extensibility/extensions/runner.ts +895 -264
  144. package/src/extensibility/extensions/types.ts +42 -0
  145. package/src/extensibility/extensions/wrapper.ts +56 -15
  146. package/src/extensibility/gjc-plugins/compiler.ts +228 -60
  147. package/src/extensibility/gjc-plugins/constrained-hooks.ts +321 -23
  148. package/src/extensibility/gjc-plugins/installer.ts +13 -12
  149. package/src/extensibility/gjc-plugins/mcp-policy.ts +81 -52
  150. package/src/extensibility/gjc-plugins/paths.ts +13 -0
  151. package/src/extensibility/gjc-plugins/registry.ts +113 -1
  152. package/src/extensibility/gjc-plugins/runtime-adapters.ts +758 -16
  153. package/src/extensibility/gjc-plugins/runtime-quarantine.ts +20 -2
  154. package/src/extensibility/gjc-plugins/schema.ts +121 -4
  155. package/src/extensibility/gjc-plugins/types.ts +25 -0
  156. package/src/extensibility/hooks/loader.ts +133 -16
  157. package/src/extensibility/hooks/types.ts +28 -0
  158. package/src/extensibility/runtime-skill-discovery.ts +149 -190
  159. package/src/extensibility/shared-events.ts +1 -1
  160. package/src/extensibility/skill-management.ts +200 -52
  161. package/src/extensibility/skills.ts +73 -25
  162. package/src/gjc-runtime/empty-delete-gc.ts +94 -4
  163. package/src/gjc-runtime/gc-runtime.ts +29 -0
  164. package/src/gjc-runtime/linux-proc.ts +14 -0
  165. package/src/gjc-runtime/repository-binding.ts +1 -1
  166. package/src/gjc-runtime/session-state-lock.ts +143 -10
  167. package/src/gjc-runtime/session-state-sidecar.ts +27 -11
  168. package/src/gjc-runtime/state-writer.ts +30 -29
  169. package/src/gjc-runtime/ultragoal-runtime.ts +189 -47
  170. package/src/gjc-runtime/ultragoal-succession.ts +1667 -0
  171. package/src/gjc-runtime/workflow-manifest.generated.json +52 -1
  172. package/src/gjc-runtime/workflow-manifest.ts +16 -0
  173. package/src/harness-control-plane/session-lease.ts +2 -2
  174. package/src/internal-urls/docs-index.generated.ts +12 -12
  175. package/src/lsp/config.ts +10 -3
  176. package/src/lsp/index.ts +1 -1
  177. package/src/lsp/path-trust.ts +69 -14
  178. package/src/main.ts +78 -35
  179. package/src/modes/DESIGN.md +54 -0
  180. package/src/modes/acp/acp-agent.ts +16 -3
  181. package/src/modes/components/assistant-message.ts +22 -9
  182. package/src/modes/components/bash-execution.ts +4 -1
  183. package/src/modes/components/execution-shared.ts +4 -1
  184. package/src/modes/components/model-selector.ts +166 -33
  185. package/src/modes/components/session-observer-overlay.ts +1 -1
  186. package/src/modes/components/settings-selector.ts +1075 -235
  187. package/src/modes/components/status-line/command.ts +190 -0
  188. package/src/modes/components/status-line/index.ts +1 -0
  189. package/src/modes/components/status-line/segments.ts +32 -5
  190. package/src/modes/components/status-line/types.ts +5 -0
  191. package/src/modes/components/tool-status-header.ts +396 -22
  192. package/src/modes/controllers/command-controller.ts +3 -0
  193. package/src/modes/controllers/event-controller.ts +151 -7
  194. package/src/modes/controllers/extension-ui-controller.ts +1 -0
  195. package/src/modes/controllers/input-controller.ts +6 -3
  196. package/src/modes/controllers/selector-controller.ts +21 -0
  197. package/src/modes/interactive-mode.ts +53 -6
  198. package/src/modes/print-mode.ts +5 -1
  199. package/src/modes/prompt-action-autocomplete.ts +54 -27
  200. package/src/modes/runtime-init.ts +2 -0
  201. package/src/modes/types.ts +17 -3
  202. package/src/modes/utils/ui-helpers.ts +2 -0
  203. package/src/prompts/system/system-prompt.md +8 -0
  204. package/src/prompts/tools/search.md +2 -0
  205. package/src/prompts/tools/subagent.md +1 -0
  206. package/src/runtime-mcp/client.ts +60 -17
  207. package/src/runtime-mcp/manager.ts +189 -14
  208. package/src/runtime-mcp/pool.test.ts +218 -0
  209. package/src/runtime-mcp/pool.ts +224 -23
  210. package/src/runtime-mcp/transports/stdio.ts +158 -24
  211. package/src/runtime-mcp/types.ts +24 -0
  212. package/src/sdk/broker/broker.ts +124 -32
  213. package/src/sdk/broker/ensure.ts +248 -41
  214. package/src/sdk/broker/lifecycle-ledger.ts +7 -17
  215. package/src/sdk/broker/lifecycle.ts +56 -6
  216. package/src/sdk/broker/startup-failure.ts +15 -6
  217. package/src/sdk/bus/chat-daemon-control.ts +3 -1
  218. package/src/sdk/bus/chat-daemon-runtime.ts +72 -6
  219. package/src/sdk/bus/chat-effect-journal.ts +132 -7
  220. package/src/sdk/bus/conversation-store.ts +29 -0
  221. package/src/sdk/bus/lifecycle-commands.ts +17 -11
  222. package/src/sdk/bus/slack-conversation.ts +1 -0
  223. package/src/sdk/bus/slack-daemon.ts +478 -49
  224. package/src/sdk/bus/slack-live-provider.ts +12 -0
  225. package/src/sdk/bus/slack-provider.ts +5 -0
  226. package/src/sdk/bus/telegram-daemon.ts +16 -2
  227. package/src/sdk/bus/topic-registry.ts +19 -0
  228. package/src/sdk/cli/master-cli.ts +1 -1
  229. package/src/sdk/cli/session-cli.ts +11 -8
  230. package/src/sdk/client/client.ts +66 -17
  231. package/src/sdk/host/host.ts +29 -9
  232. package/src/sdk/host/query/revision-store.ts +19 -13
  233. package/src/sdk/host/reverse-leases.ts +7 -4
  234. package/src/sdk/host/session-runtime.test.ts +52 -10
  235. package/src/sdk/host/session-runtime.ts +383 -44
  236. package/src/sdk/lifecycle/service.ts +4 -0
  237. package/src/sdk/protocol/operation-inventory.generated.json +77 -0
  238. package/src/sdk/router/session-router.ts +89 -38
  239. package/src/sdk/session-api-key.ts +94 -0
  240. package/src/sdk/session.ts +228 -55
  241. package/src/sdk/transport/relay.ts +35 -13
  242. package/src/sdk/transport/serve-cli.ts +3 -3
  243. package/src/session/agent-session.ts +240 -90
  244. package/src/session/contribution-prep.ts +214 -21
  245. package/src/session/fallback-chain-controller.ts +38 -0
  246. package/src/session/internal/managed-session-storage.ts +19 -5
  247. package/src/session/messages.ts +5 -0
  248. package/src/session/session-manager.ts +29 -5
  249. package/src/session-import/redact.ts +5 -1
  250. package/src/setup/paseo/announce.ts +456 -0
  251. package/src/setup/paseo/setup-deps.ts +15 -3
  252. package/src/skill-state/canonical-skills.ts +12 -0
  253. package/src/skills/skills.test.ts +41 -21
  254. package/src/slash-commands/builtin-registry.ts +1 -0
  255. package/src/system-prompt.ts +29 -3
  256. package/src/task/executor.ts +7 -1
  257. package/src/task/index.ts +21 -4
  258. package/src/tools/bash.ts +63 -19
  259. package/src/tools/cron.ts +1 -1
  260. package/src/tools/fetch.ts +29 -1
  261. package/src/tools/gh.ts +26 -3
  262. package/src/tools/github-cache.ts +68 -16
  263. package/src/tools/index.ts +10 -0
  264. package/src/tools/job.ts +21 -4
  265. package/src/tools/monitor.ts +8 -2
  266. package/src/tools/path-utils.ts +7 -0
  267. package/src/tools/read.ts +14 -2
  268. package/src/tools/render-utils.ts +1 -3
  269. package/src/tools/resource-gc.ts +28 -8
  270. package/src/tools/search.ts +116 -58
  271. package/src/tools/skill-discovery.ts +5 -0
  272. package/src/tools/skill.ts +37 -2
  273. package/src/tools/subagent.ts +6 -3
  274. package/src/tools/tool-catalog.generated.ts +10 -3
  275. package/src/tools/ultragoal-ask-guard.ts +2 -2
  276. package/src/web/insane/bridge.ts +113 -23
  277. package/src/web/search/providers/perplexity.ts +102 -41
@@ -0,0 +1,190 @@
1
+ const DEFAULT_TIMEOUT_MS = 500;
2
+ const MIN_TIMEOUT_MS = 50;
3
+ const MAX_TIMEOUT_MS = 10_000;
4
+ const DEFAULT_REFRESH_MS = 5_000;
5
+ const MIN_REFRESH_MS = 250;
6
+ const MAX_REFRESH_MS = 60_000;
7
+ export const STATUS_LINE_COMMAND_DEFAULT_MAX_LENGTH = 80;
8
+ export const STATUS_LINE_COMMAND_MAX_LENGTH = 256;
9
+ const STATUS_LINE_COMMAND_MAX_OUTPUT_BYTES = 16 * 1024;
10
+ const STATUS_LINE_COMMAND_MAX_DIAGNOSTIC_BYTES = 1_024;
11
+
12
+ export interface StatusLineCommandOptions {
13
+ command?: string;
14
+ timeoutMs?: number;
15
+ refreshMs?: number;
16
+ maxLength?: number;
17
+ }
18
+
19
+ export interface ResolvedStatusLineCommandOptions {
20
+ command: string;
21
+ timeoutMs: number;
22
+ refreshMs: number;
23
+ maxLength: number;
24
+ }
25
+
26
+ export interface StatusLineCommandResult {
27
+ stdout: string;
28
+ stderr: string;
29
+ exitCode: number;
30
+ timedOut: boolean;
31
+ outputTruncated: boolean;
32
+ }
33
+
34
+ interface BoundedReadResult {
35
+ text: string;
36
+ truncated: boolean;
37
+ }
38
+
39
+ function finiteNumber(value: unknown, fallback: number): number {
40
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
41
+ }
42
+
43
+ function clampInteger(value: unknown, fallback: number, min: number, max: number): number {
44
+ return Math.max(min, Math.min(max, Math.trunc(finiteNumber(value, fallback))));
45
+ }
46
+
47
+ export function normalizeStatusLineCommandOptions(value: unknown): ResolvedStatusLineCommandOptions {
48
+ const record = value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : {};
49
+ return {
50
+ command: typeof record.command === "string" ? record.command.trim() : "",
51
+ timeoutMs: clampInteger(record.timeoutMs, DEFAULT_TIMEOUT_MS, MIN_TIMEOUT_MS, MAX_TIMEOUT_MS),
52
+ refreshMs: clampInteger(record.refreshMs, DEFAULT_REFRESH_MS, MIN_REFRESH_MS, MAX_REFRESH_MS),
53
+ maxLength: clampInteger(
54
+ record.maxLength,
55
+ STATUS_LINE_COMMAND_DEFAULT_MAX_LENGTH,
56
+ 1,
57
+ STATUS_LINE_COMMAND_MAX_LENGTH,
58
+ ),
59
+ };
60
+ }
61
+
62
+ async function readBounded(stream: ReadableStream<Uint8Array>, maxBytes: number): Promise<BoundedReadResult> {
63
+ const reader = stream.getReader();
64
+ const chunks: Uint8Array[] = [];
65
+ let retainedBytes = 0;
66
+ let truncated = false;
67
+
68
+ try {
69
+ while (true) {
70
+ const { done, value } = await reader.read();
71
+ if (done) break;
72
+ if (!(value instanceof Uint8Array)) continue;
73
+ if (retainedBytes >= maxBytes) {
74
+ truncated = true;
75
+ continue;
76
+ }
77
+ const remaining = maxBytes - retainedBytes;
78
+ const retained = value.byteLength <= remaining ? value : value.slice(0, remaining);
79
+ chunks.push(retained);
80
+ retainedBytes += retained.byteLength;
81
+ if (retained.byteLength < value.byteLength) truncated = true;
82
+ }
83
+ } finally {
84
+ reader.releaseLock();
85
+ }
86
+
87
+ const bytes = new Uint8Array(retainedBytes);
88
+ let offset = 0;
89
+ for (const chunk of chunks) {
90
+ bytes.set(chunk, offset);
91
+ offset += chunk.byteLength;
92
+ }
93
+ return { text: new TextDecoder().decode(bytes), truncated };
94
+ }
95
+
96
+ function boundedDiagnostic(text: string): string {
97
+ return text.replace(/\s+/gu, " ").trim().slice(0, STATUS_LINE_COMMAND_MAX_DIAGNOSTIC_BYTES);
98
+ }
99
+
100
+ /**
101
+ * Run a configured status-line command without making the synchronous render
102
+ * path wait on it. The streams are drained with a hard byte cap and the whole
103
+ * process group is killed when the timeout expires.
104
+ */
105
+ export async function runStatusLineCommand(
106
+ command: string,
107
+ options: {
108
+ cwd: string;
109
+ shell: string;
110
+ shellArgs: readonly string[];
111
+ env: Record<string, string>;
112
+ timeoutMs: number;
113
+ signal?: AbortSignal;
114
+ },
115
+ ): Promise<StatusLineCommandResult> {
116
+ const proc = Bun.spawn([options.shell, ...options.shellArgs, command], {
117
+ cwd: options.cwd,
118
+ env: options.env,
119
+ stdin: "ignore",
120
+ stdout: "pipe",
121
+ stderr: "pipe",
122
+ detached: process.platform !== "win32",
123
+ ...(process.platform === "win32" ? { windowsHide: true } : {}),
124
+ });
125
+
126
+ let timedOut = false;
127
+ let termination: Promise<void> | undefined;
128
+ const terminateProcessTree = async (): Promise<void> => {
129
+ if (process.platform === "win32" && proc.pid) {
130
+ try {
131
+ const taskkill = Bun.spawn(["taskkill", "/pid", String(proc.pid), "/t", "/f"], {
132
+ stdout: "ignore",
133
+ stderr: "ignore",
134
+ windowsHide: true,
135
+ });
136
+ await taskkill.exited;
137
+ return;
138
+ } catch {
139
+ // Fall through to the direct kill if taskkill is unavailable.
140
+ }
141
+ }
142
+ try {
143
+ if (process.platform !== "win32" && proc.pid) process.kill(-proc.pid, "SIGKILL");
144
+ else proc.kill();
145
+ } catch {
146
+ try {
147
+ proc.kill();
148
+ } catch {
149
+ // The process already exited.
150
+ }
151
+ }
152
+ };
153
+ const terminate = (): void => {
154
+ termination ??= terminateProcessTree();
155
+ };
156
+ let aborted = false;
157
+ const onAbort = (): void => {
158
+ aborted = true;
159
+ terminate();
160
+ };
161
+ if (options.signal?.aborted) onAbort();
162
+ else options.signal?.addEventListener("abort", onAbort, { once: true });
163
+ const timeout = setTimeout(() => {
164
+ timedOut = true;
165
+ terminate();
166
+ }, options.timeoutMs);
167
+
168
+ try {
169
+ const exitCodePromise = proc.exited.then(async exitCode => {
170
+ if (termination) await termination;
171
+ return exitCode;
172
+ });
173
+ const [stdout, stderr, exitCode] = await Promise.all([
174
+ readBounded(proc.stdout, STATUS_LINE_COMMAND_MAX_OUTPUT_BYTES),
175
+ readBounded(proc.stderr, STATUS_LINE_COMMAND_MAX_DIAGNOSTIC_BYTES),
176
+ exitCodePromise,
177
+ ]);
178
+ if (termination) await termination;
179
+ return {
180
+ stdout: stdout.text,
181
+ stderr: boundedDiagnostic(stderr.text),
182
+ exitCode: exitCode ?? 1,
183
+ timedOut: timedOut || aborted,
184
+ outputTruncated: stdout.truncated,
185
+ };
186
+ } finally {
187
+ clearTimeout(timeout);
188
+ options.signal?.removeEventListener("abort", onAbort);
189
+ }
190
+ }
@@ -1,3 +1,4 @@
1
+ export * from "./command";
1
2
  export * from "./presets";
2
3
  export * from "./segments";
3
4
  export * from "./separators";
@@ -1,12 +1,13 @@
1
1
  import * as os from "node:os";
2
2
  import * as path from "node:path";
3
3
  import { ThinkingLevel } from "@gajae-code/agent-core";
4
- import { TERMINAL } from "@gajae-code/tui";
4
+ import { TERMINAL, truncateToWidth } from "@gajae-code/tui";
5
5
  import { formatDuration, formatNumber, getProjectDir, pathIsWithin, relativePathWithinRoot } from "@gajae-code/utils";
6
6
  import { type ThemeColor, theme } from "../../../modes/theme/theme";
7
7
  import { shortenPath } from "../../../tools/render-utils";
8
8
  import { getSessionAccentAnsi, getSessionAccentHex } from "../../../utils/session-color";
9
9
  import { sanitizeStatusText } from "../../shared";
10
+ import { normalizeStatusLineCommandOptions } from "./command";
10
11
  import { getContextUsageLevel, getContextUsageThemeColor } from "./context-thresholds";
11
12
  import { shortenModelId } from "./model-name";
12
13
  import type { RenderedSegment, SegmentContext, StatusLineSegment, StatusLineSegmentId } from "./types";
@@ -523,6 +524,26 @@ const cacheWriteSegment: StatusLineSegment = {
523
524
  },
524
525
  };
525
526
 
527
+ const commandSegment: StatusLineSegment = {
528
+ id: "command",
529
+ render(ctx) {
530
+ const state = ctx.command;
531
+ if (!state) return { content: theme.fg("dim", "?"), visible: true };
532
+
533
+ if (typeof state.output === "string") {
534
+ const text = truncateToWidth(
535
+ sanitizeStatusText(state.output),
536
+ normalizeStatusLineCommandOptions(ctx.options.command).maxLength,
537
+ );
538
+ if (text) return { content: theme.fg("statusLineOutput", text), visible: true };
539
+ }
540
+
541
+ if (state.failed) return { content: theme.fg("dim", "?"), visible: true };
542
+ if (state.pending) return { content: theme.fg("dim", "…"), visible: true };
543
+ return { content: "", visible: false };
544
+ },
545
+ };
546
+
526
547
  const sessionNameSegment: StatusLineSegment = {
527
548
  id: "session_name",
528
549
  render(ctx) {
@@ -611,16 +632,22 @@ export const SEGMENTS: Record<StatusLineSegmentId, StatusLineSegment> = {
611
632
  hostname: hostnameSegment,
612
633
  cache_read: cacheReadSegment,
613
634
  cache_write: cacheWriteSegment,
635
+ command: commandSegment,
614
636
  session_name: sessionNameSegment,
615
637
  usage: usageSegment,
616
638
  };
617
639
 
618
640
  export function renderSegment(id: StatusLineSegmentId, ctx: SegmentContext): RenderedSegment {
619
- const segment = SEGMENTS[id];
620
- if (!segment) {
621
- return { content: "", visible: false };
641
+ const segment = typeof id === "string" ? SEGMENTS[id] : undefined;
642
+ if (!segment || typeof segment.render !== "function") {
643
+ const label = truncateToWidth(sanitizeStatusText(String(id)), 20);
644
+ return { content: theme.fg("warning", `?unknown:${label || "segment"}`), visible: true };
645
+ }
646
+ try {
647
+ return segment.render(ctx);
648
+ } catch {
649
+ return { content: theme.fg("dim", "?"), visible: true };
622
650
  }
623
- return segment.render(ctx);
624
651
  }
625
652
 
626
653
  export const ALL_SEGMENT_IDS: StatusLineSegmentId[] = Object.keys(SEGMENTS) as StatusLineSegmentId[];
@@ -64,6 +64,11 @@ export interface SegmentContext {
64
64
  resetUnit?: "m" | "h";
65
65
  }>;
66
66
  } | null;
67
+ command?: {
68
+ output: string | null;
69
+ failed: boolean;
70
+ pending: boolean;
71
+ };
67
72
  }
68
73
 
69
74
  export interface RenderedSegment {