@gajae-code/coding-agent 0.11.10 → 0.11.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 (111) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/types/cli.d.ts +8 -1
  3. package/dist/types/config/model-profile-activation.d.ts +1 -0
  4. package/dist/types/config/model-profile-contract.d.ts +2 -0
  5. package/dist/types/config/settings-schema.d.ts +57 -2
  6. package/dist/types/config/settings.d.ts +1 -0
  7. package/dist/types/extensibility/extensions/types.d.ts +21 -0
  8. package/dist/types/gjc-runtime/linux-proc.d.ts +22 -14
  9. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +60 -0
  10. package/dist/types/gjc-runtime/state-runtime.d.ts +3 -1
  11. package/dist/types/modes/acp/acp-agent.d.ts +14 -9
  12. package/dist/types/modes/components/queue-pane.d.ts +8 -0
  13. package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
  14. package/dist/types/modes/components/welcome.d.ts +1 -0
  15. package/dist/types/modes/interactive-mode.d.ts +5 -1
  16. package/dist/types/runtime/memory-domain.d.ts +9 -0
  17. package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
  18. package/dist/types/runtime/memory-guard.d.ts +39 -0
  19. package/dist/types/runtime/memory-limit.d.ts +11 -0
  20. package/dist/types/runtime-mcp/manager.d.ts +8 -0
  21. package/dist/types/sdk/acp/final-text.d.ts +19 -0
  22. package/dist/types/sdk/acp/mcp.d.ts +23 -0
  23. package/dist/types/sdk/broker/lifecycle.d.ts +2 -0
  24. package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -1
  25. package/dist/types/sdk/bus/index.d.ts +3 -1
  26. package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
  27. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -4
  28. package/dist/types/sdk/bus/telegram-daemon.d.ts +23 -3
  29. package/dist/types/sdk/host/control/operations.d.ts +1 -0
  30. package/dist/types/sdk/lifecycle-session.d.ts +10 -1
  31. package/dist/types/sdk/startup-capability.d.ts +6 -0
  32. package/dist/types/session/agent-session.d.ts +9 -11
  33. package/dist/types/session/fallback-chain-controller.d.ts +18 -2
  34. package/dist/types/session/internal/managed-session-scope.d.ts +27 -0
  35. package/dist/types/session/session-manager.d.ts +34 -0
  36. package/dist/types/task/executor.d.ts +6 -0
  37. package/dist/types/task/types.d.ts +36 -0
  38. package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
  39. package/dist/types/tools/resource-gc.d.ts +19 -0
  40. package/package.json +8 -8
  41. package/scripts/generate-sdk-operation-inventory.ts +2 -0
  42. package/scripts/run-test-manifest.ts +6 -4
  43. package/src/cli/args.ts +14 -8
  44. package/src/cli/fast-help.ts +1 -1
  45. package/src/cli.ts +48 -2
  46. package/src/commands/sdk.ts +91 -7
  47. package/src/config/model-profile-activation.ts +1 -0
  48. package/src/config/model-profile-contract.ts +13 -0
  49. package/src/config/model-profiles.ts +24 -0
  50. package/src/config/settings-schema.ts +61 -2
  51. package/src/config/settings.ts +8 -0
  52. package/src/defaults/gjc/skills/ralplan/SKILL.md +21 -2
  53. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  54. package/src/extensibility/extensions/runner.ts +4 -0
  55. package/src/extensibility/extensions/types.ts +14 -0
  56. package/src/gjc-runtime/deep-interview-ambiguity.ts +16 -2
  57. package/src/gjc-runtime/deep-interview-state.ts +25 -3
  58. package/src/gjc-runtime/linux-proc.ts +70 -36
  59. package/src/gjc-runtime/ralplan-runtime.ts +252 -1
  60. package/src/gjc-runtime/state-runtime.ts +48 -11
  61. package/src/internal-urls/docs-index.generated.ts +4 -4
  62. package/src/internal-urls/local-protocol.ts +23 -4
  63. package/src/modes/acp/acp-agent.ts +554 -60
  64. package/src/modes/acp/acp-event-mapper.ts +93 -6
  65. package/src/modes/components/model-selector.ts +15 -1
  66. package/src/modes/components/notifications-settings-editor.ts +1 -1
  67. package/src/modes/components/queue-pane.ts +55 -9
  68. package/src/modes/components/queued-message-selector.ts +53 -10
  69. package/src/modes/components/tool-status-header.ts +1 -4
  70. package/src/modes/components/welcome.ts +18 -3
  71. package/src/modes/controllers/command-controller.ts +4 -0
  72. package/src/modes/controllers/extension-ui-controller.ts +4 -10
  73. package/src/modes/controllers/input-controller.ts +44 -3
  74. package/src/modes/interactive-mode.ts +65 -26
  75. package/src/modes/runtime-init.ts +1 -0
  76. package/src/prompts/agents/executor.md +1 -1
  77. package/src/runtime/memory-domain.ts +66 -0
  78. package/src/runtime/memory-guard-contract.ts +73 -0
  79. package/src/runtime/memory-guard.ts +292 -0
  80. package/src/runtime/memory-limit.ts +50 -0
  81. package/src/runtime-mcp/manager.ts +26 -6
  82. package/src/sdk/acp/adapter.ts +8 -1
  83. package/src/sdk/acp/final-text.ts +40 -0
  84. package/src/sdk/acp/mcp.ts +26 -0
  85. package/src/sdk/broker/lifecycle.ts +82 -1
  86. package/src/sdk/bus/chat-daemon-cli.ts +2 -2
  87. package/src/sdk/bus/chat-daemon-control.ts +4 -3
  88. package/src/sdk/bus/config.ts +1 -1
  89. package/src/sdk/bus/index.ts +162 -22
  90. package/src/sdk/bus/rate-limit-pool.ts +8 -0
  91. package/src/sdk/bus/telegram-daemon-contract.ts +6 -4
  92. package/src/sdk/bus/telegram-daemon.ts +531 -53
  93. package/src/sdk/host/control/dispatch.ts +2 -0
  94. package/src/sdk/host/control/operations.ts +1 -0
  95. package/src/sdk/host/host.ts +2 -2
  96. package/src/sdk/lifecycle-session.ts +19 -3
  97. package/src/sdk/protocol/operation-inventory.generated.json +47 -0
  98. package/src/sdk/protocol/operation-registry.ts +1 -0
  99. package/src/sdk/session.ts +12 -1
  100. package/src/sdk/startup-capability.ts +6 -0
  101. package/src/session/agent-session.ts +256 -142
  102. package/src/session/fallback-chain-controller.ts +47 -8
  103. package/src/session/internal/managed-session-scope.ts +40 -10
  104. package/src/session/internal/native-publish-outcome.ts +8 -3
  105. package/src/session/session-manager.ts +608 -25
  106. package/src/task/executor.ts +11 -3
  107. package/src/task/index.ts +2 -0
  108. package/src/task/types.ts +22 -11
  109. package/src/task/ultragoal-redteam-activation.ts +75 -0
  110. package/src/tools/resource-gc.ts +496 -120
  111. package/src/workflow/workflow-intent-diff.ts +4 -1
@@ -30,6 +30,7 @@ export class FallbackChainController {
30
30
 
31
31
  #attemptStarted = false;
32
32
  #totalAttemptsUsed = 0;
33
+ #restoredEntryIndices = new Set<number>();
33
34
  skips: Array<{ selector: string; reason: string }> = [];
34
35
  exhaustedForTurn = false;
35
36
 
@@ -46,6 +47,10 @@ export class FallbackChainController {
46
47
  return this.#totalAttemptsUsed;
47
48
  }
48
49
 
50
+ #maxTotalAttempts(): number {
51
+ return this.maxAttempts * this.chain.entries.length + this.#restoredEntryIndices.size;
52
+ }
53
+
49
54
  currentSelector(): string | undefined {
50
55
  return this.chain.entries[this.activeIndex];
51
56
  }
@@ -59,7 +64,7 @@ export class FallbackChainController {
59
64
  /** Charge an upstream request at its concrete transport boundary. */
60
65
  onAttemptStarted(): void {
61
66
  if (!this.currentSelector() || this.exhaustedForTurn) return;
62
- if (this.#totalAttemptsUsed >= this.maxAttempts * this.chain.entries.length) {
67
+ if (this.#totalAttemptsUsed >= this.#maxTotalAttempts()) {
63
68
  this.activeIndex = this.chain.entries.length;
64
69
  this.exhaustedForTurn = true;
65
70
  return;
@@ -82,6 +87,7 @@ export class FallbackChainController {
82
87
  this.attemptsUsed = 0;
83
88
  this.#totalAttemptsUsed = 0;
84
89
  this.tried = [];
90
+ this.#restoredEntryIndices.clear();
85
91
  this.#attemptStarted = false;
86
92
  }
87
93
 
@@ -91,6 +97,7 @@ export class FallbackChainController {
91
97
  this.skips = [...skips];
92
98
  this.attemptsUsed = 0;
93
99
  this.#totalAttemptsUsed = 0;
100
+ this.#restoredEntryIndices.clear();
94
101
  this.#attemptStarted = false;
95
102
  this.exhaustedForTurn = this.activeIndex >= this.chain.entries.length;
96
103
  }
@@ -104,7 +111,7 @@ export class FallbackChainController {
104
111
  }
105
112
  this.#attemptStarted = false;
106
113
  this.tried.push({ selector, triggerClass, reason });
107
- if (this.#totalAttemptsUsed >= this.maxAttempts * this.chain.entries.length) {
114
+ if (this.#totalAttemptsUsed >= this.#maxTotalAttempts()) {
108
115
  this.activeIndex = this.chain.entries.length;
109
116
  this.exhaustedForTurn = true;
110
117
  return "exhausted";
@@ -126,19 +133,23 @@ export class FallbackChainController {
126
133
  }
127
134
 
128
135
  /**
129
- * Restore the entry that just advanced when credential rotation permits a retry.
130
- * The chain-wide budget and failure history remain charged.
136
+ * Restore the entry that just advanced for one attempt with a rotated credential.
137
+ * Each non-terminal entry may be restored once, so credential rotation remains
138
+ * bounded and cannot consume the attempts reserved for downstream entries.
131
139
  */
132
140
  restorePreviousEntryForRetry(): boolean {
141
+ const previousIndex = this.activeIndex - 1;
133
142
  if (
134
- this.activeIndex === 0 ||
143
+ previousIndex < 0 ||
135
144
  this.exhaustedForTurn ||
136
- this.#totalAttemptsUsed >= this.maxAttempts * this.chain.entries.length
145
+ this.#restoredEntryIndices.has(previousIndex) ||
146
+ this.#totalAttemptsUsed >= this.#maxTotalAttempts()
137
147
  ) {
138
148
  return false;
139
149
  }
140
- this.activeIndex -= 1;
141
- this.attemptsUsed = 0;
150
+ this.#restoredEntryIndices.add(previousIndex);
151
+ this.activeIndex = previousIndex;
152
+ this.attemptsUsed = this.maxAttempts - 1;
142
153
  this.exhaustedForTurn = false;
143
154
  this.#attemptStarted = false;
144
155
  return true;
@@ -157,6 +168,7 @@ export class FallbackChainController {
157
168
  this.attemptsUsed = 0;
158
169
  this.#totalAttemptsUsed = 0;
159
170
  this.tried = [];
171
+ this.#restoredEntryIndices.clear();
160
172
  this.skips = [];
161
173
  this.exhaustedForTurn = this.chain.entries.length === 0;
162
174
  this.#attemptStarted = false;
@@ -174,6 +186,33 @@ export function cappedExponentialWithFullJitter(
174
186
  return Math.floor(Math.max(0, cap) * Math.max(0, Math.min(1, random())));
175
187
  }
176
188
 
189
+ /**
190
+ * Legacy auto-compaction retry delay.
191
+ *
192
+ * Deliberately the mirror image of `effectiveFallbackDelay`: this path recovers
193
+ * Retry-After by regex over provider error prose (`#parseRetryAfterMsFromError`),
194
+ * so it follows the documented legacy rule — `retry.maxDelayMs` caps every
195
+ * legacy session retry delay, including provider retry-after hints. Managed
196
+ * fallback stays uncapped because it retries within its own per-entry budget;
197
+ * compaction has no such budget, so the final candidate would otherwise sleep
198
+ * for the full server-suggested duration.
199
+ *
200
+ * `maxDelayMs <= 0` means "no cap", matching `cappedExponentialWithFullJitter`.
201
+ * A missing, NaN, or infinite hint collapses to "no usable hint".
202
+ */
203
+ export function compactionRetryDelay(
204
+ baseDelayMs: number,
205
+ maxDelayMs: number,
206
+ attempt: number,
207
+ retryAfterMs: number | undefined,
208
+ ): number {
209
+ const exponential = baseDelayMs * 2 ** Math.max(0, attempt);
210
+ const hint = Number.isFinite(retryAfterMs) ? Math.max(0, retryAfterMs as number) : 0;
211
+ const hinted = Math.max(exponential, hint);
212
+ const bounded = maxDelayMs > 0 ? Math.min(hinted, maxDelayMs) : hinted;
213
+ return Math.max(0, bounded);
214
+ }
215
+
177
216
  /** Retry-After is intentionally uncapped. */
178
217
  export function effectiveFallbackDelay(
179
218
  baseDelayMs: number,
@@ -2400,7 +2400,11 @@ type SourceArtifactCleanup = {
2400
2400
  tree: NativeDirectoryTreeSnapshot;
2401
2401
  };
2402
2402
 
2403
- function cleanupAuthorityMatches(cleanup: SourceArtifactCleanup, parent: string): boolean {
2403
+ export function cleanupAuthorityMatches(
2404
+ cleanup: SourceArtifactCleanup,
2405
+ parent: string,
2406
+ platform: NodeJS.Platform = process.platform,
2407
+ ): boolean {
2404
2408
  try {
2405
2409
  const stat = fs.lstatSync(cleanup.retainedPath, { bigint: true });
2406
2410
  if (
@@ -2408,15 +2412,26 @@ function cleanupAuthorityMatches(cleanup: SourceArtifactCleanup, parent: string)
2408
2412
  !stat.isDirectory() ||
2409
2413
  stat.isSymbolicLink() ||
2410
2414
  stat.dev !== cleanup.identity.dev ||
2411
- stat.ino !== cleanup.identity.ino ||
2412
- stat.size !== cleanup.identity.size ||
2413
- stat.mtimeNs !== cleanup.identity.mtimeNs
2415
+ stat.ino !== cleanup.identity.ino
2414
2416
  )
2415
2417
  return false;
2416
2418
  const snapshot = native.snapshotDirectoryTree(cleanup.retainedPath);
2419
+ const observedRoot = snapshot.snapshot?.entries.find(
2420
+ entry => entry.relativePath === "" && entry.kind === "directory",
2421
+ );
2422
+ if (
2423
+ !snapshot.ok ||
2424
+ !snapshot.snapshot ||
2425
+ !observedRoot ||
2426
+ (platform === "win32"
2427
+ ? observedRoot.dev !== cleanup.identity.dev.toString() ||
2428
+ observedRoot.ino !== cleanup.identity.ino.toString() ||
2429
+ BigInt(observedRoot.size) !== cleanup.identity.size ||
2430
+ BigInt(observedRoot.mtimeNs) !== cleanup.identity.mtimeNs
2431
+ : stat.size !== cleanup.identity.size || stat.mtimeNs !== cleanup.identity.mtimeNs)
2432
+ )
2433
+ return false;
2417
2434
  return (
2418
- !!snapshot.ok &&
2419
- !!snapshot.snapshot &&
2420
2435
  sameArtifactTree(snapshot.snapshot, cleanup.tree) &&
2421
2436
  cleanup.tree.entries.length === 1 &&
2422
2437
  cleanup.tree.entries[0]?.relativePath === "" &&
@@ -2427,8 +2442,9 @@ function cleanupAuthorityMatches(cleanup: SourceArtifactCleanup, parent: string)
2427
2442
  }
2428
2443
  }
2429
2444
 
2430
- function detachArtifactRootForMigration(
2445
+ export function detachArtifactRootForMigration(
2431
2446
  plan: DetachedArtifactRoot,
2447
+ platform: NodeJS.Platform = process.platform,
2432
2448
  ):
2433
2449
  | { detached: DetachedArtifactRoot; detachOutcome: "clean" }
2434
2450
  | { detached: DetachedArtifactRoot; detachOutcome: "cleanup_pending"; cleanup: SourceArtifactCleanup } {
@@ -2464,14 +2480,27 @@ function detachArtifactRootForMigration(
2464
2480
  if (!stat.isDirectory() || stat.isSymbolicLink() || path.dirname(placeholder) !== path.dirname(plan.originalPath))
2465
2481
  throw new Error("durability_failed");
2466
2482
  const snapshot = native.snapshotDirectoryTree(placeholder);
2483
+ if (!snapshot.ok || !snapshot.snapshot) throw new Error("durability_failed");
2484
+ // Windows directory size/mtime authority is the native tree root, never Bun's
2485
+ // zero-valued directory lstat. Capturing Bun values here would guarantee a
2486
+ // mismatch against the native-authoritative check below.
2487
+ const placeholderRoot = snapshot.snapshot.entries.find(
2488
+ entry => entry.relativePath === "" && entry.kind === "directory",
2489
+ );
2490
+ if (!placeholderRoot) throw new Error("durability_failed");
2467
2491
  const cleanup: SourceArtifactCleanup = {
2468
2492
  state: "cleanup_pending",
2469
2493
  role: "exchange_placeholder",
2470
2494
  retainedPath: placeholder,
2471
- identity: { dev: stat.dev, ino: stat.ino, size: stat.size, mtimeNs: stat.mtimeNs },
2472
- tree: snapshot.snapshot!,
2495
+ identity: {
2496
+ dev: stat.dev,
2497
+ ino: stat.ino,
2498
+ size: platform === "win32" ? BigInt(placeholderRoot.size) : stat.size,
2499
+ mtimeNs: platform === "win32" ? BigInt(placeholderRoot.mtimeNs) : stat.mtimeNs,
2500
+ },
2501
+ tree: snapshot.snapshot,
2473
2502
  };
2474
- if (!snapshot.ok || !snapshot.snapshot || !cleanupAuthorityMatches(cleanup, path.dirname(plan.originalPath)))
2503
+ if (!cleanupAuthorityMatches(cleanup, path.dirname(plan.originalPath), platform))
2475
2504
  throw new Error("durability_failed");
2476
2505
  return { detached, detachOutcome: "cleanup_pending", cleanup };
2477
2506
  }
@@ -2798,6 +2827,7 @@ export async function reconcileManagedTombstones(
2798
2827
  const tombstone = path.join(directory, name);
2799
2828
  const targets = retiredTargets(scope, tombstone);
2800
2829
  if (!targets) continue;
2830
+ if (targets.every(target => cleanupCompleted(scope, tombstone, target))) continue;
2801
2831
  let lock: ManagedStorageLock | undefined;
2802
2832
  try {
2803
2833
  lock = await acquireManagedLock(
@@ -171,9 +171,14 @@ function legalOutcome(outcome: NativePublishOutcome): boolean {
171
171
  outcome.durabilityState === "not_attempted" &&
172
172
  preMutationReasons.has(outcome.reason) &&
173
173
  ((outcome.phase === "rename" &&
174
- ["destination_exists", "atomic_unavailable", "cross_device", "permission_denied", "io_failure"].includes(
175
- outcome.reason,
176
- )) ||
174
+ [
175
+ "destination_exists",
176
+ "atomic_unavailable",
177
+ "cross_device",
178
+ "permission_denied",
179
+ "io_failure",
180
+ "interrupted",
181
+ ].includes(outcome.reason)) ||
177
182
  (outcome.phase === "preflight" &&
178
183
  !["atomic_unavailable", "cross_device", "interrupted"].includes(outcome.reason)) ||
179
184
  (outcome.phase === "file_sync" && outcome.reason === "io_failure"))