@ottocode/server 0.1.233 → 0.1.235

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.233",
3
+ "version": "0.1.235",
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/sdk": "0.1.233",
53
- "@ottocode/database": "0.1.233",
52
+ "@ottocode/sdk": "0.1.235",
53
+ "@ottocode/database": "0.1.235",
54
54
  "drizzle-orm": "^0.44.5",
55
55
  "hono": "^4.9.9",
56
56
  "zod": "^4.3.6"
@@ -83,11 +83,7 @@ export async function discoverAllAgents(
83
83
  agentSet.add(agentName);
84
84
  }
85
85
  }
86
- } catch (err) {
87
- logger.debug('Failed to load agents.json', {
88
- error: err instanceof Error ? err.message : String(err),
89
- });
90
- }
86
+ } catch {}
91
87
 
92
88
  try {
93
89
  const localAgentsPath = join(projectRoot, '.otto', 'agents');
@@ -100,11 +96,7 @@ export async function discoverAllAgents(
100
96
  }
101
97
  }
102
98
  }
103
- } catch (err) {
104
- logger.debug('Failed to read local agents directory', {
105
- error: err instanceof Error ? err.message : String(err),
106
- });
107
- }
99
+ } catch {}
108
100
 
109
101
  try {
110
102
  const globalAgentsPath = getGlobalAgentsDir();
@@ -117,11 +109,7 @@ export async function discoverAllAgents(
117
109
  }
118
110
  }
119
111
  }
120
- } catch (err) {
121
- logger.debug('Failed to read global agents directory', {
122
- error: err instanceof Error ? err.message : String(err),
123
- });
124
- }
112
+ } catch {}
125
113
 
126
114
  return Array.from(agentSet).sort();
127
115
  }
@@ -10,7 +10,6 @@ import { sessions } from '@ottocode/database/schema';
10
10
  import { gitCommitSchema, gitGenerateCommitMessageSchema } from './schemas.ts';
11
11
  import { validateAndGetGitRoot, parseGitStatus } from './utils.ts';
12
12
  import { resolveModel } from '../../runtime/provider/index.ts';
13
- import { debugLog } from '../../runtime/debug/index.ts';
14
13
  import {
15
14
  detectOAuth,
16
15
  adaptSimpleCall,
@@ -168,7 +167,6 @@ Commit message:`;
168
167
  });
169
168
 
170
169
  if (adapted.forceStream) {
171
- debugLog('[COMMIT] Using streamText for OpenAI OAuth');
172
170
  const result = streamText({
173
171
  model,
174
172
  system: adapted.system,
@@ -180,7 +178,6 @@ Commit message:`;
180
178
  text += chunk;
181
179
  }
182
180
  const message = text.trim();
183
- debugLog(`[COMMIT] OAuth result: "${message.slice(0, 80)}..."`);
184
181
  return c.json({ status: 'ok', data: { message } });
185
182
  }
186
183
 
@@ -18,9 +18,7 @@ export function registerTerminalsRoutes(
18
18
 
19
19
  app.post('/v1/terminals', async (c) => {
20
20
  try {
21
- logger.debug('POST /v1/terminals called');
22
21
  const body = await c.req.json();
23
- logger.debug('Creating terminal request received', body);
24
22
  const { command, args, purpose, cwd, title } = body;
25
23
 
26
24
  if (!command || !purpose) {
@@ -36,13 +34,6 @@ export function registerTerminalsRoutes(
36
34
  }
37
35
  const resolvedCwd = cwd || process.cwd();
38
36
 
39
- logger.debug('Creating terminal', {
40
- command: resolvedCommand,
41
- args,
42
- purpose,
43
- cwd: resolvedCwd,
44
- });
45
-
46
37
  const terminal = terminalManager.create({
47
38
  command: resolvedCommand,
48
39
  args: args || [],
@@ -52,8 +43,6 @@ export function registerTerminalsRoutes(
52
43
  title,
53
44
  });
54
45
 
55
- logger.debug('Terminal created successfully', { id: terminal.id });
56
-
57
46
  return c.json({
58
47
  terminalId: terminal.id,
59
48
  pid: terminal.pid,
@@ -80,25 +69,18 @@ export function registerTerminalsRoutes(
80
69
 
81
70
  const handleTerminalOutput = async (c: Context) => {
82
71
  const id = c.req.param('id');
83
- logger.debug('SSE client connecting to terminal', { id });
84
72
  const terminal = terminalManager.get(id);
85
73
 
86
74
  if (!terminal) {
87
- logger.debug('SSE terminal not found', { id });
88
75
  return c.json({ error: 'Terminal not found' }, 404);
89
76
  }
90
77
 
91
78
  const activeTerminal = terminal;
92
79
 
93
80
  return streamSSE(c, async (stream) => {
94
- logger.debug('SSE stream started for terminal', { id });
95
81
  const skipHistory = c.req.query('skipHistory') === 'true';
96
82
  if (!skipHistory) {
97
83
  const history = activeTerminal.read();
98
- logger.debug('SSE sending terminal history', {
99
- id,
100
- lines: history.length,
101
- });
102
84
  for (const line of history) {
103
85
  await stream.write(
104
86
  `data: ${JSON.stringify({ type: 'data', line })}\n\n`,
@@ -155,9 +137,6 @@ export function registerTerminalsRoutes(
155
137
  }
156
138
 
157
139
  function onAbort() {
158
- logger.debug('SSE client disconnected from terminal', {
159
- id: activeTerminal.id,
160
- });
161
140
  stream.close();
162
141
  finish();
163
142
  }
@@ -47,8 +47,6 @@ export function registerTunnelRoutes(app: Hono) {
47
47
  port = getServerPort() || 9100;
48
48
  }
49
49
 
50
- logger.debug('Starting tunnel on port:', port);
51
-
52
50
  // Kill any stale tunnel processes first
53
51
  await killStaleTunnels();
54
52
 
@@ -60,7 +58,6 @@ export function registerTunnelRoutes(app: Hono) {
60
58
 
61
59
  const url = await activeTunnel.start(port, (msg) => {
62
60
  progressMessage = msg;
63
- logger.debug('Tunnel progress', { message: msg });
64
61
  });
65
62
 
66
63
  tunnelUrl = url;
@@ -109,8 +106,6 @@ export function registerTunnelRoutes(app: Hono) {
109
106
  tunnelError = null;
110
107
  progressMessage = null;
111
108
 
112
- logger.debug('External tunnel registered:', url);
113
-
114
109
  return c.json({
115
110
  ok: true,
116
111
  url: tunnelUrl,
@@ -1,5 +1,4 @@
1
1
  import type { Tool } from 'ai';
2
- import { debugLog } from '../debug/index.ts';
3
2
 
4
3
  export interface MCPPrepareStepState {
5
4
  mcpToolsRecord: Record<string, Tool>;
@@ -57,12 +56,7 @@ export function buildPrepareStep(state: MCPPrepareStepState) {
57
56
  }
58
57
 
59
58
  const activeTools = [...state.baseToolNames, ...state.loadedMCPTools];
60
-
61
- if (state.loadedMCPTools.size > 0) {
62
- debugLog(
63
- `[MCP prepareStep] step=${stepNumber}, active MCP tools: ${[...state.loadedMCPTools].join(', ')}`,
64
- );
65
- }
59
+ void stepNumber;
66
60
 
67
61
  return { activeTools };
68
62
  };
@@ -1,5 +1,4 @@
1
1
  import { getGlobalAgentsJsonPath, getGlobalAgentsDir } from '@ottocode/sdk';
2
- import { debugLog } from '../debug/index.ts';
3
2
  import type { ProviderName } from '@ottocode/sdk';
4
3
  import { catalog } from '@ottocode/sdk';
5
4
  // Embed default agent prompts; only user overrides read from disk.
@@ -334,13 +333,7 @@ export async function resolveAgentConfig(
334
333
  const deduped = Array.from(new Set([...tools, ...baseToolSet]));
335
334
  const provider = normalizeProvider(entry?.provider);
336
335
  const model = normalizeModel(entry?.model);
337
- debugLog(`[agent] ${name} prompt source: ${promptSource}`);
338
- debugLog(
339
- `[agent] ${name} prompt summary: ${JSON.stringify({
340
- length: prompt.length,
341
- lines: prompt.split('\n').length,
342
- })}`,
343
- );
336
+ void promptSource;
344
337
  return {
345
338
  name,
346
339
  prompt,
@@ -11,7 +11,7 @@ import { discoverProjectTools } from '@ottocode/sdk';
11
11
  import type { Tool } from 'ai';
12
12
  import { adaptTools } from '../../tools/adapter.ts';
13
13
  import { buildDatabaseTools } from '../../tools/database/index.ts';
14
- import { debugLog, time } from '../debug/index.ts';
14
+ import { time } from '../debug/index.ts';
15
15
  import { isDevtoolsEnabled } from '../debug/state.ts';
16
16
  import { buildHistoryMessages } from '../message/history-builder.ts';
17
17
  import { getMaxOutputTokens } from '../utils/token.ts';
@@ -87,7 +87,6 @@ export async function setupRunner(opts: RunOpts): Promise<SetupResult> {
87
87
  const historyTimer = time('runner:buildHistory');
88
88
  let history: Awaited<ReturnType<typeof buildHistoryMessages>>;
89
89
  if (opts.isCompactCommand && opts.compactionContext) {
90
- debugLog('[RUNNER] Using minimal history for /compact command');
91
90
  history = [];
92
91
  } else {
93
92
  history = await buildHistoryMessages(
@@ -104,34 +103,14 @@ export async function setupRunner(opts: RunOpts): Promise<SetupResult> {
104
103
  .where(eq(sessions.id, opts.sessionId))
105
104
  .limit(1);
106
105
  const contextSummary = sessionRows[0]?.contextSummary ?? undefined;
107
- if (contextSummary) {
108
- debugLog(
109
- `[RUNNER] Using context summary from compaction (${contextSummary.length} chars)`,
110
- );
111
- }
112
106
 
113
107
  const isFirstMessage = !history.some((m) => m.role === 'assistant');
114
108
 
115
- debugLog(`[RUNNER] isFirstMessage: ${isFirstMessage}`);
116
- debugLog(`[RUNNER] userContext provided: ${opts.userContext ? 'YES' : 'NO'}`);
117
- if (opts.userContext) {
118
- debugLog(
119
- `[RUNNER] userContext value: ${opts.userContext.substring(0, 100)}${opts.userContext.length > 100 ? '...' : ''}`,
120
- );
121
- }
122
-
123
109
  const systemTimer = time('runner:composeSystemPrompt');
124
110
  const { getAuth } = await import('@ottocode/sdk');
125
111
  const auth = await getAuth(opts.provider, cfg.projectRoot);
126
112
  const oauth = detectOAuth(opts.provider, auth);
127
113
 
128
- debugLog(
129
- `[RUNNER] needsSpoof (OAuth): ${oauth.needsSpoof}, isOpenAIOAuth: ${oauth.isOpenAIOAuth}`,
130
- );
131
- debugLog(
132
- `[RUNNER] spoofPrompt: ${oauth.spoofPrompt ? `present (${opts.provider})` : 'none'}`,
133
- );
134
-
135
114
  const composed = await composeSystemPrompt({
136
115
  provider: opts.provider,
137
116
  model: opts.model,
@@ -155,15 +134,8 @@ export async function setupRunner(opts: RunOpts): Promise<SetupResult> {
155
134
  const { system } = adapted;
156
135
  const { systemComponents, additionalSystemMessages } = adapted;
157
136
  systemTimer.end();
158
- debugLog(
159
- `[system] summary: ${JSON.stringify({
160
- components: systemComponents,
161
- length: system.length,
162
- })}`,
163
- );
164
137
 
165
138
  if (opts.isCompactCommand && opts.compactionContext) {
166
- debugLog('[RUNNER] Injecting compaction context for /compact command');
167
139
  const compactPrompt = getCompactionSystemPrompt();
168
140
  additionalSystemMessages.push({
169
141
  role: 'system',
@@ -188,9 +160,6 @@ export async function setupRunner(opts: RunOpts): Promise<SetupResult> {
188
160
  for (const dt of dbTools) {
189
161
  discovered.tools.push(dt);
190
162
  }
191
- debugLog(
192
- `[tools] Added ${dbTools.length} database tools for research agent (parent: ${parentSessionId ?? 'none'})`,
193
- );
194
163
  }
195
164
 
196
165
  toolsTimer.end({
@@ -200,12 +169,6 @@ export async function setupRunner(opts: RunOpts): Promise<SetupResult> {
200
169
  const gated = allTools.filter(
201
170
  (tool) => allowedNames.has(tool.name) || tool.name === 'load_mcp_tools',
202
171
  );
203
- debugLog(
204
- `[tools] ${gated.length} gated tools, ${Object.keys(mcpToolsRecord).length} lazy MCP tools`,
205
- );
206
-
207
- debugLog(`[RUNNER] About to create model with provider: ${opts.provider}`);
208
- debugLog(`[RUNNER] About to create model ID: ${opts.model}`);
209
172
 
210
173
  const model = await resolveModel(opts.provider, opts.model, cfg, {
211
174
  sessionId: opts.sessionId,
@@ -218,12 +181,8 @@ export async function setupRunner(opts: RunOpts): Promise<SetupResult> {
218
181
  middleware: devToolsMiddleware(),
219
182
  })
220
183
  : model;
221
- debugLog(
222
- `[RUNNER] Model created: ${JSON.stringify({ id: model.modelId, provider: model.provider })}`,
223
- );
224
184
 
225
185
  const maxOutputTokens = adapted.maxOutputTokens;
226
- debugLog(`[RUNNER] maxOutputTokens for ${opts.model}: ${maxOutputTokens}`);
227
186
 
228
187
  const { sharedCtx, firstToolTimer, firstToolSeen } = await setupToolContext(
229
188
  opts,
@@ -253,12 +212,6 @@ export async function setupRunner(opts: RunOpts): Promise<SetupResult> {
253
212
  });
254
213
  mergeProviderOptions(providerOptions, reasoningConfig.providerOptions);
255
214
  effectiveMaxOutputTokens = reasoningConfig.effectiveMaxOutputTokens;
256
- debugLog(
257
- `[RUNNER] reasoning enabled for ${opts.provider}/${opts.model}: ${reasoningConfig.enabled}, level: ${opts.reasoningLevel ?? 'default'}`,
258
- );
259
- debugLog(
260
- `[RUNNER] final providerOptions: ${JSON.stringify(providerOptions)}`,
261
- );
262
215
 
263
216
  return {
264
217
  cfg,
@@ -1,12 +1,11 @@
1
- import { hasToolCall, stepCountIs, streamText } from 'ai';
2
- import { messages, messageParts, sessions } from '@ottocode/database/schema';
1
+ import { hasToolCall, streamText } from 'ai';
2
+ import { messageParts } from '@ottocode/database/schema';
3
3
  import { eq } from 'drizzle-orm';
4
4
  import { publish, subscribe } from '../../events/bus.ts';
5
- import { debugLog, time } from '../debug/index.ts';
5
+ import { time } from '../debug/index.ts';
6
6
  import { toErrorPayload } from '../errors/handling.ts';
7
7
  import {
8
8
  type RunOpts,
9
- enqueueAssistantRun,
10
9
  setRunning,
11
10
  dequeueJob,
12
11
  cleanupSession,
@@ -41,7 +40,6 @@ import {
41
40
  createOauthCodexTextGuardState,
42
41
  consumeOauthCodexTextDelta,
43
42
  } from '../stream/text-guard.ts';
44
- import { decideOauthCodexContinuation } from './oauth-codex-continuation.ts';
45
43
  import { createTurnDumpCollector } from '../debug/turn-dump.ts';
46
44
 
47
45
  export {
@@ -56,17 +54,9 @@ export {
56
54
  const DEFAULT_TRACED_TOOL_INPUTS = new Set(['write', 'apply_patch']);
57
55
 
58
56
  function shouldTraceToolInput(name: string): boolean {
59
- const raw = process.env.OTTO_DEBUG_TOOL_INPUT?.trim();
60
- if (!raw) return false;
61
- const normalized = raw.toLowerCase();
62
- if (['1', 'true', 'yes', 'on', 'all'].includes(normalized)) {
63
- return DEFAULT_TRACED_TOOL_INPUTS.has(name);
64
- }
65
- const tokens = raw
66
- .split(/[\s,]+/)
67
- .map((token) => token.trim().toLowerCase())
68
- .filter(Boolean);
69
- return tokens.includes('all') || tokens.includes(name.toLowerCase());
57
+ void DEFAULT_TRACED_TOOL_INPUTS;
58
+ void name;
59
+ return false;
70
60
  }
71
61
 
72
62
  function summarizeTraceValue(value: unknown, max = 160): string {
@@ -89,11 +79,7 @@ export async function runSessionLoop(sessionId: string) {
89
79
 
90
80
  try {
91
81
  await runAssistant(job);
92
- } catch (_err) {
93
- debugLog(
94
- `[RUNNER] runAssistant threw (swallowed to keep loop alive): ${_err instanceof Error ? _err.message : String(_err)}`,
95
- );
96
- }
82
+ } catch {}
97
83
  }
98
84
 
99
85
  setRunning(sessionId, false);
@@ -101,12 +87,6 @@ export async function runSessionLoop(sessionId: string) {
101
87
  }
102
88
 
103
89
  async function runAssistant(opts: RunOpts) {
104
- const separator = '='.repeat(72);
105
- debugLog(separator);
106
- debugLog(
107
- `[RUNNER] Starting turn for session ${opts.sessionId}, message ${opts.assistantMessageId}`,
108
- );
109
-
110
90
  const setup = await setupRunner(opts);
111
91
  const {
112
92
  cfg,
@@ -203,10 +183,6 @@ async function runAssistant(opts: RunOpts) {
203
183
  }
204
184
  }
205
185
 
206
- debugLog(
207
- `[RUNNER] messagesWithSystemInstructions length: ${messagesWithSystemInstructions.length}`,
208
- );
209
-
210
186
  const dump = createTurnDumpCollector({
211
187
  sessionId: opts.sessionId,
212
188
  messageId: opts.assistantMessageId,
@@ -282,11 +258,7 @@ async function runAssistant(opts: RunOpts) {
282
258
  try {
283
259
  const name = (evt.payload as { name?: string } | undefined)?.name;
284
260
  if (name === 'finish') _finishObserved = true;
285
- } catch (err) {
286
- debugLog(
287
- `[RUNNER] finish observer error: ${err instanceof Error ? err.message : String(err)}`,
288
- );
289
- }
261
+ } catch {}
290
262
  }
291
263
  });
292
264
 
@@ -364,10 +336,9 @@ async function runAssistant(opts: RunOpts) {
364
336
  const onFinish = createFinishHandler(opts, db, completeAssistantMessage);
365
337
  const isCopilotResponsesApi =
366
338
  opts.provider === 'copilot' && !opts.model.startsWith('gpt-5-mini');
367
- const stopWhenCondition =
368
- isOpenAIOAuth || isCopilotResponsesApi
369
- ? stepCountIs(20)
370
- : hasToolCall('finish');
339
+ const stopWhenCondition = isCopilotResponsesApi
340
+ ? undefined
341
+ : hasToolCall('finish');
371
342
 
372
343
  try {
373
344
  const result = streamText({
@@ -401,29 +372,19 @@ async function runAssistant(opts: RunOpts) {
401
372
  if (part.type === 'tool-input-start') {
402
373
  if (shouldTraceToolInput(part.toolName)) {
403
374
  tracedToolInputNamesById.set(part.id, part.toolName);
404
- debugLog(
405
- `[TOOL_INPUT_TRACE][runner] fullStream tool-input-start tool=${part.toolName} callId=${part.id}`,
406
- );
407
375
  }
408
376
  continue;
409
377
  }
410
378
 
411
379
  if (part.type === 'tool-input-delta') {
412
380
  const toolName = tracedToolInputNamesById.get(part.id);
413
- if (toolName) {
414
- debugLog(
415
- `[TOOL_INPUT_TRACE][runner] fullStream tool-input-delta tool=${toolName} callId=${part.id} delta=${summarizeTraceValue(part.delta)}`,
416
- );
417
- }
381
+ if (toolName) void summarizeTraceValue(part.delta);
418
382
  continue;
419
383
  }
420
384
 
421
385
  if (part.type === 'tool-input-end') {
422
386
  const toolName = tracedToolInputNamesById.get(part.id);
423
387
  if (toolName) {
424
- debugLog(
425
- `[TOOL_INPUT_TRACE][runner] fullStream tool-input-end tool=${toolName} callId=${part.id}`,
426
- );
427
388
  tracedToolInputNamesById.delete(part.id);
428
389
  }
429
390
  continue;
@@ -432,18 +393,14 @@ async function runAssistant(opts: RunOpts) {
432
393
  if (part.type === 'tool-call') {
433
394
  if (shouldTraceToolInput(part.toolName)) {
434
395
  tracedToolInputNamesById.delete(part.toolCallId);
435
- debugLog(
436
- `[TOOL_INPUT_TRACE][runner] fullStream tool-call tool=${part.toolName} callId=${part.toolCallId} input=${summarizeTraceValue(part.input)}`,
437
- );
396
+ void summarizeTraceValue(part.input);
438
397
  }
439
398
  continue;
440
399
  }
441
400
 
442
401
  if (part.type === 'tool-result') {
443
402
  if (shouldTraceToolInput(part.toolName)) {
444
- debugLog(
445
- `[TOOL_INPUT_TRACE][runner] fullStream tool-result tool=${part.toolName} callId=${part.toolCallId} output=${summarizeTraceValue(part.output)}`,
446
- );
403
+ void summarizeTraceValue(part.output);
447
404
  }
448
405
  continue;
449
406
  }
@@ -550,11 +507,6 @@ async function runAssistant(opts: RunOpts) {
550
507
  }
551
508
 
552
509
  const fs = firstToolSeen();
553
- if (oauthTextGuard?.dropped) {
554
- debugLog(
555
- '[RUNNER] Dropped pseudo tool-call text leaked by OpenAI OAuth stream',
556
- );
557
- }
558
510
  if (!fs && !_finishObserved) {
559
511
  publish({
560
512
  type: 'finish-step',
@@ -581,10 +533,6 @@ async function runAssistant(opts: RunOpts) {
581
533
  streamRawFinishReason = undefined;
582
534
  }
583
535
 
584
- debugLog(
585
- `[RUNNER] Stream finished. finishSeen=${_finishObserved}, firstToolSeen=${fs}, trailingAssistantTextAfterTool=${_trailingAssistantTextAfterTool}, finishReason=${streamFinishReason}, rawFinishReason=${streamRawFinishReason}`,
586
- );
587
-
588
536
  if (dump) {
589
537
  const finalTextSnapshot = latestAssistantText || accumulated;
590
538
  if (finalTextSnapshot.length > 0) {
@@ -601,98 +549,6 @@ async function runAssistant(opts: RunOpts) {
601
549
  aborted: _abortedByUser,
602
550
  });
603
551
  }
604
-
605
- const MAX_CONTINUATIONS = 6;
606
- const continuationCount = opts.continuationCount ?? 0;
607
- const continuationDecision = decideOauthCodexContinuation({
608
- provider: opts.provider,
609
- isOpenAIOAuth,
610
- finishObserved: _finishObserved,
611
- abortedByUser: _abortedByUser,
612
- continuationCount,
613
- maxContinuations: MAX_CONTINUATIONS,
614
- finishReason: streamFinishReason,
615
- rawFinishReason: streamRawFinishReason,
616
- firstToolSeen: fs,
617
- hasTrailingAssistantText: _trailingAssistantTextAfterTool,
618
- endedWithToolActivity: _endedWithToolActivity,
619
- lastToolName: _lastToolName,
620
- droppedPseudoToolText: oauthTextGuard?.dropped ?? false,
621
- lastAssistantText: latestAssistantText,
622
- });
623
-
624
- if (continuationDecision.shouldContinue) {
625
- const sessRows = await db
626
- .select()
627
- .from(sessions)
628
- .where(eq(sessions.id, opts.sessionId))
629
- .limit(1);
630
- const sessionInputTokens = Number(sessRows[0]?.totalInputTokens ?? 0);
631
- const MAX_SESSION_INPUT_TOKENS = 800_000;
632
- if (sessionInputTokens > MAX_SESSION_INPUT_TOKENS) {
633
- debugLog(
634
- `[RUNNER] Token budget exceeded (${sessionInputTokens} > ${MAX_SESSION_INPUT_TOKENS}), stopping continuation.`,
635
- );
636
- } else {
637
- debugLog(
638
- `[RUNNER] WARNING: Stream ended without finish. reason=${continuationDecision.reason ?? 'unknown'}, finishReason=${streamFinishReason}, rawFinishReason=${streamRawFinishReason}, firstToolSeen=${fs}. Auto-continuing.`,
639
- );
640
-
641
- debugLog(
642
- `[RUNNER] Auto-continuing (${continuationCount + 1}/${MAX_CONTINUATIONS})...`,
643
- );
644
-
645
- try {
646
- await completeAssistantMessage({}, opts, db);
647
- } catch (err) {
648
- debugLog(
649
- `[RUNNER] completeAssistantMessage failed before continuation: ${err instanceof Error ? err.message : String(err)}`,
650
- );
651
- }
652
-
653
- const continuationMessageId = crypto.randomUUID();
654
- await db.insert(messages).values({
655
- id: continuationMessageId,
656
- sessionId: opts.sessionId,
657
- role: 'assistant',
658
- status: 'pending',
659
- agent: opts.agent,
660
- provider: opts.provider,
661
- model: opts.model,
662
- createdAt: Date.now(),
663
- });
664
-
665
- publish({
666
- type: 'message.created',
667
- sessionId: opts.sessionId,
668
- payload: {
669
- id: continuationMessageId,
670
- role: 'assistant',
671
- agent: opts.agent,
672
- provider: opts.provider,
673
- model: opts.model,
674
- },
675
- });
676
-
677
- enqueueAssistantRun(
678
- {
679
- ...opts,
680
- assistantMessageId: continuationMessageId,
681
- continuationCount: continuationCount + 1,
682
- },
683
- runSessionLoop,
684
- );
685
- return;
686
- }
687
- }
688
- if (
689
- continuationDecision.reason === 'max-continuations-reached' &&
690
- !_finishObserved
691
- ) {
692
- debugLog(
693
- `[RUNNER] Max continuations (${MAX_CONTINUATIONS}) reached, stopping.`,
694
- );
695
- }
696
552
  } catch (err) {
697
553
  unsubscribeFinish();
698
554
  dump?.recordError(err);
@@ -715,17 +571,10 @@ async function runAssistant(opts: RunOpts) {
715
571
  errorCode === 'context_length_exceeded' ||
716
572
  apiErrorType === 'invalid_request_error';
717
573
 
718
- debugLog(
719
- `[RUNNER] isPromptTooLong: ${isPromptTooLong}, isCompactCommand: ${opts.isCompactCommand}`,
720
- );
721
-
722
574
  if (isPromptTooLong && !opts.isCompactCommand) {
723
- debugLog('[RUNNER] Prompt too long - auto-compacting');
724
575
  try {
725
576
  const pruneResult = await pruneSession(db, opts.sessionId);
726
- debugLog(
727
- `[RUNNER] Auto-pruned ${pruneResult.pruned} parts, saved ~${pruneResult.saved} tokens`,
728
- );
577
+ void pruneResult;
729
578
 
730
579
  publish({
731
580
  type: 'error',
@@ -739,20 +588,10 @@ async function runAssistant(opts: RunOpts) {
739
588
 
740
589
  try {
741
590
  await completeAssistantMessage({}, opts, db);
742
- } catch (err2) {
743
- debugLog(
744
- `[RUNNER] completeAssistantMessage failed after prune: ${err2 instanceof Error ? err2.message : String(err2)}`,
745
- );
746
- }
591
+ } catch {}
747
592
  return;
748
- } catch (pruneErr) {
749
- debugLog(
750
- `[RUNNER] Auto-prune failed: ${pruneErr instanceof Error ? pruneErr.message : String(pruneErr)}`,
751
- );
752
- }
593
+ } catch {}
753
594
  }
754
-
755
- debugLog(`[RUNNER] Error during stream: ${payload.message}`);
756
595
  publish({
757
596
  type: 'error',
758
597
  sessionId: opts.sessionId,
@@ -773,26 +612,13 @@ async function runAssistant(opts: RunOpts) {
773
612
  db,
774
613
  );
775
614
  await completeAssistantMessage({}, opts, db);
776
- } catch (err2) {
777
- debugLog(
778
- `[RUNNER] Failed to complete message after error: ${err2 instanceof Error ? err2.message : String(err2)}`,
779
- );
780
- }
615
+ } catch {}
781
616
  throw err;
782
617
  } finally {
783
618
  if (dump) {
784
619
  try {
785
- const dumpPath = await dump.flush(cfg.projectRoot);
786
- debugLog(`[RUNNER] Debug dump written to ${dumpPath}`);
787
- } catch (dumpErr) {
788
- debugLog(
789
- `[RUNNER] Failed to write debug dump: ${dumpErr instanceof Error ? dumpErr.message : String(dumpErr)}`,
790
- );
791
- }
620
+ await dump.flush(cfg.projectRoot);
621
+ } catch {}
792
622
  }
793
- debugLog(
794
- `[RUNNER] Turn complete for session ${opts.sessionId}, message ${opts.assistantMessageId}`,
795
- );
796
- debugLog(separator);
797
623
  }
798
624
  }