@gajae-code/coding-agent 0.16.1 → 0.16.4

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 (146) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/dist/types/cli/args.d.ts +2 -2
  3. package/dist/types/cli/root-flags.d.ts +4 -2
  4. package/dist/types/cli.d.ts +1 -1
  5. package/dist/types/commands/launch.d.ts +1 -1
  6. package/dist/types/config/autorouting-tier-map.d.ts +3 -0
  7. package/dist/types/config/model-registry.d.ts +4 -0
  8. package/dist/types/config/model-resolver.d.ts +9 -0
  9. package/dist/types/config/settings-schema.d.ts +29 -1
  10. package/dist/types/discovery/claude-plugins.d.ts +3 -1
  11. package/dist/types/discovery/helpers.d.ts +2 -0
  12. package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +16 -0
  13. package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -0
  14. package/dist/types/extensibility/runtime-skill-discovery.d.ts +1 -1
  15. package/dist/types/extensibility/shared-events.d.ts +1 -1
  16. package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
  17. package/dist/types/modes/components/assistant-message.d.ts +1 -2
  18. package/dist/types/modes/components/settings-selector.d.ts +6 -1
  19. package/dist/types/modes/components/status-line/command.d.ts +35 -0
  20. package/dist/types/modes/components/status-line/index.d.ts +1 -0
  21. package/dist/types/modes/components/status-line/types.d.ts +5 -0
  22. package/dist/types/modes/components/tool-status-header.d.ts +14 -0
  23. package/dist/types/modes/controllers/event-controller.d.ts +6 -0
  24. package/dist/types/modes/interactive-mode.d.ts +1 -0
  25. package/dist/types/modes/types.d.ts +1 -0
  26. package/dist/types/runtime-mcp/client.d.ts +9 -1
  27. package/dist/types/runtime-mcp/manager.d.ts +7 -1
  28. package/dist/types/runtime-mcp/pool.d.ts +22 -3
  29. package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
  30. package/dist/types/runtime-mcp/types.d.ts +22 -0
  31. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +12 -0
  32. package/dist/types/sdk/bus/slack-live-provider.d.ts +6 -0
  33. package/dist/types/sdk/bus/slack-provider.d.ts +12 -0
  34. package/dist/types/sdk/cli/rows.d.ts +7 -0
  35. package/dist/types/sdk/host/events.d.ts +1 -0
  36. package/dist/types/sdk/host/host.d.ts +2 -0
  37. package/dist/types/sdk/host/session-runtime.d.ts +23 -0
  38. package/dist/types/sdk/session-api-key.d.ts +26 -0
  39. package/dist/types/sdk/transport/serve-cli.d.ts +1 -1
  40. package/dist/types/session/agent-session.d.ts +9 -0
  41. package/dist/types/setup/paseo/announce.d.ts +111 -0
  42. package/dist/types/setup/paseo/setup-deps.d.ts +2 -1
  43. package/dist/types/system-prompt.d.ts +2 -0
  44. package/dist/types/task/executor.d.ts +2 -1
  45. package/dist/types/tools/fetch.d.ts +7 -0
  46. package/dist/types/tools/index.d.ts +8 -2
  47. package/dist/types/tools/path-utils.d.ts +2 -0
  48. package/dist/types/tools/search.d.ts +6 -0
  49. package/dist/types/utils/external-editor.d.ts +5 -0
  50. package/package.json +7 -7
  51. package/scripts/capture-status-line-custom-editor-showcase.ts +151 -0
  52. package/scripts/generate-sdk-operation-inventory.ts +9 -0
  53. package/scripts/verify-status-line-custom-editor-showcase.ts +309 -0
  54. package/src/cli/args.ts +20 -9
  55. package/src/cli/root-flags.ts +5 -3
  56. package/src/config/autorouting-tier-map.ts +1 -0
  57. package/src/config/file-lock.ts +181 -17
  58. package/src/config/model-preset-registry.ts +5 -3
  59. package/src/config/model-profiles.ts +40 -0
  60. package/src/config/model-registry.ts +57 -11
  61. package/src/config/model-resolver.ts +48 -0
  62. package/src/config/settings-schema.ts +33 -1
  63. package/src/config/settings.ts +1 -0
  64. package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +11 -11
  65. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +13 -2
  66. package/src/discovery/builtin.ts +13 -4
  67. package/src/discovery/claude-plugins.ts +12 -4
  68. package/src/discovery/helpers.ts +10 -2
  69. package/src/extensibility/gjc-plugins/compiler.ts +208 -58
  70. package/src/extensibility/gjc-plugins/installer.ts +13 -12
  71. package/src/extensibility/gjc-plugins/mcp-policy.ts +81 -52
  72. package/src/extensibility/gjc-plugins/paths.ts +13 -0
  73. package/src/extensibility/gjc-plugins/runtime-adapters.ts +758 -16
  74. package/src/extensibility/runtime-skill-discovery.ts +77 -151
  75. package/src/extensibility/shared-events.ts +1 -1
  76. package/src/extensibility/skills.ts +44 -16
  77. package/src/gjc-runtime/repository-binding.ts +1 -1
  78. package/src/gjc-runtime/session-state-lock.ts +94 -6
  79. package/src/internal-urls/docs-index.generated.ts +10 -10
  80. package/src/main.ts +72 -34
  81. package/src/modes/DESIGN.md +54 -0
  82. package/src/modes/acp/acp-agent.ts +29 -14
  83. package/src/modes/components/assistant-message.ts +22 -9
  84. package/src/modes/components/model-selector.ts +166 -33
  85. package/src/modes/components/settings-selector.ts +1075 -235
  86. package/src/modes/components/status-line/command.ts +190 -0
  87. package/src/modes/components/status-line/index.ts +1 -0
  88. package/src/modes/components/status-line/segments.ts +32 -5
  89. package/src/modes/components/status-line/types.ts +5 -0
  90. package/src/modes/components/tool-status-header.ts +393 -21
  91. package/src/modes/controllers/command-controller.ts +2 -0
  92. package/src/modes/controllers/event-controller.ts +148 -5
  93. package/src/modes/controllers/selector-controller.ts +21 -0
  94. package/src/modes/interactive-mode.ts +47 -1
  95. package/src/modes/types.ts +1 -0
  96. package/src/modes/utils/ui-helpers.ts +1 -0
  97. package/src/prompts/system/system-prompt.md +8 -0
  98. package/src/prompts/tools/bash.md +1 -1
  99. package/src/prompts/tools/job.md +1 -1
  100. package/src/prompts/tools/search.md +2 -0
  101. package/src/runtime-mcp/client.ts +60 -17
  102. package/src/runtime-mcp/manager.ts +171 -14
  103. package/src/runtime-mcp/pool.test.ts +209 -0
  104. package/src/runtime-mcp/pool.ts +224 -23
  105. package/src/runtime-mcp/transports/stdio.ts +158 -24
  106. package/src/runtime-mcp/types.ts +24 -0
  107. package/src/sdk/acp/adapter.ts +1 -1
  108. package/src/sdk/broker/broker.ts +5 -4
  109. package/src/sdk/bus/chat-daemon-control.ts +1 -1
  110. package/src/sdk/bus/chat-daemon-runtime.ts +44 -1
  111. package/src/sdk/bus/slack-daemon.ts +92 -2
  112. package/src/sdk/bus/slack-live-provider.ts +12 -0
  113. package/src/sdk/bus/slack-provider.ts +5 -0
  114. package/src/sdk/cli/rows.ts +47 -2
  115. package/src/sdk/cli/session-cli.ts +47 -23
  116. package/src/sdk/host/events.ts +25 -2
  117. package/src/sdk/host/host.ts +4 -1
  118. package/src/sdk/host/session-runtime.test.ts +36 -25
  119. package/src/sdk/host/session-runtime.ts +279 -43
  120. package/src/sdk/protocol/operation-inventory.generated.json +66 -0
  121. package/src/sdk/router/session-router.ts +60 -37
  122. package/src/sdk/session-api-key.ts +94 -0
  123. package/src/sdk/session.ts +73 -30
  124. package/src/sdk/transport/serve-cli.ts +3 -3
  125. package/src/session/agent-session.ts +123 -38
  126. package/src/session/contribution-prep.ts +214 -21
  127. package/src/setup/paseo/announce.ts +450 -0
  128. package/src/setup/paseo/setup-deps.ts +15 -3
  129. package/src/slash-commands/builtin-registry.ts +1 -0
  130. package/src/system-prompt.ts +4 -0
  131. package/src/task/executor.ts +2 -1
  132. package/src/task/index.ts +17 -4
  133. package/src/tools/bash.ts +50 -21
  134. package/src/tools/cron.ts +1 -1
  135. package/src/tools/fetch.ts +29 -1
  136. package/src/tools/index.ts +8 -2
  137. package/src/tools/job.ts +8 -2
  138. package/src/tools/monitor.ts +8 -2
  139. package/src/tools/path-utils.ts +7 -0
  140. package/src/tools/search.ts +116 -58
  141. package/src/tools/skill.ts +22 -2
  142. package/src/tools/subagent.ts +3 -1
  143. package/src/tools/tool-catalog.generated.ts +9 -2
  144. package/src/utils/external-editor.ts +16 -2
  145. package/src/web/insane/bridge.ts +113 -23
  146. 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 {