@gajae-code/coding-agent 0.9.5 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/types/cli/classify-install-target.d.ts +0 -10
  3. package/dist/types/cli/daemon-cli.d.ts +2 -0
  4. package/dist/types/cli/initial-message.d.ts +1 -1
  5. package/dist/types/cli/malloc-env-guard.d.ts +65 -0
  6. package/dist/types/cli/malloc-env-guard.test.d.ts +1 -0
  7. package/dist/types/cli/notify-cli.d.ts +3 -1
  8. package/dist/types/cli/session-picker.d.ts +4 -3
  9. package/dist/types/cli/update-cli.d.ts +22 -3
  10. package/dist/types/cli.d.ts +4 -0
  11. package/dist/types/commands/daemon.d.ts +6 -2
  12. package/dist/types/commands/launch.d.ts +1 -0
  13. package/dist/types/commands/notify.d.ts +6 -0
  14. package/dist/types/commit/analysis/conventional.d.ts +1 -1
  15. package/dist/types/commit/analysis/summary.d.ts +1 -1
  16. package/dist/types/commit/changelog/generate.d.ts +1 -1
  17. package/dist/types/commit/changelog/index.d.ts +2 -2
  18. package/dist/types/commit/map-reduce/map-phase.d.ts +1 -1
  19. package/dist/types/commit/map-reduce/reduce-phase.d.ts +1 -1
  20. package/dist/types/config/keybindings.d.ts +5 -0
  21. package/dist/types/config/model-profile-activation.d.ts +1 -0
  22. package/dist/types/config/settings-schema.d.ts +47 -7
  23. package/dist/types/coordinator-mcp/model-preset.d.ts +45 -0
  24. package/dist/types/coordinator-mcp/server.d.ts +67 -6
  25. package/dist/types/daemon/control-types.d.ts +10 -0
  26. package/dist/types/daemon/operator-contract.d.ts +47 -0
  27. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.d.ts +4 -0
  28. package/dist/types/discovery/helpers.d.ts +1 -1
  29. package/dist/types/discovery/substitute-plugin-root.d.ts +0 -4
  30. package/dist/types/gjc-runtime/launch-tmux.d.ts +26 -7
  31. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +34 -3
  32. package/dist/types/gjc-runtime/tmux-common.d.ts +6 -0
  33. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +5 -0
  34. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +309 -0
  35. package/dist/types/gjc-runtime/tmux-sessions.d.ts +49 -17
  36. package/dist/types/internal-urls/local-protocol.d.ts +13 -9
  37. package/dist/types/main.d.ts +66 -2
  38. package/dist/types/modes/acp/acp-agent.d.ts +19 -2
  39. package/dist/types/modes/acp/acp-mode.d.ts +12 -0
  40. package/dist/types/modes/components/assistant-message.d.ts +1 -1
  41. package/dist/types/modes/components/custom-editor.d.ts +2 -0
  42. package/dist/types/modes/components/gajae-pet-widget.d.ts +59 -0
  43. package/dist/types/modes/components/hook-selector.d.ts +5 -0
  44. package/dist/types/modes/components/irc-sidebar.d.ts +32 -0
  45. package/dist/types/modes/components/pet-selector.d.ts +11 -0
  46. package/dist/types/modes/components/session-selector.d.ts +22 -9
  47. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  48. package/dist/types/modes/components/tool-execution.d.ts +1 -0
  49. package/dist/types/modes/components/user-message.d.ts +2 -1
  50. package/dist/types/modes/controllers/event-controller.d.ts +4 -0
  51. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  52. package/dist/types/modes/interactive-mode.d.ts +24 -2
  53. package/dist/types/modes/irc-observation-ledger.d.ts +22 -0
  54. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +8 -0
  55. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +5 -0
  56. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +45 -0
  57. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +42 -2
  58. package/dist/types/modes/theme/defaults/index.d.ts +568 -568
  59. package/dist/types/modes/types.d.ts +28 -2
  60. package/dist/types/modes/utils/abort-message.d.ts +1 -1
  61. package/dist/types/modes/utils/irc-message.d.ts +38 -0
  62. package/dist/types/modes/utils/ui-helpers.d.ts +13 -4
  63. package/dist/types/notifications/config.d.ts +34 -0
  64. package/dist/types/notifications/daemon-paths.d.ts +7 -0
  65. package/dist/types/notifications/index.d.ts +27 -0
  66. package/dist/types/notifications/lifecycle-control-runtime.d.ts +12 -4
  67. package/dist/types/notifications/notification-service.d.ts +144 -0
  68. package/dist/types/notifications/rate-limit-pool.d.ts +27 -9
  69. package/dist/types/notifications/telegram-daemon-control.d.ts +6 -0
  70. package/dist/types/notifications/telegram-daemon.d.ts +130 -3
  71. package/dist/types/notifications/telegram-reference.d.ts +19 -2
  72. package/dist/types/notifications/topic-registry.d.ts +24 -4
  73. package/dist/types/registry/agent-registry.d.ts +2 -0
  74. package/dist/types/rlm/index.d.ts +1 -1
  75. package/dist/types/sdk.d.ts +2 -0
  76. package/dist/types/secrets/obfuscator.d.ts +1 -1
  77. package/dist/types/session/agent-session.d.ts +26 -2
  78. package/dist/types/session/cache-economics.d.ts +79 -0
  79. package/dist/types/session/provider-safety-stop.d.ts +5 -0
  80. package/dist/types/session/session-manager.d.ts +124 -4
  81. package/dist/types/session/session-storage.d.ts +155 -13
  82. package/dist/types/setup/credential-auto-import.d.ts +2 -2
  83. package/dist/types/task/executor.d.ts +3 -0
  84. package/dist/types/task/receipt.d.ts +3 -1
  85. package/dist/types/task/types.d.ts +8 -0
  86. package/dist/types/tools/ask-answer-registry.d.ts +5 -0
  87. package/dist/types/tools/ask.d.ts +25 -1
  88. package/dist/types/tools/bash.d.ts +1 -1
  89. package/dist/types/tools/browser/tab-supervisor.d.ts +6 -0
  90. package/dist/types/tools/index.d.ts +58 -6
  91. package/dist/types/tools/telegram-send.d.ts +7 -0
  92. package/dist/types/utils/external-editor.d.ts +2 -0
  93. package/package.json +9 -9
  94. package/scripts/compile-args.ts +8 -2
  95. package/scripts/g004-tmux-smoke.ts +196 -36
  96. package/src/cli/daemon-cli.ts +19 -29
  97. package/src/cli/malloc-env-guard.test.ts +104 -0
  98. package/src/cli/malloc-env-guard.ts +149 -0
  99. package/src/cli/notify-cli.ts +78 -14
  100. package/src/cli/session-picker.ts +23 -40
  101. package/src/cli/update-cli.ts +56 -37
  102. package/src/cli.ts +50 -10
  103. package/src/commands/daemon.ts +19 -5
  104. package/src/commands/harness.ts +515 -47
  105. package/src/commands/launch.ts +11 -3
  106. package/src/commands/notify.ts +5 -1
  107. package/src/commands/session.ts +6 -1
  108. package/src/config/keybindings.ts +5 -0
  109. package/src/config/model-profile-activation.ts +1 -1
  110. package/src/config/model-profiles.ts +23 -23
  111. package/src/config/settings-schema.ts +41 -1
  112. package/src/coordinator-mcp/model-preset.ts +100 -0
  113. package/src/coordinator-mcp/server.ts +2653 -425
  114. package/src/daemon/control-types.ts +11 -0
  115. package/src/daemon/operator-contract.ts +121 -0
  116. package/src/deep-interview/render-middleware.ts +67 -2
  117. package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +57 -17
  118. package/src/defaults/gjc/extensions/grok-cli-vendor/src/payload/sanitize.ts +15 -2
  119. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +5 -1
  120. package/src/gjc-runtime/launch-tmux.ts +702 -135
  121. package/src/gjc-runtime/session-state-sidecar.ts +756 -135
  122. package/src/gjc-runtime/team-runtime.ts +6 -0
  123. package/src/gjc-runtime/tmux-common.ts +26 -7
  124. package/src/gjc-runtime/tmux-gc.ts +52 -9
  125. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +185 -0
  126. package/src/gjc-runtime/tmux-owner-isolation.ts +2060 -0
  127. package/src/gjc-runtime/tmux-sessions.ts +871 -68
  128. package/src/internal-urls/docs-index.generated.ts +9 -8
  129. package/src/internal-urls/local-protocol.ts +29 -10
  130. package/src/main.ts +298 -75
  131. package/src/modes/acp/acp-agent.ts +728 -98
  132. package/src/modes/acp/acp-mode.ts +29 -2
  133. package/src/modes/components/assistant-message.ts +32 -3
  134. package/src/modes/components/bash-execution.ts +43 -13
  135. package/src/modes/components/custom-editor.ts +5 -0
  136. package/src/modes/components/gajae-pet-widget.ts +360 -0
  137. package/src/modes/components/hook-selector.ts +12 -0
  138. package/src/modes/components/irc-sidebar.ts +206 -0
  139. package/src/modes/components/pet-selector.ts +55 -0
  140. package/src/modes/components/session-selector.ts +222 -221
  141. package/src/modes/components/settings-selector.ts +10 -0
  142. package/src/modes/components/tool-execution.ts +47 -6
  143. package/src/modes/components/user-message.ts +26 -9
  144. package/src/modes/controllers/command-controller.ts +28 -2
  145. package/src/modes/controllers/event-controller.ts +159 -36
  146. package/src/modes/controllers/extension-ui-controller.ts +36 -17
  147. package/src/modes/controllers/input-controller.ts +8 -2
  148. package/src/modes/controllers/selector-controller.ts +62 -15
  149. package/src/modes/interactive-mode.ts +183 -7
  150. package/src/modes/irc-observation-ledger.ts +127 -0
  151. package/src/modes/shared/agent-wire/deep-interview-gate.ts +45 -2
  152. package/src/modes/shared/agent-wire/unattended-session.ts +288 -1
  153. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +130 -20
  154. package/src/modes/types.ts +34 -2
  155. package/src/modes/utils/hotkeys-markdown.ts +1 -0
  156. package/src/modes/utils/irc-message.ts +138 -0
  157. package/src/modes/utils/ui-helpers.ts +216 -50
  158. package/src/notifications/config.ts +44 -0
  159. package/src/notifications/daemon-paths.ts +8 -0
  160. package/src/notifications/index.ts +535 -75
  161. package/src/notifications/lifecycle-control-runtime.ts +930 -77
  162. package/src/notifications/notification-service.ts +710 -0
  163. package/src/notifications/rate-limit-pool.ts +46 -12
  164. package/src/notifications/telegram-daemon-cli.ts +2 -0
  165. package/src/notifications/telegram-daemon-control.ts +27 -2
  166. package/src/notifications/telegram-daemon.ts +635 -94
  167. package/src/notifications/telegram-reference.ts +73 -13
  168. package/src/notifications/topic-registry.ts +86 -9
  169. package/src/prompts/system/irc-peer-roster.md +1 -0
  170. package/src/prompts/system/subagent-system-prompt.md +1 -0
  171. package/src/prompts/system/system-prompt.md +1 -0
  172. package/src/prompts/tools/irc.md +1 -1
  173. package/src/registry/agent-registry.ts +3 -0
  174. package/src/sdk.ts +52 -1
  175. package/src/secrets/obfuscator.ts +4 -2
  176. package/src/session/agent-session.ts +396 -145
  177. package/src/session/cache-economics.ts +275 -0
  178. package/src/session/provider-safety-stop.ts +9 -0
  179. package/src/session/session-dump-format.ts +6 -0
  180. package/src/session/session-manager.ts +809 -39
  181. package/src/session/session-storage.ts +582 -38
  182. package/src/slash-commands/builtin-registry.ts +143 -9
  183. package/src/task/executor.ts +12 -3
  184. package/src/task/index.ts +8 -0
  185. package/src/task/receipt.ts +7 -2
  186. package/src/task/types.ts +26 -0
  187. package/src/tools/ask-answer-registry.ts +25 -0
  188. package/src/tools/ask.ts +355 -33
  189. package/src/tools/browser/tab-supervisor.ts +63 -6
  190. package/src/tools/browser.ts +8 -3
  191. package/src/tools/index.ts +81 -6
  192. package/src/tools/sqlite-reader.ts +8 -4
  193. package/src/tui/output-block.ts +18 -6
  194. package/src/utils/external-editor.ts +6 -1
@@ -187,7 +187,7 @@ export class BrowserTool implements AgentTool<typeof browserSchema, BrowserToolD
187
187
  case "open":
188
188
  return await this.#open(name, params, details, timeoutMs, signal);
189
189
  case "close":
190
- return await this.#close(name, params, details, signal);
190
+ return await this.#close(name, params, details, timeoutMs, signal);
191
191
  case "run":
192
192
  return await this.#run(name, params, details, timeoutMs, signal);
193
193
  case "act":
@@ -274,15 +274,20 @@ export class BrowserTool implements AgentTool<typeof browserSchema, BrowserToolD
274
274
  name: string,
275
275
  params: BrowserParams,
276
276
  details: BrowserToolDetails,
277
+ timeoutMs: number,
277
278
  signal?: AbortSignal,
278
279
  ): Promise<AgentToolResult<BrowserToolDetails>> {
279
280
  const kill = !!params.kill;
281
+ // One end-to-end budget across the whole close/close-all teardown chain (#2027):
282
+ // releaseAllTabs → waitForClosed → worker.terminate → releaseBrowser stay bounded so
283
+ // a CDP target dying mid-teardown cannot hang the tool call or the agent turn.
284
+ const deadlineAt = Date.now() + timeoutMs;
280
285
  if (params.all) {
281
- const count = await untilAborted(signal, () => releaseAllTabs({ kill }));
286
+ const count = await untilAborted(signal, () => releaseAllTabs({ kill, deadlineAt }));
282
287
  details.result = `Closed ${count} tab(s)`;
283
288
  return toolResult(details).text(details.result).done();
284
289
  }
285
- const closed = await untilAborted(signal, () => releaseTab(name, { kill }));
290
+ const closed = await untilAborted(signal, () => releaseTab(name, { kill, deadlineAt }));
286
291
  details.result = closed ? `Closed tab ${JSON.stringify(name)}` : `No tab named ${JSON.stringify(name)}`;
287
292
  return toolResult(details).text(details.result).done();
288
293
  }
@@ -122,16 +122,91 @@ export type {
122
122
  DiscoverableToolSource,
123
123
  } from "../tool-discovery/tool-index";
124
124
 
125
+ /** A typed remote action available to an ask answer source. */
126
+ export type AskRemoteControlId = "navigation_forward";
127
+
128
+ export interface AskRemoteControl {
129
+ id: AskRemoteControlId;
130
+ kind: "navigation";
131
+ label: "Next" | "Done";
132
+ enabled: boolean;
133
+ }
134
+
135
+ export interface AskAnswerRequest {
136
+ question: string;
137
+ options: string[];
138
+ interaction: "selector" | "custom_editor" | "clarification_editor";
139
+ controls: readonly AskRemoteControl[];
140
+ }
141
+
142
+ export type AskRemoteInteraction =
143
+ | { kind: "value"; value: string }
144
+ | { kind: "control"; controlId: AskRemoteControlId };
145
+
146
+ export type AskSettlement =
147
+ | { kind: "commit" }
148
+ | {
149
+ kind: "resolve_without_commit";
150
+ reason:
151
+ | "toggle"
152
+ | "other_transition"
153
+ | "clarification_transition"
154
+ | "clarification_submitted"
155
+ | "empty_navigation"
156
+ | "back_navigation"
157
+ | "cancelled"
158
+ | "aborted"
159
+ | "timed_out"
160
+ | "exception"
161
+ | "shutdown";
162
+ }
163
+ | {
164
+ kind: "invalid";
165
+ reason:
166
+ | "invalid_option"
167
+ | "invalid_control"
168
+ | "invalid_structured_answer"
169
+ | "empty_custom"
170
+ | "empty_clarification";
171
+ };
172
+
173
+ export type AskSelectedAckOutcome =
174
+ | { status: "delivered"; messageId: number }
175
+ | {
176
+ status: "failed";
177
+ reason:
178
+ | "unsupported"
179
+ | "no_participant"
180
+ | "ambiguous_participant"
181
+ | "route_missing"
182
+ | "expired"
183
+ | "cancelled"
184
+ | "telegram_rejected"
185
+ | "session_closed";
186
+ }
187
+ | { status: "unknown"; reason: "transport_ambiguous" | "origin_disconnected" | "host_timeout" | "shutdown" };
188
+
189
+ export type AskSettlementResult =
190
+ | { kind: "committed"; ack: AskSelectedAckOutcome }
191
+ | { kind: "resolved_without_commit" }
192
+ | { kind: "invalid_closed" };
193
+
194
+ export interface AskRemoteReceipt {
195
+ source: "remote";
196
+ interaction: AskRemoteInteraction;
197
+ settle(value: AskSettlement): Promise<AskSettlementResult>;
198
+ }
199
+
200
+ export type AskAnswerSourceResult = AskRemoteReceipt | string | undefined;
201
+
125
202
  /**
126
- * Source of remote answers for interactive asks (e.g. a Telegram reply routed
127
- * through the notifications SDK). Lets a pending ask resolve without RPC mode.
203
+ * Source of remote answers. `awaitAnswer` remains the legacy wire for existing
204
+ * integrations; typed sources opt into `awaitAnswerRequest`. This keeps an old
205
+ * string-only source from accidentally acquiring acknowledgement authority.
128
206
  */
129
207
  export interface AskAnswerSource {
130
- /**
131
- * Race a remote answer against the local UI for one question. Resolves with the
132
- * chosen option label or free-text answer, or `undefined` to defer to local UI.
133
- */
134
208
  awaitAnswer(question: string, options: string[], signal?: AbortSignal): Promise<string | undefined>;
209
+ awaitAnswerRequest?(request: AskAnswerRequest, signal?: AbortSignal): Promise<AskAnswerSourceResult>;
135
210
  }
136
211
 
137
212
  /** Session context for tool factories */
@@ -150,13 +150,16 @@ function buildAsciiTable(columns: string[], rows: SqliteRow[]): string {
150
150
  return lines.map(line => truncateToWidth(replaceTabs(line), MAX_RENDER_WIDTH)).join("\n");
151
151
  }
152
152
 
153
+ const DECIMAL_INTEGER_PATTERN = /^[+-]?\d+$/;
154
+
153
155
  function parseLimit(value: string | null, fallback: number): number {
154
156
  if (value === null || value.trim().length === 0) {
155
157
  return fallback;
156
158
  }
157
159
 
158
- const parsed = Number.parseInt(value, 10);
159
- if (!Number.isFinite(parsed) || parsed < 1) {
160
+ const normalizedValue = value.trim();
161
+ const parsed = Number(normalizedValue);
162
+ if (!DECIMAL_INTEGER_PATTERN.test(normalizedValue) || !Number.isFinite(parsed) || parsed < 1) {
160
163
  throw new ToolError(`SQLite limit must be a positive integer; got '${value}'`);
161
164
  }
162
165
  return Math.min(parsed, MAX_QUERY_LIMIT);
@@ -167,8 +170,9 @@ function parseOffset(value: string | null): number {
167
170
  return 0;
168
171
  }
169
172
 
170
- const parsed = Number.parseInt(value, 10);
171
- if (!Number.isFinite(parsed) || parsed < 0) {
173
+ const normalizedValue = value.trim();
174
+ const parsed = Number(normalizedValue);
175
+ if (!DECIMAL_INTEGER_PATTERN.test(normalizedValue) || !Number.isFinite(parsed) || parsed < 0) {
172
176
  throw new ToolError(`SQLite offset must be a non-negative integer; got '${value}'`);
173
177
  }
174
178
  return parsed;
@@ -1,9 +1,16 @@
1
1
  /**
2
2
  * Bordered output container with optional header and sections.
3
3
  */
4
- import { ImageProtocol, padding, TERMINAL, visibleWidth, wrapTextWithAnsi } from "@gajae-code/tui";
4
+ import {
5
+ ImageProtocol,
6
+ isTerminalGraphicsFallbackActive,
7
+ padding,
8
+ TERMINAL,
9
+ visibleWidth,
10
+ wrapTextWithAnsi,
11
+ } from "@gajae-code/tui";
5
12
  import type { Theme } from "../modes/theme/theme";
6
- import { getSixelLineMask } from "../utils/sixel";
13
+ import { containsSixelSequence, getSixelLineMask } from "../utils/sixel";
7
14
  import type { State } from "./types";
8
15
  import type { RenderCache } from "./utils";
9
16
  import { getStateBgColor, Hasher, padToWidth, truncateToWidth } from "./utils";
@@ -81,13 +88,17 @@ export function renderOutputBlock(options: OutputBlockOptions, theme: Theme): st
81
88
  );
82
89
  }
83
90
  const allLines = section.lines.flatMap(l => l.split("\n"));
84
- const sixelLineMask = TERMINAL.imageProtocol === ImageProtocol.Sixel ? getSixelLineMask(allLines) : undefined;
91
+ const fallbackActive = isTerminalGraphicsFallbackActive();
92
+ const sixelLineMask =
93
+ fallbackActive || TERMINAL.imageProtocol === ImageProtocol.Sixel ? getSixelLineMask(allLines) : undefined;
85
94
  for (let lineIndex = 0; lineIndex < allLines.length; lineIndex++) {
86
- const line = allLines[lineIndex]!;
87
- if (sixelLineMask?.[lineIndex]) {
88
- lines.push(line);
95
+ const sixelLine = sixelLineMask?.[lineIndex] ?? false;
96
+ if (sixelLine && !fallbackActive) {
97
+ lines.push(allLines[lineIndex]!);
89
98
  continue;
90
99
  }
100
+ if (sixelLine && sixelLineMask?.[lineIndex - 1] && !containsSixelSequence(allLines[lineIndex]!)) continue;
101
+ const line = sixelLine ? "[SIXEL image hidden while IRC sidebar is visible]" : allLines[lineIndex]!;
91
102
  const wrappedLines = wrapTextWithAnsi(line.trimEnd(), contentWidth);
92
103
  for (const wrappedLine of wrappedLines) {
93
104
  const innerPadding = padding(Math.max(0, contentWidth - visibleWidth(wrappedLine)));
@@ -137,6 +148,7 @@ export class CachedOutputBlock {
137
148
  h.optional(options.headerMeta);
138
149
  h.optional(options.state);
139
150
  h.bool(options.applyBg ?? true);
151
+ h.bool(isTerminalGraphicsFallbackActive());
140
152
  if (options.sections) {
141
153
  for (const s of options.sections) {
142
154
  h.optional(s.label);
@@ -21,6 +21,11 @@ export interface OpenInEditorOptions {
21
21
  trimTrailingNewline?: boolean;
22
22
  }
23
23
 
24
+ /** Remove one platform-standard trailing line terminator from editor content. */
25
+ export function trimEditorTrailingNewline(text: string): string {
26
+ return text.replace(/\r?\n$/, "");
27
+ }
28
+
24
29
  /**
25
30
  * Opens `content` in the user's external editor and returns the edited text.
26
31
  * Returns `null` if the editor exits with a non-zero code.
@@ -52,7 +57,7 @@ export async function openInEditor(
52
57
  if (options?.trimTrailingNewline === false) {
53
58
  return text;
54
59
  }
55
- return text.replace(/\n$/, "");
60
+ return trimEditorTrailingNewline(text);
56
61
  }
57
62
  return null;
58
63
  } finally {