@ottocode/server 0.1.259 → 0.1.261

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 (69) hide show
  1. package/package.json +4 -3
  2. package/src/index.ts +5 -4
  3. package/src/openapi/register.ts +92 -0
  4. package/src/openapi/route.ts +22 -0
  5. package/src/routes/ask.ts +210 -99
  6. package/src/routes/auth.ts +1701 -626
  7. package/src/routes/branch.ts +281 -90
  8. package/src/routes/config/agents.ts +79 -32
  9. package/src/routes/config/cwd.ts +46 -14
  10. package/src/routes/config/debug.ts +159 -30
  11. package/src/routes/config/defaults.ts +182 -64
  12. package/src/routes/config/main.ts +109 -73
  13. package/src/routes/config/models.ts +304 -137
  14. package/src/routes/config/providers.ts +462 -166
  15. package/src/routes/config/utils.ts +2 -2
  16. package/src/routes/doctor.ts +395 -161
  17. package/src/routes/files.ts +650 -260
  18. package/src/routes/git/branch.ts +143 -52
  19. package/src/routes/git/commit.ts +347 -141
  20. package/src/routes/git/diff.ts +239 -116
  21. package/src/routes/git/init.ts +103 -23
  22. package/src/routes/git/pull.ts +167 -65
  23. package/src/routes/git/push.ts +222 -117
  24. package/src/routes/git/remote.ts +401 -100
  25. package/src/routes/git/staging.ts +502 -141
  26. package/src/routes/git/status.ts +171 -78
  27. package/src/routes/mcp.ts +1129 -404
  28. package/src/routes/openapi.ts +27 -4
  29. package/src/routes/ottorouter.ts +1221 -389
  30. package/src/routes/provider-usage.ts +153 -36
  31. package/src/routes/research.ts +817 -370
  32. package/src/routes/root.ts +50 -6
  33. package/src/routes/session-approval.ts +228 -54
  34. package/src/routes/session-files.ts +265 -134
  35. package/src/routes/session-messages.ts +330 -150
  36. package/src/routes/session-stream.ts +83 -2
  37. package/src/routes/sessions.ts +1830 -780
  38. package/src/routes/skills.ts +849 -161
  39. package/src/routes/terminals.ts +469 -103
  40. package/src/routes/tunnel.ts +394 -118
  41. package/src/runtime/agent/runner-reasoning.ts +38 -3
  42. package/src/runtime/agent/runner.ts +1 -0
  43. package/src/runtime/ask/service.ts +1 -0
  44. package/src/runtime/message/compaction-limits.ts +3 -3
  45. package/src/runtime/provider/reasoning.ts +18 -7
  46. package/src/runtime/session/db-operations.ts +4 -3
  47. package/src/runtime/utils/token.ts +7 -2
  48. package/src/tools/adapter.ts +21 -0
  49. package/src/openapi/paths/ask.ts +0 -81
  50. package/src/openapi/paths/auth.ts +0 -687
  51. package/src/openapi/paths/branch.ts +0 -102
  52. package/src/openapi/paths/config.ts +0 -485
  53. package/src/openapi/paths/doctor.ts +0 -165
  54. package/src/openapi/paths/files.ts +0 -236
  55. package/src/openapi/paths/git.ts +0 -690
  56. package/src/openapi/paths/mcp.ts +0 -339
  57. package/src/openapi/paths/messages.ts +0 -103
  58. package/src/openapi/paths/ottorouter.ts +0 -594
  59. package/src/openapi/paths/provider-usage.ts +0 -59
  60. package/src/openapi/paths/research.ts +0 -227
  61. package/src/openapi/paths/session-approval.ts +0 -93
  62. package/src/openapi/paths/session-extras.ts +0 -336
  63. package/src/openapi/paths/session-files.ts +0 -91
  64. package/src/openapi/paths/sessions.ts +0 -210
  65. package/src/openapi/paths/skills.ts +0 -377
  66. package/src/openapi/paths/stream.ts +0 -26
  67. package/src/openapi/paths/terminals.ts +0 -226
  68. package/src/openapi/paths/tunnel.ts +0 -163
  69. package/src/openapi/spec.ts +0 -73
@@ -4,6 +4,7 @@ import {
4
4
  getProviderDefinition,
5
5
  getModelNpmBinding,
6
6
  getUnderlyingProviderKey,
7
+ isBuiltInProviderId,
7
8
  modelSupportsReasoning,
8
9
  type OttoConfig,
9
10
  type ProviderId,
@@ -27,8 +28,9 @@ function normalizeReasoningLevel(
27
28
  }
28
29
 
29
30
  function toAnthropicEffort(
31
+ model: string,
30
32
  level: ReasoningLevel | undefined,
31
- ): 'low' | 'medium' | 'high' | 'max' {
33
+ ): 'low' | 'medium' | 'high' | 'xhigh' | 'max' {
32
34
  switch (level) {
33
35
  case 'minimal':
34
36
  case 'low':
@@ -36,8 +38,9 @@ function toAnthropicEffort(
36
38
  case 'medium':
37
39
  return 'medium';
38
40
  case 'max':
39
- case 'xhigh':
40
41
  return 'max';
42
+ case 'xhigh':
43
+ return isClaudeOpus47(model) ? 'xhigh' : 'max';
41
44
  default:
42
45
  return 'high';
43
46
  }
@@ -116,7 +119,7 @@ function getOpenAICompatibleProviderOptionKeys(
116
119
  cfg?: OttoConfig,
117
120
  ): string[] {
118
121
  const definition = cfg ? getProviderDefinition(cfg, provider) : undefined;
119
- const entry = catalog[provider];
122
+ const entry = isBuiltInProviderId(provider) ? catalog[provider] : undefined;
120
123
  const keys = new Set<string>(['openaiCompatible', toCamelCaseKey(provider)]);
121
124
  const label = definition?.label ?? entry?.label;
122
125
  if (label) {
@@ -134,11 +137,15 @@ function buildSharedProviderOptions(
134
137
  return Object.fromEntries(keys.map((key) => [key, options]));
135
138
  }
136
139
 
140
+ function isClaudeOpus47(model: string): boolean {
141
+ const lower = model.toLowerCase();
142
+ return lower.includes('claude-opus-4-7') || lower.includes('claude-opus-4.7');
143
+ }
144
+
137
145
  function usesAdaptiveAnthropicThinking(model: string): boolean {
138
146
  const lower = model.toLowerCase();
139
147
  return (
140
- lower.includes('claude-opus-4-7') ||
141
- lower.includes('claude-opus-4.7') ||
148
+ isClaudeOpus47(model) ||
142
149
  lower.includes('claude-opus-4-6') ||
143
150
  lower.includes('claude-opus-4.6') ||
144
151
  lower.includes('claude-sonnet-4-6') ||
@@ -238,11 +245,15 @@ export function buildReasoningConfig(args: {
238
245
  const reasoningTarget = getReasoningProviderTarget(provider, model, cfg);
239
246
  if (reasoningTarget === 'anthropic') {
240
247
  if (usesAdaptiveAnthropicThinking(model)) {
248
+ const thinking = isClaudeOpus47(model)
249
+ ? { type: 'adaptive', display: 'summarized' }
250
+ : { type: 'adaptive' };
251
+
241
252
  return {
242
253
  providerOptions: {
243
254
  anthropic: {
244
- thinking: { type: 'adaptive' },
245
- effort: toAnthropicEffort(reasoningLevel),
255
+ thinking,
256
+ effort: toAnthropicEffort(model, reasoningLevel),
246
257
  },
247
258
  },
248
259
  effectiveMaxOutputTokens: maxOutputTokens,
@@ -1,7 +1,7 @@
1
1
  import type { getDb } from '@ottocode/database';
2
2
  import { messages, messageParts, sessions } from '@ottocode/database/schema';
3
3
  import { eq } from 'drizzle-orm';
4
- import { catalog, type ProviderId } from '@ottocode/sdk';
4
+ import { catalog, isBuiltInProviderId, type ProviderId } from '@ottocode/sdk';
5
5
  import type { RunOpts } from './queue.ts';
6
6
 
7
7
  export type UsageData = {
@@ -77,10 +77,11 @@ export function resolveUsageProvider(
77
77
  ) {
78
78
  return provider;
79
79
  }
80
- const entry = catalog[provider];
80
+ const entry = isBuiltInProviderId(provider) ? catalog[provider] : undefined;
81
81
  const normalizedModel = model.includes('/') ? model.split('/').at(-1) : model;
82
82
  const modelEntry = entry?.models.find(
83
- (m) => m.id?.toLowerCase() === normalizedModel?.toLowerCase(),
83
+ (m: { id?: string }) =>
84
+ m.id?.toLowerCase() === normalizedModel?.toLowerCase(),
84
85
  );
85
86
  const npm = modelEntry?.provider?.npm ?? '';
86
87
  if (npm.includes('openai')) return 'openai';
@@ -1,4 +1,4 @@
1
- import { catalog } from '@ottocode/sdk';
1
+ import { catalog, isBuiltInProviderId } from '@ottocode/sdk';
2
2
  import type { ProviderName } from '../provider/index.ts';
3
3
 
4
4
  /**
@@ -13,11 +13,16 @@ export function getMaxOutputTokens(
13
13
  return undefined;
14
14
  }
15
15
  try {
16
+ if (!isBuiltInProviderId(provider)) {
17
+ return undefined;
18
+ }
16
19
  const providerCatalog = catalog[provider];
17
20
  if (!providerCatalog) {
18
21
  return undefined;
19
22
  }
20
- const modelInfo = providerCatalog.models.find((m) => m.id === modelId);
23
+ const modelInfo = providerCatalog.models.find(
24
+ (m: { id: string }) => m.id === modelId,
25
+ );
21
26
  if (!modelInfo) {
22
27
  return undefined;
23
28
  }
@@ -530,6 +530,27 @@ export function adaptTools(
530
530
  streamedResult = (chunk as { result: unknown }).result;
531
531
  continue;
532
532
  }
533
+ if (
534
+ chunk &&
535
+ typeof chunk === 'object' &&
536
+ 'terminalId' in chunk &&
537
+ typeof (chunk as { terminalId?: unknown }).terminalId ===
538
+ 'string'
539
+ ) {
540
+ publish({
541
+ type: 'tool.delta',
542
+ sessionId: ctx.sessionId,
543
+ payload: {
544
+ name,
545
+ channel: 'terminal',
546
+ delta: (chunk as { terminalId: string }).terminalId,
547
+ stepIndex: stepIndexForEvent,
548
+ callId: callIdFromQueue,
549
+ messageId: ctx.messageId,
550
+ },
551
+ });
552
+ continue;
553
+ }
533
554
  const delta =
534
555
  typeof chunk === 'string'
535
556
  ? chunk
@@ -1,81 +0,0 @@
1
- import { errorResponse, projectQueryParam } from '../helpers';
2
-
3
- export const askPaths = {
4
- '/v1/ask': {
5
- post: {
6
- tags: ['ask'],
7
- operationId: 'ask',
8
- summary: 'Send a prompt using the ask service',
9
- description:
10
- 'Streamlined endpoint used by the CLI to send prompts and receive assistant responses. Creates sessions as needed and reuses the last session when requested.',
11
- parameters: [projectQueryParam()],
12
- requestBody: {
13
- required: true,
14
- content: {
15
- 'application/json': {
16
- schema: {
17
- type: 'object',
18
- required: ['prompt'],
19
- properties: {
20
- prompt: {
21
- type: 'string',
22
- description: 'User prompt to send to the assistant.',
23
- },
24
- agent: {
25
- type: 'string',
26
- description: 'Optional agent name to use for this request.',
27
- },
28
- provider: {
29
- $ref: '#/components/schemas/Provider',
30
- description:
31
- 'Optional provider override. When omitted the agent and config defaults apply.',
32
- },
33
- model: {
34
- type: 'string',
35
- description:
36
- 'Optional model override for the selected provider.',
37
- },
38
- reasoningText: {
39
- type: 'boolean',
40
- description:
41
- 'Enable extended thinking / reasoning for models that support it.',
42
- },
43
- reasoningLevel: {
44
- type: 'string',
45
- enum: ['minimal', 'low', 'medium', 'high', 'max', 'xhigh'],
46
- description:
47
- 'Optional reasoning intensity override for supported providers/models.',
48
- },
49
- sessionId: {
50
- type: 'string',
51
- description: 'Send the prompt to a specific session.',
52
- },
53
- last: {
54
- type: 'boolean',
55
- description:
56
- 'If true, reuse the most recent session for the project.',
57
- },
58
- jsonMode: {
59
- type: 'boolean',
60
- description:
61
- 'Request structured JSON output when supported by the agent.',
62
- },
63
- },
64
- },
65
- },
66
- },
67
- },
68
- responses: {
69
- 202: {
70
- description: 'Accepted',
71
- content: {
72
- 'application/json': {
73
- schema: { $ref: '#/components/schemas/AskResponse' },
74
- },
75
- },
76
- },
77
- 400: errorResponse(),
78
- },
79
- },
80
- },
81
- } as const;