chainlesschain 0.166.25 → 0.166.26

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 (160) hide show
  1. package/README.md +16 -10
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-RaxL_QQD.js → AIOps-Z8_dnLd8.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-DD3ieFO-.js → ActionButton-C4bKCISV.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-CATDJukS.js → Analytics-GztAv2jy.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-BHGsnRDS.js → AppLayout-DEqNcuVx.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-BL6NunjN.js → Artifacts-D-R4Ehap.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-D0nEWfbA.js → Audit-mzzdTIlM.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-BAP1MUol.js → BackgroundAgents-DS2QupIC.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-R4y2OeSi.js → Backup-CQSirC39.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-ByQZ2z6S.js → BaseInput-Bhuc-eOV.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-32uV--xF.js → Chat-B-RLVGnt.js} +6 -6
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-CBbMoVuE.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-D1CB-7bq.js → Checkbox-DxwgBryW.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-BPx3dQ2q.js → Codegen-Cwrm-7nh.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-DkPTQ2Gl.js → Col-DrSCT-nF.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-ZriaxRlr.js → Community-DY2D9WNs.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-C_qJ0P7F.js → Compact-o-tV0URw.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-Bgoy-saS.js → Compliance-Bndh6S8f.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-B5i9y6XK.js → Cowork-CSNQODak.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-D7vBJ5-J.js → Cron-CTgxRHdy.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-D4kvoGI_.js → Crosschain-BJoGQzDI.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-BLOeBd-r.js → DID-V0Ztm8ne.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-mecJaonC.js → Dashboard-B-38THOj.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-GPKwaFer.js → Dropdown-B3FdOwMO.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-BML9m7Dd.js → EmailListRenderer-YQDz4mUF.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DN5bAtJC.js → FamilyGuardDashboard-DYE45IF9.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-DmD6Gecd.js → Federation-DjBFjdRZ.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-6wwplN_K.js → FormItemContext-CVTXEa0R.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-DUhpLkDL.js → GenericCardRenderer-B6Tkke8X.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-eJfyXkwf.js → Git-CD0hyAzT.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-swAUW59x.js → Governance-CWOQQJr8.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CbdwJPDJ.js → Inference-lHYwUk-C.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-UuYpg1nm.js → KnowledgeGraph-Cledxv7t.js} +1 -1
  35. package/src/assets/web-panel/assets/Logs-D45mt-rM.js +2 -0
  36. package/src/assets/web-panel/assets/MarkdownRenderer-DJjPaOnM.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-CZRjuvvI.js → Marketplace-Yy30UZPw.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-BOJ9A_Rf.js → McpTools-Cil5l-bh.js} +2 -2
  39. package/src/assets/web-panel/assets/{Memory-BnkrR-Ok.js → Memory-DdJcnyqy.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-Do4mPi13.js → MobileBridge-IrzFYHEv.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-2JxWa6-p.js → MobileProjects-D8q64LMd.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-CS_mnpGd.js → Mtc-CpdTJzW7.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-DZ4J_351.js → MtcAudit-C7Tvw2m6.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-Jh74zKXu.js → Multisig-Dmj9F5Kr.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-_4n2BfnS.js → NLProgramming-C9Xchob5.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-CtENcKHv.js → Notes-Bzq6Yry5.js} +4 -4
  47. package/src/assets/web-panel/assets/{NotificationSettings-dgDCvpK9.js → NotificationSettings-DxG9eKb4.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-D5VxCrmG.js → OrderTableRenderer-BS_IYoCe.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-CpIF8Xkd.js → Organization-kazsRvcq.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-aHnBZaez.js → Overflow-i4wP-hwn.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-8ppzog2V.js → P2P-CfGeU3h-.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-D3p1BXkp.js → PdhVaultBrowser-CS-VhVUx.js} +5 -5
  53. package/src/assets/web-panel/assets/{Permissions-D7vflD5q.js → Permissions-DnEHXs0I.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-D2hY-Ek2.js → PersonalDataHub-DeD82qke.js} +5 -5
  55. package/src/assets/web-panel/assets/{Pipeline-qK2VqhJC.js → Pipeline-CMGGLgBY.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-DHJr4uu0.js → Privacy-CvHoFv32.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-DMBS6trm.js → ProjectInit-DnJapCc1.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-D3Ng74BT.js → ProjectSettings-CqVdv3-g.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-BfJFZiIW.js → Projects-B_o8vcs_.js} +1 -1
  60. package/src/assets/web-panel/assets/{Providers-DlNA95G0.js → Providers-CPKseoDW.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-CMOIYxIm.js → QrScannerModal-_iBfKbPQ.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-D6MyGp5I.js → QuickAsk-CMrlZ69a.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-W6WcShtf.js → Recommend-BwDtSZ0l.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-Dm_MjlV_.js → RemoteSession-DomUAtn4.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-Ctvij6eX.js → Reputation-Cuu2GCHr.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-DivbeDE-.js → Row-C7GVts31.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-D4famoAw.js → RssFeed-DRKvgEog.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-6gOAh3zG.js → Search-BGI9wOeA.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-DApb9kK8.js → Security-BlLaHy_L.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-B8OomyE2.js → Services-DFqZbjmX.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-BTJ2g2E3.js → Skeleton-BCGxdooP.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-NIRr4DD1.js → Skills-CwFKgcmm.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-BQHP_6px.js → Sla-CiXXh9eS.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-BVQTDSVS.js → SpeechSettings-WSx2CLqO.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-BOD4Mar6.js → SyncSettings-BBIqQOtW.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-Ciu7H2-y.js → Tasks-D1BGLjO1.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-CtlwavRU.js → Templates-CUIl9axA.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-QLWYJdL6.js → Tenant-BFZJ0hNz.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-B3q10mjm.js → Terminal-Cw-3eYVn.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-CqltBA_8.js → TimelineRenderer-bOVPB56L.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-CJOKrj4y.js → Tokens-Czfyq2VY.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-CPMGgfdM.js → Trigger-C-o4uJY0.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-DiJms7Bl.js → Trust-BKq_S6iF.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-rakR8eel.js → UkeySign-fKlWUvMx.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-DAWZUM5o.js → VideoEditing-DB5MLuS7.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-DqUPnl7K.js → Wallet-WGXBn7IS.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-BnVUwvMm.js → WebAuthn-B8TC4EMF.js} +4 -4
  88. package/src/assets/web-panel/assets/{WorkflowEditor-B1CAwxgs.js → WorkflowEditor-DLY--KmM.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-k2-0Jzfy.js → chat-Crw3XQaA.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-BAu8xBmW.js → colors-CxhWauPV.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-DMlqcdfI.js → compact-item-Cp3ojtk5.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-BU9kfiSw.js → createContext-CRuRXjSo.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-CKAQY2zn.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-2vacgdcl.js → hasIn-XGW474dj.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-Bpe2CJd-.js → index-38TRdZb6.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-B-C-Ruft.js → index-B45Vkh3T.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CSvSf9px.js → index-B5fJS-kn.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CXmpR6N3.js → index-BElgeKJ0.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-DHg3LMNP.js → index-BUWZ57T4.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DaUGdvtU.js → index-BVmSfIkJ.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BdfKoqsK.js → index-BW028Pwn.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-C9WsM29I.js → index-BXnNbbwa.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BZz2eB33.js → index-BYkjs7eP.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-Chybe7Ge.js → index-BetOkRLs.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DcA-tEQd.js → index-BuVA26SD.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-BUX4W-2v.js → index-C73pqyDb.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DH01oIaj.js → index-C8UOVaUH.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BMq0frKK.js → index-CDIpH_8Q.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-C6ICn9Y6.js → index-CPFam-me.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C5C4kSi8.js → index-CTE32qol.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Ygh0wmKz.js → index-CdlfrcC-.js} +1 -1
  112. package/src/assets/web-panel/assets/index-Cetfwq8j.js +1 -0
  113. package/src/assets/web-panel/assets/{index-oElehY4F.js → index-Ctu98x57.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BblNQlaA.js → index-DBcBsJYg.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-JsyGqKmD.js → index-DHNixOg_.js} +1 -1
  116. package/src/assets/web-panel/assets/index-DOpcRO2-.js +1 -0
  117. package/src/assets/web-panel/assets/{index-DmZNnZz7.js → index-DUSVsOGS.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CyXmP3PW.js → index-De2FN0xN.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-Bn8tARil.js → index-DfPLIA-f.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-B7wDjYUd.js → index-DhomnuaB.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BxctzdYQ.js → index-DoUC5_ry.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-z4_YwZDW.js → index-Dp2nC5On.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-TtrpHmYx.js → index-DxOtBFVy.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-Bf8YofPE.js → index-E-RSfImO.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DfWvcu4p.js → index-J_08R33H.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CONPVaxw.js → index-QqAuH7-S.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-C24NoPpy.js → index-W8_0yAi_.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CPyYXKFB.js → index-WvNZXbIO.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-hDHHJYno.js → index-Yq3bFbYX.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DCusBOqR.js → index-jrIcbPUa.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-dIYqw3f0.js → index-nJR64pA_.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DWLTSIka.js → index-qzmihx1d.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-C8ldqZi6.js → index-rsACoVT9.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-B9OXWu2e.js → initDefaultProps-DAu-hgme.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-IQ47MCDQ.js → motion-Db8yk0Hu.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-CLCU4kjV.js → move-Cii2jOin.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-CXnVlSPq.js → mtc-parser-CnZBDkyZ.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-BJjLXB0f.js → omit-Buzt1FTL.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-BHdtvdy6.js → pickAttrs-CpZ_NmE6.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-oq8X_Bwc.js → placementArrow-mBrx3dYm.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-DTD02LAO.js → responsiveObserve-DC_QzljB.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-DbEeq8to.js → slide-DT_UVED-.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-Do2fy1CJ.js → statusUtils-78t6eNLV.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-CFWD63T-.js → styleChecker-CV_T1ULL.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-BeozAWOo.js → useFlexGapSupport-s8edGuXD.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-0-rIgnBL.js → useFs-Pk9dH2HC.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-CeiNoI31.js → usePersonalDataHub-B_GqAm8c.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-Dj0ReRNg.js → vnode-Cxyss24q.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-DD7MC4Dy.js → zoom-0UY3cOuc.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/data/changelog.json +13 -0
  152. package/src/lib/read-file-loop-guard.js +186 -77
  153. package/src/lib/read-file-page.js +55 -2
  154. package/src/runtime/agent-core.js +148 -60
  155. package/src/assets/web-panel/assets/ChatBubbleRenderer-t1enanwz.js +0 -1
  156. package/src/assets/web-panel/assets/Logs-CS0G057y.js +0 -2
  157. package/src/assets/web-panel/assets/MarkdownRenderer-BxIIB4k3.js +0 -1
  158. package/src/assets/web-panel/assets/devWarning-DuGrUMAS.js +0 -1
  159. package/src/assets/web-panel/assets/index-DvFfMAux.js +0 -1
  160. package/src/assets/web-panel/assets/index-n6p-1A77.js +0 -1
@@ -16,7 +16,10 @@
16
16
 
17
17
  import fs from "fs";
18
18
  import path from "path";
19
- import { buildReadFilePage } from "../lib/read-file-page.js";
19
+ import {
20
+ buildReadFilePage,
21
+ buildReadFileOutline,
22
+ } from "../lib/read-file-page.js";
20
23
  import { ReadFileLoopGuard } from "../lib/read-file-loop-guard.js";
21
24
  import broker from "../lib/process-execution-broker/index.js";
22
25
  import os from "os";
@@ -1088,6 +1091,7 @@ Key behaviors:
1088
1091
  - For long-running commands (builds, full test suites, dev servers) set run_shell { run_in_background: true } to get a task_id back immediately, then poll output and completion with check_shell { task_id }. Kill a backgrounded server with check_shell { task_id, kill: true } when finished
1089
1092
  - When asked about git status, diff, log, or other repository operations, use the git tool instead of run_shell
1090
1093
  - When asked about files or code, use search_files to locate relevant sections, then read_file with offset/limit. Follow nextRead for large files. Reuse unchanged content already in context instead of repeatedly reading the same page; re-read when the file changes or the earlier content is no longer available.
1094
+ - Large task documents include a sampled outline with line numbers. Use it to locate relevant unfinished work and inspect those sections instead of scanning the entire document unless the task requires full coverage. File coverage and excerpts survive compaction; reading to EOF is not completing the user's task.
1091
1095
  - Before renaming or changing a symbol, use code_intelligence (action: references/definition) to find every real usage instead of guessing with text search. It degrades to "unavailable" when no language server is installed — fall back to search_files then.
1092
1096
  - After an edit, if the tool result includes a "newDiagnostics" array, you just introduced (or exposed) those errors/warnings — read them and fix before moving on. You can also run code_intelligence (action: diagnostics) on any file to check it on demand.
1093
1097
  - If a tool result includes a "subtreeInstructions" array, you just entered a subdirectory that carries its own cc.md/CLAUDE.md/AGENTS.md — treat that content as authoritative project rules for work in that subtree (it is injected once, the first time you touch the subtree).
@@ -3633,6 +3637,7 @@ export async function executeTool(name, args, context = {}) {
3633
3637
  sessionBudget: context.sessionBudget || null,
3634
3638
  hostResourceBudget: context.hostResourceBudget || null,
3635
3639
  readFileCache: context.readFileCache || null,
3640
+ readFileLoopGuard: context.readFileLoopGuard || null,
3636
3641
  // Effective contract of THIS loop (parent ceiling for a nested spawn) +
3637
3642
  // the MCP tool definitions this loop exposes (inheritable by a spawn).
3638
3643
  subAgentContract: context.subAgentContract || null,
@@ -5178,6 +5183,7 @@ async function executeToolInner(
5178
5183
  toolAdmission = null,
5179
5184
  hostResourceBudget = null,
5180
5185
  readFileCache = null,
5186
+ readFileLoopGuard = null,
5181
5187
  unattendedActionPolicy = null,
5182
5188
  managedCheckpoint = false,
5183
5189
  fileMutationScope = null,
@@ -5253,61 +5259,79 @@ async function executeToolInner(
5253
5259
  });
5254
5260
  }
5255
5261
  const fileVersion = `${fileStat.size}:${fileStat.mtimeMs}:${fileStat.ctimeMs}`;
5256
- const cacheKey = JSON.stringify([
5257
- filePath,
5258
- args.offset ?? null,
5259
- args.limit ?? null,
5260
- args.column ?? null,
5261
- args.hashed === true,
5262
- args.raw === true,
5263
- ]);
5264
- const cached = readFileCache?.get(cacheKey);
5265
- if (cached?.fileVersion === fileVersion) {
5266
- // All permission checks ran before this point. A fresh stat still
5267
- // invalidates changed/deleted files; cache only bounded pages per run.
5268
- _recordFileObservation(filePath);
5269
- readFileCache.delete(cacheKey);
5270
- readFileCache.set(cacheKey, cached);
5271
- return attachDescriptor(
5272
- await _withSubtreeInstructions(
5273
- structuredClone(cached.page),
5274
- filePath,
5275
- cwd,
5276
- subtreeInstructionScope,
5277
- ),
5278
- );
5279
- }
5280
- const content = fs.readFileSync(filePath, "utf8");
5281
- // Record the mtime so a later edit can detect an external change that
5282
- // happened between this read and the edit (read-freshness guard).
5283
5262
  _recordFileObservation(filePath);
5284
- // Jupyter notebooks: render a compact cell listing (index/id/type/source,
5285
- // outputs summarized) so the model can find cells for notebook_edit
5286
- // without ingesting raw JSON / base64 output blobs. `raw:true` returns the
5287
- // underlying JSON. Non-.ipynb reads are unchanged.
5288
- const nbView =
5289
- args.raw !== true && /\.ipynb$/i.test(filePath)
5290
- ? renderNotebook(content)
5291
- : null;
5292
- // Hashline mode: prefix each line with a 6-char content hash tag
5293
- // so downstream edit_file_hashed calls can anchor by hash.
5294
- const rendered =
5295
- nbView || (args.hashed === true ? annotateLines(content) : content);
5296
- const page = buildReadFilePage(rendered, args, {
5297
- filePath,
5298
- fileVersion,
5299
- maxChars: MAX_TOOL_RESULT_CHARS,
5300
- });
5301
- if (nbView) page.notebook = true;
5302
- if (readFileCache && !page.error) {
5303
- readFileCache.delete(cacheKey);
5304
- readFileCache.set(cacheKey, {
5263
+ let rendered;
5264
+ let nbView;
5265
+ let outline;
5266
+ const render = () => {
5267
+ if (rendered !== undefined) return rendered;
5268
+ const content = fs.readFileSync(filePath, "utf8");
5269
+ nbView =
5270
+ args.raw !== true && /\.ipynb$/i.test(filePath)
5271
+ ? renderNotebook(content)
5272
+ : null;
5273
+ rendered =
5274
+ nbView || (args.hashed === true ? annotateLines(content) : content);
5275
+ // Excerpts are data, never subtree instructions. Keep the index
5276
+ // separate from read coverage so it cannot claim the file was read.
5277
+ outline =
5278
+ ((args.offset == null && args.limit == null) ||
5279
+ Number(args.limit) >= 2000) &&
5280
+ content.length > MAX_TOOL_RESULT_CHARS &&
5281
+ /\.(?:md|mdx|txt)$/i.test(filePath)
5282
+ ? buildReadFileOutline(content)
5283
+ : null;
5284
+ return rendered;
5285
+ };
5286
+ const readPage = (request) => {
5287
+ const cacheKey = JSON.stringify([
5288
+ filePath,
5289
+ request.offset ?? null,
5290
+ request.limit ?? null,
5291
+ request.column ?? null,
5292
+ args.hashed === true,
5293
+ args.raw === true,
5294
+ ]);
5295
+ const cached = readFileCache?.get(cacheKey);
5296
+ if (cached?.fileVersion === fileVersion)
5297
+ return structuredClone(cached.page);
5298
+ render();
5299
+ const page = buildReadFilePage(rendered, request, {
5300
+ filePath,
5305
5301
  fileVersion,
5306
- page: structuredClone(page),
5302
+ // An unbounded large-document request starts with an index and a
5303
+ // small preview. A task-specific search can then avoid a full scan.
5304
+ maxChars:
5305
+ outline && request.offset == null && request.limit == null
5306
+ ? Math.min(MAX_TOOL_RESULT_CHARS, 12000)
5307
+ : MAX_TOOL_RESULT_CHARS,
5308
+ outline,
5307
5309
  });
5308
- while (readFileCache.size > 8)
5309
- readFileCache.delete(readFileCache.keys().next().value);
5310
- }
5310
+ if (nbView) page.notebook = true;
5311
+ if (readFileCache && !page.error) {
5312
+ readFileCache.delete(cacheKey);
5313
+ readFileCache.set(cacheKey, {
5314
+ fileVersion,
5315
+ page: structuredClone(page),
5316
+ });
5317
+ while (readFileCache.size > 8)
5318
+ readFileCache.delete(readFileCache.keys().next().value);
5319
+ }
5320
+ return page;
5321
+ };
5322
+ const page = readFileLoopGuard
5323
+ ? readFileLoopGuard.read(
5324
+ args,
5325
+ { filePath, fileVersion },
5326
+ readPage,
5327
+ (charOffset) => {
5328
+ const prefix = render().slice(0, charOffset);
5329
+ const offset = (prefix.match(/\n/g) || []).length + 1;
5330
+ const column = charOffset - prefix.lastIndexOf("\n");
5331
+ return readPage({ ...args, offset, column, limit: 2000 });
5332
+ },
5333
+ )
5334
+ : readPage(args);
5311
5335
  return attachDescriptor(
5312
5336
  await _withSubtreeInstructions(
5313
5337
  page,
@@ -13708,6 +13732,7 @@ export async function* agentLoop(messages, options) {
13708
13732
  // rather than looping forever (the iteration budget is the hard backstop).
13709
13733
  let emptyThinkingReprompted = false;
13710
13734
  const readFileLoopGuard = new ReadFileLoopGuard();
13735
+ toolContext.readFileLoopGuard = readFileLoopGuard;
13711
13736
 
13712
13737
  while (budget.hasRemaining()) {
13713
13738
  readFileLoopGuard.finishBatch();
@@ -13718,7 +13743,7 @@ export async function* agentLoop(messages, options) {
13718
13743
  );
13719
13744
  yield* _drainSubAgentUsage(subAgentUsageSink);
13720
13745
  const error = new Error(
13721
- "Repeated unchanged file reads: stopped after three tool batches made no new reading progress, including a recovery attempt. The task is not complete. Continue with a different file section or a targeted search.",
13746
+ "Repeated unchanged file reads: the model did not resume the task after automatic page continuation and six no-progress batches with retained findings. The task is not complete. Use a targeted section or revise the task before retrying.",
13722
13747
  );
13723
13748
  error.code = "CC_AGENT_REPEATED_FILE_READ";
13724
13749
  throw error;
@@ -14275,11 +14300,74 @@ export async function* agentLoop(messages, options) {
14275
14300
  // prepareCall runs fresh each iteration and returns an ephemeral
14276
14301
  // system-message supplement that is NOT persisted to messages history.
14277
14302
  let callMessages = messages;
14303
+ // Give a looping model a turn focused on search/action rather than another
14304
+ // whole-file request. This changes discovery for one request only; runtime
14305
+ // permissions are untouched and ordinary reads return on the next turn.
14306
+ const readRecoveryTurn = readFileLoopGuard.takeRecoveryTurn();
14307
+ const iterationToolOptions = readRecoveryTurn
14308
+ ? {
14309
+ ...effectiveToolOptions,
14310
+ disabledTools: [
14311
+ ...(effectiveToolOptions.disabledTools || []),
14312
+ "read_file",
14313
+ ],
14314
+ }
14315
+ : effectiveToolOptions;
14316
+ const readContext = [
14317
+ readFileLoopGuard.findingsHint,
14318
+ readFileLoopGuard.progressHint,
14319
+ ].filter(Boolean);
14320
+ if (readContext.length) {
14321
+ // Preserve the last conversational turn and never split a tool call
14322
+ // from its results. Source data must neither become system authority
14323
+ // nor create an assistant prefill / a new generic user request.
14324
+ const resultIndex = messages.findLastIndex(
14325
+ (message) => message.role === "tool",
14326
+ );
14327
+ if (resultIndex >= 0) {
14328
+ const result = messages[resultIndex];
14329
+ const original =
14330
+ typeof result.content === "string"
14331
+ ? result.content
14332
+ : safeStringifyToolResult(result.content);
14333
+ let content;
14334
+ try {
14335
+ const value = JSON.parse(original);
14336
+ content = JSON.stringify({
14337
+ ...value,
14338
+ retainedReadContext: readContext,
14339
+ });
14340
+ } catch {
14341
+ content = original + "\n\n" + readContext.join("\n\n");
14342
+ }
14343
+ // Enrich only the ephemeral copy. This preserves signed assistant
14344
+ // thinking blocks, the last tool result, and the persisted transcript.
14345
+ callMessages = messages.map((message, index) =>
14346
+ index === resultIndex ? { ...result, content } : message,
14347
+ );
14348
+ } else {
14349
+ // Full compaction can leave only the pinned request. Reiterate that
14350
+ // exact request after the source data, not a replacement objective.
14351
+ const request = messages.findLast((message) => message.role === "user");
14352
+ callMessages = [
14353
+ ...messages,
14354
+ ...readContext.map((content) => ({ role: "assistant", content })),
14355
+ {
14356
+ role: "user",
14357
+ content: request?.content || "Continue the original user task.",
14358
+ },
14359
+ ];
14360
+ }
14361
+ }
14278
14362
  const contextMemoryTrustedSystemIndexes = [];
14279
- if (readFileLoopGuard.progressHint) {
14363
+ if (readRecoveryTurn) {
14280
14364
  callMessages = [
14281
14365
  ...callMessages,
14282
- { role: "system", content: readFileLoopGuard.progressHint },
14366
+ {
14367
+ role: "system",
14368
+ content:
14369
+ "File-read loop recovery: read_file is temporarily omitted for this model turn. Use the retained findings to choose a concrete next action or a focused search. Do not claim the user's task is complete merely because the file was read. Normal read_file availability resumes on the following turn.",
14370
+ },
14283
14371
  ];
14284
14372
  contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
14285
14373
  }
@@ -14328,7 +14416,7 @@ export async function* agentLoop(messages, options) {
14328
14416
  {
14329
14417
  ...options,
14330
14418
  contextMemoryToolDefinitions:
14331
- getEffectiveToolDefinitions(effectiveToolOptions),
14419
+ getEffectiveToolDefinitions(iterationToolOptions),
14332
14420
  contextMemoryTrustedSystemIndexes,
14333
14421
  },
14334
14422
  );
@@ -14358,13 +14446,13 @@ export async function* agentLoop(messages, options) {
14358
14446
  );
14359
14447
  const plannedProviderOptions = canonicalProviderContext?.plan
14360
14448
  ? {
14361
- ...effectiveToolOptions,
14449
+ ...iterationToolOptions,
14362
14450
  contextEngine: null,
14363
14451
  contextMemoryPreplanned: true,
14364
14452
  contextMemorySelectedToolNames:
14365
14453
  canonicalProviderContext.selectedToolNames,
14366
14454
  }
14367
- : effectiveToolOptions;
14455
+ : iterationToolOptions;
14368
14456
  const requestOptions = providerRequestId
14369
14457
  ? { ...plannedProviderOptions, providerRequestId }
14370
14458
  : plannedProviderOptions;
@@ -14694,7 +14782,7 @@ export async function* agentLoop(messages, options) {
14694
14782
 
14695
14783
  // Add assistant message with tool calls
14696
14784
  messages.push(msg);
14697
- readFileLoopGuard.startBatch(toolCalls.length);
14785
+ readFileLoopGuard.startBatch();
14698
14786
 
14699
14787
  // Concurrent READ-ONLY batch (latency optimization). When every call in the
14700
14788
  // turn is a well-formed read-only built-in (pure fs/DB reads — no mutation,
@@ -1 +0,0 @@
1
- import{I as v,P as u,J as S,U as s,R as a,S as y,K as C,Q as x,V as w,_ as B,b as n}from"./vendor-Bn1JzzAn.js";import{_ as k}from"./index-CXmpR6N3.js";import"./icons-DG5UD-6K.js";const N={__name:"ChatBubbleRenderer",props:{event:{type:Object,required:!0}},setup(c,{expose:d}){d();const t=c,r=n(()=>{const e=t.event.content||{};return e.text||e.body||e.message||e.title||JSON.stringify(e).slice(0,200)}),i=n(()=>{const e=t.event.content||{};return e.from||e.sender||e.senderName||t.event.actor||"(unknown)"}),l=n(()=>{const e=(t.event.actor||"").toLowerCase();return e.includes("self")||e==="me"||e.endsWith("_self")}),o=n(()=>{const e=t.event.source.adapter||"";return e.startsWith("messaging-qq")?"magenta":e==="wechat"?"green":"blue"}),m=n(()=>{if(!t.event.occurredAt)return"";try{const e=new Date(t.event.occurredAt),p=e.getFullYear(),f=String(e.getMonth()+1).padStart(2,"0"),g=String(e.getDate()).padStart(2,"0"),b=String(e.getHours()).padStart(2,"0"),h=String(e.getMinutes()).padStart(2,"0");return`${p}-${f}-${g} ${b}:${h}`}catch{return""}}),_={props:t,messageText:r,actorLabel:i,isMine:l,adapterColor:o,formattedTime:m,computed:n};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}},T={class:"bubble"},M={class:"meta"},R={class:"actor"},V={class:"time"},q={class:"body"};function D(c,d,t,r,i,l){const o=v("a-tag");return u(),S("div",{class:B(["chat-row",{mine:r.isMine}])},[s("div",T,[s("div",M,[s("span",R,a(r.actorLabel),1),s("span",V,a(r.formattedTime),1)]),s("div",q,a(r.messageText),1),t.event.source.adapter?(u(),y(o,{key:0,class:"src",color:r.adapterColor},{default:C(()=>[x(a(t.event.source.adapter),1)]),_:1},8,["color"])):w("v-if",!0)])],2)}const A=k(N,[["render",D],["__scopeId","data-v-49238629"],["__file","/tmp/cc-web-panel-d2aftn/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{A as default};
@@ -1,2 +0,0 @@
1
- import{I as s,J as g,U as d,c as o,K as _,V as k,S as W,R as S,F as K,Z as Q,w as M,n as C,o as R,b as T,r,P as p,Q as O,_ as U}from"./vendor-Bn1JzzAn.js";import{_ as E,u as N}from"./index-CXmpR6N3.js";import{R as j}from"./icons-DG5UD-6K.js";const q={__name:"Logs",setup(V,{expose:a}){a();const x=N(),e=r("status"),y=r(!1),v=r(""),i=r(""),c=r(""),f=r(!0),n=r(null),h={status:"status",doctor:"doctor","skill-sources":"skill sources","llm-providers":"llm providers"},m=T(()=>i.value.split(`
2
- `)),b=T(()=>{if(!c.value)return m.value;const t=c.value.toLowerCase();return m.value.filter(u=>u.toLowerCase().includes(t))});function L(t){return t.includes("✖")||t.includes("error")||t.includes("Error")||t.includes("failed")?"line-error":t.includes("✔")||t.includes("✓")||t.includes("success")||t.includes("running")?"line-success":t.includes("warn")||t.includes("Warn")||t.includes("○")?"line-warn":t.startsWith(" ")||t.startsWith(" ")?"line-indent":""}function l(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function w(t){if(!c.value)return t;const u=c.value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return t.replace(new RegExp(`(${u})`,"gi"),"<mark>$1</mark>")}async function B(){y.value=!0,v.value="",i.value="";const t=h[e.value]||"status";try{const{output:u}=await x.execute(t,3e4);i.value=u,f.value&&(await C(),n.value&&(n.value.scrollTop=n.value.scrollHeight))}catch(u){v.value=`执行失败: ${u.message}`,i.value=v.value}finally{y.value=!1}}M(b,async()=>{f.value&&(await C(),n.value&&(n.value.scrollTop=n.value.scrollHeight))}),R(B);const H={ws:x,activeTab:e,loading:y,error:v,rawOutput:i,searchQuery:c,autoScroll:f,logContainer:n,TAB_COMMANDS:h,allLines:m,filteredLines:b,lineClass:L,escapeHtml:l,highlightSearch:w,loadLog:B,ref:r,computed:T,watch:M,nextTick:C,onMounted:R,get ReloadOutlined(){return j},get useWsStore(){return N}};return Object.defineProperty(H,"__isScriptSetup",{enumerable:!1,value:!0}),H}},z={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},A={style:{display:"flex",gap:"10px",margin:"12px 0"}},D={ref:"logContainer",class:"log-box"},F={key:0,style:{"text-align":"center",padding:"40px",color:"var(--text-muted)"}},I={key:1,style:{"text-align":"center",padding:"40px",color:"var(--text-muted)"}},P={key:2},J=["innerHTML"];function Z(V,a,x,e,y,v){const i=s("a-checkbox"),c=s("a-button"),f=s("a-space"),n=s("a-tab-pane"),h=s("a-tabs"),m=s("a-input-search"),b=s("a-tag"),L=s("a-spin");return p(),g("div",null,[d("div",z,[a[5]||(a[5]=d("div",null,[d("h2",{class:"page-title"},"日志查看"),d("p",{class:"page-sub"},"系统运行日志与诊断输出")],-1)),o(f,null,{default:_(()=>[o(i,{checked:e.autoScroll,"onUpdate:checked":a[0]||(a[0]=l=>e.autoScroll=l)},{default:_(()=>[...a[3]||(a[3]=[O("自动滚动",-1)])]),_:1},8,["checked"]),o(c,{type:"primary",ghost:"",loading:e.loading,onClick:e.loadLog},{icon:_(()=>[o(e.ReloadOutlined)]),default:_(()=>[a[4]||(a[4]=O(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),k(" Tab Selector "),o(h,{activeKey:e.activeTab,"onUpdate:activeKey":a[1]||(a[1]=l=>e.activeTab=l),onChange:e.loadLog,style:{"margin-bottom":"0"}},{default:_(()=>[o(n,{key:"status",tab:"系统状态"}),o(n,{key:"doctor",tab:"环境诊断"}),o(n,{key:"skill-sources",tab:"技能来源"}),o(n,{key:"llm-providers",tab:"LLM 提供商"})]),_:1},8,["activeKey"]),k(" Search Bar "),d("div",A,[o(m,{value:e.searchQuery,"onUpdate:value":a[2]||(a[2]=l=>e.searchQuery=l),placeholder:"搜索日志内容...","allow-clear":"",style:{flex:"1"}},null,8,["value"]),e.filteredLines.length!==e.allLines.length?(p(),W(b,{key:0,color:"blue"},{default:_(()=>[O(S(e.filteredLines.length)+" / "+S(e.allLines.length)+" 行 ",1)]),_:1})):k("v-if",!0)]),k(" Log Output "),d("div",D,[e.loading?(p(),g("div",F,[o(L,{size:"large"}),a[6]||(a[6]=d("div",{style:{"margin-top":"10px"}},"加载中...",-1))])):e.filteredLines.length?(p(),g("div",P,[(p(!0),g(K,null,Q(e.filteredLines,(l,w)=>(p(),g("div",{key:w,class:U(["log-line",e.lineClass(l)]),innerHTML:e.highlightSearch(e.escapeHtml(l))},null,10,J))),128))])):(p(),g("div",I,S(e.error||"暂无日志内容,点击刷新加载"),1))],512)])}const $=E(q,[["render",Z],["__scopeId","data-v-8c2906e0"],["__file","/tmp/cc-web-panel-d2aftn/repo/packages/web-panel/src/views/Logs.vue"]]);export{$ as default};
@@ -1 +0,0 @@
1
- import{P as c,J as d,b as a}from"./vendor-Bn1JzzAn.js";import{r as s}from"./markdown-Yo_c6Krv.js";import{_ as p}from"./index-CXmpR6N3.js";const _={__name:"MarkdownRenderer",props:{content:{type:String,default:""}},setup(t,{expose:o}){o();const e=t,r=a(()=>s(e.content||"")),n={props:e,rendered:r,computed:a,get renderMarkdown(){return s}};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}},i=["innerHTML"];function m(t,o,e,r,n,u){return c(),d("div",{class:"markdown-content",innerHTML:r.rendered},null,8,i)}const w=p(_,[["render",m],["__scopeId","data-v-0b0b9f63"],["__file","/tmp/cc-web-panel-d2aftn/repo/packages/web-panel/src/components/MarkdownRenderer.vue"]]);export{w as M};
@@ -1 +0,0 @@
1
- import{Q as r}from"./index-CXmpR6N3.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
@@ -1 +0,0 @@
1
- import{C as o}from"./Col-DkPTQ2Gl.js";import{a0 as t}from"./index-CXmpR6N3.js";import"./vendor-Bn1JzzAn.js";import"./index-BxctzdYQ.js";import"./icons-DG5UD-6K.js";const s=t(o);export{s as default};
@@ -1 +0,0 @@
1
- import{A as o}from"./Row-DivbeDE-.js";import{a0 as t}from"./index-CXmpR6N3.js";import"./vendor-Bn1JzzAn.js";import"./responsiveObserve-DTD02LAO.js";import"./useFlexGapSupport-BeozAWOo.js";import"./styleChecker-CFWD63T-.js";import"./index-BxctzdYQ.js";import"./icons-DG5UD-6K.js";const l=t(o);export{l as default};