@gajae-code/coding-agent 0.11.2 → 0.11.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 (101) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/types/cli/launch-disposition.d.ts +23 -0
  3. package/dist/types/cli/worktree-cli.d.ts +8 -25
  4. package/dist/types/commands/gc.d.ts +4 -0
  5. package/dist/types/commands/worktree.d.ts +7 -32
  6. package/dist/types/config/settings-schema.d.ts +85 -10
  7. package/dist/types/gjc-runtime/gc-runtime.d.ts +9 -0
  8. package/dist/types/gjc-runtime/state-argv.d.ts +38 -0
  9. package/dist/types/main.d.ts +1 -0
  10. package/dist/types/modes/components/custom-editor.d.ts +8 -3
  11. package/dist/types/modes/components/tool-transcript-format.d.ts +19 -0
  12. package/dist/types/modes/controllers/input-controller.d.ts +8 -2
  13. package/dist/types/modes/prompt-action-autocomplete.d.ts +4 -0
  14. package/dist/types/sdk/broker/broker.d.ts +1 -0
  15. package/dist/types/sdk/broker/discovery.d.ts +10 -0
  16. package/dist/types/sdk/broker/ensure.d.ts +24 -1
  17. package/dist/types/sdk/broker/internal.d.ts +3 -0
  18. package/dist/types/sdk/broker/session-index.d.ts +12 -0
  19. package/dist/types/sdk/broker/state-version.d.ts +2 -1
  20. package/dist/types/sdk/bus/index.d.ts +2 -0
  21. package/dist/types/sdk/session.d.ts +2 -0
  22. package/dist/types/tools/ask.d.ts +39 -12
  23. package/dist/types/tools/browser/screenshot-format.d.ts +8 -0
  24. package/dist/types/tools/browser/tab-protocol.d.ts +11 -0
  25. package/dist/types/tools/browser/tab-supervisor.d.ts +1 -1
  26. package/dist/types/tools/browser/tab-worker-path-resolver.d.ts +2 -0
  27. package/dist/types/tools/browser/tab-worker-smoke.d.ts +16 -0
  28. package/dist/types/tools/path-utils.d.ts +9 -14
  29. package/dist/types/tools/read.d.ts +2 -0
  30. package/dist/types/tools/render-utils.d.ts +1 -8
  31. package/dist/types/tools/resource-gc.d.ts +14 -0
  32. package/dist/types/tools/subagent.d.ts +1 -0
  33. package/dist/types/utils/file-mentions.d.ts +3 -3
  34. package/dist/types/utils/image-loading.d.ts +23 -0
  35. package/dist/types/utils/image-resize.d.ts +2 -0
  36. package/dist/types/utils/pasted-image-loading.d.ts +39 -0
  37. package/dist/types/utils/pasted-image-path.d.ts +21 -19
  38. package/dist/types/web/scrapers/html-to-markdown.d.ts +5 -0
  39. package/dist/types/web/scrapers/types.d.ts +1 -5
  40. package/package.json +24 -8
  41. package/scripts/run-threat-model-check.ts +60 -0
  42. package/src/cli/launch-disposition.ts +42 -0
  43. package/src/cli/worktree-cli.ts +9 -287
  44. package/src/cli.ts +10 -9
  45. package/src/commands/gc.ts +11 -1
  46. package/src/commands/sdk.ts +3 -2
  47. package/src/commands/worktree.ts +10 -53
  48. package/src/config/model-profiles.ts +15 -15
  49. package/src/config/settings-schema.ts +55 -10
  50. package/src/eval/js/shared/runtime.ts +1 -1
  51. package/src/gjc-runtime/gc-render.ts +19 -1
  52. package/src/gjc-runtime/gc-runtime.ts +68 -3
  53. package/src/gjc-runtime/state-argv.ts +292 -0
  54. package/src/gjc-runtime/state-runtime.ts +51 -212
  55. package/src/main.ts +99 -22
  56. package/src/modes/components/custom-editor.ts +103 -32
  57. package/src/modes/components/custom-provider-wizard.ts +26 -1
  58. package/src/modes/components/session-observer-overlay.ts +10 -23
  59. package/src/modes/components/tool-transcript-format.ts +72 -0
  60. package/src/modes/components/transcript-viewer-overlay.ts +42 -2
  61. package/src/modes/controllers/input-controller.ts +98 -37
  62. package/src/modes/controllers/selector-controller.ts +1 -1
  63. package/src/modes/interactive-mode.ts +13 -2
  64. package/src/modes/prompt-action-autocomplete.ts +7 -0
  65. package/src/sdk/broker/broker.ts +139 -32
  66. package/src/sdk/broker/discovery.ts +125 -0
  67. package/src/sdk/broker/ensure.ts +103 -19
  68. package/src/sdk/broker/internal.ts +10 -0
  69. package/src/sdk/broker/session-index.ts +228 -15
  70. package/src/sdk/broker/state-version.ts +5 -2
  71. package/src/sdk/bus/index.ts +4 -1
  72. package/src/sdk/bus/telegram-daemon.ts +50 -10
  73. package/src/sdk/host/host.ts +13 -1
  74. package/src/sdk/session.ts +4 -1
  75. package/src/session/internal/managed-session-scope.ts +15 -1
  76. package/src/tools/ask.ts +216 -41
  77. package/src/tools/bash-allowed-prefixes.ts +79 -29
  78. package/src/tools/browser/launch.ts +3 -1
  79. package/src/tools/browser/readable.ts +1 -1
  80. package/src/tools/browser/screenshot-format.ts +34 -0
  81. package/src/tools/browser/tab-protocol.ts +3 -0
  82. package/src/tools/browser/tab-supervisor.ts +125 -122
  83. package/src/tools/browser/tab-worker-entry.ts +33 -14
  84. package/src/tools/browser/tab-worker-path-resolver.ts +67 -0
  85. package/src/tools/browser/tab-worker-smoke.ts +87 -0
  86. package/src/tools/browser/tab-worker.ts +7 -5
  87. package/src/tools/output-meta.ts +6 -2
  88. package/src/tools/path-utils.ts +42 -35
  89. package/src/tools/read.ts +189 -64
  90. package/src/tools/render-utils.ts +1 -27
  91. package/src/tools/resource-gc.ts +123 -34
  92. package/src/tools/subagent.ts +43 -2
  93. package/src/utils/file-mentions.ts +4 -4
  94. package/src/utils/image-loading.ts +85 -34
  95. package/src/utils/image-resize.ts +16 -9
  96. package/src/utils/pasted-image-loading.ts +514 -0
  97. package/src/utils/pasted-image-path.ts +223 -98
  98. package/src/web/scrapers/html-to-markdown.ts +68 -0
  99. package/src/web/scrapers/readthedocs.ts +1 -1
  100. package/src/web/scrapers/types.ts +1 -68
  101. package/src/web/search/providers/openai-compatible.ts +76 -23
package/CHANGELOG.md CHANGED
@@ -2,6 +2,40 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.11.4] - 2026-07-20
6
+ ### Added
7
+ - Bracketed pastes containing complete lists of saved static-image paths can now attach up to 16 images in source order after explicit confirmation. Paste transactions are cancellation-safe, disabled in command modes, enforce source, encoded-output, dimension, and decoded-memory budgets before commit, reject animated, remote, linked, or path-swapped sources, and restore the literal paste on cancellation or failure.
8
+ - Rich tool-call rendering in the transcript viewer: both the session-observer and main-session transcript viewers now share one formatter so tool calls render identically (args summary + intent, then a result block with ✓ done / ✗ error / ⏳ pending states). Fixes a latent bug where a tool call with no result rendered as a false "✓ done"; expanded results cap at 100 source lines with raw/copy exposing the full text (#2656).
9
+
10
+ ### Changed
11
+ - Updated the Kimi Coding Plan Eco, Medium, and Pro presets to Kimi K3 with its supported `low`, `high`, and `max` reasoning efforts.
12
+
13
+ ### Removed
14
+ - Removed the legacy worktree cleanup implementation behind the `@gajae-code/coding-agent/cli/worktree-cli` and `@gajae-code/coding-agent/commands/worktree` package subpaths (base and `.js` forms). The `gjc worktree`/`wt` CLI command has been unregistered since the workflow-surface narrowing; the modules behind it (including the recursive-deletion `clear` path) were only reachable as package imports. The subpaths now resolve to throwing tombstone modules whose error explains the deliberate removal and the supported replacement: inspect leftover managed worktrees under `~/.gjc/wt` manually and use `git worktree remove` / `git worktree prune`.
15
+
16
+ ### Fixed
17
+ - Telegram `/btw` rich-delivery E2E coverage now awaits native and daemon teardown ownership, records exact per-iteration lifecycle phases, and uses an internal exact-tuple terminal-delivery receipt to keep fallback stress deterministic under shard load without extending the original test timeout.
18
+ - Malformed spurious Round-0 review metadata no longer blocks an otherwise valid locked-intent question/gate, while durable intent safety remains fail-closed (#2643).
19
+ - Restricted role-agent `gjc state` command authorization now fails closed on argv-classification disagreement: one shared manifest-aware native state argv grammar (action names, flag arity, positionals, effective modifiers, selector candidates) is consumed by both runtime dispatch and the policy boundary, which rejects ambiguous selectors, malformed flags, destructive actions, and file-backed input (#2665).
20
+ - Browser tab workers now bootstrap through their actual isolated entry without accidentally loading native bindings through broad imports, and startup fails closed instead of falling back to unguarded inline execution; compiled/package smoke now exercises the tab worker, with a PR-head darwin-arm64 CI gate (#2598).
21
+ - Added evidence-preserving recovery for legacy multi-writer SDK session-index corruption: `gjc gc` now diagnoses corrupt prefixes, `--repair-session-index` quarantines the original snapshot/log under the session-index lock before atomically restoring only the checksum-valid monotonic prefix, and append failures point operators to the explicit repair path (#2654).
22
+ - Malformed selectors on internal read URLs now fail explicitly instead of silently falling back to an unbounded resource read.
23
+ - Newly registered earlier resource-GC policies advance the pending sweep without postponing an already earlier sweep.
24
+ - Provider onboarding wizard completion is now deterministic under CI load: duplicate in-flight confirmation is suppressed, success tests await the real refresh/notification/status boundary instead of fixed sleeps, and the newly configured model is verified through the subsequent model selector.
25
+ - OpenAI-compatible web search now turns malformed successful response bodies into bounded provider errors while preserving normal provider fallback (#2593).
26
+ - Windows session storage now keeps a symlink-resolved drive-letter path for Bun filesystem I/O instead of a native Volume GUID identity path, preventing `ENOENT` failures during resident-cache writes that could drop the final assistant message at turn completion.
27
+ - On platforms with verified retained publication identity support, detached SDK broker processes now stop after durable loss or replacement of their owned publication while preserving warm reuse and protocol/state formats (#2583). Bounded-practical limitation: requests admitted before the first definitive loss observation—or after authoritative same-object recovery and before a later loss observation—may still perform pathname-based index, ledger, lifecycle, cleanup, or child effects. A detached session-host child spawned by an admitted request may outlive broker exit and may continue pathname effects for the session lifetime. Broker self-reap does not cancel or signal that child and does not provide absolute hostile replacement isolation.
28
+
29
+ ## [0.11.3] - 2026-07-19
30
+
31
+ ### Changed
32
+ - The `read` tool is now receipt-by-default: bare and unparseable reads return a bounded receipt (≤50 lines / 10 KiB) with a re-read-with-selector footer only when truncated, `:raw` stays pure verbatim up to a max(2 MiB, spill threshold) ceiling, structural summaries cap unit-granularly at 20 KiB while preserving elision and source-recovery footers, and directories are byte/line capped and never spill. Only an explicit full-content selector (`:raw` or an explicit range) with real content is spill-eligible. Subagent previews now enforce a real byte/code-point cap via per-shape render budgets plus a shape-aware artifact-eligibility tag enforced centrally in output-meta.
33
+
34
+ ### Fixed
35
+ - Workflow-state handoff no longer self-locks the active-state cache, so a same-turn skill handoff (e.g. ultragoal → ralplan) completes instead of stalling behind a lock the handoff itself still holds (#2638).
36
+ - SDK host shutdown now retries a failed broker unregister instead of short-circuiting with a stale broker-index entry, while retained startup-cleanup owner-release failures remain isolated from the red extension-error path (#2625).
37
+ - Non-TTY launches now fail fast when stdin is empty and automatically use print mode for positional prompts and `@file` inputs, preventing orphaned interactive TUI processes (#2507).
38
+
5
39
  ## [0.11.2] - 2026-07-19
6
40
 
7
41
  ### Changed
@@ -0,0 +1,23 @@
1
+ export type LaunchMode = "text" | "json" | "acp";
2
+ export interface LaunchDisposition {
3
+ autoPrint: boolean;
4
+ isInteractive: boolean;
5
+ /** Set when an interactive launch is impossible (non-TTY stdin, nothing to run). */
6
+ nonInteractiveError?: string;
7
+ }
8
+ /**
9
+ * Decides between interactive, auto-print, and fail-fast launches.
10
+ *
11
+ * A non-TTY stdin means the TUI can never receive input, so an interactive
12
+ * launch would execute the initial prompt and then block in the event loop
13
+ * forever. Prepared command-line input degrades to print mode; without any
14
+ * input to run we fail fast instead of hanging. Explicit `--print` and
15
+ * `--mode` launches are left untouched.
16
+ */
17
+ export declare function resolveLaunchDisposition(args: {
18
+ stdinIsTTY: boolean | undefined;
19
+ pipedInput: string | undefined;
20
+ hasPreparedInput: boolean;
21
+ print: boolean;
22
+ mode: LaunchMode | undefined;
23
+ }): LaunchDisposition;
@@ -1,26 +1,9 @@
1
- type WorktreeKind = "pr-checkout" | "task-isolation" | "empty" | "stray";
2
- export interface WorktreeEntry {
3
- /** Absolute path to the worktree dir (or stray container) under `~/.gjc/wt/`. */
4
- path: string;
5
- /** Classification of what we found on disk. */
6
- kind: WorktreeKind;
7
- /** Parent repo root, when this is a registered git worktree. */
8
- parentRepo?: string;
9
- /** Branch name extracted from the parent's tracking file, when available. */
10
- branch?: string;
11
- /** When set, the entry is unhealthy and `gjc worktree clear` will remove it. */
12
- orphanReason?: string;
13
- }
14
- export interface ListWorktreesOptions {
15
- json: boolean;
16
- }
17
- export interface ClearWorktreesOptions {
18
- /** Remove every entry, including live PR-checkout worktrees. */
19
- all: boolean;
20
- /** Print what would be removed without touching the filesystem. */
21
- dryRun: boolean;
22
- json: boolean;
23
- }
24
- export declare function listWorktrees(options: ListWorktreesOptions): Promise<void>;
25
- export declare function clearWorktrees(options: ClearWorktreesOptions): Promise<void>;
1
+ /**
2
+ * Tombstone for the removed legacy worktree cleanup API.
3
+ *
4
+ * The recursive-deletion implementation that previously lived here
5
+ * (`listWorktrees`/`clearWorktrees`) was deliberately removed and does not
6
+ * come back through this subpath. This module exists only to fail imports
7
+ * with actionable migration guidance.
8
+ */
26
9
  export {};
@@ -20,6 +20,10 @@ export default class Gc extends Command {
20
20
  description: string;
21
21
  default: boolean;
22
22
  };
23
+ "repair-session-index": import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
24
+ description: string;
25
+ default: boolean;
26
+ };
23
27
  };
24
28
  static examples: string[];
25
29
  run(): Promise<void>;
@@ -1,34 +1,9 @@
1
1
  /**
2
- * List and clean up agent-managed git worktrees under `~/.gjc/wt`.
2
+ * Tombstone for the removed legacy `worktree` CLI command module.
3
+ *
4
+ * The `gjc worktree`/`wt` command was unregistered during the
5
+ * workflow-surface narrowing and its implementation was deliberately
6
+ * removed. This module exists only to fail imports with actionable
7
+ * migration guidance.
3
8
  */
4
- import { Command } from "@gajae-code/utils/cli";
5
- export default class Worktree extends Command {
6
- static description: string;
7
- static aliases: string[];
8
- static args: {
9
- action: import("@gajae-code/utils/cli").ArgDescriptor & {
10
- description: string;
11
- required: false;
12
- options: string[];
13
- default: string;
14
- };
15
- };
16
- static flags: {
17
- all: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
18
- description: string;
19
- default: boolean;
20
- };
21
- "dry-run": import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
22
- char: string;
23
- description: string;
24
- default: boolean;
25
- };
26
- json: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
27
- char: string;
28
- description: string;
29
- default: boolean;
30
- };
31
- };
32
- static examples: string[];
33
- run(): Promise<void>;
34
- }
9
+ export {};
@@ -662,15 +662,15 @@ export declare const SETTINGS_SCHEMA: {
662
662
  };
663
663
  readonly "tools.readArtifactSpillThreshold": {
664
664
  readonly type: "number";
665
- readonly default: 0;
665
+ readonly default: 256;
666
666
  readonly ui: {
667
667
  readonly tab: "tools";
668
- readonly label: "Experimental read-tool artifact spill threshold (KB)";
669
- readonly description: "Advanced opt-in only: combined-size cap for `read` output across all requested ranges. Above this the full output is saved as an artifact and a bounded head+tail snippet is kept inline. Live layofflabs/gpt-5.5 medium evidence on 2026-07-07 found no token savings and a lower cache-hit rate at 50 KB, so normal coding sessions should leave this Off unless intentionally measuring large-read behavior.";
668
+ readonly label: "Read artifact spill threshold (KB)";
669
+ readonly description: "Explicit large reads above this combined size are saved as an artifact with a bounded head-and-tail snippet inline. Bare reads, directories, and converted-document receipts remain inline.";
670
670
  readonly options: readonly [{
671
671
  readonly value: "0";
672
672
  readonly label: "Off";
673
- readonly description: "Default; no read-specific spill (backstop only)";
673
+ readonly description: "No read-specific spill (backstop only)";
674
674
  }, {
675
675
  readonly value: "50";
676
676
  readonly label: "50 KB";
@@ -682,7 +682,7 @@ export declare const SETTINGS_SCHEMA: {
682
682
  }, {
683
683
  readonly value: "256";
684
684
  readonly label: "256 KB";
685
- readonly description: "~64K tokens";
685
+ readonly description: "Default; ~64K tokens";
686
686
  }, {
687
687
  readonly value: "512";
688
688
  readonly label: "512 KB";
@@ -696,11 +696,11 @@ export declare const SETTINGS_SCHEMA: {
696
696
  };
697
697
  readonly "tools.fileMentionInlineBytes": {
698
698
  readonly type: "number";
699
- readonly default: 20;
699
+ readonly default: 10;
700
700
  readonly ui: {
701
701
  readonly tab: "tools";
702
702
  readonly label: "File-mention inline cap (KB)";
703
- readonly description: "Inline byte cap for auto-read `@path` file mentions, deliberately below the read-tool cap so an incidental mention injects a smaller snippet than an explicit read. The full file is still available via the read tool.";
703
+ readonly description: "Inline byte cap for auto-read `@path` file mentions, aligned with the 10 KiB bare-read receipt so incidental mentions stay within the same bounded context budget. The full file is still available via the read tool.";
704
704
  readonly options: readonly [{
705
705
  readonly value: "5";
706
706
  readonly label: "5 KB";
@@ -708,15 +708,15 @@ export declare const SETTINGS_SCHEMA: {
708
708
  }, {
709
709
  readonly value: "10";
710
710
  readonly label: "10 KB";
711
- readonly description: "~2.5K tokens";
711
+ readonly description: "Default; ~2.5K tokens";
712
712
  }, {
713
713
  readonly value: "20";
714
714
  readonly label: "20 KB";
715
- readonly description: "Default; ~5K tokens";
715
+ readonly description: "~5K tokens";
716
716
  }, {
717
717
  readonly value: "50";
718
718
  readonly label: "50 KB";
719
- readonly description: "~12.5K tokens (matches read cap)";
719
+ readonly description: "~12.5K tokens (matches bare-read receipt)";
720
720
  }];
721
721
  };
722
722
  };
@@ -2437,6 +2437,81 @@ export declare const SETTINGS_SCHEMA: {
2437
2437
  }];
2438
2438
  };
2439
2439
  };
2440
+ readonly "read.receiptBudgetLines": {
2441
+ readonly type: "number";
2442
+ readonly default: 50;
2443
+ readonly ui: {
2444
+ readonly tab: "editing";
2445
+ readonly label: "Read Receipt Line Budget";
2446
+ readonly description: "Maximum lines included in a bare read receipt before a selector footer is shown";
2447
+ readonly options: readonly [{
2448
+ readonly value: "25";
2449
+ readonly label: "25 lines";
2450
+ }, {
2451
+ readonly value: "50";
2452
+ readonly label: "50 lines";
2453
+ readonly description: "Default";
2454
+ }, {
2455
+ readonly value: "100";
2456
+ readonly label: "100 lines";
2457
+ }, {
2458
+ readonly value: "200";
2459
+ readonly label: "200 lines";
2460
+ }];
2461
+ };
2462
+ };
2463
+ readonly "read.receiptBudgetBytes": {
2464
+ readonly type: "number";
2465
+ readonly default: 10;
2466
+ readonly ui: {
2467
+ readonly tab: "editing";
2468
+ readonly label: "Read Receipt Byte Budget (KB)";
2469
+ readonly description: "Maximum UTF-8 body size for a bare read receipt before a selector footer is shown";
2470
+ readonly options: readonly [{
2471
+ readonly value: "5";
2472
+ readonly label: "5 KB";
2473
+ readonly description: "~1.25K tokens";
2474
+ }, {
2475
+ readonly value: "10";
2476
+ readonly label: "10 KB";
2477
+ readonly description: "Default; ~2.5K tokens";
2478
+ }, {
2479
+ readonly value: "20";
2480
+ readonly label: "20 KB";
2481
+ readonly description: "~5K tokens";
2482
+ }, {
2483
+ readonly value: "50";
2484
+ readonly label: "50 KB";
2485
+ readonly description: "~12.5K tokens";
2486
+ }];
2487
+ };
2488
+ };
2489
+ readonly "read.summaryMaxBytes": {
2490
+ readonly type: "number";
2491
+ readonly default: 20;
2492
+ readonly ui: {
2493
+ readonly tab: "editing";
2494
+ readonly label: "Read Summary Size Budget (KB)";
2495
+ readonly description: "Maximum UTF-8 size for a structural read summary before additional units are elided";
2496
+ readonly options: readonly [{
2497
+ readonly value: "10";
2498
+ readonly label: "10 KB";
2499
+ readonly description: "~2.5K tokens";
2500
+ }, {
2501
+ readonly value: "20";
2502
+ readonly label: "20 KB";
2503
+ readonly description: "Default; ~5K tokens";
2504
+ }, {
2505
+ readonly value: "50";
2506
+ readonly label: "50 KB";
2507
+ readonly description: "~12.5K tokens";
2508
+ }, {
2509
+ readonly value: "100";
2510
+ readonly label: "100 KB";
2511
+ readonly description: "~25K tokens";
2512
+ }];
2513
+ };
2514
+ };
2440
2515
  readonly "read.summarize.enabled": {
2441
2516
  readonly type: "boolean";
2442
2517
  readonly default: true;
@@ -95,11 +95,20 @@ export interface GcCounts {
95
95
  failed: number;
96
96
  }>;
97
97
  }
98
+ export interface GcSessionIndexHealth {
99
+ status: "healthy" | "corrupt" | "repaired" | "unsupported" | "repair_failed";
100
+ valid_prefix_seq: number;
101
+ snapshot_seq?: number;
102
+ reason?: string;
103
+ quarantine_path?: string;
104
+ }
98
105
  export interface GcReport {
99
106
  dry_run: boolean;
107
+ operation?: "dry_run" | "prune" | "repair_session_index";
100
108
  stores: Record<GcStore, GcRecord[]>;
101
109
  counts: GcCounts;
102
110
  errors: GcError[];
111
+ session_index?: GcSessionIndexHealth;
103
112
  }
104
113
  export interface GcRunResult {
105
114
  stdout: string;
@@ -0,0 +1,38 @@
1
+ export type StateAction = "read" | "write" | "clear" | "contract" | "handoff" | "graph" | "prune" | "gc" | "migrate" | "status" | "doctor";
2
+ export declare const STATE_ACTION_NAMES: ReadonlySet<StateAction>;
3
+ export declare const STATE_FLAGS_WITH_VALUES: ReadonlySet<string>;
4
+ export declare const STATE_BOOLEAN_FLAGS: ReadonlySet<string>;
5
+ export interface StateFlagOccurrence {
6
+ name: string;
7
+ index: number;
8
+ value?: string;
9
+ arity: "boolean" | "value";
10
+ form: "separate" | "attached";
11
+ malformed: boolean;
12
+ }
13
+ export interface StateSelectorCandidate {
14
+ source: "mode" | "positional" | "input.mode" | "input.skill";
15
+ value: string | undefined;
16
+ index: number;
17
+ }
18
+ export type StateInputKind = "empty" | "inline" | "file" | "invalid";
19
+ export interface StateInputClassification {
20
+ index: number;
21
+ raw: string;
22
+ kind: StateInputKind;
23
+ selectors: StateSelectorCandidate[];
24
+ }
25
+ export interface StateArgvClassification {
26
+ argv: readonly string[];
27
+ action: StateAction;
28
+ effectiveAction: StateAction;
29
+ positionalSkill?: string;
30
+ positionals: readonly string[];
31
+ flags: readonly StateFlagOccurrence[];
32
+ unknownFlags: readonly string[];
33
+ inputs: readonly StateInputClassification[];
34
+ runtimeSelectorCandidates: readonly StateSelectorCandidate[];
35
+ selectorCandidates: readonly StateSelectorCandidate[];
36
+ }
37
+ export declare function firstStateFlagValue(classification: StateArgvClassification, name: string): string | undefined;
38
+ export declare function classifyStateArgv(argv: readonly string[]): StateArgvClassification;
@@ -118,6 +118,7 @@ export interface RunRootCommandDependencies {
118
118
  };
119
119
  initTheme?: typeof initTheme;
120
120
  readPipedInput?: typeof readPipedInput;
121
+ stdinIsTTY?: boolean;
121
122
  runStartupCredentialAutoImportIfNeeded?: typeof runStartupCredentialAutoImportIfNeeded;
122
123
  getChangelogForDisplay?: typeof getChangelogForDisplay;
123
124
  createInteractiveMode?: CreateInteractiveMode;
@@ -2,6 +2,11 @@ import { Editor, type KeyId } from "@gajae-code/tui";
2
2
  import { type AppKeybinding } from "../../config/keybindings";
3
3
  type ConfigurableEditorAction = Extract<AppKeybinding, "app.interrupt" | "app.clear" | "app.exit" | "app.suspend" | "app.thinking.cycle" | "app.commandPalette.open" | "app.model.cycleForward" | "app.model.cycleBackward" | "app.model.select" | "app.model.selectTemporary" | "app.tools.expand" | "app.thinking.toggle" | "app.editor.external" | "app.history.search" | "app.message.dequeue" | "app.message.followUp" | "app.message.queue" | "app.clipboard.pasteImage" | "app.clipboard.copyPrompt">;
4
4
  type PastePendingClearReason = "timeout" | "queue-limit";
5
+ export interface PasteTextContext {
6
+ readonly signal: AbortSignal;
7
+ /** Run one synchronous composer mutation only while this paste transaction is current. */
8
+ commit(commit: () => boolean): boolean;
9
+ }
5
10
  /**
6
11
  * Custom editor that handles configurable app-level shortcuts for coding-agent.
7
12
  */
@@ -35,9 +40,9 @@ export declare class CustomEditor extends Editor {
35
40
  /** Called when the configured image-paste shortcut is pressed. */
36
41
  onPasteImage?: () => Promise<boolean>;
37
42
  /** Called before bracketed paste content is inserted. Return true to consume it. */
38
- onPasteText?: (text: string) => boolean | Promise<boolean>;
39
- /** Called when async paste handling drops queued input instead of replaying it. */
40
- onPastePendingInputCleared?: (reason: PastePendingClearReason, droppedInputCount: number) => void;
43
+ onPasteText?: (text: string, context: PasteTextContext) => boolean | Promise<boolean>;
44
+ /** Called when pending paste handling is cancelled after restoring queued input. */
45
+ onPastePendingInputCleared?: (reason: PastePendingClearReason, restoredInputCount: number) => void;
41
46
  /** Called when the configured dequeue shortcut is pressed. */
42
47
  onDequeue?: () => void;
43
48
  /** Called when the configured queue shortcut is pressed. */
@@ -0,0 +1,19 @@
1
+ export declare const MAX_TOOL_ARGS_CHARS = 500;
2
+ export declare const TOOL_RESULT_MAX_EXPANDED_LINES = 100;
3
+ type ToolCallFields = {
4
+ name: string;
5
+ args: Record<string, unknown>;
6
+ intent?: string;
7
+ };
8
+ type ToolResultFields = {
9
+ resultText: string;
10
+ isError: boolean;
11
+ hasResult: boolean;
12
+ };
13
+ export type ToolTranscriptFields = ToolCallFields & ToolResultFields;
14
+ export declare function formatToolArgs(name: string, args: Record<string, unknown>): string;
15
+ export declare function composeToolCall({ name, args, intent }: ToolCallFields): string;
16
+ export declare function composeToolResult({ resultText, isError, hasResult }: ToolResultFields): string;
17
+ export declare function composeToolText(fields: ToolTranscriptFields): string;
18
+ export declare function toolDisplayText(fields: ToolTranscriptFields, expanded: boolean): string;
19
+ export {};
@@ -1,13 +1,18 @@
1
1
  import { type AutocompleteProvider, type SlashCommand } from "@gajae-code/tui";
2
2
  import { type ComposerSubmissionOptions, type InteractiveModeContext } from "../../modes/types";
3
+ import { loadPastedImageBatch } from "../../utils/pasted-image-loading";
3
4
  import { ActionRegistry } from "../action-registry";
5
+ import type { PasteTextContext } from "../components/custom-editor";
4
6
  export declare const INTERACTIVE_ABORT_CLEANUP_TIMEOUT_MS = 5000;
5
7
  export declare const BACKGROUND_FOLD_DOUBLE_PRESS_MS = 750;
8
+ interface InputControllerDependencies {
9
+ loadPastedImageBatch?: typeof loadPastedImageBatch;
10
+ }
6
11
  export declare class InputController {
7
12
  #private;
8
13
  private ctx;
9
14
  readonly actionRegistry: ActionRegistry<void>;
10
- constructor(ctx: InteractiveModeContext);
15
+ constructor(ctx: InteractiveModeContext, dependencies?: InputControllerDependencies);
11
16
  setupKeyHandlers(): void;
12
17
  setupEditorSubmitHandler(): void;
13
18
  submitText(text: string, composer: ComposerSubmissionOptions): Promise<void>;
@@ -28,7 +33,7 @@ export declare class InputController {
28
33
  }): number;
29
34
  handleBackgroundCommand(): void;
30
35
  handleForegroundToolBackgroundFold(): boolean;
31
- handleTextPaste(text: string): boolean | Promise<boolean>;
36
+ handleTextPaste(text: string, context: PasteTextContext): boolean | Promise<boolean>;
32
37
  handleImagePaste(): Promise<boolean>;
33
38
  createAutocompleteProvider(commands: SlashCommand[], basePath: string): AutocompleteProvider;
34
39
  /** Copy the current editor line to the system clipboard. */
@@ -47,3 +52,4 @@ export declare class InputController {
47
52
  openExternalEditor(): Promise<void>;
48
53
  registerExtensionShortcuts(): void;
49
54
  }
55
+ export {};
@@ -30,6 +30,10 @@ export declare class PromptActionAutocompleteProvider implements AutocompletePro
30
30
  items: AutocompleteItem[];
31
31
  prefix: string;
32
32
  } | null>;
33
+ getForceFileSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
34
+ items: AutocompleteItem[];
35
+ prefix: string;
36
+ } | null>;
33
37
  applyCompletion(lines: string[], cursorLine: number, cursorCol: number, item: AutocompleteItem, prefix: string): {
34
38
  lines: string[];
35
39
  cursorLine: number;
@@ -109,6 +109,7 @@ export declare class Broker {
109
109
  constructor(settings: BrokerSettings);
110
110
  start(): Promise<BrokerDiscovery>;
111
111
  get ownsDiscovery(): boolean;
112
+ get completion(): Promise<void>;
112
113
  status(): RedactedBrokerDiscovery | null;
113
114
  heartbeat(): Promise<void>;
114
115
  stop(): Promise<void>;
@@ -1,5 +1,11 @@
1
1
  import { processIncarnation } from "./process-incarnation";
2
2
  import { SDK_STATE_VERSION } from "./state-version";
3
+ export type BrokerPublicationObservation = "owned" | "absent" | "replaced" | "ambiguous";
4
+ export interface RetainedBrokerDiscovery {
5
+ observe(): BrokerPublicationObservation;
6
+ heartbeat(heartbeatAt: number): Promise<boolean>;
7
+ close(): void;
8
+ }
3
9
  export declare const BROKER_HEARTBEAT_TTL_MS = 15000;
4
10
  export interface BrokerDiscovery {
5
11
  version: typeof SDK_STATE_VERSION;
@@ -26,5 +32,9 @@ export declare const newBrokerToken: () => string;
26
32
  export declare const brokerProcessIncarnation: typeof processIncarnation;
27
33
  export declare function isPidAlive(pid: number): boolean;
28
34
  export declare function writeBrokerDiscovery(agentDir: string, discovery: BrokerDiscoveryWrite): Promise<void>;
35
+ /** Publish once by name, then retain no-follow native authority for recurring heartbeats. */
36
+ export declare function publishBrokerDiscovery(agentDir: string, discovery: BrokerDiscoveryWrite, platform?: NodeJS.Platform): Promise<RetainedBrokerDiscovery>;
37
+ /** Heartbeat through retained authority, or the explicit Windows compatibility path. */
38
+ export declare function heartbeatBrokerDiscoveryRetained(publication: RetainedBrokerDiscovery, heartbeatAt: number): Promise<boolean>;
29
39
  export declare function readBrokerDiscovery(agentDir: string, ttlMs?: number): Promise<BrokerDiscovery | null>;
30
40
  export declare function redactBrokerDiscovery(discovery: BrokerDiscovery): RedactedBrokerDiscovery;
@@ -12,11 +12,28 @@ export interface EnsureBrokerSettings {
12
12
  env?: NodeJS.ProcessEnv;
13
13
  }
14
14
  export interface FixtureBrokerLease {
15
+ /** Backward-compatible fixture cleanup alias for exact child termination. */
15
16
  close(): Promise<void>;
16
17
  }
18
+ export interface ExactFixtureBrokerLease extends FixtureBrokerLease {
19
+ /** Observes the retained child only; it never signals a process. */
20
+ waitForExit(timeoutMs: number): Promise<boolean>;
21
+ /** Signals only the retained ChildProcess, never a discovery-derived PID. */
22
+ terminateExactChild(): Promise<void>;
23
+ }
24
+ export interface FixtureBrokerCommand {
25
+ file: string;
26
+ args: readonly string[];
27
+ cwd?: string;
28
+ env?: NodeJS.ProcessEnv;
29
+ }
30
+ export interface StartedFixtureBrokerCommand {
31
+ lease: ExactFixtureBrokerLease;
32
+ control: NodeJS.WritableStream;
33
+ }
17
34
  export interface StartedFixtureBroker {
18
35
  discovery: BrokerDiscovery;
19
- lease: FixtureBrokerLease;
36
+ lease: ExactFixtureBrokerLease;
20
37
  }
21
38
  interface BrokerOwner {
22
39
  stop(): Promise<void>;
@@ -31,6 +48,12 @@ interface ReapTiming {
31
48
  export declare function ensureBroker(settings: EnsureBrokerSettings): Promise<BrokerDiscovery>;
32
49
  /** Starts one fresh fixture broker and returns its sole exact-child close lease. */
33
50
  export declare function startFixtureBrokerWithLeaseForTest(settings: EnsureBrokerSettings): Promise<StartedFixtureBroker>;
51
+ /**
52
+ * Test-only launch surface for topology fixtures. It accepts an already-resolved
53
+ * command and retains the exact spawned child; no production selection path
54
+ * reaches this function.
55
+ */
56
+ export declare function startFixtureBrokerCommandWithLeaseForTest(command: FixtureBrokerCommand): StartedFixtureBrokerCommand;
34
57
  /** Test hook: returns a stop handle for the detached broker this process spawned. */
35
58
  export declare function brokerOwnerForTest(agentDir: string): BrokerOwner | undefined;
36
59
  /** Test hook: drives the detached-broker reap on a controllable child surface. */
@@ -0,0 +1,3 @@
1
+ import type { Broker } from "./broker";
2
+ /** Wait for broker-local completion, then terminate only the current broker process. */
3
+ export declare function completeBrokerProcess(broker: Broker, exit?: (code: number) => never): Promise<never>;
@@ -36,12 +36,24 @@ export interface SessionList {
36
36
  sessions: IndexedSession[];
37
37
  warnings: string[];
38
38
  }
39
+ export interface SessionIndexDiagnosis {
40
+ status: "healthy" | "corrupt" | "unsupported";
41
+ validPrefixSeq: number;
42
+ snapshotSeq: number;
43
+ reason?: string;
44
+ }
45
+ export interface SessionIndexRepairResult extends SessionIndexDiagnosis {
46
+ repaired: boolean;
47
+ quarantinePath?: string;
48
+ }
39
49
  export declare const sessionIndexChecksum: (event: Omit<SessionIndexEvent, "checksum">) => string;
40
50
  export declare class SessionIndex {
41
51
  #private;
42
52
  constructor(agentDir: string);
43
53
  open(): Promise<this>;
44
54
  replay(): Promise<void>;
55
+ diagnose(): Promise<SessionIndexDiagnosis>;
56
+ repair(): Promise<SessionIndexRepairResult>;
45
57
  refresh(): Promise<void>;
46
58
  get indexSeq(): number;
47
59
  append(input: Omit<SessionIndexEvent, "version" | "indexSeq" | "checksum" | "ts"> & Partial<Pick<SessionIndexEvent, "ts">>): Promise<SessionIndexEvent>;
@@ -3,8 +3,9 @@ export declare const SESSION_INDEX_SNAPSHOT_VERSION = 2;
3
3
  export declare class UnsupportedStateVersionError extends Error {
4
4
  readonly file: string;
5
5
  readonly version: number;
6
+ readonly maximumSupportedVersion: number;
6
7
  readonly code = "unsupported_state_version";
7
- constructor(file: string, version: number);
8
+ constructor(file: string, version: number, maximumSupportedVersion?: number);
8
9
  }
9
10
  export declare function assertSupportedStateVersion(file: string, value: unknown): void;
10
11
  export declare function assertSupportedSnapshotVersion(file: string, value: unknown): void;
@@ -338,6 +338,8 @@ export declare function createNotificationsExtension(api: ExtensionAPI, options?
338
338
  /** Suppress auto-delivery for a GJC-spawned child under `sessionScope=primary`. */
339
339
  spawnedByGjc?: boolean;
340
340
  controller?: NotificationSessionController;
341
+ /** Whether this host mode can own the root SDK endpoint. Default: true. */
342
+ sdkHostModeSupported?: boolean;
341
343
  onSdkRequest?: (kind: "control" | "query", connectionId: string, frame: Record<string, unknown>) => void;
342
344
  runEphemeralTurn?: (promptText: string, signal: AbortSignal) => Promise<{
343
345
  replyText: string;
@@ -150,6 +150,8 @@ export interface CreateAgentSessionOptions {
150
150
  hasUI?: boolean;
151
151
  /** Whether this host mode can own a notification session endpoint. Default: true. */
152
152
  notificationHostModeSupported?: boolean;
153
+ /** Whether this host mode can own the root SDK endpoint. Default: true. */
154
+ sdkHostModeSupported?: boolean;
153
155
  /**
154
156
  * Opt-in OpenTelemetry instrumentation forwarded to the underlying Agent.
155
157
  * Passing `{}` enables the loop's GenAI-semantic-convention spans. See