@ottocode/server 0.1.246 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ottocode/server",
3
- "version": "0.1.246",
3
+ "version": "0.1.247",
4
4
  "description": "HTTP API server for ottocode",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -49,8 +49,8 @@
49
49
  "typecheck": "tsc --noEmit"
50
50
  },
51
51
  "dependencies": {
52
- "@ottocode/database": "0.1.246",
53
- "@ottocode/sdk": "0.1.246",
52
+ "@ottocode/database": "0.1.247",
53
+ "@ottocode/sdk": "0.1.247",
54
54
  "ai-sdk-ollama": "^3.8.3",
55
55
  "drizzle-orm": "^0.44.5",
56
56
  "hono": "^4.9.9",
package/src/presets.ts CHANGED
@@ -68,7 +68,7 @@ export const BUILTIN_TOOLS = [
68
68
  'tree',
69
69
  'pwd',
70
70
  'cd',
71
- 'bash',
71
+ 'shell',
72
72
  'terminal',
73
73
  'ripgrep',
74
74
  'glob',
@@ -126,7 +126,7 @@ const defaultToolExtras: Record<string, string[]> = {
126
126
  'write',
127
127
  'ls',
128
128
  'tree',
129
- 'bash',
129
+ 'shell',
130
130
  'update_todos',
131
131
  'glob',
132
132
  'ripgrep',
@@ -144,7 +144,7 @@ const defaultToolExtras: Record<string, string[]> = {
144
144
  'write',
145
145
  'ls',
146
146
  'tree',
147
- 'bash',
147
+ 'shell',
148
148
  'ripgrep',
149
149
  'glob',
150
150
  'websearch',
@@ -158,7 +158,7 @@ const defaultToolExtras: Record<string, string[]> = {
158
158
  'write',
159
159
  'ls',
160
160
  'tree',
161
- 'bash',
161
+ 'shell',
162
162
  'update_todos',
163
163
  'glob',
164
164
  'ripgrep',
@@ -122,6 +122,14 @@ const MODEL_FAMILY_EDIT_TOOL_POLICY_AGENTS = new Set([
122
122
  'init',
123
123
  ]);
124
124
 
125
+ function normalizeToolName(toolName: string): string {
126
+ return toolName === 'bash' ? 'shell' : toolName;
127
+ }
128
+
129
+ function normalizeToolNames(toolNames: string[]): string[] {
130
+ return Array.from(new Set(toolNames.map(normalizeToolName)));
131
+ }
132
+
125
133
  export function applyModelFamilyEditToolPolicy(
126
134
  agent: string,
127
135
  tools: string[],
@@ -129,6 +137,7 @@ export function applyModelFamilyEditToolPolicy(
129
137
  model: string,
130
138
  cfg?: OttoConfig,
131
139
  ): string[] {
140
+ tools = normalizeToolNames(tools);
132
141
  if (!MODEL_FAMILY_EDIT_TOOL_POLICY_AGENTS.has(agent)) return tools;
133
142
 
134
143
  const family = cfg
@@ -328,7 +337,10 @@ export async function setupRunner(opts: RunOpts): Promise<SetupResult> {
328
337
  opts.provider,
329
338
  opts.model,
330
339
  );
331
- const allowedNames = new Set([...allowedToolNames, 'finish']);
340
+ const allowedNames = new Set([
341
+ ...normalizeToolNames(allowedToolNames),
342
+ 'finish',
343
+ ]);
332
344
  const gated = allTools.filter(
333
345
  (tool) => allowedNames.has(tool.name) || tool.name === 'load_mcp_tools',
334
346
  );
@@ -3,6 +3,7 @@ import { publish } from '../../events/bus.ts';
3
3
  export type ToolApprovalMode = 'auto' | 'dangerous' | 'all' | 'yolo';
4
4
 
5
5
  export const DANGEROUS_TOOLS = new Set([
6
+ 'shell',
6
7
  'bash',
7
8
  'edit',
8
9
  'multiedit',
@@ -17,8 +17,9 @@ export function guardToolCall(
17
17
  const a = (args ?? {}) as Record<string, unknown>;
18
18
 
19
19
  switch (toolName) {
20
+ case 'shell':
20
21
  case 'bash':
21
- return guardBashCommand(String(a.cmd ?? ''));
22
+ return guardShellCommand(String(a.cmd ?? ''));
22
23
  case 'terminal':
23
24
  return guardTerminal(a);
24
25
  case 'read':
@@ -30,7 +31,7 @@ export function guardToolCall(
30
31
  }
31
32
  }
32
33
 
33
- function guardBashCommand(cmd: string): GuardAction {
34
+ function guardShellCommand(cmd: string): GuardAction {
34
35
  const n = cmd.trim();
35
36
  if (!n) return { type: 'allow' };
36
37
 
@@ -104,7 +105,7 @@ function checkApprovalCommand(cmd: string): string | null {
104
105
  function guardTerminal(args: Record<string, unknown>): GuardAction {
105
106
  const op = String(args.operation ?? '');
106
107
  if (op === 'start' && typeof args.command === 'string') {
107
- return guardBashCommand(args.command);
108
+ return guardShellCommand(args.command);
108
109
  }
109
110
  return { type: 'allow' };
110
111
  }
@@ -30,7 +30,8 @@ export const CANONICAL_TO_PASCAL: Record<string, string> = {
30
30
  ripgrep: 'Grep',
31
31
 
32
32
  // Execution
33
- bash: 'Bash',
33
+ shell: 'Shell',
34
+ bash: 'Shell',
34
35
  terminal: 'Terminal',
35
36
 
36
37
  // Git operations
@@ -70,7 +71,8 @@ export const PASCAL_TO_CANONICAL: Record<string, string> = {
70
71
  Grep: 'ripgrep', // Maps back to ripgrep (primary search tool)
71
72
 
72
73
  // Execution
73
- Bash: 'bash',
74
+ Shell: 'shell',
75
+ Bash: 'shell',
74
76
  Terminal: 'terminal',
75
77
 
76
78
  // Git operations
@@ -134,8 +134,8 @@ export function adaptTools(
134
134
  const stepStates = ctx.stepExecution.states;
135
135
 
136
136
  // Anthropic allows max 4 cache_control blocks
137
- // Cache only the most frequently used tools: read, write, bash
138
- const cacheableTools = new Set(['read', 'write', 'bash']);
137
+ // Cache only the most frequently used tools: read, write, shell
138
+ const cacheableTools = new Set(['read', 'write', 'shell']);
139
139
  let cachedToolCount = 0;
140
140
 
141
141
  for (const { name: canonicalName, tool } of tools) {
@@ -502,7 +502,7 @@ export function adaptTools(
502
502
  } as ToolExecuteInput;
503
503
  // biome-ignore lint/suspicious/noExplicitAny: AI SDK types are complex
504
504
  res = base.execute?.(nextInput, options as any);
505
- } else if (name === 'bash') {
505
+ } else if (name === 'shell' || name === 'bash') {
506
506
  const needsCwd =
507
507
  !input ||
508
508
  typeof (input as Record<string, unknown>).cwd !== 'string';