@gajae-code/coding-agent 0.17.4 → 0.17.5

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 (84) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/dist/types/config/autorouting-tier-map.d.ts +1031 -3
  3. package/dist/types/config/file-lock.d.ts +4 -2
  4. package/dist/types/config/model-registry.d.ts +3 -1
  5. package/dist/types/config/model-resolver.d.ts +1 -1
  6. package/dist/types/exec/bash-executor.d.ts +2 -0
  7. package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +11 -2
  8. package/dist/types/gjc-runtime/state-writer.d.ts +14 -1
  9. package/dist/types/harness-control-plane/control-endpoint.d.ts +4 -1
  10. package/dist/types/harness-control-plane/finalize.d.ts +14 -3
  11. package/dist/types/main.d.ts +1 -1
  12. package/dist/types/runtime-mcp/loader.d.ts +2 -0
  13. package/dist/types/runtime-mcp/manager.d.ts +13 -6
  14. package/dist/types/sdk/broker/broker.d.ts +4 -2
  15. package/dist/types/sdk/broker/ensure.d.ts +3 -0
  16. package/dist/types/sdk/broker/identity.d.ts +2 -0
  17. package/dist/types/sdk/broker/managed-task-dag.d.ts +1335 -0
  18. package/dist/types/sdk/broker/managed-task-verification.d.ts +37 -0
  19. package/dist/types/sdk/broker/spawn-authority.d.ts +8 -0
  20. package/dist/types/sdk/broker/startup-failure.d.ts +4 -0
  21. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +5 -1
  22. package/dist/types/sdk/prompt-deadline-flush.d.ts +2 -0
  23. package/dist/types/sdk/session.d.ts +3 -3
  24. package/dist/types/session/agent-session.d.ts +7 -2
  25. package/dist/types/task/types.d.ts +2 -0
  26. package/dist/types/tools/bash-interactive.d.ts +1 -0
  27. package/dist/types/tools/fetch.d.ts +10 -1
  28. package/dist/types/tools/subagent.d.ts +8 -1
  29. package/package.json +7 -7
  30. package/src/cli/public-command-registry.ts +8 -2
  31. package/src/cli/setup-cli.ts +1 -0
  32. package/src/cli/stats-cli.ts +11 -1
  33. package/src/config/autorouting-tier-map.ts +529 -3
  34. package/src/config/file-lock.ts +59 -14
  35. package/src/config/model-discovery-manager.ts +4 -4
  36. package/src/config/model-profile-activation.ts +83 -23
  37. package/src/config/model-registry.ts +72 -12
  38. package/src/config/model-resolver.ts +6 -1
  39. package/src/coordinator-mcp/question-state.ts +4 -1
  40. package/src/coordinator-mcp/server.ts +14 -6
  41. package/src/exec/bash-executor.ts +3 -0
  42. package/src/extensibility/gjc-plugins/runtime-adapters.ts +46 -8
  43. package/src/gjc-runtime/state-writer.ts +317 -6
  44. package/src/harness-control-plane/control-endpoint.ts +24 -6
  45. package/src/harness-control-plane/finalize.ts +312 -25
  46. package/src/harness-control-plane/owner.ts +323 -89
  47. package/src/internal-urls/docs-index.generated.ts +6 -4
  48. package/src/main.ts +69 -19
  49. package/src/modes/acp/acp-agent.ts +581 -37
  50. package/src/modes/components/gjc-bundle-settings.ts +21 -1
  51. package/src/modes/components/tool-status-header.ts +72 -6
  52. package/src/modes/controllers/runtime-mcp-command-controller.ts +1 -1
  53. package/src/runtime-mcp/loader.ts +6 -3
  54. package/src/runtime-mcp/manager.ts +177 -75
  55. package/src/sdk/broker/broker.ts +1057 -150
  56. package/src/sdk/broker/ensure.ts +21 -3
  57. package/src/sdk/broker/identity.ts +13 -0
  58. package/src/sdk/broker/managed-task-dag.ts +1927 -0
  59. package/src/sdk/broker/managed-task-verification.ts +642 -0
  60. package/src/sdk/broker/spawn-authority.ts +140 -7
  61. package/src/sdk/broker/startup-failure.ts +80 -1
  62. package/src/sdk/broker/transport.ts +1 -0
  63. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  64. package/src/sdk/bus/index.ts +22 -6
  65. package/src/sdk/bus/telegram-daemon-contract.ts +5 -1
  66. package/src/sdk/cli/session-cli.ts +18 -0
  67. package/src/sdk/host/session-runtime.test.ts +46 -0
  68. package/src/sdk/host/session-runtime.ts +13 -6
  69. package/src/sdk/lifecycle/service.ts +2 -0
  70. package/src/sdk/prompt-deadline-flush.ts +26 -4
  71. package/src/sdk/session.ts +587 -115
  72. package/src/session/agent-session.ts +40 -12
  73. package/src/session/internal/managed-session-scope.ts +10 -0
  74. package/src/session/internal/managed-session-storage.ts +30 -1
  75. package/src/setup/provider-presets.json +2 -1
  76. package/src/slash-commands/builtin-registry.ts +1 -1
  77. package/src/task/executor.ts +46 -17
  78. package/src/task/types.ts +2 -0
  79. package/src/tools/bash-interactive.ts +2 -0
  80. package/src/tools/bash.ts +20 -0
  81. package/src/tools/fetch.ts +21 -5
  82. package/src/tools/subagent-render.ts +24 -1
  83. package/src/tools/subagent.ts +27 -1
  84. package/src/utils/mupdf.ts +11 -4
@@ -0,0 +1,37 @@
1
+ import { type FinalizeChecks } from "../../harness-control-plane/finalize";
2
+ import { type ManagedDomainBinding } from "./managed-task-dag";
3
+ export type ManagedVerificationStatus = {
4
+ status: "running";
5
+ executionId: string;
6
+ started: false;
7
+ } | {
8
+ status: "unknown";
9
+ executionId: string;
10
+ started: boolean;
11
+ reason?: string;
12
+ } | {
13
+ status: "finished";
14
+ executionId: string;
15
+ started: false;
16
+ accepted: boolean;
17
+ } | {
18
+ status: "accepted";
19
+ executionId: string;
20
+ started: boolean;
21
+ acceptedId: string;
22
+ acceptedHash: string;
23
+ } | {
24
+ status: "failed";
25
+ executionId: string;
26
+ started: boolean;
27
+ reason: string;
28
+ };
29
+ export declare function markManagedVerificationUnknown(binding: ManagedDomainBinding, graphId: string, attemptId: string): Promise<void>;
30
+ export declare function reconcileRunningManagedVerification(binding: ManagedDomainBinding): Promise<void>;
31
+ export declare function verifyManagedTaskAttempt(input: {
32
+ binding: ManagedDomainBinding;
33
+ graphId: string;
34
+ nodeId: string;
35
+ owner: string;
36
+ runner?: FinalizeChecks;
37
+ }): Promise<ManagedVerificationStatus>;
@@ -161,6 +161,8 @@ export type SpawnClaimDecision = {
161
161
  } | {
162
162
  kind: "idempotency_conflict";
163
163
  claim: SpawnClaimV2;
164
+ } | {
165
+ kind: "managed_key_conflict";
164
166
  };
165
167
  type SpawnAuthorityDurableWrite = {
166
168
  claim: SpawnClaimV2;
@@ -190,6 +192,12 @@ export declare class SpawnAuthorityStore {
190
192
  claim(lifecycleIdentity: string): SpawnClaimV2 | undefined;
191
193
  authority(lifecycleIdentity: string): SpawnAuthorityV1 | undefined;
192
194
  open(): Promise<void>;
195
+ /**
196
+ * Durably reserves an ordinary session.spawn idempotency identity for one
197
+ * managed native identity. Multiple managed roots may share the alias, but an
198
+ * ordinary claim and a managed reservation can never both win.
199
+ */
200
+ reserveManagedKeyAliases(aliasIdentities: readonly string[], managedIdentity: string, controlRoot: string): Promise<boolean>;
193
201
  claimOrJoin(lifecycleIdentity: string, bindingMac: string | undefined, requestBindingMac?: string | undefined): Promise<SpawnClaimDecision>;
194
202
  /**
195
203
  * Fsyncs one allowlisted state edge. Callers cannot patch claims in place,
@@ -1,6 +1,8 @@
1
1
  export interface BrokerStartupFailureMarker {
2
2
  version: 2;
3
3
  reason: string;
4
+ /** Validated manual lock cleanup command, stored separately when it cannot fit in `reason`. */
5
+ cleanupCommand?: string;
4
6
  exitCode: number | null;
5
7
  signal: string | null;
6
8
  writtenAt: number;
@@ -17,6 +19,8 @@ export interface BrokerStartupFailureMarker {
17
19
  incarnation: string;
18
20
  }
19
21
  export declare function brokerStartupFailurePath(agentDir: string): string;
22
+ /** Whether validated compact cleanup guidance targets the exact lock path. */
23
+ export declare function brokerStartupFailureCleanupTargetsLock(marker: BrokerStartupFailureMarker | undefined, lockPath: string): boolean;
20
24
  /**
21
25
  * Best-effort durable marker write; never throws (diagnostics must not mask the
22
26
  * exit itself). `pid` must be the writing broker process's own pid
@@ -287,8 +287,12 @@ export declare const SDK_LIFECYCLE_ROUTER_PROTOCOL_VERSION = 1;
287
287
  * replaced across this upgrade.
288
288
  * Generation 190 acknowledges the protected prompt-deadline boundary change,
289
289
  * so generation-189 owners are replaced instead of retaining the old path.
290
+ * Generation 192 makes session-host liveness a reference-counted work lease,
291
+ * so generation-191 owners cannot reap hosts with queued or promoted work.
292
+ * Generation 193 gates streamed content on negotiated observer capabilities,
293
+ * so existing owners are replaced before exposing the new observer path.
290
294
  */
291
- export declare const DAEMON_GENERATION = 192;
295
+ export declare const DAEMON_GENERATION = 194;
292
296
  /**
293
297
  * Serving-compatibility boundary for daemon lifecycle requests. Epoch 7
294
298
  * requires durable publication receipts and acknowledged attachment dispatch,
@@ -55,6 +55,8 @@ export interface PromptDeadlineFlushResult {
55
55
  worktreeRoot: string;
56
56
  }
57
57
  export interface PromptDeadlineFlushOptions {
58
+ /** Active session's agent directory, used to keep volatile broker state out of the WIP commit. */
59
+ readonly agentDir?: string;
58
60
  /**
59
61
  * Whether the caller resolved `sdk.flushWorktreeOnDeadline` to `true` from a
60
62
  * value the user actually wrote, rather than from the schema default. Only an
@@ -233,9 +233,9 @@ export interface CreateAgentSessionOptions {
233
233
  inheritedAsyncJobManager?: AsyncJobManager;
234
234
  /**
235
235
  * W6b: the parent's scope-held MCP facade, handed to a canonical sub-session so
236
- * it can inherit always-on MCP tools without owning the manager. Replaces the
237
- * removed `MCPManager.instance()` inheritance path; the sub-session never
238
- * connects, registers callbacks, or disposes this manager.
236
+ * it can inherit MCP tools without owning the manager. Replaces the removed
237
+ * `MCPManager.instance()` inheritance path; the sub-session subscribes to catalog
238
+ * changes but never connects or disposes this manager.
239
239
  */
240
240
  inheritedMcpManager?: import("../runtime-mcp/manager").MCPManager;
241
241
  /** Session manager. Default: session stored under the configured agentDir sessions root */
@@ -792,8 +792,11 @@ export declare class AgentSession {
792
792
  } | undefined;
793
793
  /** Replace the session-owned MCP manager after a cwd rescope. */
794
794
  replaceOwnedMcpManager(next: MCPManager | undefined): Promise<void>;
795
- /** Swap named custom/project tools after a cwd rescope. */
796
- replaceNamedCustomTools(previousNames: readonly string[], nextTools: CustomTool[]): Promise<void>;
795
+ /** Swap named custom tools and their optional mandatory MCP selection. */
796
+ replaceNamedCustomTools(previousNames: readonly string[], nextTools: readonly CustomTool[], options?: {
797
+ mandatoryMCPToolNames?: readonly string[];
798
+ activateNewTools?: boolean;
799
+ }): Promise<void>;
797
800
  /** Best-effort accessor for the active skill's `current_phase` field from
798
801
  * its persisted mode-state file. Used by the `skill` tool to enforce the
799
802
  * terminal-phase chain guard. Returns undefined when no active skill is
@@ -1080,6 +1083,7 @@ export declare class AgentSession {
1080
1083
  refreshMCPTools(mcpTools: CustomTool[], options?: {
1081
1084
  selectedMCPToolNames?: string[];
1082
1085
  activeMCPToolNames?: string[];
1086
+ mandatoryMCPToolNames?: string[];
1083
1087
  persistMCPSelection?: boolean;
1084
1088
  }): Promise<void>;
1085
1089
  /**
@@ -1583,6 +1587,7 @@ export declare class AgentSession {
1583
1587
  reason?: TemporaryModelReason;
1584
1588
  providerSessionScope?: TemporaryProviderSessionScope;
1585
1589
  signal?: AbortSignal;
1590
+ onMutationStarted?: () => void;
1586
1591
  }): Promise<TemporaryProviderSessionScope | void>;
1587
1592
  /** Restore the exact live-model state captured before a failed selector transaction. */
1588
1593
  restoreModelSelectionForRollback(model: Model | undefined, thinkingLevel: ThinkingLevel | undefined): Promise<void>;
@@ -514,6 +514,8 @@ export interface AgentProgress {
514
514
  }>;
515
515
  recentOutput: string[];
516
516
  toolCount: number;
517
+ /** Epoch ms of the latest event observed from this subagent (any agent event). */
518
+ lastActivityMs?: number;
517
519
  /** Cumulative input + output + cacheWrite tokens across all turns. Excludes cacheRead (re-reads cached context every turn, making cumulative sum misleading). */
518
520
  tokens: number;
519
521
  /**
@@ -30,6 +30,7 @@ export declare function runInteractiveBashPty(ui: NonNullable<AgentToolContext["
30
30
  timeoutMs: number;
31
31
  signal?: AbortSignal;
32
32
  env?: Record<string, string>;
33
+ unsetEnv?: string[];
33
34
  artifactPath?: string;
34
35
  artifactId?: string;
35
36
  artifactPublisher?: TerminalArtifactPublisher;
@@ -4,8 +4,9 @@ import type { Settings } from "../config/settings";
4
4
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
5
5
  import { type Theme } from "../modes/theme/theme";
6
6
  import type { ToolSession } from "../sdk";
7
+ import type { AgentStorage } from "../session/agent-storage";
7
8
  import { type TruncationDirection } from "../session/streaming-output";
8
- import type { RenderResult } from "../web/scrapers/types";
9
+ import { type RenderResult } from "../web/scrapers/types";
9
10
  import { type OutputMeta } from "./output-meta";
10
11
  export declare function isReadableUrlPath(value: string): boolean;
11
12
  export interface ParsedReadUrlTarget {
@@ -27,6 +28,14 @@ interface FetchImagePayload {
27
28
  type FetchRenderResult = RenderResult & {
28
29
  image?: FetchImagePayload;
29
30
  };
31
+ /**
32
+ * Try all special handlers
33
+ */
34
+ declare function handleSpecialUrls(url: string, timeout: number, signal: AbortSignal | undefined, storage: AgentStorage | null): Promise<FetchRenderResult | null>;
35
+ /** Test-only seam for verifying lazy special-handler loading and dispatch. */
36
+ export declare const fetchSpecialHandlerTestHooks: {
37
+ dispatch: typeof handleSpecialUrls;
38
+ };
30
39
  export declare function tryInsaneFallback(args: {
31
40
  url: string;
32
41
  finalUrl: string;
@@ -80,6 +80,10 @@ export interface SubagentLiveProgress {
80
80
  recentOutputSummary?: {
81
81
  lineCount: number;
82
82
  };
83
+ toolCount?: number;
84
+ contextTokens?: number;
85
+ contextWindow?: number;
86
+ lastActivityMs?: number;
83
87
  fastMode?: boolean;
84
88
  retryState?: {
85
89
  attempt: number;
@@ -165,10 +169,13 @@ export declare function capCodePointsAndBytes(text: string, maxCodePoints: numbe
165
169
  * unsafe.
166
170
  *
167
171
  * Time-derived fields are intentionally excluded so the panel does not churn while
168
- * idle: raw durations (`durationMs`), current-tool elapsed (`currentToolStartMs`),
172
+ * idle (the child's last-event timestamp is included; it moves only on real
173
+ * activity): raw durations (`durationMs`), current-tool elapsed (`currentToolStartMs`),
169
174
  * and retry countdowns (`retryState.startedAtMs`) are omitted. Idle duration and
170
175
  * countdown ticking is sacrificed by design; every real transition still changes
171
176
  * the signature.
172
177
  */
178
+ /** Shared cadence for await progress refreshes and rendered last-activity age. */
179
+ export declare const SUBAGENT_ACTIVITY_BUCKET_MS = 5000;
173
180
  export declare function subagentAwaitRenderedStateSignature(subagents: readonly SubagentSnapshot[], receipt?: Pick<SubagentToolDetails, "awaitOutcome" | "interrupted">): string;
174
181
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.17.4",
4
+ "version": "0.17.5",
5
5
  "description": "Gajae Code CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://gajae-code.com",
7
7
  "author": "Yeachan-Heo and Gajae Code Contributors",
@@ -57,12 +57,12 @@
57
57
  "@agentclientprotocol/sdk": "1.3.0",
58
58
  "@babel/parser": "^7.29.3",
59
59
  "@mozilla/readability": "^0.6.0",
60
- "@gajae-code/stats": "0.17.4",
61
- "@gajae-code/agent-core": "0.17.4",
62
- "@gajae-code/ai": "0.17.4",
63
- "@gajae-code/natives": "0.17.4",
64
- "@gajae-code/tui": "0.17.4",
65
- "@gajae-code/utils": "0.17.4",
60
+ "@gajae-code/stats": "0.17.5",
61
+ "@gajae-code/agent-core": "0.17.5",
62
+ "@gajae-code/ai": "0.17.5",
63
+ "@gajae-code/natives": "0.17.5",
64
+ "@gajae-code/tui": "0.17.5",
65
+ "@gajae-code/utils": "0.17.5",
66
66
  "@puppeteer/browsers": "^2.13.0",
67
67
  "@types/turndown": "5.0.6",
68
68
  "@xterm/headless": "^6.0.0",
@@ -82,6 +82,9 @@ const argument = (description: string, extra: Partial<PublicArgumentDescriptor>
82
82
  });
83
83
  const agentDir = stringFlag("SDK broker/state directory (default: the configured agent directory).");
84
84
  const repo = stringFlag("Workspace directory for scope or saved-session resolution (default: current directory).");
85
+ const exactSessionRepo = stringFlag(
86
+ "Accepted for compatibility only; ignored because the exact session ID selects the broker target.",
87
+ );
85
88
  const timeout = positive("Request or live-follow timeout in milliseconds; send uses this for its --wait window.");
86
89
  const idempotency = stringFlag(
87
90
  "Caller idempotency key; retain it when reconciling an uncertain mutation, never blindly replay.",
@@ -275,6 +278,7 @@ export const PUBLIC_COMMANDS: readonly PublicCommandDescriptor[] = [
275
278
  node("sdk session", {
276
279
  description: "Manage broker-bound credential-free sessions.",
277
280
  children: ["list", "inspect", "send", "status", "tail", "retire", "raw"],
281
+ flags: sessionFlags,
278
282
  syntax: "<command>",
279
283
  }),
280
284
  node("sdk session list", {
@@ -294,7 +298,7 @@ export const PUBLIC_COMMANDS: readonly PublicCommandDescriptor[] = [
294
298
  node("sdk session inspect", {
295
299
  description: "Inspect a session without exposing endpoint credentials.",
296
300
  args: sessionArg,
297
- flags: sessionFlags,
301
+ flags: { ...sessionFlags, repo: exactSessionRepo },
298
302
  syntax: "<sessionId>",
299
303
  }),
300
304
  node("sdk session send", {
@@ -302,6 +306,7 @@ export const PUBLIC_COMMANDS: readonly PublicCommandDescriptor[] = [
302
306
  args: sessionArg,
303
307
  flags: {
304
308
  ...sessionFlags,
309
+ repo: exactSessionRepo,
305
310
  ...jsonInput,
306
311
  text: stringFlag("Prompt text, alternative to nonempty JSON input."),
307
312
  "op-ref": stringFlag(
@@ -324,7 +329,7 @@ export const PUBLIC_COMMANDS: readonly PublicCommandDescriptor[] = [
324
329
  node("sdk session status", {
325
330
  description: "Read the durable prompt result for a known operation reference.",
326
331
  args: { ...sessionArg, opRef: argument("Exact operation reference returned or supplied by send.") },
327
- flags: { ...sessionFlags, "timeout-ms": timeout },
332
+ flags: { ...sessionFlags, repo: exactSessionRepo, "timeout-ms": timeout },
328
333
  syntax: "<sessionId> <opRef>",
329
334
  }),
330
335
  node("sdk session tail", {
@@ -392,6 +397,7 @@ export const PUBLIC_COMMANDS: readonly PublicCommandDescriptor[] = [
392
397
  operationKind: "query",
393
398
  flags: {
394
399
  ...sessionFlags,
400
+ repo: exactSessionRepo,
395
401
  ...jsonInput,
396
402
  query: stringFlag("Query ID (including registered query aliases).", { required: true }),
397
403
  cursor: stringFlag("Raw query continuation cursor."),
@@ -935,6 +935,7 @@ ${chalk.bold("Provider example:")}
935
935
  ${APP_NAME} setup provider --preset glm
936
936
  ${APP_NAME} setup provider --preset cline-pass
937
937
  ${APP_NAME} setup provider --preset commandcode-goat
938
+ ${APP_NAME} setup provider --preset ionet
938
939
  ${APP_NAME} setup provider --preset litellm --base-url https://litellm.example.com/v1
939
940
  ${APP_NAME} setup provider --preset openai-compatible-proxy --base-url https://gateway.example.com/v1
940
941
  MY_PROVIDER_KEY=sk-... ${APP_NAME} setup provider --compat openai --provider my-oai --base-url https://api.example.com/v1 --api-key-env MY_PROVIDER_KEY --model gpt-example
@@ -168,7 +168,7 @@ export async function runStatsCommand(cmd: StatsCommandArgs): Promise<void> {
168
168
  async function printStatsSummary(): Promise<void> {
169
169
  const { getDashboardStats } = await import("@gajae-code/stats");
170
170
  const stats = await getDashboardStats();
171
- const { overall, byModel, byFolder } = stats;
171
+ const { overall, byModel, byFolder, byAgent } = stats;
172
172
 
173
173
  console.log(chalk.bold("\n=== AI Usage Statistics ===\n"));
174
174
 
@@ -196,6 +196,15 @@ async function printStatsSummary(): Promise<void> {
196
196
  }
197
197
  }
198
198
 
199
+ if (byAgent.length > 0) {
200
+ console.log(chalk.bold("\nBy Agent Role:"));
201
+ for (const agent of byAgent) {
202
+ console.log(
203
+ ` ${agent.agent}: ${formatNumber(agent.totalRequests)} reqs, ${formatNumber(agent.totalInputTokens)} input / ${formatNumber(agent.totalOutputTokens)} output, ${formatPercent(agent.cacheRate)} cache, ${formatCost(agent.totalCost)}`,
204
+ );
205
+ }
206
+ }
207
+
199
208
  if (byFolder.length > 0) {
200
209
  console.log(chalk.bold("\nBy Folder:"));
201
210
  for (const f of byFolder.slice(0, 10)) {
@@ -231,6 +240,7 @@ ${chalk.bold("Examples:")}
231
240
  ${chalk.bold("Metrics:")}
232
241
  - Total requests and error rate
233
242
  - Token usage (input, output, cache)
243
+ - Role usage (default, executor, planner, architect, critic)
234
244
  - Cost breakdown
235
245
  - Average duration and time to first token (TTFT)
236
246
  - Tokens per second throughput