@ottocode/sdk 0.1.245 → 0.1.247

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/package.json +7 -2
  2. package/src/config/src/index.ts +5 -0
  3. package/src/config/src/manager.ts +106 -30
  4. package/src/core/src/providers/resolver.ts +28 -1
  5. package/src/core/src/tools/builtin/bash.ts +1 -266
  6. package/src/core/src/tools/builtin/fs/edit-shared.ts +1 -1
  7. package/src/core/src/tools/builtin/fs/edit.txt +2 -2
  8. package/src/core/src/tools/builtin/fs/write.txt +1 -1
  9. package/src/core/src/tools/builtin/shell.ts +273 -0
  10. package/src/core/src/tools/builtin/shell.txt +13 -0
  11. package/src/core/src/tools/builtin/terminal.txt +9 -6
  12. package/src/core/src/tools/loader.ts +134 -82
  13. package/src/index.ts +33 -0
  14. package/src/prompts/src/agents/build.txt +5 -6
  15. package/src/prompts/src/modes/guided.txt +2 -2
  16. package/src/prompts/src/providers/anthropic.txt +2 -2
  17. package/src/prompts/src/providers/default.txt +2 -2
  18. package/src/prompts/src/providers/glm.txt +2 -2
  19. package/src/prompts/src/providers/google.txt +9 -9
  20. package/src/prompts/src/providers/moonshot.txt +2 -2
  21. package/src/prompts/src/providers/openai.txt +3 -3
  22. package/src/prompts/src/providers.ts +15 -0
  23. package/src/providers/src/authorization.ts +26 -1
  24. package/src/providers/src/catalog-manual.ts +21 -6
  25. package/src/providers/src/catalog-merged.ts +2 -2
  26. package/src/providers/src/catalog.ts +10462 -10283
  27. package/src/providers/src/env.ts +10 -5
  28. package/src/providers/src/index.ts +26 -0
  29. package/src/providers/src/oauth-models.ts +1 -0
  30. package/src/providers/src/ollama-discovery.ts +149 -0
  31. package/src/providers/src/pricing.ts +3 -0
  32. package/src/providers/src/registry.ts +258 -0
  33. package/src/providers/src/utils.ts +10 -3
  34. package/src/providers/src/validate.ts +63 -2
  35. package/src/skills/index.ts +3 -0
  36. package/src/skills/tool.ts +28 -36
  37. package/src/types/src/config.ts +34 -8
  38. package/src/types/src/index.ts +4 -0
  39. package/src/types/src/provider.ts +33 -3
  40. package/src/core/src/tools/builtin/bash.txt +0 -12
@@ -4,7 +4,7 @@ GUIDED MODE is active. This OVERRIDES all conciseness and brevity instructions.
4
4
  The user is NOT a developer. They cannot run commands, use terminals, or understand technical output.
5
5
 
6
6
  YOU MUST:
7
- - USE YOUR TOOLS to execute every action. Never tell the user to run a command — you run it yourself with bash or terminal tools.
7
+ - USE YOUR TOOLS to execute every action. Never tell the user to run a command — you run it yourself with shell or terminal tools.
8
8
  - NEVER ask permission or say "Want me to...?" — just do it immediately.
9
9
  - NEVER respond with just instructions or steps. Every response must include actual tool calls that do the work.
10
10
  - Check if services are already running before starting them. If not running, start them yourself.
@@ -12,7 +12,7 @@ YOU MUST:
12
12
  - Tell the user the exact URL to open and what they'll see there.
13
13
  - Explain what you DID (past tense) in simple language — not what they should do.
14
14
  - If something fails, fix it yourself silently. Only tell the user once it's resolved.
15
- - Use the terminal tool (not bash) for long-running services so they persist.
15
+ - Use the terminal tool (not shell) for interactive or persistent services so they persist.
16
16
  - Verbose, friendly responses are expected in this mode — ignore any "be concise" instructions.
17
17
 
18
18
  WRONG response: "Run `bun dev` in the project root, then open http://localhost:9100"
@@ -62,7 +62,7 @@ user: which file contains the implementation of foo?
62
62
  assistant: src/foo.c
63
63
  </example>
64
64
 
65
- When you run a non-trivial bash command — especially one that changes state — briefly explain what it does and why, so the user knows what's happening.
65
+ When you run a non-trivial shell command — especially one that changes state — briefly explain what it does and why, so the user knows what's happening.
66
66
 
67
67
  # Proactiveness
68
68
 
@@ -99,7 +99,7 @@ For software engineering requests (bugs, features, refactors, explanations):
99
99
  1. Use `update_todos` to plan multi-step work.
100
100
  2. Explore the codebase with the search tools (`glob`, `ripgrep`, `tree`, `read`). Batch independent searches in parallel.
101
101
  3. Implement the solution.
102
- 4. Verify — run the project's build/lint/test commands with `bash`. Check `README.md` / `AGENTS.md` to find the right command.
102
+ 4. Verify — run the project's build/lint/test commands with `shell`. Check `README.md` / `AGENTS.md` to find the right command.
103
103
  5. Review diffs with `git_status` / `git_diff`.
104
104
  6. NEVER commit unless the user explicitly asks.
105
105
 
@@ -26,8 +26,8 @@ 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 `edit` / `multiedit` for targeted changes; use `apply_patch` for structural or multi-file edits; use `write` only for new files or near-total rewrites.
30
- 4. Verify — run project-specific build/lint/test commands via `bash`. Check `README.md` / `AGENTS.md` for the right command.
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
+ 4. Verify — run project-specific build/lint/test commands via `shell`. Check `README.md` / `AGENTS.md` for the right command.
31
31
  5. Review — `git_status` / `git_diff`. Do NOT commit unless asked.
32
32
 
33
33
  # Direct file references
@@ -38,8 +38,8 @@ 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 `edit` / `multiedit` for targeted changes; use `apply_patch` for structural or multi-file edits; use `write` only for new files or near-total rewrites.
42
- 4. Verify — run project-specific build/lint/test commands via `bash`. Check `README.md` / `AGENTS.md` for the right command.
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
+ 4. Verify — run project-specific build/lint/test commands via `shell`. Check `README.md` / `AGENTS.md` for the right command.
43
43
  5. Review — `git_status` / `git_diff`. Do NOT commit unless asked.
44
44
 
45
45
  # Direct file references
@@ -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 `edit`, `multiedit`, `apply_patch`, `write`, `bash` — strictly adhering to Core Mandates.
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
 
@@ -30,7 +30,7 @@ For bug fixes, features, refactors, or explanations:
30
30
  1. **Understand requirements** — features, UX, platform, constraints. Ask targeted clarification questions if critical info is missing.
31
31
  2. **Propose plan.** Present a concise high-level summary (type, core purpose, key technologies, main features, visual/UX approach). For visual assets, describe the strategy for placeholders (geometric shapes, procedural patterns, open-source assets).
32
32
  3. **User approval.** Obtain approval before implementing.
33
- 4. **Implement** autonomously. Scaffold with `bash` (`npm init`, `npx create-react-app`, etc.). Create placeholder assets when needed; aim for a visually coherent prototype.
33
+ 4. **Implement** autonomously. Scaffold with `shell` (`npm init`, `npx create-react-app`, etc.). Create placeholder assets when needed; aim for a visually coherent prototype.
34
34
  5. **Verify** against the original request and approved plan. Fix bugs, deviations, placeholders. Ensure the build produces no compile errors.
35
35
  6. **Solicit feedback** — provide start-up instructions and ask for feedback.
36
36
 
@@ -48,14 +48,14 @@ For bug fixes, features, refactors, or explanations:
48
48
 
49
49
  ## Security and safety
50
50
 
51
- - **Explain critical commands.** Before executing `bash` commands that modify the file system or system state, briefly explain purpose and potential impact. Don't ask permission — the user will confirm via dialog.
51
+ - **Explain critical commands.** Before executing `shell` commands that modify the file system or system state, briefly explain purpose and potential impact. Don't ask permission — the user will confirm via dialog.
52
52
  - **Security first.** Apply security best practices. Never expose, log, or commit secrets, API keys, or sensitive information.
53
53
 
54
54
  ## Tool usage
55
55
 
56
56
  - **Parallelism.** Execute multiple independent tool calls in parallel when feasible (e.g. codebase searches).
57
- - **Command execution.** Use `bash` for shell commands; explain modifying commands first.
58
- - **Background processes.** Use `&` for long-running processes that don't stop on their own (e.g. `node server.js &`). If unsure, ask. Prefer the `terminal` tool for processes you'll monitor over multiple turns.
57
+ - **Command execution.** Use `shell` for non-interactive shell commands; explain modifying commands first.
58
+ - **Background processes.** Prefer the `terminal` tool for interactive or persistent processes you'll monitor over multiple turns. Use `shell` only for non-interactive commands that finish on their own.
59
59
  - **Interactive commands.** Avoid commands that require user interaction (e.g. `git rebase -i`). Prefer non-interactive versions (`npm init -y`).
60
60
  - **Confirmations.** If the user cancels a tool call, respect their choice — don't retry unless they ask again.
61
61
 
@@ -78,7 +78,7 @@ model: [tool_call: ls for path '/path/to/project']
78
78
 
79
79
  <example>
80
80
  user: start the server implemented in server.js
81
- model: [tool_call: bash for 'node server.js &' because it must run in the background]
81
+ model: [tool_call: terminal for 'node server.js' because it must stay running]
82
82
  </example>
83
83
 
84
84
  <example>
@@ -103,9 +103,9 @@ Here's the plan:
103
103
  Should I proceed?
104
104
  user: Yes
105
105
  model:
106
- [tool_call: edit, multiedit, write, or apply_patch to apply the refactoring to 'src/auth.py']
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
- [tool_call: bash for 'ruff check src/auth.py && pytest']
108
+ [tool_call: shell for 'ruff check src/auth.py && pytest']
109
109
  (After verification passes)
110
110
  All checks passed. This is a stable checkpoint.
111
111
  </example>
@@ -125,7 +125,7 @@ Now I'll look for existing or related test files to understand current testing c
125
125
  (After reviewing existing tests and the file content)
126
126
  [tool_call: write to create /path/to/someFile.test.ts with the test code]
127
127
  I've written the tests. Now I'll run the project's test command to verify them.
128
- [tool_call: bash for 'npm run test']
128
+ [tool_call: shell for 'npm run test']
129
129
  </example>
130
130
 
131
131
  <example>
@@ -38,8 +38,8 @@ 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 `edit` / `multiedit` for targeted changes; use `apply_patch` for structural or multi-file edits; use `write` only for new files or near-total rewrites.
42
- 4. Verify — run project-specific build/lint/test commands via `bash`. Check `README.md` / `AGENTS.md` for the right command.
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
+ 4. Verify — run project-specific build/lint/test commands via `shell`. Check `README.md` / `AGENTS.md` for the right command.
43
43
  5. Review — `git_status` / `git_diff`. Do NOT commit unless asked.
44
44
 
45
45
  # Direct file references
@@ -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 targeted edits in existing files, prefer `edit` and `multiedit`. For structural diffs or file add/delete/rename, use `apply_patch`.
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 `apply_patch` — the call fails if it didn't work.
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 `apply_patch`, don't tell users to "save the file" — just reference the path.
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
- await mgrEnsureEnv(provider, cfg.projectRoot);
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
  }
@@ -3,15 +3,16 @@ import {
3
3
  type OttoRouterModelCatalogEntry,
4
4
  } from '@ottorouter/ai-sdk';
5
5
  import type {
6
+ BuiltInProviderId,
6
7
  ModelInfo,
7
8
  ModelOwner,
8
9
  ProviderCatalogEntry,
9
- ProviderId,
10
10
  } from '../../types/src/index.ts';
11
11
 
12
- type CatalogMap = Partial<Record<ProviderId, ProviderCatalogEntry>>;
12
+ type CatalogMap = Partial<Record<BuiltInProviderId, ProviderCatalogEntry>>;
13
13
 
14
- const OTTOROUTER_ID: ProviderId = 'ottorouter';
14
+ const OLLAMA_CLOUD_ID: BuiltInProviderId = 'ollama-cloud';
15
+ const OTTOROUTER_ID: BuiltInProviderId = 'ottorouter';
15
16
 
16
17
  const OWNER_NPM: Record<ModelOwner, string> = {
17
18
  openai: '@ai-sdk/openai',
@@ -88,13 +89,27 @@ function buildOttoRouterEntry(): ProviderCatalogEntry | null {
88
89
  };
89
90
  }
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: [],
101
+ };
102
+ }
103
+
91
104
  export function mergeManualCatalog(
92
105
  base: CatalogMap,
93
- ): Record<ProviderId, ProviderCatalogEntry> {
106
+ ): Record<BuiltInProviderId, ProviderCatalogEntry> {
107
+ const ollamaCloudEntry = buildOllamaCloudEntry();
94
108
  const manualEntry = buildOttoRouterEntry();
95
- const merged: Record<ProviderId, ProviderCatalogEntry> = {
96
- ...(base as Record<ProviderId, ProviderCatalogEntry>),
109
+ const merged: Record<BuiltInProviderId, ProviderCatalogEntry> = {
110
+ ...(base as Record<BuiltInProviderId, ProviderCatalogEntry>),
97
111
  };
112
+ merged[OLLAMA_CLOUD_ID] = ollamaCloudEntry;
98
113
  if (manualEntry) {
99
114
  merged[OTTOROUTER_ID] = manualEntry;
100
115
  }
@@ -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<ProviderId, ProviderCatalogEntry> =
8
+ export const catalog: Record<BuiltInProviderId, ProviderCatalogEntry> =
9
9
  mergeManualCatalog(generatedCatalog);