@gajae-code/coding-agent 0.12.21 → 0.13.0

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 (222) hide show
  1. package/CHANGELOG.md +67 -2
  2. package/dist/types/cli/args.d.ts +5 -2
  3. package/dist/types/cli/root-flags.d.ts +246 -0
  4. package/dist/types/cli.d.ts +11 -19
  5. package/dist/types/commands/daemon.d.ts +0 -30
  6. package/dist/types/commands/launch.d.ts +11 -19
  7. package/dist/types/commands/quick-lane.d.ts +32 -0
  8. package/dist/types/commands/sdk.d.ts +21 -15
  9. package/dist/types/config/file-lock-gc.d.ts +2 -0
  10. package/dist/types/config/model-equivalence.d.ts +20 -0
  11. package/dist/types/config/model-profile-activation.d.ts +62 -17
  12. package/dist/types/config/model-profiles.d.ts +10 -0
  13. package/dist/types/config/model-registry.d.ts +68 -1
  14. package/dist/types/config/model-resolver.d.ts +15 -4
  15. package/dist/types/config/models-config-schema.d.ts +7 -2
  16. package/dist/types/config/provider-selection-policy.d.ts +62 -0
  17. package/dist/types/config/settings-schema.d.ts +36 -78
  18. package/dist/types/config/settings.d.ts +2 -0
  19. package/dist/types/edit/renderer.d.ts +5 -2
  20. package/dist/types/edit/streaming.d.ts +13 -0
  21. package/dist/types/extensibility/custom-tools/types.d.ts +2 -0
  22. package/dist/types/extensibility/extensions/compact-handler.d.ts +2 -1
  23. package/dist/types/extensibility/extensions/types.d.ts +3 -0
  24. package/dist/types/gjc-runtime/gc-runtime.d.ts +19 -5
  25. package/dist/types/internal-urls/local-protocol.d.ts +1 -0
  26. package/dist/types/modes/components/model-selector.d.ts +0 -2
  27. package/dist/types/modes/components/provider-order-context.d.ts +45 -0
  28. package/dist/types/modes/components/provider-order-editor.d.ts +24 -0
  29. package/dist/types/modes/components/settings-defs.d.ts +5 -1
  30. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  31. package/dist/types/quick-lane/classify.d.ts +40 -0
  32. package/dist/types/runtime/stt-settings-setup.d.ts +18 -0
  33. package/dist/types/sdk/broker/broker.d.ts +56 -2
  34. package/dist/types/sdk/broker/operation-receipt-ledger.d.ts +25 -0
  35. package/dist/types/sdk/broker/session-index.d.ts +83 -2
  36. package/dist/types/sdk/broker/state-version.d.ts +1 -1
  37. package/dist/types/sdk/bus/notification-service.d.ts +6 -0
  38. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +8 -1
  39. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +4 -1
  40. package/dist/types/sdk/bus/telegram-daemon.d.ts +26 -0
  41. package/dist/types/sdk/cli/rows.d.ts +98 -0
  42. package/dist/types/sdk/cli/session-cli.d.ts +35 -3
  43. package/dist/types/sdk/elevation/allowlist.d.ts +20 -0
  44. package/dist/types/sdk/elevation/audit.d.ts +93 -0
  45. package/dist/types/sdk/elevation/capability.d.ts +3 -0
  46. package/dist/types/sdk/elevation/digest.d.ts +72 -0
  47. package/dist/types/sdk/elevation/dispatch-receipt.d.ts +85 -0
  48. package/dist/types/sdk/elevation/grant-ledger.d.ts +163 -0
  49. package/dist/types/sdk/elevation/owner.d.ts +48 -0
  50. package/dist/types/sdk/guides/cache.d.ts +98 -0
  51. package/dist/types/sdk/guides/catalog.d.ts +156 -0
  52. package/dist/types/sdk/guides/cli.d.ts +39 -0
  53. package/dist/types/sdk/guides/manifest.d.ts +66 -0
  54. package/dist/types/sdk/guides/verify.d.ts +66 -0
  55. package/dist/types/sdk/host/control/dispatch.d.ts +8 -0
  56. package/dist/types/sdk/host/control/index.d.ts +1 -1
  57. package/dist/types/sdk/host/control/operations.d.ts +3 -2
  58. package/dist/types/sdk/host/query/cursor.d.ts +10 -0
  59. package/dist/types/sdk/host/query/handlers.d.ts +21 -0
  60. package/dist/types/sdk/host/session-runtime.d.ts +9 -0
  61. package/dist/types/sdk/mcp/server.d.ts +2 -2
  62. package/dist/types/sdk/prompt-status.d.ts +11 -0
  63. package/dist/types/sdk/session.d.ts +4 -0
  64. package/dist/types/sdk/transport/index.d.ts +1 -0
  65. package/dist/types/sdk/transport/relay.d.ts +1 -0
  66. package/dist/types/sdk/transport/serve-cli.d.ts +20 -1
  67. package/dist/types/session/agent-session.d.ts +32 -18
  68. package/dist/types/session/blob-store.d.ts +13 -7
  69. package/dist/types/session/fallback-chain-controller.d.ts +15 -0
  70. package/dist/types/session/internal/managed-session-storage.d.ts +25 -1
  71. package/dist/types/session/internal/session-memory-sidecar.d.ts +5 -5
  72. package/dist/types/session/session-manager.d.ts +139 -10
  73. package/dist/types/session/session-storage.d.ts +48 -0
  74. package/dist/types/setup/provider-onboarding.d.ts +7 -1
  75. package/dist/types/slash-commands/builtin-registry.d.ts +14 -0
  76. package/dist/types/stt/setup.d.ts +2 -0
  77. package/dist/types/task/executor.d.ts +10 -2
  78. package/dist/types/tools/browser/runtime-diagnostics.d.ts +65 -0
  79. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  80. package/dist/types/tools/browser/tab-supervisor.d.ts +2 -0
  81. package/dist/types/tools/browser/tab-worker.d.ts +2 -0
  82. package/dist/types/tools/browser.d.ts +2 -0
  83. package/dist/types/tools/image-gen.d.ts +14 -18
  84. package/dist/types/tools/index.d.ts +2 -0
  85. package/dist/types/tools/resource-gc.d.ts +2 -0
  86. package/dist/types/utils/pasted-image-path.d.ts +6 -0
  87. package/package.json +9 -9
  88. package/scripts/generate-sdk-operation-inventory.ts +8 -0
  89. package/scripts/run-test-manifest.ts +61 -21
  90. package/scripts/verify-gjc-sdk-canonicalization.ts +9 -4
  91. package/src/cli/args.ts +62 -9
  92. package/src/cli/completion-cli.ts +1 -0
  93. package/src/cli/fast-help.ts +1 -0
  94. package/src/cli/root-flags.ts +100 -0
  95. package/src/cli/setup-cli.ts +6 -2
  96. package/src/cli.ts +42 -65
  97. package/src/commands/acp.ts +1 -1
  98. package/src/commands/daemon.ts +2 -31
  99. package/src/commands/gc.ts +1 -1
  100. package/src/commands/launch.ts +8 -129
  101. package/src/commands/quick-lane.ts +51 -0
  102. package/src/commands/sdk.ts +200 -26
  103. package/src/commands/setup.ts +4 -2
  104. package/src/config/file-lock-gc.ts +4 -1
  105. package/src/config/model-equivalence.ts +76 -7
  106. package/src/config/model-profile-activation.ts +1115 -265
  107. package/src/config/model-profiles.ts +134 -2
  108. package/src/config/model-registry.ts +352 -50
  109. package/src/config/model-resolver.ts +289 -38
  110. package/src/config/models-config-schema.ts +11 -4
  111. package/src/config/provider-selection-policy.ts +146 -0
  112. package/src/config/settings-schema.ts +50 -77
  113. package/src/config/settings.ts +40 -0
  114. package/src/coordinator-mcp/server.ts +32 -2
  115. package/src/edit/renderer.ts +175 -223
  116. package/src/edit/streaming.ts +108 -1
  117. package/src/export/html/index.ts +57 -7
  118. package/src/extensibility/custom-tools/types.ts +2 -0
  119. package/src/extensibility/extensions/compact-handler.ts +3 -2
  120. package/src/extensibility/extensions/runner.ts +6 -0
  121. package/src/extensibility/extensions/types.ts +3 -0
  122. package/src/gjc-runtime/gc-runtime.ts +379 -20
  123. package/src/gjc-runtime/launch-worktree.ts +5 -1
  124. package/src/gjc-runtime/team-runtime.ts +59 -2
  125. package/src/gjc-runtime/tmux-owner-isolation.ts +19 -0
  126. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +16 -1
  127. package/src/internal-urls/docs-index.generated.ts +17 -13
  128. package/src/internal-urls/local-protocol.ts +1 -0
  129. package/src/main.ts +40 -3
  130. package/src/memories/index.ts +4 -2
  131. package/src/modes/acp/acp-agent.ts +235 -91
  132. package/src/modes/components/model-selector.ts +206 -42
  133. package/src/modes/components/provider-order-context.ts +197 -0
  134. package/src/modes/components/provider-order-editor.ts +441 -0
  135. package/src/modes/components/settings-defs.ts +21 -1
  136. package/src/modes/components/settings-selector.ts +45 -2
  137. package/src/modes/components/tool-execution.ts +47 -15
  138. package/src/modes/controllers/command-controller.ts +6 -3
  139. package/src/modes/controllers/extension-ui-controller.ts +2 -0
  140. package/src/modes/controllers/input-controller.ts +73 -2
  141. package/src/modes/controllers/selector-controller.ts +260 -153
  142. package/src/modes/prompt-suggestion-controller.ts +1 -1
  143. package/src/modes/runtime-init.ts +1 -0
  144. package/src/modes/utils/ui-helpers.ts +18 -0
  145. package/src/prompts/tools/browser.md +1 -0
  146. package/src/quick-lane/classify.ts +257 -0
  147. package/src/rlm/index.ts +1 -1
  148. package/src/runtime/stt-settings-setup.ts +57 -0
  149. package/src/sdk/acp/adapter.ts +2 -1
  150. package/src/sdk/broker/broker.ts +780 -12
  151. package/src/sdk/broker/lifecycle.ts +70 -29
  152. package/src/sdk/broker/operation-receipt-ledger.ts +144 -0
  153. package/src/sdk/broker/session-index.ts +463 -48
  154. package/src/sdk/broker/state-version.ts +13 -9
  155. package/src/sdk/broker/transport.ts +14 -1
  156. package/src/sdk/bus/index.ts +34 -13
  157. package/src/sdk/bus/kind-aware-reconciliation.ts +21 -2
  158. package/src/sdk/bus/notification-service.ts +47 -1
  159. package/src/sdk/bus/prompt-reconciliation.ts +22 -3
  160. package/src/sdk/bus/telegram-daemon-contract.ts +4 -1
  161. package/src/sdk/bus/telegram-daemon.ts +54 -3
  162. package/src/sdk/cli/rows.ts +247 -0
  163. package/src/sdk/cli/session-cli.ts +930 -79
  164. package/src/sdk/elevation/allowlist.ts +54 -0
  165. package/src/sdk/elevation/audit.ts +208 -0
  166. package/src/sdk/elevation/capability.ts +41 -0
  167. package/src/sdk/elevation/digest.ts +129 -0
  168. package/src/sdk/elevation/dispatch-receipt.ts +184 -0
  169. package/src/sdk/elevation/grant-ledger.ts +1142 -0
  170. package/src/sdk/elevation/owner.ts +109 -0
  171. package/src/sdk/guides/cache.ts +363 -0
  172. package/src/sdk/guides/catalog.ts +554 -0
  173. package/src/sdk/guides/cli.ts +235 -0
  174. package/src/sdk/guides/manifest.ts +152 -0
  175. package/src/sdk/guides/verify.ts +178 -0
  176. package/src/sdk/host/control/dispatch.ts +49 -1
  177. package/src/sdk/host/control/index.ts +1 -0
  178. package/src/sdk/host/control/operations.ts +8 -1
  179. package/src/sdk/host/query/cursor.ts +47 -3
  180. package/src/sdk/host/query/handlers.ts +155 -2
  181. package/src/sdk/host/sdk-surface-parity.test.ts +1 -0
  182. package/src/sdk/host/session-runtime.test.ts +391 -1
  183. package/src/sdk/host/session-runtime.ts +308 -73
  184. package/src/sdk/host/surface-policy.ts +3 -0
  185. package/src/sdk/host/websocket-transport.ts +7 -1
  186. package/src/sdk/mcp/server.ts +88 -15
  187. package/src/sdk/prompt-status.ts +8 -0
  188. package/src/sdk/protocol/operation-inventory.generated.json +62 -0
  189. package/src/sdk/protocol/operation-registry.ts +3 -2
  190. package/src/sdk/session.ts +87 -39
  191. package/src/sdk/transport/index.ts +1 -0
  192. package/src/sdk/transport/relay.ts +3 -0
  193. package/src/sdk/transport/serve-cli.ts +111 -24
  194. package/src/secrets/obfuscator.ts +92 -12
  195. package/src/session/agent-session.ts +322 -93
  196. package/src/session/blob-store.ts +60 -8
  197. package/src/session/fallback-chain-controller.ts +35 -0
  198. package/src/session/internal/managed-session-scope.ts +25 -3
  199. package/src/session/internal/managed-session-storage.ts +574 -73
  200. package/src/session/internal/session-memory-sidecar.ts +19 -29
  201. package/src/session/session-manager.ts +2166 -743
  202. package/src/session/session-storage.ts +715 -48
  203. package/src/setup/provider-onboarding.ts +19 -3
  204. package/src/setup/provider-presets.json +3 -1
  205. package/src/slash-commands/builtin-registry.ts +85 -3
  206. package/src/stt/downloader.ts +2 -3
  207. package/src/stt/setup.ts +29 -4
  208. package/src/task/executor.ts +22 -18
  209. package/src/task/index.ts +24 -1
  210. package/src/tools/archive-reader.ts +11 -2
  211. package/src/tools/browser/runtime-diagnostics.ts +249 -0
  212. package/src/tools/browser/tab-protocol.ts +4 -0
  213. package/src/tools/browser/tab-supervisor.ts +5 -0
  214. package/src/tools/browser/tab-worker.ts +36 -1
  215. package/src/tools/browser.ts +7 -0
  216. package/src/tools/image-gen.ts +110 -166
  217. package/src/tools/index.ts +2 -0
  218. package/src/tools/read.ts +1 -1
  219. package/src/tools/resource-gc.ts +6 -1
  220. package/src/tools/tool-catalog.generated.ts +5 -1
  221. package/src/utils/pasted-image-path.ts +93 -0
  222. package/src/web/search/index.ts +3 -3
@@ -0,0 +1,146 @@
1
+ import type { Api, Model } from "@gajae-code/ai/core";
2
+
3
+ /**
4
+ * Effective credential provenance for a provider, derived from credential
5
+ * surfaces (never from token shape).
6
+ *
7
+ * - `"oauth"`: requests are authenticated with an OAuth-provisioned credential,
8
+ * including OAuth flows whose access tokens happen to look like API keys
9
+ * (e.g. GitHub Copilot `ghu_` tokens).
10
+ * - `"key"`: a manual or configured API key (stored `api_key`, CLI `--api-key`
11
+ * runtime override, `models.yml` `apiKey`/`apiKeyEnv`, or environment key).
12
+ * - `"keyless"`: no credential is required (local servers, `auth: none`).
13
+ * - `"unknown"`: no credential surface is present.
14
+ */
15
+ export type EffectiveProviderAuth = "oauth" | "key" | "keyless" | "unknown";
16
+
17
+ export interface ProviderSelectionPolicyInput {
18
+ /** Explicit `modelProviderOrder` from settings; trimmed and case-insensitive. */
19
+ explicitProviderOrder: readonly string[];
20
+ /** Effective auth provenance per lowercased provider id. */
21
+ effectiveAuth: ReadonlyMap<string, EffectiveProviderAuth>;
22
+ /** Registry catalog provider ids, lowercased, first-wins catalog order. */
23
+ catalogProviders: readonly string[];
24
+ /** Registry catalog model selectors ("provider/id"), lowercased, first-wins catalog order. */
25
+ catalogModels: readonly string[];
26
+ }
27
+
28
+ export interface ProviderSelectionPolicy {
29
+ /**
30
+ * Total-order rank for a provider: explicit providers `0..n-1`, omitted
31
+ * effective-OAuth providers `n`, omitted non-OAuth/unknown/keyless providers
32
+ * `n+1`. Unknown providers that were never cataloged still receive the
33
+ * non-OAuth rank unless their effective auth is OAuth.
34
+ */
35
+ rank(provider: string): number;
36
+ /** Lowercased explicit provider ids, in explicit order (deduped). */
37
+ explicitProviders(): readonly string[];
38
+ /** Whether a provider was listed explicitly. */
39
+ isExplicit(provider: string): boolean;
40
+ /** Ordered distinct provider ids: explicit order first, then catalog order. */
41
+ orderedProviders(): readonly string[];
42
+ /** Stable catalog index per lowercased provider id (registry-owned tie data). */
43
+ providerCatalogIndex(provider: string): number;
44
+ /** Stable catalog index per lowercased model selector (registry-owned tie data). */
45
+ modelCatalogIndex(selector: string): number;
46
+ }
47
+
48
+ /**
49
+ * Build a pure provider selection policy over explicit user order, effective
50
+ * credential provenance, and registry-owned catalog tie data. The policy never
51
+ * reads settings, auth storage, or the model catalog itself — callers pass the
52
+ * current values in so ranking stays deterministic and testable.
53
+ */
54
+ export function createProviderSelectionPolicy(input: ProviderSelectionPolicyInput): ProviderSelectionPolicy {
55
+ const explicitProviders: string[] = [];
56
+ const explicitSet = new Set<string>();
57
+ for (const raw of input.explicitProviderOrder) {
58
+ const normalized = raw.trim().toLowerCase();
59
+ if (!normalized || explicitSet.has(normalized)) {
60
+ continue;
61
+ }
62
+ explicitSet.add(normalized);
63
+ explicitProviders.push(normalized);
64
+ }
65
+ const explicitCount = explicitProviders.length;
66
+ const oauthRank = explicitCount;
67
+ const nonOAuthRank = explicitCount + 1;
68
+
69
+ const providerCatalogIndex = new Map<string, number>();
70
+ const modelCatalogIndex = new Map<string, number>();
71
+ for (let index = 0; index < input.catalogProviders.length; index += 1) {
72
+ const provider = input.catalogProviders[index]!;
73
+ if (!providerCatalogIndex.has(provider)) {
74
+ providerCatalogIndex.set(provider, index);
75
+ }
76
+ }
77
+ for (let index = 0; index < input.catalogModels.length; index += 1) {
78
+ const selector = input.catalogModels[index]!;
79
+ if (!modelCatalogIndex.has(selector)) {
80
+ modelCatalogIndex.set(selector, index);
81
+ }
82
+ }
83
+
84
+ const orderedProviders = [...explicitProviders];
85
+ const seen = new Set(explicitSet);
86
+ for (const provider of input.catalogProviders) {
87
+ if (seen.has(provider)) {
88
+ continue;
89
+ }
90
+ seen.add(provider);
91
+ orderedProviders.push(provider);
92
+ }
93
+
94
+ return {
95
+ rank(provider: string): number {
96
+ const normalized = provider.trim().toLowerCase();
97
+ if (explicitSet.has(normalized)) {
98
+ return explicitProviders.indexOf(normalized);
99
+ }
100
+ return input.effectiveAuth.get(normalized) === "oauth" ? oauthRank : nonOAuthRank;
101
+ },
102
+ explicitProviders: () => explicitProviders,
103
+ isExplicit(provider: string): boolean {
104
+ return explicitSet.has(provider.trim().toLowerCase());
105
+ },
106
+ orderedProviders: () => orderedProviders,
107
+ providerCatalogIndex(provider: string): number {
108
+ return providerCatalogIndex.get(provider.trim().toLowerCase()) ?? Number.MAX_SAFE_INTEGER;
109
+ },
110
+ modelCatalogIndex(selector: string): number {
111
+ return modelCatalogIndex.get(selector.trim().toLowerCase()) ?? Number.MAX_SAFE_INTEGER;
112
+ },
113
+ };
114
+ }
115
+
116
+ export interface ProviderSelectionCatalog {
117
+ /** Lowercased provider ids in first-wins registry catalog order. */
118
+ readonly catalogProviders: readonly string[];
119
+ /** Lowercased model selectors in first-wins registry catalog order. */
120
+ readonly catalogModels: readonly string[];
121
+ }
122
+
123
+ /**
124
+ * Derive stable provider/model tie data from the registry catalog order, not
125
+ * from a caller-supplied candidate array. First occurrence wins so reordering
126
+ * candidates never changes ranking.
127
+ */
128
+ export function buildProviderSelectionCatalog(models: readonly Model<Api>[]): ProviderSelectionCatalog {
129
+ const catalogProviders: string[] = [];
130
+ const catalogModels: string[] = [];
131
+ const seenProviders = new Set<string>();
132
+ const seenModels = new Set<string>();
133
+ for (const model of models) {
134
+ const providerKey = model.provider.trim().toLowerCase();
135
+ if (providerKey && !seenProviders.has(providerKey)) {
136
+ seenProviders.add(providerKey);
137
+ catalogProviders.push(providerKey);
138
+ }
139
+ const selectorKey = `${model.provider}/${model.id}`.trim().toLowerCase();
140
+ if (selectorKey && !seenModels.has(selectorKey)) {
141
+ seenModels.add(selectorKey);
142
+ catalogModels.push(selectorKey);
143
+ }
144
+ }
145
+ return { catalogProviders, catalogModels };
146
+ }
@@ -522,6 +522,39 @@ export const SETTINGS_SCHEMA = {
522
522
  options: "runtime",
523
523
  },
524
524
  },
525
+ "modelProfile.proxyProvider": {
526
+ type: "string",
527
+ default: undefined,
528
+ ui: {
529
+ tab: "model",
530
+ label: "Proxy Provider",
531
+ description:
532
+ "Configured OpenAI-compatible proxy/gateway provider id (e.g. litellm) used by built-in model presets. Leave unset to keep direct provider endpoints.",
533
+ },
534
+ },
535
+ "modelProfile.proxyMode": {
536
+ type: "enum",
537
+ values: ["fallback", "always"] as const,
538
+ default: "fallback",
539
+ ui: {
540
+ tab: "model",
541
+ label: "Proxy Routing Mode",
542
+ description:
543
+ "fallback routes only selectors whose direct provider lacks credentials; always routes every proxy-routable built-in preset selector through the configured proxy.",
544
+ options: [
545
+ {
546
+ value: "fallback",
547
+ label: "Fallback",
548
+ description: "Use the proxy only when direct provider credentials are unavailable",
549
+ },
550
+ {
551
+ value: "always",
552
+ label: "Always",
553
+ description: "Route proxy-routable built-in preset selectors through the proxy",
554
+ },
555
+ ],
556
+ },
557
+ },
525
558
  "session.resumeModelBehavior": {
526
559
  type: "enum",
527
560
  values: ["keepSessionModel", "useCurrentDefault", "ask"] as const,
@@ -541,7 +574,16 @@ export const SETTINGS_SCHEMA = {
541
574
 
542
575
  modelTags: { type: "record", default: EMPTY_MODEL_TAGS_RECORD },
543
576
 
544
- modelProviderOrder: { type: "array", default: EMPTY_STRING_ARRAY },
577
+ modelProviderOrder: {
578
+ type: "array",
579
+ default: EMPTY_STRING_ARRAY,
580
+ ui: {
581
+ tab: "providers",
582
+ label: "Provider Priority Order",
583
+ description:
584
+ "Ordered provider priority for automatic model resolution. Providers listed earlier win ties; omitted providers fall back to curated ranking. Unavailable saved entries are retained and skipped at runtime.",
585
+ },
586
+ },
545
587
 
546
588
  cycleOrder: { type: "array", default: DEFAULT_CYCLE_ORDER },
547
589
 
@@ -2079,15 +2121,14 @@ export const SETTINGS_SCHEMA = {
2079
2121
  },
2080
2122
  },
2081
2123
 
2082
- // Bounded-memory cold-session offloading (rollout knobs; budgets are fixed
2083
- // implementation constants in the sidecar primitives, not user-tunable
2084
- // fields). "shadow" (default) measures and offloads without changing
2085
- // observable behavior; canary/default-on are release-channel states, not
2086
- // user-facing enum values.
2124
+ // Bounded-memory cold-session offloading. Budgets are fixed implementation
2125
+ // constants in the sidecar primitives, not user-tunable fields. Auto keeps
2126
+ // ordinary sessions on the eager path and routes transcripts above the eager
2127
+ // admission limit through bounded cold-session state.
2087
2128
  "sessionMemory.mode": {
2088
2129
  type: "enum",
2089
- values: ["off", "shadow", "enabled"] as const,
2090
- default: "shadow",
2130
+ values: ["off", "shadow", "enabled", "auto"] as const,
2131
+ default: "auto",
2091
2132
  },
2092
2133
  // Independent runtime switch for AgentSession's async compact-once overflow
2093
2134
  // recovery. The synchronous bounded context preflight stays always on.
@@ -3557,74 +3598,6 @@ export const SETTINGS_SCHEMA = {
3557
3598
  ],
3558
3599
  },
3559
3600
  },
3560
- "providers.image": {
3561
- type: "enum",
3562
- values: ["auto", "openai", "gemini", "openrouter", "antigravity", "alibaba", "custom"] as const,
3563
- default: "auto",
3564
- ui: {
3565
- tab: "providers",
3566
- label: "Image Generation",
3567
- description: "Provider and model for image generation tool",
3568
- options: [
3569
- {
3570
- value: "auto",
3571
- label: "Auto",
3572
- description: "Priority: GPT model image tool > Antigravity > OpenRouter > Gemini > Alibaba",
3573
- },
3574
- { value: "openai", label: "OpenAI", description: "Uses gpt-image-2 via OpenAI Responses/Codex" },
3575
- { value: "gemini", label: "Gemini", description: "Requires GEMINI_API_KEY" },
3576
- { value: "openrouter", label: "OpenRouter", description: "Requires OPENROUTER_API_KEY" },
3577
- { value: "antigravity", label: "Antigravity", description: "Requires login with google-antigravity" },
3578
- {
3579
- value: "alibaba",
3580
- label: "Alibaba Bailian",
3581
- description: "Requires ALIBABA_TOKEN_PLAN_API_KEY (wan2.7-image via Token Plan)",
3582
- },
3583
- {
3584
- value: "custom",
3585
- label: "Custom",
3586
- description: "OpenAI-compatible endpoint (set providers.imageCustomUrl)",
3587
- },
3588
- ],
3589
- },
3590
- },
3591
- "providers.imageModel": {
3592
- type: "string",
3593
- default: undefined,
3594
- ui: {
3595
- tab: "providers",
3596
- label: "Image Model",
3597
- description: "Override the default image generation model for the selected provider",
3598
- },
3599
- },
3600
- "providers.imageCustomUrl": {
3601
- type: "string",
3602
- default: undefined,
3603
- ui: {
3604
- tab: "providers",
3605
- label: "Image Custom URL",
3606
- description: "Base URL for custom OpenAI-compatible image endpoint",
3607
- },
3608
- },
3609
- "providers.imageCustomKey": {
3610
- type: "string",
3611
- default: undefined,
3612
- ui: {
3613
- tab: "providers",
3614
- label: "Image Custom API Key",
3615
- description: "API key for custom OpenAI-compatible image endpoint",
3616
- },
3617
- },
3618
- "providers.imageCustomKeyEnv": {
3619
- type: "string",
3620
- default: undefined,
3621
- ui: {
3622
- tab: "providers",
3623
- label: "Image Custom API Key Env",
3624
- description: "Environment variable name holding the API key for custom image endpoint",
3625
- },
3626
- },
3627
-
3628
3601
  "providers.kimiApiFormat": {
3629
3602
  type: "enum",
3630
3603
  values: ["openai", "anthropic"] as const,
@@ -4174,7 +4147,7 @@ export interface ShellMinimizerSettings {
4174
4147
  }
4175
4148
 
4176
4149
  export interface SessionMemorySettings {
4177
- mode: "off" | "shadow" | "enabled";
4150
+ mode: "off" | "shadow" | "enabled" | "auto";
4178
4151
  contextOverflowRecovery: boolean;
4179
4152
  }
4180
4153
 
@@ -810,6 +810,12 @@ export class Settings implements NotificationSettingsReader {
810
810
  this.#rebuildMerged();
811
811
  }
812
812
 
813
+ /** Read the exact runtime override without merged defaults. */
814
+ getOverride<P extends SettingPath>(path: P): SettingValue<P> | undefined {
815
+ const value = getByPath(this.#overrides, path.split("."));
816
+ return value === undefined ? undefined : (value as SettingValue<P>);
817
+ }
818
+
813
819
  /**
814
820
  * Clear a runtime override.
815
821
  */
@@ -1621,6 +1627,40 @@ export class Settings implements NotificationSettingsReader {
1621
1627
  }
1622
1628
  }
1623
1629
 
1630
+ // Migrate legacy providers.image* settings into modelRoles.image.
1631
+ // The image-generation model is now selected via the model-role system
1632
+ // (/model image <selector>) instead of a separate provider config dialog.
1633
+ const providersObj = raw.providers as Record<string, unknown> | undefined;
1634
+ if (providersObj && typeof providersObj.image === "string") {
1635
+ const imageProvider = providersObj.image as string;
1636
+ const imageModel = typeof providersObj.imageModel === "string" ? providersObj.imageModel : undefined;
1637
+ const imageCustomUrl =
1638
+ typeof providersObj.imageCustomUrl === "string" ? providersObj.imageCustomUrl : undefined;
1639
+
1640
+ if (imageProvider !== "auto") {
1641
+ const roles = rawSettingsRecord(raw.modelRoles) ?? {};
1642
+ if (!roles.image) {
1643
+ if (imageProvider === "custom" && imageCustomUrl) {
1644
+ // Custom providers are registered as first-class OpenAI-compatible providers;
1645
+ // the migration produces a provider/model selector.
1646
+ const customProviderId = "image-custom";
1647
+ roles.image = `${customProviderId}/${imageModel ?? "gpt-image-2"}`;
1648
+ } else if (imageModel) {
1649
+ roles.image = `${imageProvider}/${imageModel}`;
1650
+ } else {
1651
+ roles.image = imageProvider;
1652
+ }
1653
+ raw.modelRoles = roles;
1654
+ }
1655
+ }
1656
+
1657
+ delete providersObj.image;
1658
+ delete providersObj.imageModel;
1659
+ delete providersObj.imageCustomUrl;
1660
+ delete providersObj.imageCustomKey;
1661
+ delete providersObj.imageCustomKeyEnv;
1662
+ }
1663
+
1624
1664
  raw.configSchemaVersion = CONFIG_SCHEMA_VERSION;
1625
1665
 
1626
1666
  return raw;
@@ -325,6 +325,7 @@ const MISSING_FINAL_RESPONSE_ADVISORY = "completion_missing_final_response";
325
325
  const PROMPT_ACK_TIMEOUT_REASON = "runtime_prompt_ack_timeout";
326
326
  const DEFAULT_RUNTIME_PROMPT_ACK_TIMEOUT_MS = 10_000;
327
327
  const MAX_RUNTIME_PROMPT_ACK_TIMEOUT_MS = 5 * 60 * 1000;
328
+ const MAX_COORDINATOR_SESSION_LIST_PAGES = 10_000;
328
329
  const ACTIVE_TURN_STATUSES = new Set<TurnStatus>(["delivering", "active", "waiting_for_answer", "completing"]);
329
330
  const TERMINAL_TURN_STATUSES = new Set<TurnStatus>(["completed", "failed", "cancelled", "superseded"]);
330
331
  const TURN_ID_PATTERN = /^turn-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -3213,6 +3214,34 @@ export function createCoordinatorMcpServer(options: CoordinatorMcpServerOptions
3213
3214
  return asRecord(response?.result) ?? response ?? {};
3214
3215
  }
3215
3216
 
3217
+ async function paginatedBrokerSessionList(
3218
+ cwd: string,
3219
+ input: Record<string, unknown>,
3220
+ ): Promise<Record<string, unknown>> {
3221
+ const aggregate: Record<string, unknown> = {};
3222
+ const sessions: unknown[] = [];
3223
+ let cursor: string | undefined;
3224
+ for (let pageCount = 0; pageCount < MAX_COORDINATOR_SESSION_LIST_PAGES; pageCount++) {
3225
+ const page = brokerResult(
3226
+ await brokerSession(cwd, "session.list", {
3227
+ ...input,
3228
+ ...(cursor === undefined ? {} : { cursor }),
3229
+ }),
3230
+ );
3231
+ for (const [key, value] of Object.entries(page)) {
3232
+ if (key !== "sessions" && key !== "continuationCursor") aggregate[key] = value;
3233
+ }
3234
+ if (Array.isArray(page.sessions)) sessions.push(...page.sessions);
3235
+ const nextCursor =
3236
+ typeof page.continuationCursor === "string" && page.continuationCursor.length > 0
3237
+ ? page.continuationCursor
3238
+ : undefined;
3239
+ if (!nextCursor) return { ...aggregate, sessions };
3240
+ cursor = nextCursor;
3241
+ }
3242
+ throw new SdkClientError("protocol_error", "session.list exceeded the page budget.");
3243
+ }
3244
+
3216
3245
  async function canonicalBrokerWorkspace(cwd: string): Promise<string> {
3217
3246
  try {
3218
3247
  return await (services.canonicalizePath ?? (value => fs.realpath(value)))(cwd);
@@ -3259,7 +3288,8 @@ export function createCoordinatorMcpServer(options: CoordinatorMcpServerOptions
3259
3288
  };
3260
3289
 
3261
3290
  async function exactBrokerSessionAuthority(sessionId: string, workspace: string): Promise<BrokerSessionAuthority> {
3262
- const listing = brokerResult(await brokerSession(workspace, "session.list", { cwd: workspace }));
3291
+ const listing = await paginatedBrokerSessionList(workspace, { cwd: workspace });
3292
+
3263
3293
  const matches: Array<{ session: Record<string, unknown>; workspace: string }> = [];
3264
3294
  for (const session of jsonRecords(Array.isArray(listing.sessions) ? listing.sessions : [])) {
3265
3295
  if (brokerSessionId(session) !== sessionId) continue;
@@ -3410,7 +3440,7 @@ export function createCoordinatorMcpServer(options: CoordinatorMcpServerOptions
3410
3440
  const roots = cwd ? [cwd] : config.allowedRoots;
3411
3441
  const listings = await Promise.all(
3412
3442
  roots.map(async root => {
3413
- const listing = brokerResult(await brokerSession(root, "session.list", { cwd: root }));
3443
+ const listing = await paginatedBrokerSessionList(root, { cwd: root });
3414
3444
  return scopedBrokerSessions(Array.isArray(listing.sessions) ? listing.sessions : [], root, platform);
3415
3445
  }),
3416
3446
  );