@ottocode/sdk 0.1.244 → 0.1.246
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/package.json +3 -2
- package/src/auth/src/index.ts +2 -2
- package/src/auth/src/wallet.ts +5 -5
- package/src/config/src/index.ts +7 -2
- package/src/config/src/manager.ts +106 -30
- package/src/core/src/index.ts +6 -1
- package/src/core/src/providers/resolver.ts +37 -9
- package/src/core/src/tools/builtin/bash.ts +2 -2
- package/src/core/src/tools/builtin/bash.txt +1 -1
- package/src/core/src/tools/builtin/fs/edit-shared.ts +1 -1
- package/src/core/src/tools/builtin/fs/edit.txt +2 -2
- package/src/core/src/tools/builtin/fs/write.txt +1 -1
- package/src/core/src/tools/loader.ts +133 -81
- package/src/core/src/utils/debug.ts +13 -0
- package/src/index.ts +47 -12
- package/src/prompts/src/agents/build.txt +3 -4
- package/src/prompts/src/providers/default.txt +1 -1
- package/src/prompts/src/providers/glm.txt +1 -1
- package/src/prompts/src/providers/google.txt +2 -2
- package/src/prompts/src/providers/moonshot.txt +1 -1
- package/src/prompts/src/providers/openai.txt +3 -3
- package/src/prompts/src/providers.ts +15 -0
- package/src/providers/src/authorization.ts +26 -1
- package/src/providers/src/catalog-manual.ts +41 -23
- package/src/providers/src/catalog-merged.ts +2 -2
- package/src/providers/src/catalog.ts +10284 -10283
- package/src/providers/src/env.ts +11 -6
- package/src/providers/src/index.ts +38 -12
- package/src/providers/src/ollama-discovery.ts +149 -0
- package/src/providers/src/{setu-client.ts → ottorouter-client.ts} +30 -30
- package/src/providers/src/pricing.ts +4 -1
- package/src/providers/src/registry.ts +258 -0
- package/src/providers/src/utils.ts +11 -4
- package/src/providers/src/validate.ts +63 -2
- package/src/skills/index.ts +3 -0
- package/src/skills/tool.ts +28 -36
- package/src/types/src/config.ts +34 -8
- package/src/types/src/index.ts +4 -0
- package/src/types/src/provider.ts +34 -4
|
@@ -6,6 +6,9 @@ type DebugSettings = {
|
|
|
6
6
|
debugScopes?: unknown;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
let debugEnabledOverride: boolean | undefined;
|
|
10
|
+
let traceEnabledOverride: boolean | undefined;
|
|
11
|
+
|
|
9
12
|
function readDebugSettings(): DebugSettings {
|
|
10
13
|
try {
|
|
11
14
|
const raw = readFileSync(getGlobalConfigPath(), 'utf-8');
|
|
@@ -17,13 +20,23 @@ function readDebugSettings(): DebugSettings {
|
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
export function isDebugEnabled(): boolean {
|
|
23
|
+
if (debugEnabledOverride !== undefined) return debugEnabledOverride;
|
|
20
24
|
return readDebugSettings().debugEnabled === true;
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
export function isTraceEnabled(): boolean {
|
|
28
|
+
if (traceEnabledOverride !== undefined) return traceEnabledOverride;
|
|
24
29
|
return false;
|
|
25
30
|
}
|
|
26
31
|
|
|
32
|
+
export function setDebugEnabled(enabled: boolean): void {
|
|
33
|
+
debugEnabledOverride = enabled;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function setTraceEnabled(enabled: boolean): void {
|
|
37
|
+
traceEnabledOverride = enabled;
|
|
38
|
+
}
|
|
39
|
+
|
|
27
40
|
export function getDebugScopes(): string[] {
|
|
28
41
|
const scopes = readDebugSettings().debugScopes;
|
|
29
42
|
if (!Array.isArray(scopes)) return [];
|
package/src/index.ts
CHANGED
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
// =======================
|
|
15
15
|
// Provider types
|
|
16
16
|
export type {
|
|
17
|
+
BuiltInProviderId,
|
|
17
18
|
ProviderId,
|
|
19
|
+
ProviderCompatibility,
|
|
20
|
+
ProviderPromptFamily,
|
|
18
21
|
ModelOwner,
|
|
19
22
|
ModelInfo,
|
|
20
23
|
ModelProviderBinding,
|
|
@@ -28,6 +31,7 @@ export type { ApiAuth, OAuth, AuthInfo, AuthFile } from './types/src/index.ts';
|
|
|
28
31
|
export type {
|
|
29
32
|
DefaultConfig,
|
|
30
33
|
PathConfig,
|
|
34
|
+
ProviderSettingsEntry,
|
|
31
35
|
OttoConfig,
|
|
32
36
|
ReasoningLevel,
|
|
33
37
|
} from './types/src/index.ts';
|
|
@@ -51,6 +55,29 @@ export {
|
|
|
51
55
|
modelSupportsReasoning,
|
|
52
56
|
} from './providers/src/index.ts';
|
|
53
57
|
export type { UnderlyingProviderKey } from './providers/src/index.ts';
|
|
58
|
+
export {
|
|
59
|
+
discoverOllamaModels,
|
|
60
|
+
normalizeOllamaBaseURL,
|
|
61
|
+
} from './providers/src/index.ts';
|
|
62
|
+
export type {
|
|
63
|
+
DiscoverOllamaOptions,
|
|
64
|
+
DiscoverOllamaResult,
|
|
65
|
+
} from './providers/src/index.ts';
|
|
66
|
+
export {
|
|
67
|
+
isBuiltInProviderId,
|
|
68
|
+
getProviderSettings,
|
|
69
|
+
getProviderDefinition,
|
|
70
|
+
hasConfiguredProvider,
|
|
71
|
+
getConfiguredProviderIds,
|
|
72
|
+
getConfiguredProviderModels,
|
|
73
|
+
getConfiguredProviderDefaultModel,
|
|
74
|
+
providerAllowsAnyModel,
|
|
75
|
+
hasConfiguredModel,
|
|
76
|
+
getConfiguredProviderFamily,
|
|
77
|
+
getConfiguredProviderEnvVar,
|
|
78
|
+
getConfiguredProviderApiKey,
|
|
79
|
+
} from './providers/src/index.ts';
|
|
80
|
+
export type { ResolvedProviderDefinition } from './providers/src/index.ts';
|
|
54
81
|
export {
|
|
55
82
|
isProviderAuthorized,
|
|
56
83
|
ensureProviderEnv,
|
|
@@ -63,20 +90,20 @@ export {
|
|
|
63
90
|
setEnvKey,
|
|
64
91
|
} from './providers/src/index.ts';
|
|
65
92
|
export {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
93
|
+
createOttoRouter,
|
|
94
|
+
createOttoRouterFetch,
|
|
95
|
+
createOttoRouterModel,
|
|
96
|
+
fetchOttoRouterBalance,
|
|
70
97
|
getPublicKeyFromPrivate,
|
|
71
98
|
fetchSolanaUsdcBalance,
|
|
72
99
|
} from './providers/src/index.ts';
|
|
73
100
|
export type {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
OttoRouterAuth,
|
|
102
|
+
OttoRouterInstance,
|
|
103
|
+
OttoRouterProviderOptions,
|
|
104
|
+
OttoRouterPaymentCallbacks,
|
|
105
|
+
OttoRouterBalanceUpdate,
|
|
106
|
+
OttoRouterBalanceResponse,
|
|
80
107
|
SolanaUsdcBalanceResponse,
|
|
81
108
|
} from './providers/src/index.ts';
|
|
82
109
|
export {
|
|
@@ -150,8 +177,8 @@ export {
|
|
|
150
177
|
generateWallet,
|
|
151
178
|
importWallet,
|
|
152
179
|
isValidPrivateKey,
|
|
153
|
-
|
|
154
|
-
|
|
180
|
+
getOttoRouterWallet,
|
|
181
|
+
ensureOttoRouterWallet,
|
|
155
182
|
} from './auth/src/index.ts';
|
|
156
183
|
export type { WalletInfo } from './auth/src/index.ts';
|
|
157
184
|
export {
|
|
@@ -193,6 +220,9 @@ export {
|
|
|
193
220
|
isAuthorized,
|
|
194
221
|
ensureEnv,
|
|
195
222
|
writeDefaults as setConfig,
|
|
223
|
+
writeProviderSettings,
|
|
224
|
+
removeProviderSettings,
|
|
225
|
+
writeSkillSettings,
|
|
196
226
|
readDebugConfig,
|
|
197
227
|
writeDebugConfig,
|
|
198
228
|
writeAuth,
|
|
@@ -290,6 +320,8 @@ export {
|
|
|
290
320
|
time,
|
|
291
321
|
isDebugEnabled,
|
|
292
322
|
isTraceEnabled,
|
|
323
|
+
setDebugEnabled,
|
|
324
|
+
setTraceEnabled,
|
|
293
325
|
} from './core/src/index.ts';
|
|
294
326
|
|
|
295
327
|
// Schema Validation
|
|
@@ -337,8 +369,11 @@ export {
|
|
|
337
369
|
export {
|
|
338
370
|
initializeSkills,
|
|
339
371
|
getDiscoveredSkills,
|
|
372
|
+
setSkillSettings,
|
|
373
|
+
filterDiscoveredSkills,
|
|
340
374
|
isSkillsInitialized,
|
|
341
375
|
buildSkillTool,
|
|
376
|
+
summarizeDescription,
|
|
342
377
|
rebuildSkillDescription,
|
|
343
378
|
} from './skills/index.ts';
|
|
344
379
|
|
|
@@ -8,10 +8,9 @@ You help with coding and build tasks.
|
|
|
8
8
|
|
|
9
9
|
Pick the right tool for the job (each tool's description has its full contract):
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
- `
|
|
14
|
-
- `write` — NEW files only, or >70% full-file rewrites. Never for targeted edits.
|
|
11
|
+
- Use the exact-replacement editing tools available to you for targeted changes in existing files.
|
|
12
|
+
- Use patch-style editing for structural diffs, file add/delete/rename, or multi-file changes when that capability is available.
|
|
13
|
+
- Use `write` only for NEW files or >70% full-file rewrites. Never use it for targeted edits.
|
|
15
14
|
|
|
16
15
|
**Always read a file immediately before editing it.** Memory and earlier context are not reliable — the file may have changed.
|
|
17
16
|
|
|
@@ -26,7 +26,7 @@ You are a coding agent running in otto, a terminal-based coding assistant. Preci
|
|
|
26
26
|
|
|
27
27
|
1. Understand — use `glob`, `ripgrep`, `tree`, `read` to map the code. Batch independent searches.
|
|
28
28
|
2. Plan — use `update_todos` for multi-step work. Mark one step `in_progress` at a time.
|
|
29
|
-
3. Implement — prefer
|
|
29
|
+
3. Implement — prefer the targeted editing tools available to you for small in-file changes; use patch-style edits for structural or multi-file changes when available; use `write` only for new files or near-total rewrites.
|
|
30
30
|
4. Verify — run project-specific build/lint/test commands via `bash`. Check `README.md` / `AGENTS.md` for the right command.
|
|
31
31
|
5. Review — `git_status` / `git_diff`. Do NOT commit unless asked.
|
|
32
32
|
|
|
@@ -38,7 +38,7 @@ Your reasoning is powerful, but it can override what you actually read. Guard ag
|
|
|
38
38
|
|
|
39
39
|
1. Understand — use `glob`, `ripgrep`, `tree`, `read` to map the code. Batch independent searches.
|
|
40
40
|
2. Plan — use `update_todos` for multi-step work. Mark one step `in_progress` at a time.
|
|
41
|
-
3. Implement — prefer
|
|
41
|
+
3. Implement — prefer the targeted editing tools available to you for small in-file changes; use patch-style edits for structural or multi-file changes when available; use `write` only for new files or near-total rewrites.
|
|
42
42
|
4. Verify — run project-specific build/lint/test commands via `bash`. Check `README.md` / `AGENTS.md` for the right command.
|
|
43
43
|
5. Review — `git_status` / `git_diff`. Do NOT commit unless asked.
|
|
44
44
|
|
|
@@ -21,7 +21,7 @@ For bug fixes, features, refactors, or explanations:
|
|
|
21
21
|
|
|
22
22
|
1. **Understand.** Use `glob` / `ripgrep` / `tree` / `read` extensively (in parallel when independent) to understand structure, patterns, and conventions.
|
|
23
23
|
2. **Plan.** Build a grounded plan. Share an extremely concise plan with the user if it helps. Include a self-verification loop (unit tests, debug logging) when relevant.
|
|
24
|
-
3. **Implement.** Use
|
|
24
|
+
3. **Implement.** Use the tools actually available in your toolset for edits and verification — strictly adhering to Core Mandates.
|
|
25
25
|
4. **Verify (tests).** Identify test commands from `README`, `package.json`, or existing test patterns. NEVER assume standard test commands.
|
|
26
26
|
5. **Verify (standards).** Run the project's build, linter, and type-checker (e.g. `tsc`, `npm run lint`, `ruff check .`). If unsure, ask the user.
|
|
27
27
|
|
|
@@ -103,7 +103,7 @@ Here's the plan:
|
|
|
103
103
|
Should I proceed?
|
|
104
104
|
user: Yes
|
|
105
105
|
model:
|
|
106
|
-
[tool_call:
|
|
106
|
+
[tool_call: use the appropriate available file-editing tool to apply the refactoring to 'src/auth.py']
|
|
107
107
|
Refactoring complete. Running verification...
|
|
108
108
|
[tool_call: bash for 'ruff check src/auth.py && pytest']
|
|
109
109
|
(After verification passes)
|
|
@@ -38,7 +38,7 @@ Your reasoning is powerful, but it can override what you actually read. Guard ag
|
|
|
38
38
|
|
|
39
39
|
1. Understand — use `glob`, `ripgrep`, `tree`, `read` to map the code. Batch independent searches.
|
|
40
40
|
2. Plan — use `update_todos` for multi-step work. Mark one step `in_progress` at a time.
|
|
41
|
-
3. Implement — prefer
|
|
41
|
+
3. Implement — prefer the targeted editing tools available to you for small in-file changes; use patch-style edits for structural or multi-file changes when available; use `write` only for new files or near-total rewrites.
|
|
42
42
|
4. Verify — run project-specific build/lint/test commands via `bash`. Check `README.md` / `AGENTS.md` for the right command.
|
|
43
43
|
5. Review — `git_status` / `git_diff`. Do NOT commit unless asked.
|
|
44
44
|
|
|
@@ -74,7 +74,7 @@ Criteria when solving queries:
|
|
|
74
74
|
- Working on repos in the current environment is allowed, even proprietary ones.
|
|
75
75
|
- Analyzing code for vulnerabilities is allowed.
|
|
76
76
|
- Showing user code and tool call details is allowed.
|
|
77
|
-
- For
|
|
77
|
+
- For code edits, prefer the targeted editing tools you actually have. Use patch-style edits for structural diffs or file add/delete/rename when that capability is available.
|
|
78
78
|
|
|
79
79
|
Code guidelines (AGENTS.md may override):
|
|
80
80
|
|
|
@@ -85,7 +85,7 @@ Code guidelines (AGENTS.md may override):
|
|
|
85
85
|
- Keep changes consistent with existing codebase style; minimal and focused.
|
|
86
86
|
- Use `git log` / `git blame` to search history when needed.
|
|
87
87
|
- NEVER add copyright or license headers unless asked.
|
|
88
|
-
- Do NOT re-read files after
|
|
88
|
+
- Do NOT re-read files after a successful patch-style edit — the call fails if it didn't work.
|
|
89
89
|
- Do NOT `git commit` or create branches unless explicitly requested.
|
|
90
90
|
- Do NOT add inline comments within code unless asked.
|
|
91
91
|
- Do NOT use one-letter variable names unless asked.
|
|
@@ -120,7 +120,7 @@ Read like an update from a concise teammate. For casual conversation, brainstorm
|
|
|
120
120
|
|
|
121
121
|
For finished substantive work, follow the formatting guidelines below. Skip heavy formatting for simple actions or confirmations. Reserve multi-section responses for results that need grouping.
|
|
122
122
|
|
|
123
|
-
The user has access to your work. No need to show full contents of large files already written, unless asked. After
|
|
123
|
+
The user has access to your work. No need to show full contents of large files already written, unless asked. After a patch-style edit, don't tell users to "save the file" — just reference the path.
|
|
124
124
|
|
|
125
125
|
If there's a logical next step you could help with, concisely ask. Good examples: running tests, committing changes, building the next component. If there's something you couldn't do but the user might want to (like verifying changes by running the app), include instructions succinctly.
|
|
126
126
|
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
getModelInfo,
|
|
4
4
|
isProviderId,
|
|
5
5
|
} from '../../providers/src/utils.ts';
|
|
6
|
+
import type { ProviderPromptFamily } from '../../types/src/index.ts';
|
|
6
7
|
import type { UnderlyingProviderKey } from '../../providers/src/utils.ts';
|
|
7
8
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
8
9
|
import PROVIDER_OPENAI from './providers/openai.txt' with { type: 'text' };
|
|
@@ -40,6 +41,14 @@ function promptForFamily(family: UnderlyingProviderKey): string {
|
|
|
40
41
|
return (FAMILY_PROMPTS[family] ?? PROVIDER_DEFAULT).trim();
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
function promptForCustomFamily(
|
|
45
|
+
family: ProviderPromptFamily | undefined,
|
|
46
|
+
): string {
|
|
47
|
+
if (!family || family === 'default') return PROVIDER_DEFAULT.trim();
|
|
48
|
+
if (family === 'openai-compatible') return PROVIDER_DEFAULT.trim();
|
|
49
|
+
return (FAMILY_PROMPTS[family] ?? PROVIDER_DEFAULT).trim();
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
async function readIfExists(path: string): Promise<string | undefined> {
|
|
44
53
|
try {
|
|
45
54
|
const f = Bun.file(path);
|
|
@@ -76,6 +85,7 @@ export async function providerBasePrompt(
|
|
|
76
85
|
provider: string,
|
|
77
86
|
modelId: string | undefined,
|
|
78
87
|
projectRoot: string,
|
|
88
|
+
customFamily?: ProviderPromptFamily,
|
|
79
89
|
): Promise<ProviderPromptResult> {
|
|
80
90
|
const id = String(provider || '').toLowerCase();
|
|
81
91
|
const { modelPaths, providerPaths } = getPromptOverridePaths({
|
|
@@ -100,6 +110,11 @@ export async function providerBasePrompt(
|
|
|
100
110
|
return { prompt: providerText, resolvedType: `custom:${id}` };
|
|
101
111
|
}
|
|
102
112
|
|
|
113
|
+
if (!isProviderId(id) && customFamily) {
|
|
114
|
+
const result = promptForCustomFamily(customFamily);
|
|
115
|
+
return { prompt: result, resolvedType: customFamily };
|
|
116
|
+
}
|
|
117
|
+
|
|
103
118
|
if (isProviderId(id) && modelId) {
|
|
104
119
|
const info = getModelInfo(id, modelId);
|
|
105
120
|
if (info?.ownedBy) {
|
|
@@ -4,14 +4,39 @@ import {
|
|
|
4
4
|
} from '../../config/src/index.ts';
|
|
5
5
|
import type { OttoConfig } from '../../config/src/index.ts';
|
|
6
6
|
import type { ProviderId } from '../../types/src/index.ts';
|
|
7
|
+
import {
|
|
8
|
+
getConfiguredProviderApiKey,
|
|
9
|
+
getConfiguredProviderEnvVar,
|
|
10
|
+
getProviderDefinition,
|
|
11
|
+
isBuiltInProviderId,
|
|
12
|
+
} from './registry.ts';
|
|
7
13
|
|
|
8
14
|
export async function isProviderAuthorized(
|
|
9
15
|
cfg: OttoConfig,
|
|
10
16
|
provider: ProviderId,
|
|
11
17
|
) {
|
|
18
|
+
const definition = getProviderDefinition(cfg, provider);
|
|
19
|
+
if (!definition) return false;
|
|
20
|
+
if (
|
|
21
|
+
definition.source === 'custom' &&
|
|
22
|
+
cfg.providers[String(provider)]?.enabled === false
|
|
23
|
+
)
|
|
24
|
+
return false;
|
|
25
|
+
if (getConfiguredProviderApiKey(cfg, provider)) return true;
|
|
26
|
+
if (definition.apiKeyEnv && process.env[definition.apiKeyEnv]) return true;
|
|
27
|
+
if (!isBuiltInProviderId(provider)) {
|
|
28
|
+
return !definition.apiKeyEnv && !cfg.providers[String(provider)]?.apiKey;
|
|
29
|
+
}
|
|
12
30
|
return await mgrIsAuthorized(provider, cfg.projectRoot);
|
|
13
31
|
}
|
|
14
32
|
|
|
15
33
|
export async function ensureProviderEnv(cfg: OttoConfig, provider: ProviderId) {
|
|
16
|
-
|
|
34
|
+
const envVar = getConfiguredProviderEnvVar(cfg, provider);
|
|
35
|
+
const apiKey = getConfiguredProviderApiKey(cfg, provider);
|
|
36
|
+
if (envVar && apiKey && !process.env[envVar]) {
|
|
37
|
+
process.env[envVar] = apiKey;
|
|
38
|
+
}
|
|
39
|
+
if (isBuiltInProviderId(provider)) {
|
|
40
|
+
await mgrEnsureEnv(provider, cfg.projectRoot);
|
|
41
|
+
}
|
|
17
42
|
}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ottorouterCatalog,
|
|
3
|
+
type OttoRouterModelCatalogEntry,
|
|
4
|
+
} from '@ottorouter/ai-sdk';
|
|
2
5
|
import type {
|
|
6
|
+
BuiltInProviderId,
|
|
3
7
|
ModelInfo,
|
|
4
8
|
ModelOwner,
|
|
5
9
|
ProviderCatalogEntry,
|
|
6
|
-
ProviderId,
|
|
7
10
|
} from '../../types/src/index.ts';
|
|
8
11
|
|
|
9
|
-
type CatalogMap = Partial<Record<
|
|
12
|
+
type CatalogMap = Partial<Record<BuiltInProviderId, ProviderCatalogEntry>>;
|
|
10
13
|
|
|
11
|
-
const
|
|
14
|
+
const OLLAMA_CLOUD_ID: BuiltInProviderId = 'ollama-cloud';
|
|
15
|
+
const OTTOROUTER_ID: BuiltInProviderId = 'ottorouter';
|
|
12
16
|
|
|
13
17
|
const OWNER_NPM: Record<ModelOwner, string> = {
|
|
14
18
|
openai: '@ai-sdk/openai',
|
|
@@ -21,7 +25,7 @@ const OWNER_NPM: Record<ModelOwner, string> = {
|
|
|
21
25
|
minimax: '@ai-sdk/anthropic',
|
|
22
26
|
};
|
|
23
27
|
|
|
24
|
-
function
|
|
28
|
+
function convertOttoRouterModel(m: OttoRouterModelCatalogEntry): ModelInfo {
|
|
25
29
|
const ownedBy = m.owned_by as ModelOwner;
|
|
26
30
|
return {
|
|
27
31
|
id: m.id,
|
|
@@ -52,12 +56,12 @@ function convertSetuModel(m: SetuModelCatalogEntry): ModelInfo {
|
|
|
52
56
|
};
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
function
|
|
56
|
-
const
|
|
59
|
+
function buildOttoRouterEntry(): ProviderCatalogEntry | null {
|
|
60
|
+
const ottorouterModels = ottorouterCatalog.models.map(convertOttoRouterModel);
|
|
57
61
|
|
|
58
|
-
if (!
|
|
62
|
+
if (!ottorouterModels.length) return null;
|
|
59
63
|
|
|
60
|
-
|
|
64
|
+
ottorouterModels.sort((a, b) => {
|
|
61
65
|
const ownerA = a.ownedBy ?? '';
|
|
62
66
|
const ownerB = b.ownedBy ?? '';
|
|
63
67
|
if (ownerA === ownerB) {
|
|
@@ -69,31 +73,45 @@ function buildSetuEntry(): ProviderCatalogEntry | null {
|
|
|
69
73
|
});
|
|
70
74
|
|
|
71
75
|
const defaultModelId = 'gpt-5-codex';
|
|
72
|
-
const defaultIdx =
|
|
76
|
+
const defaultIdx = ottorouterModels.findIndex((m) => m.id === defaultModelId);
|
|
73
77
|
if (defaultIdx > 0) {
|
|
74
|
-
const [picked] =
|
|
75
|
-
|
|
78
|
+
const [picked] = ottorouterModels.splice(defaultIdx, 1);
|
|
79
|
+
ottorouterModels.unshift(picked);
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
return {
|
|
79
|
-
id:
|
|
80
|
-
label: '
|
|
81
|
-
env: ['
|
|
82
|
-
api: 'https://
|
|
83
|
-
doc: 'https://
|
|
84
|
-
models:
|
|
83
|
+
id: OTTOROUTER_ID,
|
|
84
|
+
label: 'OttoRouter',
|
|
85
|
+
env: ['OTTOROUTER_PRIVATE_KEY'],
|
|
86
|
+
api: 'https://api.ottorouter.org/v1',
|
|
87
|
+
doc: 'https://ottorouter.org/docs',
|
|
88
|
+
models: ottorouterModels,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function buildOllamaCloudEntry(): ProviderCatalogEntry {
|
|
93
|
+
return {
|
|
94
|
+
id: OLLAMA_CLOUD_ID,
|
|
95
|
+
label: 'Ollama Cloud',
|
|
96
|
+
env: ['OLLAMA_API_KEY'],
|
|
97
|
+
npm: 'ai-sdk-ollama',
|
|
98
|
+
api: 'https://ollama.com',
|
|
99
|
+
doc: 'https://docs.ollama.com/cloud',
|
|
100
|
+
models: [],
|
|
85
101
|
};
|
|
86
102
|
}
|
|
87
103
|
|
|
88
104
|
export function mergeManualCatalog(
|
|
89
105
|
base: CatalogMap,
|
|
90
|
-
): Record<
|
|
91
|
-
const
|
|
92
|
-
const
|
|
93
|
-
|
|
106
|
+
): Record<BuiltInProviderId, ProviderCatalogEntry> {
|
|
107
|
+
const ollamaCloudEntry = buildOllamaCloudEntry();
|
|
108
|
+
const manualEntry = buildOttoRouterEntry();
|
|
109
|
+
const merged: Record<BuiltInProviderId, ProviderCatalogEntry> = {
|
|
110
|
+
...(base as Record<BuiltInProviderId, ProviderCatalogEntry>),
|
|
94
111
|
};
|
|
112
|
+
merged[OLLAMA_CLOUD_ID] = ollamaCloudEntry;
|
|
95
113
|
if (manualEntry) {
|
|
96
|
-
merged[
|
|
114
|
+
merged[OTTOROUTER_ID] = manualEntry;
|
|
97
115
|
}
|
|
98
116
|
return merged;
|
|
99
117
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
BuiltInProviderId,
|
|
2
3
|
ProviderCatalogEntry,
|
|
3
|
-
ProviderId,
|
|
4
4
|
} from '../../types/src/index.ts';
|
|
5
5
|
import { catalog as generatedCatalog } from './catalog.ts';
|
|
6
6
|
import { mergeManualCatalog } from './catalog-manual.ts';
|
|
7
7
|
|
|
8
|
-
export const catalog: Record<
|
|
8
|
+
export const catalog: Record<BuiltInProviderId, ProviderCatalogEntry> =
|
|
9
9
|
mergeManualCatalog(generatedCatalog);
|