@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,166 @@
1
+ import { messageParts, sessions } from '@ottocode/database/schema';
2
+ import { eq } from 'drizzle-orm';
3
+ import type { ToolAdapterContext } from '../../runtime/tools/context.ts';
4
+ import { publishToolResult, type ToolResultContent } from './events.ts';
5
+
6
+ export type ToolTiming = {
7
+ endTs: number;
8
+ durationMs: number | null;
9
+ };
10
+
11
+ export function computeToolTiming(startTs?: number): ToolTiming {
12
+ const endTs = Date.now();
13
+ return {
14
+ endTs,
15
+ durationMs:
16
+ typeof startTs === 'number' ? Math.max(0, endTs - startTs) : null,
17
+ };
18
+ }
19
+
20
+ export async function persistToolCall(
21
+ ctx: ToolAdapterContext,
22
+ args: {
23
+ partId: string;
24
+ name: string;
25
+ input: unknown;
26
+ callId: string;
27
+ startTs?: number;
28
+ stepIndex?: number;
29
+ },
30
+ ): Promise<void> {
31
+ const index = await ctx.nextIndex();
32
+ await ctx.db.insert(messageParts).values({
33
+ id: args.partId,
34
+ messageId: ctx.messageId,
35
+ index,
36
+ stepIndex: args.stepIndex,
37
+ type: 'tool_call',
38
+ content: JSON.stringify({
39
+ name: args.name,
40
+ args: args.input,
41
+ callId: args.callId,
42
+ }),
43
+ agent: ctx.agent,
44
+ provider: ctx.provider,
45
+ model: ctx.model,
46
+ startedAt: args.startTs,
47
+ toolName: args.name,
48
+ toolCallId: args.callId,
49
+ });
50
+ }
51
+
52
+ export async function persistToolResultWithIndex(
53
+ ctx: ToolAdapterContext,
54
+ args: {
55
+ partId: string;
56
+ index: number;
57
+ name: string;
58
+ content: ToolResultContent;
59
+ startTs?: number;
60
+ callId?: string;
61
+ stepIndex?: number;
62
+ endTs: number;
63
+ durationMs: number | null;
64
+ },
65
+ ): Promise<void> {
66
+ await ctx.db.insert(messageParts).values({
67
+ id: args.partId,
68
+ messageId: ctx.messageId,
69
+ index: args.index,
70
+ stepIndex: args.stepIndex,
71
+ type: 'tool_result',
72
+ content: JSON.stringify(args.content),
73
+ agent: ctx.agent,
74
+ provider: ctx.provider,
75
+ model: ctx.model,
76
+ startedAt: args.startTs,
77
+ completedAt: args.endTs,
78
+ toolName: args.name,
79
+ toolCallId: args.callId,
80
+ toolDurationMs: args.durationMs ?? undefined,
81
+ });
82
+ }
83
+
84
+ export async function persistToolResult(
85
+ ctx: ToolAdapterContext,
86
+ args: {
87
+ partId: string;
88
+ name: string;
89
+ content: ToolResultContent;
90
+ startTs?: number;
91
+ callId?: string;
92
+ stepIndex?: number;
93
+ endTs: number;
94
+ durationMs: number | null;
95
+ },
96
+ ): Promise<void> {
97
+ const index = await ctx.nextIndex();
98
+ await persistToolResultWithIndex(ctx, { ...args, index });
99
+ }
100
+
101
+ export async function persistToolErrorResult(
102
+ ctx: ToolAdapterContext,
103
+ args: {
104
+ name: string;
105
+ errorResult: unknown;
106
+ callId?: string;
107
+ startTs?: number;
108
+ stepIndexForEvent?: number;
109
+ input?: unknown;
110
+ },
111
+ ): Promise<void> {
112
+ const resultPartId = crypto.randomUUID();
113
+ const { endTs, durationMs } = computeToolTiming(args.startTs);
114
+ const effectiveStepIndex = args.stepIndexForEvent ?? ctx.stepIndex;
115
+ const content: ToolResultContent = {
116
+ name: args.name,
117
+ result: args.errorResult,
118
+ callId: args.callId,
119
+ };
120
+
121
+ if (args.input !== undefined) {
122
+ content.args = args.input;
123
+ }
124
+
125
+ await persistToolResult(ctx, {
126
+ partId: resultPartId,
127
+ name: args.name,
128
+ content,
129
+ startTs: args.startTs,
130
+ callId: args.callId,
131
+ stepIndex: effectiveStepIndex,
132
+ endTs,
133
+ durationMs,
134
+ });
135
+ publishToolResult(ctx, content, effectiveStepIndex);
136
+ }
137
+
138
+ export async function updateToolSessionStats(
139
+ ctx: ToolAdapterContext,
140
+ args: { name: string; durationMs: number | null; endTs: number },
141
+ ): Promise<void> {
142
+ try {
143
+ const sessRows = await ctx.db
144
+ .select()
145
+ .from(sessions)
146
+ .where(eq(sessions.id, ctx.sessionId));
147
+ if (sessRows.length) {
148
+ const row = sessRows[0] as typeof sessions.$inferSelect;
149
+ const totalToolTimeMs =
150
+ Number(row.totalToolTimeMs || 0) + (args.durationMs ?? 0);
151
+ let counts: Record<string, number> = {};
152
+ try {
153
+ counts = row.toolCountsJson ? JSON.parse(row.toolCountsJson) : {};
154
+ } catch {}
155
+ counts[args.name] = (counts[args.name] || 0) + 1;
156
+ await ctx.db
157
+ .update(sessions)
158
+ .set({
159
+ totalToolTimeMs,
160
+ toolCountsJson: JSON.stringify(counts),
161
+ lastActiveAt: args.endTs,
162
+ })
163
+ .where(eq(sessions.id, ctx.sessionId));
164
+ }
165
+ } catch {}
166
+ }
@@ -0,0 +1,97 @@
1
+ import type { ToolResultContent } from './events.ts';
2
+
3
+ export type ToolFailureState = {
4
+ active: boolean;
5
+ toolName?: string;
6
+ };
7
+
8
+ export function createBlockedToolResult(reason: string | undefined): {
9
+ ok: false;
10
+ error: string;
11
+ details: { reason: 'safety_guard' };
12
+ } {
13
+ return {
14
+ ok: false,
15
+ error: `Blocked: ${reason}`,
16
+ details: { reason: 'safety_guard' },
17
+ };
18
+ }
19
+
20
+ export function createRejectedToolResult(): {
21
+ ok: false;
22
+ error: string;
23
+ details: { reason: 'user_rejected' };
24
+ } {
25
+ return {
26
+ ok: false,
27
+ error: 'Tool execution rejected by user',
28
+ details: { reason: 'user_rejected' },
29
+ };
30
+ }
31
+
32
+ export function createToolExceptionResult(error: unknown): unknown {
33
+ if (error && typeof error === 'object' && 'ok' in error) return error;
34
+ const errorMessage = error instanceof Error ? error.message : String(error);
35
+ const errorStack = error instanceof Error ? error.stack : undefined;
36
+ return {
37
+ ok: false,
38
+ error: errorMessage,
39
+ stack: errorStack,
40
+ };
41
+ }
42
+
43
+ export function buildToolResultContent(args: {
44
+ name: string;
45
+ result: unknown;
46
+ callId?: string;
47
+ input?: unknown;
48
+ }): ToolResultContent {
49
+ const content: ToolResultContent = {
50
+ name: args.name,
51
+ result: args.result,
52
+ callId: args.callId,
53
+ };
54
+
55
+ if (args.input !== undefined) {
56
+ content.args = args.input;
57
+ }
58
+
59
+ if (
60
+ args.result &&
61
+ typeof args.result === 'object' &&
62
+ 'artifact' in args.result
63
+ ) {
64
+ try {
65
+ const maybeArtifact = (args.result as { artifact?: unknown }).artifact;
66
+ if (maybeArtifact !== undefined) {
67
+ content.artifact = maybeArtifact;
68
+ }
69
+ } catch {}
70
+ }
71
+
72
+ return content;
73
+ }
74
+
75
+ export function markToolFailed(
76
+ stepState: { failed: boolean; failedToolName?: string },
77
+ failureState: ToolFailureState,
78
+ name: string,
79
+ ): void {
80
+ stepState.failed = true;
81
+ stepState.failedToolName = name;
82
+ failureState.active = true;
83
+ failureState.toolName = name;
84
+ }
85
+
86
+ export function markToolSucceeded(
87
+ stepState: { failed: boolean; failedToolName?: string },
88
+ failureState: ToolFailureState,
89
+ name: string,
90
+ ): void {
91
+ stepState.failed = false;
92
+ stepState.failedToolName = undefined;
93
+ if (failureState.active && failureState.toolName === name) {
94
+ failureState.active = false;
95
+ failureState.toolName = undefined;
96
+ }
97
+ }