@gajae-code/coding-agent 0.17.4 → 0.17.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 (86) hide show
  1. package/CHANGELOG.md +82 -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/lifecycle-ledger.d.ts +11 -3
  18. package/dist/types/sdk/broker/managed-task-dag.d.ts +1335 -0
  19. package/dist/types/sdk/broker/managed-task-verification.d.ts +37 -0
  20. package/dist/types/sdk/broker/spawn-authority.d.ts +8 -0
  21. package/dist/types/sdk/broker/startup-failure.d.ts +4 -0
  22. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +5 -1
  23. package/dist/types/sdk/prompt-deadline-flush.d.ts +2 -0
  24. package/dist/types/sdk/session.d.ts +3 -3
  25. package/dist/types/session/agent-session.d.ts +7 -2
  26. package/dist/types/task/types.d.ts +2 -0
  27. package/dist/types/tools/bash-interactive.d.ts +1 -0
  28. package/dist/types/tools/fetch.d.ts +10 -1
  29. package/dist/types/tools/subagent.d.ts +8 -1
  30. package/package.json +7 -7
  31. package/src/cli/public-command-registry.ts +8 -2
  32. package/src/cli/setup-cli.ts +1 -0
  33. package/src/cli/stats-cli.ts +11 -1
  34. package/src/config/autorouting-tier-map.ts +529 -3
  35. package/src/config/file-lock.ts +59 -14
  36. package/src/config/model-discovery-manager.ts +4 -4
  37. package/src/config/model-profile-activation.ts +83 -23
  38. package/src/config/model-registry.ts +72 -12
  39. package/src/config/model-resolver.ts +6 -1
  40. package/src/coordinator-mcp/question-state.ts +4 -1
  41. package/src/coordinator-mcp/server.ts +14 -6
  42. package/src/exec/bash-executor.ts +3 -0
  43. package/src/extensibility/gjc-plugins/runtime-adapters.ts +46 -8
  44. package/src/gjc-runtime/state-writer.ts +317 -6
  45. package/src/harness-control-plane/control-endpoint.ts +24 -6
  46. package/src/harness-control-plane/finalize.ts +312 -25
  47. package/src/harness-control-plane/owner.ts +323 -89
  48. package/src/internal-urls/docs-index.generated.ts +6 -4
  49. package/src/main.ts +69 -19
  50. package/src/modes/acp/acp-agent.ts +581 -37
  51. package/src/modes/components/gjc-bundle-settings.ts +21 -1
  52. package/src/modes/components/tool-status-header.ts +72 -6
  53. package/src/modes/controllers/runtime-mcp-command-controller.ts +1 -1
  54. package/src/runtime-mcp/loader.ts +6 -3
  55. package/src/runtime-mcp/manager.ts +177 -75
  56. package/src/sdk/broker/broker.ts +1058 -150
  57. package/src/sdk/broker/ensure.ts +65 -8
  58. package/src/sdk/broker/identity.ts +13 -0
  59. package/src/sdk/broker/lifecycle-ledger.ts +16 -4
  60. package/src/sdk/broker/managed-task-dag.ts +1927 -0
  61. package/src/sdk/broker/managed-task-verification.ts +642 -0
  62. package/src/sdk/broker/spawn-authority.ts +140 -7
  63. package/src/sdk/broker/startup-failure.ts +80 -1
  64. package/src/sdk/broker/transport.ts +1 -0
  65. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  66. package/src/sdk/bus/index.ts +22 -6
  67. package/src/sdk/bus/telegram-daemon-contract.ts +5 -1
  68. package/src/sdk/cli/session-cli.ts +18 -0
  69. package/src/sdk/host/session-runtime.test.ts +46 -0
  70. package/src/sdk/host/session-runtime.ts +13 -6
  71. package/src/sdk/lifecycle/service.ts +2 -0
  72. package/src/sdk/prompt-deadline-flush.ts +26 -4
  73. package/src/sdk/session.ts +587 -115
  74. package/src/session/agent-session.ts +60 -14
  75. package/src/session/internal/managed-session-scope.ts +10 -0
  76. package/src/session/internal/managed-session-storage.ts +30 -1
  77. package/src/setup/provider-presets.json +2 -1
  78. package/src/slash-commands/builtin-registry.ts +1 -1
  79. package/src/task/executor.ts +46 -17
  80. package/src/task/types.ts +2 -0
  81. package/src/tools/bash-interactive.ts +2 -0
  82. package/src/tools/bash.ts +20 -0
  83. package/src/tools/fetch.ts +21 -5
  84. package/src/tools/subagent-render.ts +24 -1
  85. package/src/tools/subagent.ts +27 -1
  86. package/src/utils/mupdf.ts +11 -4
@@ -18,13 +18,25 @@ import {
18
18
  resolveSdkInternalSpawnCommand,
19
19
  type SdkInternalSpawnCommand,
20
20
  } from "./runtime";
21
- import { BrokerStartupError, clearBrokerStartupFailureMarker, readBrokerStartupFailureMarker } from "./startup-failure";
21
+ import {
22
+ BrokerStartupError,
23
+ type BrokerStartupFailureMarker,
24
+ brokerStartupFailureCleanupTargetsLock,
25
+ clearBrokerStartupFailureMarker,
26
+ readBrokerStartupFailureMarker,
27
+ } from "./startup-failure";
22
28
 
23
29
  function resolveExpectedBrokerGeneration(): string {
24
30
  const v = (packageJson as { version?: unknown }).version;
25
31
  return typeof v === "string" && v.length > 0 ? v : "unknown";
26
32
  }
27
33
 
34
+ function brokerStartupFailureReason(marker: BrokerStartupFailureMarker | undefined): string {
35
+ if (!marker) return "Detached SDK broker exited before publishing discovery.";
36
+ if (marker.cleanupCommand && marker.reason.endsWith(": ")) return `${marker.reason}${marker.cleanupCommand}`;
37
+ return marker.reason;
38
+ }
39
+
28
40
  export function isBrokerGenerationCompatible(discovery: BrokerDiscovery | null): boolean {
29
41
  if (!discovery) return false;
30
42
  return discovery.packageGeneration === resolveExpectedBrokerGeneration();
@@ -69,6 +81,34 @@ const SPAWN_LOCK_WAIT_MS = STALE_BROKER_RETIREMENT_TIMEOUT_MS + DISCOVERY_TIMEOU
69
81
  const SPAWN_LOCK_RETRY_DELAY_MS = 50;
70
82
  const SPAWN_LOCK_TARGET_NAME = "broker.spawn";
71
83
  const STARTUP_LOCK_TARGET_NAME = "broker.startup";
84
+ const BROKER_SESSION_ENV_NAMES = new Set([
85
+ "GJC_SESSION_FILE",
86
+ "GJC_SESSION_ID",
87
+ "GJC_SESSION_CWD",
88
+ "GJC_SESSION_PROMPT_ACCEPTED_JSON",
89
+ "GJC_SESSION_WORKTREE_BASELINE_DIRTY",
90
+ "GJC_TMUX_ACTIVE_SESSION",
91
+ "GJC_TMUX_LAUNCHED",
92
+ "TMUX",
93
+ "TMUX_PANE",
94
+ "GJC_LIFECYCLE_REQUEST_ID",
95
+ "GJC_SDK_LIFECYCLE_REQUEST",
96
+ "GJC_STATE_ROOT",
97
+ "GJC_MASTER_CAPABILITY",
98
+ "GJC_MASTER_OWNER_SESSION_ID",
99
+ ]);
100
+ const BROKER_SESSION_ENV_PRESERVED_NAMES = new Set([
101
+ "GJC_SESSION_CONTEXT_BUDGET_BYTES",
102
+ "GJC_SESSION_MEMORY_GC_STRATEGY",
103
+ "GJC_SESSION_MEMORY_SECONDARY_ARTIFACT_MODE",
104
+ ]);
105
+ const BROKER_SESSION_ENV_PREFIXES = [
106
+ "GJC_SESSION_",
107
+ "GJC_COORDINATOR_SESSION_",
108
+ "GJC_COORDINATOR_SIDECAR_",
109
+ "GJC_TMUX_OWNER_",
110
+ "GJC_MANAGED_OWNER_",
111
+ ] as const;
72
112
 
73
113
  export interface BrokerStartupLockTestHooks {
74
114
  onAcquired?: () => void;
@@ -445,11 +485,22 @@ function registerBrokerOwner(
445
485
  function brokerSpawnEnvironment(command: SdkInternalSpawnCommand, override?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
446
486
  const environment = { ...(override ?? command.env) };
447
487
  delete environment.BUN_OPTIONS;
448
- // The master capability is a transient in-memory dispatch input. A broker
449
- // cold-started from the master's own Bash environment would otherwise inherit
450
- // it and pass it on to every substrate child it later launches, so it is
451
- // stripped at the lifecycle boundary exactly as lifecycle children strip it.
452
- delete environment.GJC_MASTER_CAPABILITY;
488
+ // Master capability and owner-session markers are matched by the normalized
489
+ // identity-name set below, including differently-cased Windows environment keys.
490
+ // The broker outlives the TUI session that happened to start it. Never let
491
+ // that session's identity or coordinator/tmux ownership markers flow through
492
+ // the broker's process.env into unrelated session hosts. Keep user tmux
493
+ // configuration (for example GJC_TMUX_SESSION, GJC_TMUX_COMMAND, GJC_MOUSE,
494
+ // and GJC_TMUX_PROFILE) intact. Windows environment names are case-insensitive.
495
+ for (const name of Object.keys(environment)) {
496
+ const normalizedName = name.toUpperCase();
497
+ if (BROKER_SESSION_ENV_PRESERVED_NAMES.has(normalizedName)) continue;
498
+ if (
499
+ BROKER_SESSION_ENV_NAMES.has(normalizedName) ||
500
+ BROKER_SESSION_ENV_PREFIXES.some(prefix => normalizedName.startsWith(prefix))
501
+ )
502
+ delete environment[name];
503
+ }
453
504
  if (command.kind === "bun-source") {
454
505
  delete environment.PI_COMPILED;
455
506
  delete environment.GJC_COMPILED;
@@ -712,7 +763,8 @@ async function ensureBrokerOnce(settings: EnsureBrokerSettings, initiator: Ensur
712
763
  const startupLockPath = path.join(settings.agentDir, "sdk", STARTUP_LOCK_TARGET_NAME);
713
764
  let startupFenceContention =
714
765
  exitedBeforeDiscovery &&
715
- trustedMarker?.reason.startsWith(`Failed to acquire lock for ${startupLockPath} after `) === true;
766
+ (trustedMarker?.reason.startsWith(`Failed to acquire lock for ${startupLockPath} after `) === true ||
767
+ brokerStartupFailureCleanupTargetsLock(trustedMarker, `${startupLockPath}.lock`));
716
768
  if (!startupFenceContention && exitedBeforeDiscovery && child.exitCode !== 0) {
717
769
  try {
718
770
  startupFenceContention = (await fs.stat(`${startupLockPath}.lock`)).isDirectory();
@@ -760,7 +812,7 @@ async function ensureBrokerOnce(settings: EnsureBrokerSettings, initiator: Ensur
760
812
  ? new BrokerStartupError({
761
813
  exitCode: child.exitCode,
762
814
  signal: child.signalCode,
763
- reason: trustedMarker?.reason ?? "Detached SDK broker exited before publishing discovery.",
815
+ reason: brokerStartupFailureReason(trustedMarker),
764
816
  stderrExcerpt: spawnLogTail.length > 0 ? spawnLogTail : undefined,
765
817
  })
766
818
  : discoveryError
@@ -889,3 +941,8 @@ export function registerBrokerOwnerForTest(
889
941
  ): BrokerOwner {
890
942
  return registerBrokerOwner(agentDir, child, timing);
891
943
  }
944
+
945
+ /** Test hook: exercises the same trusted-marker reason reconstruction used by ensureBroker. */
946
+ export function brokerStartupFailureReasonForTest(marker: BrokerStartupFailureMarker | undefined): string {
947
+ return brokerStartupFailureReason(marker);
948
+ }
@@ -51,6 +51,19 @@ export async function deriveIdempotencyIdentity(
51
51
  .digest("hex");
52
52
  }
53
53
 
54
+ /** Native identity for an idempotency key reserved inside one managed control root. */
55
+ export async function deriveScopedIdempotencyIdentity(
56
+ agentDir: string,
57
+ operation: string,
58
+ callerKey: string,
59
+ scope: string,
60
+ ): Promise<string> {
61
+ const key = await getBrokerIdentityKey(agentDir);
62
+ return createHmac("sha256", Buffer.from(key, "hex"))
63
+ .update(JSON.stringify(["managed-spawn-v1", operation, callerKey, scope]))
64
+ .digest("hex");
65
+ }
66
+
54
67
  /** Identity format used by lifecycle rows written before target binding. */
55
68
  export async function deriveLegacyIdentity(agentDir: string, operation: string, callerKey: string): Promise<string> {
56
69
  const key = await getBrokerIdentityKey(agentDir);
@@ -711,13 +711,25 @@ export class LifecycleLedger {
711
711
  return [...this.#byIdentity.values()].findLast(entry => entry.operationKey === operationKey);
712
712
  }
713
713
  /**
714
- * Legacy target-inclusive rows predate the operation/key index. Their opaque
714
+ * Live or uncertain legacy rows predate the operation/key index. Their opaque
715
715
  * identities cannot establish that a different target is safe, so callers
716
- * must reject rather than create a second admission.
716
+ * must reject rather than create a second admission. A fresh session.create
717
+ * may ignore completed terminal legacy rows so old successful operations do
718
+ * not block coordinator startup. Other operations retain the legacy fence
719
+ * because target-bound legacy identities cannot prove key uniqueness. For
720
+ * target-bound terminal creates, the opaque legacy identity also cannot reveal
721
+ * the original caller key, so this exception retires that legacy key history;
722
+ * exact key-only legacy creates are still rejected by the earlier lookup.
717
723
  */
718
- hasLegacyIdentity(excludedIdentities?: ReadonlySet<string>): boolean {
724
+ hasLegacyIdentity(
725
+ excludedIdentities?: ReadonlySet<string>,
726
+ options: { ignoreTerminalRows?: boolean } = {},
727
+ ): boolean {
719
728
  return [...this.#byIdentity.values()].some(
720
- entry => entry.operationKey === undefined && !excludedIdentities?.has(entry.identity),
729
+ entry =>
730
+ entry.operationKey === undefined &&
731
+ !(options.ignoreTerminalRows && terminal(entry.state)) &&
732
+ !excludedIdentities?.has(entry.identity),
721
733
  );
722
734
  }
723
735
  async migrateIdentity(