@sideboard-ai/core 0.1.52 → 0.1.53
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/agents/cursor-runner.cjs +43 -4
- package/dist/agents/cursor-runner.js +45 -6
- package/dist/{agents-ON6RKKND.js → agents-KP7UJEHJ.js} +1 -1
- package/dist/{agents-YKSS6VBO.js → agents-KYACODJ3.js} +2 -2
- package/dist/{chunk-D3METLRW.js → chunk-A6HVEMIB.js} +11 -4
- package/dist/{chunk-6QTZVJ7A.js → chunk-BZST4HMJ.js} +16 -3
- package/dist/{chunk-J5JTEJ5O.js → chunk-VG22SETP.js} +6 -0
- package/dist/index.cjs +97 -11
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +86 -11
- package/dist/mcp/run-stdio.cjs +97 -11
- package/dist/mcp/run-stdio.js +85 -10
- package/package.json +1 -1
|
@@ -171,6 +171,33 @@ function localAgentStore() {
|
|
|
171
171
|
(0, import_node_fs3.mkdirSync)(root, { recursive: true });
|
|
172
172
|
return new import_sdk.JsonlLocalAgentStore(root);
|
|
173
173
|
}
|
|
174
|
+
function isAgentBusyError(err) {
|
|
175
|
+
if (err instanceof import_sdk.AgentBusyError) return true;
|
|
176
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
177
|
+
return /already has active run/i.test(message);
|
|
178
|
+
}
|
|
179
|
+
async function cancelStaleLocalRuns(agentId, opts) {
|
|
180
|
+
const listed = await import_sdk.Agent.listRuns(agentId, {
|
|
181
|
+
runtime: "local",
|
|
182
|
+
cwd: opts.cwd,
|
|
183
|
+
store: opts.store,
|
|
184
|
+
limit: 20
|
|
185
|
+
});
|
|
186
|
+
let cancelled = 0;
|
|
187
|
+
for (const run of listed.items) {
|
|
188
|
+
if (run.status !== "running") continue;
|
|
189
|
+
try {
|
|
190
|
+
await import_sdk.Agent.cancelRun(run.id, {
|
|
191
|
+
runtime: "local",
|
|
192
|
+
cwd: opts.cwd,
|
|
193
|
+
store: opts.store
|
|
194
|
+
});
|
|
195
|
+
cancelled += 1;
|
|
196
|
+
} catch {
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return cancelled;
|
|
200
|
+
}
|
|
174
201
|
async function readStdinJson() {
|
|
175
202
|
const rl = (0, import_node_readline.createInterface)({ input: process.stdin, crlfDelay: Infinity });
|
|
176
203
|
const chunks = [];
|
|
@@ -242,10 +269,22 @@ async function main() {
|
|
|
242
269
|
}
|
|
243
270
|
try {
|
|
244
271
|
emit({ type: "session_id", data: agent.agentId });
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
272
|
+
const sendOpts = mcpServers ? { mcpServers } : void 0;
|
|
273
|
+
let run;
|
|
274
|
+
try {
|
|
275
|
+
run = await agent.send(req.prompt, sendOpts);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
if (!isAgentBusyError(err)) throw err;
|
|
278
|
+
const n = await cancelStaleLocalRuns(agent.agentId, {
|
|
279
|
+
cwd: req.cwd,
|
|
280
|
+
store
|
|
281
|
+
});
|
|
282
|
+
emit({
|
|
283
|
+
type: "stderr",
|
|
284
|
+
data: n > 0 ? `Cursor agent had ${n} stale active run(s) \u2014 cancelled and retrying` : "Cursor agent busy \u2014 retrying send"
|
|
285
|
+
});
|
|
286
|
+
run = await agent.send(req.prompt, sendOpts);
|
|
287
|
+
}
|
|
249
288
|
for await (const msg of run.stream()) {
|
|
250
289
|
for (const event of cursorSdkMessageToEvents(msg)) {
|
|
251
290
|
emit(event);
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import {
|
|
3
3
|
cursorSdkMessageToEvents,
|
|
4
4
|
formatUnknownDetail
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-VG22SETP.js";
|
|
6
6
|
import {
|
|
7
7
|
appDataDir
|
|
8
8
|
} from "../chunk-M37RITA6.js";
|
|
9
9
|
|
|
10
10
|
// src/agents/cursor-runner.ts
|
|
11
|
-
import { Agent, CursorAgentError, JsonlLocalAgentStore } from "@cursor/sdk";
|
|
11
|
+
import { Agent, AgentBusyError, CursorAgentError, JsonlLocalAgentStore } from "@cursor/sdk";
|
|
12
12
|
import { mkdirSync } from "fs";
|
|
13
13
|
import { join } from "path";
|
|
14
14
|
import { createInterface } from "readline";
|
|
@@ -35,6 +35,33 @@ function localAgentStore() {
|
|
|
35
35
|
mkdirSync(root, { recursive: true });
|
|
36
36
|
return new JsonlLocalAgentStore(root);
|
|
37
37
|
}
|
|
38
|
+
function isAgentBusyError(err) {
|
|
39
|
+
if (err instanceof AgentBusyError) return true;
|
|
40
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
41
|
+
return /already has active run/i.test(message);
|
|
42
|
+
}
|
|
43
|
+
async function cancelStaleLocalRuns(agentId, opts) {
|
|
44
|
+
const listed = await Agent.listRuns(agentId, {
|
|
45
|
+
runtime: "local",
|
|
46
|
+
cwd: opts.cwd,
|
|
47
|
+
store: opts.store,
|
|
48
|
+
limit: 20
|
|
49
|
+
});
|
|
50
|
+
let cancelled = 0;
|
|
51
|
+
for (const run of listed.items) {
|
|
52
|
+
if (run.status !== "running") continue;
|
|
53
|
+
try {
|
|
54
|
+
await Agent.cancelRun(run.id, {
|
|
55
|
+
runtime: "local",
|
|
56
|
+
cwd: opts.cwd,
|
|
57
|
+
store: opts.store
|
|
58
|
+
});
|
|
59
|
+
cancelled += 1;
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return cancelled;
|
|
64
|
+
}
|
|
38
65
|
async function readStdinJson() {
|
|
39
66
|
const rl = createInterface({ input: process.stdin, crlfDelay: Infinity });
|
|
40
67
|
const chunks = [];
|
|
@@ -106,10 +133,22 @@ async function main() {
|
|
|
106
133
|
}
|
|
107
134
|
try {
|
|
108
135
|
emit({ type: "session_id", data: agent.agentId });
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
136
|
+
const sendOpts = mcpServers ? { mcpServers } : void 0;
|
|
137
|
+
let run;
|
|
138
|
+
try {
|
|
139
|
+
run = await agent.send(req.prompt, sendOpts);
|
|
140
|
+
} catch (err) {
|
|
141
|
+
if (!isAgentBusyError(err)) throw err;
|
|
142
|
+
const n = await cancelStaleLocalRuns(agent.agentId, {
|
|
143
|
+
cwd: req.cwd,
|
|
144
|
+
store
|
|
145
|
+
});
|
|
146
|
+
emit({
|
|
147
|
+
type: "stderr",
|
|
148
|
+
data: n > 0 ? `Cursor agent had ${n} stale active run(s) \u2014 cancelled and retrying` : "Cursor agent busy \u2014 retrying send"
|
|
149
|
+
});
|
|
150
|
+
run = await agent.send(req.prompt, sendOpts);
|
|
151
|
+
}
|
|
113
152
|
for await (const msg of run.stream()) {
|
|
114
153
|
for (const event of cursorSdkMessageToEvents(msg)) {
|
|
115
154
|
emit(event);
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
permissionMode,
|
|
27
27
|
resolveCursorModelId,
|
|
28
28
|
resolveQuotaFallbackAgent
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-A6HVEMIB.js";
|
|
30
30
|
import {
|
|
31
31
|
ORCHESTRATOR_AGENT_KINDS,
|
|
32
32
|
assertOrchestratorCapableAgent,
|
|
@@ -37,7 +37,7 @@ import "./chunk-BXJ76RHF.js";
|
|
|
37
37
|
import {
|
|
38
38
|
cursorSdkMessageToEvents,
|
|
39
39
|
parseCursorRunnerLine
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-VG22SETP.js";
|
|
41
41
|
import "./chunk-T5QQVXK3.js";
|
|
42
42
|
import "./chunk-77WWLBCI.js";
|
|
43
43
|
import "./chunk-M37RITA6.js";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
formatUnknownDetail,
|
|
11
11
|
looksLikeAgentFailureMessage,
|
|
12
12
|
parseCursorRunnerLine
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-VG22SETP.js";
|
|
14
14
|
import {
|
|
15
15
|
claudeChromeEnabled,
|
|
16
16
|
loadAppSettings,
|
|
@@ -1609,6 +1609,7 @@ var opencodeAdapter = {
|
|
|
1609
1609
|
}
|
|
1610
1610
|
},
|
|
1611
1611
|
async resolveSessionId(worktreePath, cached) {
|
|
1612
|
+
const cachedId = cached?.trim() || null;
|
|
1612
1613
|
const listed = await run(
|
|
1613
1614
|
"opencode",
|
|
1614
1615
|
["session", "list", "--format", "json"],
|
|
@@ -1620,15 +1621,21 @@ var opencodeAdapter = {
|
|
|
1620
1621
|
if (Array.isArray(sessions) && sessions.length > 0) {
|
|
1621
1622
|
const norm = (p) => p.replace(/\/+$/, "");
|
|
1622
1623
|
const wt = norm(worktreePath);
|
|
1623
|
-
const
|
|
1624
|
+
const forWorktree = sessions.filter(
|
|
1624
1625
|
(s) => s.directory && norm(s.directory) === wt || s.path && norm(s.path) === wt
|
|
1625
1626
|
);
|
|
1626
|
-
if (
|
|
1627
|
+
if (cachedId && forWorktree.some((s) => s.id === cachedId)) {
|
|
1628
|
+
return cachedId;
|
|
1629
|
+
}
|
|
1630
|
+
if (cachedId && sessions.some((s) => s.id === cachedId)) {
|
|
1631
|
+
return cachedId;
|
|
1632
|
+
}
|
|
1633
|
+
return null;
|
|
1627
1634
|
}
|
|
1628
1635
|
} catch {
|
|
1629
1636
|
}
|
|
1630
1637
|
}
|
|
1631
|
-
return
|
|
1638
|
+
return cachedId;
|
|
1632
1639
|
},
|
|
1633
1640
|
async buildAttach(thread) {
|
|
1634
1641
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
@@ -109,6 +109,11 @@ function summarizeTurnStderr(tail, maxChars = 500) {
|
|
|
109
109
|
if (joined.length <= maxChars) return joined;
|
|
110
110
|
return joined.slice(joined.length - maxChars);
|
|
111
111
|
}
|
|
112
|
+
function looksLikeInvalidAgentSession(text) {
|
|
113
|
+
const lower = text.trim().toLowerCase();
|
|
114
|
+
if (!lower) return false;
|
|
115
|
+
return /session not found/.test(lower) || /no conversation found/.test(lower) || /conversation .+ not found/.test(lower) || /thread .+ not found/.test(lower) || /unknown session/.test(lower) || /invalid session/.test(lower) || /session .+ (missing|expired|deleted|gone)/.test(lower) || /cannot resume/.test(lower) || /failed to (load|resume|open) session/.test(lower);
|
|
116
|
+
}
|
|
112
117
|
function looksLikeAgentFailureMessage(text) {
|
|
113
118
|
const lower = text.trim().toLowerCase();
|
|
114
119
|
if (!lower) return false;
|
|
@@ -1766,6 +1771,7 @@ var opencodeAdapter = {
|
|
|
1766
1771
|
}
|
|
1767
1772
|
},
|
|
1768
1773
|
async resolveSessionId(worktreePath, cached) {
|
|
1774
|
+
const cachedId = cached?.trim() || null;
|
|
1769
1775
|
const listed = await run(
|
|
1770
1776
|
"opencode",
|
|
1771
1777
|
["session", "list", "--format", "json"],
|
|
@@ -1777,15 +1783,21 @@ var opencodeAdapter = {
|
|
|
1777
1783
|
if (Array.isArray(sessions) && sessions.length > 0) {
|
|
1778
1784
|
const norm = (p) => p.replace(/\/+$/, "");
|
|
1779
1785
|
const wt = norm(worktreePath);
|
|
1780
|
-
const
|
|
1786
|
+
const forWorktree = sessions.filter(
|
|
1781
1787
|
(s) => s.directory && norm(s.directory) === wt || s.path && norm(s.path) === wt
|
|
1782
1788
|
);
|
|
1783
|
-
if (
|
|
1789
|
+
if (cachedId && forWorktree.some((s) => s.id === cachedId)) {
|
|
1790
|
+
return cachedId;
|
|
1791
|
+
}
|
|
1792
|
+
if (cachedId && sessions.some((s) => s.id === cachedId)) {
|
|
1793
|
+
return cachedId;
|
|
1794
|
+
}
|
|
1795
|
+
return null;
|
|
1784
1796
|
}
|
|
1785
1797
|
} catch {
|
|
1786
1798
|
}
|
|
1787
1799
|
}
|
|
1788
|
-
return
|
|
1800
|
+
return cachedId;
|
|
1789
1801
|
},
|
|
1790
1802
|
async buildAttach(thread) {
|
|
1791
1803
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
@@ -2197,6 +2209,7 @@ function allAdapters() {
|
|
|
2197
2209
|
export {
|
|
2198
2210
|
pushTurnStderr,
|
|
2199
2211
|
summarizeTurnStderr,
|
|
2212
|
+
looksLikeInvalidAgentSession,
|
|
2200
2213
|
looksLikeAgentFailureMessage,
|
|
2201
2214
|
fallbackTurnFailDetail,
|
|
2202
2215
|
humanizeAgentFailDetail,
|
|
@@ -60,6 +60,11 @@ function summarizeTurnStderr(tail, maxChars = 500) {
|
|
|
60
60
|
if (joined.length <= maxChars) return joined;
|
|
61
61
|
return joined.slice(joined.length - maxChars);
|
|
62
62
|
}
|
|
63
|
+
function looksLikeInvalidAgentSession(text) {
|
|
64
|
+
const lower = text.trim().toLowerCase();
|
|
65
|
+
if (!lower) return false;
|
|
66
|
+
return /session not found/.test(lower) || /no conversation found/.test(lower) || /conversation .+ not found/.test(lower) || /thread .+ not found/.test(lower) || /unknown session/.test(lower) || /invalid session/.test(lower) || /session .+ (missing|expired|deleted|gone)/.test(lower) || /cannot resume/.test(lower) || /failed to (load|resume|open) session/.test(lower);
|
|
67
|
+
}
|
|
63
68
|
function looksLikeAgentFailureMessage(text) {
|
|
64
69
|
const lower = text.trim().toLowerCase();
|
|
65
70
|
if (!lower) return false;
|
|
@@ -212,6 +217,7 @@ export {
|
|
|
212
217
|
extractJsonErrorMessage,
|
|
213
218
|
pushTurnStderr,
|
|
214
219
|
summarizeTurnStderr,
|
|
220
|
+
looksLikeInvalidAgentSession,
|
|
215
221
|
looksLikeAgentFailureMessage,
|
|
216
222
|
fallbackTurnFailDetail,
|
|
217
223
|
humanizeAgentFailDetail,
|
package/dist/index.cjs
CHANGED
|
@@ -4316,6 +4316,11 @@ function summarizeTurnStderr(tail, maxChars = 500) {
|
|
|
4316
4316
|
if (joined.length <= maxChars) return joined;
|
|
4317
4317
|
return joined.slice(joined.length - maxChars);
|
|
4318
4318
|
}
|
|
4319
|
+
function looksLikeInvalidAgentSession(text) {
|
|
4320
|
+
const lower = text.trim().toLowerCase();
|
|
4321
|
+
if (!lower) return false;
|
|
4322
|
+
return /session not found/.test(lower) || /no conversation found/.test(lower) || /conversation .+ not found/.test(lower) || /thread .+ not found/.test(lower) || /unknown session/.test(lower) || /invalid session/.test(lower) || /session .+ (missing|expired|deleted|gone)/.test(lower) || /cannot resume/.test(lower) || /failed to (load|resume|open) session/.test(lower);
|
|
4323
|
+
}
|
|
4319
4324
|
function looksLikeAgentFailureMessage(text) {
|
|
4320
4325
|
const lower = text.trim().toLowerCase();
|
|
4321
4326
|
if (!lower) return false;
|
|
@@ -6124,6 +6129,7 @@ var init_opencode = __esm({
|
|
|
6124
6129
|
}
|
|
6125
6130
|
},
|
|
6126
6131
|
async resolveSessionId(worktreePath, cached) {
|
|
6132
|
+
const cachedId = cached?.trim() || null;
|
|
6127
6133
|
const listed = await run(
|
|
6128
6134
|
"opencode",
|
|
6129
6135
|
["session", "list", "--format", "json"],
|
|
@@ -6135,15 +6141,21 @@ var init_opencode = __esm({
|
|
|
6135
6141
|
if (Array.isArray(sessions) && sessions.length > 0) {
|
|
6136
6142
|
const norm = (p) => p.replace(/\/+$/, "");
|
|
6137
6143
|
const wt = norm(worktreePath);
|
|
6138
|
-
const
|
|
6144
|
+
const forWorktree = sessions.filter(
|
|
6139
6145
|
(s) => s.directory && norm(s.directory) === wt || s.path && norm(s.path) === wt
|
|
6140
6146
|
);
|
|
6141
|
-
if (
|
|
6147
|
+
if (cachedId && forWorktree.some((s) => s.id === cachedId)) {
|
|
6148
|
+
return cachedId;
|
|
6149
|
+
}
|
|
6150
|
+
if (cachedId && sessions.some((s) => s.id === cachedId)) {
|
|
6151
|
+
return cachedId;
|
|
6152
|
+
}
|
|
6153
|
+
return null;
|
|
6142
6154
|
}
|
|
6143
6155
|
} catch {
|
|
6144
6156
|
}
|
|
6145
6157
|
}
|
|
6146
|
-
return
|
|
6158
|
+
return cachedId;
|
|
6147
6159
|
},
|
|
6148
6160
|
async buildAttach(thread) {
|
|
6149
6161
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
@@ -11570,21 +11582,30 @@ var Orchestrator = class {
|
|
|
11570
11582
|
return findThreadByRef(idOrRef) ?? readThread(idOrRef);
|
|
11571
11583
|
}
|
|
11572
11584
|
async createThread(input) {
|
|
11573
|
-
|
|
11585
|
+
const thread = await createThread(input);
|
|
11574
11586
|
this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
|
|
11575
|
-
|
|
11587
|
+
void this.finishCreateThread(thread.id, input.prompt?.trim() || void 0);
|
|
11588
|
+
return thread;
|
|
11589
|
+
}
|
|
11590
|
+
async finishCreateThread(threadId, prompt) {
|
|
11591
|
+
await this.runSetupAfterCreate(threadId);
|
|
11576
11592
|
const { autoRunAfterSetupEnabled: autoRunAfterSetupEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
11577
11593
|
if (autoRunAfterSetupEnabled2()) {
|
|
11578
11594
|
try {
|
|
11579
|
-
await this.startDev(
|
|
11595
|
+
await this.startDev(threadId);
|
|
11580
11596
|
} catch {
|
|
11581
11597
|
}
|
|
11582
11598
|
}
|
|
11583
|
-
const prompt = input.prompt?.trim();
|
|
11584
11599
|
if (prompt) {
|
|
11585
|
-
|
|
11600
|
+
try {
|
|
11601
|
+
await this.send(threadId, prompt);
|
|
11602
|
+
} catch (err) {
|
|
11603
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
11604
|
+
updateThread(threadId, {
|
|
11605
|
+
lastError: `First prompt failed: ${message}`
|
|
11606
|
+
});
|
|
11607
|
+
}
|
|
11586
11608
|
}
|
|
11587
|
-
return thread;
|
|
11588
11609
|
}
|
|
11589
11610
|
/** Run workspace setup after a new worktree is created (no-op if none configured). */
|
|
11590
11611
|
async runSetupAfterCreate(threadId) {
|
|
@@ -11930,8 +11951,73 @@ var Orchestrator = class {
|
|
|
11930
11951
|
}
|
|
11931
11952
|
}
|
|
11932
11953
|
}
|
|
11933
|
-
|
|
11934
|
-
|
|
11954
|
+
let lastStderr = summarizeTurnStderr(stderrTail);
|
|
11955
|
+
let detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
11956
|
+
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && looksLikeInvalidAgentSession(detail) && this.requireThread(threadId).sessionId && this.requireThread(threadId).agent !== "cursor" && this.requireThread(threadId).agent !== "brightsy") {
|
|
11957
|
+
updateThread(threadId, { sessionId: null });
|
|
11958
|
+
pushTurnStderr(
|
|
11959
|
+
stderrTail,
|
|
11960
|
+
"Agent session missing \u2014 starting a fresh session"
|
|
11961
|
+
);
|
|
11962
|
+
this.emit({
|
|
11963
|
+
type: "turn_output",
|
|
11964
|
+
threadId,
|
|
11965
|
+
event: {
|
|
11966
|
+
type: "stderr",
|
|
11967
|
+
data: "Agent session missing \u2014 starting a fresh session"
|
|
11968
|
+
}
|
|
11969
|
+
});
|
|
11970
|
+
const retryThread = this.requireThread(threadId);
|
|
11971
|
+
const prior = retryThread.messages.slice(0, -1);
|
|
11972
|
+
const retrySeed = buildSessionSeed(prior);
|
|
11973
|
+
const retryInstructions = retryThread.agent === "claude" ? null : formatAgentInstructions(
|
|
11974
|
+
loadAgentInstructions(retryThread.worktreePath, retryThread.agent)
|
|
11975
|
+
);
|
|
11976
|
+
const retryPrefix = [
|
|
11977
|
+
coordinatorDirective,
|
|
11978
|
+
worktreeDirective,
|
|
11979
|
+
artifactDirective,
|
|
11980
|
+
renameBranchDirective,
|
|
11981
|
+
retryInstructions,
|
|
11982
|
+
retrySeed
|
|
11983
|
+
].filter(Boolean).join("\n\n---\n\n");
|
|
11984
|
+
const retryHandle = await spawnAgentTurn(
|
|
11985
|
+
retryThread,
|
|
11986
|
+
{ cachedPrefix: retryPrefix, prompt: agentPrompt },
|
|
11987
|
+
(event) => {
|
|
11988
|
+
this.emit({ type: "turn_output", threadId, event });
|
|
11989
|
+
if (event.type === "session_id") {
|
|
11990
|
+
updateThread(threadId, { sessionId: event.data });
|
|
11991
|
+
}
|
|
11992
|
+
if (event.type === "stderr" && typeof event.data === "string") {
|
|
11993
|
+
pushTurnStderr(stderrTail, event.data);
|
|
11994
|
+
}
|
|
11995
|
+
}
|
|
11996
|
+
);
|
|
11997
|
+
this.activeTurns.set(threadId, retryHandle);
|
|
11998
|
+
if (typeof retryHandle.pid === "number" && retryHandle.pid > 0) {
|
|
11999
|
+
updateThread(threadId, { agentPid: retryHandle.pid });
|
|
12000
|
+
}
|
|
12001
|
+
this.processes.set(`${threadId}:agent`, {
|
|
12002
|
+
kind: "agent",
|
|
12003
|
+
pid: retryHandle.pid,
|
|
12004
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12005
|
+
kill: retryHandle.kill
|
|
12006
|
+
});
|
|
12007
|
+
if (this.stoppedTurns.has(threadId)) {
|
|
12008
|
+
retryHandle.kill();
|
|
12009
|
+
}
|
|
12010
|
+
const retryResult = await retryHandle.done;
|
|
12011
|
+
if (retryResult.sessionId) {
|
|
12012
|
+
updateThread(threadId, { sessionId: retryResult.sessionId });
|
|
12013
|
+
}
|
|
12014
|
+
assistantText = retryResult.assistantText.trim();
|
|
12015
|
+
parts = retryResult.parts;
|
|
12016
|
+
usage = retryResult.usage ?? void 0;
|
|
12017
|
+
exitCode = retryResult.exitCode;
|
|
12018
|
+
lastStderr = summarizeTurnStderr(stderrTail);
|
|
12019
|
+
detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
12020
|
+
}
|
|
11935
12021
|
let chatText = assistantText;
|
|
11936
12022
|
if (exitCode !== 0 && !chatText && looksLikeAgentFailureMessage(detail)) {
|
|
11937
12023
|
chatText = humanizeAgentFailDetail(detail);
|
package/dist/index.d.cts
CHANGED
|
@@ -2223,6 +2223,7 @@ declare class Orchestrator {
|
|
|
2223
2223
|
getThreads(includeArchived?: boolean): Thread[];
|
|
2224
2224
|
getThread(idOrRef: string): Thread | null;
|
|
2225
2225
|
createThread(input: CreateThreadInput): Promise<Thread>;
|
|
2226
|
+
private finishCreateThread;
|
|
2226
2227
|
/** Run workspace setup after a new worktree is created (no-op if none configured). */
|
|
2227
2228
|
private runSetupAfterCreate;
|
|
2228
2229
|
listWorkspaces(): Workspace[];
|
package/dist/index.d.ts
CHANGED
|
@@ -2223,6 +2223,7 @@ declare class Orchestrator {
|
|
|
2223
2223
|
getThreads(includeArchived?: boolean): Thread[];
|
|
2224
2224
|
getThread(idOrRef: string): Thread | null;
|
|
2225
2225
|
createThread(input: CreateThreadInput): Promise<Thread>;
|
|
2226
|
+
private finishCreateThread;
|
|
2226
2227
|
/** Run workspace setup after a new worktree is created (no-op if none configured). */
|
|
2227
2228
|
private runSetupAfterCreate;
|
|
2228
2229
|
listWorkspaces(): Workspace[];
|
package/dist/index.js
CHANGED
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
resolveQuotaFallbackAgent,
|
|
71
71
|
sanitizeMcpServerName,
|
|
72
72
|
writeInjectedMcpConfig
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-A6HVEMIB.js";
|
|
74
74
|
import {
|
|
75
75
|
ORCHESTRATOR_AGENT_KINDS,
|
|
76
76
|
assertOrchestratorCapableAgent,
|
|
@@ -106,10 +106,11 @@ import {
|
|
|
106
106
|
formatTurnExitError,
|
|
107
107
|
humanizeAgentFailDetail,
|
|
108
108
|
looksLikeAgentFailureMessage,
|
|
109
|
+
looksLikeInvalidAgentSession,
|
|
109
110
|
parseCursorRunnerLine,
|
|
110
111
|
pushTurnStderr,
|
|
111
112
|
summarizeTurnStderr
|
|
112
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-VG22SETP.js";
|
|
113
114
|
import {
|
|
114
115
|
HARNESS_ENV_KEYS,
|
|
115
116
|
appSettingsPath,
|
|
@@ -2941,7 +2942,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2941
2942
|
return readThread(thread.id) ?? thread;
|
|
2942
2943
|
}
|
|
2943
2944
|
async function listLinearIssues(agent, repoPath) {
|
|
2944
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
2945
|
+
const { getAdapter: getAdapter2 } = await import("./agents-KYACODJ3.js");
|
|
2945
2946
|
await requireAgent(agent, { requireLinear: true });
|
|
2946
2947
|
const adapter = getAdapter2(agent);
|
|
2947
2948
|
if (!adapter.listLinearIssues) {
|
|
@@ -4544,21 +4545,30 @@ var Orchestrator = class {
|
|
|
4544
4545
|
return findThreadByRef(idOrRef) ?? readThread(idOrRef);
|
|
4545
4546
|
}
|
|
4546
4547
|
async createThread(input) {
|
|
4547
|
-
|
|
4548
|
+
const thread = await createThread(input);
|
|
4548
4549
|
this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
|
|
4549
|
-
|
|
4550
|
+
void this.finishCreateThread(thread.id, input.prompt?.trim() || void 0);
|
|
4551
|
+
return thread;
|
|
4552
|
+
}
|
|
4553
|
+
async finishCreateThread(threadId, prompt) {
|
|
4554
|
+
await this.runSetupAfterCreate(threadId);
|
|
4550
4555
|
const { autoRunAfterSetupEnabled: autoRunAfterSetupEnabled2 } = await import("./app-settings-LZP632KI.js");
|
|
4551
4556
|
if (autoRunAfterSetupEnabled2()) {
|
|
4552
4557
|
try {
|
|
4553
|
-
await this.startDev(
|
|
4558
|
+
await this.startDev(threadId);
|
|
4554
4559
|
} catch {
|
|
4555
4560
|
}
|
|
4556
4561
|
}
|
|
4557
|
-
const prompt = input.prompt?.trim();
|
|
4558
4562
|
if (prompt) {
|
|
4559
|
-
|
|
4563
|
+
try {
|
|
4564
|
+
await this.send(threadId, prompt);
|
|
4565
|
+
} catch (err) {
|
|
4566
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4567
|
+
updateThread(threadId, {
|
|
4568
|
+
lastError: `First prompt failed: ${message}`
|
|
4569
|
+
});
|
|
4570
|
+
}
|
|
4560
4571
|
}
|
|
4561
|
-
return thread;
|
|
4562
4572
|
}
|
|
4563
4573
|
/** Run workspace setup after a new worktree is created (no-op if none configured). */
|
|
4564
4574
|
async runSetupAfterCreate(threadId) {
|
|
@@ -4904,8 +4914,73 @@ var Orchestrator = class {
|
|
|
4904
4914
|
}
|
|
4905
4915
|
}
|
|
4906
4916
|
}
|
|
4907
|
-
|
|
4908
|
-
|
|
4917
|
+
let lastStderr = summarizeTurnStderr(stderrTail);
|
|
4918
|
+
let detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
4919
|
+
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && looksLikeInvalidAgentSession(detail) && this.requireThread(threadId).sessionId && this.requireThread(threadId).agent !== "cursor" && this.requireThread(threadId).agent !== "brightsy") {
|
|
4920
|
+
updateThread(threadId, { sessionId: null });
|
|
4921
|
+
pushTurnStderr(
|
|
4922
|
+
stderrTail,
|
|
4923
|
+
"Agent session missing \u2014 starting a fresh session"
|
|
4924
|
+
);
|
|
4925
|
+
this.emit({
|
|
4926
|
+
type: "turn_output",
|
|
4927
|
+
threadId,
|
|
4928
|
+
event: {
|
|
4929
|
+
type: "stderr",
|
|
4930
|
+
data: "Agent session missing \u2014 starting a fresh session"
|
|
4931
|
+
}
|
|
4932
|
+
});
|
|
4933
|
+
const retryThread = this.requireThread(threadId);
|
|
4934
|
+
const prior = retryThread.messages.slice(0, -1);
|
|
4935
|
+
const retrySeed = buildSessionSeed(prior);
|
|
4936
|
+
const retryInstructions = retryThread.agent === "claude" ? null : formatAgentInstructions(
|
|
4937
|
+
loadAgentInstructions(retryThread.worktreePath, retryThread.agent)
|
|
4938
|
+
);
|
|
4939
|
+
const retryPrefix = [
|
|
4940
|
+
coordinatorDirective,
|
|
4941
|
+
worktreeDirective,
|
|
4942
|
+
artifactDirective,
|
|
4943
|
+
renameBranchDirective,
|
|
4944
|
+
retryInstructions,
|
|
4945
|
+
retrySeed
|
|
4946
|
+
].filter(Boolean).join("\n\n---\n\n");
|
|
4947
|
+
const retryHandle = await spawnAgentTurn(
|
|
4948
|
+
retryThread,
|
|
4949
|
+
{ cachedPrefix: retryPrefix, prompt: agentPrompt },
|
|
4950
|
+
(event) => {
|
|
4951
|
+
this.emit({ type: "turn_output", threadId, event });
|
|
4952
|
+
if (event.type === "session_id") {
|
|
4953
|
+
updateThread(threadId, { sessionId: event.data });
|
|
4954
|
+
}
|
|
4955
|
+
if (event.type === "stderr" && typeof event.data === "string") {
|
|
4956
|
+
pushTurnStderr(stderrTail, event.data);
|
|
4957
|
+
}
|
|
4958
|
+
}
|
|
4959
|
+
);
|
|
4960
|
+
this.activeTurns.set(threadId, retryHandle);
|
|
4961
|
+
if (typeof retryHandle.pid === "number" && retryHandle.pid > 0) {
|
|
4962
|
+
updateThread(threadId, { agentPid: retryHandle.pid });
|
|
4963
|
+
}
|
|
4964
|
+
this.processes.set(`${threadId}:agent`, {
|
|
4965
|
+
kind: "agent",
|
|
4966
|
+
pid: retryHandle.pid,
|
|
4967
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4968
|
+
kill: retryHandle.kill
|
|
4969
|
+
});
|
|
4970
|
+
if (this.stoppedTurns.has(threadId)) {
|
|
4971
|
+
retryHandle.kill();
|
|
4972
|
+
}
|
|
4973
|
+
const retryResult = await retryHandle.done;
|
|
4974
|
+
if (retryResult.sessionId) {
|
|
4975
|
+
updateThread(threadId, { sessionId: retryResult.sessionId });
|
|
4976
|
+
}
|
|
4977
|
+
assistantText = retryResult.assistantText.trim();
|
|
4978
|
+
parts = retryResult.parts;
|
|
4979
|
+
usage = retryResult.usage ?? void 0;
|
|
4980
|
+
exitCode = retryResult.exitCode;
|
|
4981
|
+
lastStderr = summarizeTurnStderr(stderrTail);
|
|
4982
|
+
detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
4983
|
+
}
|
|
4909
4984
|
let chatText = assistantText;
|
|
4910
4985
|
if (exitCode !== 0 && !chatText && looksLikeAgentFailureMessage(detail)) {
|
|
4911
4986
|
chatText = humanizeAgentFailDetail(detail);
|
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -92,6 +92,11 @@ function summarizeTurnStderr(tail, maxChars = 500) {
|
|
|
92
92
|
if (joined.length <= maxChars) return joined;
|
|
93
93
|
return joined.slice(joined.length - maxChars);
|
|
94
94
|
}
|
|
95
|
+
function looksLikeInvalidAgentSession(text) {
|
|
96
|
+
const lower = text.trim().toLowerCase();
|
|
97
|
+
if (!lower) return false;
|
|
98
|
+
return /session not found/.test(lower) || /no conversation found/.test(lower) || /conversation .+ not found/.test(lower) || /thread .+ not found/.test(lower) || /unknown session/.test(lower) || /invalid session/.test(lower) || /session .+ (missing|expired|deleted|gone)/.test(lower) || /cannot resume/.test(lower) || /failed to (load|resume|open) session/.test(lower);
|
|
99
|
+
}
|
|
95
100
|
function looksLikeAgentFailureMessage(text) {
|
|
96
101
|
const lower = text.trim().toLowerCase();
|
|
97
102
|
if (!lower) return false;
|
|
@@ -5710,6 +5715,7 @@ var init_opencode = __esm({
|
|
|
5710
5715
|
}
|
|
5711
5716
|
},
|
|
5712
5717
|
async resolveSessionId(worktreePath, cached) {
|
|
5718
|
+
const cachedId = cached?.trim() || null;
|
|
5713
5719
|
const listed = await run(
|
|
5714
5720
|
"opencode",
|
|
5715
5721
|
["session", "list", "--format", "json"],
|
|
@@ -5721,15 +5727,21 @@ var init_opencode = __esm({
|
|
|
5721
5727
|
if (Array.isArray(sessions) && sessions.length > 0) {
|
|
5722
5728
|
const norm = (p) => p.replace(/\/+$/, "");
|
|
5723
5729
|
const wt = norm(worktreePath);
|
|
5724
|
-
const
|
|
5730
|
+
const forWorktree = sessions.filter(
|
|
5725
5731
|
(s) => s.directory && norm(s.directory) === wt || s.path && norm(s.path) === wt
|
|
5726
5732
|
);
|
|
5727
|
-
if (
|
|
5733
|
+
if (cachedId && forWorktree.some((s) => s.id === cachedId)) {
|
|
5734
|
+
return cachedId;
|
|
5735
|
+
}
|
|
5736
|
+
if (cachedId && sessions.some((s) => s.id === cachedId)) {
|
|
5737
|
+
return cachedId;
|
|
5738
|
+
}
|
|
5739
|
+
return null;
|
|
5728
5740
|
}
|
|
5729
5741
|
} catch {
|
|
5730
5742
|
}
|
|
5731
5743
|
}
|
|
5732
|
-
return
|
|
5744
|
+
return cachedId;
|
|
5733
5745
|
},
|
|
5734
5746
|
async buildAttach(thread) {
|
|
5735
5747
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
@@ -10479,21 +10491,30 @@ var Orchestrator = class {
|
|
|
10479
10491
|
return findThreadByRef(idOrRef) ?? readThread(idOrRef);
|
|
10480
10492
|
}
|
|
10481
10493
|
async createThread(input) {
|
|
10482
|
-
|
|
10494
|
+
const thread = await createThread(input);
|
|
10483
10495
|
this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
|
|
10484
|
-
|
|
10496
|
+
void this.finishCreateThread(thread.id, input.prompt?.trim() || void 0);
|
|
10497
|
+
return thread;
|
|
10498
|
+
}
|
|
10499
|
+
async finishCreateThread(threadId, prompt) {
|
|
10500
|
+
await this.runSetupAfterCreate(threadId);
|
|
10485
10501
|
const { autoRunAfterSetupEnabled: autoRunAfterSetupEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
10486
10502
|
if (autoRunAfterSetupEnabled2()) {
|
|
10487
10503
|
try {
|
|
10488
|
-
await this.startDev(
|
|
10504
|
+
await this.startDev(threadId);
|
|
10489
10505
|
} catch {
|
|
10490
10506
|
}
|
|
10491
10507
|
}
|
|
10492
|
-
const prompt = input.prompt?.trim();
|
|
10493
10508
|
if (prompt) {
|
|
10494
|
-
|
|
10509
|
+
try {
|
|
10510
|
+
await this.send(threadId, prompt);
|
|
10511
|
+
} catch (err) {
|
|
10512
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
10513
|
+
updateThread(threadId, {
|
|
10514
|
+
lastError: `First prompt failed: ${message}`
|
|
10515
|
+
});
|
|
10516
|
+
}
|
|
10495
10517
|
}
|
|
10496
|
-
return thread;
|
|
10497
10518
|
}
|
|
10498
10519
|
/** Run workspace setup after a new worktree is created (no-op if none configured). */
|
|
10499
10520
|
async runSetupAfterCreate(threadId) {
|
|
@@ -10839,8 +10860,73 @@ var Orchestrator = class {
|
|
|
10839
10860
|
}
|
|
10840
10861
|
}
|
|
10841
10862
|
}
|
|
10842
|
-
|
|
10843
|
-
|
|
10863
|
+
let lastStderr = summarizeTurnStderr(stderrTail);
|
|
10864
|
+
let detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
10865
|
+
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && looksLikeInvalidAgentSession(detail) && this.requireThread(threadId).sessionId && this.requireThread(threadId).agent !== "cursor" && this.requireThread(threadId).agent !== "brightsy") {
|
|
10866
|
+
updateThread(threadId, { sessionId: null });
|
|
10867
|
+
pushTurnStderr(
|
|
10868
|
+
stderrTail,
|
|
10869
|
+
"Agent session missing \u2014 starting a fresh session"
|
|
10870
|
+
);
|
|
10871
|
+
this.emit({
|
|
10872
|
+
type: "turn_output",
|
|
10873
|
+
threadId,
|
|
10874
|
+
event: {
|
|
10875
|
+
type: "stderr",
|
|
10876
|
+
data: "Agent session missing \u2014 starting a fresh session"
|
|
10877
|
+
}
|
|
10878
|
+
});
|
|
10879
|
+
const retryThread = this.requireThread(threadId);
|
|
10880
|
+
const prior = retryThread.messages.slice(0, -1);
|
|
10881
|
+
const retrySeed = buildSessionSeed(prior);
|
|
10882
|
+
const retryInstructions = retryThread.agent === "claude" ? null : formatAgentInstructions(
|
|
10883
|
+
loadAgentInstructions(retryThread.worktreePath, retryThread.agent)
|
|
10884
|
+
);
|
|
10885
|
+
const retryPrefix = [
|
|
10886
|
+
coordinatorDirective,
|
|
10887
|
+
worktreeDirective,
|
|
10888
|
+
artifactDirective,
|
|
10889
|
+
renameBranchDirective,
|
|
10890
|
+
retryInstructions,
|
|
10891
|
+
retrySeed
|
|
10892
|
+
].filter(Boolean).join("\n\n---\n\n");
|
|
10893
|
+
const retryHandle = await spawnAgentTurn(
|
|
10894
|
+
retryThread,
|
|
10895
|
+
{ cachedPrefix: retryPrefix, prompt: agentPrompt },
|
|
10896
|
+
(event) => {
|
|
10897
|
+
this.emit({ type: "turn_output", threadId, event });
|
|
10898
|
+
if (event.type === "session_id") {
|
|
10899
|
+
updateThread(threadId, { sessionId: event.data });
|
|
10900
|
+
}
|
|
10901
|
+
if (event.type === "stderr" && typeof event.data === "string") {
|
|
10902
|
+
pushTurnStderr(stderrTail, event.data);
|
|
10903
|
+
}
|
|
10904
|
+
}
|
|
10905
|
+
);
|
|
10906
|
+
this.activeTurns.set(threadId, retryHandle);
|
|
10907
|
+
if (typeof retryHandle.pid === "number" && retryHandle.pid > 0) {
|
|
10908
|
+
updateThread(threadId, { agentPid: retryHandle.pid });
|
|
10909
|
+
}
|
|
10910
|
+
this.processes.set(`${threadId}:agent`, {
|
|
10911
|
+
kind: "agent",
|
|
10912
|
+
pid: retryHandle.pid,
|
|
10913
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10914
|
+
kill: retryHandle.kill
|
|
10915
|
+
});
|
|
10916
|
+
if (this.stoppedTurns.has(threadId)) {
|
|
10917
|
+
retryHandle.kill();
|
|
10918
|
+
}
|
|
10919
|
+
const retryResult = await retryHandle.done;
|
|
10920
|
+
if (retryResult.sessionId) {
|
|
10921
|
+
updateThread(threadId, { sessionId: retryResult.sessionId });
|
|
10922
|
+
}
|
|
10923
|
+
assistantText = retryResult.assistantText.trim();
|
|
10924
|
+
parts = retryResult.parts;
|
|
10925
|
+
usage = retryResult.usage ?? void 0;
|
|
10926
|
+
exitCode = retryResult.exitCode;
|
|
10927
|
+
lastStderr = summarizeTurnStderr(stderrTail);
|
|
10928
|
+
detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
10929
|
+
}
|
|
10844
10930
|
let chatText = assistantText;
|
|
10845
10931
|
if (exitCode !== 0 && !chatText && looksLikeAgentFailureMessage(detail)) {
|
|
10846
10932
|
chatText = humanizeAgentFailDetail(detail);
|
package/dist/mcp/run-stdio.js
CHANGED
|
@@ -10,12 +10,13 @@ import {
|
|
|
10
10
|
isSessionQuotaLimit,
|
|
11
11
|
listModelsForAgent,
|
|
12
12
|
looksLikeAgentFailureMessage,
|
|
13
|
+
looksLikeInvalidAgentSession,
|
|
13
14
|
parseBrightsyCliLine,
|
|
14
15
|
parseSessionQuotaResetAt,
|
|
15
16
|
pushTurnStderr,
|
|
16
17
|
resolveQuotaFallbackAgent,
|
|
17
18
|
summarizeTurnStderr
|
|
18
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-BZST4HMJ.js";
|
|
19
20
|
import "../chunk-H6GGDLYS.js";
|
|
20
21
|
import {
|
|
21
22
|
addWorkspace,
|
|
@@ -1162,7 +1163,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
1162
1163
|
return readThread(thread.id) ?? thread;
|
|
1163
1164
|
}
|
|
1164
1165
|
async function listLinearIssues(agent, repoPath) {
|
|
1165
|
-
const { getAdapter: getAdapter2 } = await import("../agents-
|
|
1166
|
+
const { getAdapter: getAdapter2 } = await import("../agents-KP7UJEHJ.js");
|
|
1166
1167
|
await requireAgent(agent, { requireLinear: true });
|
|
1167
1168
|
const adapter = getAdapter2(agent);
|
|
1168
1169
|
if (!adapter.listLinearIssues) {
|
|
@@ -4037,21 +4038,30 @@ var Orchestrator = class {
|
|
|
4037
4038
|
return findThreadByRef(idOrRef) ?? readThread(idOrRef);
|
|
4038
4039
|
}
|
|
4039
4040
|
async createThread(input) {
|
|
4040
|
-
|
|
4041
|
+
const thread = await createThread(input);
|
|
4041
4042
|
this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
|
|
4042
|
-
|
|
4043
|
+
void this.finishCreateThread(thread.id, input.prompt?.trim() || void 0);
|
|
4044
|
+
return thread;
|
|
4045
|
+
}
|
|
4046
|
+
async finishCreateThread(threadId, prompt) {
|
|
4047
|
+
await this.runSetupAfterCreate(threadId);
|
|
4043
4048
|
const { autoRunAfterSetupEnabled } = await import("../app-settings-7XVDQJ7F.js");
|
|
4044
4049
|
if (autoRunAfterSetupEnabled()) {
|
|
4045
4050
|
try {
|
|
4046
|
-
await this.startDev(
|
|
4051
|
+
await this.startDev(threadId);
|
|
4047
4052
|
} catch {
|
|
4048
4053
|
}
|
|
4049
4054
|
}
|
|
4050
|
-
const prompt = input.prompt?.trim();
|
|
4051
4055
|
if (prompt) {
|
|
4052
|
-
|
|
4056
|
+
try {
|
|
4057
|
+
await this.send(threadId, prompt);
|
|
4058
|
+
} catch (err) {
|
|
4059
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4060
|
+
updateThread(threadId, {
|
|
4061
|
+
lastError: `First prompt failed: ${message}`
|
|
4062
|
+
});
|
|
4063
|
+
}
|
|
4053
4064
|
}
|
|
4054
|
-
return thread;
|
|
4055
4065
|
}
|
|
4056
4066
|
/** Run workspace setup after a new worktree is created (no-op if none configured). */
|
|
4057
4067
|
async runSetupAfterCreate(threadId) {
|
|
@@ -4397,8 +4407,73 @@ var Orchestrator = class {
|
|
|
4397
4407
|
}
|
|
4398
4408
|
}
|
|
4399
4409
|
}
|
|
4400
|
-
|
|
4401
|
-
|
|
4410
|
+
let lastStderr = summarizeTurnStderr(stderrTail);
|
|
4411
|
+
let detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
4412
|
+
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && looksLikeInvalidAgentSession(detail) && this.requireThread(threadId).sessionId && this.requireThread(threadId).agent !== "cursor" && this.requireThread(threadId).agent !== "brightsy") {
|
|
4413
|
+
updateThread(threadId, { sessionId: null });
|
|
4414
|
+
pushTurnStderr(
|
|
4415
|
+
stderrTail,
|
|
4416
|
+
"Agent session missing \u2014 starting a fresh session"
|
|
4417
|
+
);
|
|
4418
|
+
this.emit({
|
|
4419
|
+
type: "turn_output",
|
|
4420
|
+
threadId,
|
|
4421
|
+
event: {
|
|
4422
|
+
type: "stderr",
|
|
4423
|
+
data: "Agent session missing \u2014 starting a fresh session"
|
|
4424
|
+
}
|
|
4425
|
+
});
|
|
4426
|
+
const retryThread = this.requireThread(threadId);
|
|
4427
|
+
const prior = retryThread.messages.slice(0, -1);
|
|
4428
|
+
const retrySeed = buildSessionSeed(prior);
|
|
4429
|
+
const retryInstructions = retryThread.agent === "claude" ? null : formatAgentInstructions(
|
|
4430
|
+
loadAgentInstructions(retryThread.worktreePath, retryThread.agent)
|
|
4431
|
+
);
|
|
4432
|
+
const retryPrefix = [
|
|
4433
|
+
coordinatorDirective,
|
|
4434
|
+
worktreeDirective,
|
|
4435
|
+
artifactDirective,
|
|
4436
|
+
renameBranchDirective,
|
|
4437
|
+
retryInstructions,
|
|
4438
|
+
retrySeed
|
|
4439
|
+
].filter(Boolean).join("\n\n---\n\n");
|
|
4440
|
+
const retryHandle = await spawnAgentTurn(
|
|
4441
|
+
retryThread,
|
|
4442
|
+
{ cachedPrefix: retryPrefix, prompt: agentPrompt },
|
|
4443
|
+
(event) => {
|
|
4444
|
+
this.emit({ type: "turn_output", threadId, event });
|
|
4445
|
+
if (event.type === "session_id") {
|
|
4446
|
+
updateThread(threadId, { sessionId: event.data });
|
|
4447
|
+
}
|
|
4448
|
+
if (event.type === "stderr" && typeof event.data === "string") {
|
|
4449
|
+
pushTurnStderr(stderrTail, event.data);
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
);
|
|
4453
|
+
this.activeTurns.set(threadId, retryHandle);
|
|
4454
|
+
if (typeof retryHandle.pid === "number" && retryHandle.pid > 0) {
|
|
4455
|
+
updateThread(threadId, { agentPid: retryHandle.pid });
|
|
4456
|
+
}
|
|
4457
|
+
this.processes.set(`${threadId}:agent`, {
|
|
4458
|
+
kind: "agent",
|
|
4459
|
+
pid: retryHandle.pid,
|
|
4460
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4461
|
+
kill: retryHandle.kill
|
|
4462
|
+
});
|
|
4463
|
+
if (this.stoppedTurns.has(threadId)) {
|
|
4464
|
+
retryHandle.kill();
|
|
4465
|
+
}
|
|
4466
|
+
const retryResult = await retryHandle.done;
|
|
4467
|
+
if (retryResult.sessionId) {
|
|
4468
|
+
updateThread(threadId, { sessionId: retryResult.sessionId });
|
|
4469
|
+
}
|
|
4470
|
+
assistantText = retryResult.assistantText.trim();
|
|
4471
|
+
parts = retryResult.parts;
|
|
4472
|
+
usage = retryResult.usage ?? void 0;
|
|
4473
|
+
exitCode = retryResult.exitCode;
|
|
4474
|
+
lastStderr = summarizeTurnStderr(stderrTail);
|
|
4475
|
+
detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
4476
|
+
}
|
|
4402
4477
|
let chatText = assistantText;
|
|
4403
4478
|
if (exitCode !== 0 && !chatText && looksLikeAgentFailureMessage(detail)) {
|
|
4404
4479
|
chatText = humanizeAgentFailDetail(detail);
|