tarsk 0.5.76 → 0.5.78

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 (157) hide show
  1. package/dist/index.js +861 -186
  2. package/dist/public/assets/account-view-Bzv2EHnc.js +1 -0
  3. package/dist/public/assets/api-OO3KSG8d.js +2 -0
  4. package/dist/public/assets/{async-error-boundary-BX1G17o9.js → async-error-boundary-Dll_zcqr.js} +1 -1
  5. package/dist/public/assets/browser-tab-Cwa1TB3I.js +12 -0
  6. package/dist/public/assets/button-B5aMz2Rk.js +1 -0
  7. package/dist/public/assets/card-DRr14MEQ.js +1 -0
  8. package/dist/public/assets/chat-dock-context-Cnq0BWgm.js +1 -0
  9. package/dist/public/assets/commit-dialog-C-JfaoS6.js +1 -0
  10. package/dist/public/assets/commit-error-dialog-VXqZLeta.js +1 -0
  11. package/dist/public/assets/commit-method-fields-DAd1unUF.js +1 -0
  12. package/dist/public/assets/context-menu-BKOotkeD.js +1 -0
  13. package/dist/public/assets/conversation-history-view-CcdQRxoP.js +1 -0
  14. package/dist/public/assets/{create-project-dialog-a6Wgq-Z8.js → create-project-dialog-D1VaSgqh.js} +2 -2
  15. package/dist/public/assets/create-repo-dialog-mBGGkX-g.js +1 -0
  16. package/dist/public/assets/delete-confirm-dialog-Cx9nT7Xd.js +1 -0
  17. package/dist/public/assets/diff-view-CyOnLSEA.js +4 -0
  18. package/dist/public/assets/{dist-DsmF-KJ-.js → dist-COfI64N5.js} +1 -1
  19. package/dist/public/assets/dist-CWYnBq-n.js +1 -0
  20. package/dist/public/assets/dist-DDYi9MQo.js +1 -0
  21. package/dist/public/assets/dist-DNkA3vYh.js +2 -0
  22. package/dist/public/assets/dist-DwblUvSf.js +1 -0
  23. package/dist/public/assets/dist-T8-4ZfS0.js +1 -0
  24. package/dist/public/assets/dist-TCNzmc2V.js +5 -0
  25. package/dist/public/assets/dist-sThe8WYP.js +1 -0
  26. package/dist/public/assets/es2015-Bu0NIPbn.js +41 -0
  27. package/dist/public/assets/{explorer-monaco-editor-BdZ_bBqh.js → explorer-monaco-editor-q8CnSwWA.js} +1 -1
  28. package/dist/public/assets/explorer-tab-view-G2HmkQyY.js +2 -0
  29. package/dist/public/assets/explorer-tree-DAuc2Npx.js +1 -0
  30. package/dist/public/assets/explorer-view-BDMlnV3f.js +76 -0
  31. package/dist/public/assets/git-history-dialog-XEr5pugf.js +1 -0
  32. package/dist/public/assets/index-C4WzOmf3.css +1 -0
  33. package/dist/public/assets/index-DD_a7tQU.js +3665 -0
  34. package/dist/public/assets/lucide-react-B-115rul.js +1 -0
  35. package/dist/public/assets/main-tab-context-CNgxXqnH.js +1 -0
  36. package/dist/public/assets/model-list-controls-DAZM0NBC.js +1 -0
  37. package/dist/public/assets/onboarding-dialog-Dd9hiOOf.js +1 -0
  38. package/dist/public/assets/pill-tabs-QsjH027B.js +1 -0
  39. package/dist/public/assets/progress-indicator-C01aPXIe.js +1 -0
  40. package/dist/public/assets/project-coding-view-DbKI7sbW.js +1 -0
  41. package/dist/public/assets/project-danger-zone-view-BaSu793w.js +1 -0
  42. package/dist/public/assets/project-env-vars-view-BB66j52E.js +1 -0
  43. package/dist/public/assets/project-model-aliases-view-o1-Z2es5.js +1 -0
  44. package/dist/public/assets/project-settings-view-BKjvtOtk.js +1 -0
  45. package/dist/public/assets/project-tools-view-CZbblznF.js +1 -0
  46. package/dist/public/assets/providers-list-view-ChY2DXYc.js +1 -0
  47. package/dist/public/assets/pull-request-dialog-BZgY4vrw.js +1 -0
  48. package/dist/public/assets/pull-with-changes-dialog-DDp_srHq.js +1 -0
  49. package/dist/public/assets/{push-before-pr-dialog-CarrD3y2.js → push-before-pr-dialog-Bt0BChlV.js} +1 -1
  50. package/dist/public/assets/scroll-area-DwRwR2nQ.js +1 -0
  51. package/dist/public/assets/settings-general-tabs-view-BH7AaXyP.js +2 -0
  52. package/dist/public/assets/settings-general-view-B-t99LmD.js +1 -0
  53. package/dist/public/assets/settings-list-Dn4CHP4Z.js +1 -0
  54. package/dist/public/assets/{settings-logs-view-DbKM1SNk.js → settings-logs-view-BCRjz-Fr.js} +3 -3
  55. package/dist/public/assets/settings-mcp-servers-view-xv9D4DPO.js +5 -0
  56. package/dist/public/assets/settings-models-view-rUeqlE4k.js +1 -0
  57. package/dist/public/assets/settings-plugins-view-qnWmII61.js +2 -0
  58. package/dist/public/assets/settings-providers-view-DsxTdBEQ.js +2 -0
  59. package/dist/public/assets/settings-setup-view-ew5KW8gL.js +2 -0
  60. package/dist/public/assets/settings-skills-view-C4NxP4gI.js +3 -0
  61. package/dist/public/assets/settings-slack-view-BNT5ervf.js +1 -0
  62. package/dist/public/assets/settings-slash-commands-view-CE7FT3dB.js +1 -0
  63. package/dist/public/assets/settings-statistics-view-jKPoSWBs.js +1 -0
  64. package/dist/public/assets/settings-storage-view-C_Rs-9Hw.js +1 -0
  65. package/dist/public/assets/settings-subagents-view-DHVSAmCY.js +2 -0
  66. package/dist/public/assets/settings-system-prompt-view-B_nF2HUy.js +1 -0
  67. package/dist/public/assets/settings-tab-bar-DAHxT5KE.js +1 -0
  68. package/dist/public/assets/settings-view-BY6OO-xy.js +2 -0
  69. package/dist/public/assets/slug-utils-BQZ6c2py.js +1 -0
  70. package/dist/public/assets/store-B7EgrEO7.js +9 -0
  71. package/dist/public/assets/suspense-resource-DzlMlIgR.js +1 -0
  72. package/dist/public/assets/table-7hMwxpkF.js +1 -0
  73. package/dist/public/assets/tasks-view-Dc7sthjm.js +1 -0
  74. package/dist/public/assets/terminal-output-activity-B1bjjsl7.js +1 -0
  75. package/dist/public/assets/terminal-panel-BNOIOh8z.js +38 -0
  76. package/dist/public/assets/toggle-group-UiksQ0n9.js +1 -0
  77. package/dist/public/assets/tooltip-Dvmz78Z_.js +1 -0
  78. package/dist/public/assets/{use-active-dock-panel-instance-DRfRj6MV.js → use-active-dock-panel-instance-2LfvItRH.js} +1 -1
  79. package/dist/public/assets/use-installed-ai-files-BkpswqGI.js +1 -0
  80. package/dist/public/assets/{useBaseQuery-34f0-SVd.js → useBaseQuery-D5as4SgS.js} +1 -1
  81. package/dist/public/assets/utils-B-qS8qMg.js +1 -0
  82. package/dist/public/assets/{web-C2KGFouM.js → web-B9ndApmi.js} +1 -1
  83. package/dist/public/assets/{web-DycfRH4j.js → web-BkuMY08B.js} +1 -1
  84. package/dist/public/assets/{web-Dk3GAfTy.js → web-DyqJbQ3L.js} +1 -1
  85. package/dist/public/assets/{web-Bn9n5e7r.js → web-gEWIDddb.js} +1 -1
  86. package/dist/public/index.html +26 -28
  87. package/package.json +1 -1
  88. package/dist/public/assets/account-view-CWtpznW2.js +0 -1
  89. package/dist/public/assets/alert-dialog-BxMfaLuO.js +0 -7
  90. package/dist/public/assets/api-DX1ny6q-.js +0 -2
  91. package/dist/public/assets/async-loading-fallback-V0EaQ_Kn.js +0 -1
  92. package/dist/public/assets/browser-tab-D_5MLhxE.js +0 -12
  93. package/dist/public/assets/button-kWtLAMpB.js +0 -1
  94. package/dist/public/assets/card-B_EASkic.js +0 -1
  95. package/dist/public/assets/chat-dock-context-8K8Ikjgy.js +0 -1
  96. package/dist/public/assets/commit-dialog-CSXPoomw.js +0 -1
  97. package/dist/public/assets/commit-error-dialog-CdcGI69P.js +0 -1
  98. package/dist/public/assets/commit-method-fields-BtEHb0_G.js +0 -1
  99. package/dist/public/assets/context-menu-BcM6I0Sx.js +0 -1
  100. package/dist/public/assets/conversation-history-view-CuzU9qF6.js +0 -1
  101. package/dist/public/assets/create-project-workspace-Dv_lEfZx.js +0 -2
  102. package/dist/public/assets/create-repo-dialog-BTIQ5Nw4.js +0 -1
  103. package/dist/public/assets/delete-confirm-dialog-Dl76vaxb.js +0 -1
  104. package/dist/public/assets/diff-view-DA1uT9tc.js +0 -4
  105. package/dist/public/assets/dist-C2G92uPn.js +0 -1
  106. package/dist/public/assets/dist-CHhgoHp6.js +0 -1
  107. package/dist/public/assets/dist-CTLFS4dn.js +0 -2
  108. package/dist/public/assets/dist-D-2G8xGB.js +0 -5
  109. package/dist/public/assets/dist-DD4GtbiM.js +0 -1
  110. package/dist/public/assets/dist-DoxvnNEY.js +0 -1
  111. package/dist/public/assets/dist-c_QADQ5u.js +0 -1
  112. package/dist/public/assets/dist-yM5kyz9Q.js +0 -1
  113. package/dist/public/assets/es2015-BlPKkFZZ.js +0 -41
  114. package/dist/public/assets/explorer-tab-view-CewTYYOm.js +0 -2
  115. package/dist/public/assets/explorer-tree-C0VDhihz.js +0 -1
  116. package/dist/public/assets/explorer-view-RCfDm3p5.js +0 -76
  117. package/dist/public/assets/git-history-dialog-DL0Trxiz.js +0 -1
  118. package/dist/public/assets/index-B3-5kIOf.js +0 -3658
  119. package/dist/public/assets/index-BLNUy5nZ.css +0 -1
  120. package/dist/public/assets/main-tab-context-Byl1LybL.js +0 -1
  121. package/dist/public/assets/merged-pr-dialog-BzND8nzx.js +0 -1
  122. package/dist/public/assets/model-list-controls-I67L2x3H.js +0 -1
  123. package/dist/public/assets/onboarding-dialog-DY8v11hv.js +0 -1
  124. package/dist/public/assets/project-coding-view-DxOwsjtt.js +0 -1
  125. package/dist/public/assets/project-danger-zone-view-CkvKOQrl.js +0 -1
  126. package/dist/public/assets/project-env-vars-view-DYLWA7s0.js +0 -1
  127. package/dist/public/assets/project-model-aliases-view-DWu9khLA.js +0 -1
  128. package/dist/public/assets/project-settings-view-DJfmaWn6.js +0 -1
  129. package/dist/public/assets/project-tools-view-BEjBkghz.js +0 -1
  130. package/dist/public/assets/providers-list-view-jMEPJCci.js +0 -1
  131. package/dist/public/assets/pull-request-dialog-B_JCqT53.js +0 -1
  132. package/dist/public/assets/pull-with-changes-dialog-V3_km2zQ.js +0 -1
  133. package/dist/public/assets/radio-group-Dn_pN-pn.js +0 -1
  134. package/dist/public/assets/scroll-area-lkVMElz5.js +0 -1
  135. package/dist/public/assets/settings-general-view-BhrfHGfQ.js +0 -1
  136. package/dist/public/assets/settings-list-DiiYzOxn.js +0 -1
  137. package/dist/public/assets/settings-mcp-servers-view-4FpPIeYV.js +0 -5
  138. package/dist/public/assets/settings-models-view-CJVeo9ad.js +0 -1
  139. package/dist/public/assets/settings-skills-view-DoRPGbHG.js +0 -3
  140. package/dist/public/assets/settings-slack-view-Cc1NgVkx.js +0 -1
  141. package/dist/public/assets/settings-slash-commands-view-CmlWqqmi.js +0 -1
  142. package/dist/public/assets/settings-statistics-view-DRuyEbcN.js +0 -1
  143. package/dist/public/assets/settings-storage-view-DihbtUYb.js +0 -1
  144. package/dist/public/assets/settings-subagents-view-B2RvxDZI.js +0 -2
  145. package/dist/public/assets/settings-system-prompt-view-CvVbgjNN.js +0 -1
  146. package/dist/public/assets/settings-view-CPUAjTMa.js +0 -2
  147. package/dist/public/assets/slug-utils-CQ8PMWUL.js +0 -1
  148. package/dist/public/assets/store-BSzKIu5G.js +0 -9
  149. package/dist/public/assets/suspense-resource-BFrb_XJX.js +0 -1
  150. package/dist/public/assets/table-A3cgauiZ.js +0 -1
  151. package/dist/public/assets/tasks-view-CvFFLPeD.js +0 -1
  152. package/dist/public/assets/terminal-panel-DIh6it7K.js +0 -38
  153. package/dist/public/assets/toggle-group-Q36wRGKA.js +0 -1
  154. package/dist/public/assets/tooltip-Db8UeYxm.js +0 -1
  155. package/dist/public/assets/use-installed-ai-files-C8nNWGC7.js +0 -1
  156. package/dist/public/assets/use-suspense-resource-Dakt9lfT.js +0 -1
  157. package/dist/public/assets/use-toast-xpb5jNtN.js +0 -1
package/dist/index.js CHANGED
@@ -365,6 +365,19 @@ var init_agent_modes = __esm({
365
365
  }
366
366
  });
367
367
 
368
+ // ../shared/dist/agent-note.js
369
+ function isTarskAgentNoteModel(model) {
370
+ return model === TARSK_AGENT_NOTE_MODEL;
371
+ }
372
+ var TARSK_AGENT_NOTE_MODEL, TARSK_AGENT_NOTE_LABEL;
373
+ var init_agent_note = __esm({
374
+ "../shared/dist/agent-note.js"() {
375
+ "use strict";
376
+ TARSK_AGENT_NOTE_MODEL = "tarsk";
377
+ TARSK_AGENT_NOTE_LABEL = "Tarsk";
378
+ }
379
+ });
380
+
368
381
  // ../shared/dist/agent-session.js
369
382
  var AGENT_MAIN_LANE, AGENT_SESSION_STORAGE_VERSION, AGENT_SESSION_LEGACY_STORAGE_VERSION, AGENT_ROLLOVER_DETAILS_KIND;
370
383
  var init_agent_session = __esm({
@@ -867,6 +880,110 @@ var init_observations = __esm({
867
880
  }
868
881
  });
869
882
 
883
+ // ../shared/dist/grep-limits.js
884
+ function clampGrepContextLines(value2) {
885
+ if (value2 === void 0) {
886
+ return void 0;
887
+ }
888
+ if (!Number.isFinite(value2)) {
889
+ return 0;
890
+ }
891
+ return Math.max(0, Math.min(MAX_GREP_CONTENT_CONTEXT, Math.trunc(value2)));
892
+ }
893
+ function grepContextWidth(before, after) {
894
+ return Math.max(1, before + after + 1);
895
+ }
896
+ function scaleGrepHeadLimitForContext(requested, contextWidth) {
897
+ if (contextWidth <= 1) {
898
+ return requested;
899
+ }
900
+ const scaled = Math.ceil(requested / contextWidth);
901
+ return Math.max(contextWidth, scaled);
902
+ }
903
+ function isContentMode(mode) {
904
+ return mode === void 0 || mode === "content";
905
+ }
906
+ function contextWasClamped(requested, clamped) {
907
+ if (requested === void 0 || clamped === void 0) {
908
+ return false;
909
+ }
910
+ return requested !== clamped;
911
+ }
912
+ function resolveGrepContentBudget(input2) {
913
+ if (!isContentMode(input2.output_mode)) {
914
+ return {
915
+ contextWidth: 1,
916
+ contextClamped: false,
917
+ headLimit: input2.head_limit,
918
+ headLimitScaled: false
919
+ };
920
+ }
921
+ const context2 = clampGrepContextLines(input2.context);
922
+ const contextC = clampGrepContextLines(input2["-C"]);
923
+ const contextBefore = clampGrepContextLines(input2["-B"]);
924
+ const contextAfter = clampGrepContextLines(input2["-A"]);
925
+ const contextClamped = contextWasClamped(input2.context, context2) || contextWasClamped(input2["-C"], contextC) || contextWasClamped(input2["-B"], contextBefore) || contextWasClamped(input2["-A"], contextAfter);
926
+ let before = 0;
927
+ let after = 0;
928
+ if (context2 !== void 0) {
929
+ before = context2;
930
+ after = context2;
931
+ } else if (contextC !== void 0) {
932
+ before = contextC;
933
+ after = contextC;
934
+ } else {
935
+ before = contextBefore ?? 0;
936
+ after = contextAfter ?? 0;
937
+ }
938
+ const contextWidth = grepContextWidth(before, after);
939
+ if (contextWidth <= 1) {
940
+ return {
941
+ context: context2,
942
+ contextC,
943
+ contextBefore,
944
+ contextAfter,
945
+ contextWidth: 1,
946
+ contextClamped,
947
+ headLimit: input2.head_limit,
948
+ headLimitScaled: false
949
+ };
950
+ }
951
+ const requested = input2.head_limit === void 0 || input2.head_limit === 0 ? DEFAULT_GREP_HEAD_LIMIT : input2.head_limit;
952
+ const headLimit = scaleGrepHeadLimitForContext(requested, contextWidth);
953
+ return {
954
+ context: context2,
955
+ contextC,
956
+ contextBefore,
957
+ contextAfter,
958
+ contextWidth,
959
+ contextClamped,
960
+ headLimit,
961
+ headLimitScaled: headLimit !== input2.head_limit
962
+ };
963
+ }
964
+ function formatGrepContextBudgetNotice(budget) {
965
+ const parts = [];
966
+ if (budget.contextClamped) {
967
+ parts.push(`Context limited to ${MAX_GREP_CONTENT_CONTEXT} lines per side.`);
968
+ }
969
+ if (budget.headLimitScaled && budget.headLimit) {
970
+ parts.push(`Output line budget scaled to ${budget.headLimit}.`);
971
+ }
972
+ if (parts.length === 0) {
973
+ return "";
974
+ }
975
+ return `[${parts.join(" ")}]`;
976
+ }
977
+ var DEFAULT_GREP_HEAD_LIMIT, DEFAULT_GREP_CONTENT_CONTEXT, MAX_GREP_CONTENT_CONTEXT;
978
+ var init_grep_limits = __esm({
979
+ "../shared/dist/grep-limits.js"() {
980
+ "use strict";
981
+ DEFAULT_GREP_HEAD_LIMIT = 40;
982
+ DEFAULT_GREP_CONTENT_CONTEXT = 0;
983
+ MAX_GREP_CONTENT_CONTEXT = 2;
984
+ }
985
+ });
986
+
870
987
  // ../shared/dist/selection.js
871
988
  function areResultSelectionsEnabled() {
872
989
  return process.env[RESULT_SELECTION_ENV_FLAG] !== "false";
@@ -937,7 +1054,7 @@ function isPromptCacheUnavailable(cacheHitRate) {
937
1054
  function isMicrocompactEligibleTool(toolName2) {
938
1055
  return MICROCOMPACT_ELIGIBLE_TOOL_SET.has(toolName2);
939
1056
  }
940
- var MICROCOMPACT_KEEP_RECENT, MICROCOMPACT_KEEP_TOKENS, MICROCOMPACT_TRIGGER_MARGIN, MICROCOMPACT_MIN_SAVE_TOKENS, MICROCOMPACT_DIGEST_MIN_CHARS, MICROCOMPACT_NO_CACHE_DIGEST_MIN_CHARS, MICROCOMPACT_SHORT_STUB_MAX_CHARS, MICROCOMPACT_PROACTIVE_TURN_THRESHOLD, MICROCOMPACT_PROACTIVE_PAYLOAD_TOKENS, MICROCOMPACT_PROACTIVE_MIN_SAVE_TOKENS, MICROCOMPACT_PROACTIVE_KEEP_TOKENS, MICROCOMPACT_NO_CACHE_KEEP_TOKENS, MICROCOMPACT_OVERFLOW_KEEP_RECENT, MICROCOMPACT_OVERFLOW_KEEP_TOKENS, MICROCOMPACT_OVERFLOW_MIN_SAVE_TOKENS, MICROCOMPACT_OVERFLOW_DIGEST_MIN_CHARS, MICROCOMPACT_NO_CACHE_HIT_RATE_THRESHOLD, MICROCOMPACT_NO_CACHE_AGGRESSION_FACTOR, MICROCOMPACT_MARKER_PREFIX, SUPERSESSION_MARKER_PREFIX, MICROCOMPACT_ELIGIBLE_TOOLS, MICROCOMPACT_ELIGIBLE_TOOL_SET;
1057
+ var MICROCOMPACT_KEEP_RECENT, MICROCOMPACT_KEEP_TOKENS, MICROCOMPACT_TRIGGER_MARGIN, MICROCOMPACT_MIN_SAVE_TOKENS, MICROCOMPACT_DIGEST_MIN_CHARS, MICROCOMPACT_NO_CACHE_DIGEST_MIN_CHARS, MICROCOMPACT_SHORT_STUB_MAX_CHARS, MICROCOMPACT_PROACTIVE_TURN_THRESHOLD, MICROCOMPACT_PROACTIVE_PAYLOAD_TOKENS, MICROCOMPACT_CACHE_RECLAIM_PAYLOAD_TOKENS, MICROCOMPACT_CACHE_RECLAIM_MESSAGE_COUNT, MICROCOMPACT_PROACTIVE_MIN_SAVE_TOKENS, MICROCOMPACT_PROACTIVE_KEEP_TOKENS, MICROCOMPACT_NO_CACHE_KEEP_TOKENS, MICROCOMPACT_OVERFLOW_KEEP_RECENT, MICROCOMPACT_OVERFLOW_KEEP_TOKENS, MICROCOMPACT_OVERFLOW_MIN_SAVE_TOKENS, MICROCOMPACT_OVERFLOW_DIGEST_MIN_CHARS, MICROCOMPACT_NO_CACHE_HIT_RATE_THRESHOLD, MICROCOMPACT_NO_CACHE_AGGRESSION_FACTOR, MICROCOMPACT_MARKER_PREFIX, SUPERSESSION_MARKER_PREFIX, MICROCOMPACT_ELIGIBLE_TOOLS, MICROCOMPACT_ELIGIBLE_TOOL_SET;
941
1058
  var init_microcompact = __esm({
942
1059
  "../shared/dist/microcompact.js"() {
943
1060
  "use strict";
@@ -950,6 +1067,8 @@ var init_microcompact = __esm({
950
1067
  MICROCOMPACT_SHORT_STUB_MAX_CHARS = 2048;
951
1068
  MICROCOMPACT_PROACTIVE_TURN_THRESHOLD = 15;
952
1069
  MICROCOMPACT_PROACTIVE_PAYLOAD_TOKENS = 5e4;
1070
+ MICROCOMPACT_CACHE_RECLAIM_PAYLOAD_TOKENS = 8e4;
1071
+ MICROCOMPACT_CACHE_RECLAIM_MESSAGE_COUNT = 80;
953
1072
  MICROCOMPACT_PROACTIVE_MIN_SAVE_TOKENS = 5e3;
954
1073
  MICROCOMPACT_PROACTIVE_KEEP_TOKENS = 1e4;
955
1074
  MICROCOMPACT_NO_CACHE_KEEP_TOKENS = 2e3;
@@ -997,6 +1116,13 @@ var init_processing_similes = __esm({
997
1116
  }
998
1117
  });
999
1118
 
1119
+ // ../shared/dist/processing-polling.js
1120
+ var init_processing_polling = __esm({
1121
+ "../shared/dist/processing-polling.js"() {
1122
+ "use strict";
1123
+ }
1124
+ });
1125
+
1000
1126
  // ../shared/dist/context-rollover.js
1001
1127
  var CONTEXT_ROLLOVER_MARKER, CONTEXT_ROLLOVER_NOTICE, CONTEXT_ROLLOVER_MAX_HANDOFF_CHARS, CONTEXT_ROLLOVER_MAX_NOTE_CHARS, CONTEXT_ROLLOVER_MAX_TODO_CHARS, CONTEXT_ROLLOVER_MAX_RECENT_MESSAGE_CHARS, CONTEXT_ROLLOVER_MAX_REPOSITORY_STATE_CHARS, CONTEXT_ROLLOVER_MAX_CHANGE_DIGEST_CHARS, CONTEXT_ROLLOVER_MAX_HUNKS_PER_FILE, CONTEXT_HISTORY_PAGE_CHARS, CONTEXT_HISTORY_SEARCH_LIMIT, CONTEXT_HISTORY_SEARCH_EXCERPT_CHARS, CONTEXT_NOTE_NAME_MAX_CHARS, CONTEXT_NOTE_CONTENT_MAX_CHARS, CONTEXT_NOTE_PAGE_CHARS, CONTEXT_NOTE_SEARCH_EXCERPT_CHARS, CONTEXT_MEMORY_INSTRUCTIONS;
1002
1128
  var init_context_rollover = __esm({
@@ -1030,7 +1156,7 @@ This conversation can move to a fresh model context while its complete transcrip
1030
1156
  // ../shared/dist/system-prompt.js
1031
1157
  function buildDefaultSystemPrompt(toolNames) {
1032
1158
  const toolList = toolNames.length > 0 ? toolNames.join(", ") : "read, bash, edit, and write";
1033
- return `You are a helpful coding assistant. You have access to ${toolList} tools. Use them to explore and modify the codebase as needed. ${SHELL_WORKING_DIRECTORY_INSTRUCTION} Skills are created and stored in .agents/skills/ . Use Mermaid for flowcharts, sequence diagrams, state diagrams, or graphs when appropriate. When a tool returns a local image, audio, or video file intended for the user, present it in the conversation by returning the file path or URL plainly so the UI can render it inline. If the user asks you to do multiple tasks "in subagents" or asks for work to be split across subagents, delegate the work by calling the agent tool once per subtask when that tool is available. Break the request into clear focused prompts, run subagents in parallel when supported by the runtime, and then synthesize their results for the user. Be concise and answer directly; do not restate the question, add preamble, or end with unsolicited follow-ups. Do not use emojis.
1159
+ return `You are a helpful coding assistant. You have access to ${toolList} tools. Use them to explore and modify the codebase as needed. ${PARALLEL_TOOL_CALLS_INSTRUCTION} ${SHELL_WORKING_DIRECTORY_INSTRUCTION} Skills are created and stored in .agents/skills/ . Use Mermaid for flowcharts, sequence diagrams, state diagrams, or graphs when appropriate. When a tool returns a local image, audio, or video file intended for the user, present it in the conversation by returning the file path or URL plainly so the UI can render it inline. If the user asks you to do multiple tasks "in subagents" or asks for work to be split across subagents, delegate the work by calling the agent tool once per subtask when that tool is available. Break the request into clear focused prompts, run subagents in parallel when supported by the runtime, and then synthesize their results for the user. Be concise and answer directly; do not restate the question, add preamble, or end with unsolicited follow-ups. Do not use emojis.
1034
1160
 
1035
1161
  ${CONTEXT_MEMORY_INSTRUCTIONS}`;
1036
1162
  }
@@ -1043,14 +1169,15 @@ function formatCurrentDateLine(referenceDate = /* @__PURE__ */ new Date()) {
1043
1169
  });
1044
1170
  return `The current date is ${date5}.`;
1045
1171
  }
1046
- var TARSK_REPO_ROOT_ENV_VAR, SHELL_WORKING_DIRECTORY_INSTRUCTION, BASE_SYSTEM_PROMPT;
1172
+ var TARSK_REPO_ROOT_ENV_VAR, SHELL_WORKING_DIRECTORY_INSTRUCTION, PARALLEL_TOOL_CALLS_INSTRUCTION, BASE_SYSTEM_PROMPT;
1047
1173
  var init_system_prompt = __esm({
1048
1174
  "../shared/dist/system-prompt.js"() {
1049
1175
  "use strict";
1050
1176
  init_context_rollover();
1051
1177
  TARSK_REPO_ROOT_ENV_VAR = "TARSK_REPO_ROOT";
1052
1178
  SHELL_WORKING_DIRECTORY_INSTRUCTION = `Shell commands start in the repository root. Assume that working directory, prefer repository-relative paths, and do not prefix commands with an absolute-path cd. Use $${TARSK_REPO_ROOT_ENV_VAR} only as a fallback when the working directory cannot be assumed.`;
1053
- BASE_SYSTEM_PROMPT = `You are a helpful coding assistant. ${SHELL_WORKING_DIRECTORY_INSTRUCTION} Skills are created and stored in .agents/skills/ . Use Mermaid for flowcharts, sequence diagrams, state diagrams, or graphs when appropriate. When a tool returns a local image/audio/video file intended for the user, present it in the conversation by returning the file path or URL plainly so the UI can render it inline. Be concise and answer directly; do not restate the question, add preamble, or end with unsolicited follow-ups. Do not use emojis.
1179
+ PARALLEL_TOOL_CALLS_INSTRUCTION = "Issue independent tool calls together in the same turn so they run in parallel.";
1180
+ BASE_SYSTEM_PROMPT = `You are a helpful coding assistant. ${SHELL_WORKING_DIRECTORY_INSTRUCTION} ${PARALLEL_TOOL_CALLS_INSTRUCTION} Skills are created and stored in .agents/skills/ . Use Mermaid for flowcharts, sequence diagrams, state diagrams, or graphs when appropriate. When a tool returns a local image/audio/video file intended for the user, present it in the conversation by returning the file path or URL plainly so the UI can render it inline. Be concise and answer directly; do not restate the question, add preamble, or end with unsolicited follow-ups. Do not use emojis.
1054
1181
 
1055
1182
  ${CONTEXT_MEMORY_INSTRUCTIONS}`;
1056
1183
  }
@@ -2416,6 +2543,34 @@ var init_providers = __esm({
2416
2543
  }
2417
2544
  });
2418
2545
 
2546
+ // ../shared/dist/provider-settings.js
2547
+ var init_provider_settings = __esm({
2548
+ "../shared/dist/provider-settings.js"() {
2549
+ "use strict";
2550
+ }
2551
+ });
2552
+
2553
+ // ../shared/dist/general-settings.js
2554
+ var init_general_settings = __esm({
2555
+ "../shared/dist/general-settings.js"() {
2556
+ "use strict";
2557
+ }
2558
+ });
2559
+
2560
+ // ../shared/dist/plugin-settings.js
2561
+ var init_plugin_settings = __esm({
2562
+ "../shared/dist/plugin-settings.js"() {
2563
+ "use strict";
2564
+ }
2565
+ });
2566
+
2567
+ // ../shared/dist/setup-settings.js
2568
+ var init_setup_settings = __esm({
2569
+ "../shared/dist/setup-settings.js"() {
2570
+ "use strict";
2571
+ }
2572
+ });
2573
+
2419
2574
  // ../shared/dist/web-fetch.js
2420
2575
  function normalizeFetchHostname(hostname4) {
2421
2576
  const lower2 = hostname4.toLowerCase();
@@ -13389,6 +13544,7 @@ var init_dist = __esm({
13389
13544
  init_model_aliases();
13390
13545
  init_model_id();
13391
13546
  init_agent_modes();
13547
+ init_agent_note();
13392
13548
  init_agent_session();
13393
13549
  init_auto_route();
13394
13550
  init_model_reasoning();
@@ -13399,10 +13555,12 @@ var init_dist = __esm({
13399
13555
  init_assistant_summary();
13400
13556
  init_conversation_title();
13401
13557
  init_observations();
13558
+ init_grep_limits();
13402
13559
  init_selection();
13403
13560
  init_user_message();
13404
13561
  init_microcompact();
13405
13562
  init_processing_similes();
13563
+ init_processing_polling();
13406
13564
  init_system_prompt();
13407
13565
  init_context_rollover();
13408
13566
  init_image_payload();
@@ -13418,6 +13576,10 @@ var init_dist = __esm({
13418
13576
  init_smart_js_plan();
13419
13577
  init_smart_js_results();
13420
13578
  init_providers();
13579
+ init_provider_settings();
13580
+ init_general_settings();
13581
+ init_plugin_settings();
13582
+ init_setup_settings();
13421
13583
  init_web_fetch();
13422
13584
  init_permission_messages();
13423
13585
  init_explorer_media();
@@ -57542,6 +57704,13 @@ function isProactiveMicrocompactTrigger(messages, options2) {
57542
57704
  const tokensBefore = sumMessageTokens(messages) + config3.fixedOverheadTokens;
57543
57705
  return countAssistantTurns(messages) >= config3.proactiveTurnThreshold || tokensBefore >= config3.proactivePayloadTokens;
57544
57706
  }
57707
+ function isCacheReclaimTrigger(messages, config3, cacheHitRate) {
57708
+ if (isPromptCacheUnavailable(cacheHitRate) || cacheHitRate === void 0 || cacheHitRate <= 0) {
57709
+ return false;
57710
+ }
57711
+ const tokensBefore = sumMessageTokens(messages) + config3.fixedOverheadTokens;
57712
+ return tokensBefore >= config3.cacheReclaimPayloadTokens || messages.length >= config3.cacheReclaimMessageCount;
57713
+ }
57545
57714
  function isNearWindowCeilingTrigger(messages, options2, config3, cacheHitRate) {
57546
57715
  if (options2.overflowRecovery === true) {
57547
57716
  return true;
@@ -57566,6 +57735,37 @@ function unprotectInTurnFrozenIds(messages, frozenToolCallIds, unprotectInTurn)
57566
57735
  }
57567
57736
  return stillFrozen;
57568
57737
  }
57738
+ function unprotectOldestFrozenIds(messages, frozenToolCallIds, keepRecent, keepTokens) {
57739
+ if (!frozenToolCallIds || frozenToolCallIds.size === 0) {
57740
+ return frozenToolCallIds;
57741
+ }
57742
+ const frozenIndexes = [];
57743
+ for (let index4 = 0; index4 < messages.length; index4++) {
57744
+ const message = messages[index4];
57745
+ if (isToolResultMessage3(message) && frozenToolCallIds.has(message.toolCallId)) {
57746
+ frozenIndexes.push(index4);
57747
+ }
57748
+ }
57749
+ if (frozenIndexes.length === 0) {
57750
+ return frozenToolCallIds;
57751
+ }
57752
+ const stillFrozen = /* @__PURE__ */ new Set();
57753
+ let keptTokens = 0;
57754
+ let keptRecent = 0;
57755
+ for (let cursor = frozenIndexes.length - 1; cursor >= 0; cursor--) {
57756
+ const message = messages[frozenIndexes[cursor]];
57757
+ if (!isToolResultMessage3(message)) {
57758
+ continue;
57759
+ }
57760
+ if (keptRecent >= keepRecent && keptTokens >= keepTokens) {
57761
+ break;
57762
+ }
57763
+ stillFrozen.add(message.toolCallId);
57764
+ keptRecent += 1;
57765
+ keptTokens += estimateMessageTokens(message);
57766
+ }
57767
+ return stillFrozen;
57768
+ }
57569
57769
  function isCompactedToolResultText(text) {
57570
57770
  return text.startsWith(MICROCOMPACT_MARKER_PREFIX) || text.startsWith(TODO_DUPLICATE_OMITTED_PREFIX) || isSupersessionMarker(text);
57571
57771
  }
@@ -57783,6 +57983,14 @@ function resolveMicrocompactConfig(options2) {
57783
57983
  MICROCOMPACT_PROACTIVE_MIN_SAVE_TOKENS
57784
57984
  ),
57785
57985
  proactiveKeepTokens: overflowRecovery ? MICROCOMPACT_OVERFLOW_KEEP_TOKENS : resolveNumericOption(options2.proactiveKeepTokens, MICROCOMPACT_PROACTIVE_KEEP_TOKENS),
57986
+ cacheReclaimPayloadTokens: resolveNumericOption(
57987
+ options2.cacheReclaimPayloadTokens,
57988
+ MICROCOMPACT_CACHE_RECLAIM_PAYLOAD_TOKENS
57989
+ ),
57990
+ cacheReclaimMessageCount: resolveNumericOption(
57991
+ options2.cacheReclaimMessageCount,
57992
+ MICROCOMPACT_CACHE_RECLAIM_MESSAGE_COUNT
57993
+ ),
57786
57994
  // Callers guard against an absent context window before resolving config, so
57787
57995
  // the fallback value is never actually used to make a decision.
57788
57996
  effectiveWindow: computeEffectiveContextWindow(
@@ -57883,13 +58091,20 @@ function computeMicrocompactTriggerState(messages, options2, config3) {
57883
58091
  cacheHitRate
57884
58092
  );
57885
58093
  const proactiveTrigger = isProactiveMicrocompactTrigger(messages, options2);
57886
- const frozenToolCallIds = overflowRecovery || noCache ? void 0 : unprotectInTurnFrozenIds(messages, options2.frozenToolCallIds, nearWindowCeiling);
58094
+ const cacheReclaim = isCacheReclaimTrigger(messages, config3, cacheHitRate);
58095
+ const frozenToolCallIds = overflowRecovery || noCache ? void 0 : cacheReclaim ? unprotectOldestFrozenIds(
58096
+ messages,
58097
+ options2.frozenToolCallIds,
58098
+ config3.keepRecent,
58099
+ config3.proactiveKeepTokens
58100
+ ) : unprotectInTurnFrozenIds(messages, options2.frozenToolCallIds, nearWindowCeiling);
57887
58101
  const { messageCount: cacheProtectedMessageCount, tokens: cacheProtectedTokens } = countCacheProtected(messages, frozenToolCallIds);
57888
58102
  if (cacheProtectedMessageCount > 0) {
57889
58103
  log4.debug("Preserving cache-protected prompt prefix", {
57890
58104
  cacheProtectedMessageCount,
57891
58105
  cacheProtectedTokens,
57892
- tokensBefore
58106
+ tokensBefore,
58107
+ cacheReclaim
57893
58108
  });
57894
58109
  }
57895
58110
  return {
@@ -57899,23 +58114,24 @@ function computeMicrocompactTriggerState(messages, options2, config3) {
57899
58114
  frozenToolCallIds,
57900
58115
  nearWindowCeiling,
57901
58116
  proactiveTrigger,
58117
+ cacheReclaim,
57902
58118
  cacheProtectedMessageCount,
57903
58119
  cacheProtectedTokens
57904
58120
  };
57905
58121
  }
57906
- function resolveEffectiveMinSaveTokens(config3, noCache, proactiveTrigger, nearWindowCeiling) {
58122
+ function resolveEffectiveMinSaveTokens(config3, noCache, proactiveTrigger, nearWindowCeiling, cacheReclaim) {
57907
58123
  if (noCache) {
57908
58124
  return Math.min(
57909
58125
  Math.floor(config3.minSaveTokens * MICROCOMPACT_NO_CACHE_AGGRESSION_FACTOR),
57910
58126
  config3.proactiveMinSaveTokens
57911
58127
  );
57912
58128
  }
57913
- if (proactiveTrigger && !nearWindowCeiling) {
58129
+ if ((proactiveTrigger || cacheReclaim) && !nearWindowCeiling) {
57914
58130
  return config3.proactiveMinSaveTokens;
57915
58131
  }
57916
58132
  return config3.minSaveTokens;
57917
58133
  }
57918
- function resolveEffectiveKeepTokens(config3, noCache, proactiveTrigger, nearWindowCeiling) {
58134
+ function resolveEffectiveKeepTokens(config3, noCache, proactiveTrigger, nearWindowCeiling, cacheReclaim) {
57919
58135
  if (noCache) {
57920
58136
  return Math.min(
57921
58137
  config3.keepTokens,
@@ -57923,7 +58139,7 @@ function resolveEffectiveKeepTokens(config3, noCache, proactiveTrigger, nearWind
57923
58139
  MICROCOMPACT_NO_CACHE_KEEP_TOKENS
57924
58140
  );
57925
58141
  }
57926
- if (proactiveTrigger && !nearWindowCeiling) {
58142
+ if ((proactiveTrigger || cacheReclaim) && !nearWindowCeiling) {
57927
58143
  return Math.min(config3.keepTokens, config3.proactiveKeepTokens);
57928
58144
  }
57929
58145
  return config3.keepTokens;
@@ -57936,13 +58152,15 @@ function resolveMicrocompactThresholds(config3, trigger) {
57936
58152
  config3,
57937
58153
  trigger.noCache,
57938
58154
  trigger.proactiveTrigger,
57939
- trigger.nearWindowCeiling
58155
+ trigger.nearWindowCeiling,
58156
+ trigger.cacheReclaim
57940
58157
  );
57941
58158
  const effectiveKeepTokens = resolveEffectiveKeepTokens(
57942
58159
  config3,
57943
58160
  trigger.noCache,
57944
58161
  trigger.proactiveTrigger,
57945
- trigger.nearWindowCeiling
58162
+ trigger.nearWindowCeiling,
58163
+ trigger.cacheReclaim
57946
58164
  );
57947
58165
  const effectiveDigestMinChars = resolveEffectiveDigestMinChars(config3, trigger.noCache);
57948
58166
  if (trigger.noCache) {
@@ -58037,8 +58255,8 @@ function shouldSkipPrefixRewriteForCacheEconomics(trigger, options2, messages, c
58037
58255
  const projected = projectClearedMessages(messages, clearCandidates);
58038
58256
  return !isMicrocompactRewriteCheaperThanKeep(previousWire, messages, projected);
58039
58257
  }
58040
- function isUnprotectedInTurnCandidate(trigger, options2, messages, index4) {
58041
- if (!trigger.nearWindowCeiling) {
58258
+ function isUnprotectedFrozenCandidate(trigger, options2, messages, index4) {
58259
+ if (!trigger.nearWindowCeiling && !trigger.cacheReclaim) {
58042
58260
  return false;
58043
58261
  }
58044
58262
  const message = messages[index4];
@@ -58056,7 +58274,7 @@ function selectCacheEconomicClearCandidates(trigger, options2, messages, clearCa
58056
58274
  }
58057
58275
  const prefixLength = options2.previousWire?.length ?? 0;
58058
58276
  return clearCandidates.filter(function isAllowedRewrite(index4) {
58059
- return index4 >= prefixLength || isUnprotectedInTurnCandidate(trigger, options2, messages, index4);
58277
+ return index4 >= prefixLength || isUnprotectedFrozenCandidate(trigger, options2, messages, index4);
58060
58278
  });
58061
58279
  }
58062
58280
  async function applyMicrocompactClearance(params) {
@@ -58087,7 +58305,7 @@ async function microcompactMessages(messages, options2 = {}) {
58087
58305
  }
58088
58306
  const config3 = resolveMicrocompactConfig(options2);
58089
58307
  const trigger = computeMicrocompactTriggerState(messages, options2, config3);
58090
- if (!trigger.nearWindowCeiling && !trigger.proactiveTrigger) {
58308
+ if (!trigger.nearWindowCeiling && !trigger.proactiveTrigger && !trigger.cacheReclaim) {
58091
58309
  return unchangedMicrocompactResult(messages, emptyStats2, trigger.tokensBefore);
58092
58310
  }
58093
58311
  const { effectiveMinSaveTokens, effectiveKeepTokens, effectiveDigestMinChars } = resolveMicrocompactThresholds(config3, trigger);
@@ -58790,7 +59008,12 @@ async function reconcileInterruptedSessionTurns(db, sessionId, sessionEntryCurso
58790
59008
  if (earliestOpenStart === null) {
58791
59009
  return 0;
58792
59010
  }
58793
- const entries = await loadSessionEntriesFrom(db, sessionId, earliestOpenStart, sessionEntryCursor);
59011
+ const entries = await loadSessionEntriesFrom(
59012
+ db,
59013
+ sessionId,
59014
+ earliestOpenStart,
59015
+ sessionEntryCursor
59016
+ );
58794
59017
  let reconciledCount = 0;
58795
59018
  for (let index4 = 0; index4 < turns.length; index4 += 1) {
58796
59019
  const reconciled = await reconcileOpenTurn(
@@ -59183,6 +59406,10 @@ async function clearConversationHistory(db, threadId, conversationId) {
59183
59406
  {
59184
59407
  sql: "DELETE FROM conversation_reads WHERE threadId = ? AND conversationId = ?",
59185
59408
  args: [threadId, conversationId]
59409
+ },
59410
+ {
59411
+ sql: "DELETE FROM conversation_completions WHERE threadId = ? AND conversationId = ?",
59412
+ args: [threadId, conversationId]
59186
59413
  }
59187
59414
  ],
59188
59415
  "write"
@@ -59535,7 +59762,13 @@ async function getRecentConversations(db, limit3, offset = 0, projectId, exclude
59535
59762
  AND last_turn.status = 'active'
59536
59763
  ORDER BY last_turn.timestamp DESC
59537
59764
  LIMIT 1
59538
- ) as model
59765
+ ) as model,
59766
+ EXISTS (
59767
+ SELECT 1
59768
+ FROM conversation_completions completions
59769
+ WHERE completions.threadId = recent.threadId
59770
+ AND completions.conversationId = recent.conversationId
59771
+ ) as isComplete
59539
59772
  FROM recent_conversations recent
59540
59773
  INNER JOIN (
59541
59774
  SELECT threadId, conversationId, input_tokens, output_tokens
@@ -59573,6 +59806,23 @@ async function markConversationRead(db, threadId, conversationId) {
59573
59806
  throw error2;
59574
59807
  }
59575
59808
  }
59809
+ async function markConversationComplete(db, threadId, conversationId) {
59810
+ await db.execute(
59811
+ `
59812
+ INSERT INTO conversation_completions (threadId, conversationId, completedAt)
59813
+ VALUES (?, ?, ?)
59814
+ ON CONFLICT (threadId, conversationId)
59815
+ DO UPDATE SET completedAt = excluded.completedAt
59816
+ `,
59817
+ [threadId, conversationId, (/* @__PURE__ */ new Date()).toISOString()]
59818
+ );
59819
+ }
59820
+ async function unmarkConversationComplete(db, threadId, conversationId) {
59821
+ await db.execute(
59822
+ "DELETE FROM conversation_completions WHERE threadId = ? AND conversationId = ?",
59823
+ [threadId, conversationId]
59824
+ );
59825
+ }
59576
59826
  async function unmarkConversationRead(db, threadId, conversationId) {
59577
59827
  try {
59578
59828
  await db.execute("DELETE FROM conversation_reads WHERE threadId = ? AND conversationId = ?", [
@@ -59669,6 +59919,7 @@ async function purgeAllConversationHistory(db) {
59669
59919
  [
59670
59920
  "DELETE FROM agent_sessions",
59671
59921
  "DELETE FROM conversation_reads",
59922
+ "DELETE FROM conversation_completions",
59672
59923
  "DELETE FROM conversation_history"
59673
59924
  ],
59674
59925
  "write"
@@ -59690,6 +59941,10 @@ async function purgeConversationHistoryForThread(db, threadId) {
59690
59941
  sql: "DELETE FROM conversation_reads WHERE threadId = ?",
59691
59942
  args: [threadId]
59692
59943
  },
59944
+ {
59945
+ sql: "DELETE FROM conversation_completions WHERE threadId = ?",
59946
+ args: [threadId]
59947
+ },
59693
59948
  {
59694
59949
  sql: "DELETE FROM conversation_history WHERE threadId = ?",
59695
59950
  args: [threadId]
@@ -59724,6 +59979,15 @@ async function purgeConversationHistoryForProject(db, projectId) {
59724
59979
  `,
59725
59980
  args: [projectId]
59726
59981
  },
59982
+ {
59983
+ sql: `
59984
+ DELETE FROM conversation_completions
59985
+ WHERE threadId IN (
59986
+ SELECT threads.id FROM threads WHERE threads.projectId = ?
59987
+ )
59988
+ `,
59989
+ args: [projectId]
59990
+ },
59727
59991
  {
59728
59992
  sql: `
59729
59993
  DELETE FROM conversation_history
@@ -101161,7 +101425,7 @@ var require_gaxios = __commonJS({
101161
101425
  var retry_js_1 = require_retry3();
101162
101426
  var stream_1 = __require("stream");
101163
101427
  var interceptor_js_1 = require_interceptor();
101164
- var randomUUID27 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
101428
+ var randomUUID28 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
101165
101429
  var HTTP_STATUS_NO_CONTENT = 204;
101166
101430
  var Gaxios = class {
101167
101431
  agentCache = /* @__PURE__ */ new Map();
@@ -101434,7 +101698,7 @@ var require_gaxios = __commonJS({
101434
101698
  */
101435
101699
  ["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
101436
101700
  if (opts.multipart?.length) {
101437
- const boundary = await randomUUID27();
101701
+ const boundary = await randomUUID28();
101438
101702
  preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
101439
101703
  opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
101440
101704
  } else if (shouldDirectlyPassData) {
@@ -148366,6 +148630,24 @@ async function migrateConversationReads(db) {
148366
148630
  )
148367
148631
  `);
148368
148632
  }
148633
+ async function migrateConversationCompletions(db) {
148634
+ const exists = await db.execute(
148635
+ `SELECT name FROM sqlite_master WHERE type='table' AND name='conversation_completions'`
148636
+ );
148637
+ if (exists.rows.length > 0) {
148638
+ return;
148639
+ }
148640
+ tarskDebugLog("[db] Running migration: Creating conversation_completions table");
148641
+ await db.execute(`
148642
+ CREATE TABLE conversation_completions (
148643
+ threadId TEXT NOT NULL,
148644
+ conversationId TEXT NOT NULL,
148645
+ completedAt TEXT NOT NULL,
148646
+ PRIMARY KEY (threadId, conversationId),
148647
+ FOREIGN KEY (threadId) REFERENCES threads(id) ON DELETE CASCADE
148648
+ )
148649
+ `);
148650
+ }
148369
148651
  async function migrateCrossProjectLaunches(db) {
148370
148652
  const exists = await db.execute(
148371
148653
  `SELECT name FROM sqlite_master WHERE type='table' AND name='cross_project_launches'`
@@ -148467,6 +148749,7 @@ async function runMigrations(db) {
148467
148749
  await migrateConversationHistorySummary(db);
148468
148750
  await migrateConversationProcessingStarts(db);
148469
148751
  await migrateConversationReads(db);
148752
+ await migrateConversationCompletions(db);
148470
148753
  await migrateCrossProjectLaunches(db);
148471
148754
  await migrateCrossProjectRoutes(db);
148472
148755
  await migrateThreadsChatTitles(db);
@@ -148608,6 +148891,17 @@ var init_database = __esm({
148608
148891
  PRIMARY KEY (threadId, conversationId),
148609
148892
  FOREIGN KEY (threadId) REFERENCES threads(id) ON DELETE CASCADE
148610
148893
  )
148894
+ `,
148895
+ // Conversations completed after their pull request merged. A subsequent
148896
+ // user message clears the marker and makes the conversation active again.
148897
+ `
148898
+ CREATE TABLE IF NOT EXISTS conversation_completions (
148899
+ threadId TEXT NOT NULL,
148900
+ conversationId TEXT NOT NULL,
148901
+ completedAt TEXT NOT NULL,
148902
+ PRIMARY KEY (threadId, conversationId),
148903
+ FOREIGN KEY (threadId) REFERENCES threads(id) ON DELETE CASCADE
148904
+ )
148611
148905
  `,
148612
148906
  `
148613
148907
  CREATE TABLE IF NOT EXISTS cross_project_launches (
@@ -172245,6 +172539,9 @@ var init_conversation_prompt_snapshot = __esm({
172245
172539
 
172246
172540
  // src/agent/prompt-cache-fingerprint.ts
172247
172541
  import { createHash as createHash4 } from "node:crypto";
172542
+ function promptCacheLaneSessionId(sessionId, lane = "agent") {
172543
+ return lane === "compact" ? `${sessionId}:compact` : sessionId;
172544
+ }
172248
172545
  function readNumber(value2) {
172249
172546
  return typeof value2 === "number" && Number.isFinite(value2) && value2 > 0 ? value2 : 0;
172250
172547
  }
@@ -172316,6 +172613,33 @@ function hash(value2) {
172316
172613
  function hashCanonical(value2) {
172317
172614
  return hashSerialized(serializeCanonical(value2));
172318
172615
  }
172616
+ function touchTrackedMap(map3, key2, value2) {
172617
+ map3.delete(key2);
172618
+ map3.set(key2, value2);
172619
+ if (map3.size <= MAX_TRACKED_SESSIONS2) {
172620
+ return;
172621
+ }
172622
+ const oldest = map3.keys().next().value;
172623
+ if (oldest !== void 0) {
172624
+ map3.delete(oldest);
172625
+ }
172626
+ }
172627
+ function rollingCacheHitRateFromTotals(totals) {
172628
+ return calculatePromptCacheHitRate(
172629
+ totals.cacheReadTokens,
172630
+ billablePromptTokensFromCounts(
172631
+ totals.inputTokens,
172632
+ totals.cacheReadTokens,
172633
+ totals.cacheWriteTokens
172634
+ )
172635
+ );
172636
+ }
172637
+ function shouldWarnPromptCacheMiss(totals, implicitPromptCache) {
172638
+ if (implicitPromptCache || totals.calls < ZERO_CACHE_MIN_CALLS) {
172639
+ return false;
172640
+ }
172641
+ return rollingCacheHitRateFromTotals(totals) < ZERO_CACHE_HIT_RATE_THRESHOLD;
172642
+ }
172319
172643
  function extractPayloadSections(payload) {
172320
172644
  if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
172321
172645
  return { system: void 0, tools: void 0, messages: payload };
@@ -172436,9 +172760,10 @@ function applyStablePromptCacheKey(payload, model, provider, sessionId, baseUrl)
172436
172760
  prompt_cache_key: createStablePromptCacheKey(model, payload, provider)
172437
172761
  };
172438
172762
  }
172439
- function applyPromptCacheToProviderPayload(payload, modelId, provider, sessionId, baseUrl) {
172440
- const next = applyStablePromptCacheKey(payload, modelId, provider, sessionId, baseUrl);
172441
- recordPromptCacheFingerprint(sessionId, provider, modelId, next, baseUrl);
172763
+ function applyPromptCacheToProviderPayload(payload, modelId, provider, sessionId, baseUrl, lane = "agent") {
172764
+ const cacheSessionId = promptCacheLaneSessionId(sessionId, lane);
172765
+ const next = applyStablePromptCacheKey(payload, modelId, provider, cacheSessionId, baseUrl);
172766
+ recordPromptCacheFingerprint(cacheSessionId, provider, modelId, next, baseUrl);
172442
172767
  return next;
172443
172768
  }
172444
172769
  function promptCacheTurnMetrics(usage2, firstTurn) {
@@ -172503,9 +172828,10 @@ function recordPromptCacheUsage(sessionId, event) {
172503
172828
  totals.inputTokens += usage2.inputTokens;
172504
172829
  totals.cacheReadTokens += usage2.cacheReadTokens;
172505
172830
  totals.cacheWriteTokens += usage2.cacheWriteTokens;
172506
- usageBySession.set(sessionId, totals);
172831
+ touchTrackedMap(usageBySession, sessionId, totals);
172507
172832
  const last2 = lastFingerprintBySession.get(sessionId);
172508
172833
  const metrics = promptCacheTurnMetrics(usage2, last2?.firstTurn === true);
172834
+ const rollingHitRate = rollingCacheHitRateFromTotals(totals);
172509
172835
  if (last2?.firstTurn) {
172510
172836
  lastFingerprintBySession.set(sessionId, { ...last2, firstTurn: false });
172511
172837
  }
@@ -172514,6 +172840,7 @@ function recordPromptCacheUsage(sessionId, event) {
172514
172840
  sessionId,
172515
172841
  ...usage2,
172516
172842
  ...metrics,
172843
+ rollingHitRate,
172517
172844
  promptCacheKey: last2?.promptCacheKey,
172518
172845
  sessionAffinityId: last2?.sessionAffinityId,
172519
172846
  implicitPromptCache: last2?.implicitPromptCache,
@@ -172524,12 +172851,12 @@ function recordPromptCacheUsage(sessionId, event) {
172524
172851
  payloadBytes: last2?.fingerprint.payloadBytes,
172525
172852
  messageCount: last2?.fingerprint.messageHashes.length
172526
172853
  });
172527
- if (!warnedNoCacheSessions.has(sessionId) && !last2?.implicitPromptCache && totals.calls >= ZERO_CACHE_MIN_CALLS && metrics.cacheHitRate < ZERO_CACHE_HIT_RATE_THRESHOLD) {
172854
+ if (!warnedNoCacheSessions.has(sessionId) && shouldWarnPromptCacheMiss(totals, last2?.implicitPromptCache === true)) {
172528
172855
  warnedNoCacheSessions.add(sessionId);
172529
172856
  log35.warn("Prompt cache is not being hit for this session", {
172530
172857
  sessionId,
172531
172858
  calls: totals.calls,
172532
- cacheHitRate: metrics.cacheHitRate,
172859
+ cacheHitRate: rollingHitRate,
172533
172860
  cacheReadTokens: totals.cacheReadTokens,
172534
172861
  cacheWriteTokens: totals.cacheWriteTokens,
172535
172862
  inputTokens: totals.inputTokens,
@@ -172544,12 +172871,7 @@ function getSessionCacheHitRate(sessionId) {
172544
172871
  if (!totals || totals.calls < ZERO_CACHE_MIN_CALLS) {
172545
172872
  return void 0;
172546
172873
  }
172547
- const billable = billablePromptTokensFromCounts(
172548
- totals.inputTokens,
172549
- totals.cacheReadTokens,
172550
- totals.cacheWriteTokens
172551
- );
172552
- const cacheHitRate = calculatePromptCacheHitRate(totals.cacheReadTokens, billable);
172874
+ const cacheHitRate = rollingCacheHitRateFromTotals(totals);
172553
172875
  if (last2?.implicitPromptCache && cacheHitRate < ZERO_CACHE_HIT_RATE_THRESHOLD) {
172554
172876
  return void 0;
172555
172877
  }
@@ -172566,7 +172888,7 @@ function logPromptCacheDiagnostics(sessionId) {
172566
172888
  totals.cacheReadTokens,
172567
172889
  totals.cacheWriteTokens
172568
172890
  );
172569
- const cacheHitRate = calculatePromptCacheHitRate(totals.cacheReadTokens, billablePromptTokens2);
172891
+ const cacheHitRate = rollingCacheHitRateFromTotals(totals);
172570
172892
  const caching = !last2?.implicitPromptCache && totals.calls >= ZERO_CACHE_MIN_CALLS && cacheHitRate < ZERO_CACHE_HIT_RATE_THRESHOLD ? "unavailable" : totals.cacheReadTokens > 0 ? "available" : "unknown";
172571
172893
  const diagnostics = {
172572
172894
  sessionId,
@@ -172592,7 +172914,6 @@ function logPromptCacheDiagnostics(sessionId) {
172592
172914
  });
172593
172915
  }
172594
172916
  log35.info("Prompt cache session diagnostics", diagnostics);
172595
- clearPromptCacheSessionState(sessionId);
172596
172917
  return diagnostics;
172597
172918
  }
172598
172919
  function clearPromptCacheSessionState(sessionId) {
@@ -172611,17 +172932,10 @@ function recordPromptCacheFingerprint(sessionId, provider, model, payload, baseU
172611
172932
  const fingerprint = createPromptCacheFingerprint(payload, previous);
172612
172933
  const promptCacheKey = extractPromptCacheKey(payload);
172613
172934
  const firstTurn = previous === void 0;
172614
- previousBySession.delete(key2);
172615
- previousBySession.set(key2, fingerprint);
172616
- if (previousBySession.size > MAX_TRACKED_SESSIONS2) {
172617
- const oldest = previousBySession.keys().next().value;
172618
- if (oldest !== void 0) {
172619
- previousBySession.delete(oldest);
172620
- }
172621
- }
172935
+ touchTrackedMap(previousBySession, key2, fingerprint);
172622
172936
  const sessionAffinityId = extractOpenRouterSessionId(payload);
172623
172937
  const implicitPromptCache = openRouterUsesImplicitPromptCache(model, baseUrl);
172624
- lastFingerprintBySession.set(sessionId, {
172938
+ touchTrackedMap(lastFingerprintBySession, sessionId, {
172625
172939
  fingerprint,
172626
172940
  promptCacheKey,
172627
172941
  sessionAffinityId,
@@ -173106,6 +173420,7 @@ async function executeSubagent(options2) {
173106
173420
  if (signal) signal.removeEventListener("abort", onAbort);
173107
173421
  unsubscribe();
173108
173422
  logPromptCacheDiagnostics(sessionId);
173423
+ clearPromptCacheSessionState(sessionId);
173109
173424
  await harness.close(SESSION_CONTEXT).catch((error2) => {
173110
173425
  log36.warn("Subagent cleanup failed", { error: error2 });
173111
173426
  });
@@ -177128,8 +177443,15 @@ function findFilesByBasenameInCwd(fileBasename, cwd, limit3) {
177128
177443
  try {
177129
177444
  const found = ts(`**/${fileBasename}`, {
177130
177445
  cwd,
177131
- dot: false,
177132
- ignore: ["**/node_modules/**", "**/.git/**"],
177446
+ dot: true,
177447
+ ignore: [
177448
+ "**/node_modules/**",
177449
+ "**/.git/**",
177450
+ "**/.hg/**",
177451
+ "**/.svn/**",
177452
+ "**/.jj/**",
177453
+ "**/.sl/**"
177454
+ ],
177133
177455
  nodir: true
177134
177456
  });
177135
177457
  return found.slice(0, limit3).map((match2) => match2.replace(/\\/g, "/"));
@@ -177137,6 +177459,39 @@ function findFilesByBasenameInCwd(fileBasename, cwd, limit3) {
177137
177459
  return [];
177138
177460
  }
177139
177461
  }
177462
+ function findHiddenDotSegmentPath(resolvedPath2, cwd) {
177463
+ const relativePath = relative4(cwd, resolvedPath2).replace(/\\/g, "/");
177464
+ if (!relativePath || relativePath.startsWith("..") || isAbsolute4(relativePath)) {
177465
+ return void 0;
177466
+ }
177467
+ const segments = relativePath.split("/").filter(Boolean);
177468
+ const rebuilt = [];
177469
+ let current = cwd;
177470
+ for (let index4 = 0; index4 < segments.length; index4++) {
177471
+ const segment = segments[index4];
177472
+ const next = resolvePath3(current, segment);
177473
+ if (fileExists(next)) {
177474
+ rebuilt.push(segment);
177475
+ current = next;
177476
+ continue;
177477
+ }
177478
+ if (segment.startsWith(".")) {
177479
+ return void 0;
177480
+ }
177481
+ const dotted = `.${segment}`;
177482
+ if (TOP_LEVEL_LAYOUT_SKIP.has(dotted)) {
177483
+ return void 0;
177484
+ }
177485
+ const remainder = segments.slice(index4 + 1);
177486
+ const candidateRel = [...rebuilt, dotted, ...remainder].join("/");
177487
+ const candidateAbs = resolvePath3(cwd, candidateRel);
177488
+ if (fileExists(candidateAbs)) {
177489
+ return candidateRel;
177490
+ }
177491
+ return void 0;
177492
+ }
177493
+ return void 0;
177494
+ }
177140
177495
  function segmentEditDistance(a2, b2) {
177141
177496
  if (a2 === b2) return 0;
177142
177497
  const al = a2.length;
@@ -177205,6 +177560,10 @@ function collectFileNotFoundHints(resolvedPath2, cwd) {
177205
177560
  if (suffixMatch && suffixMatch !== requestedRelative && suffixMatch !== ".") {
177206
177561
  return [`Try: ${suffixMatch}`];
177207
177562
  }
177563
+ const hiddenDotMatch = findHiddenDotSegmentPath(resolvedPath2, cwd);
177564
+ if (hiddenDotMatch && hiddenDotMatch !== requestedRelative) {
177565
+ return [`Try: ${hiddenDotMatch}`];
177566
+ }
177208
177567
  const siblingTypos = findSiblingNameTypos(resolvedPath2, cwd).filter(
177209
177568
  (match2) => match2 !== requestedRelative
177210
177569
  );
@@ -178900,7 +179259,7 @@ var init_tool_helpers = __esm({
178900
179259
 
178901
179260
  // src/tools/try-path-from-error.ts
178902
179261
  function extractTryPathFromError(error2) {
178903
- const pattern = /\bTry:\s*([A-Za-z0-9_./@+-]+\.[A-Za-z0-9]+|[A-Za-z0-9_./@+-]+\/[A-Za-z0-9_./@+-]+|[A-Za-z0-9_][A-Za-z0-9_./@+-]*)/g;
179262
+ const pattern = /\bTry:\s*(\.?[A-Za-z0-9_./@+-]+\.[A-Za-z0-9]+|\.?[A-Za-z0-9_./@+-]+\/[A-Za-z0-9_./@+-]+|\.?[A-Za-z0-9_][A-Za-z0-9_./@+-]*)/g;
178904
179263
  let match2;
178905
179264
  let lastValid = null;
178906
179265
  while ((match2 = pattern.exec(error2)) !== null) {
@@ -181663,20 +182022,34 @@ var init_grep = __esm({
181663
182022
  // src/tools/rip-grep.ts
181664
182023
  import { statSync as statSync8 } from "node:fs";
181665
182024
  import path9 from "node:path";
182025
+ function grepContentBudgetFor(input2) {
182026
+ return resolveGrepContentBudget({
182027
+ output_mode: input2.output_mode,
182028
+ head_limit: input2.head_limit,
182029
+ context: input2.context,
182030
+ "-C": input2["-C"],
182031
+ "-A": input2["-A"],
182032
+ "-B": input2["-B"]
182033
+ });
182034
+ }
181666
182035
  function resolveMaxOutputLines(input2, smartJsCapture) {
181667
- if (input2.head_limit === 0) {
182036
+ if (input2.head_limit === void 0 && smartJsCapture) {
181668
182037
  return void 0;
181669
182038
  }
181670
- if (input2.head_limit === void 0 && smartJsCapture) {
182039
+ const budget = grepContentBudgetFor(input2);
182040
+ if (budget.headLimit === 0) {
182041
+ return void 0;
182042
+ }
182043
+ if (input2.head_limit === 0 && !budget.headLimitScaled) {
181671
182044
  return void 0;
181672
182045
  }
181673
- return (input2.head_limit ?? DEFAULT_HEAD_LIMIT) + (input2.offset ?? 0) + 1;
182046
+ return (budget.headLimit ?? DEFAULT_GREP_HEAD_LIMIT) + (input2.offset ?? 0) + 1;
181674
182047
  }
181675
182048
  function applyHeadLimit(items, limit3, offset = 0) {
181676
182049
  if (limit3 === 0) {
181677
182050
  return { items: items.slice(offset), appliedLimit: void 0 };
181678
182051
  }
181679
- const effectiveLimit = limit3 ?? DEFAULT_HEAD_LIMIT;
182052
+ const effectiveLimit = limit3 ?? DEFAULT_GREP_HEAD_LIMIT;
181680
182053
  const sliced = items.slice(offset, offset + effectiveLimit);
181681
182054
  const wasTruncated = items.length - offset > effectiveLimit;
181682
182055
  return {
@@ -181756,14 +182129,11 @@ function buildRipgrepArgs(input2, fixedStrings = false, smartJsCapture = false)
181756
182129
  glob: glob2,
181757
182130
  type,
181758
182131
  output_mode = "content",
181759
- "-B": contextBefore,
181760
- "-A": contextAfter,
181761
- "-C": contextC,
181762
- context: context2,
181763
182132
  "-n": showLineNumbers = true,
181764
182133
  "-i": caseInsensitive = false,
181765
182134
  multiline = false
181766
182135
  } = input2;
182136
+ const budget = grepContentBudgetFor(input2);
181767
182137
  const args2 = ["--hidden", "--color=never"];
181768
182138
  if (fixedStrings) {
181769
182139
  args2.push("--fixed-strings");
@@ -181782,7 +182152,13 @@ function buildRipgrepArgs(input2, fixedStrings = false, smartJsCapture = false)
181782
182152
  if (smartJsCapture && output_mode === "count") args2.push("--with-filename");
181783
182153
  if (output_mode === "content") {
181784
182154
  if (hasExplicitGrepContext(input2)) {
181785
- appendContextArgs(args2, context2, contextC, contextBefore, contextAfter);
182155
+ appendContextArgs(
182156
+ args2,
182157
+ budget.context,
182158
+ budget.contextC,
182159
+ budget.contextBefore,
182160
+ budget.contextAfter
182161
+ );
181786
182162
  } else if (DEFAULT_GREP_CONTENT_CONTEXT > 0) {
181787
182163
  appendContextArgs(args2, void 0, DEFAULT_GREP_CONTENT_CONTEXT, void 0, void 0);
181788
182164
  }
@@ -181939,10 +182315,11 @@ function emptyMatchText(input2) {
181939
182315
  }
181940
182316
  return "No matches found";
181941
182317
  }
181942
- function formatContentResult(cwd, results, headLimit, offset, emptyText) {
182318
+ function formatContentResult(cwd, results, headLimit, offset, emptyText, budget) {
181943
182319
  const { items: limitedResults, appliedLimit } = applyHeadLimit(results, headLimit, offset);
181944
182320
  const finalLines = limitedResults.map((line) => relativizeContentLine(cwd, line));
181945
182321
  const limitInfo = formatLimitInfo(appliedLimit, offset > 0 ? offset : void 0);
182322
+ const budgetNotice = budget ? formatGrepContextBudgetNotice(budget) : "";
181946
182323
  let text;
181947
182324
  if (finalLines.length === 0) {
181948
182325
  text = emptyText;
@@ -181952,6 +182329,11 @@ function formatContentResult(cwd, results, headLimit, offset, emptyText) {
181952
182329
  logCompressOutput("grep.content", flat, compressed.text);
181953
182330
  text = compressed.applied ? `${GREP_CONTENT_BANNER}
181954
182331
  ${compressed.text}` : compressed.text;
182332
+ if (budgetNotice) {
182333
+ text += `
182334
+
182335
+ ${budgetNotice}`;
182336
+ }
181955
182337
  if (limitInfo) {
181956
182338
  text += `
181957
182339
 
@@ -182057,9 +182439,9 @@ function createRipGrepTool(cwd, options2) {
182057
182439
  }
182058
182440
  };
182059
182441
  }
182060
- function formatOutputByMode(cwd, results, outputMode, headLimit, offset, emptyText) {
182442
+ function formatOutputByMode(cwd, results, outputMode, headLimit, offset, emptyText, budget) {
182061
182443
  if (outputMode === "content") {
182062
- return formatContentResult(cwd, results, headLimit, offset, emptyText);
182444
+ return formatContentResult(cwd, results, headLimit, offset, emptyText, budget);
182063
182445
  }
182064
182446
  if (outputMode === "count") {
182065
182447
  return formatCountResult(cwd, results, headLimit, offset, emptyText);
@@ -182159,11 +182541,19 @@ function selectRawRipgrepCaptureSource(mode, input2, ordered) {
182159
182541
  return mode === "content" && !hasExplicitGrepContext(input2) ? ordered.filter(isGrepContentMatchLine) : ordered;
182160
182542
  }
182161
182543
  function resolveRawRipgrepDisplayLimit(input2) {
182162
- return input2.head_limit === 0 ? 0 : input2.head_limit ?? DEFAULT_HEAD_LIMIT;
182544
+ const budget = grepContentBudgetFor(input2);
182545
+ if (budget.headLimit === 0) {
182546
+ return 0;
182547
+ }
182548
+ return budget.headLimit ?? DEFAULT_GREP_HEAD_LIMIT;
182163
182549
  }
182164
182550
  function buildRawRipgrepText(params) {
182165
182551
  const { searchedAsLiteral, skippedPaths, displayItems, emptyText, diagnostics } = params;
182166
182552
  let text = `${buildPrefixNotices(searchedAsLiteral, skippedPaths)}${displayItems.join("\n") || emptyText}${diagnostics}`;
182553
+ const budgetNotice = params.budget ? formatGrepContextBudgetNotice(params.budget) : "";
182554
+ if (budgetNotice) text += `
182555
+
182556
+ ${budgetNotice}`;
182167
182557
  const limitInfo = formatLimitInfo(params.appliedLimit, params.offset ? params.offset : void 0);
182168
182558
  if (limitInfo) text += `
182169
182559
 
@@ -182205,7 +182595,8 @@ ${capture.diagnostics.join("\n")}` : "";
182205
182595
  emptyText,
182206
182596
  diagnostics,
182207
182597
  appliedLimit,
182208
- offset: input2.offset
182598
+ offset: input2.offset,
182599
+ budget: grepContentBudgetFor(input2)
182209
182600
  });
182210
182601
  const details = buildRawRipgrepDetails({
182211
182602
  mode,
@@ -182236,7 +182627,8 @@ async function executeRipgrepSearch(cwd, input2, smartJsCapture = false, signal)
182236
182627
  return executeRawRipgrepSearch(cwd, effectiveInput, absolutePaths, skippedPaths, runOptions);
182237
182628
  }
182238
182629
  const outputMode = effectiveInput.output_mode ?? "content";
182239
- const headLimit = effectiveInput.head_limit;
182630
+ const budget = grepContentBudgetFor(effectiveInput);
182631
+ const headLimit = budget.headLimit;
182240
182632
  const offset = effectiveInput.offset ?? 0;
182241
182633
  const { results, searchedAsLiteral } = await runRipgrepMultiWithLiteralFallback(
182242
182634
  { ...effectiveInput, output_mode: outputMode },
@@ -182250,7 +182642,8 @@ async function executeRipgrepSearch(cwd, input2, smartJsCapture = false, signal)
182250
182642
  outputMode,
182251
182643
  headLimit,
182252
182644
  offset,
182253
- emptyMatchText(effectiveInput)
182645
+ emptyMatchText(effectiveInput),
182646
+ budget
182254
182647
  );
182255
182648
  const truncation = truncateHead2(formatted.text);
182256
182649
  const trailing = buildTrailingNotice(truncation);
@@ -182281,7 +182674,7 @@ async function executeRipgrepSearch(cwd, input2, smartJsCapture = false, signal)
182281
182674
  details: Object.keys(details).length > 0 ? details : void 0
182282
182675
  };
182283
182676
  }
182284
- var VCS_DIRECTORIES_TO_EXCLUDE, DEFAULT_HEAD_LIMIT, DEFAULT_GREP_CONTENT_CONTEXT, GREP_TOOL_DESCRIPTION, ripGrepSchema, log40, PATHLESS_CONTENT_LINE2, REGEX_PARSE_ERROR_RE, REGEX_PARSE_HINT, LITERAL_FALLBACK_NOTICE;
182677
+ var VCS_DIRECTORIES_TO_EXCLUDE, GREP_TOOL_DESCRIPTION, ripGrepSchema, log40, PATHLESS_CONTENT_LINE2, REGEX_PARSE_ERROR_RE, REGEX_PARSE_HINT, LITERAL_FALLBACK_NOTICE;
182285
182678
  var init_rip_grep = __esm({
182286
182679
  "src/tools/rip-grep.ts"() {
182287
182680
  "use strict";
@@ -182304,8 +182697,6 @@ var init_rip_grep = __esm({
182304
182697
  "node_modules",
182305
182698
  ".bun"
182306
182699
  ];
182307
- DEFAULT_HEAD_LIMIT = 40;
182308
- DEFAULT_GREP_CONTENT_CONTEXT = 0;
182309
182700
  GREP_TOOL_DESCRIPTION = "Search file contents with regex (ripgrep-compatible grepts). Use read directly when the exact file path is already known. Content mode defaults to match lines only (-C 0); pass -C 3 (or -A/-B/context) when you need nearby lines for a unique edit hunk. Batch independent searches in one turn. output_mode: content (default; -A/-B/-C/context/-n apply here, -n defaults true), files_with_matches, count. Scope with path; glob for name/extension (*.ts, **/*.tsx)\u2014not a path substitute. type = rg --type. head_limit default 40 (0=unlimited); offset skips. multiline: . matches newlines. Respects .gitignore.";
182310
182701
  ripGrepSchema = Type2.Object({
182311
182702
  pattern: Type2.String(),
@@ -187166,13 +187557,50 @@ function normalizeSkillRef(input2) {
187166
187557
  }
187167
187558
  return { value: trimmed };
187168
187559
  }
187560
+ function stripTaskIdTruncation(id) {
187561
+ const trimmed = id.trim();
187562
+ const cleaned = trimmed.replace(/(?:\.{2,}|[?…]+)+$/u, "");
187563
+ return { cleaned, truncated: cleaned !== trimmed };
187564
+ }
187565
+ function isUuidPrefix(value2) {
187566
+ if (value2.length < 8 || value2.length >= 36) return false;
187567
+ return /^[0-9a-f]{8}(?:-[0-9a-f]{0,4}){0,4}[0-9a-f]*$/i.test(value2);
187568
+ }
187569
+ function formatTaskIdSuggestions(matches) {
187570
+ return matches.map((task) => ` - ${task.id}: ${task.title}`).join("\n");
187571
+ }
187572
+ async function resolveTaskById(db, projectId, rawId) {
187573
+ const { cleaned, truncated } = stripTaskIdTruncation(rawId);
187574
+ const exact = await getTaskById(db, rawId);
187575
+ if (exact && exact.projectId === projectId) {
187576
+ return { ok: true, id: exact.id, task: exact };
187577
+ }
187578
+ if (cleaned !== rawId) {
187579
+ const cleanedMatch = await getTaskById(db, cleaned);
187580
+ if (cleanedMatch && cleanedMatch.projectId === projectId) {
187581
+ return { ok: true, id: cleanedMatch.id, task: cleanedMatch };
187582
+ }
187583
+ }
187584
+ if (truncated || isUuidPrefix(cleaned)) {
187585
+ const matches = (await getTasksByProject(db, projectId)).filter(
187586
+ (task) => task.id.toLowerCase().startsWith(cleaned.toLowerCase())
187587
+ );
187588
+ if (matches.length === 1) {
187589
+ return { ok: true, id: matches[0].id, task: matches[0] };
187590
+ }
187591
+ if (matches.length > 1) {
187592
+ return {
187593
+ ok: false,
187594
+ error: `Error: task not found: ${rawId}. Similar ids:
187595
+ ${formatTaskIdSuggestions(matches)}`
187596
+ };
187597
+ }
187598
+ }
187599
+ return { ok: false, error: `Error: task not found: ${rawId}` };
187600
+ }
187169
187601
  async function resolveTaskReference(db, projectId, id, reference, action) {
187170
187602
  if (id?.trim()) {
187171
- const existing = await getTaskById(db, id);
187172
- if (!existing || existing.projectId !== projectId) {
187173
- return { ok: false, error: `Error: task not found: ${id}` };
187174
- }
187175
- return { ok: true, id, task: existing };
187603
+ return resolveTaskById(db, projectId, id.trim());
187176
187604
  }
187177
187605
  if (reference?.trim()) {
187178
187606
  const { exact, contains } = await findTasksByReference(db, projectId, reference.trim());
@@ -187398,8 +187826,14 @@ function createTasksTool(projectId, threadId, executionDeps) {
187398
187826
  if (tagIds) {
187399
187827
  rows = rows.filter((task) => tagIds.has(task.id));
187400
187828
  }
187829
+ const serialized = await serializeTasksWithTags(db, rows);
187401
187830
  const payload = {
187402
- tasks: rows.map((task) => ({ id: task.id, title: task.title, status: task.status }))
187831
+ tasks: serialized.map((task) => ({
187832
+ id: task.id,
187833
+ title: task.title,
187834
+ status: task.status,
187835
+ tags: task.tags.map((tag) => tag.name)
187836
+ }))
187403
187837
  };
187404
187838
  if (trimmedQuery) payload.query = trimmedQuery;
187405
187839
  return jsonResult(payload);
@@ -187628,7 +188062,7 @@ var init_tasks = __esm({
187628
188062
  init_task_trigger_validation();
187629
188063
  init_task_default_model();
187630
188064
  VALID_STATUSES = ["Ready", "Plan", "Build", "Test", "Review", "Done"];
187631
- TASKS_TOOL_DESCRIPTION = "Project tasks. add/schedule: title+description required; optional tags, skillRef, trigger. list: id/title/status, hides Done; filter query/status/tags. get: full task. tags: vocabulary+counts. update any field (null clears trigger/skill). implement this chat; runNow new thread (scheduled/event only). delete. Target by id or unique reference. Skills load only at run.";
188065
+ TASKS_TOOL_DESCRIPTION = "Project tasks. add/schedule: title+description required; optional tags, skillRef, trigger. list: id/title/status/tags, hides Done; filter query/status/tags. get: full task. tags: vocabulary+counts. update any field (null clears trigger/skill). implement this chat; runNow new thread (scheduled/event only). delete. Target by id or unique reference. Truncated ids resolve when unique. Skills load only at run.";
187632
188066
  tasksSchema = Type2.Object({
187633
188067
  action: Type2.Union([
187634
188068
  Type2.Literal("add"),
@@ -218227,8 +218661,8 @@ async function resolveInlineLlmModel(metadataManager, options2) {
218227
218661
  const resolved = await resolveModelAndKey(options2.provider, options2.model, metadataManager);
218228
218662
  return resolved ? { ...resolved, provider: options2.provider } : null;
218229
218663
  }
218664
+ const db = await getDatabase();
218230
218665
  if (options2.threadId) {
218231
- const db = await getDatabase();
218232
218666
  const thread = await getThread(db, options2.threadId);
218233
218667
  if (thread?.modelProvider && thread.model) {
218234
218668
  const resolved = await resolveModelAndKey(
@@ -218239,14 +218673,28 @@ async function resolveInlineLlmModel(metadataManager, options2) {
218239
218673
  return resolved ? { ...resolved, provider: thread.modelProvider } : null;
218240
218674
  }
218241
218675
  }
218676
+ try {
218677
+ const defaultAlias = resolveModelAlias("default", await getModelAliases(db));
218678
+ if (defaultAlias) {
218679
+ const resolved = await resolveModelAndKey(
218680
+ defaultAlias.provider,
218681
+ defaultAlias.model,
218682
+ metadataManager
218683
+ );
218684
+ return resolved ? { ...resolved, provider: defaultAlias.provider } : null;
218685
+ }
218686
+ } catch {
218687
+ }
218242
218688
  return null;
218243
218689
  }
218244
218690
  var init_inline_model = __esm({
218245
218691
  "src/core/inline-model.ts"() {
218246
218692
  "use strict";
218693
+ init_dist();
218247
218694
  init_git_utils();
218248
218695
  init_database();
218249
218696
  init_threads_database();
218697
+ init_model_aliases_store();
218250
218698
  }
218251
218699
  });
218252
218700
 
@@ -223326,6 +223774,8 @@ var init_agent_executor_run = __esm({
223326
223774
  usageCompactCount = 0;
223327
223775
  pendingUsageCompact = false;
223328
223776
  skipUsageCompactOnce = false;
223777
+ /** Compact/rollover payloads must not share the agent prompt-cache lane. */
223778
+ compactPayloadLane = false;
223329
223779
  incompleteStopResumeCount = 0;
223330
223780
  observationHandler;
223331
223781
  harness;
@@ -223665,12 +224115,14 @@ ${prompt}` : prompt;
223665
224115
  }
223666
224116
  registerHarnessPayloadHandler() {
223667
224117
  this.harness.hooks.on("before_payload", (event) => {
224118
+ const lane = this.compactPayloadLane ? "compact" : "agent";
223668
224119
  const payload = applyPromptCacheToProviderPayload(
223669
224120
  compactToolSchemasInPayload(event.payload),
223670
224121
  event.model.id,
223671
224122
  event.model.provider,
223672
224123
  this.sessionMetadata.id,
223673
- event.model.baseUrl
224124
+ event.model.baseUrl,
224125
+ lane
223674
224126
  );
223675
224127
  return { payload };
223676
224128
  });
@@ -223819,36 +224271,51 @@ ${prompt}` : prompt;
223819
224271
  return 0;
223820
224272
  }
223821
224273
  }
224274
+ async withCompactCacheLane(run) {
224275
+ this.compactPayloadLane = true;
224276
+ try {
224277
+ return await run();
224278
+ } finally {
224279
+ this.compactPayloadLane = false;
224280
+ }
224281
+ }
223822
224282
  async compactForOverflowResume(notice = OVERFLOW_COMPACT_NOTICE) {
223823
224283
  await this.lane.waitForIdle(this.runContext);
223824
224284
  const messagesBefore = await this.countSessionUserMessages();
223825
224285
  const contextBefore = await readContextMessages(this.session, this.runContext);
223826
224286
  const tokensBefore = estimateContextTokens(contextBefore).tokens;
223827
- if (this.persistentTurn && this.context.conversationId && this.context.projectId) {
223828
- await rolloverConversationContext(
223829
- {
223830
- db: this.persistentTurn.db,
223831
- harness: this.harness,
223832
- lane: this.lane,
223833
- session: this.session,
223834
- projectId: this.context.projectId,
223835
- threadId: this.context.threadId,
223836
- conversationId: this.context.conversationId,
223837
- requestModel: normalizeCompactModelId(
223838
- this.model,
223839
- this.providerName,
223840
- this.resolvedModel.id
223841
- ),
223842
- reason: this.pendingOverflowError ? "overflow" : "mid-turn",
223843
- projectMarker: false
223844
- },
223845
- this.runContext
224287
+ const persistentTurn = this.persistentTurn;
224288
+ const conversationId = this.context.conversationId;
224289
+ const projectId = this.context.projectId;
224290
+ if (persistentTurn && conversationId && projectId) {
224291
+ await this.withCompactCacheLane(
224292
+ () => rolloverConversationContext(
224293
+ {
224294
+ db: persistentTurn.db,
224295
+ harness: this.harness,
224296
+ lane: this.lane,
224297
+ session: this.session,
224298
+ projectId,
224299
+ threadId: this.context.threadId,
224300
+ conversationId,
224301
+ requestModel: normalizeCompactModelId(
224302
+ this.model,
224303
+ this.providerName,
224304
+ this.resolvedModel.id
224305
+ ),
224306
+ reason: this.pendingOverflowError ? "overflow" : "mid-turn",
224307
+ projectMarker: false
224308
+ },
224309
+ this.runContext
224310
+ )
223846
224311
  );
223847
224312
  } else {
223848
- const result = await this.lane.compact(
223849
- { customInstructions: `${COMPACT_SUMMARY_PROMPT}
224313
+ const result = await this.withCompactCacheLane(
224314
+ () => this.lane.compact(
224315
+ { customInstructions: `${COMPACT_SUMMARY_PROMPT}
223850
224316
  ${OVERFLOW_COMPACT_FOCUS}` },
223851
- this.runContext
224317
+ this.runContext
224318
+ )
223852
224319
  );
223853
224320
  if (Result.isErr(result)) {
223854
224321
  throw new Error(`Overflow compaction failed: ${result.error.message}`);
@@ -223918,7 +224385,6 @@ ${OVERFLOW_COMPACT_FOCUS}` },
223918
224385
  });
223919
224386
  return;
223920
224387
  }
223921
- clearPromptCacheSessionState(this.sessionMetadata.id);
223922
224388
  handlePromptError(err2, {
223923
224389
  eventQueue: this.eventQueue,
223924
224390
  promptRequest: this.promptRequest
@@ -226734,6 +227200,49 @@ var init_stream_helper = __esm({
226734
227200
  }
226735
227201
  });
226736
227202
 
227203
+ // src/features/chat/chat-auto-route.service.ts
227204
+ async function routePromptToDecision(prompt, aliases, metadataManager, dependencies = {}) {
227205
+ const router = resolveAutoRouteModelAlias(aliases);
227206
+ if (!router || !prompt.trim()) {
227207
+ return "default";
227208
+ }
227209
+ try {
227210
+ const modelResolver = dependencies.modelResolver ?? resolveModelAndKey;
227211
+ const resolved = await modelResolver(router.provider, router.model, metadataManager);
227212
+ if (!resolved) {
227213
+ return "default";
227214
+ }
227215
+ const complete = dependencies.complete ?? completeSimpleWithSpend;
227216
+ const response = await complete(
227217
+ resolved.model,
227218
+ {
227219
+ systemPrompt: AUTO_ROUTE_SYSTEM_PROMPT,
227220
+ messages: [
227221
+ {
227222
+ role: "user",
227223
+ content: prompt.trim(),
227224
+ timestamp: Date.now()
227225
+ }
227226
+ ]
227227
+ },
227228
+ { apiKey: resolved.apiKey },
227229
+ router.provider
227230
+ );
227231
+ const raw2 = response.content.filter((block) => block.type === "text").map((block) => block.text).join("").trim();
227232
+ return parseAutoRouteDecision(raw2) ?? "default";
227233
+ } catch {
227234
+ return "default";
227235
+ }
227236
+ }
227237
+ var init_chat_auto_route_service = __esm({
227238
+ "src/features/chat/chat-auto-route.service.ts"() {
227239
+ "use strict";
227240
+ init_dist();
227241
+ init_git_utils();
227242
+ init_spend_record();
227243
+ }
227244
+ });
227245
+
226737
227246
  // src/core/runtime-log-level.ts
226738
227247
  function syncRuntimeLogLevel(isDebug2) {
226739
227248
  setLogLevel(
@@ -227661,7 +228170,9 @@ function prepareChatRequest(c, body) {
227661
228170
  conversationId: requestedConversationId,
227662
228171
  attribution: rawAttribution,
227663
228172
  idempotencyKey: rawIdempotencyKey,
227664
- hideUserMessage: rawHideUserMessage
228173
+ hideUserMessage: rawHideUserMessage,
228174
+ runInBackground: rawRunInBackground,
228175
+ autoRoute: rawAutoRoute
227665
228176
  } = body;
227666
228177
  if (!threadId || typeof threadId !== "string") {
227667
228178
  return {
@@ -227739,7 +228250,9 @@ function prepareChatRequest(c, body) {
227739
228250
  requestedConversationId,
227740
228251
  attribution: parseTurnAttribution(rawAttribution),
227741
228252
  ...idempotencyKey ? { idempotencyKey } : {},
227742
- hideUserMessage: rawHideUserMessage === true
228253
+ hideUserMessage: rawHideUserMessage === true,
228254
+ runInBackground: rawRunInBackground === true,
228255
+ autoRoute: rawAutoRoute === true
227743
228256
  }
227744
228257
  };
227745
228258
  }
@@ -227888,7 +228401,9 @@ async function launchReservedChatTurn(args2) {
227888
228401
  return args2.c.json({
227889
228402
  ok: true,
227890
228403
  threadId: args2.deps.activeThreadId,
227891
- conversationId: args2.deps.conversationId
228404
+ conversationId: args2.deps.conversationId,
228405
+ model: args2.deps.model,
228406
+ provider: args2.deps.provider
227892
228407
  });
227893
228408
  }
227894
228409
  return streamAsyncGenerator(args2.c, withCompleteSignal(), {
@@ -228033,7 +228548,9 @@ async function postChatMessage(c, threadManager, agentExecutor, conversationMana
228033
228548
  requestedConversationId,
228034
228549
  attribution,
228035
228550
  idempotencyKey,
228036
- hideUserMessage
228551
+ autoRoute,
228552
+ hideUserMessage,
228553
+ runInBackground
228037
228554
  } = prepared.request;
228038
228555
  let provider = rawProvider;
228039
228556
  let model = baseModel;
@@ -228075,15 +228592,23 @@ async function postChatMessage(c, threadManager, agentExecutor, conversationMana
228075
228592
  });
228076
228593
  return conversationBusyResponse(c, activeThreadId, conversationId);
228077
228594
  }
228595
+ const db = await getDatabase();
228596
+ const project = await getProject(db, thread.projectId);
228597
+ const seatbeltSandboxEnabled = await resolveSeatbeltSandboxEnabled(db);
228598
+ const modelAliases = await getModelAliases(db);
228599
+ if (autoRoute) {
228600
+ const decision = await routePromptToDecision(userContent, modelAliases, metadataManager);
228601
+ const routedAlias = decision === "cheap" ? resolveModelAlias("cheap", modelAliases) : decision === "smart" ? resolveSmartModelAlias(modelAliases) : null;
228602
+ if (routedAlias) {
228603
+ model = routedAlias.model;
228604
+ provider = routedAlias.provider;
228605
+ }
228606
+ }
228078
228607
  const { availableSkills, activatedSkills, agents } = await loadSkillAndAgentContext(
228079
228608
  thread,
228080
228609
  threadPath,
228081
228610
  userContent
228082
228611
  );
228083
- const db = await getDatabase();
228084
- const project = await getProject(db, thread.projectId);
228085
- const seatbeltSandboxEnabled = await resolveSeatbeltSandboxEnabled(db);
228086
- const modelAliases = await getModelAliases(db);
228087
228612
  const orchestrated = resolveOrchestrateModel(c, modelAliases, orchestrateMode, model, provider);
228088
228613
  if (!orchestrated.ok) {
228089
228614
  return orchestrated.response;
@@ -228130,7 +228655,10 @@ async function postChatMessage(c, threadManager, agentExecutor, conversationMana
228130
228655
  reservedRun = { threadId: activeThreadId, conversationId };
228131
228656
  return captureMessageAndLaunch({
228132
228657
  c,
228133
- options: options2,
228658
+ options: {
228659
+ ...options2,
228660
+ runInBackground: options2?.runInBackground === true || runInBackground === true
228661
+ },
228134
228662
  thread,
228135
228663
  threadManager,
228136
228664
  conversationManager,
@@ -228185,6 +228713,7 @@ var init_chat_post_route = __esm({
228185
228713
  init_conversations_content();
228186
228714
  init_route_helpers();
228187
228715
  init_error_responses();
228716
+ init_chat_auto_route_service();
228188
228717
  init_database();
228189
228718
  init_database_state();
228190
228719
  init_account_settings_route();
@@ -228351,6 +228880,17 @@ function buildMessageMetadata(tokenCount, estimatedCost, processingTimeMs) {
228351
228880
  };
228352
228881
  }
228353
228882
  function buildAgentMessage(message, response, pricingByModelId, threadModelId) {
228883
+ if (isTarskAgentNoteModel(message.request.model)) {
228884
+ const { content: sanitizedContent2 } = sanitizeStructuredMessageContent(response.content);
228885
+ return {
228886
+ messageId: `agent-${message.id}`,
228887
+ sender: "agent",
228888
+ content: sanitizedContent2,
228889
+ contentType: "markdown",
228890
+ timestamp: response.completedAt,
228891
+ senderLabel: TARSK_AGENT_NOTE_LABEL
228892
+ };
228893
+ }
228354
228894
  const usageFromEvents = extractUsageFromEvents(response.events);
228355
228895
  const tokenCount = resolveTokenCount(usageFromEvents, message);
228356
228896
  const estimatedCost = resolveEstimatedCost(
@@ -228497,49 +229037,6 @@ var init_chat_compact_route = __esm({
228497
229037
  }
228498
229038
  });
228499
229039
 
228500
- // src/features/chat/chat-auto-route.service.ts
228501
- async function routePromptToDecision(prompt, aliases, metadataManager, dependencies = {}) {
228502
- const router = resolveAutoRouteModelAlias(aliases);
228503
- if (!router || !prompt.trim()) {
228504
- return "default";
228505
- }
228506
- try {
228507
- const modelResolver = dependencies.modelResolver ?? resolveModelAndKey;
228508
- const resolved = await modelResolver(router.provider, router.model, metadataManager);
228509
- if (!resolved) {
228510
- return "default";
228511
- }
228512
- const complete = dependencies.complete ?? completeSimpleWithSpend;
228513
- const response = await complete(
228514
- resolved.model,
228515
- {
228516
- systemPrompt: AUTO_ROUTE_SYSTEM_PROMPT,
228517
- messages: [
228518
- {
228519
- role: "user",
228520
- content: prompt.trim(),
228521
- timestamp: Date.now()
228522
- }
228523
- ]
228524
- },
228525
- { apiKey: resolved.apiKey },
228526
- router.provider
228527
- );
228528
- const raw2 = response.content.filter((block) => block.type === "text").map((block) => block.text).join("").trim();
228529
- return parseAutoRouteDecision(raw2) ?? "default";
228530
- } catch {
228531
- return "default";
228532
- }
228533
- }
228534
- var init_chat_auto_route_service = __esm({
228535
- "src/features/chat/chat-auto-route.service.ts"() {
228536
- "use strict";
228537
- init_dist();
228538
- init_git_utils();
228539
- init_spend_record();
228540
- }
228541
- });
228542
-
228543
229040
  // src/features/chat/chat-auto-route.route.ts
228544
229041
  async function handleAutoRoute(c, threadManager, metadataManager) {
228545
229042
  const threadId = c.req.param("threadId");
@@ -228786,6 +229283,85 @@ var init_chat_delete_route = __esm({
228786
229283
  }
228787
229284
  });
228788
229285
 
229286
+ // src/features/chat/chat-agent-note.route.ts
229287
+ import { randomUUID as randomUUID17 } from "crypto";
229288
+ async function postAgentNote(c, threadManager, conversationManager) {
229289
+ try {
229290
+ const threadIdResult = requireThreadIdParam(c);
229291
+ if (!threadIdResult.ok) {
229292
+ return threadIdResult.response;
229293
+ }
229294
+ const { threadId } = threadIdResult;
229295
+ let body = {};
229296
+ try {
229297
+ body = await c.req.json();
229298
+ } catch {
229299
+ return errorResponse(c, ErrorCodes.REQUEST_PARSE_ERROR, "Invalid JSON body", 400);
229300
+ }
229301
+ const content = typeof body.content === "string" ? body.content.trim() : "";
229302
+ if (!content) {
229303
+ return errorResponse(c, ErrorCodes.INVALID_REQUEST, "content is required", 400);
229304
+ }
229305
+ const threadResult = await requireThread(c, threadManager, threadId);
229306
+ if (!threadResult.ok) {
229307
+ return threadResult.response;
229308
+ }
229309
+ const { thread } = threadResult;
229310
+ const requestedConversationId = typeof body.conversationId === "string" ? body.conversationId.trim() : "";
229311
+ let conversationId = requestedConversationId || thread.currentConversationId;
229312
+ if (!conversationId) {
229313
+ conversationId = randomUUID17();
229314
+ await threadManager.updateThread(threadId, { currentConversationId: conversationId });
229315
+ }
229316
+ const messageId = await conversationManager.startMessage(
229317
+ threadId,
229318
+ thread.path ?? "",
229319
+ conversationId,
229320
+ "",
229321
+ TARSK_AGENT_NOTE_MODEL
229322
+ );
229323
+ await conversationManager.completeMessage(messageId, content, [
229324
+ { type: "message", role: "assistant", content }
229325
+ ]);
229326
+ if (body.markComplete === true) {
229327
+ await conversationManager.markConversationComplete(threadId, conversationId);
229328
+ }
229329
+ const history2 = await conversationManager.getConversationHistoryByConversationId(
229330
+ threadId,
229331
+ conversationId
229332
+ );
229333
+ const inserted = history2?.messages.find((message) => message.id === messageId);
229334
+ if (!inserted) {
229335
+ return errorResponse(
229336
+ c,
229337
+ ErrorCodes.INTERNAL_ERROR,
229338
+ "Failed to load the inserted agent note",
229339
+ 500
229340
+ );
229341
+ }
229342
+ const [mapped] = mapConversationMessagesToThreadResponse([inserted]);
229343
+ return successResponse(c, mapped);
229344
+ } catch (error2) {
229345
+ return errorResponse(
229346
+ c,
229347
+ ErrorCodes.INTERNAL_ERROR,
229348
+ "Failed to insert agent note",
229349
+ 500,
229350
+ error2 instanceof Error ? error2.message : String(error2)
229351
+ );
229352
+ }
229353
+ }
229354
+ var init_chat_agent_note_route = __esm({
229355
+ "src/features/chat/chat-agent-note.route.ts"() {
229356
+ "use strict";
229357
+ init_dist();
229358
+ init_threads_messages_mapper();
229359
+ init_conversation_route_params();
229360
+ init_route_helpers();
229361
+ init_error_responses();
229362
+ }
229363
+ });
229364
+
228789
229365
  // src/features/chat/chat-subscribe.route.ts
228790
229366
  function flushPendingAssistantContent(state3, target) {
228791
229367
  const chunks = state3.pendingChunks;
@@ -229177,6 +229753,7 @@ function createChatRoutes(threadManager, agentExecutor, conversationManager, pro
229177
229753
  "/:threadId/workspace-handoff",
229178
229754
  (c) => handleWorkspaceHandoff(c, threadManager, conversationManager, metadataManager)
229179
229755
  );
229756
+ router.post("/:threadId/agent-note", (c) => postAgentNote(c, threadManager, conversationManager));
229180
229757
  router.post(
229181
229758
  "/:threadId/steer",
229182
229759
  (c) => steerChatMessage(c, agentExecutor, processingStateManager, conversationManager)
@@ -229196,6 +229773,7 @@ var init_chat_routes = __esm({
229196
229773
  init_chat_auto_route_route();
229197
229774
  init_chat_workspace_handoff_route();
229198
229775
  init_chat_delete_route();
229776
+ init_chat_agent_note_route();
229199
229777
  init_chat_subscribe_route();
229200
229778
  init_chat_buffer_route();
229201
229779
  init_chat_stop_route();
@@ -229284,6 +229862,9 @@ var init_conversations_manager = __esm({
229284
229862
  if (!this.db) {
229285
229863
  await this.initialize();
229286
229864
  }
229865
+ if (message.trim()) {
229866
+ await unmarkConversationComplete(this.db, threadId, conversationId);
229867
+ }
229287
229868
  const messageId = await insertMessage(
229288
229869
  this.db,
229289
229870
  threadId,
@@ -229590,6 +230171,14 @@ var init_conversations_manager = __esm({
229590
230171
  * Removes a conversation's read mark so it returns to the unread Chats
229591
230172
  * list. Used when the user resumes a chat from History.
229592
230173
  */
230174
+ async markConversationComplete(threadId, conversationId) {
230175
+ try {
230176
+ await markConversationComplete(this.db, threadId, conversationId);
230177
+ } catch (error2) {
230178
+ log83.error("Failed to mark conversation complete", { error: error2, threadId, conversationId });
230179
+ throw error2;
230180
+ }
230181
+ }
229593
230182
  async unmarkConversationRead(threadId, conversationId) {
229594
230183
  try {
229595
230184
  await unmarkConversationRead(this.db, threadId, conversationId);
@@ -230177,7 +230766,8 @@ async function getRecentConversations2(c, conversationManager) {
230177
230766
  inputTokens: Number(conversation.inputTokens) || 0,
230178
230767
  outputTokens: Number(conversation.outputTokens) || 0,
230179
230768
  model: conversation.model,
230180
- branch: conversation.branch
230769
+ branch: conversation.branch,
230770
+ isComplete: Boolean(conversation.isComplete)
230181
230771
  }));
230182
230772
  return successResponse(c, { conversations, total, limit: safeLimit, offset: safeOffset }, 200);
230183
230773
  } catch (error2) {
@@ -238998,7 +239588,7 @@ var init_projects_routes = __esm({
238998
239588
  });
238999
239589
 
239000
239590
  // src/features/git/git-auth.broker.ts
239001
- import { randomUUID as randomUUID17 } from "crypto";
239591
+ import { randomUUID as randomUUID18 } from "crypto";
239002
239592
  var GitAuthBroker;
239003
239593
  var init_git_auth_broker = __esm({
239004
239594
  "src/features/git/git-auth.broker.ts"() {
@@ -239010,7 +239600,7 @@ var init_git_auth_broker = __esm({
239010
239600
  * with the credential, or null when the user cancelled the dialog.
239011
239601
  */
239012
239602
  begin(context2) {
239013
- const authId = randomUUID17();
239603
+ const authId = randomUUID18();
239014
239604
  const credential = new Promise((resolve21) => {
239015
239605
  this.pending.set(authId, {
239016
239606
  resolve: (value2) => {
@@ -240389,7 +240979,7 @@ var init_random_words = __esm({
240389
240979
  });
240390
240980
 
240391
240981
  // src/features/projects/projects.creator.ts
240392
- import { randomUUID as randomUUID18 } from "crypto";
240982
+ import { randomUUID as randomUUID19 } from "crypto";
240393
240983
  import { basename as basename7, dirname as dirname16, join as join40, relative as relative11, resolve as resolvePath5, sep as sep6 } from "path";
240394
240984
  import { realpathSync as realpathSync2 } from "fs";
240395
240985
  import { access as access7, mkdir as mkdir9, rm as rm6, stat as stat11, readdir as readdir11, writeFile as writeFile12 } from "fs/promises";
@@ -240692,14 +241282,14 @@ var init_projects_creator = __esm({
240692
241282
  }
240693
241283
  let initialThreadId;
240694
241284
  try {
240695
- const projectId = randomUUID18();
241285
+ const projectId = randomUUID19();
240696
241286
  const existingProjects = await this.metadataManager.loadProjects();
240697
241287
  const existingNames = existingProjects.map((p) => p.name);
240698
241288
  const projectName = this.ensureUniqueProjectName(
240699
241289
  this.deriveProjectName(gitUrl),
240700
241290
  existingNames
240701
241291
  );
240702
- initialThreadId = randomUUID18();
241292
+ initialThreadId = randomUUID19();
240703
241293
  const initialThreadTitle = generateRandomHyphenatedName();
240704
241294
  const baseFolderName = this.toFolderName(this.deriveProjectName(gitUrl));
240705
241295
  if (!baseFolderName) {
@@ -240796,8 +241386,8 @@ var init_projects_creator = __esm({
240796
241386
  };
240797
241387
  return;
240798
241388
  }
240799
- const projectId = randomUUID18();
240800
- const initialThreadId = randomUUID18();
241389
+ const projectId = randomUUID19();
241390
+ const initialThreadId = randomUUID19();
240801
241391
  const initialThreadTitle = generateRandomHyphenatedName();
240802
241392
  this.processingStateManager?.setProcessing(initialThreadId);
240803
241393
  try {
@@ -240906,8 +241496,8 @@ var init_projects_creator = __esm({
240906
241496
  };
240907
241497
  return;
240908
241498
  }
240909
- const projectId = randomUUID18();
240910
- const initialThreadId = randomUUID18();
241499
+ const projectId = randomUUID19();
241500
+ const initialThreadId = randomUUID19();
240911
241501
  const initialThreadTitle = generateRandomHyphenatedName();
240912
241502
  const { signal } = options2 ?? {};
240913
241503
  let folderPath;
@@ -241001,7 +241591,7 @@ var init_projects_creator = __esm({
241001
241591
  yield { type: "error", message: "Could not derive a valid folder name from the zip" };
241002
241592
  return;
241003
241593
  }
241004
- let projectId = randomUUID18();
241594
+ let projectId = randomUUID19();
241005
241595
  let projectNameToPersist = projectName;
241006
241596
  if (options2?.signal?.aborted) {
241007
241597
  return;
@@ -241015,7 +241605,7 @@ var init_projects_creator = __esm({
241015
241605
  projectId = overrideProjectId;
241016
241606
  projectNameToPersist = result.name;
241017
241607
  }
241018
- const initialThreadId = randomUUID18();
241608
+ const initialThreadId = randomUUID19();
241019
241609
  const initialThreadTitle = generateRandomHyphenatedName();
241020
241610
  let folderPath;
241021
241611
  let projectMetadataSaved = false;
@@ -241184,8 +241774,8 @@ var init_projects_creator = __esm({
241184
241774
  };
241185
241775
  return;
241186
241776
  }
241187
- const projectId = randomUUID18();
241188
- const initialThreadId = randomUUID18();
241777
+ const projectId = randomUUID19();
241778
+ const initialThreadId = randomUUID19();
241189
241779
  const initialThreadTitle = generateRandomHyphenatedName();
241190
241780
  this.processingStateManager?.setProcessing(initialThreadId);
241191
241781
  try {
@@ -242705,11 +243295,91 @@ var init_providers_open_external_route = __esm({
242705
243295
  }
242706
243296
  });
242707
243297
 
243298
+ // src/features/providers/providers-openrouter-oauth.route.ts
243299
+ function encodeBase64Url(bytes) {
243300
+ let binary = "";
243301
+ for (const byte of bytes) binary += String.fromCharCode(byte);
243302
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
243303
+ }
243304
+ async function createPkcePair() {
243305
+ const verifierBytes = new Uint8Array(32);
243306
+ crypto.getRandomValues(verifierBytes);
243307
+ const verifier = encodeBase64Url(verifierBytes);
243308
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
243309
+ return { verifier, challenge: encodeBase64Url(new Uint8Array(digest)) };
243310
+ }
243311
+ function removeExpiredAuthorizations() {
243312
+ const now = Date.now();
243313
+ for (const [state3, authorization] of pendingAuthorizations) {
243314
+ if (now - authorization.createdAt > PENDING_TTL_MS) pendingAuthorizations.delete(state3);
243315
+ }
243316
+ }
243317
+ async function startOpenRouterOAuth(c) {
243318
+ removeExpiredAuthorizations();
243319
+ const { verifier, challenge } = await createPkcePair();
243320
+ const stateBytes = new Uint8Array(24);
243321
+ crypto.getRandomValues(stateBytes);
243322
+ const state3 = encodeBase64Url(stateBytes);
243323
+ const callbackUrl = new URL("/api/providers/openrouter/oauth/callback", c.req.url).toString();
243324
+ pendingAuthorizations.set(state3, { verifier, callbackUrl, createdAt: Date.now() });
243325
+ const authorizationUrl = new URL(OPENROUTER_AUTH_URL);
243326
+ authorizationUrl.searchParams.set("callback_url", callbackUrl);
243327
+ authorizationUrl.searchParams.set("code_challenge", challenge);
243328
+ authorizationUrl.searchParams.set("code_challenge_method", "S256");
243329
+ authorizationUrl.searchParams.set("key_label", "Tarsk");
243330
+ authorizationUrl.searchParams.set("state", state3);
243331
+ return c.json({ url: authorizationUrl.toString() });
243332
+ }
243333
+ async function completeOpenRouterOAuth(c, metadataManager) {
243334
+ const code = new URL(c.req.url).searchParams.get("code");
243335
+ const state3 = new URL(c.req.url).searchParams.get("state");
243336
+ if (!code || !state3) return c.text("Missing OAuth code or state", 400);
243337
+ const pending2 = pendingAuthorizations.get(state3);
243338
+ pendingAuthorizations.delete(state3);
243339
+ if (!pending2 || Date.now() - pending2.createdAt > PENDING_TTL_MS) {
243340
+ return c.text("This OAuth session has expired. Return to Tarsk and try again.", 400);
243341
+ }
243342
+ const response = await fetch(OPENROUTER_EXCHANGE_URL, {
243343
+ method: "POST",
243344
+ headers: { "Content-Type": "application/json" },
243345
+ body: JSON.stringify({
243346
+ code,
243347
+ code_verifier: pending2.verifier,
243348
+ code_challenge_method: "S256"
243349
+ })
243350
+ });
243351
+ if (!response.ok)
243352
+ return c.text("OpenRouter authorization could not be completed. Try again.", 502);
243353
+ const result = await response.json();
243354
+ if (!result.key) return c.text("OpenRouter did not return an API key. Try again.", 502);
243355
+ await metadataManager.saveProviderKey("openrouter", result.key);
243356
+ const keyName = await resolveProviderKeyName("openrouter");
243357
+ if (keyName) {
243358
+ updateRuntimeEnv({ [keyName]: result.key });
243359
+ await updateEnvFile({ [keyName]: result.key });
243360
+ }
243361
+ return c.html("<h1>OpenRouter connected</h1><p>You can close this tab and return to Tarsk.</p>");
243362
+ }
243363
+ var OPENROUTER_AUTH_URL, OPENROUTER_EXCHANGE_URL, PENDING_TTL_MS, pendingAuthorizations;
243364
+ var init_providers_openrouter_oauth_route = __esm({
243365
+ "src/features/providers/providers-openrouter-oauth.route.ts"() {
243366
+ "use strict";
243367
+ init_env_manager();
243368
+ init_provider_resolver();
243369
+ OPENROUTER_AUTH_URL = "https://openrouter.ai/auth";
243370
+ OPENROUTER_EXCHANGE_URL = "https://openrouter.ai/api/v1/auth/keys";
243371
+ PENDING_TTL_MS = 10 * 60 * 1e3;
243372
+ pendingAuthorizations = /* @__PURE__ */ new Map();
243373
+ }
243374
+ });
243375
+
242708
243376
  // src/features/providers/providers.routes.ts
242709
243377
  function createProviderRoutes(metadataManager) {
242710
243378
  const router = new Hono2();
242711
243379
  router.get("/", (c) => getProviders(c, metadataManager));
242712
243380
  router.post("/open-external", (c) => openExternalUrl(c));
243381
+ router.get("/openrouter/oauth/start", (c) => startOpenRouterOAuth(c));
243382
+ router.get("/openrouter/oauth/callback", (c) => completeOpenRouterOAuth(c, metadataManager));
242713
243383
  router.post("/keys", (c) => postProviderKeys(c, metadataManager));
242714
243384
  router.post("/bulk-keys", (c) => postProviderBulkKeys(c, metadataManager));
242715
243385
  router.post("/env", (c) => postProviderEnv(c, metadataManager));
@@ -242728,6 +243398,7 @@ var init_providers_routes = __esm({
242728
243398
  init_providers_get_credits_route();
242729
243399
  init_providers_get_logo_route();
242730
243400
  init_providers_open_external_route();
243401
+ init_providers_openrouter_oauth_route();
242731
243402
  }
242732
243403
  });
242733
243404
 
@@ -243985,7 +244656,7 @@ var init_thread_folder_name = __esm({
243985
244656
  });
243986
244657
 
243987
244658
  // src/features/threads/thread-copy-clone.ts
243988
- import { randomUUID as randomUUID19 } from "crypto";
244659
+ import { randomUUID as randomUUID20 } from "crypto";
243989
244660
  import { readdir as readdir13, rename as rename5, stat as stat12, rm as rm8 } from "fs/promises";
243990
244661
  import { join as join45 } from "path";
243991
244662
  function supportsCopyOnWriteClone() {
@@ -244060,7 +244731,7 @@ async function cloneDirectoryTree(sourcePath, targetPath) {
244060
244731
  if (typeof Worker === "undefined") {
244061
244732
  return { ok: false, error: "workers are unavailable in this runtime" };
244062
244733
  }
244063
- const stagingPath = `${targetPath}.copying-${randomUUID19().slice(0, 8)}`;
244734
+ const stagingPath = `${targetPath}.copying-${randomUUID20().slice(0, 8)}`;
244064
244735
  let worker;
244065
244736
  try {
244066
244737
  const workerUrl = URL.createObjectURL(
@@ -244213,7 +244884,7 @@ self.onmessage = (event) => {
244213
244884
  });
244214
244885
 
244215
244886
  // src/features/threads/threads.manager.ts
244216
- import { randomUUID as randomUUID20 } from "crypto";
244887
+ import { randomUUID as randomUUID21 } from "crypto";
244217
244888
  import { join as join46 } from "path";
244218
244889
  import { execSync as execSync3 } from "child_process";
244219
244890
  import { rm as rm9, stat as stat13, mkdir as mkdir11 } from "fs/promises";
@@ -244305,13 +244976,13 @@ var init_threads_manager = __esm({
244305
244976
  return;
244306
244977
  }
244307
244978
  await this.ensureProjectDirectory(project.path);
244308
- threadId = randomUUID20();
244979
+ threadId = randomUUID21();
244309
244980
  const threadTitle = await this.resolveThreadTitle(projectId, title);
244310
244981
  const threadPath = await this.generateThreadPath(project.gitUrl, project.name);
244311
244982
  this.processingStateManager?.setProcessing(threadId);
244312
244983
  yield {
244313
244984
  type: "progress",
244314
- message: `Creating thread "${threadTitle}" for project "${project.name}"...`,
244985
+ message: `Creating workspace "${threadTitle}" for project "${project.name}"...`,
244315
244986
  threadId
244316
244987
  };
244317
244988
  let populateFailed = false;
@@ -244761,7 +245432,7 @@ var init_threads_manager = __esm({
244761
245432
  const shouldDeleteProject = isProjectRoot && project.threads.length === 0;
244762
245433
  if (project.threads.length === 0 && isBuiltInBot(project)) {
244763
245434
  const replacement = {
244764
- id: randomUUID20(),
245435
+ id: randomUUID21(),
244765
245436
  projectId: project.id,
244766
245437
  title: generateRandomHyphenatedName(),
244767
245438
  path: project.path,
@@ -245186,7 +245857,7 @@ var init_threads_delete_route = __esm({
245186
245857
  });
245187
245858
 
245188
245859
  // src/features/project-scripts/project-scripts.database.ts
245189
- import { randomUUID as randomUUID21 } from "crypto";
245860
+ import { randomUUID as randomUUID22 } from "crypto";
245190
245861
  async function getScriptsByProject(db, projectId) {
245191
245862
  const result = await db.execute({
245192
245863
  sql: `SELECT id, projectId, workspace, name, command, friendlyName, updatedAt
@@ -245203,7 +245874,7 @@ async function upsertProjectScripts(projectId, scripts) {
245203
245874
  sql: `INSERT OR REPLACE INTO project_scripts (id, projectId, workspace, name, command, friendlyName, updatedAt)
245204
245875
  VALUES (?, ?, ?, ?, ?, ?, ?)`,
245205
245876
  args: [
245206
- randomUUID21(),
245877
+ randomUUID22(),
245207
245878
  projectId,
245208
245879
  script.workspace,
245209
245880
  script.name,
@@ -404562,7 +405233,11 @@ async function gitCreateBranchHandler(c, metadataManager) {
404562
405233
  } catch {
404563
405234
  return c.json({ error: `Path is not a git repository: ${absolutePath}` }, 400);
404564
405235
  }
404565
- const baseBranch = body.baseBranch ?? await findDefaultBranch(gitRoot) ?? void 0;
405236
+ const previousBranch = await getCurrentBranch(gitRoot);
405237
+ const baseBranch = body.baseBranch ?? await findDefaultBranch(gitRoot);
405238
+ if (!baseBranch) {
405239
+ return c.json({ error: "Could not determine the default branch" }, 400);
405240
+ }
404566
405241
  let branchName = body.branchName ? sanitizeBranchName(body.branchName) : sanitizeBranchName(generateRandomHyphenatedName());
404567
405242
  if (!branchName) {
404568
405243
  return c.json({ error: "Invalid branch name" }, 400);
@@ -404576,7 +405251,7 @@ async function gitCreateBranchHandler(c, metadataManager) {
404576
405251
  }
404577
405252
  await createAndCheckoutBranch(gitRoot, branchName, baseBranch);
404578
405253
  await updateThreadCurrentBranch(metadataManager, threadId, branchName);
404579
- return c.json({ success: true, branchName });
405254
+ return c.json({ success: true, branchName, previousBranch, baseBranch });
404580
405255
  } catch (error2) {
404581
405256
  const message = error2 instanceof Error ? error2.message : "Failed to create branch";
404582
405257
  return c.json({ error: message }, 500);
@@ -440546,7 +441221,7 @@ var init_slack_shared = __esm({
440546
441221
  });
440547
441222
 
440548
441223
  // src/features/slack/slack.dispatch.ts
440549
- import { randomUUID as randomUUID22 } from "crypto";
441224
+ import { randomUUID as randomUUID23 } from "crypto";
440550
441225
  function clearBackgroundTurnRecovery() {
440551
441226
  backgroundTurnRecovery.clear();
440552
441227
  }
@@ -440812,7 +441487,7 @@ async function resolveOrCreateChannelThread(ctx, params) {
440812
441487
  return { ok: false };
440813
441488
  }
440814
441489
  const tarskThreadId = createdThread.id;
440815
- const nextConversationId = conversationId ?? randomUUID22();
441490
+ const nextConversationId = conversationId ?? randomUUID23();
440816
441491
  const nextSlackMode = slackMode ?? (claimChannelDefault ? "plan" : "branch");
440817
441492
  await announceChannelBranchReady(ctx, {
440818
441493
  channelId,
@@ -440945,7 +441620,7 @@ async function claimChannelDefaultOwnership(ctx, params) {
440945
441620
  log139.warn("Failed to delete duplicate channel default clone", { error: error2, tarskThreadId });
440946
441621
  }
440947
441622
  const winnerThreadId = claim.existing.defaultTarskThreadId;
440948
- const conversationId = randomUUID22();
441623
+ const conversationId = randomUUID23();
440949
441624
  await upsertSlackThreadMap({
440950
441625
  slackTeamId: teamId,
440951
441626
  slackChannelId: channelId,
@@ -441171,7 +441846,7 @@ async function resolveSlackConversationId(ctx, params) {
441171
441846
  return thread.currentConversationId;
441172
441847
  }
441173
441848
  }
441174
- const conversationId = randomUUID22();
441849
+ const conversationId = randomUUID23();
441175
441850
  await ctx.deps.threadManager.updateThread(tarskThreadId, {
441176
441851
  currentConversationId: conversationId
441177
441852
  });
@@ -441195,7 +441870,7 @@ var init_slack_dispatch = __esm({
441195
441870
  });
441196
441871
 
441197
441872
  // src/features/slack/slack.branch.ts
441198
- import { randomUUID as randomUUID23 } from "crypto";
441873
+ import { randomUUID as randomUUID24 } from "crypto";
441199
441874
  async function handleBranchCommand(ctx, params) {
441200
441875
  const { teamId, channelId, userId, messageTs, prompt, attachments, projectId } = params;
441201
441876
  const project = await ctx.deps.projectManager.getProject(projectId);
@@ -441282,7 +441957,7 @@ async function remapSlackThreadToBranch(ctx, params) {
441282
441957
  threadTitle,
441283
441958
  slackMode: "branch",
441284
441959
  isNewConversation: true,
441285
- conversationId: randomUUID23(),
441960
+ conversationId: randomUUID24(),
441286
441961
  clearPendingPropose: true
441287
441962
  });
441288
441963
  }
@@ -442171,7 +442846,7 @@ var init_slack_attachments = __esm({
442171
442846
  });
442172
442847
 
442173
442848
  // src/features/slack/slack.mentions.ts
442174
- import { randomUUID as randomUUID24 } from "crypto";
442849
+ import { randomUUID as randomUUID25 } from "crypto";
442175
442850
  function messageMentionsBot(event, botUserId) {
442176
442851
  const text = event.text;
442177
442852
  if (!botUserId || !text) {
@@ -442266,7 +442941,7 @@ async function handleAppMention(ctx, event, body) {
442266
442941
  }
442267
442942
  const defaultTarget = await resolveChannelDefaultTarget(ctx, teamId, channelId, binding);
442268
442943
  if (defaultTarget) {
442269
- const conversationId2 = randomUUID24();
442944
+ const conversationId2 = randomUUID25();
442270
442945
  await upsertSlackThreadMap({
442271
442946
  slackTeamId: teamId,
442272
442947
  slackChannelId: channelId,
@@ -442305,7 +442980,7 @@ async function handleAppMention(ctx, event, body) {
442305
442980
  });
442306
442981
  return;
442307
442982
  }
442308
- const conversationId = randomUUID24();
442983
+ const conversationId = randomUUID25();
442309
442984
  const channelLabel = binding.slackChannelName ?? await resolveSlackChannelName(ctx.getWeb(), channelId);
442310
442985
  await dispatchChannelPrompt(ctx, {
442311
442986
  teamId,
@@ -443486,7 +444161,7 @@ var init_file_routes = __esm({
443486
444161
 
443487
444162
  // src/features/browser-js/browser-js.routes.ts
443488
444163
  import { homedir as homedir11 } from "node:os";
443489
- import { randomUUID as randomUUID25 } from "node:crypto";
444164
+ import { randomUUID as randomUUID26 } from "node:crypto";
443490
444165
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
443491
444166
  function prepareSmartJsArguments(params, output2) {
443492
444167
  const validated = validateSmartJsOutput(output2);
@@ -443612,7 +444287,7 @@ async function resolveExecutionTool(args2) {
443612
444287
  return tools[args2.toolName];
443613
444288
  }
443614
444289
  async function executeAndCaptureSmartJsResult(args2) {
443615
- const executionId = randomUUID25();
444290
+ const executionId = randomUUID26();
443616
444291
  let result;
443617
444292
  try {
443618
444293
  result = await args2.tool.execute(executionId, args2.executionParams);
@@ -444234,7 +444909,7 @@ var init_logs_routes = __esm({
444234
444909
  });
444235
444910
 
444236
444911
  // src/features/user-tasks/user-tasks.database.ts
444237
- import { randomUUID as randomUUID26 } from "crypto";
444912
+ import { randomUUID as randomUUID27 } from "crypto";
444238
444913
  async function getUserTasksByProject(db, projectId) {
444239
444914
  const result = await db.execute({
444240
444915
  sql: `SELECT id, projectId, content, createdAt, updatedAt
@@ -444247,7 +444922,7 @@ async function getUserTasksByProject(db, projectId) {
444247
444922
  }
444248
444923
  async function insertUserTask(projectId, content) {
444249
444924
  const db = await getDatabase();
444250
- const id = randomUUID26();
444925
+ const id = randomUUID27();
444251
444926
  const now = (/* @__PURE__ */ new Date()).toISOString();
444252
444927
  await db.execute({
444253
444928
  sql: `INSERT INTO user_tasks (id, projectId, content, createdAt, updatedAt)