@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
@@ -1,8 +1,9 @@
1
1
  import { type Model } from "@gajae-code/ai/core";
2
2
  import * as z from "zod/v4";
3
3
  import { type ModelRegistry } from "../config/model-registry";
4
+ import type { Settings } from "../config/settings";
4
5
  import type { CustomTool } from "../extensibility/custom-tools/types";
5
- type ImageProvider = "alibaba" | "antigravity" | "gemini" | "openai" | "openai-codex" | "openrouter";
6
+ type ImageProvider = "alibaba" | "antigravity" | "gemini" | "openai" | "openai-codex" | "openrouter" | (string & {});
6
7
  declare const responseModalitySchema: z.ZodEnum<{
7
8
  IMAGE: "IMAGE";
8
9
  TEXT: "TEXT";
@@ -116,22 +117,17 @@ interface InlineImageData {
116
117
  data: string;
117
118
  mimeType: string;
118
119
  }
119
- /** Set the preferred image provider from settings */
120
- export declare function setPreferredImageProvider(provider: ImageProvider | "auto"): void;
121
- /** Provider → default image model mapping for auto-binding */
120
+ /** Provider → default image model mapping for fallbacks */
122
121
  export declare const IMAGE_PROVIDER_DEFAULTS: Record<string, string>;
123
- /** Resolved image generation configuration from settings */
124
- export interface ImageProviderConfig {
125
- provider: ImageProvider | "auto" | "custom";
126
- model: string | null;
127
- customUrl?: string;
128
- customKey?: string;
129
- customKeyEnv?: string;
130
- }
131
- /** Set the configured image provider + model from settings */
132
- export declare function setConfiguredImageModel(config: ImageProviderConfig | null): void;
133
- /** Get the current configured image model (for UI display) */
134
- export declare function getConfiguredImageModel(): ImageProviderConfig | null;
122
+ /**
123
+ * Resolve the image-generation model from the `modelRoles.image` settings entry.
124
+ * Returns the resolved Model (with provider identity) or undefined when no
125
+ * image role is configured / no matching model is available.
126
+ */
127
+ export declare function resolveImageRoleModel(settings: Settings, modelRegistry: ModelRegistry, options?: {
128
+ sessionId?: string;
129
+ credentialSessionId?: string;
130
+ }): Model | undefined;
135
131
  /** Resolve the effective image model for a configured provider */
136
132
  export declare function resolveImageModel(provider: string, modelOverride: string | null): string;
137
133
  /** Test seam: the Google image key fallback as resolved from trusted env. */
@@ -140,6 +136,6 @@ export declare function isOpenAIHostedImageModel(model: Model | undefined): mode
140
136
  /** Test seam: the image-request base URL as resolved from trusted env. */
141
137
  export declare function getOpenAIImageBaseUrlForTest(model: Model, authCredentialType?: "api_key" | "oauth"): string;
142
138
  export declare const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails>;
143
- export declare function getImageGenTools(modelRegistry?: ModelRegistry, activeModel?: Model): Promise<Array<CustomTool<typeof imageGenSchema, ImageGenToolDetails>>>;
144
- export declare function getImageGenToolsWithRegistry(modelRegistry: ModelRegistry, activeModel?: Model): Promise<Array<CustomTool<typeof imageGenSchema, ImageGenToolDetails>>>;
139
+ export declare function getImageGenTools(modelRegistry?: ModelRegistry, settings?: Settings): Promise<Array<CustomTool<typeof imageGenSchema, ImageGenToolDetails>>>;
140
+ export declare function getImageGenToolsWithRegistry(modelRegistry: ModelRegistry, settings: Settings): Promise<Array<CustomTool<typeof imageGenSchema, ImageGenToolDetails>>>;
145
141
  export {};
@@ -171,6 +171,8 @@ export interface ToolSession {
171
171
  requestForegroundBashBackground?: () => boolean;
172
172
  /** Get session ID */
173
173
  getSessionId?: () => string | null;
174
+ /** Get credential-selection session identity. */
175
+ getCredentialSessionId?: () => string | null;
174
176
  /** Scope-held MCP facade for mcp:// resolution. */
175
177
  getMcpManager?: () => import("../runtime-mcp/manager").MCPManager | undefined;
176
178
  /** Whether local:// must use external managed scratch instead of artifacts/local. */
@@ -39,6 +39,8 @@ export interface ResourceGcDeps {
39
39
  listTeamWorkers?: (cwd: string, sessionId: string) => Promise<MemoryGuardWorkerSample[]>;
40
40
  applyTeamWorkerGuard?: (cwd: string, sessionId: string, workerId: string, excessBytes: number, incidentId: string) => Promise<void>;
41
41
  }
42
+ /** Request collection without synchronously stopping the main event loop. */
43
+ export declare function requestMemoryPressureGc(): void;
42
44
  export interface ResourceGcRegistration {
43
45
  sessionId: string;
44
46
  settings: Settings;
@@ -32,3 +32,9 @@ export declare function resolvePastedImagePath(text: string, options?: ResolvePa
32
32
  */
33
33
  export declare function parsePastedImagePaths(text: string, options?: ResolvePastedImagePathOptions): PastedImagePathParseResult | undefined;
34
34
  export declare function formatPastedImageReference(placeholder: string, imagePath: string): string;
35
+ export interface PastedImageReferenceRange {
36
+ imageIndex: number;
37
+ startCol: number;
38
+ endCol: number;
39
+ }
40
+ export declare function locatePastedImageReferenceAroundCursor(line: string, cursorCol: number): PastedImageReferenceRange | null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.12.21",
4
+ "version": "0.13.0",
5
5
  "description": "Gajae Code CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://gajae-code.com",
7
7
  "author": "Yeachan-Heo and Gajae Code Contributors",
@@ -48,19 +48,19 @@
48
48
  "install:defaults": "bun src/cli.ts setup defaults",
49
49
  "verify:insane-vendor": "bun scripts/verify-insane-vendor.ts",
50
50
  "verify:sdk-canonicalization": "bun scripts/verify-gjc-sdk-canonicalization.ts",
51
- "check:sdk-closure": "bun ../../scripts/telegram-daemon-generation-guard.ts --validate-current-tree && bun test ../../scripts/telegram-daemon-generation-guard.test.ts && bun scripts/generate-sdk-operation-inventory.ts --check && bun scripts/generate-sdk-adapter-parity-manifest.ts --check && bun scripts/run-test-manifest.ts test/manifests/sdk-adapter-parity-v1.json && bun scripts/generate-telegram-baseline-manifest.ts --check && bun scripts/run-test-manifest.ts test/manifests/telegram-baseline-v1.json && bun test test/sdk-downgrade-rollback.test.ts test/sdk-downgrade-unknown-version.test.ts && bun scripts/verify-gjc-sdk-canonicalization.ts --self-test && bun scripts/verify-gjc-sdk-canonicalization.ts && bun scripts/verify-gjc-sdk-rename.ts"
51
+ "check:sdk-closure": "bun ../../scripts/telegram-daemon-generation-guard.ts --validate-current-tree && bun test ../../scripts/telegram-daemon-generation-guard.test.ts && bun scripts/generate-sdk-operation-inventory.ts --check && bun scripts/generate-sdk-adapter-parity-manifest.ts --check && GJC_MANIFEST_RECEIPT_CONCURRENCY=8 bun scripts/run-test-manifest.ts test/manifests/sdk-adapter-parity-v1.json && bun scripts/generate-telegram-baseline-manifest.ts --check && bun scripts/run-test-manifest.ts test/manifests/telegram-baseline-v1.json && bun test test/sdk-downgrade-rollback.test.ts test/sdk-downgrade-unknown-version.test.ts && bun scripts/verify-gjc-sdk-canonicalization.ts --self-test && bun scripts/verify-gjc-sdk-canonicalization.ts && bun scripts/verify-gjc-sdk-rename.ts"
52
52
  },
53
53
  "dependencies": {
54
54
  "@agentclientprotocol/sdk": "1.3.0",
55
55
  "@babel/parser": "^7.29.3",
56
56
  "@mozilla/readability": "^0.6.0",
57
- "@gajae-code/stats": "0.12.21",
58
- "@gajae-code/agent-core": "0.12.21",
59
- "@gajae-code/ai": "0.12.21",
60
- "@gajae-code/bridge-client": "0.12.21",
61
- "@gajae-code/natives": "0.12.21",
62
- "@gajae-code/tui": "0.12.21",
63
- "@gajae-code/utils": "0.12.21",
57
+ "@gajae-code/stats": "0.13.0",
58
+ "@gajae-code/agent-core": "0.13.0",
59
+ "@gajae-code/ai": "0.13.0",
60
+ "@gajae-code/bridge-client": "0.13.0",
61
+ "@gajae-code/natives": "0.13.0",
62
+ "@gajae-code/tui": "0.13.0",
63
+ "@gajae-code/utils": "0.13.0",
64
64
  "@puppeteer/browsers": "^2.13.0",
65
65
  "@types/turndown": "5.0.6",
66
66
  "@xterm/headless": "^6.0.0",
@@ -35,6 +35,14 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
35
35
  "slash_command:transcript": "visual/local-only transcript viewer, not a user-facing SDK control seam",
36
36
  "slash_command:sessions": "visual/local-only sessions dashboard, not a user-facing SDK control seam",
37
37
  "agent_session:constructor": "internal accessor/plumbing, not a user-facing control seam",
38
+ "agent_session:getConfiguredModelChainState":
39
+ "internal model-profile transaction snapshot, not a user-facing SDK control seam",
40
+ "agent_session:getDefaultFallbackRuntimeState":
41
+ "internal model-profile transaction snapshot, not a user-facing SDK control seam",
42
+ "agent_session:restoreDefaultFallbackRuntimeState":
43
+ "internal rollback compensation, not a user-facing SDK control seam",
44
+ "agent_session:restoreModelSelectionForRollback":
45
+ "internal rollback compensation, not a user-facing SDK control seam",
38
46
  "agent_session:materializeActiveDefaultModelProfileAssignment":
39
47
  "internal extension selection materialization seam, not a user-facing SDK control seam",
40
48
  "agent_session:registerToolSessionCleanup":
@@ -115,41 +115,81 @@ if (rows.length > 0) {
115
115
  if (checkOnly) process.exit(0);
116
116
 
117
117
  const startedAt = performance.now();
118
- let commandReceipts = 0;
119
- let rowReceipts = 0;
120
118
  const perAdapter = new Map<string, number>();
121
119
 
122
- async function executeReceipt(argv: string[]): Promise<void> {
120
+ /**
121
+ * A receipt is already an isolated `bun test` process, so a manifest whose
122
+ * receipts are independent can run them through a bounded worker pool instead of
123
+ * one at a time — which is what made this gate the dominant cost of `check:ts`,
124
+ * a few hundred process startups serialized behind each other. Independence is
125
+ * not free, though: receipts that each spawn a detached SDK broker and load
126
+ * Node-API addons fail when they race, so concurrency is never assumed. It stays
127
+ * sequential unless the caller opts a specific manifest in through
128
+ * `GJC_MANIFEST_RECEIPT_CONCURRENCY`, and every receipt keeps its own process,
129
+ * its own argv, and its own receipt line either way.
130
+ */
131
+ const receiptConcurrency = (() => {
132
+ const configured = Number(process.env.GJC_MANIFEST_RECEIPT_CONCURRENCY);
133
+ return Number.isSafeInteger(configured) && configured >= 1 ? configured : 1;
134
+ })();
135
+
136
+ type ReceiptOutcome = { stdout: string; stderr: string; exitCode: number; tests: number | undefined };
137
+
138
+ function satisfiesReceipt(outcome: ReceiptOutcome): boolean {
139
+ return outcome.exitCode === 0 && outcome.tests !== undefined && outcome.tests >= 1;
140
+ }
141
+
142
+ async function runReceipt(argv: string[]): Promise<ReceiptOutcome> {
123
143
  const child = Bun.spawn(argv, { cwd: repoRoot, stdout: "pipe", stderr: "pipe" });
124
144
  const [stdout, stderr, exitCode] = await Promise.all([
125
145
  new Response(child.stdout).text(),
126
146
  new Response(child.stderr).text(),
127
147
  child.exited,
128
148
  ]);
129
- process.stdout.write(stdout);
130
- process.stderr.write(stderr);
131
- const tests = testCount(`${stdout}\n${stderr}`);
132
- process.stdout.write(`receipt: ${argv.join(" ")} exit=${exitCode} tests=${tests ?? "unknown"}\n`);
133
- if (exitCode === 0 && tests !== undefined && tests >= 1) return;
134
- const reason = exitCode !== 0 ? `exit ${exitCode}` : "did not report at least one test";
135
- process.stderr.write(`Manifest receipt failed: ${argv.join(" ")} (${reason})\n`);
136
- process.exit(1);
149
+ return { stdout, stderr, exitCode, tests: testCount(`${stdout}\n${stderr}`) };
137
150
  }
138
151
 
139
- for (const command of manifest.commands) {
140
- await executeReceipt(command.argv);
141
- commandReceipts++;
152
+ /**
153
+ * Runs one phase to completion and then reports it in manifest order. A failing
154
+ * receipt stops the pool from claiming further work and exits non-zero, so the
155
+ * gate still fails closed; receipts already in flight are drained rather than
156
+ * abandoned, and receipts that were never claimed are never reported as evidence.
157
+ */
158
+ async function executePhase(argvs: string[][]): Promise<void> {
159
+ const outcomes = new Array<ReceiptOutcome | undefined>(argvs.length);
160
+ let claimed = 0;
161
+ let stopped = false;
162
+ const drain = async (): Promise<void> => {
163
+ for (;;) {
164
+ const index = claimed++;
165
+ if (stopped || index >= argvs.length) return;
166
+ const outcome = await runReceipt(argvs[index]!);
167
+ outcomes[index] = outcome;
168
+ if (!satisfiesReceipt(outcome)) stopped = true;
169
+ }
170
+ };
171
+ await Promise.all(Array.from({ length: Math.min(receiptConcurrency, argvs.length) }, drain));
172
+ for (const [index, argv] of argvs.entries()) {
173
+ const outcome = outcomes[index];
174
+ if (!outcome) continue;
175
+ process.stdout.write(outcome.stdout);
176
+ process.stderr.write(outcome.stderr);
177
+ process.stdout.write(`receipt: ${argv.join(" ")} exit=${outcome.exitCode} tests=${outcome.tests ?? "unknown"}\n`);
178
+ if (satisfiesReceipt(outcome)) continue;
179
+ const reason = outcome.exitCode !== 0 ? `exit ${outcome.exitCode}` : "did not report at least one test";
180
+ process.stderr.write(`Manifest receipt failed: ${argv.join(" ")} (${reason})\n`);
181
+ process.exit(1);
182
+ }
142
183
  }
143
- process.stdout.write(`manifest command receipts complete: ${commandReceipts}\n`);
144
184
 
145
- for (const row of rows) {
146
- await executeReceipt(row.argv);
147
- rowReceipts++;
148
- perAdapter.set(row.adapter, (perAdapter.get(row.adapter) ?? 0) + 1);
149
- }
185
+ await executePhase(manifest.commands.map(command => command.argv));
186
+ process.stdout.write(`manifest command receipts complete: ${manifest.commands.length}\n`);
187
+
188
+ await executePhase(rows.map(row => row.argv));
189
+ for (const row of rows) perAdapter.set(row.adapter, (perAdapter.get(row.adapter) ?? 0) + 1);
150
190
  if (rows.length > 0) {
151
191
  process.stdout.write(
152
- `manifest row receipts complete: ${rowReceipts} (${[...perAdapter].map(([adapter, count]) => `${adapter}=${count}`).join(", ")})\n`,
192
+ `manifest row receipts complete: ${rows.length} (${[...perAdapter].map(([adapter, count]) => `${adapter}=${count}`).join(", ")})\n`,
153
193
  );
154
194
  }
155
195
  process.stdout.write(`manifest receipts runtime=${Math.round(performance.now() - startedAt)}ms\n`);
@@ -1635,14 +1635,14 @@ function lineNumber(contents: string, offset: number): number {
1635
1635
  const machineEntrypoints = new Map<string, string>([
1636
1636
  ["packages/coding-agent/src/modes/acp/acp-agent.ts", "ACP"],
1637
1637
  ["packages/coding-agent/src/commands/mcp-serve.ts", "MCP"],
1638
- ["packages/coding-agent/src/sdk/cli/session-cli.ts", "daemon session CLI"],
1638
+ ["packages/coding-agent/src/sdk/cli/session-cli.ts", "sdk session CLI"],
1639
1639
  ]);
1640
1640
 
1641
1641
  const machineWrapperEntrypoints = new Map<string, string>([
1642
1642
  ["packages/coding-agent/src/commands/acp.ts", "ACP command"],
1643
1643
  ["packages/coding-agent/src/commands/daemon.ts", "daemon command"],
1644
1644
  ["packages/coding-agent/src/commands/mcp-serve.ts", "MCP command"],
1645
- ["packages/coding-agent/src/sdk/cli/session-cli.ts", "daemon session CLI"],
1645
+ ["packages/coding-agent/src/sdk/cli/session-cli.ts", "sdk session CLI"],
1646
1646
  ]);
1647
1647
  const rootAcpEntrypoint = "packages/coding-agent/src/main.ts";
1648
1648
  const directMachineWrapperRoutePattern =
@@ -1938,9 +1938,14 @@ async function scan(): Promise<string[]> {
1938
1938
  violations.push(`${file}: shipped ACP command does not dispatch through the root ACP bootstrap`);
1939
1939
  }
1940
1940
  }
1941
- if (file === "packages/coding-agent/src/commands/daemon.ts") {
1941
+ if (file === "packages/coding-agent/src/commands/sdk.ts") {
1942
1942
  if (!/runSdkSessionCli\s*\(/.test(contents)) {
1943
- violations.push(`${file}: shipped daemon session command does not dispatch the SDK session CLI`);
1943
+ violations.push(`${file}: shipped sdk session command does not dispatch the SDK session CLI`);
1944
+ }
1945
+ }
1946
+ if (file === "packages/coding-agent/src/commands/daemon.ts") {
1947
+ if (/\brawAction\s*===\s*["']session["']|\baction:\s*["']session["']\s*[,}]/.test(contents)) {
1948
+ violations.push(`${file}: daemon command retained removed SDK session routing`);
1944
1949
  }
1945
1950
  }
1946
1951
  if (file === "packages/coding-agent/src/modes/acp/acp-agent.ts") {
package/src/cli/args.ts CHANGED
@@ -7,9 +7,34 @@ import { logger } from "@gajae-code/utils";
7
7
  import { CliParseError } from "@gajae-code/utils/cli";
8
8
  import { parseEffort } from "../thinking";
9
9
  import { BUILTIN_TOOLS } from "../tools";
10
+ import { type ConsumerLaunchFlagName, LAUNCH_PARSE_FLAGS, launchFlagIsOwnedBy } from "./root-flags";
11
+
12
+ const ROOT_FLAG_TOKENS = new Set<string>();
13
+ for (const [name, descriptor] of Object.entries(LAUNCH_PARSE_FLAGS)) {
14
+ ROOT_FLAG_TOKENS.add(`--${name}`);
15
+ if (descriptor.char) ROOT_FLAG_TOKENS.add(`-${descriptor.char}`);
16
+ }
17
+
18
+ const INTERNAL_ROOT_FLAG_TOKENS = new Set(["--help", "-h", "--version", "-v", "--session", "--provider-session-id"]);
19
+
20
+ function isExternallyParsedRootFlagToken(arg: string): boolean {
21
+ return (
22
+ arg === "--acp-terminal-auth" ||
23
+ arg === "--worktree" ||
24
+ arg === "-w" ||
25
+ arg.startsWith("-w=") ||
26
+ arg.startsWith("-w")
27
+ );
28
+ }
29
+
30
+ function isKnownRootFlagToken(arg: string): boolean {
31
+ return ROOT_FLAG_TOKENS.has(arg) || INTERNAL_ROOT_FLAG_TOKENS.has(arg) || isExternallyParsedRootFlagToken(arg);
32
+ }
10
33
 
11
34
  export type Mode = "text" | "json" | "acp";
12
35
 
36
+ export type ParseArgsAuthority = "local" | "acp" | "deferred";
37
+
13
38
  export interface Args {
14
39
  cwd?: string;
15
40
  allowHome?: boolean;
@@ -58,12 +83,14 @@ export interface Args {
58
83
  noTitle?: boolean;
59
84
  messages: string[];
60
85
  fileArgs: string[];
61
- /** Retained for test/runtime compatibility; extension-defined flags are no longer parsed. */
86
+ /** Flags unknown to every launch parser; their consumer supplies the diagnostic. */
62
87
  unknownFlags: Map<string, boolean | string>;
63
88
  /** Exact interactive startup login intent, recognized before model-profile activation. */
64
89
  authBootstrap?: true;
65
90
  }
66
91
 
92
+ const CONSUMER_FLAGS_BY_ARGS = new WeakMap<Args, Map<ConsumerLaunchFlagName, string>>();
93
+
67
94
  function isStartupSlashCommandArg(arg: string | undefined): boolean {
68
95
  return (
69
96
  arg === "/provider" ||
@@ -99,12 +126,13 @@ function takePromptValue(
99
126
  return takeFlagValue(args, index, flag, allowInlineDashPrefixed || allowSeparatedDashPrefixed);
100
127
  }
101
128
 
102
- export function parseArgs(args: string[]): Args {
129
+ export function parseArgs(args: string[], authority: ParseArgsAuthority = "local"): Args {
103
130
  const result: Args = {
104
131
  messages: [],
105
132
  fileArgs: [],
106
133
  unknownFlags: new Map(),
107
134
  };
135
+ const consumerFlags = new Map<ConsumerLaunchFlagName, string>();
108
136
 
109
137
  for (let i = 0; i < args.length; i++) {
110
138
  let arg = args[i];
@@ -120,6 +148,13 @@ export function parseArgs(args: string[]): Args {
120
148
  result.messages.push(args.slice(i).join(" "));
121
149
  break;
122
150
  }
151
+ if (arg === "--") {
152
+ for (const positional of args.slice(i + 1)) {
153
+ if (positional.startsWith("@")) result.fileArgs.push(positional.slice(1));
154
+ else result.messages.push(positional);
155
+ }
156
+ break;
157
+ }
123
158
 
124
159
  // Support --flag=value syntax (e.g. --tools=ask,read)
125
160
  if (arg.startsWith("--") && arg.includes("=")) {
@@ -130,6 +165,11 @@ export function parseArgs(args: string[]): Args {
130
165
  // Insert the value so the existing "args[++i]" logic picks it up
131
166
  args.splice(i + 1, 0, value);
132
167
  }
168
+ if (arg.startsWith("-") && !isKnownRootFlagToken(arg)) {
169
+ result.unknownFlags.set(arg, true);
170
+ if (hasInlineValue) i++;
171
+ continue;
172
+ }
133
173
 
134
174
  if (arg === "--help" || arg === "-h") {
135
175
  result.help = true;
@@ -239,18 +279,23 @@ export function parseArgs(args: string[]): Args {
239
279
  } else if (arg === "--extension" || arg === "-e") {
240
280
  const extension = takeFlagValue(args, i++, "--extension");
241
281
  result.extensions = [...(result.extensions ?? []), extension];
282
+ consumerFlags.set("extension", "--extension");
242
283
  } else if (arg === "--hook") {
243
284
  const hook = takeFlagValue(args, i++, "--hook");
244
285
  result.hooks = [...(result.hooks ?? []), hook];
286
+ consumerFlags.set("hook", "--hook");
245
287
  } else if (arg === "--no-extensions") {
246
288
  result.noExtensions = true;
289
+ consumerFlags.set("no-extensions", "--no-extensions");
247
290
  } else if (arg === "--no-skills") {
248
291
  result.noSkills = true;
292
+ consumerFlags.set("no-skills", "--no-skills");
249
293
  } else if (arg === "--skills") {
250
294
  result.skills = takeFlagValue(args, i++, "--skills")
251
295
  .split(",")
252
296
  .map(s => s.trim())
253
297
  .filter(Boolean);
298
+ consumerFlags.set("skills", "--skills");
254
299
  } else if (arg === "--tools") {
255
300
  const toolNames = takeFlagValue(args, i++, "--tools")
256
301
  .split(",")
@@ -302,24 +347,32 @@ export function parseArgs(args: string[]): Args {
302
347
  }
303
348
  } else if (arg.startsWith("@")) {
304
349
  result.fileArgs.push(arg.slice(1)); // Remove @ prefix
305
- } else if (arg.startsWith("-")) {
306
- result.unknownFlags.set(arg, true);
307
- } else {
350
+ } else if (!arg.startsWith("-")) {
308
351
  result.messages.push(arg);
352
+ } else if (!isExternallyParsedRootFlagToken(arg)) {
353
+ throw new CliParseError(`Root option is declared but not parsed: ${arg}`);
309
354
  }
310
355
  }
311
356
 
312
357
  if (result.default && !result.mpreset) {
313
358
  throw new CliParseError("--default requires --mpreset <name>");
314
359
  }
315
- if (
316
- result.mcpConfig !== undefined &&
317
- (result.mode === "acp" || result.listModels !== undefined || result.export !== undefined)
318
- ) {
360
+ if (result.mcpConfig !== undefined && (result.listModels !== undefined || result.export !== undefined)) {
319
361
  throw new CliParseError(
320
362
  "--mcp-config is only supported in standalone interactive, tmux, print, text, or json modes.",
321
363
  );
322
364
  }
323
365
 
366
+ CONSUMER_FLAGS_BY_ARGS.set(result, consumerFlags);
367
+ if (authority === "local") assertLocalLaunchArgs(result);
324
368
  return result;
325
369
  }
370
+
371
+ /** Reject flags whose only owners are non-local startup consumers. */
372
+ export function assertLocalLaunchArgs(parsed: Args): void {
373
+ const unknown = parsed.unknownFlags.keys().next().value;
374
+ if (unknown) throw new CliParseError(`Unknown option: ${unknown}`);
375
+ for (const [name, token] of CONSUMER_FLAGS_BY_ARGS.get(parsed) ?? []) {
376
+ if (!launchFlagIsOwnedBy(name, "local")) throw new CliParseError(`Unknown option: ${token}`);
377
+ }
378
+ }
@@ -107,6 +107,7 @@ function figOptionFromFlag(name: string, descriptor: FlagDescriptor): FigOption
107
107
  const arg: FigArg = { name: optionArgName(name, descriptor) };
108
108
  const suggestions = argSuggestions(descriptor.options);
109
109
  if (suggestions) arg.suggestions = suggestions;
110
+ if (descriptor.optionalValue) arg.isOptional = true;
110
111
  option.args = arg;
111
112
  }
112
113
  return option;
@@ -30,6 +30,7 @@ export function getExtraHelpText(): string {
30
30
  ${APP_NAME} web-search - Search the web from the CLI (alias: q)
31
31
  ${APP_NAME} codex-native-hook - Run Codex native hook integration
32
32
  ${APP_NAME} gc - Run garbage-collection/cleanup helpers
33
+ ${APP_NAME} quick-lane - Classify a task into quick lane or deep path
33
34
  ${APP_NAME} <command> --help - Show command-specific help
34
35
 
35
36
  Environment Variables:
@@ -0,0 +1,100 @@
1
+ import { type FlagDescriptor, Flags } from "@gajae-code/utils/cli";
2
+
3
+ const ROOT_THINKING_EFFORTS = ["minimal", "low", "medium", "high", "xhigh", "max"] as const;
4
+
5
+ /** Public launch flags shared by root help, completion, and the launch command. */
6
+ export const ROOT_LAUNCH_FLAGS = {
7
+ model: Flags.string({ description: 'Model to use (fuzzy match: "opus", "gpt-5.2", or "openai/gpt-5.2")' }),
8
+ smol: Flags.string({ description: "Smol/fast model for lightweight tasks (or GJC_SMOL_MODEL env)" }),
9
+ slow: Flags.string({ description: "Slow/reasoning model for thorough analysis (or GJC_SLOW_MODEL env)" }),
10
+ plan: Flags.string({ description: "Plan model for architectural planning (or GJC_PLAN_MODEL env)" }),
11
+ mpreset: Flags.string({ description: "Model profile preset to activate for this session" }),
12
+ default: Flags.boolean({ description: "Persist --mpreset as the default model profile" }),
13
+ provider: Flags.string({ description: "Provider to use (legacy; prefer --model)" }),
14
+ "api-key": Flags.string({ description: "API key (defaults to env vars)" }),
15
+ credential: Flags.string({
16
+ description:
17
+ "Stored credential selector: email:<addr>, id:<n>, account:<id>, project:<id>, or provider/email:<addr>",
18
+ }),
19
+ "system-prompt": Flags.string({ description: "System prompt (default: coding assistant prompt)" }),
20
+ "append-system-prompt": Flags.string({ description: "Append text or file contents to the system prompt" }),
21
+ "mcp-config": Flags.string({ description: "Tools-only MCP config file (absolute path)" }),
22
+ "clipboard-transport": Flags.string({
23
+ description: "Clipboard transport: auto (default), native, osc52, or ssh",
24
+ options: ["auto", "native", "osc52", "ssh"],
25
+ }),
26
+ "clipboard-ssh-host": Flags.string({
27
+ description: "SSH host alias for --clipboard-transport ssh (from ~/.ssh/config)",
28
+ }),
29
+ "allow-home": Flags.boolean({ description: "Allow starting in ~ without auto-switching to a temp dir" }),
30
+ mode: Flags.string({
31
+ description: "Output mode: text (default), json, or acp",
32
+ options: ["text", "json", "acp"],
33
+ }),
34
+ print: Flags.boolean({ char: "p", description: "Non-interactive mode: process prompt and exit" }),
35
+ continue: Flags.boolean({ char: "c", description: "Continue previous session" }),
36
+ resume: Flags.string({
37
+ char: "r",
38
+ description: "Resume a session (by ID prefix, path, or picker if omitted)",
39
+ optionalValue: true,
40
+ }),
41
+ fork: Flags.string({ description: "Fork a session (by ID prefix or path)" }),
42
+ worktree: Flags.string({
43
+ char: "w",
44
+ description: "Launch in a managed worktree (optional branch name)",
45
+ optionalValue: true,
46
+ }),
47
+ "session-dir": Flags.string({
48
+ description: "Explicit session storage directory and lookup override (default uses managed v2 workspace scope)",
49
+ }),
50
+ "no-session": Flags.boolean({ description: "Don't save session (ephemeral)" }),
51
+ models: Flags.string({ description: "Comma-separated model patterns for Alt+N cycling" }),
52
+ "no-tools": Flags.boolean({ description: "Disable all built-in tools" }),
53
+ "no-lsp": Flags.boolean({ description: "Disable LSP tools, formatting, and diagnostics" }),
54
+ "no-pty": Flags.boolean({ description: "Disable PTY-based interactive bash execution" }),
55
+ tmux: Flags.boolean({ description: "Launch interactive startup inside tmux" }),
56
+ tools: Flags.string({ description: "Comma-separated list of tools to enable (default: all)" }),
57
+ thinking: Flags.string({
58
+ description: `Set thinking level: ${ROOT_THINKING_EFFORTS.join(", ")}`,
59
+ options: ROOT_THINKING_EFFORTS,
60
+ }),
61
+ "no-rules": Flags.boolean({ description: "Disable rules discovery and loading" }),
62
+ export: Flags.string({ description: "Export session file to HTML and exit" }),
63
+ "list-models": Flags.string({
64
+ description: "List available models (with optional fuzzy search)",
65
+ optionalValue: true,
66
+ }),
67
+ "no-title": Flags.boolean({ description: "Disable title auto-generation" }),
68
+ };
69
+
70
+ export type ConsumerLaunchFlagName = "hook" | "extension" | "no-extensions" | "no-skills" | "skills";
71
+
72
+ export type LaunchFlagConsumer = "acp" | "local";
73
+
74
+ /**
75
+ * Flags accepted only so their owning startup consumer can classify them. They
76
+ * deliberately stay out of root help and completion.
77
+ */
78
+ export const CONSUMER_LAUNCH_FLAGS: Record<ConsumerLaunchFlagName, FlagDescriptor> = {
79
+ hook: Flags.string({ multiple: true }),
80
+ extension: Flags.string({ char: "e", multiple: true }),
81
+ "no-extensions": Flags.boolean(),
82
+ "no-skills": Flags.boolean(),
83
+ skills: Flags.string(),
84
+ };
85
+
86
+ /** Every flag understood by the launch argument parser, including hidden consumer-owned flags. */
87
+ export const LAUNCH_PARSE_FLAGS = { ...ROOT_LAUNCH_FLAGS, ...CONSUMER_LAUNCH_FLAGS };
88
+
89
+ /** Startup consumers that may receive a hidden launch flag. */
90
+ export const LAUNCH_FLAG_CONSUMERS: Record<ConsumerLaunchFlagName, readonly LaunchFlagConsumer[]> = {
91
+ hook: ["acp"],
92
+ extension: ["acp"],
93
+ "no-extensions": ["acp"],
94
+ "no-skills": ["acp", "local"],
95
+ skills: ["acp"],
96
+ };
97
+
98
+ export function launchFlagIsOwnedBy(name: ConsumerLaunchFlagName, consumer: LaunchFlagConsumer): boolean {
99
+ return LAUNCH_FLAG_CONSUMERS[name].includes(consumer);
100
+ }
@@ -496,7 +496,7 @@ async function handlePythonSetup(flags: { json?: boolean; check?: boolean }): Pr
496
496
  }
497
497
 
498
498
  async function handleSttSetup(flags: { json?: boolean; check?: boolean }): Promise<void> {
499
- const { checkDependencies, formatDependencyStatus } = await import("../stt/setup");
499
+ const { checkDependencies, formatDependencyStatus, formatSTTUsage } = await import("../stt/setup");
500
500
  const status = await checkDependencies();
501
501
 
502
502
  if (flags.json) {
@@ -509,6 +509,7 @@ async function handleSttSetup(flags: { json?: boolean; check?: boolean }): Promi
509
509
 
510
510
  if (status.recorder.available && status.python.available && status.whisper.available) {
511
511
  console.log(chalk.green(`\n${theme.status.success} Speech-to-text is ready`));
512
+ console.log(`\n${formatSTTUsage()}`);
512
513
  return;
513
514
  }
514
515
 
@@ -542,6 +543,7 @@ async function handleSttSetup(flags: { json?: boolean; check?: boolean }): Promi
542
543
  const recheck = await checkDependencies();
543
544
  if (recheck.recorder.available && recheck.python.available && recheck.whisper.available) {
544
545
  console.log(chalk.green(`\n${theme.status.success} Speech-to-text is ready`));
546
+ console.log(`\n${formatSTTUsage()}`);
545
547
  } else {
546
548
  console.error(chalk.red(`\n${theme.status.error} Setup incomplete`));
547
549
  console.log(formatDependencyStatus(recheck));
@@ -733,6 +735,8 @@ ${chalk.bold("Provider example:")}
733
735
  ${APP_NAME} setup provider --preset glm
734
736
  ${APP_NAME} setup provider --preset cline-pass
735
737
  ${APP_NAME} setup provider --preset commandcode-goat
738
+ ${APP_NAME} setup provider --preset litellm --base-url https://litellm.example.com/v1
739
+ ${APP_NAME} setup provider --preset openai-compatible-proxy --base-url https://gateway.example.com/v1
736
740
  MY_PROVIDER_KEY=sk-... ${APP_NAME} setup provider --compat openai --provider my-oai --base-url https://api.example.com/v1 --api-key-env MY_PROVIDER_KEY --model gpt-example
737
741
 
738
742
  ${chalk.bold("Hermes example:")}
@@ -748,7 +752,7 @@ ${chalk.bold("Options:")}
748
752
  --preset Provider preset id (run setup provider --help to list available presets)
749
753
  --compat Provider compatibility: openai or anthropic
750
754
  --provider Provider id to add to models.yml
751
- --base-url Provider API base URL
755
+ --base-url Provider API base URL (required for proxy presets: litellm, openai-compatible-proxy)
752
756
  --api-key-env Read provider API key from this environment variable
753
757
  --model, --models Model id to add (repeat or comma-separate)
754
758
  --models-path Override models config path