openfox 1.6.75 → 1.6.76

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 (65) hide show
  1. package/dist/{ask-3RK5YJZE.js → ask-5SSOA6SZ.js} +2 -2
  2. package/dist/{auth-LZZX63KI.js → auth-56SIRACI.js} +3 -6
  3. package/dist/auto-compaction-V3PA77WG.js +27 -0
  4. package/dist/{branch.api-XADFZZAA.js → branch.api-PWFW26KC.js} +2 -2
  5. package/dist/{chat-handler-KYMMXPP6.js → chat-handler-7DKHGTVO.js} +31 -29
  6. package/dist/{chunk-5UTTLO4D.js → chunk-5ZD3GZTK.js} +89 -49
  7. package/dist/{chunk-AFATQ5LJ.js → chunk-B5AP3RSV.js} +1 -1
  8. package/dist/{chunk-22CTURMH.js → chunk-BJYPTN5S.js} +1 -1
  9. package/dist/{chunk-DLINTLB7.js → chunk-BSTVRSV6.js} +7 -5
  10. package/dist/{chunk-7JPKRM6M.js → chunk-CMQCO27Y.js} +22 -12
  11. package/dist/{chunk-R4HADRYO.js → chunk-CQGTEGKL.js} +1 -1
  12. package/dist/{chunk-J5DV33SS.js → chunk-CUDAT6SS.js} +46 -18
  13. package/dist/{chunk-ETIXH35K.js → chunk-H5EICXF3.js} +499 -277
  14. package/dist/{chunk-XIZ6B6IS.js → chunk-K2V7EW5F.js} +541 -299
  15. package/dist/{chunk-PNBH3RAX.js → chunk-K44MW7JJ.js} +1 -1
  16. package/dist/{chunk-BLNFJ22S.js → chunk-KIOUKC3Z.js} +6 -4
  17. package/dist/{chunk-4CQ7CUQ6.js → chunk-LCQ3MPXD.js} +5 -5
  18. package/dist/{chunk-CTAIXOZJ.js → chunk-NDJ6FKSP.js} +1 -1
  19. package/dist/{chunk-IA4O65CR.js → chunk-NHJ2GVCF.js} +100 -68
  20. package/dist/{chunk-GQZGIMJO.js → chunk-OXI26S7U.js} +12 -7
  21. package/dist/{chunk-NBU6KIOD.js → chunk-PBGOZMVY.js} +4 -4
  22. package/dist/{chunk-B7E3BICY.js → chunk-RGRBWDZP.js} +2 -4
  23. package/dist/{chunk-VIGOXEZG.js → chunk-RQ4XSKUR.js} +15 -16
  24. package/dist/{chunk-KFBIHS3S.js → chunk-STYHKCG7.js} +20 -14
  25. package/dist/{chunk-55Z3DJ7G.js → chunk-TGWEH2BC.js} +10 -11
  26. package/dist/{chunk-TYUNDOX2.js → chunk-UKMRZDWM.js} +90 -41
  27. package/dist/{chunk-PFRQO5Z3.js → chunk-VAMTEAYI.js} +49 -27
  28. package/dist/{chunk-574HZVLE.js → chunk-VRGRAQDG.js} +2 -2
  29. package/dist/{chunk-JQBTYHUR.js → chunk-WR6QCJJO.js} +53 -15
  30. package/dist/{chunk-RBPOAAIZ.js → chunk-XKIEDGQF.js} +22 -18
  31. package/dist/cli/dev.js +2 -2
  32. package/dist/cli/index.js +2 -2
  33. package/dist/{config-6T4EHAP2.js → config-5CONAOL7.js} +7 -7
  34. package/dist/{events-LKEZ3YCW.js → events-BDXQOC7F.js} +6 -6
  35. package/dist/{folding-JN2WT44N.js → folding-2HW7FIKL.js} +2 -2
  36. package/dist/{inspect-proxy-Y4MRAVB7.js → inspect-proxy-Y75AXMRX.js} +3 -3
  37. package/dist/{manager-HM2J5VMW.js → manager-W7N3XQ4Q.js} +3 -3
  38. package/dist/orchestrator-KCHEENHK.js +43 -0
  39. package/dist/package.json +19 -3
  40. package/dist/{paths-ZRI56O63.js → paths-X46PPOI2.js} +2 -2
  41. package/dist/{processor-23O4HPSS.js → processor-6TS37IYH.js} +15 -11
  42. package/dist/{project-creator-LASKNQPA.js → project-creator-VD7MLOWE.js} +8 -5
  43. package/dist/{projects-HEUOWNSR.js → projects-XLMSDFTQ.js} +4 -4
  44. package/dist/{protocol-5AWNGFLH.js → protocol-4CTV7OZC.js} +3 -3
  45. package/dist/{protocol-DRBnujwe.d.ts → protocol-4xbfAlGO.d.ts} +3 -0
  46. package/dist/{provider-AKN355YH.js → provider-ESEBV3LL.js} +15 -11
  47. package/dist/{pwa-GHQCMCIU.js → pwa-76XP2DY2.js} +2 -2
  48. package/dist/{runtime-config-ZCK74XKM.js → runtime-config-CBJJJGBD.js} +2 -2
  49. package/dist/{serve-TW63YCNQ.js → serve-OLDABBV3.js} +29 -27
  50. package/dist/server/index.d.ts +6 -1
  51. package/dist/server/index.js +22 -22
  52. package/dist/server/public/__inspect__.js +2 -1
  53. package/dist/{service-74Z7JK2J.js → service-D6LC3CAM.js} +3 -2
  54. package/dist/{settings-NI4ITGV6.js → settings-TQNQB56H.js} +4 -4
  55. package/dist/shared/index.d.ts +2 -2
  56. package/dist/shared/index.js +2 -2
  57. package/dist/{store-2IF3ZSLD.js → store-OQ45KONN.js} +2 -2
  58. package/dist/{tools-RUAY6EVI.js → tools-BHYHS3RY.js} +18 -18
  59. package/dist/{vision-fallback-AXH3BGJC.js → vision-fallback-ED27LH6C.js} +3 -3
  60. package/dist/web/assets/{index-CWdKiSP8.js → index-DAuZ02-Q.js} +57 -57
  61. package/dist/web/index.html +1 -1
  62. package/dist/web/sw.js +1 -1
  63. package/package.json +19 -3
  64. package/dist/auto-compaction-OW4P2QWQ.js +0 -27
  65. package/dist/orchestrator-QP4O7MUM.js +0 -43
@@ -3,13 +3,13 @@ import {
3
3
  deleteSetting,
4
4
  getSetting,
5
5
  setSetting
6
- } from "./chunk-GQZGIMJO.js";
6
+ } from "./chunk-OXI26S7U.js";
7
7
  import {
8
8
  getProject
9
- } from "./chunk-7JPKRM6M.js";
9
+ } from "./chunk-CMQCO27Y.js";
10
10
  import {
11
11
  startInspectProxy
12
- } from "./chunk-RBPOAAIZ.js";
12
+ } from "./chunk-XKIEDGQF.js";
13
13
  import {
14
14
  createProcess,
15
15
  getPlatformShell,
@@ -18,22 +18,22 @@ import {
18
18
  getSessionProcesses,
19
19
  startProcessCommand,
20
20
  stopProcess
21
- } from "./chunk-NBU6KIOD.js";
21
+ } from "./chunk-PBGOZMVY.js";
22
22
  import {
23
23
  getMaxPerSession,
24
24
  getSessionProcessCount
25
- } from "./chunk-574HZVLE.js";
25
+ } from "./chunk-VRGRAQDG.js";
26
26
  import {
27
27
  buildModelParams,
28
28
  getBackendCapabilities,
29
29
  getModelProfile,
30
30
  streamWithSegments
31
- } from "./chunk-J5DV33SS.js";
31
+ } from "./chunk-CUDAT6SS.js";
32
32
  import {
33
33
  getContextMessages,
34
34
  getCurrentContextWindowId,
35
35
  getEventStore
36
- } from "./chunk-5UTTLO4D.js";
36
+ } from "./chunk-5ZD3GZTK.js";
37
37
  import {
38
38
  createChatDoneMessage,
39
39
  createChatMessageMessage,
@@ -42,20 +42,20 @@ import {
42
42
  createChatToolOutputMessage,
43
43
  createChatVisionFallbackMessage,
44
44
  createQueueStateMessage
45
- } from "./chunk-KFBIHS3S.js";
45
+ } from "./chunk-STYHKCG7.js";
46
46
  import {
47
47
  AskUserInterrupt,
48
48
  askUserTool
49
- } from "./chunk-22CTURMH.js";
49
+ } from "./chunk-BJYPTN5S.js";
50
50
  import {
51
51
  getGlobalConfigDir
52
- } from "./chunk-R4HADRYO.js";
52
+ } from "./chunk-CQGTEGKL.js";
53
53
  import {
54
54
  getRuntimeConfig
55
- } from "./chunk-AFATQ5LJ.js";
55
+ } from "./chunk-B5AP3RSV.js";
56
56
  import {
57
57
  logger
58
- } from "./chunk-PNBH3RAX.js";
58
+ } from "./chunk-K44MW7JJ.js";
59
59
 
60
60
  // src/server/context/instructions.ts
61
61
  import { readFile, access } from "fs/promises";
@@ -147,6 +147,13 @@ async function fileExists(path) {
147
147
  return false;
148
148
  }
149
149
  }
150
+ function toInjectedFiles(files) {
151
+ return files.map((file) => ({
152
+ path: file.path,
153
+ content: file.content ?? "",
154
+ source: file.source
155
+ }));
156
+ }
150
157
 
151
158
  // src/server/context/compactor.ts
152
159
  function shouldCompact(currentTokens, maxTokens, threshold) {
@@ -403,6 +410,7 @@ function minimalMessageToRequestContextMessage(message, source = "history") {
403
410
  role: message.role,
404
411
  content: message.content,
405
412
  source,
413
+ ...message.thinkingContent ? { thinkingContent: message.thinkingContent } : {},
406
414
  ...spreadMessageProps(message)
407
415
  };
408
416
  }
@@ -410,6 +418,7 @@ function messageToMinimal(message) {
410
418
  return {
411
419
  role: message.role,
412
420
  content: message.content,
421
+ ...message.thinkingContent ? { thinkingContent: message.thinkingContent } : {},
413
422
  ...spreadMessageProps(message)
414
423
  };
415
424
  }
@@ -475,12 +484,7 @@ function buildAssemblyInput(systemPrompt, baseInput) {
475
484
  function assembleAgentRequest(input) {
476
485
  const { agentDef, subAgentDefs, ...baseInput } = input;
477
486
  if (agentDef.metadata.subagent) {
478
- const systemPrompt2 = buildSubAgentSystemPrompt(
479
- baseInput.workdir,
480
- agentDef,
481
- baseInput.skills,
482
- baseInput.modelName
483
- );
487
+ const systemPrompt2 = buildSubAgentSystemPrompt(baseInput.workdir, agentDef, baseInput.skills, baseInput.modelName);
484
488
  return buildAssemblyInput(systemPrompt2, baseInput);
485
489
  }
486
490
  const systemPrompt = buildTopLevelSystemPrompt(
@@ -495,7 +499,16 @@ function assembleAgentRequest(input) {
495
499
 
496
500
  // src/server/chat/stream-utils.ts
497
501
  function buildStreamRequestObject(params) {
498
- const { messages, tools, toolChoice, disableThinking, signal, modelSettings, onVisionFallbackStart, onVisionFallbackDone } = params;
502
+ const {
503
+ messages,
504
+ tools,
505
+ toolChoice,
506
+ disableThinking,
507
+ signal,
508
+ modelSettings,
509
+ onVisionFallbackStart,
510
+ onVisionFallbackDone
511
+ } = params;
499
512
  const streamRequest = {
500
513
  messages,
501
514
  ...tools && { tools },
@@ -515,7 +528,17 @@ function buildStreamRequest(client, options) {
515
528
  // src/server/chat/stats.ts
516
529
  var roundTo1 = (n) => Math.round(n * 10) / 10;
517
530
  function computeAggregatedStats(input) {
518
- const { identity, mode, totalPrefillTokens, totalGenTokens, totalPrefillTime, totalGenTime, totalToolTime, totalTime, llmCalls } = input;
531
+ const {
532
+ identity,
533
+ mode,
534
+ totalPrefillTokens,
535
+ totalGenTokens,
536
+ totalPrefillTime,
537
+ totalGenTime,
538
+ totalToolTime,
539
+ totalTime,
540
+ llmCalls
541
+ } = input;
519
542
  return {
520
543
  ...identity,
521
544
  mode,
@@ -543,7 +566,18 @@ function createEmptyStreamResult(aborted, xmlFormatError, modelParams) {
543
566
  };
544
567
  }
545
568
  async function* streamLLMPure(options) {
546
- const { messageId, systemPrompt, llmClient, messages, tools, toolChoice, signal, disableThinking, onVisionFallbackStart, onVisionFallbackDone } = options;
569
+ const {
570
+ messageId,
571
+ systemPrompt,
572
+ llmClient,
573
+ messages,
574
+ tools,
575
+ toolChoice,
576
+ signal,
577
+ disableThinking,
578
+ onVisionFallbackStart,
579
+ onVisionFallbackDone
580
+ } = options;
547
581
  const llmMessages = [{ role: "system", content: systemPrompt }, ...messages];
548
582
  const profile = getModelProfile(llmClient.getModel());
549
583
  const backend = getBackendCapabilities(llmClient.getBackend());
@@ -584,6 +618,7 @@ async function* streamLLMPure(options) {
584
618
  const toolNames = /* @__PURE__ */ new Map();
585
619
  const toolIds = /* @__PURE__ */ new Map();
586
620
  const returnValueArgs = /* @__PURE__ */ new Map();
621
+ const toolArgs = /* @__PURE__ */ new Map();
587
622
  let result = null;
588
623
  let aborted = false;
589
624
  let xmlFormatError = false;
@@ -619,13 +654,32 @@ async function* streamLLMPure(options) {
619
654
  if (value.id) {
620
655
  toolIds.set(value.index, value.id);
621
656
  }
657
+ if (value.arguments) {
658
+ const existingArgs = toolArgs.get(value.index) ?? "";
659
+ toolArgs.set(value.index, existingArgs + value.arguments);
660
+ }
622
661
  const fullName = toolNames.get(value.index);
623
662
  if (!seenToolIndices.has(value.index) && fullName) {
624
663
  seenToolIndices.add(value.index);
664
+ const accumulatedArgs = toolArgs.get(value.index);
625
665
  yield {
626
666
  type: "tool.preparing",
627
- data: { messageId, index: value.index, name: fullName }
667
+ data: {
668
+ messageId,
669
+ index: value.index,
670
+ name: fullName,
671
+ ...accumulatedArgs ? { arguments: accumulatedArgs } : {}
672
+ }
628
673
  };
674
+ } else if (seenToolIndices.has(value.index) && value.arguments) {
675
+ const accumulatedArgs = toolArgs.get(value.index);
676
+ const name = toolNames.get(value.index);
677
+ if (accumulatedArgs && name) {
678
+ yield {
679
+ type: "tool.preparing",
680
+ data: { messageId, index: value.index, name, arguments: accumulatedArgs }
681
+ };
682
+ }
629
683
  }
630
684
  if (fullName === "return_value" && value.arguments) {
631
685
  const toolCallId = toolIds.get(value.index);
@@ -884,10 +938,12 @@ async function consumeStreamWithToolLoop(options) {
884
938
  turnMetrics.addLLMCall(result.timing, result.usage.promptTokens, result.usage.completionTokens, result.modelParams);
885
939
  if (result.toolCalls.length > 0) {
886
940
  const stats = turnMetrics.buildStats(statsIdentity, "compaction");
887
- onEvent(createMessageDoneEvent(messageId, {
888
- segments: result.segments,
889
- stats
890
- }));
941
+ onEvent(
942
+ createMessageDoneEvent(messageId, {
943
+ segments: result.segments,
944
+ stats
945
+ })
946
+ );
891
947
  const toolContext = {
892
948
  sessionId,
893
949
  workdir,
@@ -910,6 +966,7 @@ async function consumeStreamWithToolLoop(options) {
910
966
  currentMessages.push({
911
967
  role: "assistant",
912
968
  content: result.content,
969
+ ...result.thinkingContent ? { thinkingContent: result.thinkingContent } : {},
913
970
  toolCalls: result.toolCalls
914
971
  });
915
972
  continue;
@@ -1036,10 +1093,7 @@ async function loadUserAgents(configDir) {
1036
1093
  return loadAgentsFromDir(getAgentsDir(configDir));
1037
1094
  }
1038
1095
  async function loadAllAgents(configDir) {
1039
- const [defaultAgents, userAgents] = await Promise.all([
1040
- loadDefaultAgents(),
1041
- loadUserAgents(configDir)
1042
- ]);
1096
+ const [defaultAgents, userAgents] = await Promise.all([loadDefaultAgents(), loadUserAgents(configDir)]);
1043
1097
  const agentMap = /* @__PURE__ */ new Map();
1044
1098
  for (const agent of defaultAgents) {
1045
1099
  agentMap.set(agent.metadata.id, agent);
@@ -1077,10 +1131,7 @@ async function isDefaultAgent(agentId) {
1077
1131
  }
1078
1132
  function getAgentFilePaths(agentsDir, agentId) {
1079
1133
  const hyphenated = agentId.replace(/_/g, "-");
1080
- return [
1081
- join2(agentsDir, `${agentId}${AGENT_EXTENSION}`),
1082
- join2(agentsDir, `${hyphenated}${AGENT_EXTENSION}`)
1083
- ];
1134
+ return [join2(agentsDir, `${agentId}${AGENT_EXTENSION}`), join2(agentsDir, `${hyphenated}${AGENT_EXTENSION}`)];
1084
1135
  }
1085
1136
  function findAgentById(agentId, agents) {
1086
1137
  return agents.find((a) => a.metadata.id === agentId);
@@ -1171,11 +1222,7 @@ var SAFE_PATHS = /* @__PURE__ */ new Set([
1171
1222
  "/dev/fd/1",
1172
1223
  "/dev/fd/2"
1173
1224
  ]);
1174
- var ALLOWED_ROOTS = [
1175
- "/tmp",
1176
- "/var/tmp",
1177
- tmpdir()
1178
- ];
1225
+ var ALLOWED_ROOTS = ["/tmp", "/var/tmp", tmpdir()];
1179
1226
  var SENSITIVE_FILE_PATTERNS = [
1180
1227
  // Dotenv files (but not .envrc, .env-example, .env.example)
1181
1228
  /^\.env$/,
@@ -1261,7 +1308,7 @@ function extractAbsolutePathsFromCommand(command) {
1261
1308
  const paths = [];
1262
1309
  const home = homedir();
1263
1310
  let sanitized = command.replace(/https?:\/\/[^\s'"]+/g, " __URL__ ").replace(/ftp:\/\/[^\s'"]+/g, " __URL__ ");
1264
- sanitized = sanitized.replace(/s\/[^\/]*\/[^\/]*\/[gip]*/g, " __SED__ ");
1311
+ sanitized = sanitized.replace(/s\/[^/]*\/[^/]*\/[gip]*/g, " __SED__ ");
1265
1312
  sanitized = sanitized.replace(/s\|[^|]*\|[^|]*\|[gip]*/g, " __SED__ ");
1266
1313
  sanitized = sanitized.replace(/s:[^:]*:[^:]*:[gip]*/g, " __SED__ ");
1267
1314
  const fileUrlMatches = command.matchAll(/file:\/\/([^\s'"]+)/g);
@@ -1371,7 +1418,7 @@ async function checkPathsAccess(paths, workdir, sessionId) {
1371
1418
  }
1372
1419
  var DANGEROUS_PATTERNS = [
1373
1420
  /sudo\s/,
1374
- /rm\s+(-rf?|--recursive)\s+[\/~]/,
1421
+ /rm\s+(-rf?|--recursive)\s+[~]/,
1375
1422
  /chmod\s+777/,
1376
1423
  />\s*\/dev\/sd/,
1377
1424
  /mkfs\s/,
@@ -1421,7 +1468,9 @@ async function requestPathAccess(paths, workdir, sessionId, callId, tool, onEven
1421
1468
  if (dangerousPatterns.length > 0) {
1422
1469
  emitPendingEvent([workdir], "dangerous_command");
1423
1470
  const confirmationPromise2 = registerPathConfirmation(callId, [workdir], sessionId);
1424
- onEvent(createChatPathConfirmationMessage(callId, tool, [dangerousPatterns.join(", ")], workdir, "dangerous_command"));
1471
+ onEvent(
1472
+ createChatPathConfirmationMessage(callId, tool, [dangerousPatterns.join(", ")], workdir, "dangerous_command")
1473
+ );
1425
1474
  const approved2 = await confirmationPromise2;
1426
1475
  if (!approved2) {
1427
1476
  throw new PathAccessDeniedError(dangerousPatterns, tool, "dangerous_command");
@@ -1477,7 +1526,7 @@ function providePathConfirmation(callId, approved, alwaysAllow) {
1477
1526
  type: "path.confirmation_responded",
1478
1527
  data: { callId, approved, alwaysAllow: alwaysAllow ?? false }
1479
1528
  });
1480
- } catch (error) {
1529
+ } catch {
1481
1530
  }
1482
1531
  if (approved) {
1483
1532
  if (alwaysAllow) {
@@ -1602,7 +1651,9 @@ var FileNotReadError = class extends Error {
1602
1651
  };
1603
1652
  var FileChangedExternallyError = class extends Error {
1604
1653
  constructor(path) {
1605
- super(`File "${path}" was modified externally and must be read before writing. Use read_file to see current contents.`);
1654
+ super(
1655
+ `File "${path}" was modified externally and must be read before writing. Use read_file to see current contents.`
1656
+ );
1606
1657
  this.name = "FileChangedExternallyError";
1607
1658
  }
1608
1659
  };
@@ -1655,7 +1706,11 @@ var IMAGE_MIME_TYPES = {
1655
1706
  ".svg": "image/svg+xml"
1656
1707
  };
1657
1708
  var IMAGE_SIGNATURES = [
1658
- { mimeType: "image/png", signature: Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]), extension: ".png" },
1709
+ {
1710
+ mimeType: "image/png",
1711
+ signature: Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]),
1712
+ extension: ".png"
1713
+ },
1659
1714
  { mimeType: "image/jpeg", signature: Buffer.from([255, 216, 255]), extension: ".jpg" },
1660
1715
  { mimeType: "image/gif", signature: Buffer.from([71, 73, 70, 56]), extension: ".gif" },
1661
1716
  { mimeType: "image/webp", signature: Buffer.from([]), extension: ".webp" },
@@ -1723,10 +1778,7 @@ var readFileTool = createTool(
1723
1778
  },
1724
1779
  async (args, context, helpers) => {
1725
1780
  const offset = args.offset ?? 1;
1726
- const limit = Math.min(
1727
- args.limit ?? OUTPUT_LIMITS.read_file.maxLines,
1728
- OUTPUT_LIMITS.read_file.maxLines
1729
- );
1781
+ const limit = Math.min(args.limit ?? OUTPUT_LIMITS.read_file.maxLines, OUTPUT_LIMITS.read_file.maxLines);
1730
1782
  const fullPath = helpers.resolvePath(args.path);
1731
1783
  await helpers.checkPathAccess([fullPath]);
1732
1784
  try {
@@ -1735,7 +1787,9 @@ var readFileTool = createTool(
1735
1787
  return helpers.error(`Path is a directory, not a file: ${args.path}`);
1736
1788
  }
1737
1789
  if (stats.size > OUTPUT_LIMITS.read_file.maxImageBytes) {
1738
- return helpers.error(`File size (${stats.size} bytes) exceeds image size limit (2MB). Use shell command to process large files.`);
1790
+ return helpers.error(
1791
+ `File size (${stats.size} bytes) exceeds image size limit (2MB). Use shell command to process large files.`
1792
+ );
1739
1793
  }
1740
1794
  } catch {
1741
1795
  return helpers.error(`File not found: ${args.path}`);
@@ -1749,19 +1803,15 @@ var readFileTool = createTool(
1749
1803
  if (contentHash2) {
1750
1804
  context.sessionManager.recordFileRead(context.sessionId, fullPath, contentHash2);
1751
1805
  }
1752
- return helpers.success(
1753
- `[Image: ${args.path} (${mimeType}, ${rawBuffer.length} bytes)]`,
1754
- false,
1755
- {
1756
- metadata: {
1757
- mimeType,
1758
- size: rawBuffer.length,
1759
- base64Data,
1760
- dataUrl,
1761
- path: fullPath
1762
- }
1806
+ return helpers.success(`[Image: ${args.path} (${mimeType}, ${rawBuffer.length} bytes)]`, false, {
1807
+ metadata: {
1808
+ mimeType,
1809
+ size: rawBuffer.length,
1810
+ base64Data,
1811
+ dataUrl,
1812
+ path: fullPath
1763
1813
  }
1764
- );
1814
+ });
1765
1815
  }
1766
1816
  const content = rawBuffer.toString("utf-8");
1767
1817
  const lines = content.split("\n");
@@ -1865,11 +1915,7 @@ var writeFileTool = createTool(
1865
1915
  if (newHash) {
1866
1916
  context.sessionManager.updateFileHash(context.sessionId, fullPath, newHash);
1867
1917
  }
1868
- return helpers.success(
1869
- output,
1870
- false,
1871
- diagnostics.length > 0 ? { diagnostics } : void 0
1872
- );
1918
+ return helpers.success(output, false, diagnostics.length > 0 ? { diagnostics } : void 0);
1873
1919
  }
1874
1920
  );
1875
1921
 
@@ -2054,7 +2100,12 @@ Make sure whitespace and indentation match exactly.`
2054
2100
  `Found ${occurrences} matches for old_string. Use replace_all: true to replace all, or provide more context to make the match unique.`
2055
2101
  );
2056
2102
  }
2057
- const contextResult = extractEditContext(normalizedContent, normalizedOldString, normalizeToLF(args.new_string), replaceAll);
2103
+ const contextResult = extractEditContext(
2104
+ normalizedContent,
2105
+ normalizedOldString,
2106
+ normalizeToLF(args.new_string),
2107
+ replaceAll
2108
+ );
2058
2109
  const editContextRegions = contextResult.regions.map((region) => ({
2059
2110
  beforeContext: region.beforeContext.map((line) => ({
2060
2111
  lineNumber: line.lineNumber,
@@ -2086,7 +2137,10 @@ Make sure whitespace and indentation match exactly.`
2086
2137
  }
2087
2138
  replacedContent = normalizedContent.slice(0, index) + normalizedNewString + normalizedContent.slice(index + normalizedOldString.length);
2088
2139
  }
2089
- const newContent = replacedContent.replace(/\n/g, fileLineEnding === "crlf" ? "\r\n" : fileLineEnding === "cr" ? "\r" : "\n");
2140
+ const newContent = replacedContent.replace(
2141
+ /\n/g,
2142
+ fileLineEnding === "crlf" ? "\r\n" : fileLineEnding === "cr" ? "\r" : "\n"
2143
+ );
2090
2144
  await writeFile3(fullPath, newContent, "utf-8");
2091
2145
  let output = `Successfully replaced ${replaceAll ? occurrences : 1} occurrence(s) in ${args.path}`;
2092
2146
  let diagnostics = [];
@@ -2359,12 +2413,21 @@ var criterionTool = createTool(
2359
2413
  }
2360
2414
  },
2361
2415
  async (args, context, helpers) => {
2362
- const actionError = validateActionWithPermission(args.action, ["get", "add", "update", "remove", "complete", "pass", "fail"], "criterion", context.permittedActions);
2416
+ const actionError = validateActionWithPermission(
2417
+ args.action,
2418
+ ["get", "add", "update", "remove", "complete", "pass", "fail"],
2419
+ "criterion",
2420
+ context.permittedActions
2421
+ );
2363
2422
  if (actionError) return actionError;
2364
2423
  const session = requireSession(context.sessionManager, context.sessionId);
2365
2424
  if (args.action === "get") {
2366
2425
  return helpers.success(
2367
- session.criteria.length === 0 ? "No criteria defined yet." : JSON.stringify(session.criteria.map((c) => ({ id: c.id, description: c.description })), null, 2)
2426
+ session.criteria.length === 0 ? "No criteria defined yet." : JSON.stringify(
2427
+ session.criteria.map((c) => ({ id: c.id, description: c.description })),
2428
+ null,
2429
+ 2
2430
+ )
2368
2431
  );
2369
2432
  }
2370
2433
  if (args.action === "add") {
@@ -2377,14 +2440,18 @@ var criterionTool = createTool(
2377
2440
  };
2378
2441
  const result = context.sessionManager.addCriterion(context.sessionId, criterion);
2379
2442
  if ("error" in result) return helpers.error(result.error);
2380
- return helpers.success(`Added criterion "${result.actualId}". Current criteria:
2381
- ${formatCriteriaList(result.criteria)}`);
2443
+ return helpers.success(
2444
+ `Added criterion "${result.actualId}". Current criteria:
2445
+ ${formatCriteriaList(result.criteria)}`
2446
+ );
2382
2447
  }
2383
2448
  if (args.action === "update") {
2384
2449
  if (!args.id) return helpers.error("Missing required field: id");
2385
2450
  if (!args.description) return helpers.error("Missing required field: description");
2386
2451
  if (!session.criteria.find((c) => c.id === args.id)) return helpers.error(`Criterion "${args.id}" not found`);
2387
- const criteria = context.sessionManager.updateCriterionFull(context.sessionId, args.id, { description: args.description });
2452
+ const criteria = context.sessionManager.updateCriterionFull(context.sessionId, args.id, {
2453
+ description: args.description
2454
+ });
2388
2455
  return helpers.success(`Updated criterion "${args.id}". Current criteria:
2389
2456
  ${formatCriteriaList(criteria)}`);
2390
2457
  }
@@ -2400,13 +2467,18 @@ ${formatCriteriaList(criteria)}`
2400
2467
  if (args.action === "complete") {
2401
2468
  if (!args.id) return helpers.error("Missing required field: id");
2402
2469
  const criterion = session.criteria.find((c) => c.id === args.id);
2403
- if (!criterion) return helpers.error(`Criterion "${args.id}" not found. Available: ${session.criteria.map((c) => c.id).join(", ")}`);
2470
+ if (!criterion)
2471
+ return helpers.error(
2472
+ `Criterion "${args.id}" not found. Available: ${session.criteria.map((c) => c.id).join(", ")}`
2473
+ );
2404
2474
  context.sessionManager.updateCriterionStatus(context.sessionId, args.id, {
2405
2475
  type: "completed",
2406
2476
  completedAt: (/* @__PURE__ */ new Date()).toISOString(),
2407
2477
  ...args.reason ? { reason: args.reason } : {}
2408
2478
  });
2409
- return helpers.success(`Criterion "${args.id}" marked as completed.${args.reason ? ` Reason: ${args.reason}` : ""}`);
2479
+ return helpers.success(
2480
+ `Criterion "${args.id}" marked as completed.${args.reason ? ` Reason: ${args.reason}` : ""}`
2481
+ );
2410
2482
  }
2411
2483
  if (args.action === "pass") {
2412
2484
  if (!args.id) return helpers.error("Missing required field: id");
@@ -2485,13 +2557,16 @@ var todoTool = createTool(
2485
2557
  }
2486
2558
  },
2487
2559
  async (args, context, helpers) => {
2488
- const actionError = validateActionWithPermission(args.action, ["list", "write", "add", "update", "remove"], "todo", context.permittedActions);
2560
+ const actionError = validateActionWithPermission(
2561
+ args.action,
2562
+ ["list", "write", "add", "update", "remove"],
2563
+ "todo",
2564
+ context.permittedActions
2565
+ );
2489
2566
  if (actionError) return actionError;
2490
2567
  if (args.action === "list") {
2491
2568
  const todosList = sessionTodos.get(context.sessionId) ?? [];
2492
- return helpers.success(
2493
- todosList.length === 0 ? "No tasks defined yet." : JSON.stringify(todosList, null, 2)
2494
- );
2569
+ return helpers.success(todosList.length === 0 ? "No tasks defined yet." : JSON.stringify(todosList, null, 2));
2495
2570
  }
2496
2571
  if (args.action === "write") {
2497
2572
  if (!args.todos) return helpers.error("Missing required field: todos");
@@ -2504,7 +2579,9 @@ var todoTool = createTool(
2504
2579
  }
2505
2580
  sessionTodos.set(context.sessionId, args.todos);
2506
2581
  if (onTodoUpdate) onTodoUpdate(context.sessionId, args.todos);
2507
- return helpers.success(`${args.todos.filter((t) => t.status === "completed").length} completed, ${args.todos.filter((t) => t.status === "in_progress").length} in progress, ${args.todos.filter((t) => t.status === "pending").length} pending`);
2582
+ return helpers.success(
2583
+ `${args.todos.filter((t) => t.status === "completed").length} completed, ${args.todos.filter((t) => t.status === "in_progress").length} in progress, ${args.todos.filter((t) => t.status === "pending").length} pending`
2584
+ );
2508
2585
  }
2509
2586
  if (args.action === "add") {
2510
2587
  if (!args.content) return helpers.error("Missing required field: content");
@@ -2650,10 +2727,7 @@ async function loadUserSkills(configDir) {
2650
2727
  });
2651
2728
  }
2652
2729
  async function loadAllSkills(configDir) {
2653
- const [defaultSkills, userSkills] = await Promise.all([
2654
- loadDefaultSkills(),
2655
- loadUserSkills(configDir)
2656
- ]);
2730
+ const [defaultSkills, userSkills] = await Promise.all([loadDefaultSkills(), loadUserSkills(configDir)]);
2657
2731
  const skillMap = /* @__PURE__ */ new Map();
2658
2732
  for (const skill of defaultSkills) {
2659
2733
  skillMap.set(skill.metadata.id, skill);
@@ -2726,11 +2800,14 @@ async function deleteSkill(configDir, skillId) {
2726
2800
  import stripAnsi from "strip-ansi";
2727
2801
  function emitPartialDoneEvents(sessionId, assistantMsgId, statsIdentity, mode, turnMetrics, promptContext, eventStore) {
2728
2802
  const stats = turnMetrics.buildStats(statsIdentity, mode);
2729
- eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
2730
- stats,
2731
- partial: true,
2732
- promptContext
2733
- }));
2803
+ eventStore.append(
2804
+ sessionId,
2805
+ createMessageDoneEvent(assistantMsgId, {
2806
+ stats,
2807
+ partial: true,
2808
+ promptContext
2809
+ })
2810
+ );
2734
2811
  eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "stopped", stats));
2735
2812
  }
2736
2813
  function getCurrentWindowMessageOptions(sessionId) {
@@ -2798,7 +2875,7 @@ async function executeToolBatch(assistantMsgId, toolCalls, ctx) {
2798
2875
  type: "chat.ask_user",
2799
2876
  data: { callId: error.callId, question: error.question }
2800
2877
  });
2801
- const { awaitAnswer } = await import("./ask-3RK5YJZE.js");
2878
+ const { awaitAnswer } = await import("./ask-5SSOA6SZ.js");
2802
2879
  const answerPromise = awaitAnswer(error.callId);
2803
2880
  if (!answerPromise) {
2804
2881
  throw new Error(`No pending question found for callId: ${error.callId}`);
@@ -2823,9 +2900,11 @@ async function executeToolBatch(assistantMsgId, toolCalls, ctx) {
2823
2900
  }
2824
2901
  toolMessages.push({
2825
2902
  role: "tool",
2826
- content: stripAnsi(toolResult.success ? toolResult.output ?? "Success" : toolResult.output ? `${toolResult.output}
2903
+ content: stripAnsi(
2904
+ toolResult.success ? toolResult.output ?? "Success" : toolResult.output ? `${toolResult.output}
2827
2905
 
2828
- Error: ${toolResult.error}` : `Error: ${toolResult.error}`),
2906
+ Error: ${toolResult.error}` : `Error: ${toolResult.error}`
2907
+ ),
2829
2908
  source: "history",
2830
2909
  toolCallId: toolCall.id
2831
2910
  });
@@ -2845,7 +2924,14 @@ function toRequestContextMessages(messages) {
2845
2924
  role: message.role,
2846
2925
  content: message.content,
2847
2926
  source: "history",
2848
- ...message.toolCalls ? { toolCalls: message.toolCalls.map((toolCall) => ({ id: toolCall.id, name: toolCall.name, arguments: toolCall.arguments })) } : {},
2927
+ ...message.thinkingContent ? { thinkingContent: message.thinkingContent } : {},
2928
+ ...message.toolCalls ? {
2929
+ toolCalls: message.toolCalls.map((toolCall) => ({
2930
+ id: toolCall.id,
2931
+ name: toolCall.name,
2932
+ arguments: toolCall.arguments
2933
+ }))
2934
+ } : {},
2849
2935
  ...message.toolCallId ? { toolCallId: message.toolCallId } : {},
2850
2936
  ...message.attachments ? { attachments: message.attachments } : {}
2851
2937
  }));
@@ -2881,11 +2967,14 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
2881
2967
  const requestMessages = toRequestContextMessages(getContextMessages(sessionId));
2882
2968
  if (formatRetryCount > 0) {
2883
2969
  const correctionMsgId = crypto.randomUUID();
2884
- eventStore.append(sessionId, createMessageStartEvent(correctionMsgId, "user", FORMAT_CORRECTION_PROMPT2, {
2885
- ...currentWindowMessageOptions ?? {},
2886
- isSystemGenerated: true,
2887
- messageKind: "correction"
2888
- }));
2970
+ eventStore.append(
2971
+ sessionId,
2972
+ createMessageStartEvent(correctionMsgId, "user", FORMAT_CORRECTION_PROMPT2, {
2973
+ ...currentWindowMessageOptions ?? {},
2974
+ isSystemGenerated: true,
2975
+ messageKind: "correction"
2976
+ })
2977
+ );
2889
2978
  eventStore.append(sessionId, createFormatRetryEvent(formatRetryCount, MAX_FORMAT_RETRIES));
2890
2979
  requestMessages.push({ role: "user", content: FORMAT_CORRECTION_PROMPT2, source: "runtime" });
2891
2980
  }
@@ -2902,7 +2991,10 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
2902
2991
  ...skills.length > 0 ? { skills } : {}
2903
2992
  });
2904
2993
  const assistantMsgId = crypto.randomUUID();
2905
- eventStore.append(sessionId, createMessageStartEvent(assistantMsgId, "assistant", void 0, currentWindowMessageOptions));
2994
+ eventStore.append(
2995
+ sessionId,
2996
+ createMessageStartEvent(assistantMsgId, "assistant", void 0, currentWindowMessageOptions)
2997
+ );
2906
2998
  const doOnMessage = (msg) => {
2907
2999
  onMessage?.(msg);
2908
3000
  };
@@ -2933,7 +3025,9 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
2933
3025
  type: "vision_fallback.done",
2934
3026
  data: { messageId: assistantMsgId, attachmentId, description }
2935
3027
  });
2936
- doOnMessage(createChatVisionFallbackMessage({ type: "done", messageId: assistantMsgId, attachmentId, description }));
3028
+ doOnMessage(
3029
+ createChatVisionFallbackMessage({ type: "done", messageId: assistantMsgId, attachmentId, description })
3030
+ );
2937
3031
  };
2938
3032
  const modelSettings = sessionManager.getCurrentModelSettings();
2939
3033
  const streamGen = streamLLMPure({
@@ -2965,16 +3059,27 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
2965
3059
  }
2966
3060
  }
2967
3061
  if (result.aborted) {
2968
- emitPartialDoneEvents(sessionId, assistantMsgId, statsIdentity, mode, turnMetrics, assembledRequest.promptContext, eventStore);
3062
+ emitPartialDoneEvents(
3063
+ sessionId,
3064
+ assistantMsgId,
3065
+ statsIdentity,
3066
+ mode,
3067
+ turnMetrics,
3068
+ assembledRequest.promptContext,
3069
+ eventStore
3070
+ );
2969
3071
  throw new Error("Aborted");
2970
3072
  }
2971
3073
  turnMetrics.addLLMCall(result.timing, result.usage.promptTokens, result.usage.completionTokens, result.modelParams);
2972
3074
  sessionManager.setCurrentContextSize(sessionId, result.usage.promptTokens);
2973
3075
  if (result.toolCalls.length > 0) {
2974
- eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
2975
- segments: result.segments,
2976
- promptContext: assembledRequest.promptContext
2977
- }));
3076
+ eventStore.append(
3077
+ sessionId,
3078
+ createMessageDoneEvent(assistantMsgId, {
3079
+ segments: result.segments,
3080
+ promptContext: assembledRequest.promptContext
3081
+ })
3082
+ );
2978
3083
  try {
2979
3084
  const batchContext = {
2980
3085
  toolRegistry,
@@ -3000,22 +3105,41 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
3000
3105
  }
3001
3106
  } catch (error) {
3002
3107
  if (error instanceof Error && error.message === "Aborted") {
3003
- emitPartialDoneEvents(sessionId, assistantMsgId, statsIdentity, mode, turnMetrics, assembledRequest.promptContext, eventStore);
3108
+ emitPartialDoneEvents(
3109
+ sessionId,
3110
+ assistantMsgId,
3111
+ statsIdentity,
3112
+ mode,
3113
+ turnMetrics,
3114
+ assembledRequest.promptContext,
3115
+ eventStore
3116
+ );
3004
3117
  throw error;
3005
3118
  }
3006
3119
  throw error;
3007
3120
  }
3008
3121
  if (signal?.aborted) {
3009
- emitPartialDoneEvents(sessionId, assistantMsgId, statsIdentity, mode, turnMetrics, assembledRequest.promptContext, eventStore);
3122
+ emitPartialDoneEvents(
3123
+ sessionId,
3124
+ assistantMsgId,
3125
+ statsIdentity,
3126
+ mode,
3127
+ turnMetrics,
3128
+ assembledRequest.promptContext,
3129
+ eventStore
3130
+ );
3010
3131
  throw new Error("Aborted");
3011
3132
  }
3012
3133
  const asapMessages = sessionManager.drainAsapMessages(sessionId);
3013
3134
  for (const asap of asapMessages) {
3014
3135
  const asapMsgId = crypto.randomUUID();
3015
- eventStore.append(sessionId, createMessageStartEvent(asapMsgId, "user", asap.content, {
3016
- ...getCurrentWindowMessageOptions(sessionId),
3017
- ...asap.attachments ? { attachments: asap.attachments } : {}
3018
- }));
3136
+ eventStore.append(
3137
+ sessionId,
3138
+ createMessageStartEvent(asapMsgId, "user", asap.content, {
3139
+ ...getCurrentWindowMessageOptions(sessionId),
3140
+ ...asap.attachments ? { attachments: asap.attachments } : {}
3141
+ })
3142
+ );
3019
3143
  eventStore.append(sessionId, { type: "message.done", data: { messageId: asapMsgId } });
3020
3144
  }
3021
3145
  if (asapMessages.length > 0) {
@@ -3025,11 +3149,14 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
3025
3149
  continue;
3026
3150
  }
3027
3151
  const stats = turnMetrics.buildStats(statsIdentity, mode);
3028
- eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
3029
- segments: result.segments,
3030
- stats,
3031
- promptContext: assembledRequest.promptContext
3032
- }));
3152
+ eventStore.append(
3153
+ sessionId,
3154
+ createMessageDoneEvent(assistantMsgId, {
3155
+ segments: result.segments,
3156
+ stats,
3157
+ promptContext: assembledRequest.promptContext
3158
+ })
3159
+ );
3033
3160
  eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "complete", stats));
3034
3161
  const currentWindowMessages = sessionManager.getCurrentWindowMessages(sessionId);
3035
3162
  const lastUserMessage = [...currentWindowMessages].reverse().find((m) => m.role === "user");
@@ -3045,15 +3172,36 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
3045
3172
  }
3046
3173
 
3047
3174
  // src/server/context/nudge-helpers.ts
3175
+ function buildPromptContextForNudge(systemPrompt, injectedFiles, userMessage, messages, tools) {
3176
+ return {
3177
+ systemPrompt,
3178
+ injectedFiles,
3179
+ userMessage,
3180
+ messages: messages.map((m) => ({
3181
+ role: m.role,
3182
+ content: m.content,
3183
+ source: m.source
3184
+ })),
3185
+ tools: tools.map((t) => ({
3186
+ name: t.function.name,
3187
+ description: t.function.description,
3188
+ parameters: t.function.parameters
3189
+ })),
3190
+ requestOptions: { toolChoice: "auto", disableThinking: true }
3191
+ };
3192
+ }
3048
3193
  function appendNudgeMessage(eventStore, sessionId, content, currentWindowMessageOptions, options) {
3049
3194
  const msgId = crypto.randomUUID();
3050
- eventStore.append(sessionId, createMessageStartEvent(msgId, "user", content, {
3051
- ...currentWindowMessageOptions ?? {},
3052
- isSystemGenerated: true,
3053
- messageKind: "correction",
3054
- subAgentId: options.subAgentId,
3055
- subAgentType: options.subAgentType
3056
- }));
3195
+ eventStore.append(
3196
+ sessionId,
3197
+ createMessageStartEvent(msgId, "user", content, {
3198
+ ...currentWindowMessageOptions ?? {},
3199
+ isSystemGenerated: true,
3200
+ messageKind: "correction",
3201
+ subAgentId: options.subAgentId,
3202
+ subAgentType: options.subAgentType
3203
+ })
3204
+ );
3057
3205
  eventStore.append(sessionId, { type: "message.done", data: { messageId: msgId } });
3058
3206
  }
3059
3207
 
@@ -3104,40 +3252,26 @@ async function executeSubAgent(options) {
3104
3252
  const subAgentId = crypto.randomUUID();
3105
3253
  let session = sessionManager.requireSession(sessionId);
3106
3254
  const currentWindowMessageOptions = getCurrentWindowMessageOptions2(sessionId);
3107
- const contextMessages = [
3108
- { role: "user", content: prompt, source: "runtime" }
3109
- ];
3255
+ const contextMessages = [{ role: "user", content: prompt, source: "runtime" }];
3110
3256
  logger.debug("Sub-agent starting", { subAgentType, subAgentId, sessionId });
3111
3257
  const resetMsgId = crypto.randomUUID();
3112
- eventStore.append(sessionId, createMessageStartEvent(resetMsgId, "user", `Fresh Context - ${agentDef.metadata.name} Sub-Agent`, {
3113
- ...currentWindowMessageOptions ?? {},
3114
- isSystemGenerated: true,
3115
- messageKind: "context-reset",
3116
- subAgentId,
3117
- subAgentType
3118
- }));
3119
- eventStore.append(sessionId, { type: "message.done", data: { messageId: resetMsgId } });
3120
- for (const msg of contextMessages) {
3121
- const msgId = crypto.randomUUID();
3122
- eventStore.append(sessionId, createMessageStartEvent(msgId, "user", msg.content, {
3258
+ eventStore.append(
3259
+ sessionId,
3260
+ createMessageStartEvent(resetMsgId, "user", `Fresh Context - ${agentDef.metadata.name} Sub-Agent`, {
3123
3261
  ...currentWindowMessageOptions ?? {},
3124
3262
  isSystemGenerated: true,
3125
- messageKind: "auto-prompt",
3263
+ messageKind: "context-reset",
3126
3264
  subAgentId,
3127
- subAgentType,
3128
- metadata: {
3129
- type: "subagent",
3130
- name: agentDef.metadata.name,
3131
- color: agentDef.metadata.color ?? "#6b7280"
3132
- }
3133
- }));
3134
- eventStore.append(sessionId, { type: "message.done", data: { messageId: msgId } });
3135
- if (onMessage) {
3136
- onMessage(createChatMessageMessage({
3137
- id: msgId,
3138
- role: "user",
3139
- content: msg.content,
3140
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3265
+ subAgentType
3266
+ })
3267
+ );
3268
+ eventStore.append(sessionId, { type: "message.done", data: { messageId: resetMsgId } });
3269
+ for (const msg of contextMessages) {
3270
+ const msgId = crypto.randomUUID();
3271
+ eventStore.append(
3272
+ sessionId,
3273
+ createMessageStartEvent(msgId, "user", msg.content, {
3274
+ ...currentWindowMessageOptions ?? {},
3141
3275
  isSystemGenerated: true,
3142
3276
  messageKind: "auto-prompt",
3143
3277
  subAgentId,
@@ -3147,15 +3281,31 @@ async function executeSubAgent(options) {
3147
3281
  name: agentDef.metadata.name,
3148
3282
  color: agentDef.metadata.color ?? "#6b7280"
3149
3283
  }
3150
- }));
3284
+ })
3285
+ );
3286
+ eventStore.append(sessionId, { type: "message.done", data: { messageId: msgId } });
3287
+ if (onMessage) {
3288
+ onMessage(
3289
+ createChatMessageMessage({
3290
+ id: msgId,
3291
+ role: "user",
3292
+ content: msg.content,
3293
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3294
+ isSystemGenerated: true,
3295
+ messageKind: "auto-prompt",
3296
+ subAgentId,
3297
+ subAgentType,
3298
+ metadata: {
3299
+ type: "subagent",
3300
+ name: agentDef.metadata.name,
3301
+ color: agentDef.metadata.color ?? "#6b7280"
3302
+ }
3303
+ })
3304
+ );
3151
3305
  }
3152
3306
  }
3153
3307
  const { files } = await getAllInstructions(session.workdir, session.projectId);
3154
- const injectedFiles = files.map((file) => ({
3155
- path: file.path,
3156
- content: file.content ?? "",
3157
- source: file.source
3158
- }));
3308
+ const injectedFiles = toInjectedFiles(files);
3159
3309
  const configDir = getGlobalConfigDir(getRuntimeConfig().mode ?? "production");
3160
3310
  const skills = await getEnabledSkillMetadata(configDir);
3161
3311
  const systemPrompt = buildSubAgentSystemPrompt(
@@ -3166,7 +3316,7 @@ async function executeSubAgent(options) {
3166
3316
  );
3167
3317
  let customMessages = [...contextMessages];
3168
3318
  let consecutiveEmptyStops = 0;
3169
- let finalContent = "";
3319
+ let finalContent;
3170
3320
  let returnValueContent = null;
3171
3321
  let returnValueResult = void 0;
3172
3322
  let returnValueNudged = false;
@@ -3182,19 +3332,21 @@ async function executeSubAgent(options) {
3182
3332
  ...signal ? { signal } : {}
3183
3333
  });
3184
3334
  const assistantMsgId = crypto.randomUUID();
3185
- eventStore.append(sessionId, createMessageStartEvent(assistantMsgId, "assistant", void 0, {
3186
- ...currentWindowMessageOptions ?? {},
3187
- subAgentId,
3188
- subAgentType
3189
- }));
3190
- const promptContext = {
3335
+ eventStore.append(
3336
+ sessionId,
3337
+ createMessageStartEvent(assistantMsgId, "assistant", void 0, {
3338
+ ...currentWindowMessageOptions ?? {},
3339
+ subAgentId,
3340
+ subAgentType
3341
+ })
3342
+ );
3343
+ const promptContext = buildPromptContextForNudge(
3191
3344
  systemPrompt,
3192
3345
  injectedFiles,
3193
- userMessage: prompt,
3194
- messages: customMessages.map((m) => ({ role: m.role, content: m.content, source: m.source })),
3195
- tools: toolRegistry.definitions.map((t) => ({ name: t.function.name, description: t.function.description, parameters: t.function.parameters })),
3196
- requestOptions: { toolChoice: "auto", disableThinking: true }
3197
- };
3346
+ prompt,
3347
+ customMessages,
3348
+ toolRegistry.definitions
3349
+ );
3198
3350
  const streamGen = streamLLMPure({
3199
3351
  messageId: assistantMsgId,
3200
3352
  systemPrompt: systemPrompt + RETURN_VALUE_INSTRUCTION,
@@ -3215,11 +3367,14 @@ async function executeSubAgent(options) {
3215
3367
  });
3216
3368
  if (result.aborted) {
3217
3369
  const stats = turnMetrics.buildStats(statsIdentity, "verifier");
3218
- eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
3219
- stats,
3220
- partial: true,
3221
- promptContext
3222
- }));
3370
+ eventStore.append(
3371
+ sessionId,
3372
+ createMessageDoneEvent(assistantMsgId, {
3373
+ stats,
3374
+ partial: true,
3375
+ promptContext
3376
+ })
3377
+ );
3223
3378
  eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "stopped", stats));
3224
3379
  throw new Error("Aborted");
3225
3380
  }
@@ -3240,48 +3395,69 @@ async function executeSubAgent(options) {
3240
3395
  if (consecutiveEmptyStops < nudgeConfig.maxConsecutiveNudges) {
3241
3396
  consecutiveEmptyStops += 1;
3242
3397
  const nudgeContent = nudgeConfig.buildNudgeContent(criteriaAwaiting);
3243
- eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
3244
- segments: result.segments,
3245
- promptContext
3246
- }));
3247
- appendNudgeMessage(eventStore, sessionId, nudgeContent, currentWindowMessageOptions, { subAgentId, subAgentType });
3398
+ eventStore.append(
3399
+ sessionId,
3400
+ createMessageDoneEvent(assistantMsgId, {
3401
+ segments: result.segments,
3402
+ promptContext
3403
+ })
3404
+ );
3405
+ appendNudgeMessage(eventStore, sessionId, nudgeContent, currentWindowMessageOptions, {
3406
+ subAgentId,
3407
+ subAgentType
3408
+ });
3248
3409
  customMessages = [...customMessages, { role: "user", content: nudgeContent, source: "runtime" }];
3249
3410
  continue;
3250
3411
  }
3251
3412
  const stalledMsgId = crypto.randomUUID();
3252
- eventStore.append(sessionId, createMessageStartEvent(stalledMsgId, "user", nudgeConfig.buildRestartContent(criteriaAwaiting), {
3253
- ...currentWindowMessageOptions ?? {},
3254
- isSystemGenerated: true,
3255
- messageKind: "correction",
3256
- subAgentId,
3257
- subAgentType
3258
- }));
3413
+ eventStore.append(
3414
+ sessionId,
3415
+ createMessageStartEvent(stalledMsgId, "user", nudgeConfig.buildRestartContent(criteriaAwaiting), {
3416
+ ...currentWindowMessageOptions ?? {},
3417
+ isSystemGenerated: true,
3418
+ messageKind: "correction",
3419
+ subAgentId,
3420
+ subAgentType
3421
+ })
3422
+ );
3259
3423
  eventStore.append(sessionId, { type: "message.done", data: { messageId: stalledMsgId } });
3260
3424
  }
3261
3425
  }
3262
3426
  if (!returnValueContent && !returnValueNudged) {
3263
3427
  returnValueNudged = true;
3264
- eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
3265
- segments: result.segments,
3266
- promptContext
3267
- }));
3268
- appendNudgeMessage(eventStore, sessionId, RETURN_VALUE_NUDGE, currentWindowMessageOptions, { subAgentId, subAgentType });
3428
+ eventStore.append(
3429
+ sessionId,
3430
+ createMessageDoneEvent(assistantMsgId, {
3431
+ segments: result.segments,
3432
+ promptContext
3433
+ })
3434
+ );
3435
+ appendNudgeMessage(eventStore, sessionId, RETURN_VALUE_NUDGE, currentWindowMessageOptions, {
3436
+ subAgentId,
3437
+ subAgentType
3438
+ });
3269
3439
  customMessages = [...customMessages, { role: "user", content: RETURN_VALUE_NUDGE, source: "runtime" }];
3270
3440
  continue;
3271
3441
  }
3272
3442
  const stats = turnMetrics.buildStats(statsIdentity, "verifier");
3273
- eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
3274
- segments: result.segments,
3275
- stats,
3276
- promptContext
3277
- }));
3443
+ eventStore.append(
3444
+ sessionId,
3445
+ createMessageDoneEvent(assistantMsgId, {
3446
+ segments: result.segments,
3447
+ stats,
3448
+ promptContext
3449
+ })
3450
+ );
3278
3451
  eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "complete", stats));
3279
3452
  break;
3280
3453
  }
3281
- eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
3282
- segments: result.segments,
3283
- promptContext
3284
- }));
3454
+ eventStore.append(
3455
+ sessionId,
3456
+ createMessageDoneEvent(assistantMsgId, {
3457
+ segments: result.segments,
3458
+ promptContext
3459
+ })
3460
+ );
3285
3461
  const batchResult = await executeToolBatch(assistantMsgId, result.toolCalls, {
3286
3462
  toolRegistry,
3287
3463
  sessionManager,
@@ -3294,13 +3470,15 @@ async function executeSubAgent(options) {
3294
3470
  if (batchResult.returnValueContent) {
3295
3471
  returnValueContent = batchResult.returnValueContent;
3296
3472
  returnValueResult = batchResult.returnValueResult;
3297
- customMessages = [...customMessages, ...batchResult.toolMessages];
3298
3473
  const stats = turnMetrics.buildStats(statsIdentity, subAgentType);
3299
- eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
3300
- segments: result.segments,
3301
- stats,
3302
- promptContext
3303
- }));
3474
+ eventStore.append(
3475
+ sessionId,
3476
+ createMessageDoneEvent(assistantMsgId, {
3477
+ segments: result.segments,
3478
+ stats,
3479
+ promptContext
3480
+ })
3481
+ );
3304
3482
  if (onMessage) {
3305
3483
  onMessage(createChatMessageUpdatedMessage(assistantMsgId, { isStreaming: false, stats, promptContext }));
3306
3484
  }
@@ -3323,7 +3501,13 @@ async function executeSubAgent(options) {
3323
3501
  });
3324
3502
  const failed = session.criteria.filter((c) => c.status.type === "failed").map((c) => ({ id: c.id, reason: c.status.reason ?? "unknown" }));
3325
3503
  const remaining = nudgeConfig?.getCriteriaAwaiting(session.criteria) ?? [];
3326
- return buildSubAgentResult(returnValueContent ?? void 0, returnValueResult ?? (subAgentType !== "verifier" ? "success" : void 0), subAgentType, failed, remaining);
3504
+ return buildSubAgentResult(
3505
+ returnValueContent ?? void 0,
3506
+ returnValueResult ?? (subAgentType !== "verifier" ? "success" : void 0),
3507
+ subAgentType,
3508
+ failed,
3509
+ remaining
3510
+ );
3327
3511
  }
3328
3512
 
3329
3513
  // src/server/tools/sub-agent.ts
@@ -3391,7 +3575,7 @@ var callSubAgentTool = {
3391
3575
  };
3392
3576
  }
3393
3577
  try {
3394
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-RUAY6EVI.js");
3578
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-BHYHS3RY.js");
3395
3579
  const toolRegistry = getToolRegistryForAgent2(agentDef);
3396
3580
  const turnMetrics = new TurnMetrics();
3397
3581
  const result = await executeSubAgent({
@@ -3580,14 +3764,11 @@ var webFetchTool = createTool(
3580
3764
  if (!url.startsWith("http://") && !url.startsWith("https://")) {
3581
3765
  return helpers.error("URL must start with http:// or https://");
3582
3766
  }
3583
- const timeoutMs = Math.min(
3584
- (args.timeout ?? DEFAULT_TIMEOUT_MS / 1e3) * 1e3,
3585
- MAX_TIMEOUT_MS
3586
- );
3767
+ const timeoutMs = Math.min((args.timeout ?? DEFAULT_TIMEOUT_MS / 1e3) * 1e3, MAX_TIMEOUT_MS);
3587
3768
  const signal = buildSignal(timeoutMs, context.signal);
3588
3769
  const headers = {
3589
3770
  "User-Agent": USER_AGENT,
3590
- "Accept": buildAcceptHeader(format),
3771
+ Accept: buildAcceptHeader(format),
3591
3772
  "Accept-Language": "en-US,en;q=0.9"
3592
3773
  };
3593
3774
  const initial = await fetch(url, { signal, headers });
@@ -3919,16 +4100,20 @@ var devServerTool = createTool(
3919
4100
  const offset = args.offset ?? 0;
3920
4101
  const limit = args.limit ?? 100;
3921
4102
  const result = devServerManager.getLogsSlice(workdir, offset, limit);
3922
- const formattedLogs = result.logs.map(
3923
- (entry) => `${entry.stream === "stderr" ? "[stderr] " : ""}${entry.content}`
3924
- ).join("");
3925
- return helpers.success(JSON.stringify({
3926
- logs: formattedLogs,
3927
- total: result.total,
3928
- offset,
3929
- limit,
3930
- hasMore: offset + limit < result.total
3931
- }, null, 2));
4103
+ const formattedLogs = result.logs.map((entry) => `${entry.stream === "stderr" ? "[stderr] " : ""}${entry.content}`).join("");
4104
+ return helpers.success(
4105
+ JSON.stringify(
4106
+ {
4107
+ logs: formattedLogs,
4108
+ total: result.total,
4109
+ offset,
4110
+ limit,
4111
+ hasMore: offset + limit < result.total
4112
+ },
4113
+ null,
4114
+ 2
4115
+ )
4116
+ );
3932
4117
  }
3933
4118
  let status;
3934
4119
  switch (args.action) {
@@ -3958,12 +4143,18 @@ var devServerTool = createTool(
3958
4143
  'No .openfox/dev-dev.json (dev mode) or .openfox/dev.json (prod) config found. Create one with:\n\n{\n "command": "npm run dev",\n "url": "http://localhost:3000",\n "hotReload": true\n}'
3959
4144
  );
3960
4145
  }
3961
- return helpers.success(JSON.stringify({
3962
- state: status.state,
3963
- url: status.url,
3964
- hotReload: status.hotReload,
3965
- ...status.errorMessage ? { error: status.errorMessage } : {}
3966
- }, null, 2));
4146
+ return helpers.success(
4147
+ JSON.stringify(
4148
+ {
4149
+ state: status.state,
4150
+ url: status.url,
4151
+ hotReload: status.hotReload,
4152
+ ...status.errorMessage ? { error: status.errorMessage } : {}
4153
+ },
4154
+ null,
4155
+ 2
4156
+ )
4157
+ );
3967
4158
  }
3968
4159
  );
3969
4160
 
@@ -4064,7 +4255,9 @@ These processes run independently of agent turns and persist across session comp
4064
4255
  const count = getSessionProcessCount(sessionId);
4065
4256
  const maxPerSession = getMaxPerSession();
4066
4257
  if (count >= maxPerSession) {
4067
- return helpers.error(`Maximum number of background processes (${maxPerSession}) reached. Stop existing processes before starting new ones.`);
4258
+ return helpers.error(
4259
+ `Maximum number of background processes (${maxPerSession}) reached. Stop existing processes before starting new ones.`
4260
+ );
4068
4261
  }
4069
4262
  const name = args.name ?? args.command?.split(" ")[0] ?? "process";
4070
4263
  const process2 = createProcess(sessionId, name, args.command, cwd, args.timeout);
@@ -4075,13 +4268,19 @@ These processes run independently of agent turns and persist across session comp
4075
4268
  if (!pid) {
4076
4269
  return helpers.error(`Failed to start process.`);
4077
4270
  }
4078
- return helpers.success(JSON.stringify({
4079
- processId: process2.id,
4080
- name: process2.name,
4081
- pid,
4082
- status: "running",
4083
- maxReached: count + 1 >= maxPerSession
4084
- }, null, 2));
4271
+ return helpers.success(
4272
+ JSON.stringify(
4273
+ {
4274
+ processId: process2.id,
4275
+ name: process2.name,
4276
+ pid,
4277
+ status: "running",
4278
+ maxReached: count + 1 >= maxPerSession
4279
+ },
4280
+ null,
4281
+ 2
4282
+ )
4283
+ );
4085
4284
  }
4086
4285
  case "stop": {
4087
4286
  const proc = getProcessStatus(args.processId, sessionId);
@@ -4092,19 +4291,31 @@ These processes run independently of agent turns and persist across session comp
4092
4291
  return helpers.error(`Process is not running (status: ${proc.status}). Cannot stop.`);
4093
4292
  }
4094
4293
  await stopProcess(args.processId, sessionId);
4095
- return helpers.success(JSON.stringify({
4096
- processId: args.processId,
4097
- status: "removed"
4098
- }, null, 2));
4294
+ return helpers.success(
4295
+ JSON.stringify(
4296
+ {
4297
+ processId: args.processId,
4298
+ status: "removed"
4299
+ },
4300
+ null,
4301
+ 2
4302
+ )
4303
+ );
4099
4304
  }
4100
4305
  case "list": {
4101
4306
  const processes = getSessionProcesses(sessionId);
4102
4307
  const maxPerSession = getMaxPerSession();
4103
- return helpers.success(JSON.stringify({
4104
- processes,
4105
- maxPerSession,
4106
- currentCount: processes.filter((p) => p.status !== "exited").length
4107
- }, null, 2));
4308
+ return helpers.success(
4309
+ JSON.stringify(
4310
+ {
4311
+ processes,
4312
+ maxPerSession,
4313
+ currentCount: processes.filter((p) => p.status !== "exited").length
4314
+ },
4315
+ null,
4316
+ 2
4317
+ )
4318
+ );
4108
4319
  }
4109
4320
  case "status": {
4110
4321
  const proc = getProcessStatus(args.processId, sessionId);
@@ -4112,10 +4323,16 @@ These processes run independently of agent turns and persist across session comp
4112
4323
  return helpers.error(`Process not found: ${args.processId}`);
4113
4324
  }
4114
4325
  const uptime = proc.startedAt ? Date.now() - proc.startedAt : null;
4115
- return helpers.success(JSON.stringify({
4116
- process: proc,
4117
- uptime
4118
- }, null, 2));
4326
+ return helpers.success(
4327
+ JSON.stringify(
4328
+ {
4329
+ process: proc,
4330
+ uptime
4331
+ },
4332
+ null,
4333
+ 2
4334
+ )
4335
+ );
4119
4336
  }
4120
4337
  case "logs": {
4121
4338
  const proc = getProcessStatus(args.processId, sessionId);
@@ -4125,14 +4342,20 @@ These processes run independently of agent turns and persist across session comp
4125
4342
  const since = args.since ?? 0;
4126
4343
  const maxLines = Math.min(args.maxLines ?? 500, 2e3);
4127
4344
  const { lines, totalLines, nextOffset, hasMore } = getProcessLogs(args.processId, since, maxLines);
4128
- return helpers.success(JSON.stringify({
4129
- processId: args.processId,
4130
- lines,
4131
- totalLines,
4132
- nextOffset,
4133
- hasMore,
4134
- truncated: hasMore
4135
- }, null, 2));
4345
+ return helpers.success(
4346
+ JSON.stringify(
4347
+ {
4348
+ processId: args.processId,
4349
+ lines,
4350
+ totalLines,
4351
+ nextOffset,
4352
+ hasMore,
4353
+ truncated: hasMore
4354
+ },
4355
+ null,
4356
+ 2
4357
+ )
4358
+ );
4136
4359
  }
4137
4360
  default:
4138
4361
  return helpers.error(`Unknown action: ${args.action}`);
@@ -4384,11 +4607,7 @@ async function performContextCompaction(options) {
4384
4607
  const eventStore = getEventStore();
4385
4608
  const session = sessionManager.requireSession(sessionId);
4386
4609
  const { content: instructions, files } = await getAllInstructions(session.workdir, session.projectId);
4387
- const injectedFiles = files.map((file) => ({
4388
- path: file.path,
4389
- content: file.content ?? "",
4390
- source: file.source
4391
- }));
4610
+ const injectedFiles = toInjectedFiles(files);
4392
4611
  const requestMessages = toRequestContextMessages2(getContextMessages(sessionId));
4393
4612
  const config = getRuntimeConfig();
4394
4613
  const allAgents = await loadAllAgentsDefault();
@@ -4414,20 +4633,23 @@ async function performContextCompaction(options) {
4414
4633
  const compactionReminder = `<system-reminder>
4415
4634
  ${COMPACTION_PROMPT}
4416
4635
  </system-reminder>`;
4417
- const llmMessages = [
4418
- ...assembledRequest.messages,
4419
- { role: "user", content: compactionReminder }
4420
- ];
4636
+ const llmMessages = [...assembledRequest.messages, { role: "user", content: compactionReminder }];
4421
4637
  const compactPromptMsgId = crypto.randomUUID();
4422
- eventStore.append(sessionId, createMessageStartEvent(compactPromptMsgId, "user", COMPACTION_PROMPT, {
4423
- ...getCurrentWindowMessageOptions3(sessionId) ?? {},
4424
- isSystemGenerated: true,
4425
- messageKind: "auto-prompt",
4426
- metadata: { type: "compaction", name: "Compaction", color: "#64748b" }
4427
- }));
4638
+ eventStore.append(
4639
+ sessionId,
4640
+ createMessageStartEvent(compactPromptMsgId, "user", COMPACTION_PROMPT, {
4641
+ ...getCurrentWindowMessageOptions3(sessionId) ?? {},
4642
+ isSystemGenerated: true,
4643
+ messageKind: "auto-prompt",
4644
+ metadata: { type: "compaction", name: "Compaction", color: "#64748b" }
4645
+ })
4646
+ );
4428
4647
  eventStore.append(sessionId, { type: "message.done", data: { messageId: compactPromptMsgId } });
4429
4648
  const assistantMsgId = crypto.randomUUID();
4430
- eventStore.append(sessionId, createMessageStartEvent(assistantMsgId, "assistant", void 0, getCurrentWindowMessageOptions3(sessionId)));
4649
+ eventStore.append(
4650
+ sessionId,
4651
+ createMessageStartEvent(assistantMsgId, "assistant", void 0, getCurrentWindowMessageOptions3(sessionId))
4652
+ );
4431
4653
  const turnMetrics = new TurnMetrics();
4432
4654
  const compactionToolRegistry = {
4433
4655
  execute: async (name, args, ctx) => {
@@ -4545,4 +4767,4 @@ export {
4545
4767
  getToolRegistryForAgent,
4546
4768
  createToolRegistry
4547
4769
  };
4548
- //# sourceMappingURL=chunk-ETIXH35K.js.map
4770
+ //# sourceMappingURL=chunk-H5EICXF3.js.map