@openbuilder/cli 0.50.43 → 0.50.46
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/dist/chunks/{Banner-C-FTiOIR.js → Banner-BKC6yG6z.js} +2 -2
- package/dist/chunks/Banner-BKC6yG6z.js.map +1 -0
- package/dist/chunks/auto-update-Dq2PFvjt.js +1 -0
- package/dist/chunks/auto-update-Dq2PFvjt.js.map +1 -0
- package/dist/chunks/build-D0qYqIq0.js +1 -0
- package/dist/chunks/build-D0qYqIq0.js.map +1 -0
- package/dist/chunks/cleanup-qVTsA3tk.js +1 -0
- package/dist/chunks/cleanup-qVTsA3tk.js.map +1 -0
- package/dist/chunks/{cli-auth-ChCnxlFl.js → cli-auth-BgiGSBOt.js} +4 -3
- package/dist/chunks/cli-auth-BgiGSBOt.js.map +1 -0
- package/dist/chunks/cli-error-BjQwvWtK.js +1 -0
- package/dist/chunks/cli-error-BjQwvWtK.js.map +1 -0
- package/dist/chunks/config-BGP1jZJ4.js +1 -0
- package/dist/chunks/config-BGP1jZJ4.js.map +1 -0
- package/dist/chunks/config-manager-BkbjtN-H.js +1 -0
- package/dist/chunks/config-manager-BkbjtN-H.js.map +1 -0
- package/dist/chunks/database-BvAbD4sP.js +1 -0
- package/dist/chunks/database-BvAbD4sP.js.map +1 -0
- package/dist/chunks/database-setup-BYjIRAmT.js +1 -0
- package/dist/chunks/database-setup-BYjIRAmT.js.map +1 -0
- package/dist/chunks/devtools-7A3EXJhY.js +75 -0
- package/dist/chunks/devtools-7A3EXJhY.js.map +1 -0
- package/dist/chunks/index-ZNRLfdj5.js +119 -0
- package/dist/chunks/index-ZNRLfdj5.js.map +1 -0
- package/dist/chunks/{init-DNyPS_SR.js → init-IQRjA1g3.js} +8 -9
- package/dist/chunks/init-IQRjA1g3.js.map +1 -0
- package/dist/chunks/{init-tui-EFMXj-MG.js → init-tui-B4jfmo3U.js} +7 -8
- package/dist/chunks/init-tui-B4jfmo3U.js.map +1 -0
- package/dist/chunks/logger-ZpJi7chw.js +1 -0
- package/dist/chunks/logger-ZpJi7chw.js.map +1 -0
- package/dist/chunks/{login-BhtodVsj.js → login-CrIcDJpS.js} +2 -1
- package/dist/chunks/login-CrIcDJpS.js.map +1 -0
- package/dist/chunks/{logout-CDDASeuQ.js → logout-BxgiczmY.js} +2 -1
- package/dist/chunks/logout-BxgiczmY.js.map +1 -0
- package/dist/chunks/{main-tui-D-SG-Ba5.js → main-tui-NPDVPKol.js} +9 -10
- package/dist/chunks/main-tui-NPDVPKol.js.map +1 -0
- package/dist/chunks/manager-CvGX9qqe.js +1 -0
- package/dist/chunks/manager-CvGX9qqe.js.map +1 -0
- package/dist/chunks/{port-allocator-B0q7xkLs.js → port-allocator-DuAZe2_S.js} +3 -36
- package/dist/chunks/port-allocator-DuAZe2_S.js.map +1 -0
- package/dist/chunks/process-killer-CaUL7Kpl.js +1 -0
- package/dist/chunks/process-killer-CaUL7Kpl.js.map +1 -0
- package/dist/chunks/prompts-1QbE_bRr.js +1 -0
- package/dist/chunks/prompts-1QbE_bRr.js.map +1 -0
- package/dist/chunks/repo-cloner-CpOQjFSo.js +1 -0
- package/dist/chunks/repo-cloner-CpOQjFSo.js.map +1 -0
- package/dist/chunks/repo-detector-B_oj696o.js +1 -0
- package/dist/chunks/repo-detector-B_oj696o.js.map +1 -0
- package/dist/chunks/{run-Cor14S0I.js → run-Yh3YjeLl.js} +17 -36
- package/dist/chunks/run-Yh3YjeLl.js.map +1 -0
- package/dist/chunks/runner-logger-instance-nDWv2h2T.js +1 -0
- package/dist/chunks/runner-logger-instance-nDWv2h2T.js.map +1 -0
- package/dist/chunks/spinner-BJL9zWAJ.js +1 -0
- package/dist/chunks/spinner-BJL9zWAJ.js.map +1 -0
- package/dist/chunks/{start-k9iGDVWo.js → start-B-brfyVy.js} +7 -7
- package/dist/chunks/start-B-brfyVy.js.map +1 -0
- package/dist/chunks/start-traditional-uoLZXdxm.js +1 -0
- package/dist/chunks/start-traditional-uoLZXdxm.js.map +1 -0
- package/dist/chunks/status-cS8YwtUx.js +1 -0
- package/dist/chunks/status-cS8YwtUx.js.map +1 -0
- package/dist/chunks/{vendor-react-CXgiD1Dl.js → theme-DOjeB8BU.js} +50 -225
- package/dist/chunks/theme-DOjeB8BU.js.map +1 -0
- package/dist/chunks/upgrade-CKjl4HlB.js +1 -0
- package/dist/chunks/upgrade-CKjl4HlB.js.map +1 -0
- package/dist/chunks/use-app-DozfqdJj.js +10 -0
- package/dist/chunks/use-app-DozfqdJj.js.map +1 -0
- package/dist/chunks/{useBuildState-DscLOZLl.js → useBuildState-DV6wurQ2.js} +2 -2
- package/dist/chunks/useBuildState-DV6wurQ2.js.map +1 -0
- package/dist/cli/index.js +8 -7
- package/dist/cli/index.js.map +1 -0
- package/dist/index.js +109 -700
- package/dist/index.js.map +1 -0
- package/dist/instrument.js +8 -81
- package/dist/instrument.js.map +1 -0
- package/package.json +2 -11
- package/dist/chunks/theme-DhorI2Hb.js +0 -43
- package/dist/chunks/vendor-ai-sdk-CSJ0bw9X.js +0 -1970
- package/dist/chunks/vendor-sentry-CqA9P3UG.js +0 -71910
- package/scripts/install-vendor-deps.js +0 -34
- package/scripts/install-vendor.js +0 -167
- package/scripts/prepare-release.js +0 -83
- package/vendor/ai-sdk-provider-claude-code-LOCAL.tgz +0 -0
- package/vendor/sentry-core-LOCAL.tgz +0 -0
- package/vendor/sentry-nextjs-LOCAL.tgz +0 -0
- package/vendor/sentry-node-LOCAL.tgz +0 -0
- package/vendor/sentry-node-core-LOCAL.tgz +0 -0
package/dist/index.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
// OpenBuilder CLI - Built with Rollup
|
|
2
|
+
import * as Sentry from '@sentry/node';
|
|
2
3
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
3
4
|
import { Codex } from '@openai/codex-sdk';
|
|
4
5
|
import { a as streamLog, f as fileLog, i as initRunnerLogger, s as setFileLoggerTuiMode, b as getLogger } from './chunks/runner-logger-instance-nDWv2h2T.js';
|
|
5
6
|
import { config as config$1 } from 'dotenv';
|
|
6
|
-
import
|
|
7
|
+
import path$1, { resolve, relative, isAbsolute, dirname, join as join$1 } from 'node:path';
|
|
7
8
|
import { fileURLToPath } from 'node:url';
|
|
8
|
-
import { generateText, streamText } from 'ai';
|
|
9
|
-
import { c as claudeCode } from './chunks/vendor-ai-sdk-CSJ0bw9X.js';
|
|
10
9
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
11
10
|
import { readFile } from 'fs/promises';
|
|
12
11
|
import * as path from 'path';
|
|
@@ -19,8 +18,7 @@ import { sql, eq, and, desc, isNull } from 'drizzle-orm';
|
|
|
19
18
|
import { randomUUID, createHash } from 'crypto';
|
|
20
19
|
import { migrate } from 'drizzle-orm/node-postgres/migrator';
|
|
21
20
|
import { z } from 'zod';
|
|
22
|
-
import
|
|
23
|
-
import os__default from 'node:os';
|
|
21
|
+
import os$1 from 'node:os';
|
|
24
22
|
import { randomUUID as randomUUID$1 } from 'node:crypto';
|
|
25
23
|
import express from 'express';
|
|
26
24
|
import { spawn } from 'node:child_process';
|
|
@@ -32,33 +30,6 @@ import * as os from 'os';
|
|
|
32
30
|
import { existsSync as existsSync$1, mkdirSync as mkdirSync$1 } from 'fs';
|
|
33
31
|
import { tunnelManager } from './chunks/manager-CvGX9qqe.js';
|
|
34
32
|
import 'chalk';
|
|
35
|
-
import 'zod/v4';
|
|
36
|
-
import 'zod/v3';
|
|
37
|
-
import 'jsonc-parser';
|
|
38
|
-
import 'url';
|
|
39
|
-
import 'tty';
|
|
40
|
-
import 'util';
|
|
41
|
-
import 'worker_threads';
|
|
42
|
-
import 'process';
|
|
43
|
-
import 'node:module';
|
|
44
|
-
import 'async_hooks';
|
|
45
|
-
import 'diagnostics_channel';
|
|
46
|
-
import './chunks/vendor-react-CXgiD1Dl.js';
|
|
47
|
-
import 'module';
|
|
48
|
-
import 'events';
|
|
49
|
-
import 'assert';
|
|
50
|
-
import 'react-devtools-core';
|
|
51
|
-
import 'node:stream';
|
|
52
|
-
import 'node:process';
|
|
53
|
-
import 'node:buffer';
|
|
54
|
-
import 'node:diagnostics_channel';
|
|
55
|
-
import 'node:util';
|
|
56
|
-
import 'node:readline';
|
|
57
|
-
import 'node:worker_threads';
|
|
58
|
-
import 'node:http';
|
|
59
|
-
import 'node:https';
|
|
60
|
-
import 'node:zlib';
|
|
61
|
-
import 'node:tls';
|
|
62
33
|
import 'http';
|
|
63
34
|
import 'http-proxy';
|
|
64
35
|
import 'zlib';
|
|
@@ -2196,7 +2167,7 @@ var BuildLogger$1 = class BuildLogger {
|
|
|
2196
2167
|
if (typeof process !== "undefined" && process.env.NODE_ENV !== "test") {
|
|
2197
2168
|
try {
|
|
2198
2169
|
if (level === "warn" || level === "error") {
|
|
2199
|
-
addBreadcrumb({
|
|
2170
|
+
Sentry.addBreadcrumb({
|
|
2200
2171
|
category: `build-logger.${context}`,
|
|
2201
2172
|
message,
|
|
2202
2173
|
level: level === "error" ? "error" : "warning",
|
|
@@ -3668,7 +3639,7 @@ var BuildWebSocketServer = class {
|
|
|
3668
3639
|
pingInterval,
|
|
3669
3640
|
userId: runnerUserId
|
|
3670
3641
|
});
|
|
3671
|
-
addBreadcrumb({
|
|
3642
|
+
Sentry.addBreadcrumb({
|
|
3672
3643
|
category: "websocket",
|
|
3673
3644
|
message: `Runner connected: ${runnerId}`,
|
|
3674
3645
|
level: "info"
|
|
@@ -3702,7 +3673,7 @@ var BuildWebSocketServer = class {
|
|
|
3702
3673
|
}
|
|
3703
3674
|
} catch (error) {
|
|
3704
3675
|
this.runnerTotalErrors++;
|
|
3705
|
-
captureException(error, {
|
|
3676
|
+
Sentry.captureException(error, {
|
|
3706
3677
|
tags: { runnerId, source: "websocket_message" },
|
|
3707
3678
|
level: "error"
|
|
3708
3679
|
});
|
|
@@ -3719,7 +3690,7 @@ var BuildWebSocketServer = class {
|
|
|
3719
3690
|
httpProxyManager.cancelRequestsForRunner(runnerId);
|
|
3720
3691
|
hmrProxyManager$1.disconnectRunner(runnerId);
|
|
3721
3692
|
this.cleanupRunnerProcesses(runnerId);
|
|
3722
|
-
addBreadcrumb({
|
|
3693
|
+
Sentry.addBreadcrumb({
|
|
3723
3694
|
category: "websocket",
|
|
3724
3695
|
message: `Runner disconnected: ${runnerId}`,
|
|
3725
3696
|
level: "info",
|
|
@@ -3729,7 +3700,7 @@ var BuildWebSocketServer = class {
|
|
|
3729
3700
|
ws.on("error", (error) => {
|
|
3730
3701
|
buildLogger$2.websocket.error("Runner socket error", error, { runnerId });
|
|
3731
3702
|
this.runnerTotalErrors++;
|
|
3732
|
-
captureException(error, {
|
|
3703
|
+
Sentry.captureException(error, {
|
|
3733
3704
|
tags: { runnerId, source: "websocket_error" },
|
|
3734
3705
|
level: "error"
|
|
3735
3706
|
});
|
|
@@ -3770,10 +3741,10 @@ var BuildWebSocketServer = class {
|
|
|
3770
3741
|
return false;
|
|
3771
3742
|
}
|
|
3772
3743
|
try {
|
|
3773
|
-
const activeSpan = getActiveSpan();
|
|
3744
|
+
const activeSpan = Sentry.getActiveSpan();
|
|
3774
3745
|
const hasTrace = !!activeSpan;
|
|
3775
3746
|
if (activeSpan) {
|
|
3776
|
-
const traceData = getTraceData();
|
|
3747
|
+
const traceData = Sentry.getTraceData();
|
|
3777
3748
|
if (traceData["sentry-trace"]) {
|
|
3778
3749
|
command._sentry = {
|
|
3779
3750
|
trace: traceData["sentry-trace"],
|
|
@@ -3790,7 +3761,7 @@ var BuildWebSocketServer = class {
|
|
|
3790
3761
|
return true;
|
|
3791
3762
|
} catch (error) {
|
|
3792
3763
|
this.runnerTotalErrors++;
|
|
3793
|
-
captureException(error, {
|
|
3764
|
+
Sentry.captureException(error, {
|
|
3794
3765
|
tags: { runnerId, commandType: command.type },
|
|
3795
3766
|
level: "error"
|
|
3796
3767
|
});
|
|
@@ -3856,7 +3827,7 @@ var BuildWebSocketServer = class {
|
|
|
3856
3827
|
for (const [runnerId, conn] of this.runnerConnections.entries()) {
|
|
3857
3828
|
if (now - conn.lastHeartbeat > this.RUNNER_HEARTBEAT_TIMEOUT) {
|
|
3858
3829
|
buildLogger$2.websocket.runnerStaleRemoved(runnerId);
|
|
3859
|
-
addBreadcrumb({
|
|
3830
|
+
Sentry.addBreadcrumb({
|
|
3860
3831
|
category: "websocket",
|
|
3861
3832
|
message: `Stale runner connection removed: ${runnerId}`,
|
|
3862
3833
|
level: "warning",
|
|
@@ -3899,7 +3870,7 @@ var BuildWebSocketServer = class {
|
|
|
3899
3870
|
runnerId,
|
|
3900
3871
|
projectIds
|
|
3901
3872
|
});
|
|
3902
|
-
addBreadcrumb({
|
|
3873
|
+
Sentry.addBreadcrumb({
|
|
3903
3874
|
category: "websocket",
|
|
3904
3875
|
message: `Cleaned up processes for disconnected runner`,
|
|
3905
3876
|
level: "info",
|
|
@@ -3914,7 +3885,7 @@ var BuildWebSocketServer = class {
|
|
|
3914
3885
|
}
|
|
3915
3886
|
} catch (error) {
|
|
3916
3887
|
buildLogger$2.websocket.error("Failed to cleanup runner processes", error, { runnerId });
|
|
3917
|
-
captureException(error, {
|
|
3888
|
+
Sentry.captureException(error, {
|
|
3918
3889
|
tags: { runnerId, source: "runner_cleanup" },
|
|
3919
3890
|
level: "error"
|
|
3920
3891
|
});
|
|
@@ -4065,10 +4036,10 @@ var BuildWebSocketServer = class {
|
|
|
4065
4036
|
updates: []
|
|
4066
4037
|
});
|
|
4067
4038
|
}
|
|
4068
|
-
const activeSpan = getActiveSpan();
|
|
4039
|
+
const activeSpan = Sentry.getActiveSpan();
|
|
4069
4040
|
const traceContext = activeSpan ? {
|
|
4070
|
-
trace: getTraceData()["sentry-trace"],
|
|
4071
|
-
baggage: getTraceData().baggage
|
|
4041
|
+
trace: Sentry.getTraceData()["sentry-trace"],
|
|
4042
|
+
baggage: Sentry.getTraceData().baggage
|
|
4072
4043
|
} : void 0;
|
|
4073
4044
|
const batch = this.pendingUpdates.get(key);
|
|
4074
4045
|
batch.updates.push({
|
|
@@ -4100,10 +4071,10 @@ var BuildWebSocketServer = class {
|
|
|
4100
4071
|
updates: []
|
|
4101
4072
|
});
|
|
4102
4073
|
}
|
|
4103
|
-
const activeSpan = getActiveSpan();
|
|
4074
|
+
const activeSpan = Sentry.getActiveSpan();
|
|
4104
4075
|
const traceContext = activeSpan ? {
|
|
4105
|
-
trace: getTraceData()["sentry-trace"],
|
|
4106
|
-
baggage: getTraceData().baggage
|
|
4076
|
+
trace: Sentry.getTraceData()["sentry-trace"],
|
|
4077
|
+
baggage: Sentry.getTraceData().baggage
|
|
4107
4078
|
} : void 0;
|
|
4108
4079
|
const batch = this.pendingUpdates.get(key);
|
|
4109
4080
|
batch.updates.push({
|
|
@@ -4592,9 +4563,9 @@ var AgentCore = /*#__PURE__*/Object.freeze({
|
|
|
4592
4563
|
* - Direct streaming without adaptation layer
|
|
4593
4564
|
*/
|
|
4594
4565
|
// Debug logging helper - suppressed in TUI mode (SILENT_MODE=1)
|
|
4595
|
-
const debugLog$
|
|
4566
|
+
const debugLog$3 = (message) => {
|
|
4596
4567
|
if (process.env.SILENT_MODE !== '1' && process.env.DEBUG_BUILD === '1') {
|
|
4597
|
-
debugLog$
|
|
4568
|
+
debugLog$3();
|
|
4598
4569
|
}
|
|
4599
4570
|
};
|
|
4600
4571
|
/**
|
|
@@ -4713,10 +4684,10 @@ function buildPromptWithImages(prompt, messageParts) {
|
|
|
4713
4684
|
*/
|
|
4714
4685
|
function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortController) {
|
|
4715
4686
|
return async function* nativeClaudeQuery(prompt, workingDirectory, systemPrompt, _agent, _codexThreadId, messageParts) {
|
|
4716
|
-
debugLog$
|
|
4717
|
-
debugLog$
|
|
4718
|
-
debugLog$
|
|
4719
|
-
debugLog$
|
|
4687
|
+
debugLog$3();
|
|
4688
|
+
debugLog$3();
|
|
4689
|
+
debugLog$3();
|
|
4690
|
+
debugLog$3(`[runner] [native-sdk] Prompt length: ${prompt.length}\n`);
|
|
4720
4691
|
// Build combined system prompt
|
|
4721
4692
|
const systemPromptSegments = [CLAUDE_SYSTEM_PROMPT.trim()];
|
|
4722
4693
|
if (systemPrompt && systemPrompt.trim().length > 0) {
|
|
@@ -4732,7 +4703,7 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
|
|
|
4732
4703
|
const hasImages = messageParts?.some(p => p.type === 'image');
|
|
4733
4704
|
if (hasImages) {
|
|
4734
4705
|
messageParts?.filter(p => p.type === 'image').length || 0;
|
|
4735
|
-
debugLog$
|
|
4706
|
+
debugLog$3();
|
|
4736
4707
|
}
|
|
4737
4708
|
// Build the final prompt
|
|
4738
4709
|
const finalPrompt = buildPromptWithImages(prompt);
|
|
@@ -4766,7 +4737,7 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
|
|
|
4766
4737
|
// See: https://github.com/anthropics/claude-agent-sdk-typescript/issues/46
|
|
4767
4738
|
abortController,
|
|
4768
4739
|
};
|
|
4769
|
-
debugLog$
|
|
4740
|
+
debugLog$3();
|
|
4770
4741
|
let messageCount = 0;
|
|
4771
4742
|
let toolCallCount = 0;
|
|
4772
4743
|
let textBlockCount = 0;
|
|
@@ -4783,7 +4754,7 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
|
|
|
4783
4754
|
for (const block of transformed.message.content) {
|
|
4784
4755
|
if (block.type === 'tool_use') {
|
|
4785
4756
|
toolCallCount++;
|
|
4786
|
-
debugLog$
|
|
4757
|
+
debugLog$3(`[runner] [native-sdk] 🔧 Tool call: ${block.name}\n`);
|
|
4787
4758
|
}
|
|
4788
4759
|
else if (block.type === 'text') {
|
|
4789
4760
|
textBlockCount++;
|
|
@@ -4795,29 +4766,22 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
|
|
|
4795
4766
|
// Log result messages
|
|
4796
4767
|
if (sdkMessage.type === 'result') {
|
|
4797
4768
|
if (sdkMessage.subtype === 'success') {
|
|
4798
|
-
debugLog$
|
|
4769
|
+
debugLog$3(`[runner] [native-sdk] ✅ Query complete - ${sdkMessage.num_turns} turns, $${sdkMessage.total_cost_usd?.toFixed(4)} USD\n`);
|
|
4799
4770
|
}
|
|
4800
4771
|
else {
|
|
4801
|
-
debugLog$
|
|
4772
|
+
debugLog$3(`[runner] [native-sdk] ⚠️ Query ended with: ${sdkMessage.subtype}\n`);
|
|
4802
4773
|
}
|
|
4803
4774
|
}
|
|
4804
4775
|
}
|
|
4805
|
-
debugLog$
|
|
4776
|
+
debugLog$3(`[runner] [native-sdk] 📊 Stream complete - ${messageCount} messages, ${toolCallCount} tool calls, ${textBlockCount} text blocks\n`);
|
|
4806
4777
|
}
|
|
4807
4778
|
catch (error) {
|
|
4808
|
-
debugLog$
|
|
4809
|
-
captureException(error);
|
|
4779
|
+
debugLog$3(`[runner] [native-sdk] ❌ Error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
4780
|
+
Sentry.captureException(error);
|
|
4810
4781
|
throw error;
|
|
4811
4782
|
}
|
|
4812
4783
|
};
|
|
4813
4784
|
}
|
|
4814
|
-
/**
|
|
4815
|
-
* Feature flag to control which implementation to use
|
|
4816
|
-
*
|
|
4817
|
-
* Default: Native SDK is enabled (true)
|
|
4818
|
-
* Set USE_LEGACY_AI_SDK=1 to use the old AI SDK + community provider path
|
|
4819
|
-
*/
|
|
4820
|
-
const USE_NATIVE_SDK = process.env.USE_LEGACY_AI_SDK !== '1';
|
|
4821
4785
|
|
|
4822
4786
|
/**
|
|
4823
4787
|
* OpenCode SDK Integration
|
|
@@ -4832,7 +4796,7 @@ const USE_NATIVE_SDK = process.env.USE_LEGACY_AI_SDK !== '1';
|
|
|
4832
4796
|
* - Runner receives events and transforms them to SSE format for the frontend
|
|
4833
4797
|
*/
|
|
4834
4798
|
// Debug logging helper
|
|
4835
|
-
const debugLog$
|
|
4799
|
+
const debugLog$2 = (message) => {
|
|
4836
4800
|
if (process.env.SILENT_MODE !== '1' && process.env.DEBUG_BUILD === '1') {
|
|
4837
4801
|
console.error(message);
|
|
4838
4802
|
}
|
|
@@ -4997,10 +4961,10 @@ function parseSSEEvent(data) {
|
|
|
4997
4961
|
*/
|
|
4998
4962
|
function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
4999
4963
|
return async function* openCodeQuery(prompt, workingDirectory, systemPrompt, _agent, _codexThreadId, messageParts) {
|
|
5000
|
-
debugLog$
|
|
5001
|
-
debugLog$
|
|
5002
|
-
debugLog$
|
|
5003
|
-
debugLog$
|
|
4964
|
+
debugLog$2('[runner] [opencode-sdk] Starting OpenCode query');
|
|
4965
|
+
debugLog$2(`[runner] [opencode-sdk] Model: ${modelId}`);
|
|
4966
|
+
debugLog$2(`[runner] [opencode-sdk] Working dir: ${workingDirectory}`);
|
|
4967
|
+
debugLog$2(`[runner] [opencode-sdk] Prompt length: ${prompt.length}`);
|
|
5004
4968
|
// Ensure working directory exists
|
|
5005
4969
|
if (!existsSync(workingDirectory)) {
|
|
5006
4970
|
console.log(`[opencode-sdk] Creating working directory: ${workingDirectory}`);
|
|
@@ -5026,7 +4990,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
|
5026
4990
|
let sessionId = null;
|
|
5027
4991
|
// Start Sentry AI agent span for the entire OpenCode query
|
|
5028
4992
|
// This provides visibility into AI operations in Sentry's trace view
|
|
5029
|
-
const aiSpan = startInactiveSpan({
|
|
4993
|
+
const aiSpan = Sentry.startInactiveSpan({
|
|
5030
4994
|
name: 'opencode.query',
|
|
5031
4995
|
op: 'ai.pipeline',
|
|
5032
4996
|
attributes: {
|
|
@@ -5040,7 +5004,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
|
5040
5004
|
});
|
|
5041
5005
|
try {
|
|
5042
5006
|
// Step 1: Create a session
|
|
5043
|
-
debugLog$
|
|
5007
|
+
debugLog$2('[runner] [opencode-sdk] Creating session...');
|
|
5044
5008
|
const sessionResponse = await fetch(`${baseUrl}/session`, {
|
|
5045
5009
|
method: 'POST',
|
|
5046
5010
|
headers,
|
|
@@ -5054,13 +5018,13 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
|
5054
5018
|
}
|
|
5055
5019
|
const session = await sessionResponse.json();
|
|
5056
5020
|
sessionId = session.id;
|
|
5057
|
-
debugLog$
|
|
5021
|
+
debugLog$2(`[runner] [opencode-sdk] Session created: ${sessionId}`);
|
|
5058
5022
|
// Update span with session info
|
|
5059
5023
|
if (sessionId) {
|
|
5060
5024
|
aiSpan?.setAttribute('opencode.session_id', sessionId);
|
|
5061
5025
|
}
|
|
5062
5026
|
// Step 2: Subscribe to events
|
|
5063
|
-
debugLog$
|
|
5027
|
+
debugLog$2('[runner] [opencode-sdk] Subscribing to events...');
|
|
5064
5028
|
const eventResponse = await fetch(`${baseUrl}/event`, {
|
|
5065
5029
|
headers: {
|
|
5066
5030
|
...headers,
|
|
@@ -5081,7 +5045,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
|
5081
5045
|
image: part.image,
|
|
5082
5046
|
mimeType: part.mimeType || 'image/png',
|
|
5083
5047
|
});
|
|
5084
|
-
debugLog$
|
|
5048
|
+
debugLog$2('[runner] [opencode-sdk] Added image part');
|
|
5085
5049
|
}
|
|
5086
5050
|
}
|
|
5087
5051
|
}
|
|
@@ -5091,7 +5055,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
|
5091
5055
|
text: prompt,
|
|
5092
5056
|
});
|
|
5093
5057
|
// Step 4: Send the prompt (don't await - we'll stream the response)
|
|
5094
|
-
debugLog$
|
|
5058
|
+
debugLog$2('[runner] [opencode-sdk] Sending prompt...');
|
|
5095
5059
|
const promptPromise = fetch(`${baseUrl}/session/${sessionId}/message`, {
|
|
5096
5060
|
method: 'POST',
|
|
5097
5061
|
headers,
|
|
@@ -5115,7 +5079,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
|
5115
5079
|
while (!completed) {
|
|
5116
5080
|
const { done, value } = await reader.read();
|
|
5117
5081
|
if (done) {
|
|
5118
|
-
debugLog$
|
|
5082
|
+
debugLog$2('[runner] [opencode-sdk] Event stream ended');
|
|
5119
5083
|
break;
|
|
5120
5084
|
}
|
|
5121
5085
|
buffer += decoder.decode(value, { stream: true });
|
|
@@ -5183,15 +5147,15 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
|
5183
5147
|
subtype: 'success',
|
|
5184
5148
|
};
|
|
5185
5149
|
}
|
|
5186
|
-
debugLog$
|
|
5150
|
+
debugLog$2('[runner] [opencode-sdk] Query complete');
|
|
5187
5151
|
// Update span with final metrics
|
|
5188
5152
|
aiSpan?.setAttribute('opencode.tool_calls', toolCallCount);
|
|
5189
5153
|
aiSpan?.setAttribute('opencode.messages', messageCount);
|
|
5190
5154
|
aiSpan?.setStatus({ code: 1 }); // OK status
|
|
5191
5155
|
}
|
|
5192
5156
|
catch (error) {
|
|
5193
|
-
debugLog$
|
|
5194
|
-
captureException(error);
|
|
5157
|
+
debugLog$2(`[runner] [opencode-sdk] Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
5158
|
+
Sentry.captureException(error);
|
|
5195
5159
|
// Mark span as errored
|
|
5196
5160
|
aiSpan?.setStatus({ code: 2, message: error instanceof Error ? error.message : String(error) });
|
|
5197
5161
|
// Yield error result
|
|
@@ -5218,141 +5182,6 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
|
5218
5182
|
*/
|
|
5219
5183
|
const USE_OPENCODE_SDK = process.env.USE_OPENCODE_SDK === '1' && !!process.env.OPENCODE_URL;
|
|
5220
5184
|
|
|
5221
|
-
// src/lib/claude/tools.ts
|
|
5222
|
-
var genericInput = z.any();
|
|
5223
|
-
var genericObject = z.record(z.string(), z.any());
|
|
5224
|
-
var dynamicMcpTool = {
|
|
5225
|
-
description: "Generic MCP tool passthrough",
|
|
5226
|
-
type: "dynamic",
|
|
5227
|
-
inputSchema: genericObject
|
|
5228
|
-
};
|
|
5229
|
-
var fallbackTool = {
|
|
5230
|
-
description: "Fallback Claude CLI tool",
|
|
5231
|
-
inputSchema: genericInput
|
|
5232
|
-
};
|
|
5233
|
-
var builtinTools = {
|
|
5234
|
-
Agent: {
|
|
5235
|
-
description: "Launches a nested Claude agent",
|
|
5236
|
-
inputSchema: genericObject
|
|
5237
|
-
},
|
|
5238
|
-
Bash: {
|
|
5239
|
-
description: "Execute shell commands via Claude CLI",
|
|
5240
|
-
inputSchema: genericObject
|
|
5241
|
-
},
|
|
5242
|
-
BashOutput: {
|
|
5243
|
-
description: "Fetch output from a background bash process",
|
|
5244
|
-
inputSchema: genericObject
|
|
5245
|
-
},
|
|
5246
|
-
ExitPlanMode: {
|
|
5247
|
-
description: "Exit plan/approval mode with a summary",
|
|
5248
|
-
inputSchema: genericObject
|
|
5249
|
-
},
|
|
5250
|
-
Read: {
|
|
5251
|
-
description: "Read file contents",
|
|
5252
|
-
inputSchema: genericObject
|
|
5253
|
-
},
|
|
5254
|
-
Write: {
|
|
5255
|
-
description: "Write entire file contents",
|
|
5256
|
-
inputSchema: genericObject
|
|
5257
|
-
},
|
|
5258
|
-
Edit: {
|
|
5259
|
-
description: "Edit part of a file by replacing text",
|
|
5260
|
-
inputSchema: genericObject
|
|
5261
|
-
},
|
|
5262
|
-
Glob: {
|
|
5263
|
-
description: "Match files using glob patterns",
|
|
5264
|
-
inputSchema: genericObject
|
|
5265
|
-
},
|
|
5266
|
-
Grep: {
|
|
5267
|
-
description: "Search files for a regex pattern",
|
|
5268
|
-
inputSchema: genericObject
|
|
5269
|
-
},
|
|
5270
|
-
KillShell: {
|
|
5271
|
-
description: "Stop a running bash session",
|
|
5272
|
-
inputSchema: genericObject
|
|
5273
|
-
},
|
|
5274
|
-
ListMcpResources: {
|
|
5275
|
-
description: "Enumerate MCP resources",
|
|
5276
|
-
inputSchema: genericObject
|
|
5277
|
-
},
|
|
5278
|
-
Mcp: {
|
|
5279
|
-
description: "Invoke an MCP tool",
|
|
5280
|
-
inputSchema: genericObject
|
|
5281
|
-
},
|
|
5282
|
-
NotebookEdit: {
|
|
5283
|
-
description: "Edit Jupyter notebooks",
|
|
5284
|
-
inputSchema: genericObject
|
|
5285
|
-
},
|
|
5286
|
-
ReadMcpResource: {
|
|
5287
|
-
description: "Read a particular MCP resource",
|
|
5288
|
-
inputSchema: genericObject
|
|
5289
|
-
},
|
|
5290
|
-
TimeMachine: {
|
|
5291
|
-
description: "Rewind conversation with a course correction",
|
|
5292
|
-
inputSchema: genericObject
|
|
5293
|
-
},
|
|
5294
|
-
TodoWrite: {
|
|
5295
|
-
description: "Emit TODO status updates",
|
|
5296
|
-
inputSchema: genericObject
|
|
5297
|
-
},
|
|
5298
|
-
WebFetch: {
|
|
5299
|
-
description: "Fetch and summarize a URL",
|
|
5300
|
-
inputSchema: genericObject
|
|
5301
|
-
},
|
|
5302
|
-
WebSearch: {
|
|
5303
|
-
description: "Search the web with constraints",
|
|
5304
|
-
inputSchema: genericObject
|
|
5305
|
-
},
|
|
5306
|
-
MultipleChoiceQuestion: {
|
|
5307
|
-
description: "Ask the user a multiple choice question",
|
|
5308
|
-
inputSchema: genericObject
|
|
5309
|
-
},
|
|
5310
|
-
// Common aliases seen in telemetry/logs
|
|
5311
|
-
LS: {
|
|
5312
|
-
description: "List files in the working directory",
|
|
5313
|
-
inputSchema: genericObject
|
|
5314
|
-
},
|
|
5315
|
-
TodoRead: {
|
|
5316
|
-
description: "Read TODO state emitted from runner",
|
|
5317
|
-
inputSchema: genericObject
|
|
5318
|
-
}
|
|
5319
|
-
};
|
|
5320
|
-
var proxyHandler = {
|
|
5321
|
-
get(target, prop) {
|
|
5322
|
-
if (typeof prop !== "string") {
|
|
5323
|
-
return Reflect.get(target, prop);
|
|
5324
|
-
}
|
|
5325
|
-
if (Reflect.has(target, prop)) {
|
|
5326
|
-
return Reflect.get(target, prop);
|
|
5327
|
-
}
|
|
5328
|
-
if (prop.startsWith("mcp__")) {
|
|
5329
|
-
return dynamicMcpTool;
|
|
5330
|
-
}
|
|
5331
|
-
return fallbackTool;
|
|
5332
|
-
},
|
|
5333
|
-
has(target, prop) {
|
|
5334
|
-
if (typeof prop === "string") {
|
|
5335
|
-
if (Reflect.has(target, prop) || prop.startsWith("mcp__")) {
|
|
5336
|
-
return true;
|
|
5337
|
-
}
|
|
5338
|
-
}
|
|
5339
|
-
return Reflect.has(target, prop);
|
|
5340
|
-
},
|
|
5341
|
-
ownKeys(target) {
|
|
5342
|
-
return Reflect.ownKeys(target);
|
|
5343
|
-
},
|
|
5344
|
-
getOwnPropertyDescriptor(target, prop) {
|
|
5345
|
-
if (Reflect.has(target, prop)) {
|
|
5346
|
-
return Object.getOwnPropertyDescriptor(target, prop);
|
|
5347
|
-
}
|
|
5348
|
-
return void 0;
|
|
5349
|
-
}
|
|
5350
|
-
};
|
|
5351
|
-
function createClaudeToolRegistry() {
|
|
5352
|
-
return new Proxy(builtinTools, proxyHandler);
|
|
5353
|
-
}
|
|
5354
|
-
var CLAUDE_CLI_TOOL_REGISTRY = createClaudeToolRegistry();
|
|
5355
|
-
|
|
5356
5185
|
// src/lib/logging/build-logger.ts
|
|
5357
5186
|
var BuildLogger = class {
|
|
5358
5187
|
buildId = null;
|
|
@@ -5407,7 +5236,7 @@ var BuildLogger = class {
|
|
|
5407
5236
|
if (typeof process !== "undefined" && process.env.NODE_ENV !== "test") {
|
|
5408
5237
|
try {
|
|
5409
5238
|
if (level === "warn" || level === "error") {
|
|
5410
|
-
addBreadcrumb({
|
|
5239
|
+
Sentry.addBreadcrumb({
|
|
5411
5240
|
category: `build-logger.${context}`,
|
|
5412
5241
|
message,
|
|
5413
5242
|
level: level === "error" ? "error" : "warning",
|
|
@@ -6893,9 +6722,9 @@ async function resolveAgentStrategy(agentId) {
|
|
|
6893
6722
|
}
|
|
6894
6723
|
|
|
6895
6724
|
// Debug logging helper - suppressed in TUI mode (SILENT_MODE=1)
|
|
6896
|
-
const debugLog$
|
|
6725
|
+
const debugLog$1 = (message) => {
|
|
6897
6726
|
if (process.env.SILENT_MODE !== '1' && process.env.DEBUG_BUILD === '1') {
|
|
6898
|
-
debugLog$
|
|
6727
|
+
debugLog$1();
|
|
6899
6728
|
}
|
|
6900
6729
|
};
|
|
6901
6730
|
/**
|
|
@@ -6906,7 +6735,7 @@ async function createBuildStream(options) {
|
|
|
6906
6735
|
// For Codex on NEW projects, use parent directory as CWD (Codex will create the project dir)
|
|
6907
6736
|
// For everything else, use the project directory
|
|
6908
6737
|
const strategy = await resolveAgentStrategy(agent);
|
|
6909
|
-
const projectName = options.projectName ||
|
|
6738
|
+
const projectName = options.projectName || path$1.basename(workingDirectory);
|
|
6910
6739
|
const strategyContext = {
|
|
6911
6740
|
projectId: options.projectId,
|
|
6912
6741
|
projectName,
|
|
@@ -6940,19 +6769,19 @@ async function createBuildStream(options) {
|
|
|
6940
6769
|
// Pass prompt, working directory, and system prompt to the query function
|
|
6941
6770
|
// The buildQuery wrapper will configure the SDK with all options
|
|
6942
6771
|
// Use actualWorkingDir so the query function gets the correct CWD
|
|
6943
|
-
debugLog$
|
|
6772
|
+
debugLog$1();
|
|
6944
6773
|
const generator = query(fullPrompt, actualWorkingDir, systemPrompt, agent, options.codexThreadId, messageParts);
|
|
6945
|
-
debugLog$
|
|
6774
|
+
debugLog$1();
|
|
6946
6775
|
// Create a ReadableStream from the AsyncGenerator
|
|
6947
6776
|
const stream = new ReadableStream({
|
|
6948
6777
|
async start(controller) {
|
|
6949
|
-
debugLog$
|
|
6778
|
+
debugLog$1();
|
|
6950
6779
|
let chunkCount = 0;
|
|
6951
6780
|
try {
|
|
6952
6781
|
for await (const chunk of generator) {
|
|
6953
6782
|
chunkCount++;
|
|
6954
6783
|
if (chunkCount % 5 === 0) {
|
|
6955
|
-
debugLog$
|
|
6784
|
+
debugLog$1(`[runner] [build-engine] Processed ${chunkCount} chunks from generator\n`);
|
|
6956
6785
|
}
|
|
6957
6786
|
// Convert chunk to appropriate format
|
|
6958
6787
|
if (typeof chunk === 'string') {
|
|
@@ -6965,11 +6794,11 @@ async function createBuildStream(options) {
|
|
|
6965
6794
|
controller.enqueue(new TextEncoder().encode(JSON.stringify(chunk)));
|
|
6966
6795
|
}
|
|
6967
6796
|
}
|
|
6968
|
-
debugLog$
|
|
6797
|
+
debugLog$1(`[runner] [build-engine] ✅ Generator exhausted after ${chunkCount} chunks, closing stream\n`);
|
|
6969
6798
|
controller.close();
|
|
6970
6799
|
}
|
|
6971
6800
|
catch (error) {
|
|
6972
|
-
debugLog$
|
|
6801
|
+
debugLog$1();
|
|
6973
6802
|
controller.error(error);
|
|
6974
6803
|
}
|
|
6975
6804
|
finally {
|
|
@@ -6978,7 +6807,7 @@ async function createBuildStream(options) {
|
|
|
6978
6807
|
}
|
|
6979
6808
|
},
|
|
6980
6809
|
});
|
|
6981
|
-
debugLog$
|
|
6810
|
+
debugLog$1();
|
|
6982
6811
|
return stream;
|
|
6983
6812
|
}
|
|
6984
6813
|
|
|
@@ -7960,296 +7789,6 @@ function transformAgentMessageToSSE(agentMessage) {
|
|
|
7960
7789
|
return events;
|
|
7961
7790
|
}
|
|
7962
7791
|
|
|
7963
|
-
// Debug logging helper - suppressed in TUI mode (SILENT_MODE=1)
|
|
7964
|
-
const debugLog$1 = (message) => {
|
|
7965
|
-
if (process.env.SILENT_MODE !== '1' && process.env.DEBUG_BUILD === '1') {
|
|
7966
|
-
debugLog$1();
|
|
7967
|
-
}
|
|
7968
|
-
};
|
|
7969
|
-
/**
|
|
7970
|
-
* Truncate strings for logging to prevent excessive output
|
|
7971
|
-
*/
|
|
7972
|
-
function truncate$1(str, maxLength = 200) {
|
|
7973
|
-
if (str.length <= maxLength)
|
|
7974
|
-
return str;
|
|
7975
|
-
return str.substring(0, maxLength) + '...';
|
|
7976
|
-
}
|
|
7977
|
-
/**
|
|
7978
|
-
* Truncate JSON objects for logging
|
|
7979
|
-
*/
|
|
7980
|
-
function truncateJSON$1(obj, maxLength = 200) {
|
|
7981
|
-
const json = JSON.stringify(obj, null, 2);
|
|
7982
|
-
return truncate$1(json, maxLength);
|
|
7983
|
-
}
|
|
7984
|
-
/**
|
|
7985
|
-
* Transforms AI SDK stream events into messages compatible with our message transformer
|
|
7986
|
-
*/
|
|
7987
|
-
async function* transformAISDKStream(stream) {
|
|
7988
|
-
const DEBUG = process.env.DEBUG_BUILD === '1';
|
|
7989
|
-
let currentMessageId = `msg-${Date.now()}`; // Always have a default ID
|
|
7990
|
-
let currentTextContent = '';
|
|
7991
|
-
const toolInputBuffer = new Map();
|
|
7992
|
-
const toolResults = new Map();
|
|
7993
|
-
let eventCount = 0;
|
|
7994
|
-
let yieldCount = 0;
|
|
7995
|
-
// Track active tool spans for proper duration measurement
|
|
7996
|
-
const activeToolSpans = new Map();
|
|
7997
|
-
// ALWAYS log start - write to stderr to bypass TUI console interceptor
|
|
7998
|
-
debugLog$1();
|
|
7999
|
-
streamLog.info('━━━ STREAM TRANSFORMATION STARTED ━━━');
|
|
8000
|
-
for await (const part of stream) {
|
|
8001
|
-
eventCount++;
|
|
8002
|
-
// Log ALL events to file (first 50)
|
|
8003
|
-
if (eventCount <= 50) {
|
|
8004
|
-
streamLog.event(eventCount, part.type, part);
|
|
8005
|
-
}
|
|
8006
|
-
// DEBUG: Log first 20 events with full JSON to see what we're actually getting
|
|
8007
|
-
if (DEBUG && eventCount <= 20) {
|
|
8008
|
-
debugLog$1(`[runner] [ai-sdk-adapter] Event #${eventCount}: type="${part.type}"\n`);
|
|
8009
|
-
debugLog$1(`[runner] [ai-sdk-adapter] Full JSON: ${truncateJSON$1(part, 500)}\n`);
|
|
8010
|
-
}
|
|
8011
|
-
if (DEBUG)
|
|
8012
|
-
console.log('[ai-sdk-adapter] Event:', part.type, part);
|
|
8013
|
-
// DEBUG: Log every 10 events to show progress
|
|
8014
|
-
if (DEBUG && eventCount % 10 === 0) {
|
|
8015
|
-
debugLog$1();
|
|
8016
|
-
}
|
|
8017
|
-
switch (part.type) {
|
|
8018
|
-
case 'start':
|
|
8019
|
-
case 'start-step':
|
|
8020
|
-
// Update message ID if provided
|
|
8021
|
-
if (part.id) {
|
|
8022
|
-
currentMessageId = part.id;
|
|
8023
|
-
if (DEBUG)
|
|
8024
|
-
debugLog$1();
|
|
8025
|
-
}
|
|
8026
|
-
break;
|
|
8027
|
-
case 'text-start':
|
|
8028
|
-
// Capture message ID from text-start event
|
|
8029
|
-
if (part.id) {
|
|
8030
|
-
currentMessageId = part.id;
|
|
8031
|
-
if (DEBUG)
|
|
8032
|
-
debugLog$1();
|
|
8033
|
-
}
|
|
8034
|
-
break;
|
|
8035
|
-
case 'text-delta':
|
|
8036
|
-
// Just accumulate text content - DON'T yield for every token!
|
|
8037
|
-
// We'll only yield when there's a tool call or the message finishes
|
|
8038
|
-
const textChunk = part.delta ?? part.text ?? part.textDelta;
|
|
8039
|
-
if (typeof textChunk === 'string') {
|
|
8040
|
-
currentTextContent += textChunk;
|
|
8041
|
-
// Update message ID if provided in the event
|
|
8042
|
-
if (part.id) {
|
|
8043
|
-
currentMessageId = part.id;
|
|
8044
|
-
}
|
|
8045
|
-
}
|
|
8046
|
-
break;
|
|
8047
|
-
case 'tool-input-start':
|
|
8048
|
-
// Start buffering tool input
|
|
8049
|
-
toolInputBuffer.set(part.id, {
|
|
8050
|
-
name: part.toolName,
|
|
8051
|
-
input: '',
|
|
8052
|
-
});
|
|
8053
|
-
break;
|
|
8054
|
-
case 'tool-input-delta':
|
|
8055
|
-
// Accumulate tool input
|
|
8056
|
-
const buffer = toolInputBuffer.get(part.id);
|
|
8057
|
-
if (buffer) {
|
|
8058
|
-
buffer.input += part.delta || '';
|
|
8059
|
-
}
|
|
8060
|
-
break;
|
|
8061
|
-
case 'tool-input-end':
|
|
8062
|
-
case 'tool-call':
|
|
8063
|
-
// Tool call is complete - emit it
|
|
8064
|
-
const toolCallId = part.toolCallId || part.id;
|
|
8065
|
-
const toolName = part.toolName;
|
|
8066
|
-
let toolInput = part.args || part.input;
|
|
8067
|
-
// If we have buffered input, parse it
|
|
8068
|
-
if (!toolInput && toolInputBuffer.has(toolCallId) && typeof toolCallId === 'string') {
|
|
8069
|
-
const buffered = toolInputBuffer.get(toolCallId);
|
|
8070
|
-
if (buffered?.input) {
|
|
8071
|
-
if (typeof buffered.input === 'string') {
|
|
8072
|
-
try {
|
|
8073
|
-
toolInput = JSON.parse(buffered.input);
|
|
8074
|
-
}
|
|
8075
|
-
catch {
|
|
8076
|
-
toolInput = { raw: buffered.input };
|
|
8077
|
-
}
|
|
8078
|
-
}
|
|
8079
|
-
try {
|
|
8080
|
-
toolInput = JSON.parse(buffered.input);
|
|
8081
|
-
}
|
|
8082
|
-
catch {
|
|
8083
|
-
toolInput = { raw: buffered.input };
|
|
8084
|
-
}
|
|
8085
|
-
}
|
|
8086
|
-
toolInputBuffer.delete(toolCallId);
|
|
8087
|
-
}
|
|
8088
|
-
if (toolName) {
|
|
8089
|
-
// First, yield any accumulated text as a separate message
|
|
8090
|
-
if (currentTextContent.trim().length > 0) {
|
|
8091
|
-
const textMessage = {
|
|
8092
|
-
type: 'assistant',
|
|
8093
|
-
message: {
|
|
8094
|
-
id: currentMessageId,
|
|
8095
|
-
content: [{ type: 'text', text: currentTextContent }],
|
|
8096
|
-
},
|
|
8097
|
-
};
|
|
8098
|
-
yieldCount++;
|
|
8099
|
-
debugLog$1(`[runner] [ai-sdk-adapter] 💬 Yielding text before tool: ${currentTextContent.length} chars\n`);
|
|
8100
|
-
yield textMessage;
|
|
8101
|
-
// Reset so it's not included in the tool message
|
|
8102
|
-
currentTextContent = '';
|
|
8103
|
-
}
|
|
8104
|
-
// Now yield the tool call as a separate message
|
|
8105
|
-
const toolMessage = {
|
|
8106
|
-
type: 'assistant',
|
|
8107
|
-
message: {
|
|
8108
|
-
id: `${currentMessageId}-tool-${toolCallId}`,
|
|
8109
|
-
content: [
|
|
8110
|
-
{
|
|
8111
|
-
type: 'tool_use',
|
|
8112
|
-
id: toolCallId,
|
|
8113
|
-
name: toolName,
|
|
8114
|
-
input: toolInput || {},
|
|
8115
|
-
},
|
|
8116
|
-
],
|
|
8117
|
-
},
|
|
8118
|
-
};
|
|
8119
|
-
yieldCount++;
|
|
8120
|
-
debugLog$1();
|
|
8121
|
-
debugLog$1(`[runner] [ai-sdk-adapter] Tool input: ${truncateJSON$1(toolInput)}\n`);
|
|
8122
|
-
// Log to file
|
|
8123
|
-
streamLog.yield('tool-call', { toolName, toolCallId, toolInput, message: toolMessage });
|
|
8124
|
-
yield toolMessage;
|
|
8125
|
-
}
|
|
8126
|
-
break;
|
|
8127
|
-
case 'tool-result':
|
|
8128
|
-
// Store tool result
|
|
8129
|
-
const resultId = part.toolCallId;
|
|
8130
|
-
const toolResult = part.result ?? part.output;
|
|
8131
|
-
toolResults.set(resultId, toolResult);
|
|
8132
|
-
// Emit tool result as a user message
|
|
8133
|
-
const resultMessage = {
|
|
8134
|
-
type: 'user',
|
|
8135
|
-
message: {
|
|
8136
|
-
id: `result-${resultId}`,
|
|
8137
|
-
content: [
|
|
8138
|
-
{
|
|
8139
|
-
type: 'tool_result',
|
|
8140
|
-
tool_use_id: resultId,
|
|
8141
|
-
content: JSON.stringify(toolResult),
|
|
8142
|
-
},
|
|
8143
|
-
],
|
|
8144
|
-
},
|
|
8145
|
-
};
|
|
8146
|
-
yieldCount++;
|
|
8147
|
-
debugLog$1(`[runner] [ai-sdk-adapter] 📥 Tool result for: ${part.toolName || resultId}\n`);
|
|
8148
|
-
// Special handling for verbose tool results
|
|
8149
|
-
if (part.toolName === 'TodoWrite') {
|
|
8150
|
-
debugLog$1();
|
|
8151
|
-
}
|
|
8152
|
-
else {
|
|
8153
|
-
debugLog$1(`[runner] [ai-sdk-adapter] Result: ${truncateJSON$1(toolResult)}\n`);
|
|
8154
|
-
}
|
|
8155
|
-
yield resultMessage;
|
|
8156
|
-
break;
|
|
8157
|
-
case 'tool-error':
|
|
8158
|
-
// Emit tool error as a user message
|
|
8159
|
-
const errorId = part.toolCallId || part.id;
|
|
8160
|
-
const errorMessage = {
|
|
8161
|
-
type: 'user',
|
|
8162
|
-
message: {
|
|
8163
|
-
id: `error-${errorId}`,
|
|
8164
|
-
content: [
|
|
8165
|
-
{
|
|
8166
|
-
type: 'tool_result',
|
|
8167
|
-
tool_use_id: errorId,
|
|
8168
|
-
content: JSON.stringify({ error: part.error }),
|
|
8169
|
-
is_error: true,
|
|
8170
|
-
},
|
|
8171
|
-
],
|
|
8172
|
-
},
|
|
8173
|
-
};
|
|
8174
|
-
yieldCount++;
|
|
8175
|
-
debugLog$1(`[runner] [ai-sdk-adapter] ⚠️ Tool error: ${part.toolName || errorId}\n`);
|
|
8176
|
-
debugLog$1(`[runner] [ai-sdk-adapter] Error: ${truncate$1(JSON.stringify(part.error), 150)}\n`);
|
|
8177
|
-
yield errorMessage;
|
|
8178
|
-
break;
|
|
8179
|
-
case 'text-end':
|
|
8180
|
-
// Text block is complete - yield the accumulated text
|
|
8181
|
-
if (currentTextContent.trim().length > 0) {
|
|
8182
|
-
const message = {
|
|
8183
|
-
type: 'assistant',
|
|
8184
|
-
message: {
|
|
8185
|
-
id: currentMessageId,
|
|
8186
|
-
content: [{ type: 'text', text: currentTextContent }],
|
|
8187
|
-
},
|
|
8188
|
-
};
|
|
8189
|
-
yieldCount++;
|
|
8190
|
-
debugLog$1(`[runner] [ai-sdk-adapter] Yielding complete text block: ${currentTextContent.length} chars\n`);
|
|
8191
|
-
yield message;
|
|
8192
|
-
// Reset text content for next block
|
|
8193
|
-
currentTextContent = '';
|
|
8194
|
-
}
|
|
8195
|
-
break;
|
|
8196
|
-
case 'finish':
|
|
8197
|
-
case 'finish-step':
|
|
8198
|
-
// Final message - yield any remaining text
|
|
8199
|
-
if (currentTextContent.trim().length > 0) {
|
|
8200
|
-
yieldCount++;
|
|
8201
|
-
if (DEBUG)
|
|
8202
|
-
debugLog$1(`[runner] [ai-sdk-adapter] Yielding final text: ${currentTextContent.length} chars\n`);
|
|
8203
|
-
yield {
|
|
8204
|
-
type: 'assistant',
|
|
8205
|
-
message: {
|
|
8206
|
-
id: currentMessageId,
|
|
8207
|
-
content: [{ type: 'text', text: currentTextContent }],
|
|
8208
|
-
},
|
|
8209
|
-
};
|
|
8210
|
-
}
|
|
8211
|
-
break;
|
|
8212
|
-
case 'error':
|
|
8213
|
-
// Emit error
|
|
8214
|
-
const errorPayload = part.error ?? { message: 'Unknown Claude stream error' };
|
|
8215
|
-
const errorText = typeof errorPayload === 'object' && errorPayload !== null
|
|
8216
|
-
? JSON.stringify(errorPayload)
|
|
8217
|
-
: String(errorPayload);
|
|
8218
|
-
const wrappedError = new Error(`Claude stream error: ${errorText}`);
|
|
8219
|
-
Object.assign(wrappedError, { cause: errorPayload });
|
|
8220
|
-
debugLog$1();
|
|
8221
|
-
throw wrappedError;
|
|
8222
|
-
// Ignore other event types
|
|
8223
|
-
case 'stream-start':
|
|
8224
|
-
case 'response-metadata':
|
|
8225
|
-
break;
|
|
8226
|
-
default:
|
|
8227
|
-
// Log unknown event types for debugging
|
|
8228
|
-
if (process.env.DEBUG_BUILD === '1') {
|
|
8229
|
-
console.log('[ai-sdk-adapter] Unknown event type:', part.type);
|
|
8230
|
-
}
|
|
8231
|
-
break;
|
|
8232
|
-
}
|
|
8233
|
-
}
|
|
8234
|
-
// Clean up any orphaned tool spans (tool calls that never received results)
|
|
8235
|
-
if (activeToolSpans.size > 0) {
|
|
8236
|
-
debugLog$1(`[runner] [ai-sdk-adapter] ⚠️ Cleaning up ${activeToolSpans.size} orphaned tool spans\n`);
|
|
8237
|
-
for (const [toolId, span] of activeToolSpans) {
|
|
8238
|
-
span.setStatus({ code: 2, message: 'Tool execution incomplete - no result received' });
|
|
8239
|
-
span.end();
|
|
8240
|
-
debugLog$1();
|
|
8241
|
-
}
|
|
8242
|
-
activeToolSpans.clear();
|
|
8243
|
-
}
|
|
8244
|
-
// DEBUG: Log completion stats
|
|
8245
|
-
if (DEBUG) {
|
|
8246
|
-
debugLog$1();
|
|
8247
|
-
}
|
|
8248
|
-
streamLog.info('━━━ STREAM TRANSFORMATION COMPLETE ━━━');
|
|
8249
|
-
streamLog.info(`Total events: ${eventCount}`);
|
|
8250
|
-
streamLog.info(`Total yields: ${yieldCount}`);
|
|
8251
|
-
}
|
|
8252
|
-
|
|
8253
7792
|
/**
|
|
8254
7793
|
* Adapter to transform Codex SDK events into the unified format expected by message transformer
|
|
8255
7794
|
*
|
|
@@ -10017,7 +9556,7 @@ CRITICAL: Your response must START with { and END with }. Output only the JSON o
|
|
|
10017
9556
|
}
|
|
10018
9557
|
catch (error) {
|
|
10019
9558
|
console.error('[project-analyzer] SDK query failed:', error);
|
|
10020
|
-
captureException(error);
|
|
9559
|
+
Sentry.captureException(error);
|
|
10021
9560
|
throw error;
|
|
10022
9561
|
}
|
|
10023
9562
|
if (!responseText) {
|
|
@@ -10555,7 +10094,7 @@ const hmrProxyManager = new HmrProxyManager();
|
|
|
10555
10094
|
|
|
10556
10095
|
// Sentry is initialized via --import flag (see package.json scripts)
|
|
10557
10096
|
// This ensures instrumentation loads before any other modules
|
|
10558
|
-
|
|
10097
|
+
// AI SDK log warnings disabled (legacy - no longer using AI SDK)
|
|
10559
10098
|
/**
|
|
10560
10099
|
* Truncate strings for logging to prevent excessive output
|
|
10561
10100
|
*/
|
|
@@ -10626,146 +10165,6 @@ const debugLog = (...args) => {
|
|
|
10626
10165
|
};
|
|
10627
10166
|
const DEFAULT_AGENT = "claude-code";
|
|
10628
10167
|
const CODEX_MODEL = "gpt-5-codex";
|
|
10629
|
-
// Stderr debug logging - suppressed in TUI mode (SILENT_MODE=1)
|
|
10630
|
-
const stderrDebug = (message) => {
|
|
10631
|
-
if (process.env.SILENT_MODE !== '1' && DEBUG_BUILD) {
|
|
10632
|
-
process.stderr.write(message);
|
|
10633
|
-
}
|
|
10634
|
-
};
|
|
10635
|
-
/**
|
|
10636
|
-
* Create Claude query function using AI SDK
|
|
10637
|
-
*
|
|
10638
|
-
* NOTE: This function prepends CLAUDE_SYSTEM_PROMPT to the systemPrompt from orchestrator.
|
|
10639
|
-
* The orchestrator provides context-specific sections only (no base prompt).
|
|
10640
|
-
*/
|
|
10641
|
-
function createClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID) {
|
|
10642
|
-
return async function* (prompt, workingDirectory, systemPrompt, agent, codexThreadId, messageParts) {
|
|
10643
|
-
// Note: query is auto-instrumented by Sentry's claudeCodeAgentSdkIntegration via OpenTelemetry
|
|
10644
|
-
stderrDebug("[runner] [createClaudeQuery] 🎯 Query function called\n");
|
|
10645
|
-
stderrDebug(`[runner] [createClaudeQuery] Model: ${modelId}\n`);
|
|
10646
|
-
stderrDebug(`[runner] [createClaudeQuery] Working dir: ${workingDirectory}\n`);
|
|
10647
|
-
stderrDebug(`[runner] [createClaudeQuery] Prompt length: ${prompt.length}\n`);
|
|
10648
|
-
// Check if we have image parts
|
|
10649
|
-
const hasImages = messageParts?.some(p => p.type === 'image');
|
|
10650
|
-
if (hasImages) {
|
|
10651
|
-
const imageCount = messageParts?.filter(p => p.type === 'image').length || 0;
|
|
10652
|
-
stderrDebug(`[runner] [createClaudeQuery] 🖼️ Multi-modal message with ${imageCount} image(s)\n`);
|
|
10653
|
-
}
|
|
10654
|
-
// Build combined system prompt
|
|
10655
|
-
const systemPromptSegments = [CLAUDE_SYSTEM_PROMPT.trim()];
|
|
10656
|
-
if (systemPrompt && systemPrompt.trim().length > 0) {
|
|
10657
|
-
systemPromptSegments.push(systemPrompt.trim());
|
|
10658
|
-
}
|
|
10659
|
-
const appendedSystemPrompt = systemPromptSegments.join("\n\n");
|
|
10660
|
-
// Use the full model ID as-is (claude-haiku-4-5, claude-sonnet-4-5, claude-opus-4-5)
|
|
10661
|
-
const aiSdkModelId = modelId || "claude-haiku-4-5";
|
|
10662
|
-
// Ensure working directory exists before passing to Claude Code
|
|
10663
|
-
if (!existsSync(workingDirectory)) {
|
|
10664
|
-
console.log(`[createClaudeQuery] Creating working directory: ${workingDirectory}`);
|
|
10665
|
-
mkdirSync(workingDirectory, { recursive: true });
|
|
10666
|
-
}
|
|
10667
|
-
// NOTE: The community provider (ai-sdk-provider-claude-code) bundles an older
|
|
10668
|
-
// version of the SDK types. We cast to `any` to avoid type conflicts.
|
|
10669
|
-
// This legacy path is deprecated in favor of the native SDK implementation.
|
|
10670
|
-
const model = claudeCode(aiSdkModelId, {
|
|
10671
|
-
queryFunction: query, // Cast to avoid SDK version type conflict
|
|
10672
|
-
systemPrompt: {
|
|
10673
|
-
type: "preset",
|
|
10674
|
-
preset: "claude_code",
|
|
10675
|
-
append: appendedSystemPrompt,
|
|
10676
|
-
},
|
|
10677
|
-
cwd: workingDirectory,
|
|
10678
|
-
permissionMode: "bypassPermissions",
|
|
10679
|
-
maxTurns: 100,
|
|
10680
|
-
additionalDirectories: [workingDirectory],
|
|
10681
|
-
env: {
|
|
10682
|
-
// Claude Code CLI default output cap is 32k; bumping to 64k per
|
|
10683
|
-
// https://docs.claude.com/en/docs/claude-code/settings#environment-variables
|
|
10684
|
-
CLAUDE_CODE_MAX_OUTPUT_TOKENS: process.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS ?? "64000",
|
|
10685
|
-
},
|
|
10686
|
-
// Explicitly allow all tools to prevent "No tools are available" errors
|
|
10687
|
-
canUseTool: createProjectScopedPermissionHandler(workingDirectory), // Cast for type compat
|
|
10688
|
-
streamingInput: "always", // REQUIRED when using canUseTool - enables tool callbacks
|
|
10689
|
-
includePartialMessages: true,
|
|
10690
|
-
settingSources: ["user", "project"], // Load skills from user and project directories
|
|
10691
|
-
});
|
|
10692
|
-
// Build user message - either simple text or multi-part with images
|
|
10693
|
-
let userMessage;
|
|
10694
|
-
if (messageParts && messageParts.length > 0) {
|
|
10695
|
-
// Multi-part message with images
|
|
10696
|
-
const contentParts = [];
|
|
10697
|
-
// Add image parts first (Claude best practice)
|
|
10698
|
-
for (const part of messageParts) {
|
|
10699
|
-
if (part.type === 'image' && part.image) {
|
|
10700
|
-
// AI SDK expects images as data URLs, which we already have
|
|
10701
|
-
contentParts.push({
|
|
10702
|
-
type: 'image',
|
|
10703
|
-
image: part.image, // Already a base64 data URL
|
|
10704
|
-
});
|
|
10705
|
-
// Extract media type for logging
|
|
10706
|
-
const match = part.image.match(/^data:(.+);base64,/);
|
|
10707
|
-
if (match) {
|
|
10708
|
-
stderrDebug(`[runner] [createClaudeQuery] ✅ Added image part (${match[1]})\n`);
|
|
10709
|
-
}
|
|
10710
|
-
}
|
|
10711
|
-
else if (part.type === 'text' && part.text) {
|
|
10712
|
-
contentParts.push({
|
|
10713
|
-
type: 'text',
|
|
10714
|
-
text: part.text
|
|
10715
|
-
});
|
|
10716
|
-
}
|
|
10717
|
-
}
|
|
10718
|
-
// Add prompt text if not already in parts
|
|
10719
|
-
if (!contentParts.some(p => p.type === 'text')) {
|
|
10720
|
-
contentParts.push({
|
|
10721
|
-
type: 'text',
|
|
10722
|
-
text: prompt
|
|
10723
|
-
});
|
|
10724
|
-
}
|
|
10725
|
-
userMessage = contentParts;
|
|
10726
|
-
stderrDebug(`[runner] [createClaudeQuery] 📦 Built multi-part message with ${contentParts.length} part(s)\n`);
|
|
10727
|
-
}
|
|
10728
|
-
else {
|
|
10729
|
-
// Simple text message (existing behavior)
|
|
10730
|
-
userMessage = prompt;
|
|
10731
|
-
}
|
|
10732
|
-
// Stream with telemetry enabled for Sentry
|
|
10733
|
-
// Use 'messages' param for multi-part content, 'prompt' for simple text
|
|
10734
|
-
// IMPORTANT: experimental_telemetry is REQUIRED for the Vercel AI SDK integration to work
|
|
10735
|
-
const streamOptions = {
|
|
10736
|
-
model,
|
|
10737
|
-
tools: CLAUDE_CLI_TOOL_REGISTRY,
|
|
10738
|
-
experimental_telemetry: {
|
|
10739
|
-
isEnabled: true,
|
|
10740
|
-
functionId: 'createClaudeQuery',
|
|
10741
|
-
recordInputs: true,
|
|
10742
|
-
recordOutputs: true,
|
|
10743
|
-
},
|
|
10744
|
-
};
|
|
10745
|
-
const result = Array.isArray(userMessage)
|
|
10746
|
-
? streamText({
|
|
10747
|
-
...streamOptions,
|
|
10748
|
-
messages: [{ role: 'user', content: userMessage }],
|
|
10749
|
-
})
|
|
10750
|
-
: streamText({
|
|
10751
|
-
...streamOptions,
|
|
10752
|
-
prompt: userMessage,
|
|
10753
|
-
});
|
|
10754
|
-
// Transform AI SDK stream format to our message format
|
|
10755
|
-
if (process.env.DEBUG_BUILD === "1") {
|
|
10756
|
-
console.log("[createClaudeQuery] Starting stream consumption...");
|
|
10757
|
-
}
|
|
10758
|
-
for await (const message of transformAISDKStream(result.fullStream)) {
|
|
10759
|
-
if (process.env.DEBUG_BUILD === "1") {
|
|
10760
|
-
console.log("[createClaudeQuery] Yielding message:", message.type);
|
|
10761
|
-
}
|
|
10762
|
-
yield message;
|
|
10763
|
-
}
|
|
10764
|
-
if (process.env.DEBUG_BUILD === "1") {
|
|
10765
|
-
console.log("[createClaudeQuery] Stream consumption complete");
|
|
10766
|
-
}
|
|
10767
|
-
};
|
|
10768
|
-
}
|
|
10769
10168
|
/**
|
|
10770
10169
|
* Create Codex query function using ORIGINAL Codex SDK (NOT AI SDK)
|
|
10771
10170
|
*
|
|
@@ -10860,7 +10259,7 @@ function createCodexQuery() {
|
|
|
10860
10259
|
log(`🚀 [codex-query] Turn ${turnCount}: ${turnCount === 1 ? 'Initial request' : 'Continuing work'}...`);
|
|
10861
10260
|
// Log full prompt being sent to Codex
|
|
10862
10261
|
if (turnCount === 1) {
|
|
10863
|
-
info(fmt `Full Codex prompt (Turn 1) ${{
|
|
10262
|
+
Sentry.logger.info(Sentry.logger.fmt `Full Codex prompt (Turn 1) ${{
|
|
10864
10263
|
prompt: turnPrompt,
|
|
10865
10264
|
promptLength: turnPrompt.length,
|
|
10866
10265
|
promptPreview: turnPrompt.substring(0, 200),
|
|
@@ -10928,13 +10327,8 @@ function createBuildQuery(agent, modelId, abortController) {
|
|
|
10928
10327
|
console.log('[runner] 🔄 Using direct Codex SDK (fallback mode)');
|
|
10929
10328
|
return createCodexQuery();
|
|
10930
10329
|
}
|
|
10931
|
-
// Use legacy AI SDK path when explicitly requested
|
|
10932
|
-
if (!USE_NATIVE_SDK) {
|
|
10933
|
-
console.log('[runner] 🔄 Using AI SDK with claude-code provider (legacy mode)');
|
|
10934
|
-
return createClaudeQuery(modelId ?? DEFAULT_CLAUDE_MODEL_ID);
|
|
10935
|
-
}
|
|
10936
10330
|
// Default: Use native Claude Agent SDK (direct integration)
|
|
10937
|
-
console.log('[runner] 🔄 Using NATIVE Claude Agent SDK
|
|
10331
|
+
console.log('[runner] 🔄 Using NATIVE Claude Agent SDK');
|
|
10938
10332
|
return createNativeClaudeQuery(modelId ?? DEFAULT_CLAUDE_MODEL_ID, abortController);
|
|
10939
10333
|
}
|
|
10940
10334
|
/**
|
|
@@ -11110,7 +10504,7 @@ async function startRunner(options = {}) {
|
|
|
11110
10504
|
const RUNNER_ID = options.runnerId ||
|
|
11111
10505
|
process.env.RUNNER_ID ||
|
|
11112
10506
|
process.env.RAILWAY_REPLICA_ID ||
|
|
11113
|
-
`runner-${
|
|
10507
|
+
`runner-${os$1.hostname()}`;
|
|
11114
10508
|
// WebSocket URL for direct connection to Next.js server
|
|
11115
10509
|
// Supports both new RUNNER_WS_URL and legacy RUNNER_BROKER_URL for backward compatibility
|
|
11116
10510
|
const WS_URL = options.wsUrl ||
|
|
@@ -11245,7 +10639,7 @@ async function startRunner(options = {}) {
|
|
|
11245
10639
|
throw lastError || new Error('Persistence failed after retries');
|
|
11246
10640
|
}
|
|
11247
10641
|
async function persistBuildEventDirect(context, event) {
|
|
11248
|
-
return startSpan({
|
|
10642
|
+
return Sentry.startSpan({
|
|
11249
10643
|
name: `persist.build-event.${event.type}`,
|
|
11250
10644
|
op: 'http.client',
|
|
11251
10645
|
attributes: {
|
|
@@ -11256,7 +10650,7 @@ async function startRunner(options = {}) {
|
|
|
11256
10650
|
},
|
|
11257
10651
|
}, async () => {
|
|
11258
10652
|
// Get trace context for propagation
|
|
11259
|
-
const traceData = getTraceData();
|
|
10653
|
+
const traceData = Sentry.getTraceData();
|
|
11260
10654
|
const headers = {
|
|
11261
10655
|
'Authorization': `Bearer ${runnerSharedSecret}`,
|
|
11262
10656
|
'Content-Type': 'application/json',
|
|
@@ -11364,7 +10758,7 @@ async function startRunner(options = {}) {
|
|
|
11364
10758
|
*/
|
|
11365
10759
|
async function persistRunnerEvent(event) {
|
|
11366
10760
|
// Wrap in Sentry span to create proper trace hierarchy
|
|
11367
|
-
return startSpan({
|
|
10761
|
+
return Sentry.startSpan({
|
|
11368
10762
|
name: `persist.runner-event.${event.type}`,
|
|
11369
10763
|
op: 'http.client',
|
|
11370
10764
|
attributes: {
|
|
@@ -11418,9 +10812,9 @@ async function startRunner(options = {}) {
|
|
|
11418
10812
|
try {
|
|
11419
10813
|
// Attach trace context to ALL events for distributed tracing
|
|
11420
10814
|
// This allows events to be linked back to the originating frontend request
|
|
11421
|
-
const span = getActiveSpan();
|
|
10815
|
+
const span = Sentry.getActiveSpan();
|
|
11422
10816
|
if (span) {
|
|
11423
|
-
const traceData = getTraceData();
|
|
10817
|
+
const traceData = Sentry.getTraceData();
|
|
11424
10818
|
event._sentry = {
|
|
11425
10819
|
trace: traceData['sentry-trace'],
|
|
11426
10820
|
baggage: traceData.baggage,
|
|
@@ -11925,7 +11319,7 @@ async function startRunner(options = {}) {
|
|
|
11925
11319
|
logger.tunnel({ port, url: tunnelUrl, status: 'created' });
|
|
11926
11320
|
// Instrument tunnel startup timing
|
|
11927
11321
|
const tunnelDuration = Date.now() - tunnelStartTime;
|
|
11928
|
-
distribution('tunnel_startup_duration', tunnelDuration, {
|
|
11322
|
+
Sentry.metrics.distribution('tunnel_startup_duration', tunnelDuration, {
|
|
11929
11323
|
unit: 'millisecond',
|
|
11930
11324
|
attributes: {
|
|
11931
11325
|
port: port.toString(),
|
|
@@ -11943,7 +11337,7 @@ async function startRunner(options = {}) {
|
|
|
11943
11337
|
console.error("Failed to create tunnel:", error);
|
|
11944
11338
|
// Instrument failed tunnel startup timing
|
|
11945
11339
|
const tunnelDuration = Date.now() - tunnelStartTime;
|
|
11946
|
-
distribution('tunnel_startup_duration', tunnelDuration, {
|
|
11340
|
+
Sentry.metrics.distribution('tunnel_startup_duration', tunnelDuration, {
|
|
11947
11341
|
unit: 'millisecond',
|
|
11948
11342
|
attributes: {
|
|
11949
11343
|
port: command.payload.port.toString(),
|
|
@@ -12616,7 +12010,7 @@ async function startRunner(options = {}) {
|
|
|
12616
12010
|
// Detect framework from generated files
|
|
12617
12011
|
let detectedFramework = null;
|
|
12618
12012
|
try {
|
|
12619
|
-
const { detectFrameworkFromFilesystem } = await import('./chunks/port-allocator-
|
|
12013
|
+
const { detectFrameworkFromFilesystem } = await import('./chunks/port-allocator-DuAZe2_S.js');
|
|
12620
12014
|
const framework = await detectFrameworkFromFilesystem(projectDirectory);
|
|
12621
12015
|
detectedFramework = framework;
|
|
12622
12016
|
if (framework) {
|
|
@@ -12655,11 +12049,25 @@ ${filesArray.length > 0 ? `Files modified:\n${filesArray.map(f => `- ${f}`).join
|
|
|
12655
12049
|
${completedTodoSnapshot.length > 0 ? `Tasks completed:\n${completedTodoSnapshot.map(t => `- ${t}`).join('\n')}` : ''}
|
|
12656
12050
|
|
|
12657
12051
|
Write a brief, professional summary (1-3 sentences) describing what was accomplished. Focus on the outcome, not the process. Do not use phrases like "I did" or "The assistant". Just describe what was built or changed.`;
|
|
12658
|
-
|
|
12659
|
-
|
|
12052
|
+
// Use native Claude Agent SDK for summary generation
|
|
12053
|
+
let summaryText = '';
|
|
12054
|
+
for await (const msg of query({
|
|
12660
12055
|
prompt: summaryPrompt,
|
|
12661
|
-
|
|
12662
|
-
|
|
12056
|
+
options: {
|
|
12057
|
+
model: 'claude-haiku-4-5',
|
|
12058
|
+
maxTurns: 1,
|
|
12059
|
+
permissionMode: 'default',
|
|
12060
|
+
},
|
|
12061
|
+
})) {
|
|
12062
|
+
if (msg.type === 'assistant' && msg.message?.content) {
|
|
12063
|
+
for (const block of msg.message.content) {
|
|
12064
|
+
if (block.type === 'text') {
|
|
12065
|
+
summaryText += block.text;
|
|
12066
|
+
}
|
|
12067
|
+
}
|
|
12068
|
+
}
|
|
12069
|
+
}
|
|
12070
|
+
summaryText = summaryText.trim();
|
|
12663
12071
|
if (summaryText) {
|
|
12664
12072
|
buildLog(` ✅ AI summary generated (${summaryText.length} chars)`);
|
|
12665
12073
|
sendEvent({
|
|
@@ -12704,7 +12112,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
12704
12112
|
catch (error) {
|
|
12705
12113
|
const errorMessage = error instanceof Error ? error.message : "Failed to run build";
|
|
12706
12114
|
logger.buildFailed(errorMessage);
|
|
12707
|
-
getActiveSpan()?.setStatus({
|
|
12115
|
+
Sentry.getActiveSpan()?.setStatus({
|
|
12708
12116
|
code: 2, // SPAN_STATUS_ERROR
|
|
12709
12117
|
message: "Build failed",
|
|
12710
12118
|
});
|
|
@@ -12921,15 +12329,15 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
12921
12329
|
}
|
|
12922
12330
|
function publishStatus(projectId, commandId) {
|
|
12923
12331
|
const uptimeSeconds = Math.round(process.uptime());
|
|
12924
|
-
const load =
|
|
12332
|
+
const load = os$1.loadavg?.()[0];
|
|
12925
12333
|
sendEvent({
|
|
12926
12334
|
type: "runner-status",
|
|
12927
12335
|
...buildEventBase(projectId, commandId),
|
|
12928
12336
|
payload: {
|
|
12929
12337
|
status: "online",
|
|
12930
12338
|
version: "prototype",
|
|
12931
|
-
hostname:
|
|
12932
|
-
platform:
|
|
12339
|
+
hostname: os$1.hostname(),
|
|
12340
|
+
platform: os$1.platform(),
|
|
12933
12341
|
uptimeSeconds,
|
|
12934
12342
|
load,
|
|
12935
12343
|
},
|
|
@@ -13057,12 +12465,12 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
13057
12465
|
// This creates a span within the continued trace for the runner's work
|
|
13058
12466
|
if (command._sentry?.trace) {
|
|
13059
12467
|
console.log("[runner] Continuing trace from frontend:", command._sentry.trace.substring(0, 50));
|
|
13060
|
-
await continueTrace({
|
|
12468
|
+
await Sentry.continueTrace({
|
|
13061
12469
|
sentryTrace: command._sentry.trace,
|
|
13062
12470
|
baggage: command._sentry.baggage,
|
|
13063
12471
|
}, async () => {
|
|
13064
12472
|
// Create a span for this command execution within the continued trace
|
|
13065
|
-
await startSpan({
|
|
12473
|
+
await Sentry.startSpan({
|
|
13066
12474
|
name: `runner.${command.type}`,
|
|
13067
12475
|
op: command.type === 'start-build' ? 'build.runner' : `runner.${command.type}`,
|
|
13068
12476
|
attributes: {
|
|
@@ -13073,9 +12481,9 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
13073
12481
|
},
|
|
13074
12482
|
}, async (span) => {
|
|
13075
12483
|
try {
|
|
13076
|
-
setTag("command_type", command.type);
|
|
13077
|
-
setTag("project_id", projectIdForTelemetry);
|
|
13078
|
-
setTag("command_id", command.id);
|
|
12484
|
+
Sentry.setTag("command_type", command.type);
|
|
12485
|
+
Sentry.setTag("project_id", projectIdForTelemetry);
|
|
12486
|
+
Sentry.setTag("command_id", command.id);
|
|
13079
12487
|
// Capture build metrics for start-build commands
|
|
13080
12488
|
if (command.type === 'start-build' && command.payload) {
|
|
13081
12489
|
const agent = command.payload.agent ?? 'claude-code';
|
|
@@ -13085,7 +12493,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
13085
12493
|
command.payload.claudeModel === 'claude-opus-4-5')
|
|
13086
12494
|
? command.payload.claudeModel
|
|
13087
12495
|
: 'claude-sonnet-4-5';
|
|
13088
|
-
count('runner.build.started', 1, {
|
|
12496
|
+
Sentry.metrics.count('runner.build.started', 1, {
|
|
13089
12497
|
attributes: {
|
|
13090
12498
|
project_id: command.projectId,
|
|
13091
12499
|
model: agent === 'claude-code' ? claudeModel : agent,
|
|
@@ -13106,7 +12514,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
13106
12514
|
else {
|
|
13107
12515
|
console.log("[runner] No trace context - starting isolated span");
|
|
13108
12516
|
// Create an isolated span when no trace context is provided
|
|
13109
|
-
await startSpan({
|
|
12517
|
+
await Sentry.startSpan({
|
|
13110
12518
|
name: `runner.${command.type}`,
|
|
13111
12519
|
op: command.type === 'start-build' ? 'build.runner' : `runner.${command.type}`,
|
|
13112
12520
|
attributes: {
|
|
@@ -13117,9 +12525,9 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
13117
12525
|
},
|
|
13118
12526
|
}, async (span) => {
|
|
13119
12527
|
try {
|
|
13120
|
-
setTag("command_type", command.type);
|
|
13121
|
-
setTag("project_id", projectIdForTelemetry);
|
|
13122
|
-
setTag("command_id", command.id);
|
|
12528
|
+
Sentry.setTag("command_type", command.type);
|
|
12529
|
+
Sentry.setTag("project_id", projectIdForTelemetry);
|
|
12530
|
+
Sentry.setTag("command_id", command.id);
|
|
13123
12531
|
// Capture build metrics for start-build commands
|
|
13124
12532
|
if (command.type === 'start-build' && command.payload) {
|
|
13125
12533
|
const agent = command.payload.agent ?? 'claude-code';
|
|
@@ -13129,7 +12537,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
13129
12537
|
command.payload.claudeModel === 'claude-opus-4-5')
|
|
13130
12538
|
? command.payload.claudeModel
|
|
13131
12539
|
: 'claude-sonnet-4-5';
|
|
13132
|
-
count('runner.build.started', 1, {
|
|
12540
|
+
Sentry.metrics.count('runner.build.started', 1, {
|
|
13133
12541
|
attributes: {
|
|
13134
12542
|
project_id: command.projectId,
|
|
13135
12543
|
model: agent === 'claude-code' ? claudeModel : agent,
|
|
@@ -13149,7 +12557,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
13149
12557
|
}
|
|
13150
12558
|
catch (error) {
|
|
13151
12559
|
console.error("Failed to parse command", error);
|
|
13152
|
-
captureException(error);
|
|
12560
|
+
Sentry.captureException(error);
|
|
13153
12561
|
sendEvent({
|
|
13154
12562
|
type: "error",
|
|
13155
12563
|
...buildEventBase(undefined, randomUUID$1()),
|
|
@@ -13241,7 +12649,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
|
|
|
13241
12649
|
// Final cleanup of any remaining tunnels
|
|
13242
12650
|
await tunnelManager.closeAll();
|
|
13243
12651
|
// Flush Sentry events before exiting
|
|
13244
|
-
await flush(2000);
|
|
12652
|
+
await Sentry.flush(2000);
|
|
13245
12653
|
log("shutdown complete");
|
|
13246
12654
|
};
|
|
13247
12655
|
process.on("SIGINT", async () => {
|
|
@@ -13274,3 +12682,4 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
|
|
13274
12682
|
}
|
|
13275
12683
|
|
|
13276
12684
|
export { startRunner };
|
|
12685
|
+
//# sourceMappingURL=index.js.map
|