@gajae-code/coding-agent 0.11.6 → 0.11.8
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.
- package/CHANGELOG.md +92 -0
- package/dist/types/capability/index.d.ts +10 -20
- package/dist/types/capability/types.d.ts +3 -0
- package/dist/types/cli/args.d.ts +0 -2
- package/dist/types/commands/daemon.d.ts +2 -2
- package/dist/types/commands/sdk.d.ts +20 -2
- package/dist/types/config/keybindings.d.ts +34 -4
- package/dist/types/config/model-profile-activation.d.ts +4 -3
- package/dist/types/config/model-profile-contract.d.ts +38 -0
- package/dist/types/config/settings-schema.d.ts +70 -7
- package/dist/types/edit/modes/patch.d.ts +13 -0
- package/dist/types/edit/path-mutation-lock.d.ts +15 -0
- package/dist/types/eval/py/executor.d.ts +1 -1
- package/dist/types/eval/py/runner-artifact.d.ts +8 -0
- package/dist/types/eval/py/tool-bridge.d.ts +1 -2
- package/dist/types/gjc-runtime/repository-binding.d.ts +63 -0
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +6 -5
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +20 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +43 -5
- package/dist/types/main.d.ts +32 -1
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +2 -1
- package/dist/types/modes/components/tool-status-header.d.ts +4 -2
- package/dist/types/modes/components/welcome.d.ts +2 -0
- package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -1
- package/dist/types/modes/interactive-mode.d.ts +7 -2
- package/dist/types/modes/prompt-action-autocomplete.d.ts +6 -1
- package/dist/types/modes/prompt-suggestion-controller.d.ts +35 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -2
- package/dist/types/modes/types.d.ts +4 -0
- package/dist/types/modes/utils/hotkeys-markdown.d.ts +2 -1
- package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
- package/dist/types/runtime-mcp/manager.d.ts +1 -1
- package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -5
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +14 -0
- package/dist/types/sdk/broker/broker.d.ts +2 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +6 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +6 -1
- package/dist/types/sdk/bus/config-commands.d.ts +2 -2
- package/dist/types/sdk/bus/config.d.ts +2 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +26 -1
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
- package/dist/types/sdk/bus/notification-orchestration.d.ts +1 -0
- package/dist/types/sdk/bus/notification-service.d.ts +34 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +105 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +18 -3
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +189 -4
- package/dist/types/sdk/bus/telegram-reference.d.ts +2 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
- package/dist/types/sdk/client/discovery.d.ts +2 -0
- package/dist/types/sdk/client/liveness.d.ts +7 -0
- package/dist/types/sdk/host/control/operations.d.ts +1 -1
- package/dist/types/sdk/host/host.d.ts +1 -1
- package/dist/types/sdk/host/query/handlers.d.ts +9 -0
- package/dist/types/sdk/index.d.ts +2 -0
- package/dist/types/sdk/prompt-status.d.ts +88 -0
- package/dist/types/sdk/session-directory.d.ts +1 -1
- package/dist/types/sdk/startup-capability.d.ts +3 -0
- package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
- package/dist/types/sdk/transport/index.d.ts +12 -0
- package/dist/types/sdk/transport/relay.d.ts +43 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
- package/dist/types/sdk/transport/socket.d.ts +7 -0
- package/dist/types/sdk/transport/stdio.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +30 -5
- package/dist/types/session/btw-contract.d.ts +16 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +32 -9
- package/dist/types/session/internal/managed-session-storage.d.ts +27 -10
- package/dist/types/session/internal/native-publish-outcome.d.ts +48 -0
- package/dist/types/session/session-manager.d.ts +25 -4
- package/dist/types/session/session-storage.d.ts +18 -0
- package/dist/types/setup/credential-import.d.ts +5 -1
- package/dist/types/setup/provider-onboarding.d.ts +2 -0
- package/dist/types/ssh/utils.d.ts +1 -0
- package/dist/types/task/discovery.d.ts +3 -1
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/task/types.d.ts +94 -0
- package/dist/types/tools/ask.d.ts +454 -174
- package/dist/types/tools/fetch.d.ts +5 -8
- package/dist/types/tools/image-gen.d.ts +63 -1
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/skill-discovery.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +7 -0
- package/dist/types/utils/prompt-suggestion.d.ts +33 -0
- package/dist/types/utils/shell-snapshot.d.ts +12 -0
- package/dist/types/web/insane/bridge.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +17 -0
- package/package.json +8 -8
- package/scripts/capture-platform-shortcut-labels-showcase.ts +342 -0
- package/scripts/dogfood-repository-binding.ts +209 -0
- package/scripts/generate-sdk-operation-inventory.ts +4 -0
- package/scripts/run-test-manifest.ts +4 -4
- package/src/capability/index.ts +50 -42
- package/src/capability/types.ts +3 -0
- package/src/cli/args.ts +2 -92
- package/src/cli/notify-cli.ts +5 -38
- package/src/cli/setup-cli.ts +10 -4
- package/src/cli.ts +52 -9
- package/src/commands/daemon.ts +22 -5
- package/src/commands/sdk.ts +44 -11
- package/src/config/keybindings.ts +158 -25
- package/src/config/model-profile-activation.ts +7 -18
- package/src/config/model-profile-contract.ts +161 -0
- package/src/config/model-profiles.ts +18 -0
- package/src/config/model-registry.ts +11 -1
- package/src/config/settings-schema.ts +73 -7
- package/src/coordinator-mcp/model-preset.ts +21 -74
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +2 -2
- package/src/defaults/gjc/skills/ralplan/SKILL.md +3 -1
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +42 -1
- package/src/discovery/ssh.ts +12 -1
- package/src/edit/index.ts +3 -6
- package/src/edit/modes/patch.ts +38 -1
- package/src/edit/modes/replace.ts +42 -0
- package/src/edit/path-mutation-lock.ts +112 -0
- package/src/eval/py/executor.ts +30 -11
- package/src/eval/py/kernel.ts +1 -21
- package/src/eval/py/prelude.py +2 -2
- package/src/eval/py/runner-artifact.ts +84 -0
- package/src/eval/py/tool-bridge.ts +34 -18
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +2 -1
- package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
- package/src/gjc-runtime/launch-tmux.ts +1 -1
- package/src/gjc-runtime/managed-owner-supervisor.ts +83 -4
- package/src/gjc-runtime/ralplan-runtime.ts +75 -3
- package/src/gjc-runtime/repository-binding.ts +267 -0
- package/src/gjc-runtime/session-state-sidecar.ts +25 -9
- package/src/gjc-runtime/tmux-owner-isolation.ts +2 -1
- package/src/gjc-runtime/tmux-sessions.ts +45 -6
- package/src/gjc-runtime/ultragoal-guard.ts +93 -15
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +103 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +456 -31
- package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
- package/src/gjc-runtime/workflow-manifest.ts +23 -0
- package/src/internal-urls/docs-index.generated.ts +12 -10
- package/src/internal-urls/local-protocol.ts +64 -21
- package/src/internal-urls/mcp-protocol.ts +73 -11
- package/src/main.ts +111 -37
- package/src/modes/DESIGN.md +5 -0
- package/src/modes/acp/acp-agent.ts +50 -16
- package/src/modes/action-registry.ts +1 -1
- package/src/modes/components/btw-panel.ts +82 -16
- package/src/modes/components/model-selector.ts +73 -11
- package/src/modes/components/plan-preview-overlay.ts +1 -1
- package/src/modes/components/runtime-mcp-add-wizard.ts +5 -0
- package/src/modes/components/tool-status-header.ts +25 -4
- package/src/modes/components/welcome.ts +22 -18
- package/src/modes/controllers/btw-controller.ts +119 -36
- package/src/modes/controllers/command-controller.ts +97 -54
- package/src/modes/controllers/event-controller.ts +10 -0
- package/src/modes/controllers/input-controller.ts +38 -2
- package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -6
- package/src/modes/controllers/selector-controller.ts +149 -63
- package/src/modes/interactive-mode.ts +57 -34
- package/src/modes/prompt-action-autocomplete.ts +32 -13
- package/src/modes/prompt-suggestion-controller.ts +96 -0
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -2
- package/src/modes/types.ts +4 -0
- package/src/modes/utils/hotkeys-markdown.ts +64 -36
- package/src/modes/utils/ui-helpers.ts +5 -3
- package/src/prompts/agents/architect.md +0 -1
- package/src/prompts/agents/critic.md +0 -1
- package/src/prompts/system/btw-user.md +3 -8
- package/src/prompts/system/prompt-suggestion-system.md +32 -0
- package/src/prompts/system/system-prompt.md +6 -4
- package/src/prompts/tools/cron.md +3 -1
- package/src/prompts/tools/skill-discovery.md +1 -0
- package/src/runtime-mcp/client.ts +41 -55
- package/src/runtime-mcp/content-limits.ts +71 -0
- package/src/runtime-mcp/json-rpc.ts +23 -9
- package/src/runtime-mcp/manager.ts +51 -53
- package/src/runtime-mcp/oauth-flow.ts +0 -72
- package/src/runtime-mcp/plugin-network-boundary.ts +101 -0
- package/src/runtime-mcp/transports/http.ts +63 -22
- package/src/sdk/broker/broker.ts +34 -20
- package/src/sdk/broker/lifecycle.ts +185 -36
- package/src/sdk/bus/chat-daemon-control.ts +19 -5
- package/src/sdk/bus/config-commands.ts +2 -2
- package/src/sdk/bus/config.ts +9 -1
- package/src/sdk/bus/conversation-store.ts +40 -6
- package/src/sdk/bus/index.ts +244 -70
- package/src/sdk/bus/lifecycle-commands.ts +63 -10
- package/src/sdk/bus/lifecycle-control-runtime.ts +11 -2
- package/src/sdk/bus/lifecycle-orchestrator.ts +32 -1
- package/src/sdk/bus/notification-orchestration.ts +12 -0
- package/src/sdk/bus/notification-service.ts +68 -20
- package/src/sdk/bus/prompt-reconciliation.ts +239 -0
- package/src/sdk/bus/recent-activity.ts +90 -26
- package/src/sdk/bus/telegram-daemon-contract.ts +18 -3
- package/src/sdk/bus/telegram-daemon-control.ts +147 -35
- package/src/sdk/bus/telegram-daemon.ts +2463 -450
- package/src/sdk/bus/telegram-reference.ts +20 -2
- package/src/sdk/bus/topic-registry.ts +451 -12
- package/src/sdk/cli/session-cli.ts +15 -2
- package/src/sdk/client/discovery.ts +19 -3
- package/src/sdk/client/liveness.ts +49 -0
- package/src/sdk/host/control/dispatch.ts +1 -1
- package/src/sdk/host/control/operations.ts +1 -1
- package/src/sdk/host/host.ts +2 -6
- package/src/sdk/host/query/handlers.ts +70 -5
- package/src/sdk/index.ts +12 -0
- package/src/sdk/prompt-status.ts +97 -0
- package/src/sdk/protocol/operation-inventory.generated.json +58 -0
- package/src/sdk/protocol/operation-registry.ts +18 -4
- package/src/sdk/session-directory.ts +5 -1
- package/src/sdk/session.ts +31 -5
- package/src/sdk/startup-capability.ts +9 -1
- package/src/sdk/transport/auth-preface.ts +82 -0
- package/src/sdk/transport/index.ts +18 -0
- package/src/sdk/transport/relay.ts +252 -0
- package/src/sdk/transport/serve-cli.ts +105 -0
- package/src/sdk/transport/socket.ts +197 -0
- package/src/sdk/transport/stdio.ts +17 -0
- package/src/session/agent-session.ts +292 -154
- package/src/session/blob-store.ts +25 -7
- package/src/session/btw-contract.ts +59 -0
- package/src/session/internal/managed-session-scope.ts +1163 -137
- package/src/session/internal/managed-session-storage.ts +397 -234
- package/src/session/internal/native-publish-outcome.ts +266 -0
- package/src/session/session-manager.ts +620 -403
- package/src/session/session-storage.ts +128 -11
- package/src/setup/credential-import.ts +28 -3
- package/src/setup/provider-onboarding.ts +30 -1
- package/src/setup/provider-presets.json +2 -1
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/ssh/utils.ts +14 -0
- package/src/task/discovery.ts +8 -2
- package/src/task/gjc-command.ts +2 -2
- package/src/task/index.ts +121 -15
- package/src/task/receipt.ts +3 -0
- package/src/task/types.ts +34 -3
- package/src/tools/ask.ts +199 -89
- package/src/tools/ast-edit.ts +2 -2
- package/src/tools/bash-pty-selection.ts +2 -2
- package/src/tools/browser/screenshot-format.ts +6 -1
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +13 -131
- package/src/tools/image-gen.ts +476 -23
- package/src/tools/index.ts +4 -0
- package/src/tools/read.ts +2 -0
- package/src/tools/render-utils.ts +7 -1
- package/src/tools/skill-discovery.ts +39 -3
- package/src/tools/sqlite-reader.ts +63 -5
- package/src/utils/edit-mode.ts +2 -2
- package/src/utils/pasted-image-path.ts +15 -6
- package/src/utils/prompt-suggestion.ts +265 -0
- package/src/utils/shell-snapshot.ts +173 -63
- package/src/utils/sixel.ts +3 -3
- package/src/web/insane/bridge.ts +5 -1
- package/src/web/insane/url-guard.ts +140 -27
- package/src/web/scrapers/docs-rs.ts +30 -5
- package/src/web/scrapers/types.ts +19 -49
- package/src/web/scrapers/utils.ts +12 -26
package/src/cli.ts
CHANGED
|
@@ -8,6 +8,12 @@ import "@gajae-code/utils/postmortem";
|
|
|
8
8
|
import { Args, type CliConfig, Command, type CommandEntry, Flags, run } from "@gajae-code/utils/cli";
|
|
9
9
|
import { APP_NAME, formatBunRuntimeError, MIN_BUN_VERSION, VERSION } from "@gajae-code/utils/dirs";
|
|
10
10
|
import { runFixtureReport } from "./cli/fixture-report";
|
|
11
|
+
import { admitManagedOwnerBeforeCli, completeManagedOwnerRecovery } from "./gjc-runtime/managed-owner-admission";
|
|
12
|
+
import {
|
|
13
|
+
isManagedOwnerSupervisorArgv,
|
|
14
|
+
MANAGED_OWNER_CHILD_TOKEN_ENV,
|
|
15
|
+
runManagedOwnerSupervisor,
|
|
16
|
+
} from "./gjc-runtime/managed-owner-supervisor";
|
|
11
17
|
import { isTmuxOwnerIsolationCliArgv, runTmuxOwnerIsolationCliFromStdin } from "./gjc-runtime/tmux-owner-isolation-cli";
|
|
12
18
|
import { smokeTestTabWorker } from "./tools/browser/tab-worker-smoke";
|
|
13
19
|
|
|
@@ -287,9 +293,34 @@ export function normalizeResumeAlias(argv: readonly string[]): string[] {
|
|
|
287
293
|
return argv.length === 1 && argv[0] === "resume" ? ["--resume"] : [...argv];
|
|
288
294
|
}
|
|
289
295
|
|
|
296
|
+
function routeLegacyRootArgv(argv: readonly string[]): string[] | undefined {
|
|
297
|
+
if (argv[0] === "coordinator-mcp") return ["mcp-serve", "coordinator", ...argv.slice(1)];
|
|
298
|
+
if (argv[0] !== "--team") return undefined;
|
|
299
|
+
const sizeValues: string[] = [];
|
|
300
|
+
const remaining: string[] = [];
|
|
301
|
+
for (let index = 1; index < argv.length; index++) {
|
|
302
|
+
const arg = argv[index] ?? "";
|
|
303
|
+
if (arg === "--team-size") {
|
|
304
|
+
sizeValues.push(argv[index + 1] ?? "");
|
|
305
|
+
index++;
|
|
306
|
+
} else if (arg.startsWith("--team-size=")) {
|
|
307
|
+
sizeValues.push(arg.slice("--team-size=".length));
|
|
308
|
+
} else {
|
|
309
|
+
remaining.push(arg);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
const size = sizeValues[0];
|
|
313
|
+
if (sizeValues.length !== 1 || !size || !/^[1-9]\d*$/.test(size)) {
|
|
314
|
+
return ["team", "0", "invalid legacy --team-size"];
|
|
315
|
+
}
|
|
316
|
+
return ["team", size, ...remaining];
|
|
317
|
+
}
|
|
318
|
+
|
|
290
319
|
/** Apply the same default-launch routing used by runCli after root fast paths. */
|
|
291
320
|
export function routeRootArgv(argv: readonly string[]): string[] {
|
|
292
321
|
const normalizedArgv = normalizeResumeAlias(argv);
|
|
322
|
+
const legacyArgv = routeLegacyRootArgv(normalizedArgv);
|
|
323
|
+
if (legacyArgv) return legacyArgv;
|
|
293
324
|
const first = normalizedArgv[0];
|
|
294
325
|
return first === "--help" || first === "-h" || first === "--version" || first === "-v" || first === "help"
|
|
295
326
|
? normalizedArgv
|
|
@@ -325,6 +356,18 @@ export async function runCli(argv: string[]): Promise<void> {
|
|
|
325
356
|
await runTmuxOwnerIsolationCliFromStdin();
|
|
326
357
|
return;
|
|
327
358
|
}
|
|
359
|
+
if (isManagedOwnerSupervisorArgv(argv)) {
|
|
360
|
+
await runManagedOwnerSupervisor();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (process.env[MANAGED_OWNER_CHILD_TOKEN_ENV] !== undefined) {
|
|
364
|
+
const admission = await admitManagedOwnerBeforeCli();
|
|
365
|
+
if (admission.kind === "blocked") return;
|
|
366
|
+
if (admission.kind === "recovery") {
|
|
367
|
+
await completeManagedOwnerRecovery(admission.context);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
328
371
|
if (isNotifyDaemonInternalFastPath(argv)) {
|
|
329
372
|
await runNotifyDaemonInternalFastPath(argv);
|
|
330
373
|
return;
|
|
@@ -348,11 +391,9 @@ export async function runCli(argv: string[]): Promise<void> {
|
|
|
348
391
|
process.exitCode = await runFixtureReport(id);
|
|
349
392
|
return;
|
|
350
393
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
if (hasRootHelpFlag(argv)) {
|
|
394
|
+
const normalizedArgv = normalizeResumeAlias(argv);
|
|
395
|
+
const legacyArgv = routeLegacyRootArgv(normalizedArgv);
|
|
396
|
+
if (!legacyArgv && hasRootHelpFlag(normalizedArgv)) {
|
|
356
397
|
const { renderRootHelp } = await import("@gajae-code/utils/cli");
|
|
357
398
|
const { getExtraHelpText } = await import("./cli/fast-help");
|
|
358
399
|
renderRootHelp({ bin: APP_NAME, version: VERSION, commands: new Map([["launch", RootHelpCommand]]) });
|
|
@@ -362,14 +403,16 @@ export async function runCli(argv: string[]): Promise<void> {
|
|
|
362
403
|
}
|
|
363
404
|
return;
|
|
364
405
|
}
|
|
365
|
-
if (hasRootVersionFlag(
|
|
406
|
+
if (!legacyArgv && hasRootVersionFlag(normalizedArgv)) {
|
|
366
407
|
process.stdout.write(`${APP_NAME}/${VERSION}\n`);
|
|
367
408
|
return;
|
|
368
409
|
}
|
|
410
|
+
const runArgv = legacyArgv ?? routeRootArgv(normalizedArgv);
|
|
411
|
+
if (isStatsHelpFastPath(runArgv)) {
|
|
412
|
+
showStatsFastHelp();
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
369
415
|
await installRuntimeGlobals();
|
|
370
|
-
// --help and --version are handled by run() directly, don't rewrite those.
|
|
371
|
-
// Everything else that isn't a known subcommand routes to "launch".
|
|
372
|
-
const runArgv = routeRootArgv(argv);
|
|
373
416
|
return run({ bin: APP_NAME, version: VERSION, argv: runArgv, commands, help: showHelp });
|
|
374
417
|
}
|
|
375
418
|
|
package/src/commands/daemon.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Manage GJC background daemons (status/list/stop/reload).
|
|
3
3
|
*/
|
|
4
|
-
import { Args, Command, Flags } from "@gajae-code/utils/cli";
|
|
4
|
+
import { Args, CliParseError, Command, Flags } from "@gajae-code/utils/cli";
|
|
5
5
|
import {
|
|
6
6
|
type DaemonCommandAction,
|
|
7
7
|
type DaemonCommandArgs,
|
|
@@ -15,6 +15,18 @@ import { runSdkSessionCli } from "../sdk/cli";
|
|
|
15
15
|
|
|
16
16
|
const ACTIONS = [...DAEMON_ACTION_TOKENS, "discord-internal", "slack-internal", "session"] as const;
|
|
17
17
|
|
|
18
|
+
function parsePositiveTimeout(raw: string | undefined, flagName: string): number | undefined {
|
|
19
|
+
if (raw === undefined) return undefined;
|
|
20
|
+
if (!/^[0-9]+$/.test(raw)) {
|
|
21
|
+
throw new CliParseError(`Expected ${flagName} to be a positive safe integer, got "${raw}"`);
|
|
22
|
+
}
|
|
23
|
+
const value = Number(raw);
|
|
24
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
25
|
+
throw new CliParseError(`Expected ${flagName} to be a positive safe integer, got "${raw}"`);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
export default class Daemon extends Command {
|
|
19
31
|
static description =
|
|
20
32
|
"Manage GJC background daemons and SDK sessions. Routine use: `gjc daemon status` to check, `gjc daemon restart` to reload (spawns one if none is running). `stop`/`list` and the escalation flags below are advanced primitives.";
|
|
@@ -41,8 +53,8 @@ export default class Daemon extends Command {
|
|
|
41
53
|
all: Flags.boolean({ description: "Target all registered daemon kinds" }),
|
|
42
54
|
json: Flags.boolean({ description: "Emit JSON output" }),
|
|
43
55
|
force: Flags.boolean({ description: "Allow hard-kill escalation when graceful stop times out" }),
|
|
44
|
-
"graceful-timeout-ms": Flags.
|
|
45
|
-
"kill-timeout-ms": Flags.
|
|
56
|
+
"graceful-timeout-ms": Flags.string({ description: "Cooperative stop timeout before escalation" }),
|
|
57
|
+
"kill-timeout-ms": Flags.string({ description: "Wait for old pid death after SIGKILL" }),
|
|
46
58
|
"spawn-if-stopped": Flags.boolean({ description: "On reload, spawn even when no daemon is running" }),
|
|
47
59
|
smoke: Flags.boolean({ description: "Internal: run worker smoke without configuration or network" }),
|
|
48
60
|
"owner-id": Flags.string({ description: "Internal: daemon owner id" }),
|
|
@@ -64,6 +76,11 @@ export default class Daemon extends Command {
|
|
|
64
76
|
const rawAction = args.action ?? "status";
|
|
65
77
|
const positional = Array.isArray(args.kind) ? args.kind : args.kind ? [args.kind] : [];
|
|
66
78
|
const flagRec = flags as Record<string, unknown>;
|
|
79
|
+
const gracefulTimeoutMs = parsePositiveTimeout(
|
|
80
|
+
flagRec["graceful-timeout-ms"] as string | undefined,
|
|
81
|
+
"--graceful-timeout-ms",
|
|
82
|
+
);
|
|
83
|
+
const killTimeoutMs = parsePositiveTimeout(flagRec["kill-timeout-ms"] as string | undefined, "--kill-timeout-ms");
|
|
67
84
|
if (rawAction === "session") {
|
|
68
85
|
await runSdkSessionCli({
|
|
69
86
|
action: positional[0],
|
|
@@ -91,8 +108,8 @@ export default class Daemon extends Command {
|
|
|
91
108
|
json: Boolean(flags.json),
|
|
92
109
|
force: Boolean(flags.force),
|
|
93
110
|
verbose: Boolean(flags.verbose),
|
|
94
|
-
gracefulTimeoutMs
|
|
95
|
-
killTimeoutMs
|
|
111
|
+
gracefulTimeoutMs,
|
|
112
|
+
killTimeoutMs,
|
|
96
113
|
spawnIfStopped: flagRec["spawn-if-stopped"] as boolean | undefined,
|
|
97
114
|
smoke: Boolean(flags.smoke),
|
|
98
115
|
ownerId: flagRec["owner-id"] as string | undefined,
|
package/src/commands/sdk.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs/promises";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { Args, Command, Flags } from "@gajae-code/utils/cli";
|
|
4
|
+
import { Args, CliParseError, Command, Flags, renderCommandHelp } from "@gajae-code/utils/cli";
|
|
5
5
|
import type { Args as ParsedArgs } from "../cli/args";
|
|
6
6
|
import { Settings } from "../config/settings";
|
|
7
7
|
import { applyStartupModelProfiles, createSessionManager } from "../main";
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type SdkStartupRollbackResult,
|
|
26
26
|
SdkStartupRollbackTracker,
|
|
27
27
|
} from "../sdk/startup-capability";
|
|
28
|
+
import { runSdkServe } from "../sdk/transport/serve-cli";
|
|
28
29
|
import {
|
|
29
30
|
type CapturedSessionTranscriptSnapshot,
|
|
30
31
|
type ResumeSessionIdentity,
|
|
@@ -294,14 +295,14 @@ export async function runSessionHost(
|
|
|
294
295
|
rollback.recordAbsent();
|
|
295
296
|
const failure = normalizeSdkStartupFailure("registration", "failed", error);
|
|
296
297
|
await writeFailure(failure, rollback.result);
|
|
297
|
-
throw
|
|
298
|
+
throw failure;
|
|
298
299
|
}
|
|
299
300
|
const { parsed } = opened;
|
|
300
301
|
if ("failure" in created) {
|
|
301
302
|
created.rollback.recordAbsent();
|
|
302
303
|
await writeFailure(created.failure, created.rollback.result);
|
|
303
304
|
|
|
304
|
-
throw
|
|
305
|
+
throw created.failure;
|
|
305
306
|
}
|
|
306
307
|
const { session, capability, rollback } = created;
|
|
307
308
|
let sessionDisposal: Promise<void> | undefined;
|
|
@@ -423,19 +424,51 @@ export async function runSessionHost(
|
|
|
423
424
|
await new Promise<void>(() => {});
|
|
424
425
|
}
|
|
425
426
|
|
|
427
|
+
export type SdkInternalArgv = { action: "broker-internal"; agentDir: string } | { action: "session-host-internal" };
|
|
428
|
+
|
|
429
|
+
/** Parses the exact private argv contracts used by SDK child-process spawns. */
|
|
430
|
+
export function parseSdkInternalArgv(argv: readonly string[]): SdkInternalArgv {
|
|
431
|
+
if (argv[0] === "session-host-internal" && argv.length === 1) return { action: "session-host-internal" };
|
|
432
|
+
if (argv[0] === "broker-internal" && argv.length === 3 && argv[1] === "--agent-dir" && argv[2])
|
|
433
|
+
return { action: "broker-internal", agentDir: argv[2] };
|
|
434
|
+
throw new CliParseError("Invalid internal SDK invocation.");
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
class SdkServeHelp extends Command {
|
|
438
|
+
static description = "gjc sdk serve --stdio | --socket <path> [--session <id>] [--pending-ceiling <bytes>]";
|
|
439
|
+
static flags = {
|
|
440
|
+
stdio: Flags.boolean({ description: "Serve SDK frames over standard input and output" }),
|
|
441
|
+
socket: Flags.string({ description: "Serve SDK frames over a Unix socket path" }),
|
|
442
|
+
session: Flags.string({ description: "Attach to a specific SDK session" }),
|
|
443
|
+
"pending-ceiling": Flags.string({ description: "Maximum queued relay bytes per direction" }),
|
|
444
|
+
};
|
|
445
|
+
async run(): Promise<void> {}
|
|
446
|
+
}
|
|
447
|
+
|
|
426
448
|
export default class Sdk extends Command {
|
|
427
|
-
static description = "
|
|
428
|
-
static hidden =
|
|
429
|
-
static
|
|
430
|
-
static
|
|
449
|
+
static description = "gjc sdk serve --stdio | --socket <path> [--session <id>] [--pending-ceiling <bytes>]";
|
|
450
|
+
static hidden = false;
|
|
451
|
+
static delegateHelp = true;
|
|
452
|
+
static args = { action: Args.string({ required: false, options: ["serve"] }) };
|
|
453
|
+
static flags = SdkServeHelp.flags;
|
|
431
454
|
async run(): Promise<void> {
|
|
432
|
-
const
|
|
433
|
-
if (
|
|
455
|
+
const action = this.argv[0];
|
|
456
|
+
if (this.argv.includes("--help") || this.argv.includes("-h")) {
|
|
457
|
+
renderCommandHelp("gjc", action === "serve" ? "sdk serve" : "sdk", action === "serve" ? SdkServeHelp : Sdk);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
if (action === "serve") {
|
|
461
|
+
await runSdkServe(this.argv.slice(1));
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (action !== "broker-internal" && action !== "session-host-internal")
|
|
465
|
+
throw new CliParseError("Expected action to be serve.");
|
|
466
|
+
const internal = parseSdkInternalArgv(this.argv);
|
|
467
|
+
if (internal.action === "session-host-internal") {
|
|
434
468
|
await runSessionHost();
|
|
435
469
|
return;
|
|
436
470
|
}
|
|
437
|
-
const agentDir =
|
|
438
|
-
if (!agentDir) throw new Error("--agent-dir is required for sdk broker-internal.");
|
|
471
|
+
const agentDir = internal.agentDir;
|
|
439
472
|
const broker = new Broker({
|
|
440
473
|
agentDir,
|
|
441
474
|
resolveDirectoryMigration: async cwd => {
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
type KeybindingDefinitions,
|
|
6
6
|
type KeybindingsConfig,
|
|
7
7
|
type KeyId,
|
|
8
|
+
parseKeyId,
|
|
8
9
|
setKeybindings,
|
|
9
10
|
TUI_KEYBINDINGS,
|
|
10
11
|
KeybindingsManager as TuiKeybindingsManager,
|
|
@@ -172,7 +173,7 @@ export const KEYBINDINGS = {
|
|
|
172
173
|
},
|
|
173
174
|
"app.session.fork": {
|
|
174
175
|
defaultKeys: [],
|
|
175
|
-
description: "
|
|
176
|
+
description: "Branch from message",
|
|
176
177
|
},
|
|
177
178
|
"app.session.resume": {
|
|
178
179
|
defaultKeys: [],
|
|
@@ -352,10 +353,29 @@ function toKeybindingsConfig(value: unknown): KeybindingsConfig {
|
|
|
352
353
|
logger.info("Ignoring unknown keybinding entry", { key });
|
|
353
354
|
continue;
|
|
354
355
|
}
|
|
355
|
-
if (val === undefined)
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
356
|
+
if (val === undefined) {
|
|
357
|
+
config[key] = undefined;
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const keys = typeof val === "string" ? [val] : Array.isArray(val) ? val : undefined;
|
|
362
|
+
if (!keys?.every(keyValue => typeof keyValue === "string")) {
|
|
363
|
+
logger.info("Ignoring malformed keybinding entry", { key });
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const normalizedKeys: KeyId[] = [];
|
|
368
|
+
for (const keyValue of keys) {
|
|
369
|
+
const parsedKey = parseKeyId(keyValue);
|
|
370
|
+
if (!parsedKey) {
|
|
371
|
+
logger.info("Ignoring invalid keybinding entry", { key, category: "invalid-keybinding" });
|
|
372
|
+
normalizedKeys.length = 0;
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
normalizedKeys.push(parsedKey.keyId);
|
|
376
|
+
}
|
|
377
|
+
if (normalizedKeys.length !== keys.length) continue;
|
|
378
|
+
config[key] = typeof val === "string" ? normalizedKeys[0] : normalizedKeys;
|
|
359
379
|
}
|
|
360
380
|
return config;
|
|
361
381
|
}
|
|
@@ -461,11 +481,18 @@ function migrateKeybindingsConfigFile(agentDir: string): void {
|
|
|
461
481
|
*/
|
|
462
482
|
export class KeybindingsManager extends TuiKeybindingsManager {
|
|
463
483
|
#configPath: string | undefined;
|
|
484
|
+
#displayContext: KeyDisplayContext = runtimeKeyDisplayContext;
|
|
464
485
|
|
|
465
486
|
constructor(userBindings: KeybindingsConfig = {}, configPath?: string) {
|
|
466
|
-
super(KEYBINDINGS, userBindings);
|
|
487
|
+
super(KEYBINDINGS, toKeybindingsConfig(userBindings));
|
|
467
488
|
this.#configPath = configPath;
|
|
468
489
|
}
|
|
490
|
+
/**
|
|
491
|
+
* Replace user bindings only after canonical grammar validation.
|
|
492
|
+
*/
|
|
493
|
+
override setUserBindings(userBindings: KeybindingsConfig): void {
|
|
494
|
+
super.setUserBindings(toKeybindingsConfig(userBindings));
|
|
495
|
+
}
|
|
469
496
|
|
|
470
497
|
/**
|
|
471
498
|
* Create from config file at agentDir/keybindings.json.
|
|
@@ -485,6 +512,13 @@ export class KeybindingsManager extends TuiKeybindingsManager {
|
|
|
485
512
|
static inMemory(userBindings: KeybindingsConfig = {}): KeybindingsManager {
|
|
486
513
|
return new KeybindingsManager(userBindings);
|
|
487
514
|
}
|
|
515
|
+
/**
|
|
516
|
+
* Set the default display context used by composed surfaces that do not
|
|
517
|
+
* supply an explicit context.
|
|
518
|
+
*/
|
|
519
|
+
setDisplayContext(context: KeyDisplayContext): void {
|
|
520
|
+
this.#displayContext = context;
|
|
521
|
+
}
|
|
488
522
|
|
|
489
523
|
/**
|
|
490
524
|
* Reload keybindings from the config file.
|
|
@@ -504,9 +538,29 @@ export class KeybindingsManager extends TuiKeybindingsManager {
|
|
|
504
538
|
/**
|
|
505
539
|
* Get display string for a keybinding (e.g., "ctrl+c/escape").
|
|
506
540
|
*/
|
|
507
|
-
getDisplayString(keybinding: Keybinding): string {
|
|
541
|
+
getDisplayString(keybinding: Keybinding, context: KeyDisplayContext = this.#displayContext): string {
|
|
542
|
+
const keys = this.getKeys(keybinding);
|
|
543
|
+
return formatKeyHints(keys, context);
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Get an accessibility-oriented display string for help surfaces.
|
|
547
|
+
* Darwin chords include both the concise glyphs and expanded key names.
|
|
548
|
+
*/
|
|
549
|
+
getAccessibleDisplayString(keybinding: Keybinding, context: KeyDisplayContext = this.#displayContext): string {
|
|
508
550
|
const keys = this.getKeys(keybinding);
|
|
509
|
-
return
|
|
551
|
+
return formatAccessibleKeyHints(keys, context);
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Format a fixed key chord using this manager's display context.
|
|
555
|
+
*/
|
|
556
|
+
formatKeyHint(key: string): string {
|
|
557
|
+
return formatKeyHint(key, this.#displayContext);
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Format a fixed key chord for accessibility-oriented help surfaces.
|
|
561
|
+
*/
|
|
562
|
+
formatAccessibleKeyHint(key: string): string {
|
|
563
|
+
return formatAccessibleKeyHint(key, this.#displayContext);
|
|
510
564
|
}
|
|
511
565
|
|
|
512
566
|
/**
|
|
@@ -520,13 +574,20 @@ export class KeybindingsManager extends TuiKeybindingsManager {
|
|
|
520
574
|
/**
|
|
521
575
|
* Key hint formatting utilities for UI labels.
|
|
522
576
|
*/
|
|
523
|
-
|
|
577
|
+
export interface KeyDisplayContext {
|
|
578
|
+
platform: NodeJS.Platform;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const runtimeKeyDisplayContext: KeyDisplayContext = { platform: process.platform };
|
|
582
|
+
|
|
583
|
+
const TEXTUAL_MODIFIER_LABELS: Record<string, string> = {
|
|
524
584
|
ctrl: "Ctrl",
|
|
525
|
-
shift: "Shift",
|
|
526
585
|
alt: "Alt",
|
|
586
|
+
shift: "Shift",
|
|
587
|
+
super: "Super",
|
|
527
588
|
};
|
|
528
589
|
|
|
529
|
-
const
|
|
590
|
+
const TEXTUAL_KEY_LABELS: Record<string, string> = {
|
|
530
591
|
esc: "Esc",
|
|
531
592
|
escape: "Esc",
|
|
532
593
|
enter: "Enter",
|
|
@@ -535,33 +596,105 @@ const KEY_LABELS: Record<string, string> = {
|
|
|
535
596
|
tab: "Tab",
|
|
536
597
|
backspace: "Backspace",
|
|
537
598
|
delete: "Delete",
|
|
599
|
+
insert: "Insert",
|
|
600
|
+
clear: "Clear",
|
|
538
601
|
home: "Home",
|
|
539
602
|
end: "End",
|
|
540
|
-
|
|
541
|
-
|
|
603
|
+
pageUp: "PgUp",
|
|
604
|
+
pageDown: "PgDn",
|
|
542
605
|
up: "Up",
|
|
543
606
|
down: "Down",
|
|
544
607
|
left: "Left",
|
|
545
608
|
right: "Right",
|
|
546
609
|
};
|
|
547
610
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
611
|
+
const DARWIN_MODIFIER_LABELS: Record<string, string> = {
|
|
612
|
+
ctrl: "⌃",
|
|
613
|
+
alt: "⌥",
|
|
614
|
+
shift: "⇧",
|
|
615
|
+
super: "⌘",
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
const DARWIN_KEY_LABELS: Record<string, string> = {
|
|
619
|
+
...TEXTUAL_KEY_LABELS,
|
|
620
|
+
esc: "⎋",
|
|
621
|
+
escape: "⎋",
|
|
622
|
+
enter: "↩",
|
|
623
|
+
return: "↩",
|
|
624
|
+
tab: "⇥",
|
|
625
|
+
backspace: "⌫",
|
|
626
|
+
delete: "⌦",
|
|
627
|
+
up: "↑",
|
|
628
|
+
down: "↓",
|
|
629
|
+
left: "←",
|
|
630
|
+
right: "→",
|
|
631
|
+
};
|
|
632
|
+
const DARWIN_ACCESSIBLE_MODIFIER_LABELS: Record<string, string> = {
|
|
633
|
+
ctrl: "Control",
|
|
634
|
+
alt: "Option",
|
|
635
|
+
shift: "Shift",
|
|
636
|
+
super: "Command",
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
const DARWIN_ACCESSIBLE_KEY_LABELS: Record<string, string> = {
|
|
640
|
+
...TEXTUAL_KEY_LABELS,
|
|
641
|
+
esc: "Escape",
|
|
642
|
+
escape: "Escape",
|
|
643
|
+
pageUp: "Page Up",
|
|
644
|
+
pageDown: "Page Down",
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
const DISPLAY_MODIFIER_ORDER = ["ctrl", "alt", "shift", "super"] as const;
|
|
648
|
+
const INVALID_KEYBINDING_DISPLAY = "Invalid keybinding";
|
|
649
|
+
|
|
650
|
+
function formatBaseKey(baseKey: string, labels: Record<string, string>): string {
|
|
651
|
+
const label = labels[baseKey];
|
|
553
652
|
if (label) return label;
|
|
554
|
-
if (
|
|
555
|
-
return `${
|
|
653
|
+
if (baseKey.length === 1) return baseKey.toUpperCase();
|
|
654
|
+
return `${baseKey.charAt(0).toUpperCase()}${baseKey.slice(1)}`;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
export function formatKeyHint(key: string, context: KeyDisplayContext = runtimeKeyDisplayContext): string {
|
|
658
|
+
const parsed = parseKeyId(key);
|
|
659
|
+
if (!parsed) return INVALID_KEYBINDING_DISPLAY;
|
|
660
|
+
|
|
661
|
+
const darwin = context.platform === "darwin";
|
|
662
|
+
const modifierLabels = darwin ? DARWIN_MODIFIER_LABELS : TEXTUAL_MODIFIER_LABELS;
|
|
663
|
+
const baseLabels = darwin ? DARWIN_KEY_LABELS : TEXTUAL_KEY_LABELS;
|
|
664
|
+
const modifiers = DISPLAY_MODIFIER_ORDER.filter(modifier => parsed.modifiers.includes(modifier)).map(
|
|
665
|
+
modifier => modifierLabels[modifier],
|
|
666
|
+
);
|
|
667
|
+
const parts = [...modifiers, formatBaseKey(parsed.baseKey, baseLabels)];
|
|
668
|
+
return parts.join(darwin ? "" : "+");
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
export function formatAccessibleKeyHint(key: string, context: KeyDisplayContext = runtimeKeyDisplayContext): string {
|
|
672
|
+
const concise = formatKeyHint(key, context);
|
|
673
|
+
if (context.platform !== "darwin" || concise === INVALID_KEYBINDING_DISPLAY) return concise;
|
|
674
|
+
|
|
675
|
+
const parsed = parseKeyId(key);
|
|
676
|
+
if (!parsed) return INVALID_KEYBINDING_DISPLAY;
|
|
677
|
+
const modifiers = DISPLAY_MODIFIER_ORDER.filter(modifier => parsed.modifiers.includes(modifier)).map(
|
|
678
|
+
modifier => DARWIN_ACCESSIBLE_MODIFIER_LABELS[modifier],
|
|
679
|
+
);
|
|
680
|
+
const expanded = [...modifiers, formatBaseKey(parsed.baseKey, DARWIN_ACCESSIBLE_KEY_LABELS)].join("+");
|
|
681
|
+
return concise === expanded ? concise : `${concise} (${expanded})`;
|
|
556
682
|
}
|
|
557
683
|
|
|
558
|
-
export function
|
|
559
|
-
|
|
684
|
+
export function formatKeyHints(
|
|
685
|
+
keys: string | readonly string[],
|
|
686
|
+
context: KeyDisplayContext = runtimeKeyDisplayContext,
|
|
687
|
+
): string {
|
|
688
|
+
const list: readonly string[] = typeof keys === "string" ? [keys] : keys;
|
|
689
|
+
return list.map(key => formatKeyHint(key, context)).join("/");
|
|
560
690
|
}
|
|
561
691
|
|
|
562
|
-
export function
|
|
563
|
-
|
|
564
|
-
|
|
692
|
+
export function formatAccessibleKeyHints(
|
|
693
|
+
keys: string | readonly string[],
|
|
694
|
+
context: KeyDisplayContext = runtimeKeyDisplayContext,
|
|
695
|
+
): string {
|
|
696
|
+
const list: readonly string[] = typeof keys === "string" ? [keys] : keys;
|
|
697
|
+
return list.map(key => formatAccessibleKeyHint(key, context)).join("/");
|
|
565
698
|
}
|
|
566
699
|
|
|
567
700
|
export type { Keybinding, KeybindingsConfig, KeyId };
|
|
@@ -2,12 +2,15 @@ import { ThinkingLevel } from "@gajae-code/agent-core";
|
|
|
2
2
|
import type { Api, Model } from "@gajae-code/ai";
|
|
3
3
|
import type { AgentSession } from "../session/agent-session";
|
|
4
4
|
import { formatClampedModelSelector } from "../thinking";
|
|
5
|
+
import { validateModelProfileName } from "./model-profile-contract";
|
|
5
6
|
import {
|
|
6
7
|
aggregateModelProfileRequiredProviders,
|
|
7
|
-
formatAvailableProfileNames,
|
|
8
8
|
formatModelProfileDisplayLabel,
|
|
9
9
|
resolveProfileBindings,
|
|
10
10
|
} from "./model-profiles";
|
|
11
|
+
|
|
12
|
+
export { resolveModelProfileName } from "./model-profile-contract";
|
|
13
|
+
|
|
11
14
|
import {
|
|
12
15
|
GJC_MODEL_ASSIGNMENT_TARGETS,
|
|
13
16
|
type GjcModelAssignmentTargetId,
|
|
@@ -24,8 +27,6 @@ import {
|
|
|
24
27
|
import { type ModelSelectorValue, normalizeModelSelectorValue } from "./model-selector-value";
|
|
25
28
|
import type { Settings } from "./settings";
|
|
26
29
|
|
|
27
|
-
const LEGACY_MODEL_PROFILE_ALIASES: ReadonlyMap<string, string> = new Map([["codex-standard", "codex-medium"]]);
|
|
28
|
-
|
|
29
30
|
type ModelProfileActivationSession = Pick<
|
|
30
31
|
AgentSession,
|
|
31
32
|
"model" | "thinkingLevel" | "sessionId" | "getConfiguredModelChain" | "setConfiguredModelChain"
|
|
@@ -50,7 +51,7 @@ export interface PrepareModelProfileActivationOptions {
|
|
|
50
51
|
| "resolveCanonicalModel"
|
|
51
52
|
| "getCanonicalVariants"
|
|
52
53
|
| "getCanonicalId"
|
|
53
|
-
|
|
54
|
+
> & { getError?: ModelRegistry["getError"] };
|
|
54
55
|
settings: Pick<Settings, "get">;
|
|
55
56
|
profileName: string;
|
|
56
57
|
}
|
|
@@ -236,14 +237,6 @@ export function formatModelProfileCredentialError(profileLabel: string, provider
|
|
|
236
237
|
return `Model profile "${profileLabel}" requires credentials for: ${providers.join(", ")}. Run /login and configure the missing provider(s), then retry.`;
|
|
237
238
|
}
|
|
238
239
|
|
|
239
|
-
export function resolveModelProfileName(profileName: string, profiles: ReadonlyMap<string, unknown>): string {
|
|
240
|
-
// A retired-name alias is fallback-only: never shadow a profile that actually
|
|
241
|
-
// exists under the requested name (e.g. a user-defined `codex-standard`).
|
|
242
|
-
if (profiles.has(profileName)) return profileName;
|
|
243
|
-
const replacement = LEGACY_MODEL_PROFILE_ALIASES.get(profileName);
|
|
244
|
-
return replacement && profiles.has(replacement) ? replacement : profileName;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
240
|
/**
|
|
248
241
|
* Rewrite a selector only within the selector provider's own alternative group.
|
|
249
242
|
* Strict providers are never rewritten, and authenticated alternative providers
|
|
@@ -348,12 +341,8 @@ export async function prepareModelProfileActivation(
|
|
|
348
341
|
options: PrepareModelProfileActivationOptions,
|
|
349
342
|
): Promise<PreparedModelProfileActivation> {
|
|
350
343
|
const profiles = options.modelRegistry.getModelProfiles();
|
|
351
|
-
const profileName =
|
|
352
|
-
const profile = profiles.get(profileName) ?? options.modelRegistry.getModelProfile(profileName)
|
|
353
|
-
if (!profile) {
|
|
354
|
-
const available = formatAvailableProfileNames(profiles);
|
|
355
|
-
throw new Error(`Unknown model profile "${options.profileName}". Available profiles: ${available}`);
|
|
356
|
-
}
|
|
344
|
+
const profileName = validateModelProfileName(options.profileName, profiles, options.modelRegistry.getError?.());
|
|
345
|
+
const profile = profiles.get(profileName) ?? options.modelRegistry.getModelProfile(profileName)!;
|
|
357
346
|
const profileLabel = formatModelProfileDisplayLabel(profile);
|
|
358
347
|
|
|
359
348
|
const requiredProviders = aggregateModelProfileRequiredProviders(profile.requiredProviders, profile);
|