@gajae-code/coding-agent 0.15.2 → 0.15.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 (107) hide show
  1. package/CHANGELOG.md +43 -1
  2. package/dist/types/config/autorouting-tier-map.d.ts +0 -9
  3. package/dist/types/config/file-lock.d.ts +7 -1
  4. package/dist/types/config/keybindings.d.ts +13 -3
  5. package/dist/types/config/model-registry.d.ts +5 -0
  6. package/dist/types/config/model-resolver.d.ts +1 -0
  7. package/dist/types/config/settings-schema.d.ts +65 -1
  8. package/dist/types/coordinator/contract.d.ts +1 -1
  9. package/dist/types/coordinator-mcp/question-state.d.ts +42 -2
  10. package/dist/types/extensibility/extensions/types.d.ts +2 -0
  11. package/dist/types/gjc-runtime/deep-interview-state.d.ts +12 -0
  12. package/dist/types/gjc-runtime/workflow-placeholder.d.ts +6 -0
  13. package/dist/types/main.d.ts +1 -1
  14. package/dist/types/modes/action-registry.d.ts +1 -0
  15. package/dist/types/modes/components/hook-selector.d.ts +1 -0
  16. package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +1 -1
  17. package/dist/types/modes/components/welcome.d.ts +2 -0
  18. package/dist/types/modes/controllers/input-controller.d.ts +16 -1
  19. package/dist/types/modes/controllers/runtime-mcp-command-controller.d.ts +42 -0
  20. package/dist/types/modes/interactive-mode.d.ts +7 -0
  21. package/dist/types/modes/shared/oauth-url-copy.d.ts +9 -0
  22. package/dist/types/modes/types.d.ts +3 -0
  23. package/dist/types/modes/ui-language.d.ts +2 -1
  24. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +1 -0
  25. package/dist/types/sdk/broker/session-index.d.ts +18 -0
  26. package/dist/types/sdk/bus/index.d.ts +4 -1
  27. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +4 -1
  28. package/dist/types/sdk/bus/telegram-daemon.d.ts +2 -0
  29. package/dist/types/sdk/cli/session-cli.d.ts +1 -1
  30. package/dist/types/sdk/lifecycle/service.d.ts +32 -5
  31. package/dist/types/sdk/session.d.ts +5 -0
  32. package/dist/types/session/agent-session.d.ts +4 -0
  33. package/dist/types/session/fallback-chain-controller.d.ts +8 -0
  34. package/dist/types/slash-commands/helpers/aside.d.ts +54 -0
  35. package/dist/types/tools/ask.d.ts +9 -0
  36. package/dist/types/utils/clipboard.d.ts +9 -1
  37. package/package.json +7 -7
  38. package/scripts/generate-sdk-adapter-parity-manifest.ts +5 -2
  39. package/scripts/generate-sdk-operation-inventory.ts +3 -0
  40. package/src/commands/sdk.ts +2 -2
  41. package/src/config/autorouting-tier-map.ts +0 -9
  42. package/src/config/file-lock.ts +15 -1
  43. package/src/config/keybindings.ts +13 -3
  44. package/src/config/model-registry.ts +132 -21
  45. package/src/config/model-resolver.ts +2 -1
  46. package/src/config/models-config-schema.ts +2 -2
  47. package/src/config/settings-schema.ts +66 -1
  48. package/src/config/settings.ts +1 -1
  49. package/src/coordinator/contract.ts +1 -0
  50. package/src/coordinator-mcp/question-state.ts +235 -4
  51. package/src/coordinator-mcp/server.ts +402 -2
  52. package/src/dap/client.ts +19 -8
  53. package/src/deep-interview/render-middleware.ts +6 -2
  54. package/src/extensibility/extensions/types.ts +2 -0
  55. package/src/gjc-runtime/deep-interview-stage.ts +20 -1
  56. package/src/gjc-runtime/deep-interview-state.ts +3 -1
  57. package/src/gjc-runtime/ralplan-runtime.ts +6 -1
  58. package/src/gjc-runtime/session-state-lock.ts +11 -2
  59. package/src/gjc-runtime/ultragoal-runtime.ts +5 -0
  60. package/src/gjc-runtime/workflow-placeholder.ts +33 -0
  61. package/src/internal-urls/docs-index.generated.ts +11 -9
  62. package/src/lsp/client.ts +39 -4
  63. package/src/main.ts +42 -11
  64. package/src/modes/action-registry.ts +7 -0
  65. package/src/modes/components/hook-selector.ts +2 -1
  66. package/src/modes/components/iterm-pet-transport.ts +4 -2
  67. package/src/modes/components/runtime-mcp-add-wizard.ts +38 -1
  68. package/src/modes/components/settings-selector.ts +1 -0
  69. package/src/modes/components/tool-status-header.ts +149 -41
  70. package/src/modes/components/welcome.ts +8 -0
  71. package/src/modes/controllers/extension-ui-controller.ts +1 -0
  72. package/src/modes/controllers/goal-mode-controller.ts +7 -2
  73. package/src/modes/controllers/input-controller.ts +141 -7
  74. package/src/modes/controllers/plan-mode-controller.ts +12 -4
  75. package/src/modes/controllers/runtime-mcp-command-controller.ts +164 -20
  76. package/src/modes/controllers/selector-controller.ts +11 -2
  77. package/src/modes/interactive-mode.ts +88 -1
  78. package/src/modes/shared/oauth-url-copy.ts +33 -0
  79. package/src/modes/types.ts +3 -0
  80. package/src/modes/ui-language.ts +44 -3
  81. package/src/runtime-mcp/oauth-flow.ts +19 -8
  82. package/src/runtime-mcp/transports/stdio.ts +27 -13
  83. package/src/sdk/acp/adapter.ts +29 -2
  84. package/src/sdk/broker/broker.ts +26 -6
  85. package/src/sdk/broker/lifecycle-ledger.ts +28 -1
  86. package/src/sdk/broker/lifecycle.ts +664 -5
  87. package/src/sdk/broker/session-index.ts +246 -0
  88. package/src/sdk/broker/transport.ts +1 -0
  89. package/src/sdk/bus/index.ts +135 -38
  90. package/src/sdk/bus/natives-augment.d.ts +20 -1
  91. package/src/sdk/bus/telegram-daemon-contract.ts +4 -1
  92. package/src/sdk/bus/telegram-daemon.ts +3 -0
  93. package/src/sdk/cli/session-cli.ts +34 -7
  94. package/src/sdk/lifecycle/service.ts +166 -11
  95. package/src/sdk/mcp/server.ts +2 -1
  96. package/src/sdk/protocol/operation-inventory.generated.json +40 -0
  97. package/src/sdk/protocol/operation-registry.ts +2 -1
  98. package/src/sdk/session.ts +91 -7
  99. package/src/session/agent-session.ts +473 -66
  100. package/src/session/fallback-chain-controller.ts +17 -0
  101. package/src/setup/frictionless-onboarding.ts +4 -4
  102. package/src/slash-commands/aside-command.test.ts +366 -0
  103. package/src/slash-commands/builtin-registry.ts +19 -0
  104. package/src/slash-commands/helpers/aside.ts +299 -0
  105. package/src/tools/ask-contract.ts +54 -3
  106. package/src/tools/ask.ts +54 -6
  107. package/src/utils/clipboard.ts +37 -28
@@ -287,18 +287,51 @@ export interface CreationRequestV1 {
287
287
  key_digest: string;
288
288
  request_digest: string;
289
289
  tool: string;
290
- phase: "claimed" | "remote_started" | "wal_committed" | "projected" | "completed" | "uncertain";
290
+ phase: "claimed" | "remote_started" | "wal_committed" | "projected" | "completed" | "uncertain" | "retired";
291
291
  canonical_create_intent: CanonicalCreateIntentV1 | null;
292
292
  remote_create_key: string;
293
293
  session_id: string | null;
294
294
  endpoint_incarnation: string | null;
295
295
  sidecar_verifier: { key_id: string; public_key: string } | null;
296
+ /** Retirement is staged before the broker effect so a post-effect crash can replay safely. */
297
+ retirement_intent?: CreationRetirementIntentV1;
296
298
  wal_revision?: number;
297
299
  wal_digest?: string;
298
300
  safe_response?: Record<string, unknown>;
299
301
  created_at: string;
300
302
  updated_at: string;
301
303
  }
304
+ export interface CreationRetirementProofV1 {
305
+ session_id: string;
306
+ cwd: string;
307
+ state_root: string;
308
+ endpoint_generation: number;
309
+ endpoint_mtime_ms: number;
310
+ process_incarnation: string;
311
+ host_incarnation: string;
312
+ lifecycle_request_id: string;
313
+ remote_create_key: string;
314
+ }
315
+ export interface CreationRetirementBrokerProofV1 {
316
+ session_id: string;
317
+ retired: true;
318
+ ledger_state: "terminal_error";
319
+ index_type: "session_closed";
320
+ state_root: string;
321
+ endpoint_generation: number;
322
+ endpoint_mtime_ms: number;
323
+ process_incarnation: string;
324
+ host_incarnation: string;
325
+ lifecycle_request_id: string;
326
+ remote_create_key: string;
327
+ }
328
+ export interface CreationRetirementIntentV1 {
329
+ phase: "intent" | "pre_effect_rejected" | "broker_retired";
330
+ proof: CreationRetirementProofV1;
331
+ retirement_key_digest?: string;
332
+ broker_proof?: CreationRetirementBrokerProofV1;
333
+ updated_at: string;
334
+ }
302
335
  export interface NamespaceDeletionEntryV1 {
303
336
  deletion_id: string;
304
337
  session_id: string;
@@ -2395,21 +2428,219 @@ export async function repairProjections(
2395
2428
  });
2396
2429
  }
2397
2430
 
2431
+ function sameCreationRetirementProof(left: CreationRetirementProofV1, right: CreationRetirementProofV1): boolean {
2432
+ return canonicalJson(left) === canonicalJson(right);
2433
+ }
2434
+
2435
+ function assertCreationRetirementProofMatches(
2436
+ request: CreationRequestV1,
2437
+ proof: CreationRetirementProofV1,
2438
+ includeStaged = true,
2439
+ ): void {
2440
+ if (
2441
+ !proof.session_id ||
2442
+ !proof.cwd ||
2443
+ !proof.state_root ||
2444
+ !Number.isSafeInteger(proof.endpoint_generation) ||
2445
+ proof.endpoint_generation <= 0 ||
2446
+ !Number.isFinite(proof.endpoint_mtime_ms) ||
2447
+ proof.endpoint_mtime_ms <= 0 ||
2448
+ !proof.process_incarnation ||
2449
+ !proof.host_incarnation ||
2450
+ !proof.lifecycle_request_id ||
2451
+ !proof.remote_create_key
2452
+ )
2453
+ throw new Error("invalid_input");
2454
+ if (request.remote_create_key !== proof.remote_create_key) throw new Error("idempotency_conflict");
2455
+ if (request.session_id !== null && request.session_id !== proof.session_id) throw new Error("idempotency_conflict");
2456
+ const intent = request.canonical_create_intent;
2457
+ if (intent) {
2458
+ const session = intent.session;
2459
+ if (
2460
+ session.session_id !== proof.session_id ||
2461
+ path.resolve(session.cwd) !== path.resolve(proof.cwd) ||
2462
+ path.resolve(session.cwd, ".gjc", "state") !== path.resolve(proof.state_root) ||
2463
+ session.broker.endpoint_generation !== proof.endpoint_generation ||
2464
+ intent.kind === "register" ||
2465
+ intent.remote_create_key !== proof.remote_create_key
2466
+ )
2467
+ throw new Error("idempotency_conflict");
2468
+ }
2469
+ const staged = includeStaged ? request.retirement_intent : undefined;
2470
+ if (staged && !sameCreationRetirementProof(staged.proof, proof)) throw new Error("idempotency_conflict");
2471
+ }
2472
+
2473
+ /** Claims retirement under the creation receipt before any broker effect. */
2474
+ export async function recordCreationRetirementIntent(
2475
+ paths: CoordinatorStatePaths,
2476
+ keyDigest: string,
2477
+ proof: CreationRetirementProofV1,
2478
+ retirementKeyDigest?: string,
2479
+ ): Promise<CreationRequestV1> {
2480
+ return await withNamespaceRegistry(paths, async registry => {
2481
+ const request = registry.creations[keyDigest];
2482
+ if (!request) throw new Error("state_corrupt");
2483
+ if (request.phase !== "remote_started" && request.phase !== "uncertain" && request.phase !== "retired")
2484
+ throw new Error("retire_not_allowed");
2485
+ assertCreationRetirementProofMatches(request, proof, request.retirement_intent?.phase !== "pre_effect_rejected");
2486
+ if (
2487
+ request.retirement_intent?.phase !== "pre_effect_rejected" &&
2488
+ retirementKeyDigest &&
2489
+ request.retirement_intent?.retirement_key_digest &&
2490
+ request.retirement_intent.retirement_key_digest !== retirementKeyDigest
2491
+ )
2492
+ throw new Error("idempotency_conflict");
2493
+ if (!request.retirement_intent) {
2494
+ request.retirement_intent = {
2495
+ phase: "intent",
2496
+ proof,
2497
+ ...(retirementKeyDigest ? { retirement_key_digest: retirementKeyDigest } : {}),
2498
+ updated_at: new Date().toISOString(),
2499
+ };
2500
+ request.updated_at = new Date().toISOString();
2501
+ } else if (request.retirement_intent.phase === "pre_effect_rejected") {
2502
+ request.retirement_intent.phase = "intent";
2503
+ request.retirement_intent.proof = proof;
2504
+ if (retirementKeyDigest) request.retirement_intent.retirement_key_digest = retirementKeyDigest;
2505
+ request.retirement_intent.updated_at = new Date().toISOString();
2506
+ request.updated_at = request.retirement_intent.updated_at;
2507
+ } else if (retirementKeyDigest && !request.retirement_intent.retirement_key_digest) {
2508
+ request.retirement_intent.retirement_key_digest = retirementKeyDigest;
2509
+ request.retirement_intent.updated_at = new Date().toISOString();
2510
+ request.updated_at = new Date().toISOString();
2511
+ }
2512
+ return request;
2513
+ });
2514
+ }
2515
+
2516
+ /** Replaces only a pre-effect retirement proof after an explicit broker rejection. */
2517
+ export async function replaceCreationRetirementIntent(
2518
+ paths: CoordinatorStatePaths,
2519
+ keyDigest: string,
2520
+ proof: CreationRetirementProofV1,
2521
+ retirementKeyDigest: string,
2522
+ ): Promise<CreationRequestV1> {
2523
+ return await withNamespaceRegistry(paths, async registry => {
2524
+ const request = registry.creations[keyDigest];
2525
+ if (!request) throw new Error("state_corrupt");
2526
+ if (request.phase !== "remote_started" && request.phase !== "uncertain" && request.phase !== "retired")
2527
+ throw new Error("retire_not_allowed");
2528
+ const staged = request.retirement_intent;
2529
+ if (!staged || staged.phase !== "intent" || staged.broker_proof) throw new Error("state_corrupt");
2530
+ if (staged.retirement_key_digest !== retirementKeyDigest) throw new Error("idempotency_conflict");
2531
+ assertCreationRetirementProofMatches(request, proof, false);
2532
+ staged.phase = "pre_effect_rejected";
2533
+ staged.updated_at = new Date().toISOString();
2534
+ request.updated_at = staged.updated_at;
2535
+ return request;
2536
+ });
2537
+ }
2538
+
2539
+ /** Records the bounded broker proof before receipt advancement or idempotency sealing. */
2540
+ export async function recordCreationRetirementBrokerProof(
2541
+ paths: CoordinatorStatePaths,
2542
+ keyDigest: string,
2543
+ proof: CreationRetirementProofV1,
2544
+ brokerProof: CreationRetirementBrokerProofV1,
2545
+ ): Promise<CreationRequestV1> {
2546
+ return await withNamespaceRegistry(paths, async registry => {
2547
+ const request = registry.creations[keyDigest];
2548
+ if (!request) throw new Error("state_corrupt");
2549
+ if (request.phase !== "remote_started" && request.phase !== "uncertain" && request.phase !== "retired")
2550
+ throw new Error("retire_not_allowed");
2551
+ assertCreationRetirementProofMatches(request, proof);
2552
+ if (
2553
+ brokerProof.session_id !== proof.session_id ||
2554
+ brokerProof.state_root !== proof.state_root ||
2555
+ brokerProof.endpoint_generation !== proof.endpoint_generation ||
2556
+ brokerProof.endpoint_mtime_ms !== proof.endpoint_mtime_ms ||
2557
+ brokerProof.process_incarnation !== proof.process_incarnation ||
2558
+ brokerProof.host_incarnation !== proof.host_incarnation ||
2559
+ brokerProof.lifecycle_request_id !== proof.lifecycle_request_id ||
2560
+ brokerProof.remote_create_key !== proof.remote_create_key ||
2561
+ brokerProof.retired !== true ||
2562
+ brokerProof.ledger_state !== "terminal_error" ||
2563
+ brokerProof.index_type !== "session_closed"
2564
+ )
2565
+ throw new Error("protocol_error");
2566
+ const staged = request.retirement_intent;
2567
+ if (staged?.broker_proof) {
2568
+ if (canonicalJson(staged.broker_proof) !== canonicalJson(brokerProof)) throw new Error("state_corrupt");
2569
+ return request;
2570
+ }
2571
+ if (!staged) {
2572
+ request.retirement_intent = {
2573
+ phase: "broker_retired",
2574
+ proof,
2575
+ broker_proof: brokerProof,
2576
+ updated_at: new Date().toISOString(),
2577
+ };
2578
+ } else {
2579
+ staged.phase = "broker_retired";
2580
+ staged.broker_proof = brokerProof;
2581
+ staged.updated_at = new Date().toISOString();
2582
+ }
2583
+ request.updated_at = new Date().toISOString();
2584
+ return request;
2585
+ });
2586
+ }
2587
+
2398
2588
  /** Advances a creation receipt only after its WAL or projection authority exists. */
2589
+ export async function assertCreationRetirementIdentity(
2590
+ paths: CoordinatorStatePaths,
2591
+ keyDigest: string,
2592
+ proof: CreationRetirementProofV1,
2593
+ ): Promise<CreationRequestV1> {
2594
+ return await withNamespaceRegistry(paths, async registry => {
2595
+ const request = registry.creations[keyDigest];
2596
+ if (!request) throw new Error("state_corrupt");
2597
+ if (request.phase !== "remote_started" && request.phase !== "uncertain" && request.phase !== "retired")
2598
+ throw new Error("retire_not_allowed");
2599
+ assertCreationRetirementProofMatches(request, proof, request.retirement_intent?.phase !== "pre_effect_rejected");
2600
+ return request;
2601
+ });
2602
+ }
2603
+
2399
2604
  export async function advanceCreationReceipt(
2400
2605
  paths: CoordinatorStatePaths,
2401
2606
  keyDigest: string,
2402
- phase: "projected" | "completed" | "uncertain",
2607
+ phase: "projected" | "completed" | "uncertain" | "retired",
2403
2608
  safeResponse?: Record<string, unknown>,
2609
+ proof?: CreationRetirementProofV1,
2404
2610
  ): Promise<void> {
2405
2611
  await withNamespaceRegistry(paths, async registry => {
2406
2612
  const request = registry.creations[keyDigest];
2407
2613
  if (!request) throw new Error("state_corrupt");
2408
- if (request.phase === phase) return;
2409
- if (phase !== "uncertain" && request.phase !== "wal_committed" && request.phase !== "projected")
2614
+ if (proof) assertCreationRetirementProofMatches(request, proof);
2615
+ if (request.phase === phase) {
2616
+ if (phase === "retired" && safeResponse) {
2617
+ request.safe_response = safeResponse;
2618
+ if (request.retirement_intent) request.retirement_intent.updated_at = new Date().toISOString();
2619
+ request.updated_at = new Date().toISOString();
2620
+ }
2621
+ return;
2622
+ }
2623
+ if (
2624
+ phase === "retired" &&
2625
+ (request.phase === "completed" || request.phase === "retired" || request.phase === "claimed")
2626
+ )
2627
+ throw new Error("state_corrupt");
2628
+ if (
2629
+ phase !== "uncertain" &&
2630
+ phase !== "retired" &&
2631
+ request.phase !== "wal_committed" &&
2632
+ request.phase !== "projected"
2633
+ )
2410
2634
  throw new Error("state_corrupt");
2411
2635
  request.phase = phase;
2412
2636
  request.safe_response = safeResponse;
2637
+ if (phase === "retired" && proof && !request.retirement_intent) {
2638
+ request.retirement_intent = {
2639
+ phase: "intent",
2640
+ proof,
2641
+ updated_at: new Date().toISOString(),
2642
+ };
2643
+ }
2413
2644
  request.updated_at = new Date().toISOString();
2414
2645
  });
2415
2646
  }