@ottocode/server 0.1.264 → 0.1.266

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 (74) hide show
  1. package/package.json +3 -3
  2. package/src/routes/auth/copilot.ts +699 -0
  3. package/src/routes/auth/oauth.ts +578 -0
  4. package/src/routes/auth/onboarding.ts +45 -0
  5. package/src/routes/auth/providers.ts +189 -0
  6. package/src/routes/auth/service.ts +167 -0
  7. package/src/routes/auth/state.ts +23 -0
  8. package/src/routes/auth/status.ts +203 -0
  9. package/src/routes/auth/wallet.ts +229 -0
  10. package/src/routes/auth.ts +12 -2080
  11. package/src/routes/config/models-service.ts +411 -0
  12. package/src/routes/config/models.ts +6 -426
  13. package/src/routes/config/providers-service.ts +237 -0
  14. package/src/routes/config/providers.ts +10 -242
  15. package/src/routes/files/handlers.ts +297 -0
  16. package/src/routes/files/service.ts +313 -0
  17. package/src/routes/files.ts +12 -608
  18. package/src/routes/git/commit-service.ts +207 -0
  19. package/src/routes/git/commit.ts +6 -220
  20. package/src/routes/git/remote-service.ts +116 -0
  21. package/src/routes/git/remote.ts +8 -115
  22. package/src/routes/git/staging-service.ts +111 -0
  23. package/src/routes/git/staging.ts +10 -205
  24. package/src/routes/mcp/auth.ts +338 -0
  25. package/src/routes/mcp/lifecycle.ts +263 -0
  26. package/src/routes/mcp/servers.ts +212 -0
  27. package/src/routes/mcp/service.ts +664 -0
  28. package/src/routes/mcp/state.ts +13 -0
  29. package/src/routes/mcp.ts +6 -1233
  30. package/src/routes/ottorouter/billing.ts +593 -0
  31. package/src/routes/ottorouter/service.ts +92 -0
  32. package/src/routes/ottorouter/topup.ts +301 -0
  33. package/src/routes/ottorouter/wallet.ts +370 -0
  34. package/src/routes/ottorouter.ts +6 -1319
  35. package/src/routes/research/service.ts +339 -0
  36. package/src/routes/research.ts +12 -390
  37. package/src/routes/sessions/crud.ts +563 -0
  38. package/src/routes/sessions/queue.ts +242 -0
  39. package/src/routes/sessions/retry.ts +121 -0
  40. package/src/routes/sessions/service.ts +768 -0
  41. package/src/routes/sessions/share.ts +434 -0
  42. package/src/routes/sessions.ts +8 -1977
  43. package/src/routes/skills/service.ts +221 -0
  44. package/src/routes/skills/spec.ts +309 -0
  45. package/src/routes/skills.ts +31 -909
  46. package/src/routes/terminals/service.ts +326 -0
  47. package/src/routes/terminals.ts +19 -295
  48. package/src/routes/tunnel/service.ts +217 -0
  49. package/src/routes/tunnel.ts +29 -219
  50. package/src/runtime/agent/registry-prompts.ts +147 -0
  51. package/src/runtime/agent/registry.ts +6 -124
  52. package/src/runtime/agent/runner-errors.ts +116 -0
  53. package/src/runtime/agent/runner-reminders.ts +45 -0
  54. package/src/runtime/agent/runner-setup-model.ts +75 -0
  55. package/src/runtime/agent/runner-setup-prompt.ts +185 -0
  56. package/src/runtime/agent/runner-setup-tools.ts +103 -0
  57. package/src/runtime/agent/runner-setup-utils.ts +21 -0
  58. package/src/runtime/agent/runner-setup.ts +54 -288
  59. package/src/runtime/agent/runner-telemetry.ts +112 -0
  60. package/src/runtime/agent/runner-text.ts +108 -0
  61. package/src/runtime/agent/runner-tool-observer.ts +86 -0
  62. package/src/runtime/agent/runner.ts +79 -378
  63. package/src/runtime/ask/service.ts +1 -0
  64. package/src/runtime/provider/custom.ts +73 -0
  65. package/src/runtime/provider/index.ts +6 -85
  66. package/src/runtime/provider/reasoning-builders.ts +280 -0
  67. package/src/runtime/provider/reasoning.ts +68 -264
  68. package/src/runtime/provider/xai.ts +8 -0
  69. package/src/tools/adapter/events.ts +116 -0
  70. package/src/tools/adapter/execution.ts +160 -0
  71. package/src/tools/adapter/pending.ts +37 -0
  72. package/src/tools/adapter/persistence.ts +166 -0
  73. package/src/tools/adapter/results.ts +97 -0
  74. package/src/tools/adapter.ts +124 -451
@@ -0,0 +1,111 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import type { Context } from 'hono';
4
+ import {
5
+ gitDeleteSchema,
6
+ gitRestoreSchema,
7
+ gitStageSchema,
8
+ gitUnstageSchema,
9
+ } from './schemas.ts';
10
+ import { validateAndGetGitRoot } from './utils.ts';
11
+
12
+ const execFileAsync = promisify(execFile);
13
+
14
+ type StagingAction = 'stage' | 'unstage' | 'restore' | 'delete';
15
+
16
+ const actionConfig: Record<
17
+ StagingAction,
18
+ {
19
+ schema: typeof gitStageSchema;
20
+ command: (files: string[]) => string[];
21
+ dataKey: 'staged' | 'unstaged' | 'restored' | 'deleted';
22
+ fallbackError: string;
23
+ }
24
+ > = {
25
+ stage: {
26
+ schema: gitStageSchema,
27
+ command: (files) => ['add', ...files],
28
+ dataKey: 'staged',
29
+ fallbackError: 'Failed to stage files',
30
+ },
31
+ unstage: {
32
+ schema: gitUnstageSchema,
33
+ command: (files) => ['reset', 'HEAD', '--', ...files],
34
+ dataKey: 'unstaged',
35
+ fallbackError: 'Failed to unstage files',
36
+ },
37
+ restore: {
38
+ schema: gitRestoreSchema,
39
+ command: (files) => ['restore', '--', ...files],
40
+ dataKey: 'restored',
41
+ fallbackError: 'Failed to restore files',
42
+ },
43
+ delete: {
44
+ schema: gitDeleteSchema,
45
+ command: (files) => ['clean', '-f', '--', ...files],
46
+ dataKey: 'deleted',
47
+ fallbackError: 'Failed to delete files',
48
+ },
49
+ };
50
+
51
+ async function handleStagingAction(c: Context, action: StagingAction) {
52
+ const config = actionConfig[action];
53
+ try {
54
+ const body = await c.req.json();
55
+ const { files, project } = config.schema.parse(body);
56
+ const requestedPath = project || process.cwd();
57
+
58
+ const validation = await validateAndGetGitRoot(requestedPath);
59
+ if ('error' in validation) {
60
+ return c.json(
61
+ { status: 'error', error: validation.error, code: validation.code },
62
+ 400,
63
+ );
64
+ }
65
+
66
+ if (files.length === 0) {
67
+ return c.json(
68
+ {
69
+ status: 'error',
70
+ error: 'No files specified',
71
+ },
72
+ 400,
73
+ );
74
+ }
75
+
76
+ await execFileAsync('git', config.command(files), {
77
+ cwd: validation.gitRoot,
78
+ });
79
+
80
+ return c.json({
81
+ status: 'ok',
82
+ data: {
83
+ [config.dataKey]: files,
84
+ },
85
+ });
86
+ } catch (error) {
87
+ return c.json(
88
+ {
89
+ status: 'error',
90
+ error: error instanceof Error ? error.message : config.fallbackError,
91
+ },
92
+ 500,
93
+ );
94
+ }
95
+ }
96
+
97
+ export function handleStageFiles(c: Context) {
98
+ return handleStagingAction(c, 'stage');
99
+ }
100
+
101
+ export function handleUnstageFiles(c: Context) {
102
+ return handleStagingAction(c, 'unstage');
103
+ }
104
+
105
+ export function handleRestoreFiles(c: Context) {
106
+ return handleStagingAction(c, 'restore');
107
+ }
108
+
109
+ export function handleDeleteFiles(c: Context) {
110
+ return handleStagingAction(c, 'delete');
111
+ }
@@ -1,16 +1,11 @@
1
1
  import type { Hono } from 'hono';
2
- import { execFile } from 'node:child_process';
3
- import { promisify } from 'node:util';
4
- import {
5
- gitStageSchema,
6
- gitUnstageSchema,
7
- gitRestoreSchema,
8
- gitDeleteSchema,
9
- } from './schemas.ts';
10
- import { validateAndGetGitRoot } from './utils.ts';
11
2
  import { openApiRoute } from '../../openapi/route.ts';
12
-
13
- const execFileAsync = promisify(execFile);
3
+ import {
4
+ handleDeleteFiles,
5
+ handleRestoreFiles,
6
+ handleStageFiles,
7
+ handleUnstageFiles,
8
+ } from './staging-service.ts';
14
9
 
15
10
  export function registerStagingRoutes(app: Hono) {
16
11
  openApiRoute(
@@ -104,52 +99,7 @@ export function registerStagingRoutes(app: Hono) {
104
99
  },
105
100
  },
106
101
  },
107
- async (c) => {
108
- try {
109
- const body = await c.req.json();
110
- const { files, project } = gitStageSchema.parse(body);
111
-
112
- const requestedPath = project || process.cwd();
113
-
114
- const validation = await validateAndGetGitRoot(requestedPath);
115
- if ('error' in validation) {
116
- return c.json(
117
- { status: 'error', error: validation.error, code: validation.code },
118
- 400,
119
- );
120
- }
121
-
122
- const { gitRoot } = validation;
123
-
124
- if (files.length === 0) {
125
- return c.json(
126
- {
127
- status: 'error',
128
- error: 'No files specified',
129
- },
130
- 400,
131
- );
132
- }
133
-
134
- await execFileAsync('git', ['add', ...files], { cwd: gitRoot });
135
-
136
- return c.json({
137
- status: 'ok',
138
- data: {
139
- staged: files,
140
- },
141
- });
142
- } catch (error) {
143
- return c.json(
144
- {
145
- status: 'error',
146
- error:
147
- error instanceof Error ? error.message : 'Failed to stage files',
148
- },
149
- 500,
150
- );
151
- }
152
- },
102
+ handleStageFiles,
153
103
  );
154
104
 
155
105
  openApiRoute(
@@ -243,56 +193,7 @@ export function registerStagingRoutes(app: Hono) {
243
193
  },
244
194
  },
245
195
  },
246
- async (c) => {
247
- try {
248
- const body = await c.req.json();
249
- const { files, project } = gitUnstageSchema.parse(body);
250
-
251
- const requestedPath = project || process.cwd();
252
-
253
- const validation = await validateAndGetGitRoot(requestedPath);
254
- if ('error' in validation) {
255
- return c.json(
256
- { status: 'error', error: validation.error, code: validation.code },
257
- 400,
258
- );
259
- }
260
-
261
- const { gitRoot } = validation;
262
-
263
- if (files.length === 0) {
264
- return c.json(
265
- {
266
- status: 'error',
267
- error: 'No files specified',
268
- },
269
- 400,
270
- );
271
- }
272
-
273
- await execFileAsync('git', ['reset', 'HEAD', '--', ...files], {
274
- cwd: gitRoot,
275
- });
276
-
277
- return c.json({
278
- status: 'ok',
279
- data: {
280
- unstaged: files,
281
- },
282
- });
283
- } catch (error) {
284
- return c.json(
285
- {
286
- status: 'error',
287
- error:
288
- error instanceof Error
289
- ? error.message
290
- : 'Failed to unstage files',
291
- },
292
- 500,
293
- );
294
- }
295
- },
196
+ handleUnstageFiles,
296
197
  );
297
198
 
298
199
  openApiRoute(
@@ -380,56 +281,7 @@ export function registerStagingRoutes(app: Hono) {
380
281
  },
381
282
  },
382
283
  },
383
- async (c) => {
384
- try {
385
- const body = await c.req.json();
386
- const { files, project } = gitRestoreSchema.parse(body);
387
-
388
- const requestedPath = project || process.cwd();
389
-
390
- const validation = await validateAndGetGitRoot(requestedPath);
391
- if ('error' in validation) {
392
- return c.json(
393
- { status: 'error', error: validation.error, code: validation.code },
394
- 400,
395
- );
396
- }
397
-
398
- const { gitRoot } = validation;
399
-
400
- if (files.length === 0) {
401
- return c.json(
402
- {
403
- status: 'error',
404
- error: 'No files specified',
405
- },
406
- 400,
407
- );
408
- }
409
-
410
- await execFileAsync('git', ['restore', '--', ...files], {
411
- cwd: gitRoot,
412
- });
413
-
414
- return c.json({
415
- status: 'ok',
416
- data: {
417
- restored: files,
418
- },
419
- });
420
- } catch (error) {
421
- return c.json(
422
- {
423
- status: 'error',
424
- error:
425
- error instanceof Error
426
- ? error.message
427
- : 'Failed to restore files',
428
- },
429
- 500,
430
- );
431
- }
432
- },
284
+ handleRestoreFiles,
433
285
  );
434
286
 
435
287
  openApiRoute(
@@ -517,53 +369,6 @@ export function registerStagingRoutes(app: Hono) {
517
369
  },
518
370
  },
519
371
  },
520
- async (c) => {
521
- try {
522
- const body = await c.req.json();
523
- const { files, project } = gitDeleteSchema.parse(body);
524
-
525
- const requestedPath = project || process.cwd();
526
-
527
- const validation = await validateAndGetGitRoot(requestedPath);
528
- if ('error' in validation) {
529
- return c.json(
530
- { status: 'error', error: validation.error, code: validation.code },
531
- 400,
532
- );
533
- }
534
-
535
- const { gitRoot } = validation;
536
-
537
- if (files.length === 0) {
538
- return c.json(
539
- {
540
- status: 'error',
541
- error: 'No files specified',
542
- },
543
- 400,
544
- );
545
- }
546
-
547
- await execFileAsync('git', ['clean', '-f', '--', ...files], {
548
- cwd: gitRoot,
549
- });
550
-
551
- return c.json({
552
- status: 'ok',
553
- data: {
554
- deleted: files,
555
- },
556
- });
557
- } catch (error) {
558
- return c.json(
559
- {
560
- status: 'error',
561
- error:
562
- error instanceof Error ? error.message : 'Failed to delete files',
563
- },
564
- 500,
565
- );
566
- }
567
- },
372
+ handleDeleteFiles,
568
373
  );
569
374
  }
@@ -0,0 +1,338 @@
1
+ import type { Hono } from 'hono';
2
+ import { openApiRoute } from '../../openapi/route.ts';
3
+ import {
4
+ completeMCPAuth,
5
+ getMCPAuthStatus,
6
+ initiateMCPAuth,
7
+ revokeMCPAuth,
8
+ } from './service.ts';
9
+ import { copilotMCPOAuthStore, copilotMCPSessions } from './state.ts';
10
+
11
+ export function registerMCPAuthRoutes(app: Hono) {
12
+ openApiRoute(
13
+ app,
14
+ {
15
+ method: 'post',
16
+ path: '/v1/mcp/servers/{name}/auth',
17
+ tags: ['mcp'],
18
+ operationId: 'initiateMCPAuth',
19
+ summary: 'Initiate auth for an MCP server',
20
+ parameters: [
21
+ {
22
+ in: 'path',
23
+ name: 'name',
24
+ required: true,
25
+ schema: {
26
+ type: 'string',
27
+ },
28
+ description: 'MCP server name',
29
+ },
30
+ ],
31
+ responses: {
32
+ '200': {
33
+ description: 'OK',
34
+ content: {
35
+ 'application/json': {
36
+ schema: {
37
+ type: 'object',
38
+ properties: {
39
+ ok: {
40
+ type: 'boolean',
41
+ },
42
+ name: {
43
+ type: 'string',
44
+ },
45
+ authUrl: {
46
+ type: 'string',
47
+ },
48
+ authType: {
49
+ type: 'string',
50
+ },
51
+ authenticated: {
52
+ type: 'boolean',
53
+ },
54
+ sessionId: {
55
+ type: 'string',
56
+ },
57
+ userCode: {
58
+ type: 'string',
59
+ },
60
+ verificationUri: {
61
+ type: 'string',
62
+ },
63
+ interval: {
64
+ type: 'integer',
65
+ },
66
+ message: {
67
+ type: 'string',
68
+ },
69
+ error: {
70
+ type: 'string',
71
+ },
72
+ },
73
+ required: ['ok'],
74
+ },
75
+ },
76
+ },
77
+ },
78
+ '404': {
79
+ description: 'Bad Request',
80
+ content: {
81
+ 'application/json': {
82
+ schema: {
83
+ type: 'object',
84
+ properties: {
85
+ error: {
86
+ type: 'string',
87
+ },
88
+ },
89
+ required: ['error'],
90
+ },
91
+ },
92
+ },
93
+ },
94
+ },
95
+ },
96
+ async (c) => {
97
+ const result = await initiateMCPAuth({
98
+ name: c.req.param('name'),
99
+ oAuthStore: copilotMCPOAuthStore,
100
+ sessions: copilotMCPSessions,
101
+ });
102
+ return result.ok
103
+ ? c.json(result.body)
104
+ : c.json(result.body, result.status);
105
+ },
106
+ );
107
+
108
+ openApiRoute(
109
+ app,
110
+ {
111
+ method: 'post',
112
+ path: '/v1/mcp/servers/{name}/auth/callback',
113
+ tags: ['mcp'],
114
+ operationId: 'completeMCPAuth',
115
+ summary: 'Complete MCP server auth callback',
116
+ parameters: [
117
+ {
118
+ in: 'path',
119
+ name: 'name',
120
+ required: true,
121
+ schema: {
122
+ type: 'string',
123
+ },
124
+ description: 'MCP server name',
125
+ },
126
+ ],
127
+ requestBody: {
128
+ required: true,
129
+ content: {
130
+ 'application/json': {
131
+ schema: {
132
+ type: 'object',
133
+ properties: {
134
+ code: {
135
+ type: 'string',
136
+ },
137
+ sessionId: {
138
+ type: 'string',
139
+ },
140
+ },
141
+ },
142
+ },
143
+ },
144
+ },
145
+ responses: {
146
+ '200': {
147
+ description: 'OK',
148
+ content: {
149
+ 'application/json': {
150
+ schema: {
151
+ type: 'object',
152
+ properties: {
153
+ ok: {
154
+ type: 'boolean',
155
+ },
156
+ status: {
157
+ type: 'string',
158
+ enum: ['complete', 'pending', 'error'],
159
+ },
160
+ name: {
161
+ type: 'string',
162
+ },
163
+ connected: {
164
+ type: 'boolean',
165
+ },
166
+ tools: {
167
+ type: 'array',
168
+ items: {
169
+ type: 'object',
170
+ properties: {
171
+ name: {
172
+ type: 'string',
173
+ },
174
+ description: {
175
+ type: 'string',
176
+ },
177
+ },
178
+ },
179
+ },
180
+ error: {
181
+ type: 'string',
182
+ },
183
+ },
184
+ required: ['ok'],
185
+ },
186
+ },
187
+ },
188
+ },
189
+ '400': {
190
+ description: 'Bad Request',
191
+ content: {
192
+ 'application/json': {
193
+ schema: {
194
+ type: 'object',
195
+ properties: {
196
+ error: {
197
+ type: 'string',
198
+ },
199
+ },
200
+ required: ['error'],
201
+ },
202
+ },
203
+ },
204
+ },
205
+ },
206
+ },
207
+ async (c) => {
208
+ const result = await completeMCPAuth({
209
+ name: c.req.param('name'),
210
+ body: await c.req.json(),
211
+ oAuthStore: copilotMCPOAuthStore,
212
+ sessions: copilotMCPSessions,
213
+ });
214
+ return result.ok
215
+ ? c.json(result.body)
216
+ : c.json(result.body, result.status);
217
+ },
218
+ );
219
+
220
+ openApiRoute(
221
+ app,
222
+ {
223
+ method: 'get',
224
+ path: '/v1/mcp/servers/{name}/auth/status',
225
+ tags: ['mcp'],
226
+ operationId: 'getMCPAuthStatus',
227
+ summary: 'Get auth status for an MCP server',
228
+ parameters: [
229
+ {
230
+ in: 'path',
231
+ name: 'name',
232
+ required: true,
233
+ schema: {
234
+ type: 'string',
235
+ },
236
+ description: 'MCP server name',
237
+ },
238
+ ],
239
+ responses: {
240
+ '200': {
241
+ description: 'OK',
242
+ content: {
243
+ 'application/json': {
244
+ schema: {
245
+ type: 'object',
246
+ properties: {
247
+ authenticated: {
248
+ type: 'boolean',
249
+ },
250
+ authType: {
251
+ type: 'string',
252
+ },
253
+ },
254
+ required: ['authenticated'],
255
+ },
256
+ },
257
+ },
258
+ },
259
+ },
260
+ },
261
+ async (c) => {
262
+ return c.json(
263
+ await getMCPAuthStatus({
264
+ name: c.req.param('name'),
265
+ oAuthStore: copilotMCPOAuthStore,
266
+ }),
267
+ );
268
+ },
269
+ );
270
+
271
+ openApiRoute(
272
+ app,
273
+ {
274
+ method: 'delete',
275
+ path: '/v1/mcp/servers/{name}/auth',
276
+ tags: ['mcp'],
277
+ operationId: 'revokeMCPAuth',
278
+ summary: 'Revoke auth for an MCP server',
279
+ parameters: [
280
+ {
281
+ in: 'path',
282
+ name: 'name',
283
+ required: true,
284
+ schema: {
285
+ type: 'string',
286
+ },
287
+ description: 'MCP server name',
288
+ },
289
+ ],
290
+ responses: {
291
+ '200': {
292
+ description: 'OK',
293
+ content: {
294
+ 'application/json': {
295
+ schema: {
296
+ type: 'object',
297
+ properties: {
298
+ ok: {
299
+ type: 'boolean',
300
+ },
301
+ error: {
302
+ type: 'string',
303
+ },
304
+ },
305
+ required: ['ok'],
306
+ },
307
+ },
308
+ },
309
+ },
310
+ '400': {
311
+ description: 'Bad Request',
312
+ content: {
313
+ 'application/json': {
314
+ schema: {
315
+ type: 'object',
316
+ properties: {
317
+ error: {
318
+ type: 'string',
319
+ },
320
+ },
321
+ required: ['error'],
322
+ },
323
+ },
324
+ },
325
+ },
326
+ },
327
+ },
328
+ async (c) => {
329
+ const result = await revokeMCPAuth({
330
+ name: c.req.param('name'),
331
+ oAuthStore: copilotMCPOAuthStore,
332
+ });
333
+ return result.ok
334
+ ? c.json(result.body)
335
+ : c.json(result.body, result.status);
336
+ },
337
+ );
338
+ }