@sideboard-ai/core 0.1.52 → 0.1.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/agents/cursor-runner.cjs +126 -11
  2. package/dist/agents/cursor-runner.js +45 -6
  3. package/dist/{agents-YKSS6VBO.js → agents-2YYWW723.js} +3 -3
  4. package/dist/{agents-ON6RKKND.js → agents-AQFEFKBL.js} +2 -2
  5. package/dist/{app-settings-LZP632KI.js → app-settings-2LQNRTBE.js} +3 -1
  6. package/dist/{app-settings-7XVDQJ7F.js → app-settings-73DI4B6T.js} +3 -1
  7. package/dist/{chunk-J5JTEJ5O.js → chunk-3WJAUKIL.js} +89 -7
  8. package/dist/{chunk-GNML24AW.js → chunk-5DMYULLC.js} +1 -1
  9. package/dist/{chunk-D3METLRW.js → chunk-7F454EE2.js} +96 -14
  10. package/dist/{chunk-6QTZVJ7A.js → chunk-C3J4GDW4.js} +188 -24
  11. package/dist/{chunk-HBJSHRY2.js → chunk-C4BCC5X5.js} +17 -1
  12. package/dist/{chunk-T5QQVXK3.js → chunk-DIOF73S2.js} +17 -1
  13. package/dist/{chunk-UEAHMGHW.js → chunk-DQJ5D42H.js} +16 -2
  14. package/dist/{chunk-YOWIYAVA.js → chunk-EBWEKG52.js} +36 -11
  15. package/dist/{chunk-XX5BB7NV.js → chunk-S42XDFKF.js} +36 -11
  16. package/dist/{chunk-LRLKJM3O.js → chunk-UA5NDAHL.js} +16 -2
  17. package/dist/{chunk-YDXQ72MD.js → chunk-V2DUTUNC.js} +1 -1
  18. package/dist/{coordinator-prompt-S6JZD5EF.js → coordinator-prompt-ICF36NUQ.js} +2 -1
  19. package/dist/{coordinator-prompt-6FXVTSFN.js → coordinator-prompt-RBKUNRPR.js} +2 -1
  20. package/dist/{global-workspace-EV4G2WMQ.js → global-workspace-667XLBW6.js} +3 -2
  21. package/dist/{global-workspace-MSX2K27Y.js → global-workspace-S7VLWPWG.js} +3 -2
  22. package/dist/index.cjs +395 -61
  23. package/dist/index.d.cts +25 -2
  24. package/dist/index.d.ts +25 -2
  25. package/dist/index.js +164 -43
  26. package/dist/mcp/run-stdio.cjs +389 -57
  27. package/dist/mcp/run-stdio.js +164 -44
  28. package/dist/{workspaces-AYTBR6KQ.js → workspaces-FPJJXXAE.js} +4 -3
  29. package/dist/{workspaces-3RQQZQRO.js → workspaces-LYIDE2VR.js} +4 -3
  30. package/package.json +1 -1
@@ -10,12 +10,12 @@ import {
10
10
  formatUnknownDetail,
11
11
  looksLikeAgentFailureMessage,
12
12
  parseCursorRunnerLine
13
- } from "./chunk-J5JTEJ5O.js";
13
+ } from "./chunk-3WJAUKIL.js";
14
14
  import {
15
15
  claudeChromeEnabled,
16
16
  loadAppSettings,
17
17
  resolveClaudeExecutable
18
- } from "./chunk-T5QQVXK3.js";
18
+ } from "./chunk-DIOF73S2.js";
19
19
  import {
20
20
  ensureAgentPath,
21
21
  run
@@ -623,6 +623,7 @@ function toCodexMcpConfigArgs(servers) {
623
623
  args.push("-c", `${prefix}.env.${key}=${JSON.stringify(value)}`);
624
624
  }
625
625
  }
626
+ args.push("-c", `${prefix}.default_tools_approval_mode=${JSON.stringify("approve")}`);
626
627
  }
627
628
  return args;
628
629
  }
@@ -839,7 +840,7 @@ var claudeAdapter = {
839
840
  );
840
841
  }
841
842
  const mode = permissionMode(thread);
842
- const { isOrchestratorThread } = await import("./global-workspace-MSX2K27Y.js");
843
+ const { isOrchestratorThread } = await import("./global-workspace-S7VLWPWG.js");
843
844
  const isOrchestrator = isOrchestratorThread(thread);
844
845
  const injectedServers = await buildInjectedMcpServers({
845
846
  includeSideboard: true,
@@ -1099,6 +1100,32 @@ function codexConfigHasNetworkAccess() {
1099
1100
  }
1100
1101
  return false;
1101
1102
  }
1103
+ function unwrapCodexMcpResult(result) {
1104
+ if (result == null) return void 0;
1105
+ if (typeof result === "string") return result;
1106
+ if (typeof result !== "object") return String(result);
1107
+ const rec = result;
1108
+ if (Array.isArray(rec.content)) {
1109
+ const texts = [];
1110
+ for (const item of rec.content) {
1111
+ if (!item || typeof item !== "object") continue;
1112
+ const text = item.text;
1113
+ if (typeof text === "string") texts.push(text);
1114
+ }
1115
+ if (texts.length) return texts.join("\n");
1116
+ }
1117
+ try {
1118
+ return JSON.stringify(result);
1119
+ } catch {
1120
+ return String(result);
1121
+ }
1122
+ }
1123
+ function asRecord(value) {
1124
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1125
+ return value;
1126
+ }
1127
+ return void 0;
1128
+ }
1102
1129
  var codexAdapter = {
1103
1130
  kind: "codex",
1104
1131
  async detect() {
@@ -1189,15 +1216,49 @@ var codexAdapter = {
1189
1216
  }
1190
1217
  if (typeof obj.item === "object" && obj.item !== null) {
1191
1218
  const item = obj.item;
1192
- if (item.type === "error") {
1219
+ const itemType = item.type ?? item.item_type;
1220
+ if (itemType === "error") {
1193
1221
  const detail = item.message?.trim() || extractJsonErrorMessage(obj) || "Codex item error";
1194
1222
  return { type: "stderr", data: detail };
1195
1223
  }
1196
- if (item.type === "agent_message" && item.text) {
1224
+ if (itemType === "agent_message" && item.text) {
1197
1225
  return { type: "stdout", data: item.text };
1198
1226
  }
1227
+ if (itemType === "mcp_tool_call" && item.id && item.server && item.tool) {
1228
+ const name = `mcp__${item.server}__${item.tool}`;
1229
+ const input = asRecord(item.arguments);
1230
+ const events = [
1231
+ { type: "tool_use", id: item.id, name, input }
1232
+ ];
1233
+ const finished = type === "item.completed" || item.status === "completed" || item.status === "failed";
1234
+ if (finished) {
1235
+ const errMsg = item.error && typeof item.error.message === "string" ? item.error.message : void 0;
1236
+ events.push({
1237
+ type: "tool_result",
1238
+ id: item.id,
1239
+ content: unwrapCodexMcpResult(item.result) ?? errMsg,
1240
+ isError: item.status === "failed" || Boolean(errMsg)
1241
+ });
1242
+ }
1243
+ return events.length === 1 ? events[0] : events;
1244
+ }
1245
+ if (itemType === "command_execution" && item.id) {
1246
+ const input = item.command ? { command: item.command } : void 0;
1247
+ const events = [
1248
+ { type: "tool_use", id: item.id, name: "Bash", input }
1249
+ ];
1250
+ if (type === "item.completed" || item.status === "completed" || item.status === "failed") {
1251
+ events.push({
1252
+ type: "tool_result",
1253
+ id: item.id,
1254
+ content: item.aggregated_output,
1255
+ isError: item.status === "failed"
1256
+ });
1257
+ }
1258
+ return events.length === 1 ? events[0] : events;
1259
+ }
1199
1260
  if (item.status === "failed") {
1200
- const detail = item.message?.trim() || extractJsonErrorMessage(item) || `Codex ${item.type ?? "item"} failed`;
1261
+ const detail = item.message?.trim() || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
1201
1262
  return { type: "stderr", data: detail };
1202
1263
  }
1203
1264
  }
@@ -1571,17 +1632,31 @@ var opencodeAdapter = {
1571
1632
  return { type: "stderr", data: detail };
1572
1633
  }
1573
1634
  const sid = typeof obj.sessionID === "string" && obj.sessionID || typeof obj.sessionId === "string" && obj.sessionId || typeof obj.session_id === "string" && obj.session_id;
1574
- if (sid) return { type: "session_id", data: sid };
1635
+ if (sid && (!obj.type || obj.type === "step_start" || obj.type === "session")) {
1636
+ return { type: "session_id", data: sid };
1637
+ }
1575
1638
  if (obj.type === "text") {
1576
1639
  const text = obj.part?.text ?? obj.text;
1577
1640
  if (text) return { type: "stdout", data: text };
1578
1641
  }
1579
1642
  if (obj.type === "tool_use") {
1580
1643
  const part = obj.part;
1581
- const id = part?.id ?? obj.id ?? `tool-${Date.now()}`;
1582
- const name = part?.name ?? part?.tool ?? obj.name ?? obj.tool ?? "tool";
1583
- const input = part?.input ?? obj.input;
1584
- return { type: "tool_use", id, name, input };
1644
+ const id = part?.callID ?? part?.id ?? obj.id ?? `tool-${Date.now()}`;
1645
+ const name = part?.tool ?? part?.name ?? obj.tool ?? obj.name ?? "tool";
1646
+ const state = part?.state;
1647
+ const input = (state?.input && typeof state.input === "object" ? state.input : void 0) ?? part?.input ?? obj.input;
1648
+ const events = [{ type: "tool_use", id, name, input }];
1649
+ const output = state?.output;
1650
+ if (output != null || state?.status === "completed" || state?.status === "error") {
1651
+ const content = typeof output === "string" ? output : output != null ? JSON.stringify(output) : formatUnknownDetail(state?.error) || void 0;
1652
+ events.push({
1653
+ type: "tool_result",
1654
+ id,
1655
+ content,
1656
+ isError: state?.status === "error" || state?.status === "failed"
1657
+ });
1658
+ }
1659
+ return events.length === 1 ? events[0] : events;
1585
1660
  }
1586
1661
  if (obj.type === "tool_result") {
1587
1662
  const part = obj.part;
@@ -1609,6 +1684,7 @@ var opencodeAdapter = {
1609
1684
  }
1610
1685
  },
1611
1686
  async resolveSessionId(worktreePath, cached) {
1687
+ const cachedId = cached?.trim() || null;
1612
1688
  const listed = await run(
1613
1689
  "opencode",
1614
1690
  ["session", "list", "--format", "json"],
@@ -1620,15 +1696,21 @@ var opencodeAdapter = {
1620
1696
  if (Array.isArray(sessions) && sessions.length > 0) {
1621
1697
  const norm = (p) => p.replace(/\/+$/, "");
1622
1698
  const wt = norm(worktreePath);
1623
- const match = sessions.find(
1699
+ const forWorktree = sessions.filter(
1624
1700
  (s) => s.directory && norm(s.directory) === wt || s.path && norm(s.path) === wt
1625
1701
  );
1626
- if (match?.id) return match.id;
1702
+ if (cachedId && forWorktree.some((s) => s.id === cachedId)) {
1703
+ return cachedId;
1704
+ }
1705
+ if (cachedId && sessions.some((s) => s.id === cachedId)) {
1706
+ return cachedId;
1707
+ }
1708
+ return null;
1627
1709
  }
1628
1710
  } catch {
1629
1711
  }
1630
1712
  }
1631
- return cached;
1713
+ return cachedId;
1632
1714
  },
1633
1715
  async buildAttach(thread) {
1634
1716
  const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
@@ -7,15 +7,15 @@ import {
7
7
  ensureConnectedBrightsyTeamTokens,
8
8
  loadBrightsyConfig
9
9
  } from "./chunk-H6GGDLYS.js";
10
- import {
11
- claudeChromeEnabled,
12
- loadAppSettings,
13
- resolveClaudeExecutable
14
- } from "./chunk-HBJSHRY2.js";
15
10
  import {
16
11
  ensureAgentPath,
17
12
  run
18
13
  } from "./chunk-ZNM4MAN4.js";
14
+ import {
15
+ claudeChromeEnabled,
16
+ loadAppSettings,
17
+ resolveClaudeExecutable
18
+ } from "./chunk-C4BCC5X5.js";
19
19
 
20
20
  // src/agents/brightsy-targets.ts
21
21
  function encodeBrightsyTarget(type, id, accountId) {
@@ -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;
@@ -688,6 +693,7 @@ function toCodexMcpConfigArgs(servers) {
688
693
  args.push("-c", `${prefix}.env.${key}=${JSON.stringify(value)}`);
689
694
  }
690
695
  }
696
+ args.push("-c", `${prefix}.default_tools_approval_mode=${JSON.stringify("approve")}`);
691
697
  }
692
698
  return args;
693
699
  }
@@ -901,7 +907,7 @@ var claudeAdapter = {
901
907
  );
902
908
  }
903
909
  const mode = permissionMode(thread);
904
- const { isOrchestratorThread } = await import("./global-workspace-EV4G2WMQ.js");
910
+ const { isOrchestratorThread } = await import("./global-workspace-667XLBW6.js");
905
911
  const isOrchestrator = isOrchestratorThread(thread);
906
912
  const injectedServers = await buildInjectedMcpServers({
907
913
  includeSideboard: true,
@@ -1161,6 +1167,32 @@ function codexConfigHasNetworkAccess() {
1161
1167
  }
1162
1168
  return false;
1163
1169
  }
1170
+ function unwrapCodexMcpResult(result) {
1171
+ if (result == null) return void 0;
1172
+ if (typeof result === "string") return result;
1173
+ if (typeof result !== "object") return String(result);
1174
+ const rec = result;
1175
+ if (Array.isArray(rec.content)) {
1176
+ const texts = [];
1177
+ for (const item of rec.content) {
1178
+ if (!item || typeof item !== "object") continue;
1179
+ const text = item.text;
1180
+ if (typeof text === "string") texts.push(text);
1181
+ }
1182
+ if (texts.length) return texts.join("\n");
1183
+ }
1184
+ try {
1185
+ return JSON.stringify(result);
1186
+ } catch {
1187
+ return String(result);
1188
+ }
1189
+ }
1190
+ function asRecord(value) {
1191
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1192
+ return value;
1193
+ }
1194
+ return void 0;
1195
+ }
1164
1196
  var codexAdapter = {
1165
1197
  kind: "codex",
1166
1198
  async detect() {
@@ -1251,15 +1283,49 @@ var codexAdapter = {
1251
1283
  }
1252
1284
  if (typeof obj.item === "object" && obj.item !== null) {
1253
1285
  const item = obj.item;
1254
- if (item.type === "error") {
1286
+ const itemType = item.type ?? item.item_type;
1287
+ if (itemType === "error") {
1255
1288
  const detail = item.message?.trim() || extractJsonErrorMessage(obj) || "Codex item error";
1256
1289
  return { type: "stderr", data: detail };
1257
1290
  }
1258
- if (item.type === "agent_message" && item.text) {
1291
+ if (itemType === "agent_message" && item.text) {
1259
1292
  return { type: "stdout", data: item.text };
1260
1293
  }
1294
+ if (itemType === "mcp_tool_call" && item.id && item.server && item.tool) {
1295
+ const name = `mcp__${item.server}__${item.tool}`;
1296
+ const input = asRecord(item.arguments);
1297
+ const events = [
1298
+ { type: "tool_use", id: item.id, name, input }
1299
+ ];
1300
+ const finished = type === "item.completed" || item.status === "completed" || item.status === "failed";
1301
+ if (finished) {
1302
+ const errMsg = item.error && typeof item.error.message === "string" ? item.error.message : void 0;
1303
+ events.push({
1304
+ type: "tool_result",
1305
+ id: item.id,
1306
+ content: unwrapCodexMcpResult(item.result) ?? errMsg,
1307
+ isError: item.status === "failed" || Boolean(errMsg)
1308
+ });
1309
+ }
1310
+ return events.length === 1 ? events[0] : events;
1311
+ }
1312
+ if (itemType === "command_execution" && item.id) {
1313
+ const input = item.command ? { command: item.command } : void 0;
1314
+ const events = [
1315
+ { type: "tool_use", id: item.id, name: "Bash", input }
1316
+ ];
1317
+ if (type === "item.completed" || item.status === "completed" || item.status === "failed") {
1318
+ events.push({
1319
+ type: "tool_result",
1320
+ id: item.id,
1321
+ content: item.aggregated_output,
1322
+ isError: item.status === "failed"
1323
+ });
1324
+ }
1325
+ return events.length === 1 ? events[0] : events;
1326
+ }
1261
1327
  if (item.status === "failed") {
1262
- const detail = item.message?.trim() || extractJsonErrorMessage(item) || `Codex ${item.type ?? "item"} failed`;
1328
+ const detail = item.message?.trim() || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
1263
1329
  return { type: "stderr", data: detail };
1264
1330
  }
1265
1331
  }
@@ -1350,6 +1416,75 @@ function usageFromCursor(usage) {
1350
1416
  cacheWriteTokens: usage.cacheWriteTokens ? Number(usage.cacheWriteTokens) : void 0
1351
1417
  };
1352
1418
  }
1419
+ function asRecord2(value) {
1420
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1421
+ return value;
1422
+ }
1423
+ return void 0;
1424
+ }
1425
+ function normalizeCursorToolCall(name, args) {
1426
+ const raw = asRecord2(args);
1427
+ const toolName = typeof raw?.toolName === "string" && raw.toolName.trim() ? raw.toolName.trim() : null;
1428
+ const looksLikeMcp = name === "mcp" || toolName != null && (typeof raw?.providerIdentifier === "string" || asRecord2(raw?.args) != null);
1429
+ if (looksLikeMcp && toolName) {
1430
+ const providerRaw = typeof raw.providerIdentifier === "string" && raw.providerIdentifier.trim() ? raw.providerIdentifier.trim() : "sideboard";
1431
+ const provider = providerRaw.replace(/[^a-zA-Z0-9_-]/g, "_");
1432
+ const nested = asRecord2(raw.args);
1433
+ return {
1434
+ name: `mcp__${provider}__${toolName}`,
1435
+ input: nested ?? { toolName }
1436
+ };
1437
+ }
1438
+ return { name, input: raw };
1439
+ }
1440
+ function unwrapCursorToolResult(result) {
1441
+ if (result == null) return void 0;
1442
+ if (typeof result === "string") return result;
1443
+ const rec = asRecord2(result);
1444
+ if (!rec) {
1445
+ try {
1446
+ return JSON.stringify(result);
1447
+ } catch {
1448
+ return String(result);
1449
+ }
1450
+ }
1451
+ const collectTexts = (items) => {
1452
+ const texts = [];
1453
+ for (const item of items) {
1454
+ const row = asRecord2(item);
1455
+ if (!row) continue;
1456
+ if (typeof row.text === "string") {
1457
+ texts.push(row.text);
1458
+ continue;
1459
+ }
1460
+ const nested = asRecord2(row.text);
1461
+ if (typeof nested?.text === "string") texts.push(nested.text);
1462
+ }
1463
+ return texts;
1464
+ };
1465
+ const value = asRecord2(rec.value);
1466
+ if (value && Array.isArray(value.content)) {
1467
+ const texts = collectTexts(value.content);
1468
+ if (texts.length) return texts.join("\n");
1469
+ }
1470
+ if (Array.isArray(rec.content)) {
1471
+ const texts = collectTexts(rec.content);
1472
+ if (texts.length) return texts.join("\n");
1473
+ }
1474
+ try {
1475
+ return JSON.stringify(result);
1476
+ } catch {
1477
+ return String(result);
1478
+ }
1479
+ }
1480
+ function cursorToolResultIsError(status, result) {
1481
+ if (status === "error") return true;
1482
+ const rec = asRecord2(result);
1483
+ if (!rec) return false;
1484
+ if (rec.status === "error") return true;
1485
+ const value = asRecord2(rec.value);
1486
+ return value?.isError === true;
1487
+ }
1353
1488
  function cursorSdkMessageToEvents(msg) {
1354
1489
  if (!msg?.type) return [];
1355
1490
  if (msg.type === "system" && msg.agent_id) {
@@ -1364,35 +1499,42 @@ function cursorSdkMessageToEvents(msg) {
1364
1499
  if (block?.type === "text" && block.text) {
1365
1500
  out.push({ type: "stdout", data: block.text });
1366
1501
  } else if (block?.type === "tool_use" && block.id && block.name) {
1502
+ const normalized = normalizeCursorToolCall(block.name, block.input);
1367
1503
  out.push({
1368
1504
  type: "tool_use",
1369
1505
  id: block.id,
1370
- name: block.name,
1371
- input: block.input && typeof block.input === "object" ? block.input : void 0
1506
+ name: normalized.name,
1507
+ input: normalized.input
1372
1508
  });
1373
1509
  }
1374
1510
  }
1375
1511
  return out;
1376
1512
  }
1377
1513
  if (msg.type === "tool_call" && msg.call_id && msg.name) {
1514
+ const normalized = normalizeCursorToolCall(msg.name, msg.args);
1378
1515
  if (msg.status === "running") {
1379
1516
  return [
1380
1517
  {
1381
1518
  type: "tool_use",
1382
1519
  id: msg.call_id,
1383
- name: msg.name,
1384
- input: msg.args && typeof msg.args === "object" ? msg.args : void 0
1520
+ name: normalized.name,
1521
+ input: normalized.input
1385
1522
  }
1386
1523
  ];
1387
1524
  }
1388
1525
  if (msg.status === "completed" || msg.status === "error") {
1389
- const content = typeof msg.result === "string" ? msg.result : msg.result != null ? JSON.stringify(msg.result) : void 0;
1390
1526
  return [
1527
+ {
1528
+ type: "tool_use",
1529
+ id: msg.call_id,
1530
+ name: normalized.name,
1531
+ input: normalized.input
1532
+ },
1391
1533
  {
1392
1534
  type: "tool_result",
1393
1535
  id: msg.call_id,
1394
- content,
1395
- isError: msg.status === "error"
1536
+ content: unwrapCursorToolResult(msg.result),
1537
+ isError: cursorToolResultIsError(msg.status, msg.result)
1396
1538
  }
1397
1539
  ];
1398
1540
  }
@@ -1728,17 +1870,31 @@ var opencodeAdapter = {
1728
1870
  return { type: "stderr", data: detail };
1729
1871
  }
1730
1872
  const sid = typeof obj.sessionID === "string" && obj.sessionID || typeof obj.sessionId === "string" && obj.sessionId || typeof obj.session_id === "string" && obj.session_id;
1731
- if (sid) return { type: "session_id", data: sid };
1873
+ if (sid && (!obj.type || obj.type === "step_start" || obj.type === "session")) {
1874
+ return { type: "session_id", data: sid };
1875
+ }
1732
1876
  if (obj.type === "text") {
1733
1877
  const text = obj.part?.text ?? obj.text;
1734
1878
  if (text) return { type: "stdout", data: text };
1735
1879
  }
1736
1880
  if (obj.type === "tool_use") {
1737
1881
  const part = obj.part;
1738
- const id = part?.id ?? obj.id ?? `tool-${Date.now()}`;
1739
- const name = part?.name ?? part?.tool ?? obj.name ?? obj.tool ?? "tool";
1740
- const input = part?.input ?? obj.input;
1741
- return { type: "tool_use", id, name, input };
1882
+ const id = part?.callID ?? part?.id ?? obj.id ?? `tool-${Date.now()}`;
1883
+ const name = part?.tool ?? part?.name ?? obj.tool ?? obj.name ?? "tool";
1884
+ const state = part?.state;
1885
+ const input = (state?.input && typeof state.input === "object" ? state.input : void 0) ?? part?.input ?? obj.input;
1886
+ const events = [{ type: "tool_use", id, name, input }];
1887
+ const output = state?.output;
1888
+ if (output != null || state?.status === "completed" || state?.status === "error") {
1889
+ const content = typeof output === "string" ? output : output != null ? JSON.stringify(output) : formatUnknownDetail(state?.error) || void 0;
1890
+ events.push({
1891
+ type: "tool_result",
1892
+ id,
1893
+ content,
1894
+ isError: state?.status === "error" || state?.status === "failed"
1895
+ });
1896
+ }
1897
+ return events.length === 1 ? events[0] : events;
1742
1898
  }
1743
1899
  if (obj.type === "tool_result") {
1744
1900
  const part = obj.part;
@@ -1766,6 +1922,7 @@ var opencodeAdapter = {
1766
1922
  }
1767
1923
  },
1768
1924
  async resolveSessionId(worktreePath, cached) {
1925
+ const cachedId = cached?.trim() || null;
1769
1926
  const listed = await run(
1770
1927
  "opencode",
1771
1928
  ["session", "list", "--format", "json"],
@@ -1777,15 +1934,21 @@ var opencodeAdapter = {
1777
1934
  if (Array.isArray(sessions) && sessions.length > 0) {
1778
1935
  const norm = (p) => p.replace(/\/+$/, "");
1779
1936
  const wt = norm(worktreePath);
1780
- const match = sessions.find(
1937
+ const forWorktree = sessions.filter(
1781
1938
  (s) => s.directory && norm(s.directory) === wt || s.path && norm(s.path) === wt
1782
1939
  );
1783
- if (match?.id) return match.id;
1940
+ if (cachedId && forWorktree.some((s) => s.id === cachedId)) {
1941
+ return cachedId;
1942
+ }
1943
+ if (cachedId && sessions.some((s) => s.id === cachedId)) {
1944
+ return cachedId;
1945
+ }
1946
+ return null;
1784
1947
  }
1785
1948
  } catch {
1786
1949
  }
1787
1950
  }
1788
- return cached;
1951
+ return cachedId;
1789
1952
  },
1790
1953
  async buildAttach(thread) {
1791
1954
  const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
@@ -2197,6 +2360,7 @@ function allAdapters() {
2197
2360
  export {
2198
2361
  pushTurnStderr,
2199
2362
  summarizeTurnStderr,
2363
+ looksLikeInvalidAgentSession,
2200
2364
  looksLikeAgentFailureMessage,
2201
2365
  fallbackTurnFailDetail,
2202
2366
  humanizeAgentFailDetail,
@@ -323,6 +323,16 @@ function resolveThreadDefaults(settings = loadAppSettings()) {
323
323
  fast: getDefaultFast(settings)
324
324
  };
325
325
  }
326
+ function resolveNewThreadOptions(overrides = {}, settings = loadAppSettings()) {
327
+ const defaults = resolveThreadDefaults(settings);
328
+ const effort = overrides.effort === void 0 || overrides.effort === null ? defaults.effort : normalizeThinkingEffort(overrides.effort) ?? defaults.effort;
329
+ return {
330
+ agent: overrides.agent ?? defaults.agent,
331
+ model: overrides.model === void 0 ? defaults.model : overrides.model?.trim() || null,
332
+ effort,
333
+ fast: overrides.fast === void 0 || overrides.fast === null ? defaults.fast : Boolean(overrides.fast)
334
+ };
335
+ }
326
336
  function isLinearConnected(settings = loadAppSettings()) {
327
337
  return Boolean(settings.integrations.linearApiKey?.trim());
328
338
  }
@@ -342,7 +352,12 @@ function brightsyCloudConnectEnabled(settings = loadAppSettings()) {
342
352
  return Boolean(settings.brightsy.cloudConnectEnabled);
343
353
  }
344
354
  function brightsyCloudConnectAgent(settings = loadAppSettings()) {
345
- return settings.brightsy.cloudConnectAgent ?? "claude";
355
+ const fallback = settings.brightsy.cloudConnectAgent && CLOUD_CONNECT_AGENTS.has(settings.brightsy.cloudConnectAgent) ? settings.brightsy.cloudConnectAgent : "claude";
356
+ const preferred = getDefaultAgent(settings);
357
+ if (CLOUD_CONNECT_AGENTS.has(preferred)) {
358
+ return preferred;
359
+ }
360
+ return fallback;
346
361
  }
347
362
  function updateAdvancedSettings(patch) {
348
363
  const current = loadAppSettings();
@@ -470,6 +485,7 @@ export {
470
485
  getDefaultEffort,
471
486
  getDefaultFast,
472
487
  resolveThreadDefaults,
488
+ resolveNewThreadOptions,
473
489
  isLinearConnected,
474
490
  getIssueSource,
475
491
  resolveEffectiveIssueSource,
@@ -321,6 +321,16 @@ function resolveThreadDefaults(settings = loadAppSettings()) {
321
321
  fast: getDefaultFast(settings)
322
322
  };
323
323
  }
324
+ function resolveNewThreadOptions(overrides = {}, settings = loadAppSettings()) {
325
+ const defaults = resolveThreadDefaults(settings);
326
+ const effort = overrides.effort === void 0 || overrides.effort === null ? defaults.effort : normalizeThinkingEffort(overrides.effort) ?? defaults.effort;
327
+ return {
328
+ agent: overrides.agent ?? defaults.agent,
329
+ model: overrides.model === void 0 ? defaults.model : overrides.model?.trim() || null,
330
+ effort,
331
+ fast: overrides.fast === void 0 || overrides.fast === null ? defaults.fast : Boolean(overrides.fast)
332
+ };
333
+ }
324
334
  function isLinearConnected(settings = loadAppSettings()) {
325
335
  return Boolean(settings.integrations.linearApiKey?.trim());
326
336
  }
@@ -340,7 +350,12 @@ function brightsyCloudConnectEnabled(settings = loadAppSettings()) {
340
350
  return Boolean(settings.brightsy.cloudConnectEnabled);
341
351
  }
342
352
  function brightsyCloudConnectAgent(settings = loadAppSettings()) {
343
- return settings.brightsy.cloudConnectAgent ?? "claude";
353
+ const fallback = settings.brightsy.cloudConnectAgent && CLOUD_CONNECT_AGENTS.has(settings.brightsy.cloudConnectAgent) ? settings.brightsy.cloudConnectAgent : "claude";
354
+ const preferred = getDefaultAgent(settings);
355
+ if (CLOUD_CONNECT_AGENTS.has(preferred)) {
356
+ return preferred;
357
+ }
358
+ return fallback;
344
359
  }
345
360
  function updateAdvancedSettings(patch) {
346
361
  const current = loadAppSettings();
@@ -468,6 +483,7 @@ export {
468
483
  getDefaultEffort,
469
484
  getDefaultFast,
470
485
  resolveThreadDefaults,
486
+ resolveNewThreadOptions,
471
487
  isLinearConnected,
472
488
  getIssueSource,
473
489
  resolveEffectiveIssueSource,
@@ -3,6 +3,9 @@
3
3
  import {
4
4
  resolveGithubRepoSlug
5
5
  } from "./chunk-XOU6HNQJ.js";
6
+ import {
7
+ resolveThreadDefaults
8
+ } from "./chunk-C4BCC5X5.js";
6
9
  import {
7
10
  globalAgentCwd,
8
11
  sideboardReposDir
@@ -45,12 +48,12 @@ var COORDINATOR_TOOL_PLAYBOOK = [
45
48
  "- list_workspaces \u2014 registered repos (path + github slug when known)",
46
49
  "- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces (issues: Linear API or GitHub Issues)",
47
50
  "- get_pr_stack / open_pr_stack_layers / add_stack_layer / create_pr_stack \u2014 GitHub stacked PRs (`gh stack`); one worktree per layer",
48
- "- list_models \u2014 only when you need a specific model (rare); otherwise leave model unset = Auto",
51
+ "- list_models \u2014 only when you need a specific model (rare); otherwise omit model so Account defaults apply",
49
52
  "- list_threads / get_thread \u2014 fleet status (what is going on)",
50
53
  "Workspaces:",
51
54
  "- add_workspace / remove_workspace \u2014 register or unregister a git repo",
52
55
  "Worktree threads (chats):",
53
- "- create_thread \u2014 create a worktree + chat from branch | pr | ticket; pass repoPath + parentThreadId",
56
+ "- create_thread \u2014 create a worktree + chat from branch | pr | ticket; pass repoPath + parentThreadId; omit agent and model to use Sideboard Account defaults (Settings \u2192 Default agent, model & effort)",
54
57
  "- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
55
58
  "- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
56
59
  "- send_to_thread \u2014 queue a prompt (start/continue a chat turn); pass force_stop: true to interrupt mid-turn / clear stale queued prompts before replacing with a new request",
@@ -68,6 +71,11 @@ var COORDINATOR_TOOL_PLAYBOOK = [
68
71
  "Thread links in replies: when mentioning a chat/thread for the user, include a markdown link `[Title](sideboard://thread/<id>)` using the full id (or the link field from create_thread / list_threads). Sideboard renders these as clickable opens.",
69
72
  "Bash / Read / etc: allowed for (1) inspecting target worktrees / registered repo paths from MCP, and (2) greenfield setup under ~/sideboard/repos (git clone, gh repo create, git init+remote). Never git init/clone *inside* this synthetic home cwd \u2014 emptiness here is expected, not a bug."
70
73
  ].join("\n");
74
+ function accountDefaultsPlaybookLine() {
75
+ const d = resolveThreadDefaults();
76
+ const model = d.model?.trim() || "Auto";
77
+ return `- Account defaults for create_thread (omit agent/model to use these): agent=${d.agent}, model=${model}, effort=${d.effort}`;
78
+ }
71
79
  function coordinatorTurnReminder(opts) {
72
80
  const goal = opts.goal?.trim();
73
81
  return [
@@ -77,6 +85,7 @@ function coordinatorTurnReminder(opts) {
77
85
  "- Registered workspaces / child threads are the fleet you manage via Sideboard MCP.",
78
86
  `- Parent thread id (pass as parentThreadId when creating children): ${opts.parentId}`,
79
87
  goal ? `- Goal / title: ${goal}` : null,
88
+ accountDefaultsPlaybookLine(),
80
89
  `- For "what's going on": call list_threads (and list_workspaces if needed). Summarize fleet status \u2014 do not ls/git-status this synthetic home.`,
81
90
  "- Existing repo: create_thread on a repoPath \u2192 send_to_thread \u2192 wait_for_turn.",
82
91
  "- New repo: Bash (clone or gh repo create under ~/sideboard/repos/<name>) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 draft PR.",
@@ -99,9 +108,12 @@ function ensureGlobalCoordinatorCwd() {
99
108
  "",
100
109
  COORDINATOR_TOOL_PLAYBOOK,
101
110
  "",
111
+ accountDefaultsPlaybookLine(),
112
+ "",
102
113
  coordinatorGreenfieldPlaybook(reposDir),
103
114
  "",
104
115
  "When creating threads, pass `repoPath` from `list_workspaces` (or the path you just registered) and `parentThreadId` for children.",
116
+ "Omit `agent` / `model` on `create_thread` unless you have a reason to override Account defaults.",
105
117
  "Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn.",
106
118
  "Typical flow (new app): Bash create/clone under repos dir \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 draft PR via worktree agent.",
107
119
  "Always ask worktree agents to open draft PRs (`send_to_thread` + `gh pr create --draft -R <origin>`); never open PRs from the orchestrator."
@@ -127,8 +139,10 @@ function coordinatorSystemPrompt(opts) {
127
139
  "You operate across ALL registered workspaces below.",
128
140
  "You have no project git home \u2014 this process cwd is synthetic and empty on purpose.",
129
141
  COORDINATOR_TOOL_PLAYBOOK,
142
+ accountDefaultsPlaybookLine(),
130
143
  coordinatorGreenfieldPlaybook(reposDir),
131
144
  "When creating threads, pass the correct repoPath for the target workspace and parentThreadId for children.",
145
+ "Omit agent/model on create_thread unless you need to override Account defaults.",
132
146
  "Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 send_to_thread (ask for `gh pr create --draft -R <origin-owner/name>` using the workspace github slug) \u2192 wait_for_turn. Never target upstream. Never open PRs from the orchestrator.",
133
147
  "Typical flow (new app): Bash under repos dir (clone or gh repo create) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 draft PR via worktree agent.",
134
148
  `Goal: ${opts.goal}`,