@oh-my-pi/pi-coding-agent 15.5.15 → 15.7.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.
- package/CHANGELOG.md +81 -0
- package/dist/types/capability/rule-buckets.d.ts +30 -0
- package/dist/types/capability/rule.d.ts +7 -0
- package/dist/types/cli/classify-install-target.d.ts +0 -10
- package/dist/types/cli/completion-gen.d.ts +80 -0
- package/dist/types/cli/initial-message.d.ts +1 -1
- package/dist/types/cli/tiny-models-cli.d.ts +9 -0
- package/dist/types/commands/complete.d.ts +6 -0
- package/dist/types/commands/completions.d.ts +13 -0
- package/dist/types/commands/setup.d.ts +10 -1
- package/dist/types/commands/tiny-models.d.ts +22 -0
- package/dist/types/commit/analysis/conventional.d.ts +1 -1
- package/dist/types/commit/analysis/summary.d.ts +1 -1
- package/dist/types/commit/changelog/generate.d.ts +1 -1
- package/dist/types/commit/changelog/index.d.ts +2 -2
- package/dist/types/commit/map-reduce/map-phase.d.ts +1 -1
- package/dist/types/commit/map-reduce/reduce-phase.d.ts +1 -1
- package/dist/types/config/model-id-affixes.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +402 -17
- package/dist/types/discovery/builtin-defaults.d.ts +1 -0
- package/dist/types/discovery/builtin-rules/index.d.ts +7 -0
- package/dist/types/discovery/helpers.d.ts +1 -1
- package/dist/types/discovery/index.d.ts +1 -0
- package/dist/types/discovery/substitute-plugin-root.d.ts +0 -4
- package/dist/types/edit/hashline/block-resolver.d.ts +9 -0
- package/dist/types/edit/hashline/index.d.ts +1 -0
- package/dist/types/eval/js/shared/rewrite-imports.d.ts +16 -1
- package/dist/types/eval/py/kernel.d.ts +3 -0
- package/dist/types/eval/py/runtime.d.ts +11 -1
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/internal-urls/agent-protocol.d.ts +2 -1
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -1
- package/dist/types/internal-urls/local-protocol.d.ts +2 -1
- package/dist/types/internal-urls/memory-protocol.d.ts +2 -1
- package/dist/types/internal-urls/omp-protocol.d.ts +2 -1
- package/dist/types/internal-urls/router.d.ts +8 -1
- package/dist/types/internal-urls/rule-protocol.d.ts +2 -1
- package/dist/types/internal-urls/skill-protocol.d.ts +2 -1
- package/dist/types/internal-urls/types.d.ts +26 -0
- package/dist/types/main.d.ts +1 -0
- package/dist/types/memory-backend/index.d.ts +1 -0
- package/dist/types/memory-backend/resolve.d.ts +2 -1
- package/dist/types/memory-backend/types.d.ts +7 -1
- package/dist/types/mnemosyne/backend.d.ts +4 -0
- package/dist/types/mnemosyne/config.d.ts +29 -0
- package/dist/types/mnemosyne/index.d.ts +3 -0
- package/dist/types/mnemosyne/state.d.ts +72 -0
- package/dist/types/modes/components/custom-editor.d.ts +2 -3
- package/dist/types/modes/components/hook-selector.d.ts +27 -0
- package/dist/types/modes/components/index.d.ts +2 -0
- package/dist/types/modes/components/segment-track.d.ts +22 -0
- package/dist/types/modes/components/status-line/context-thresholds.d.ts +6 -0
- package/dist/types/modes/components/tiny-title-download-progress.d.ts +11 -0
- package/dist/types/modes/components/welcome.d.ts +22 -0
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +4 -1
- package/dist/types/modes/gradient-highlight.d.ts +23 -0
- package/dist/types/modes/interactive-mode.d.ts +7 -4
- package/dist/types/modes/internal-url-autocomplete.d.ts +43 -0
- package/dist/types/modes/orchestrate.d.ts +10 -0
- package/dist/types/modes/setup-wizard/index.d.ts +16 -0
- package/dist/types/modes/setup-wizard/scenes/glyph.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/outro.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/providers.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +19 -0
- package/dist/types/modes/setup-wizard/scenes/splash.d.ts +11 -0
- package/dist/types/modes/setup-wizard/scenes/theme.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/types.d.ts +43 -0
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +19 -0
- package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +14 -0
- package/dist/types/modes/theme/defaults/index.d.ts +8406 -8406
- package/dist/types/modes/theme/shimmer.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +11 -0
- package/dist/types/modes/types.d.ts +5 -1
- package/dist/types/modes/ultrathink.d.ts +3 -3
- package/dist/types/modes/utils/keybinding-matchers.d.ts +5 -0
- package/dist/types/sdk.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +33 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +2 -0
- package/dist/types/task/render.d.ts +5 -1
- package/dist/types/tiny/device.d.ts +78 -0
- package/dist/types/tiny/dtype.d.ts +85 -0
- package/dist/types/tiny/models.d.ts +185 -0
- package/dist/types/tiny/text.d.ts +19 -0
- package/dist/types/tiny/title-client.d.ts +32 -0
- package/dist/types/tiny/title-protocol.d.ts +74 -0
- package/dist/types/tiny/worker.d.ts +2 -0
- package/dist/types/tools/bash.d.ts +3 -2
- package/dist/types/tools/eval.d.ts +1 -1
- package/dist/types/tools/index.d.ts +7 -4
- package/dist/types/tools/memory-edit.d.ts +40 -0
- package/dist/types/tools/{hindsight-recall.d.ts → memory-recall.d.ts} +6 -6
- package/dist/types/tools/{hindsight-reflect.d.ts → memory-reflect.d.ts} +6 -6
- package/dist/types/tools/memory-render.d.ts +60 -0
- package/dist/types/tools/{hindsight-retain.d.ts → memory-retain.d.ts} +6 -6
- package/dist/types/tools/todo-write.d.ts +8 -0
- package/dist/types/tools/tool-result.d.ts +2 -0
- package/dist/types/tui/code-cell.d.ts +2 -0
- package/dist/types/tui/output-block.d.ts +17 -0
- package/dist/types/utils/title-generator.d.ts +3 -0
- package/package.json +18 -14
- package/scripts/build-binary.ts +1 -0
- package/src/capability/rule-buckets.ts +64 -0
- package/src/capability/rule.ts +8 -0
- package/src/cli/completion-gen.ts +550 -0
- package/src/cli/setup-cli.ts +5 -3
- package/src/cli/tiny-models-cli.ts +127 -0
- package/src/cli-commands.ts +3 -0
- package/src/cli.ts +9 -15
- package/src/commands/complete.ts +66 -0
- package/src/commands/completions.ts +60 -0
- package/src/commands/setup.ts +29 -4
- package/src/commands/tiny-models.ts +36 -0
- package/src/config/model-equivalence.ts +43 -2
- package/src/config/model-id-affixes.ts +64 -0
- package/src/config/model-registry.ts +84 -10
- package/src/config/settings-schema.ts +275 -15
- package/src/discovery/builtin-defaults.ts +39 -0
- package/src/discovery/builtin-rules/index.ts +48 -0
- package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
- package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
- package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
- package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
- package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
- package/src/discovery/builtin-rules/rs-result-type.md +19 -0
- package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
- package/src/discovery/builtin-rules/ts-import-type.md +42 -0
- package/src/discovery/builtin-rules/ts-no-any.md +56 -0
- package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
- package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
- package/src/discovery/builtin-rules/ts-no-tiny-functions.md +50 -0
- package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
- package/src/discovery/builtin-rules/ts-set-map.md +28 -0
- package/src/discovery/index.ts +1 -0
- package/src/edit/hashline/block-resolver.ts +14 -0
- package/src/edit/hashline/diff.ts +9 -8
- package/src/edit/hashline/execute.ts +2 -1
- package/src/edit/hashline/index.ts +1 -0
- package/src/eval/__tests__/shared-executors.test.ts +36 -0
- package/src/eval/js/shared/local-module-loader.ts +13 -1
- package/src/eval/js/shared/rewrite-imports.ts +31 -26
- package/src/eval/py/kernel.ts +37 -15
- package/src/eval/py/runtime.ts +57 -28
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +0 -12
- package/src/export/ttsr.ts +2 -0
- package/src/internal-urls/agent-protocol.ts +18 -1
- package/src/internal-urls/artifact-protocol.ts +19 -1
- package/src/internal-urls/docs-index.generated.ts +8 -7
- package/src/internal-urls/local-protocol.ts +14 -1
- package/src/internal-urls/memory-protocol.ts +6 -1
- package/src/internal-urls/omp-protocol.ts +5 -1
- package/src/internal-urls/router.ts +20 -1
- package/src/internal-urls/rule-protocol.ts +8 -1
- package/src/internal-urls/skill-protocol.ts +8 -1
- package/src/internal-urls/types.ts +27 -0
- package/src/lsp/render.ts +1 -1
- package/src/main.ts +18 -1
- package/src/mcp/oauth-flow.ts +2 -2
- package/src/memory-backend/index.ts +1 -0
- package/src/memory-backend/resolve.ts +4 -1
- package/src/memory-backend/types.ts +8 -1
- package/src/mnemosyne/backend.ts +374 -0
- package/src/mnemosyne/config.ts +160 -0
- package/src/mnemosyne/index.ts +3 -0
- package/src/mnemosyne/state.ts +548 -0
- package/src/modes/acp/acp-agent.ts +11 -6
- package/src/modes/components/agent-dashboard.ts +4 -4
- package/src/modes/components/custom-editor.ts +3 -2
- package/src/modes/components/diff.ts +2 -2
- package/src/modes/components/extensions/extension-list.ts +3 -2
- package/src/modes/components/footer.ts +5 -6
- package/src/modes/components/history-search.ts +3 -3
- package/src/modes/components/hook-selector.ts +92 -8
- package/src/modes/components/index.ts +2 -0
- package/src/modes/components/mcp-add-wizard.ts +3 -3
- package/src/modes/components/model-selector.ts +5 -4
- package/src/modes/components/oauth-selector.ts +3 -3
- package/src/modes/components/segment-track.ts +52 -0
- package/src/modes/components/session-observer-overlay.ts +19 -13
- package/src/modes/components/session-selector.ts +3 -3
- package/src/modes/components/settings-defs.ts +7 -0
- package/src/modes/components/status-line/context-thresholds.ts +11 -0
- package/src/modes/components/status-line/segments.ts +2 -2
- package/src/modes/components/tiny-title-download-progress.ts +90 -0
- package/src/modes/components/tips.txt +13 -0
- package/src/modes/components/tool-execution.ts +72 -4
- package/src/modes/components/tree-selector.ts +3 -3
- package/src/modes/components/user-message-selector.ts +3 -3
- package/src/modes/components/welcome.ts +102 -43
- package/src/modes/controllers/command-controller.ts +16 -1
- package/src/modes/controllers/extension-ui-controller.ts +3 -1
- package/src/modes/controllers/input-controller.ts +69 -21
- package/src/modes/gradient-highlight.ts +70 -0
- package/src/modes/interactive-mode.ts +75 -114
- package/src/modes/internal-url-autocomplete.ts +143 -0
- package/src/modes/orchestrate.ts +36 -0
- package/src/modes/prompt-action-autocomplete.ts +12 -0
- package/src/modes/setup-wizard/index.ts +88 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +96 -0
- package/src/modes/setup-wizard/scenes/outro.ts +35 -0
- package/src/modes/setup-wizard/scenes/providers.ts +69 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +193 -0
- package/src/modes/setup-wizard/scenes/splash.ts +201 -0
- package/src/modes/setup-wizard/scenes/theme.ts +299 -0
- package/src/modes/setup-wizard/scenes/types.ts +48 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +128 -0
- package/src/modes/setup-wizard/wizard-overlay.ts +275 -0
- package/src/modes/theme/shimmer.ts +5 -0
- package/src/modes/theme/theme.ts +44 -20
- package/src/modes/types.ts +6 -1
- package/src/modes/ultrathink.ts +9 -53
- package/src/modes/utils/keybinding-matchers.ts +11 -0
- package/src/prompts/system/memory-consolidation-system.md +8 -0
- package/src/prompts/system/memory-extraction-system.md +26 -0
- package/src/prompts/{commands/orchestrate.md → system/orchestrate-notice.md} +6 -17
- package/src/prompts/system/system-prompt.md +2 -0
- package/src/prompts/system/tiny-title-system.md +8 -0
- package/src/prompts/tools/memory-edit.md +8 -0
- package/src/prompts/tools/read.md +4 -0
- package/src/prompts/tools/task.md +4 -7
- package/src/sdk.ts +13 -21
- package/src/session/agent-session.ts +128 -44
- package/src/slash-commands/builtin-registry.ts +18 -1
- package/src/system-prompt.ts +4 -0
- package/src/task/commands.ts +1 -5
- package/src/task/executor.ts +8 -0
- package/src/task/index.ts +2 -0
- package/src/task/render.ts +69 -26
- package/src/tiny/device.ts +117 -0
- package/src/tiny/dtype.ts +101 -0
- package/src/tiny/models.ts +218 -0
- package/src/tiny/text.ts +54 -0
- package/src/tiny/title-client.ts +395 -0
- package/src/tiny/title-protocol.ts +51 -0
- package/src/tiny/worker.ts +587 -0
- package/src/tools/bash.ts +74 -29
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/eval.ts +9 -4
- package/src/tools/index.ts +17 -22
- package/src/tools/memory-edit.ts +59 -0
- package/src/tools/memory-recall.ts +100 -0
- package/src/tools/memory-reflect.ts +88 -0
- package/src/tools/memory-render.ts +185 -0
- package/src/tools/memory-retain.ts +91 -0
- package/src/tools/read.ts +1 -0
- package/src/tools/renderers.ts +4 -2
- package/src/tools/todo-write.ts +128 -29
- package/src/tools/tool-result.ts +8 -0
- package/src/tui/code-cell.ts +6 -1
- package/src/tui/output-block.ts +199 -38
- package/src/utils/title-generator.ts +115 -13
- package/dist/types/tools/recipe/index.d.ts +0 -46
- package/dist/types/tools/recipe/render.d.ts +0 -36
- package/dist/types/tools/recipe/runner.d.ts +0 -60
- package/dist/types/tools/recipe/runners/cargo.d.ts +0 -16
- package/dist/types/tools/recipe/runners/index.d.ts +0 -2
- package/dist/types/tools/recipe/runners/just.d.ts +0 -2
- package/dist/types/tools/recipe/runners/make.d.ts +0 -2
- package/dist/types/tools/recipe/runners/pkg.d.ts +0 -2
- package/dist/types/tools/recipe/runners/task.d.ts +0 -2
- package/src/prompts/tools/recipe.md +0 -16
- package/src/tools/hindsight-recall.ts +0 -69
- package/src/tools/hindsight-reflect.ts +0 -58
- package/src/tools/hindsight-retain.ts +0 -57
- package/src/tools/recipe/index.ts +0 -81
- package/src/tools/recipe/render.ts +0 -19
- package/src/tools/recipe/runner.ts +0 -219
- package/src/tools/recipe/runners/cargo.ts +0 -131
- package/src/tools/recipe/runners/index.ts +0 -8
- package/src/tools/recipe/runners/just.ts +0 -73
- package/src/tools/recipe/runners/make.ts +0 -101
- package/src/tools/recipe/runners/pkg.ts +0 -167
- package/src/tools/recipe/runners/task.ts +0 -72
package/src/cli-commands.ts
CHANGED
|
@@ -17,6 +17,8 @@ export const commands: CommandEntry[] = [
|
|
|
17
17
|
{ name: "auth-gateway", load: () => import("./commands/auth-gateway").then(m => m.default) },
|
|
18
18
|
{ name: "agents", load: () => import("./commands/agents").then(m => m.default) },
|
|
19
19
|
{ name: "commit", load: () => import("./commands/commit").then(m => m.default) },
|
|
20
|
+
{ name: "completions", load: () => import("./commands/completions").then(m => m.default) },
|
|
21
|
+
{ name: "__complete", load: () => import("./commands/complete").then(m => m.default) },
|
|
20
22
|
{ name: "config", load: () => import("./commands/config").then(m => m.default) },
|
|
21
23
|
{ name: "grep", load: () => import("./commands/grep").then(m => m.default) },
|
|
22
24
|
{ name: "grievances", load: () => import("./commands/grievances").then(m => m.default) },
|
|
@@ -28,6 +30,7 @@ export const commands: CommandEntry[] = [
|
|
|
28
30
|
{ name: "ssh", load: () => import("./commands/ssh").then(m => m.default) },
|
|
29
31
|
{ name: "stats", load: () => import("./commands/stats").then(m => m.default) },
|
|
30
32
|
{ name: "update", load: () => import("./commands/update").then(m => m.default) },
|
|
33
|
+
{ name: "tiny-models", load: () => import("./commands/tiny-models").then(m => m.default) },
|
|
31
34
|
{ name: "worktree", load: () => import("./commands/worktree").then(m => m.default), aliases: ["wt"] },
|
|
32
35
|
{ name: "search", load: () => import("./commands/web-search").then(m => m.default), aliases: ["q"] },
|
|
33
36
|
];
|
package/src/cli.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { APP_NAME, MIN_BUN_VERSION, procmgr, VERSION } from "@oh-my-pi/pi-utils";
|
|
3
|
-
|
|
4
|
-
// Strip macOS malloc-stack-logging env vars before any subprocess is spawned.
|
|
5
|
-
// Otherwise every child bun process (subagents, plugin installs, ptree spawns,
|
|
6
|
-
// etc.) prints a `MallocStackLogging: can't turn off …` warning to stderr.
|
|
7
|
-
procmgr.scrubProcessEnv();
|
|
8
|
-
|
|
9
2
|
/**
|
|
10
3
|
* CLI entry point — registers all commands explicitly and delegates to the
|
|
11
4
|
* lightweight CLI runner from pi-utils.
|
|
12
5
|
*/
|
|
13
6
|
import { type CliConfig, run } from "@oh-my-pi/pi-utils/cli";
|
|
7
|
+
import { APP_NAME, MIN_BUN_VERSION, VERSION } from "@oh-my-pi/pi-utils/dirs";
|
|
14
8
|
import { commands, isSubcommand } from "./cli-commands";
|
|
15
9
|
|
|
16
10
|
if (Bun.semver.order(Bun.version, MIN_BUN_VERSION) < 0) {
|
|
@@ -32,20 +26,20 @@ async function showHelp(config: CliConfig): Promise<void> {
|
|
|
32
26
|
}
|
|
33
27
|
}
|
|
34
28
|
/**
|
|
35
|
-
* Smoke-test entry. Spawns
|
|
29
|
+
* Smoke-test entry. Spawns bundled workers, pings them, exits.
|
|
36
30
|
*
|
|
37
31
|
* Purpose: catch the silent worker-load regressions that hit compiled
|
|
38
|
-
* binaries (issues #1011 and #1027).
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* `scripts/install-tests/run-ci.sh` so binary / source-link / tarball
|
|
44
|
-
* installs all exercise it on every CI run.
|
|
32
|
+
* binaries (issues #1011 and #1027). Version/help paths do not spawn worker
|
|
33
|
+
* modules on a fresh install, so this probe is the minimal end-to-end test
|
|
34
|
+
* that proves `new Worker(...)` resolves and bundled worker modules evaluate.
|
|
35
|
+
* Wired into `scripts/install-tests/run-ci.sh` so binary / source-link /
|
|
36
|
+
* tarball installs all exercise it on every CI run.
|
|
45
37
|
*/
|
|
46
38
|
async function runSmokeTest(): Promise<void> {
|
|
47
39
|
const { smokeTestSyncWorker } = await import("@oh-my-pi/omp-stats");
|
|
40
|
+
const { smokeTestTinyTitleWorker } = await import("./tiny/title-client");
|
|
48
41
|
await smokeTestSyncWorker();
|
|
42
|
+
await smokeTestTinyTitleWorker();
|
|
49
43
|
process.stdout.write("smoke-test: ok\n");
|
|
50
44
|
}
|
|
51
45
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `omp __complete <kind> [-- <prefix>]` — dynamic completion candidates.
|
|
3
|
+
*
|
|
4
|
+
* Hidden helper invoked by the generated shell completion scripts to resolve
|
|
5
|
+
* values that can't be baked into the script: the live model catalog and
|
|
6
|
+
* on-disk sessions. Output is one `value\tdescription` line per candidate
|
|
7
|
+
* (tab-separated); shells that show descriptions parse the tab, bash uses the
|
|
8
|
+
* first field. The import surface is kept deliberately narrow so a TAB press
|
|
9
|
+
* doesn't pay for the full agent boot.
|
|
10
|
+
*/
|
|
11
|
+
import { type GeneratedProvider, getBundledModels, getBundledProviders } from "@oh-my-pi/pi-ai/models";
|
|
12
|
+
import { Command } from "@oh-my-pi/pi-utils/cli";
|
|
13
|
+
import { SessionManager } from "../session/session-manager";
|
|
14
|
+
|
|
15
|
+
export default class Complete extends Command {
|
|
16
|
+
static hidden = true;
|
|
17
|
+
static strict = false;
|
|
18
|
+
|
|
19
|
+
async run(): Promise<void> {
|
|
20
|
+
const argv = this.argv.filter(token => token !== "--");
|
|
21
|
+
const kind = argv[0];
|
|
22
|
+
const prefix = argv.length > 1 ? argv[argv.length - 1] : "";
|
|
23
|
+
if (kind === "models") {
|
|
24
|
+
completeModels(prefix);
|
|
25
|
+
} else if (kind === "sessions") {
|
|
26
|
+
await completeSessions(prefix);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Strip control chars that would corrupt the tab-separated line protocol. */
|
|
32
|
+
function clean(text: string): string {
|
|
33
|
+
return text.replace(/[\t\r\n]+/g, " ").trim();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function completeModels(prefix: string): void {
|
|
37
|
+
const needle = prefix.toLowerCase();
|
|
38
|
+
const seen = new Set<string>();
|
|
39
|
+
const lines: string[] = [];
|
|
40
|
+
for (const provider of getBundledProviders()) {
|
|
41
|
+
for (const model of getBundledModels(provider as GeneratedProvider)) {
|
|
42
|
+
// Offer both the fully-qualified `provider/id` and the bare `id`
|
|
43
|
+
// (matches the fuzzy resolution `--model` accepts).
|
|
44
|
+
const candidates = [`${model.provider}/${model.id}`, model.id];
|
|
45
|
+
for (const candidate of candidates) {
|
|
46
|
+
if (seen.has(candidate)) continue;
|
|
47
|
+
seen.add(candidate);
|
|
48
|
+
if (needle && !candidate.toLowerCase().includes(needle)) continue;
|
|
49
|
+
lines.push(`${candidate}\t${model.provider}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
lines.sort();
|
|
54
|
+
if (lines.length > 0) process.stdout.write(`${lines.join("\n")}\n`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function completeSessions(prefix: string): Promise<void> {
|
|
58
|
+
const sessions = await SessionManager.list(process.cwd());
|
|
59
|
+
const lines: string[] = [];
|
|
60
|
+
for (const session of sessions) {
|
|
61
|
+
if (prefix && !session.id.startsWith(prefix)) continue;
|
|
62
|
+
const label = clean(session.title ?? session.firstMessage ?? "").slice(0, 72);
|
|
63
|
+
lines.push(`${session.id}\t${label}`);
|
|
64
|
+
}
|
|
65
|
+
if (lines.length > 0) process.stdout.write(`${lines.join("\n")}\n`);
|
|
66
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `omp completions <bash|zsh|fish>` — print a shell completion script.
|
|
3
|
+
*
|
|
4
|
+
* The script is derived entirely from the declarative command/flag metadata
|
|
5
|
+
* (see `cli/completion-gen.ts`), so it never drifts from the actual CLI surface.
|
|
6
|
+
*/
|
|
7
|
+
import { APP_NAME, VERSION } from "@oh-my-pi/pi-utils";
|
|
8
|
+
import { Args, type CliConfig, Command, type CommandCtor } from "@oh-my-pi/pi-utils/cli";
|
|
9
|
+
import { buildSpec, generateCompletion, type Shell } from "../cli/completion-gen";
|
|
10
|
+
import { commands } from "../cli-commands";
|
|
11
|
+
|
|
12
|
+
/** Entry name of the default command whose flags become top-level completions. */
|
|
13
|
+
const ROOT_COMMAND = "launch";
|
|
14
|
+
const SHELLS = ["bash", "zsh", "fish"] as const;
|
|
15
|
+
|
|
16
|
+
export default class Completions extends Command {
|
|
17
|
+
static description = "Print a shell completion script (bash, zsh, or fish)";
|
|
18
|
+
|
|
19
|
+
static args = {
|
|
20
|
+
shell: Args.string({
|
|
21
|
+
description: "Target shell",
|
|
22
|
+
required: true,
|
|
23
|
+
options: SHELLS,
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
static examples = [
|
|
28
|
+
`# zsh — eval at startup, or write to a file in $fpath\n eval "$(${APP_NAME} completions zsh)"`,
|
|
29
|
+
`# bash\n eval "$(${APP_NAME} completions bash)"`,
|
|
30
|
+
`# fish\n ${APP_NAME} completions fish > ~/.config/fish/completions/${APP_NAME}.fish`,
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
async run(): Promise<void> {
|
|
34
|
+
const shell = this.argv[0];
|
|
35
|
+
if (!isShell(shell)) {
|
|
36
|
+
process.stderr.write(`Usage: ${APP_NAME} completions <${SHELLS.join("|")}>\n`);
|
|
37
|
+
process.exitCode = 1;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Load every command class so we can read its static flag/arg descriptors,
|
|
42
|
+
// and collect aliases from both the registration table and the class.
|
|
43
|
+
const loaded = await Promise.all(commands.map(async entry => ({ entry, Cmd: await entry.load() })));
|
|
44
|
+
const map = new Map<string, CommandCtor>();
|
|
45
|
+
const aliasMap = new Map<string, readonly string[]>();
|
|
46
|
+
for (const { entry, Cmd } of loaded) {
|
|
47
|
+
map.set(entry.name, Cmd);
|
|
48
|
+
const merged = new Set<string>([...(Cmd.aliases ?? []), ...(entry.aliases ?? [])]);
|
|
49
|
+
aliasMap.set(entry.name, [...merged]);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const config: CliConfig = { bin: APP_NAME, version: VERSION, commands: map };
|
|
53
|
+
const spec = buildSpec(config, ROOT_COMMAND, aliasMap);
|
|
54
|
+
process.stdout.write(generateCompletion(shell, spec));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isShell(value: string | undefined): value is Shell {
|
|
59
|
+
return value === "bash" || value === "zsh" || value === "fish";
|
|
60
|
+
}
|
package/src/commands/setup.ts
CHANGED
|
@@ -1,18 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Run onboarding setup or install dependencies for optional features.
|
|
3
3
|
*/
|
|
4
4
|
import { Args, Command, Flags, renderCommandHelp } from "@oh-my-pi/pi-utils/cli";
|
|
5
|
+
import { parseArgs } from "../cli/args";
|
|
5
6
|
import { runSetupCommand, type SetupCommandArgs, type SetupComponent } from "../cli/setup-cli";
|
|
7
|
+
import { runRootCommand } from "../main";
|
|
6
8
|
import { initTheme } from "../modes/theme/theme";
|
|
7
9
|
|
|
8
10
|
const COMPONENTS: SetupComponent[] = ["python", "stt"];
|
|
9
11
|
|
|
12
|
+
export interface OnboardingSetupDependencies {
|
|
13
|
+
runRoot?: typeof runRootCommand;
|
|
14
|
+
stdinIsTTY?: boolean;
|
|
15
|
+
stdoutIsTTY?: boolean;
|
|
16
|
+
writeStderr?: (text: string) => void;
|
|
17
|
+
exit?: (code: number) => never;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function runOnboardingSetup(deps: OnboardingSetupDependencies = {}): Promise<void> {
|
|
21
|
+
const stdinIsTTY = deps.stdinIsTTY ?? process.stdin.isTTY;
|
|
22
|
+
const stdoutIsTTY = deps.stdoutIsTTY ?? process.stdout.isTTY;
|
|
23
|
+
if (!stdinIsTTY || !stdoutIsTTY) {
|
|
24
|
+
(deps.writeStderr ?? (text => process.stderr.write(text)))("omp setup requires an interactive TTY.\n");
|
|
25
|
+
(deps.exit ?? process.exit)(1);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
await (deps.runRoot ?? runRootCommand)(parseArgs([]), [], { forceSetupWizard: true });
|
|
29
|
+
}
|
|
30
|
+
|
|
10
31
|
export default class Setup extends Command {
|
|
11
|
-
static description = "
|
|
32
|
+
static description = "Run onboarding setup or install dependencies for optional features";
|
|
12
33
|
|
|
13
34
|
static args = {
|
|
14
35
|
component: Args.string({
|
|
15
|
-
description: "
|
|
36
|
+
description: "Optional component to install",
|
|
16
37
|
required: false,
|
|
17
38
|
options: COMPONENTS,
|
|
18
39
|
}),
|
|
@@ -26,7 +47,11 @@ export default class Setup extends Command {
|
|
|
26
47
|
async run(): Promise<void> {
|
|
27
48
|
const { args, flags } = await this.parse(Setup);
|
|
28
49
|
if (!args.component) {
|
|
29
|
-
|
|
50
|
+
if (flags.check || flags.json) {
|
|
51
|
+
renderCommandHelp("omp", "setup", Setup);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
await runOnboardingSetup();
|
|
30
55
|
return;
|
|
31
56
|
}
|
|
32
57
|
const cmd: SetupCommandArgs = {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
|
|
2
|
+
import { runTinyModelsCommand, type TinyModelsAction, type TinyModelsCommandArgs } from "../cli/tiny-models-cli";
|
|
3
|
+
|
|
4
|
+
const ACTIONS: TinyModelsAction[] = ["download", "list"];
|
|
5
|
+
|
|
6
|
+
export default class TinyModels extends Command {
|
|
7
|
+
static description = "Download tiny local models (session titles + memory)";
|
|
8
|
+
|
|
9
|
+
static args = {
|
|
10
|
+
action: Args.string({
|
|
11
|
+
description: "Action to perform",
|
|
12
|
+
required: false,
|
|
13
|
+
options: ACTIONS,
|
|
14
|
+
}),
|
|
15
|
+
model: Args.string({
|
|
16
|
+
description: "Model key, or all",
|
|
17
|
+
required: false,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
static flags = {
|
|
22
|
+
json: Flags.boolean({ description: "Output JSON" }),
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
async run(): Promise<void> {
|
|
26
|
+
const { args, flags } = await this.parse(TinyModels);
|
|
27
|
+
const command: TinyModelsCommandArgs = {
|
|
28
|
+
action: (args.action ?? "download") as TinyModelsAction,
|
|
29
|
+
model: args.model,
|
|
30
|
+
flags: {
|
|
31
|
+
json: flags.json,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
await runTinyModelsCommand(command);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { type Api, getBundledModels, getBundledProviders, type Model } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import {
|
|
3
|
+
getBracketStrippedModelIdCandidates,
|
|
4
|
+
getLongestModelLikeIdSegment,
|
|
5
|
+
getModelLikeIdSegments,
|
|
6
|
+
} from "./model-id-affixes";
|
|
2
7
|
|
|
3
8
|
export type CanonicalModelSource = "override" | "bundled" | "heuristic" | "fallback";
|
|
4
9
|
|
|
@@ -29,6 +34,7 @@ export interface CanonicalModelIndex {
|
|
|
29
34
|
interface CanonicalReferenceData {
|
|
30
35
|
references: Map<string, Model<Api>>;
|
|
31
36
|
officialIds: Set<string>;
|
|
37
|
+
suffixAliases: Map<string, string>;
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
interface CompiledEquivalenceConfig {
|
|
@@ -70,6 +76,26 @@ function shouldReplaceReference(existing: Model<Api> | undefined, candidate: Mod
|
|
|
70
76
|
return existing.provider !== "openai" && candidate.provider === "openai";
|
|
71
77
|
}
|
|
72
78
|
|
|
79
|
+
function buildCanonicalSuffixAliasMap(references: ReadonlyMap<string, Model<Api>>): Map<string, string> {
|
|
80
|
+
const aliases = new Map<string, string>();
|
|
81
|
+
for (const reference of references.values()) {
|
|
82
|
+
const slashIndex = reference.id.lastIndexOf("/");
|
|
83
|
+
if (slashIndex === -1) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const suffix = reference.id.slice(slashIndex + 1);
|
|
87
|
+
const alias = getLongestModelLikeIdSegment(suffix);
|
|
88
|
+
if (!alias) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const existing = aliases.get(alias);
|
|
92
|
+
if (!existing || compareCandidatePreference(reference.id, existing) < 0) {
|
|
93
|
+
aliases.set(alias, reference.id);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return new Map([...aliases.entries()].map(([alias, referenceId]) => [normalizeCanonicalIdKey(alias), referenceId]));
|
|
97
|
+
}
|
|
98
|
+
|
|
73
99
|
function createCanonicalReferenceData(): CanonicalReferenceData {
|
|
74
100
|
if (referenceDataCache) {
|
|
75
101
|
return referenceDataCache;
|
|
@@ -85,9 +111,11 @@ function createCanonicalReferenceData(): CanonicalReferenceData {
|
|
|
85
111
|
}
|
|
86
112
|
}
|
|
87
113
|
const officialIds = new Set(references.keys());
|
|
114
|
+
const suffixAliases = buildCanonicalSuffixAliasMap(references);
|
|
88
115
|
referenceDataCache = {
|
|
89
116
|
references: Object.freeze(references) as Map<string, Model<Api>>,
|
|
90
117
|
officialIds: Object.freeze(officialIds) as Set<string>,
|
|
118
|
+
suffixAliases: Object.freeze(suffixAliases) as Map<string, string>,
|
|
91
119
|
};
|
|
92
120
|
return referenceDataCache;
|
|
93
121
|
}
|
|
@@ -590,6 +618,13 @@ function expandHeavyCanonicalCandidates(normalized: string, queue: string[]): vo
|
|
|
590
618
|
queue.push(wrapperCandidate);
|
|
591
619
|
}
|
|
592
620
|
|
|
621
|
+
for (const strippedAffixCandidate of getBracketStrippedModelIdCandidates(normalized)) {
|
|
622
|
+
queue.push(strippedAffixCandidate);
|
|
623
|
+
}
|
|
624
|
+
for (const segment of getModelLikeIdSegments(normalized)) {
|
|
625
|
+
queue.push(segment);
|
|
626
|
+
}
|
|
627
|
+
|
|
593
628
|
const strippedSyntheticPrefix = stripSyntheticPrefix(normalized);
|
|
594
629
|
if (strippedSyntheticPrefix) {
|
|
595
630
|
queue.push(strippedSyntheticPrefix);
|
|
@@ -718,9 +753,15 @@ function resolveCanonicalIdForModel(
|
|
|
718
753
|
}
|
|
719
754
|
|
|
720
755
|
const heuristicCandidates = getHeuristicCanonicalCandidates(model.id, referenceData.officialIds);
|
|
721
|
-
const officialMatches = heuristicCandidates.filter(candidate => referenceData.officialIds.has(candidate));
|
|
756
|
+
const officialMatches = new Set(heuristicCandidates.filter(candidate => referenceData.officialIds.has(candidate)));
|
|
757
|
+
for (const candidate of heuristicCandidates) {
|
|
758
|
+
const aliased = referenceData.suffixAliases.get(normalizeCanonicalIdKey(candidate));
|
|
759
|
+
if (aliased) {
|
|
760
|
+
officialMatches.add(aliased);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
722
763
|
const preferredFallback = getPreferredFallbackCanonicalCandidate(model.id, heuristicCandidates);
|
|
723
|
-
const match = selectBestOfficialCandidate(officialMatches);
|
|
764
|
+
const match = selectBestOfficialCandidate([...officialMatches]);
|
|
724
765
|
if (match) {
|
|
725
766
|
if (
|
|
726
767
|
preferredFallback &&
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const LEADING_BRACKETED_AFFIX_PATTERN = /^(?:\s*(?:\[|【)[^\]】]+(?:\]|】)\s*)+/u;
|
|
2
|
+
const TRAILING_BRACKETED_AFFIX_PATTERN = /(?:\s*(?:\[|【)[^\]】]+(?:\]|】)\s*)+$/u;
|
|
3
|
+
const MODEL_ID_SEGMENT_PATTERN = /[a-z0-9.:-]+/g;
|
|
4
|
+
const MODEL_FAMILY_PREFIX_PATTERN =
|
|
5
|
+
/^(claude|gemini|gpt|grok|glm|qwen|deepseek|kimi|mimo|doubao|ernie|gpt-oss|gemma|minimax|step|command|jamba|llama|o[1345])/i;
|
|
6
|
+
|
|
7
|
+
function hasDigit(value: string): boolean {
|
|
8
|
+
return /\d/.test(value);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function compareSegmentPreference(left: string, right: string): number {
|
|
12
|
+
if (left.length !== right.length) {
|
|
13
|
+
return right.length - left.length;
|
|
14
|
+
}
|
|
15
|
+
return left.localeCompare(right);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getModelLikeIdSegments(modelId: string): string[] {
|
|
19
|
+
const normalized = normalizeModelIdWhitespace(modelId).toLowerCase();
|
|
20
|
+
if (!normalized) return [];
|
|
21
|
+
const segments = (normalized.match(MODEL_ID_SEGMENT_PATTERN) ?? []).filter(
|
|
22
|
+
segment => MODEL_FAMILY_PREFIX_PATTERN.test(segment) && hasDigit(segment),
|
|
23
|
+
);
|
|
24
|
+
const unique = [...new Set(segments)];
|
|
25
|
+
unique.sort(compareSegmentPreference);
|
|
26
|
+
return unique;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getLongestModelLikeIdSegment(modelId: string): string | undefined {
|
|
30
|
+
return getModelLikeIdSegments(modelId)[0];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normalizeModelIdWhitespace(value: string): string {
|
|
34
|
+
return value.trim().replace(/\s+/g, " ");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Strip reseller / wrapper tags that are injected as bracketed affixes around an
|
|
39
|
+
* upstream model id, e.g.
|
|
40
|
+
* "[Kiro] claude-opus-4-8" -> "claude-opus-4-8"
|
|
41
|
+
* "[gcli转] gemini-3.1-pro-preview [假流]" -> "gemini-3.1-pro-preview"
|
|
42
|
+
*/
|
|
43
|
+
export function getBracketStrippedModelIdCandidates(modelId: string): string[] {
|
|
44
|
+
const normalized = normalizeModelIdWhitespace(modelId);
|
|
45
|
+
if (!normalized) return [];
|
|
46
|
+
|
|
47
|
+
const candidates = new Set<string>();
|
|
48
|
+
const withoutLeading = normalizeModelIdWhitespace(normalized.replace(LEADING_BRACKETED_AFFIX_PATTERN, ""));
|
|
49
|
+
const withoutTrailing = normalizeModelIdWhitespace(normalized.replace(TRAILING_BRACKETED_AFFIX_PATTERN, ""));
|
|
50
|
+
const withoutBoth = normalizeModelIdWhitespace(
|
|
51
|
+
normalized.replace(LEADING_BRACKETED_AFFIX_PATTERN, "").replace(TRAILING_BRACKETED_AFFIX_PATTERN, ""),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
for (const candidate of [withoutBoth, withoutLeading, withoutTrailing]) {
|
|
55
|
+
if (candidate && candidate !== normalized) {
|
|
56
|
+
candidates.add(candidate);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return [...candidates];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function stripBracketedModelIdAffixes(modelId: string): string | undefined {
|
|
63
|
+
return getBracketStrippedModelIdCandidates(modelId)[0];
|
|
64
|
+
}
|
|
@@ -42,6 +42,12 @@ import {
|
|
|
42
42
|
formatCanonicalVariantSelector,
|
|
43
43
|
type ModelEquivalenceConfig,
|
|
44
44
|
} from "./model-equivalence";
|
|
45
|
+
import {
|
|
46
|
+
getBracketStrippedModelIdCandidates,
|
|
47
|
+
getLongestModelLikeIdSegment,
|
|
48
|
+
getModelLikeIdSegments,
|
|
49
|
+
stripBracketedModelIdAffixes,
|
|
50
|
+
} from "./model-id-affixes";
|
|
45
51
|
import {
|
|
46
52
|
type ModelOverride,
|
|
47
53
|
type ModelsConfig,
|
|
@@ -650,20 +656,53 @@ function shouldReplaceCustomReference(existing: Model<Api> | undefined, candidat
|
|
|
650
656
|
return existing.provider !== "openai" && candidate.provider === "openai";
|
|
651
657
|
}
|
|
652
658
|
|
|
659
|
+
function normalizeCustomReferenceKey(value: string): string {
|
|
660
|
+
return value.trim().toLowerCase();
|
|
661
|
+
}
|
|
662
|
+
|
|
653
663
|
function buildCustomReferenceMap(): Map<string, Model<Api>> {
|
|
654
664
|
const references = new Map<string, Model<Api>>();
|
|
655
665
|
for (const provider of getBundledProviders()) {
|
|
656
666
|
for (const model of getBundledModels(provider as Parameters<typeof getBundledModels>[0])) {
|
|
657
667
|
const candidate = model as Model<Api>;
|
|
658
|
-
|
|
659
|
-
|
|
668
|
+
const key = normalizeCustomReferenceKey(candidate.id);
|
|
669
|
+
if (shouldReplaceCustomReference(references.get(key), candidate)) {
|
|
670
|
+
references.set(key, candidate);
|
|
660
671
|
}
|
|
661
672
|
}
|
|
662
673
|
}
|
|
663
674
|
return references;
|
|
664
675
|
}
|
|
665
676
|
|
|
677
|
+
function buildCustomReferenceSuffixAliasMap(exactReferences: ReadonlyMap<string, Model<Api>>): Map<string, Model<Api>> {
|
|
678
|
+
const aliases = new Map<string, Model<Api>>();
|
|
679
|
+
for (const reference of exactReferences.values()) {
|
|
680
|
+
const slashIndex = reference.id.lastIndexOf("/");
|
|
681
|
+
if (slashIndex === -1) {
|
|
682
|
+
continue;
|
|
683
|
+
}
|
|
684
|
+
const suffix = reference.id.slice(slashIndex + 1);
|
|
685
|
+
const alias = getLongestModelLikeIdSegment(suffix);
|
|
686
|
+
if (!alias) {
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
if (shouldReplaceCustomReference(aliases.get(alias), reference)) {
|
|
690
|
+
aliases.set(alias, reference);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return aliases;
|
|
694
|
+
}
|
|
695
|
+
|
|
666
696
|
const customReferenceMap = buildCustomReferenceMap();
|
|
697
|
+
const customReferenceSuffixAliasMap = buildCustomReferenceSuffixAliasMap(customReferenceMap);
|
|
698
|
+
|
|
699
|
+
const CUSTOM_REFERENCE_TRAILING_MARKER_PATTERN =
|
|
700
|
+
/[-:](?:thinking|customtools|high|low|medium|minimal|xhigh|free|cloud|exacto|nitro|original|optimized|nvfp4|fp8|fp4|bf16|int8|int4|search)$/i;
|
|
701
|
+
|
|
702
|
+
function stripCustomReferenceTrailingMarker(candidate: string): string | undefined {
|
|
703
|
+
const match = CUSTOM_REFERENCE_TRAILING_MARKER_PATTERN.exec(candidate);
|
|
704
|
+
return match ? candidate.slice(0, match.index) : undefined;
|
|
705
|
+
}
|
|
667
706
|
|
|
668
707
|
function getCustomReferenceCandidateIds(modelId: string): string[] {
|
|
669
708
|
const candidates = new Set<string>();
|
|
@@ -673,23 +712,46 @@ function getCustomReferenceCandidateIds(modelId: string): string[] {
|
|
|
673
712
|
if (!candidate || candidates.has(candidate)) continue;
|
|
674
713
|
candidates.add(candidate);
|
|
675
714
|
|
|
715
|
+
for (const stripped of getBracketStrippedModelIdCandidates(candidate)) {
|
|
716
|
+
queue.push(stripped);
|
|
717
|
+
}
|
|
718
|
+
for (const segment of getModelLikeIdSegments(candidate)) {
|
|
719
|
+
queue.push(segment);
|
|
720
|
+
}
|
|
721
|
+
|
|
676
722
|
for (const suffix of [":cloud", "-cloud"] as const) {
|
|
677
723
|
if (candidate.toLowerCase().endsWith(suffix)) {
|
|
678
724
|
queue.push(candidate.slice(0, -suffix.length));
|
|
679
725
|
}
|
|
680
726
|
}
|
|
681
727
|
|
|
728
|
+
const slashIndex = candidate.lastIndexOf("/");
|
|
729
|
+
if (slashIndex !== -1) {
|
|
730
|
+
queue.push(candidate.slice(slashIndex + 1));
|
|
731
|
+
}
|
|
732
|
+
|
|
682
733
|
const colonToDash = candidate.replace(/:/g, "-");
|
|
683
734
|
if (colonToDash !== candidate) {
|
|
684
735
|
queue.push(colonToDash);
|
|
685
736
|
}
|
|
737
|
+
|
|
738
|
+
const lowercased = candidate.toLowerCase();
|
|
739
|
+
if (lowercased !== candidate) {
|
|
740
|
+
queue.push(lowercased);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
const strippedMarker = stripCustomReferenceTrailingMarker(candidate);
|
|
744
|
+
if (strippedMarker) {
|
|
745
|
+
queue.push(strippedMarker);
|
|
746
|
+
}
|
|
686
747
|
}
|
|
687
748
|
return [...candidates];
|
|
688
749
|
}
|
|
689
750
|
|
|
690
751
|
function resolveCustomModelReference(modelId: string): Model<Api> | undefined {
|
|
691
752
|
for (const candidate of getCustomReferenceCandidateIds(modelId)) {
|
|
692
|
-
const
|
|
753
|
+
const key = normalizeCustomReferenceKey(candidate);
|
|
754
|
+
const reference = customReferenceMap.get(key) ?? customReferenceSuffixAliasMap.get(key);
|
|
693
755
|
if (reference) return reference;
|
|
694
756
|
}
|
|
695
757
|
return undefined;
|
|
@@ -1785,7 +1847,7 @@ export class ModelRegistry {
|
|
|
1785
1847
|
throw new Error(`HTTP ${response.status} from ${modelsUrl}`);
|
|
1786
1848
|
}
|
|
1787
1849
|
const payload = (await response.json()) as {
|
|
1788
|
-
data?: Array<{ id?: string; supported_endpoint_types?: string[] }>;
|
|
1850
|
+
data?: Array<{ id?: string; name?: string; supported_endpoint_types?: string[] }>;
|
|
1789
1851
|
};
|
|
1790
1852
|
const items = payload.data ?? [];
|
|
1791
1853
|
const discovered: Model<Api>[] = [];
|
|
@@ -1800,23 +1862,35 @@ export class ModelRegistry {
|
|
|
1800
1862
|
: providerConfig.api;
|
|
1801
1863
|
if (!api) continue;
|
|
1802
1864
|
const isAnthropic = api === "anthropic-messages";
|
|
1865
|
+
const reference = resolveCustomModelReference(id);
|
|
1866
|
+
const discoveryName = typeof item.name === "string" ? item.name.trim() : "";
|
|
1867
|
+
const displayName =
|
|
1868
|
+
reference?.name ??
|
|
1869
|
+
(discoveryName && discoveryName !== id ? discoveryName : undefined) ??
|
|
1870
|
+
stripBracketedModelIdAffixes(id) ??
|
|
1871
|
+
id;
|
|
1803
1872
|
discovered.push(
|
|
1804
1873
|
enrichModelThinking({
|
|
1805
1874
|
id,
|
|
1806
|
-
name:
|
|
1875
|
+
name: displayName,
|
|
1807
1876
|
api,
|
|
1808
1877
|
provider: providerConfig.provider,
|
|
1809
1878
|
baseUrl,
|
|
1810
|
-
reasoning: false,
|
|
1811
|
-
|
|
1879
|
+
reasoning: reference?.reasoning ?? false,
|
|
1880
|
+
thinking: reference?.thinking,
|
|
1881
|
+
input: reference?.input ?? ["text"],
|
|
1882
|
+
// Proxy pricing is provider-specific and usually does not match
|
|
1883
|
+
// upstream bundled catalogs, so keep costs local-unknown even when
|
|
1884
|
+
// we successfully recover the upstream model identity.
|
|
1812
1885
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1813
|
-
contextWindow: 128000,
|
|
1814
|
-
maxTokens: 8192,
|
|
1886
|
+
contextWindow: reference?.contextWindow ?? 128000,
|
|
1887
|
+
maxTokens: reference?.maxTokens ?? 8192,
|
|
1815
1888
|
headers,
|
|
1816
1889
|
// OpenAI-compat fields are no-ops on anthropic models; the
|
|
1817
1890
|
// Anthropic SDK ignores them. Provider-level disableStrictTools
|
|
1818
1891
|
// flows in via #applyProviderCompat for the third-party-Anthropic
|
|
1819
|
-
// path.
|
|
1892
|
+
// path. Cross-wire bundled compat is intentionally not copied:
|
|
1893
|
+
// request-shaping fields are provider-wire specific.
|
|
1820
1894
|
compat: isAnthropic
|
|
1821
1895
|
? undefined
|
|
1822
1896
|
: {
|