@zqagent/core 0.3.13 → 0.3.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{TurnEngine-BZjUGic_.d.ts → TurnEngine-C8qqbilC.d.ts} +18 -3
- package/dist/{TurnEngine-CMGdcSdp.d.cts → TurnEngine-DKSczYaA.d.cts} +18 -3
- package/dist/{conflictGuard-BBOOIxxK.d.cts → conflictGuard-BuICnWEI.d.cts} +8 -0
- package/dist/{conflictGuard-BBOOIxxK.d.ts → conflictGuard-BuICnWEI.d.ts} +8 -0
- package/dist/index.cjs +3451 -1129
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +242 -6
- package/dist/index.d.ts +242 -6
- package/dist/index.js +3500 -1178
- package/dist/index.js.map +1 -1
- package/dist/internal/engine/FileLogHook.d.cts +1 -1
- package/dist/internal/engine/FileLogHook.d.ts +1 -1
- package/dist/internal/update/controller.cjs +1 -1
- package/dist/internal/update/controller.js +1 -1
- package/dist/internal/update/platform.cjs +1 -1
- package/dist/internal/update/platform.js +1 -1
- package/dist/tools/diff.d.cts +1 -1
- package/dist/tools/diff.d.ts +1 -1
- package/dist/tools/explore.cjs +504 -127
- package/dist/tools/explore.cjs.map +1 -1
- package/dist/tools/explore.d.cts +1 -1
- package/dist/tools/explore.d.ts +1 -1
- package/dist/tools/explore.js +504 -127
- package/dist/tools/explore.js.map +1 -1
- package/dist/tools/files.cjs +267 -47
- package/dist/tools/files.cjs.map +1 -1
- package/dist/tools/files.d.cts +1 -1
- package/dist/tools/files.d.ts +1 -1
- package/dist/tools/files.js +267 -47
- package/dist/tools/files.js.map +1 -1
- package/dist/tools/search.cjs +103 -24
- package/dist/tools/search.cjs.map +1 -1
- package/dist/tools/search.d.cts +8 -2
- package/dist/tools/search.d.ts +8 -2
- package/dist/tools/search.js +103 -24
- package/dist/tools/search.js.map +1 -1
- package/package.json +6 -5
package/dist/tools/explore.cjs
CHANGED
|
@@ -345,8 +345,17 @@ var zh = {
|
|
|
345
345
|
- \u4E0D\u8981\u5C06\u5B8C\u6574\u7684\u6587\u4EF6\u5185\u5BB9\u5F53\u4F5C\u771F\u7406\u3002\u53EA\u8BB0\u5F55\u67D0\u4E2A\u6587\u4EF6\u88AB\u8BFB\u53D6/\u7F16\u8F91\u8FC7\u8FD9\u4E00\u4E8B\u5B9E\uFF1B\u534F\u4F5C\u8005\u5982\u679C\u9700\u8981\u518D\u6B21\u83B7\u53D6\u5185\u5BB9\u4F1A\u91CD\u65B0\u8BFB\u53D6\u3002\u9648\u65E7\u7684\u6587\u4EF6\u8BB0\u5FC6\u6BD4\u6CA1\u6709\u8BB0\u5FC6\u66F4\u7CDF\u7CD5\u3002
|
|
346
346
|
- \u82E5\u63D0\u4F9B\u4E86\u4E0A\u4E00\u7248\u6458\u8981\uFF1A\u53EA\u628A\u5B83\u4ECD\u7136\u6709\u6548\u7684\u7ED3\u8BBA\u5E76\u5165\u5BF9\u5E94\u7AE0\u8282\uFF0C\u4E0D\u8981\u6574\u6BB5\u590D\u8FF0\u6216\u9010\u6761\u8F6C\u6284\u3002
|
|
347
347
|
- \u8981\u5177\u4F53\uFF1A\u8DEF\u5F84\u3001\u540D\u79F0\u3001\u547D\u4EE4\u3001id\u2014\u2014\u800C\u4E0D\u662F\u6A21\u7CCA\u7684\u5F15\u7528\u3002
|
|
348
|
+
- \u7528\u7B80\u4F53\u4E2D\u6587\u64B0\u5199\u6458\u8981\u3002\u6458\u8981\u5728\u540E\u7EED\u6BCF\u4E00\u8F6E\u90FD\u4F1A\u968F\u4E0A\u4E0B\u6587\u91CD\u53D1\uFF0C\u8BED\u8A00\u4E0D\u4E00\u81F4\u4F1A\u8BA9\u534F\u4F5C\u8005\u6539\u7528\u82F1\u6587\u4F5C\u7B54\u3002
|
|
348
349
|
- \u4EC5\u8F93\u51FA\u6458\u8981\u7AE0\u8282\uFF0C\u4E0D\u9644\u52A0\u524D\u8A00\u3002`,
|
|
349
350
|
continuationContract: "\u4ECE\u4F60\u4E4B\u524D\u4E2D\u65AD\u7684\u5730\u65B9\u7EE7\u7EED\uFF1A\u5B8C\u5168\u6309\u7167\u63CF\u8FF0\u63A5\u7EED\u5F53\u524D\u5DE5\u4F5C\u548C\u4E0B\u4E00\u6B65\u3002\u4E0D\u8981\u91CD\u65B0\u8BE2\u95EE\u5DF2\u56DE\u7B54\u7684\u95EE\u9898\uFF0C\u4E0D\u8981\u56DE\u987E\uFF0C\u4E0D\u8981\u63D0\u53CA\u4E0A\u4E0B\u6587\u5DF2\u88AB\u538B\u7F29\u3002\u5982\u679C\u4F60\u9700\u8981\u4E0A\u8FF0\u63D0\u5230\u7684\u6587\u4EF6\u7684\u5185\u5BB9\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u5B83\u3002",
|
|
351
|
+
compactedIntro: "\u672C\u4F1A\u8BDD\u8F83\u65E9\u7684\u8F6E\u6B21\u5DF2\u88AB\u538B\u7F29\u3002\u4E0B\u9762\u7684\u6458\u8981\u5C31\u662F\u4F60\u5BF9\u90A3\u4E9B\u8F6E\u6B21\u7684\u8BB0\u5FC6\u3002",
|
|
352
|
+
compactedUserMessagesHeader: "## \u538B\u7F29\u533A\u95F4\u5185\u7684\u7528\u6237\u6D88\u606F\uFF08\u539F\u6587\uFF0C\u6309\u65F6\u95F4\u987A\u5E8F\uFF09",
|
|
353
|
+
compactedOmittedNote: (n) => `\uFF08\u66F4\u65E9\u7684 ${n} \u6761\u7528\u6237\u6D88\u606F\u5DF2\u7701\u7565 \u2014\u2014 \u5176\u610F\u56FE\u5DF2\u5305\u542B\u5728\u4E0A\u9762\u7684\u6458\u8981\u4E2D\uFF09`,
|
|
354
|
+
compactedTrimmedNote: "\uFF08\u8F83\u65E9\u7684\u8F6E\u6B21\u56E0\u4E0A\u4E0B\u6587\u7A97\u53E3\u9650\u5236\u88AB\u88C1\u526A\uFF0C\u6CA1\u6709\u53EF\u7528\u6458\u8981\u3002\u5982\u679C\u9700\u8981\u65E9\u5148\u7684\u7ED3\u679C\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\u6216\u91CD\u65B0\u6267\u884C\u547D\u4EE4\u3002\uFF09",
|
|
355
|
+
workingStateHeader: "## \u5DE5\u4F5C\u72B6\u6001\uFF08\u4ECE\u5DE5\u5177\u8BB0\u5F55\u4E2D\u673A\u68B0\u63D0\u53D6\uFF09",
|
|
356
|
+
workingStateFiles: "\u5DF2\u5199\u5165/\u4FEE\u6539\u7684\u6587\u4EF6\uFF08\u6700\u8FD1\u7684\u5728\u524D\uFF09\uFF1A",
|
|
357
|
+
workingStateCommands: "\u6700\u8FD1\u7684 shell \u547D\u4EE4\uFF1A",
|
|
358
|
+
workingStateTools: (list) => `\u538B\u7F29\u533A\u95F4\u5185\u4F7F\u7528\u8FC7\u7684\u5DE5\u5177\uFF1A${list}`,
|
|
350
359
|
genCommitMessageInstructions: `\u4F60\u662F Git \u63D0\u4EA4\u8BF4\u660E\u751F\u6210\u52A9\u624B\u3002\u6839\u636E\u7ED9\u5B9A\u7684\u4EE3\u7801\u5DEE\u5F02\uFF0C\u751F\u6210\u4E00\u6761\u51C6\u786E\u3001\u7B80\u6D01\u7684\u63D0\u4EA4\u8BF4\u660E\u3002
|
|
351
360
|
|
|
352
361
|
\u8981\u6C42\uFF1A
|
|
@@ -500,8 +509,17 @@ Rules:
|
|
|
500
509
|
- Do not treat full file contents as truth. Record only the fact that a file was read/edited; the collaborator will re-read it if it needs the content again. Stale file memory is worse than no memory.
|
|
501
510
|
- If a previous summary is provided: fold only its still-valid conclusions into the matching sections; do not restate it wholesale or copy it entry by entry.
|
|
502
511
|
- Be specific: paths, names, commands, ids \u2014 not vague references.
|
|
512
|
+
- Write the summary in English. It is re-sent with the context on every later turn; a language mismatch makes the collaborator switch to another language.
|
|
503
513
|
- Output only the summary sections, with no preamble.`,
|
|
504
514
|
continuationContract: "Continue from where you left off: pick up the current work and next step exactly as described. Do not re-ask questions that were already answered, do not recap, and do not mention that the context was compacted. If you need the contents of a file mentioned above, read it again.",
|
|
515
|
+
compactedIntro: "Earlier turns of this session were compacted. The summary below is your memory of them.",
|
|
516
|
+
compactedUserMessagesHeader: "## User messages in the compacted span (verbatim, chronological)",
|
|
517
|
+
compactedOmittedNote: (n) => `(${n} earlier user messages omitted \u2014 their intent is covered by the summary above)`,
|
|
518
|
+
compactedTrimmedNote: "(Older turns were trimmed to fit the context window; no summary is available for them. Re-read files and re-run commands if earlier results are needed.)",
|
|
519
|
+
workingStateHeader: "## Working state (extracted mechanically from tool records)",
|
|
520
|
+
workingStateFiles: "Files written/edited (most recent first):",
|
|
521
|
+
workingStateCommands: "Recent shell commands:",
|
|
522
|
+
workingStateTools: (list) => `Tools used in the summarized span: ${list}`,
|
|
505
523
|
genCommitMessageInstructions: `You are a Git commit message assistant. Given a code diff, produce an accurate, concise commit message.
|
|
506
524
|
|
|
507
525
|
Requirements:
|
|
@@ -655,8 +673,17 @@ var zhTW = {
|
|
|
655
673
|
- \u4E0D\u8981\u5C07\u5B8C\u6574\u7684\u6A94\u6848\u5167\u5BB9\u7576\u4F5C\u771F\u7406\u3002\u53EA\u8A18\u9304\u67D0\u500B\u6A94\u6848\u88AB\u8B80\u53D6/\u7DE8\u8F2F\u904E\u9019\u4E00\u4E8B\u5BE6\uFF1B\u5354\u4F5C\u8005\u5982\u679C\u9700\u8981\u518D\u6B21\u7372\u53D6\u5167\u5BB9\u6703\u91CD\u65B0\u8B80\u53D6\u3002\u9673\u820A\u7684\u6A94\u6848\u8A18\u61B6\u6BD4\u6C92\u6709\u8A18\u61B6\u66F4\u7CDF\u7CD5\u3002
|
|
656
674
|
- \u82E5\u63D0\u4F9B\u4E86\u4E0A\u4E00\u7248\u6458\u8981\uFF1A\u53EA\u628A\u5B83\u4ECD\u7136\u6709\u6548\u7684\u7D50\u8AD6\u4F75\u5165\u5C0D\u61C9\u7AE0\u7BC0\uFF0C\u4E0D\u8981\u6574\u6BB5\u8907\u8FF0\u6216\u9010\u689D\u8F49\u6284\u3002
|
|
657
675
|
- \u8981\u5177\u9AD4\uFF1A\u8DEF\u5F91\u3001\u540D\u7A31\u3001\u547D\u4EE4\u3001id\u2014\u2014\u800C\u4E0D\u662F\u6A21\u7CCA\u7684\u5F15\u7528\u3002
|
|
676
|
+
- \u7528\u7E41\u9AD4\u4E2D\u6587\u64B0\u5BEB\u6458\u8981\u3002\u6458\u8981\u5728\u5F8C\u7E8C\u6BCF\u4E00\u8F2A\u90FD\u6703\u96A8\u4E0A\u4E0B\u6587\u91CD\u767C\uFF0C\u8A9E\u8A00\u4E0D\u4E00\u81F4\u6703\u8B93\u5354\u4F5C\u8005\u6539\u7528\u5176\u4ED6\u8A9E\u8A00\u4F5C\u7B54\u3002
|
|
658
677
|
- \u50C5\u8F38\u51FA\u6458\u8981\u7AE0\u7BC0\uFF0C\u4E0D\u9644\u52A0\u524D\u8A00\u3002`,
|
|
659
678
|
continuationContract: "\u5F9E\u4F60\u4E4B\u524D\u4E2D\u65B7\u7684\u5730\u65B9\u7E7C\u7E8C\uFF1A\u5B8C\u5168\u6309\u7167\u63CF\u8FF0\u63A5\u7E8C\u7576\u524D\u5DE5\u4F5C\u548C\u4E0B\u4E00\u6B65\u3002\u4E0D\u8981\u91CD\u65B0\u8A62\u554F\u5DF2\u56DE\u7B54\u7684\u554F\u984C\uFF0C\u4E0D\u8981\u56DE\u9867\uFF0C\u4E0D\u8981\u63D0\u53CA\u4E0A\u4E0B\u6587\u5DF2\u88AB\u58D3\u7E2E\u3002\u5982\u679C\u4F60\u9700\u8981\u4E0A\u8FF0\u63D0\u5230\u7684\u6A94\u6848\u7684\u5167\u5BB9\uFF0C\u8ACB\u91CD\u65B0\u8B80\u53D6\u5B83\u3002",
|
|
679
|
+
compactedIntro: "\u672C\u6703\u8A71\u8F03\u65E9\u7684\u8F2A\u6B21\u5DF2\u88AB\u58D3\u7E2E\u3002\u4E0B\u9762\u7684\u6458\u8981\u5C31\u662F\u4F60\u5C0D\u90A3\u4E9B\u8F2A\u6B21\u7684\u8A18\u61B6\u3002",
|
|
680
|
+
compactedUserMessagesHeader: "## \u58D3\u7E2E\u5340\u9593\u5167\u7684\u4F7F\u7528\u8005\u8A0A\u606F\uFF08\u539F\u6587\uFF0C\u6309\u6642\u9593\u9806\u5E8F\uFF09",
|
|
681
|
+
compactedOmittedNote: (n) => `\uFF08\u66F4\u65E9\u7684 ${n} \u5247\u4F7F\u7528\u8005\u8A0A\u606F\u5DF2\u7701\u7565 \u2014\u2014 \u5176\u610F\u5716\u5DF2\u5305\u542B\u5728\u4E0A\u9762\u7684\u6458\u8981\u4E2D\uFF09`,
|
|
682
|
+
compactedTrimmedNote: "\uFF08\u8F03\u65E9\u7684\u8F2A\u6B21\u56E0\u4E0A\u4E0B\u6587\u8996\u7A97\u9650\u5236\u88AB\u88C1\u526A\uFF0C\u6C92\u6709\u53EF\u7528\u6458\u8981\u3002\u5982\u679C\u9700\u8981\u65E9\u5148\u7684\u7D50\u679C\uFF0C\u8ACB\u91CD\u65B0\u8B80\u53D6\u6A94\u6848\u6216\u91CD\u65B0\u57F7\u884C\u547D\u4EE4\u3002\uFF09",
|
|
683
|
+
workingStateHeader: "## \u5DE5\u4F5C\u72C0\u614B\uFF08\u5F9E\u5DE5\u5177\u8A18\u9304\u4E2D\u6A5F\u68B0\u63D0\u53D6\uFF09",
|
|
684
|
+
workingStateFiles: "\u5DF2\u5BEB\u5165/\u4FEE\u6539\u7684\u6A94\u6848\uFF08\u6700\u8FD1\u7684\u5728\u524D\uFF09\uFF1A",
|
|
685
|
+
workingStateCommands: "\u6700\u8FD1\u7684 shell \u547D\u4EE4\uFF1A",
|
|
686
|
+
workingStateTools: (list) => `\u58D3\u7E2E\u5340\u9593\u5167\u4F7F\u7528\u904E\u7684\u5DE5\u5177\uFF1A${list}`,
|
|
660
687
|
genCommitMessageInstructions: `\u4F60\u662F Git \u63D0\u4EA4\u8AAA\u660E\u751F\u6210\u52A9\u624B\u3002\u6839\u64DA\u7D66\u5B9A\u7684\u7A0B\u5F0F\u78BC\u5DEE\u7570\uFF0C\u751F\u6210\u4E00\u689D\u6E96\u78BA\u3001\u7C21\u6F54\u7684\u63D0\u4EA4\u8AAA\u660E\u3002
|
|
661
688
|
|
|
662
689
|
\u8981\u6C42\uFF1A
|
|
@@ -810,8 +837,17 @@ shell \u30B3\u30DE\u30F3\u30C9\u306B\u8907\u6570\u884C\u306E\u30B9\u30AF\u30EA\u
|
|
|
810
837
|
- \u30D5\u30A1\u30A4\u30EB\u306E\u5185\u5BB9\u5168\u4F53\u3092\u771F\u5B9F\u3068\u3057\u3066\u6271\u308F\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\u3042\u308B\u30D5\u30A1\u30A4\u30EB\u304C\u8AAD\u307E\u308C\u305F\uFF0F\u7DE8\u96C6\u3055\u308C\u305F\u3068\u3044\u3046\u4E8B\u5B9F\u3060\u3051\u3092\u8A18\u9332\u3057\u307E\u3059\u3002\u5354\u50CD\u8005\u306F\u5185\u5BB9\u304C\u518D\u3073\u5FC5\u8981\u306B\u306A\u308C\u3070\u8AAD\u307F\u76F4\u3057\u307E\u3059\u3002\u53E4\u3044\u30D5\u30A1\u30A4\u30EB\u8A18\u61B6\u306F\u8A18\u61B6\u304C\u306A\u3044\u3088\u308A\u60AA\u3044\u3002
|
|
811
838
|
- \u524D\u56DE\u306E\u8981\u7D04\u304C\u63D0\u4F9B\u3055\u308C\u305F\u5834\u5408\uFF1A\u307E\u3060\u6709\u52B9\u306A\u7D50\u8AD6\u3060\u3051\u3092\u8A72\u5F53\u30BB\u30AF\u30B7\u30E7\u30F3\u306B\u7D71\u5408\u3057\u3001\u5168\u4F53\u3092\u66F8\u304D\u76F4\u3057\u305F\u308A\u9805\u76EE\u3054\u3068\u306B\u8EE2\u8A18\u3057\u305F\u308A\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
|
|
812
839
|
- \u5177\u4F53\u7684\u306B\uFF1A\u30D1\u30B9\u3001\u540D\u524D\u3001\u30B3\u30DE\u30F3\u30C9\u3001id \u3092\u66F8\u304F\u3002\u66D6\u6627\u306A\u53C2\u7167\u306B\u3057\u306A\u3044\u3002
|
|
840
|
+
- \u8981\u7D04\u306F\u65E5\u672C\u8A9E\u3067\u66F8\u3044\u3066\u304F\u3060\u3055\u3044\u3002\u8981\u7D04\u306F\u4EE5\u964D\u306E\u6BCE\u30BF\u30FC\u30F3\u3067\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3068\u3068\u3082\u306B\u518D\u9001\u3055\u308C\u308B\u305F\u3081\u3001\u8A00\u8A9E\u304C\u98DF\u3044\u9055\u3046\u3068\u5354\u50CD\u8005\u304C\u5225\u306E\u8A00\u8A9E\u3067\u7B54\u3048\u308B\u3088\u3046\u306B\u306A\u308A\u307E\u3059\u3002
|
|
813
841
|
- \u8981\u7D04\u30BB\u30AF\u30B7\u30E7\u30F3\u3060\u3051\u3092\u51FA\u529B\u3057\u3001\u524D\u7F6E\u304D\u3092\u4ED8\u3051\u306A\u3044\u3002`,
|
|
814
842
|
continuationContract: "\u524D\u56DE\u4E2D\u65AD\u3057\u305F\u3068\u3053\u308D\u304B\u3089\u7D9A\u3051\u3066\u304F\u3060\u3055\u3044\uFF1A\u8AAC\u660E\u3069\u304A\u308A\u306B\u73FE\u5728\u306E\u4F5C\u696D\u3068\u6B21\u306E\u624B\u9806\u3092\u5F15\u304D\u7D99\u304E\u307E\u3059\u3002\u65E2\u306B\u56DE\u7B54\u6E08\u307F\u306E\u8CEA\u554F\u3092\u7E70\u308A\u8FD4\u3055\u305A\u3001\u632F\u308A\u8FD4\u3089\u305A\u3001\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u304C\u5727\u7E2E\u3055\u308C\u305F\u3053\u3068\u306B\u3082\u89E6\u308C\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\u4E0A\u8A18\u3067\u8A00\u53CA\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u306E\u5185\u5BB9\u304C\u5FC5\u8981\u306A\u5834\u5408\u306F\u3001\u3082\u3046\u4E00\u5EA6\u8AAD\u3093\u3067\u304F\u3060\u3055\u3044\u3002",
|
|
843
|
+
compactedIntro: "\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u4EE5\u524D\u306E\u30BF\u30FC\u30F3\u306F\u5727\u7E2E\u3055\u308C\u307E\u3057\u305F\u3002\u4EE5\u4E0B\u306E\u8981\u7D04\u304C\u305D\u308C\u3089\u306E\u30BF\u30FC\u30F3\u306B\u3064\u3044\u3066\u306E\u3042\u306A\u305F\u306E\u8A18\u61B6\u3067\u3059\u3002",
|
|
844
|
+
compactedUserMessagesHeader: "## \u5727\u7E2E\u533A\u9593\u5185\u306E\u30E6\u30FC\u30B6\u30FC\u30E1\u30C3\u30BB\u30FC\u30B8\uFF08\u539F\u6587\u3001\u6642\u7CFB\u5217\uFF09",
|
|
845
|
+
compactedOmittedNote: (n) => `\uFF08\u4EE5\u524D\u306E\u30E6\u30FC\u30B6\u30FC\u30E1\u30C3\u30BB\u30FC\u30B8 ${n} \u4EF6\u306F\u7701\u7565\u3055\u308C\u307E\u3057\u305F \u2014 \u305D\u306E\u610F\u56F3\u306F\u4E0A\u8A18\u306E\u8981\u7D04\u306B\u542B\u307E\u308C\u3066\u3044\u307E\u3059\uFF09`,
|
|
846
|
+
compactedTrimmedNote: "\uFF08\u4EE5\u524D\u306E\u30BF\u30FC\u30F3\u306F\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u30A6\u30A3\u30F3\u30C9\u30A6\u306E\u5236\u9650\u306B\u3088\u308A\u5207\u308A\u8A70\u3081\u3089\u308C\u3001\u8981\u7D04\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u4EE5\u524D\u306E\u7D50\u679C\u304C\u5FC5\u8981\u306A\u5834\u5408\u306F\u3001\u30D5\u30A1\u30A4\u30EB\u3092\u518D\u8AAD\u307F\u8FBC\u307F\u3059\u308B\u304B\u30B3\u30DE\u30F3\u30C9\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002\uFF09",
|
|
847
|
+
workingStateHeader: "## \u4F5C\u696D\u72B6\u614B\uFF08\u30C4\u30FC\u30EB\u8A18\u9332\u304B\u3089\u6A5F\u68B0\u7684\u306B\u62BD\u51FA\uFF09",
|
|
848
|
+
workingStateFiles: "\u66F8\u304D\u8FBC\u307F/\u7DE8\u96C6\u3057\u305F\u30D5\u30A1\u30A4\u30EB\uFF08\u65B0\u3057\u3044\u9806\uFF09\uFF1A",
|
|
849
|
+
workingStateCommands: "\u6700\u8FD1\u306E\u30B7\u30A7\u30EB\u30B3\u30DE\u30F3\u30C9\uFF1A",
|
|
850
|
+
workingStateTools: (list) => `\u5727\u7E2E\u533A\u9593\u5185\u3067\u4F7F\u7528\u3057\u305F\u30C4\u30FC\u30EB\uFF1A${list}`,
|
|
815
851
|
genCommitMessageInstructions: `\u3042\u306A\u305F\u306F Git \u30B3\u30DF\u30C3\u30C8\u30E1\u30C3\u30BB\u30FC\u30B8\u751F\u6210\u30A2\u30B7\u30B9\u30BF\u30F3\u30C8\u3067\u3059\u3002\u4E0E\u3048\u3089\u308C\u305F\u30B3\u30FC\u30C9\u5DEE\u5206\u304B\u3089\u3001\u6B63\u78BA\u3067\u7C21\u6F54\u306A\u30B3\u30DF\u30C3\u30C8\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u751F\u6210\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
816
852
|
|
|
817
853
|
\u8981\u4EF6\uFF1A
|
|
@@ -965,8 +1001,17 @@ shell \uBA85\uB839\uC5D0 \uC5EC\uB7EC \uC904 \uC2A4\uD06C\uB9BD\uD2B8\uB97C \uC7
|
|
|
965
1001
|
- \uD30C\uC77C \uB0B4\uC6A9 \uC804\uCCB4\uB97C \uC9C4\uC2E4\uB85C \uCDE8\uAE09\uD558\uC9C0 \uB9C8\uC138\uC694. \uC5B4\uB5A4 \uD30C\uC77C\uC774 \uC77D\uD788\uAC70\uB098 \uD3B8\uC9D1\uB418\uC5C8\uB2E4\uB294 \uC0AC\uC2E4\uB9CC \uAE30\uB85D\uD569\uB2C8\uB2E4. \uD611\uC5C5\uC790\uB294 \uB0B4\uC6A9\uC774 \uB2E4\uC2DC \uD544\uC694\uD558\uBA74 \uB2E4\uC2DC \uC77D\uC2B5\uB2C8\uB2E4. \uC624\uB798\uB41C \uD30C\uC77C \uAE30\uC5B5\uC740 \uAE30\uC5B5\uC774 \uC5C6\uB294 \uAC83\uBCF4\uB2E4 \uB098\uC069\uB2C8\uB2E4.
|
|
966
1002
|
- \uC774\uC804 \uC694\uC57D\uC774 \uC81C\uACF5\uB418\uC5C8\uB2E4\uBA74: \uC5EC\uC804\uD788 \uC720\uD6A8\uD55C \uACB0\uB860\uB9CC \uD574\uB2F9 \uC139\uC158\uC5D0 \uBCD1\uD569\uD558\uACE0, \uC804\uCCB4\uB97C \uB2E4\uC2DC \uC4F0\uAC70\uB098 \uD56D\uBAA9\uBCC4\uB85C \uC62E\uACA8 \uC801\uC9C0 \uB9C8\uC138\uC694.
|
|
967
1003
|
- \uAD6C\uCCB4\uC801\uC73C\uB85C: \uACBD\uB85C, \uC774\uB984, \uBA85\uB839, id\uB97C \uC4F8 \uAC83. \uBAA8\uD638\uD55C \uCC38\uC870\uB294 \uAE08\uC9C0.
|
|
1004
|
+
- \uC694\uC57D\uC740 \uD55C\uAD6D\uC5B4\uB85C \uC791\uC131\uD558\uC138\uC694. \uC694\uC57D\uC740 \uC774\uD6C4 \uB9E4 \uD134\uB9C8\uB2E4 \uCEE8\uD14D\uC2A4\uD2B8\uC640 \uD568\uAED8 \uB2E4\uC2DC \uC804\uC1A1\uB418\uBBC0\uB85C, \uC5B8\uC5B4\uAC00 \uC5B4\uAE0B\uB098\uBA74 \uD611\uC5C5\uC790\uAC00 \uB2E4\uB978 \uC5B8\uC5B4\uB85C \uB2F5\uD558\uAC8C \uB429\uB2C8\uB2E4.
|
|
968
1005
|
- \uC694\uC57D \uC139\uC158\uB9CC \uCD9C\uB825\uD558\uACE0 \uC11C\uB450\uB97C \uBD99\uC774\uC9C0 \uB9C8\uC138\uC694.`,
|
|
969
1006
|
continuationContract: "\uC911\uB2E8\uD55C \uC9C0\uC810\uBD80\uD130 \uC774\uC5B4\uAC00\uC138\uC694: \uC124\uBA85\uD55C \uB300\uB85C \uD604\uC7AC \uC791\uC5C5\uACFC \uB2E4\uC74C \uB2E8\uACC4\uB97C \uADF8\uB300\uB85C \uC774\uC5B4\uBC1B\uC2B5\uB2C8\uB2E4. \uC774\uBBF8 \uB2F5\uD55C \uC9C8\uBB38\uC744 \uB2E4\uC2DC \uBB3B\uC9C0 \uB9D0\uACE0, \uB418\uB3CC\uC544\uBCF4\uC9C0 \uB9D0\uACE0, \uCEE8\uD14D\uC2A4\uD2B8\uAC00 \uC555\uCD95\uB418\uC5C8\uB2E4\uB294 \uC0AC\uC2E4\uB3C4 \uC5B8\uAE09\uD558\uC9C0 \uB9C8\uC138\uC694. \uC704\uC5D0\uC11C \uC5B8\uAE09\uD55C \uD30C\uC77C\uC758 \uB0B4\uC6A9\uC774 \uD544\uC694\uD558\uBA74 \uB2E4\uC2DC \uC77D\uC73C\uC138\uC694.",
|
|
1007
|
+
compactedIntro: "\uC774 \uC138\uC158\uC758 \uC774\uC804 \uD134\uC740 \uC555\uCD95\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC544\uB798 \uC694\uC57D\uC774 \uADF8 \uD134\uB4E4\uC5D0 \uB300\uD55C \uB2F9\uC2E0\uC758 \uAE30\uC5B5\uC785\uB2C8\uB2E4.",
|
|
1008
|
+
compactedUserMessagesHeader: "## \uC555\uCD95 \uAD6C\uAC04\uC758 \uC0AC\uC6A9\uC790 \uBA54\uC2DC\uC9C0 (\uC6D0\uBB38, \uC2DC\uAC04 \uC21C)",
|
|
1009
|
+
compactedOmittedNote: (n) => `(\uC774\uC804 \uC0AC\uC6A9\uC790 \uBA54\uC2DC\uC9C0 ${n}\uAC1C\uB294 \uC0DD\uB7B5\uB428 \u2014 \uADF8 \uC758\uB3C4\uB294 \uC704 \uC694\uC57D\uC5D0 \uD3EC\uD568\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4)`,
|
|
1010
|
+
compactedTrimmedNote: "(\uC774\uC804 \uD134\uC740 \uCEE8\uD14D\uC2A4\uD2B8 \uC708\uB3C4 \uC81C\uD55C\uC73C\uB85C \uC798\uB838\uC73C\uBA70 \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uC694\uC57D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uC774\uC804 \uACB0\uACFC\uAC00 \uD544\uC694\uD558\uBA74 \uD30C\uC77C\uC744 \uB2E4\uC2DC \uC77D\uAC70\uB098 \uBA85\uB839\uC744 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.)",
|
|
1011
|
+
workingStateHeader: "## \uC791\uC5C5 \uC0C1\uD0DC (\uB3C4\uAD6C \uAE30\uB85D\uC5D0\uC11C \uAE30\uACC4\uC801\uC73C\uB85C \uCD94\uCD9C)",
|
|
1012
|
+
workingStateFiles: "\uC791\uC131/\uC218\uC815\uD55C \uD30C\uC77C (\uCD5C\uADFC \uC21C):",
|
|
1013
|
+
workingStateCommands: "\uCD5C\uADFC \uC178 \uBA85\uB839:",
|
|
1014
|
+
workingStateTools: (list) => `\uC555\uCD95 \uAD6C\uAC04\uC5D0\uC11C \uC0AC\uC6A9\uD55C \uB3C4\uAD6C: ${list}`,
|
|
970
1015
|
genCommitMessageInstructions: `\uB2F9\uC2E0\uC740 Git \uCEE4\uBC0B \uBA54\uC2DC\uC9C0 \uC0DD\uC131 \uC5B4\uC2DC\uC2A4\uD134\uD2B8\uC785\uB2C8\uB2E4. \uC8FC\uC5B4\uC9C4 \uCF54\uB4DC \uCC28\uC774\uB85C \uC815\uD655\uD558\uACE0 \uAC04\uACB0\uD55C \uCEE4\uBC0B \uBA54\uC2DC\uC9C0\uB97C \uC0DD\uC131\uD558\uC138\uC694.
|
|
971
1016
|
|
|
972
1017
|
\uC694\uAD6C \uC0AC\uD56D:
|
|
@@ -1120,8 +1165,17 @@ Reglas:
|
|
|
1120
1165
|
- No trates el contenido completo de un archivo como verdad. Registra solo el hecho de que un archivo se ley\xF3 o edit\xF3; el colaborador volver\xE1 a leerlo si necesita el contenido. Una memoria obsoleta de un archivo es peor que no tener memoria.
|
|
1121
1166
|
- Si se proporciona un resumen anterior: integra solo sus conclusiones a\xFAn v\xE1lidas en las secciones correspondientes; no lo repitas entero ni lo copies entrada por entrada.
|
|
1122
1167
|
- S\xE9 concreto: rutas, nombres, comandos, ids, no referencias vagas.
|
|
1168
|
+
- Escribe el resumen en espa\xF1ol. Se reenv\xEDa con el contexto en cada turno posterior; una diferencia de idioma hace que el colaborador responda en otro idioma.
|
|
1123
1169
|
- Devuelve solo las secciones del resumen, sin pre\xE1mbulo.`,
|
|
1124
1170
|
continuationContract: "Contin\xFAa donde lo dejaste: retoma el trabajo actual y el siguiente paso exactamente como se describe. No vuelvas a preguntar lo que ya se respondi\xF3, no recapitules y no menciones que el contexto se ha compactado. Si necesitas el contenido de alg\xFAn archivo mencionado arriba, vuelve a leerlo.",
|
|
1171
|
+
compactedIntro: "Los turnos anteriores de esta sesi\xF3n se compactaron. El resumen de abajo es tu memoria de ellos.",
|
|
1172
|
+
compactedUserMessagesHeader: "## Mensajes del usuario en el tramo compactado (textual, cronol\xF3gico)",
|
|
1173
|
+
compactedOmittedNote: (n) => `(${n} mensajes anteriores del usuario omitidos \u2014 su intenci\xF3n est\xE1 cubierta por el resumen de arriba)`,
|
|
1174
|
+
compactedTrimmedNote: "(Los turnos anteriores se recortaron para ajustarse a la ventana de contexto; no hay resumen disponible. Vuelve a leer archivos y reejecuta comandos si necesitas resultados previos.)",
|
|
1175
|
+
workingStateHeader: "## Estado de trabajo (extra\xEDdo mec\xE1nicamente de los registros de herramientas)",
|
|
1176
|
+
workingStateFiles: "Archivos escritos/editados (m\xE1s recientes primero):",
|
|
1177
|
+
workingStateCommands: "Comandos de shell recientes:",
|
|
1178
|
+
workingStateTools: (list) => `Herramientas usadas en el tramo resumido: ${list}`,
|
|
1125
1179
|
genCommitMessageInstructions: `Eres un asistente de mensajes de commit de Git. Dado un diff de c\xF3digo, produce un mensaje de commit preciso y conciso.
|
|
1126
1180
|
|
|
1127
1181
|
Requisitos:
|
|
@@ -1378,7 +1432,7 @@ function pickBoundary(messages, keepTokens) {
|
|
|
1378
1432
|
return boundary;
|
|
1379
1433
|
}
|
|
1380
1434
|
var WRITE_HINTS = ["write", "edit", "append", "save", "create", "patch"];
|
|
1381
|
-
function extractWorkingState(span) {
|
|
1435
|
+
function extractWorkingState(span, lang) {
|
|
1382
1436
|
const files = [];
|
|
1383
1437
|
const commands = [];
|
|
1384
1438
|
const tools = /* @__PURE__ */ new Set();
|
|
@@ -1421,23 +1475,20 @@ function extractWorkingState(span) {
|
|
|
1421
1475
|
}
|
|
1422
1476
|
return seen;
|
|
1423
1477
|
};
|
|
1424
|
-
const
|
|
1425
|
-
|
|
1426
|
-
];
|
|
1478
|
+
const p = getPrompts(lang);
|
|
1479
|
+
const lines = [p.workingStateHeader];
|
|
1427
1480
|
const written = dedupe(files, 20);
|
|
1428
1481
|
if (written.length) {
|
|
1429
|
-
lines.push(
|
|
1482
|
+
lines.push(p.workingStateFiles);
|
|
1430
1483
|
lines.push(...written.map((f) => `- ${f}`));
|
|
1431
1484
|
}
|
|
1432
1485
|
const recentCmds = commands.slice(-10);
|
|
1433
1486
|
if (recentCmds.length) {
|
|
1434
|
-
lines.push(
|
|
1487
|
+
lines.push(p.workingStateCommands);
|
|
1435
1488
|
lines.push(...recentCmds.map((c) => `- ${c}`));
|
|
1436
1489
|
}
|
|
1437
1490
|
if (tools.size) {
|
|
1438
|
-
lines.push(
|
|
1439
|
-
"Tools used in the summarized span: " + [...tools].sort().join(", ")
|
|
1440
|
-
);
|
|
1491
|
+
lines.push(p.workingStateTools([...tools].sort().join(", ")));
|
|
1441
1492
|
}
|
|
1442
1493
|
return lines.length > 1 ? lines.join("\n") : "";
|
|
1443
1494
|
}
|
|
@@ -1561,7 +1612,7 @@ async function buildState(messages, provider, model, keepTokens, prior = null, o
|
|
|
1561
1612
|
return {
|
|
1562
1613
|
boundaryIndex: boundary,
|
|
1563
1614
|
summaryText: summary,
|
|
1564
|
-
workingState: extractWorkingState(span),
|
|
1615
|
+
workingState: extractWorkingState(span, lang),
|
|
1565
1616
|
userMessages: cappedUsers,
|
|
1566
1617
|
userMessagesDropped: dropped,
|
|
1567
1618
|
createdAt: Date.now(),
|
|
@@ -1569,7 +1620,7 @@ async function buildState(messages, provider, model, keepTokens, prior = null, o
|
|
|
1569
1620
|
trimmed: false
|
|
1570
1621
|
};
|
|
1571
1622
|
}
|
|
1572
|
-
function trimState(messages, prior = null, fraction = TRIM_FRACTION) {
|
|
1623
|
+
function trimState(messages, prior = null, fraction = TRIM_FRACTION, lang) {
|
|
1573
1624
|
const start = prior?.boundaryIndex ?? 0;
|
|
1574
1625
|
const remaining = messages.length - start;
|
|
1575
1626
|
if (remaining <= 2) return null;
|
|
@@ -1587,7 +1638,7 @@ function trimState(messages, prior = null, fraction = TRIM_FRACTION) {
|
|
|
1587
1638
|
const span = messages.slice(start, boundary);
|
|
1588
1639
|
const priorUsers = prior?.userMessages ? [...prior.userMessages] : [];
|
|
1589
1640
|
const priorSummary = prior?.summaryText ?? "";
|
|
1590
|
-
const summary = (priorSummary ? priorSummary + "\n\n" : "") +
|
|
1641
|
+
const summary = (priorSummary ? priorSummary + "\n\n" : "") + getPrompts(lang).compactedTrimmedNote;
|
|
1591
1642
|
const allUsers = [...priorUsers, ...extractUserMessages(span)];
|
|
1592
1643
|
const { messages: cappedUsers, dropped } = capUserMessages(
|
|
1593
1644
|
allUsers,
|
|
@@ -1596,7 +1647,7 @@ function trimState(messages, prior = null, fraction = TRIM_FRACTION) {
|
|
|
1596
1647
|
return {
|
|
1597
1648
|
boundaryIndex: boundary,
|
|
1598
1649
|
summaryText: summary,
|
|
1599
|
-
workingState: extractWorkingState(span),
|
|
1650
|
+
workingState: extractWorkingState(span, lang),
|
|
1600
1651
|
userMessages: cappedUsers,
|
|
1601
1652
|
userMessagesDropped: dropped,
|
|
1602
1653
|
createdAt: Date.now(),
|
|
@@ -1607,7 +1658,7 @@ function trimState(messages, prior = null, fraction = TRIM_FRACTION) {
|
|
|
1607
1658
|
function compactedBlock(state, lang) {
|
|
1608
1659
|
const parts = [
|
|
1609
1660
|
"<compacted-history>",
|
|
1610
|
-
|
|
1661
|
+
getPrompts(lang).compactedIntro,
|
|
1611
1662
|
"",
|
|
1612
1663
|
state.summaryText
|
|
1613
1664
|
];
|
|
@@ -1617,12 +1668,10 @@ function compactedBlock(state, lang) {
|
|
|
1617
1668
|
if (state.userMessages.length > 0) {
|
|
1618
1669
|
parts.push(
|
|
1619
1670
|
"",
|
|
1620
|
-
|
|
1671
|
+
getPrompts(lang).compactedUserMessagesHeader
|
|
1621
1672
|
);
|
|
1622
1673
|
if (state.userMessagesDropped > 0) {
|
|
1623
|
-
parts.push(
|
|
1624
|
-
`(${state.userMessagesDropped} earlier user messages omitted \u2014 their intent is covered by the summary above)`
|
|
1625
|
-
);
|
|
1674
|
+
parts.push(getPrompts(lang).compactedOmittedNote(state.userMessagesDropped));
|
|
1626
1675
|
}
|
|
1627
1676
|
parts.push(...state.userMessages.map((u) => `- ${u}`));
|
|
1628
1677
|
}
|
|
@@ -1724,12 +1773,12 @@ var MUTATING_TOOLS = /* @__PURE__ */ new Set([
|
|
|
1724
1773
|
]);
|
|
1725
1774
|
function parseReadFileSpan(content) {
|
|
1726
1775
|
const body = content.replace(/^\[tool output truncated:[^\n]*\]\n\n/, "");
|
|
1727
|
-
let
|
|
1776
|
+
let path13;
|
|
1728
1777
|
let start;
|
|
1729
1778
|
let end;
|
|
1730
1779
|
try {
|
|
1731
1780
|
const obj = JSON.parse(body);
|
|
1732
|
-
|
|
1781
|
+
path13 = obj.path;
|
|
1733
1782
|
start = obj.start_line;
|
|
1734
1783
|
end = obj.end_line;
|
|
1735
1784
|
} catch {
|
|
@@ -1738,14 +1787,14 @@ function parseReadFileSpan(content) {
|
|
|
1738
1787
|
const m = new RegExp(`"${key}"\\s*:\\s*(\\d+)`).exec(body);
|
|
1739
1788
|
return m ? Number(m[1]) : void 0;
|
|
1740
1789
|
};
|
|
1741
|
-
|
|
1790
|
+
path13 = str("path");
|
|
1742
1791
|
start = num("start_line");
|
|
1743
1792
|
end = num("end_line");
|
|
1744
1793
|
}
|
|
1745
|
-
if (typeof
|
|
1794
|
+
if (typeof path13 !== "string" || !path13) return null;
|
|
1746
1795
|
if (typeof start !== "number" || typeof end !== "number") return null;
|
|
1747
1796
|
if (!Number.isFinite(start) || !Number.isFinite(end)) return null;
|
|
1748
|
-
return { path:
|
|
1797
|
+
return { path: path13, start, end };
|
|
1749
1798
|
}
|
|
1750
1799
|
function addSpan(spans, start, end) {
|
|
1751
1800
|
spans.push([start, end]);
|
|
@@ -1802,16 +1851,45 @@ function applyReadFileDedup(messages) {
|
|
|
1802
1851
|
}
|
|
1803
1852
|
var OVERFLOW_MARKERS = [
|
|
1804
1853
|
"context_length_exceeded",
|
|
1805
|
-
"
|
|
1854
|
+
"context length",
|
|
1806
1855
|
"context window",
|
|
1807
1856
|
"prompt is too long",
|
|
1808
1857
|
"input is too long",
|
|
1809
1858
|
"too many tokens",
|
|
1810
1859
|
"input length and `max_tokens` exceed",
|
|
1811
|
-
"exceeds the maximum number of tokens"
|
|
1860
|
+
"exceeds the maximum number of tokens",
|
|
1861
|
+
"\u8D85\u51FA\u6A21\u578B\u4E0A\u4E0B\u6587",
|
|
1862
|
+
"\u8D85\u8FC7\u6A21\u578B\u4E0A\u4E0B\u6587",
|
|
1863
|
+
"\u8D85\u904E\u6A21\u578B\u4E0A\u4E0B\u6587",
|
|
1864
|
+
"\u4E0A\u4E0B\u6587\u957F\u5EA6\u8D85\u8FC7",
|
|
1865
|
+
"\u8D85\u8FC7\u6700\u5927\u4E0A\u4E0B\u6587",
|
|
1866
|
+
"\u8D85\u904E\u6700\u5927\u4E0A\u4E0B\u6587",
|
|
1867
|
+
"\u4E0A\u4E0B\u6587\u8D85\u9650",
|
|
1868
|
+
"\u8F93\u5165\u8FC7\u957F"
|
|
1812
1869
|
];
|
|
1870
|
+
function overflowText(exc) {
|
|
1871
|
+
const parts = [];
|
|
1872
|
+
const push = (v) => {
|
|
1873
|
+
if (typeof v === "string" && v) parts.push(v);
|
|
1874
|
+
};
|
|
1875
|
+
push(String(exc));
|
|
1876
|
+
if (exc && typeof exc === "object") {
|
|
1877
|
+
const rec = exc;
|
|
1878
|
+
push(rec["message"]);
|
|
1879
|
+
push(rec["detail"]);
|
|
1880
|
+
const body = rec["error"];
|
|
1881
|
+
if (body && typeof body === "object") {
|
|
1882
|
+
const b = body;
|
|
1883
|
+
push(b["message"]);
|
|
1884
|
+
push(b["code"]);
|
|
1885
|
+
} else {
|
|
1886
|
+
push(body);
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
return parts.join(" ").toLowerCase();
|
|
1890
|
+
}
|
|
1813
1891
|
function isContextOverflow(exc) {
|
|
1814
|
-
const text =
|
|
1892
|
+
const text = overflowText(exc);
|
|
1815
1893
|
return OVERFLOW_MARKERS.some((m) => text.includes(m));
|
|
1816
1894
|
}
|
|
1817
1895
|
|
|
@@ -1844,6 +1922,9 @@ var TOOL_MAX_CHARS = {
|
|
|
1844
1922
|
web_search: 8e3,
|
|
1845
1923
|
list_files: 8e3,
|
|
1846
1924
|
shell_task_output: 8e3,
|
|
1925
|
+
/* repo_map 自带 16K 上限(tools/repoMap.ts 的 MAX_CHARS)。这里显式登记,
|
|
1926
|
+
* 而不是落到 24K 默认值 —— 免得将来工具上限调大时被二次裁剪,口径也保持一致。 */
|
|
1927
|
+
repo_map: 16e3,
|
|
1847
1928
|
git_log: 6e3,
|
|
1848
1929
|
git_status: 4e3
|
|
1849
1930
|
};
|
|
@@ -2151,6 +2232,7 @@ var INTERACTIVE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
2151
2232
|
var MAX_COMPACT_ROUNDS = 4;
|
|
2152
2233
|
var OVERFLOW_TARGET_RATIO = 0.5;
|
|
2153
2234
|
var OVERFLOW_TRIM_FRACTION = 0.5;
|
|
2235
|
+
var OVERFLOW_ELIDE_KEEP_FRACTION = 0.02;
|
|
2154
2236
|
var COMPACT_STALL_RETRY_DELTA = 20;
|
|
2155
2237
|
var FINALIZE_ON_LIMIT_PROMPT = "\u5DF2\u8FBE\u5230\u672C\u8F6E\u8FED\u4EE3\u4E0A\u9650\uFF0C\u4F60\u4E0D\u80FD\u518D\u8C03\u7528\u4EFB\u4F55\u5DE5\u5177\u3002\u8BF7\u7ACB\u5373\u57FA\u4E8E\u4E0A\u9762\u5DF2\u7ECF\u6536\u96C6\u5230\u7684\u4FE1\u606F\u8F93\u51FA\u6700\u7EC8\u62A5\u544A\uFF1A\u76F4\u63A5\u56DE\u7B54\u4EFB\u52A1\u3001\u7ED9\u51FA\u7ED3\u8BBA\u4E0E path:line \u5F15\u7528\uFF0C\u5E76\u660E\u786E\u8BF4\u660E\u54EA\u4E9B\u90E8\u5206\u5C1A\u672A\u67E5\u8BC1\u3002\u4E0D\u8981\u8BE2\u95EE\u3001\u4E0D\u8981\u7EE7\u7EED\u63A2\u7D22\u3002";
|
|
2156
2238
|
function toolResultMessage(tc, result, taskId, toolResultDir2) {
|
|
@@ -2279,6 +2361,8 @@ var TurnEngine = class _TurnEngine {
|
|
|
2279
2361
|
_lastContextTokens = null;
|
|
2280
2362
|
/** 压缩无进展时的消息条数快照;-1 表示无冷却 */
|
|
2281
2363
|
_compactStalledAt = -1;
|
|
2364
|
+
/** 溢出兜底:已 400 时无条件淘汰旧工具结果(下一次成功调用后复位) */
|
|
2365
|
+
_overflowElide = false;
|
|
2282
2366
|
/** 显式配置的上下文窗口大小(token 数),未设置时为 undefined(走自动检测) */
|
|
2283
2367
|
_contextWindow;
|
|
2284
2368
|
/** 压缩触发阈值比例(默认 0.8) */
|
|
@@ -2417,11 +2501,12 @@ ${notice}` : text,
|
|
|
2417
2501
|
};
|
|
2418
2502
|
}
|
|
2419
2503
|
/** 排队 steering 消息(下一迭代间隙注入为 user 消息) */
|
|
2420
|
-
queueSteering(text, attachments, attachmentRefs) {
|
|
2504
|
+
queueSteering(text, attachments, attachmentRefs, actor) {
|
|
2421
2505
|
this._steering.push({
|
|
2422
2506
|
text,
|
|
2423
2507
|
...attachments?.length ? { attachments } : {},
|
|
2424
|
-
...attachmentRefs?.length ? { attachmentRefs } : {}
|
|
2508
|
+
...attachmentRefs?.length ? { attachmentRefs } : {},
|
|
2509
|
+
...actor ? { actor } : {}
|
|
2425
2510
|
});
|
|
2426
2511
|
}
|
|
2427
2512
|
/**
|
|
@@ -2446,7 +2531,7 @@ ${notice}` : text,
|
|
|
2446
2531
|
* 追加用户输入到历史,产出 TURN_START 事件,然后转发 _loop()
|
|
2447
2532
|
* 的全部事件。收到中断后仍会消费完剩余事件(保证 TURN_END 产出)。
|
|
2448
2533
|
*/
|
|
2449
|
-
async *run(userInput, taskId, attachments, attachmentRefs) {
|
|
2534
|
+
async *run(userInput, taskId, attachments, attachmentRefs, actor) {
|
|
2450
2535
|
if (!this.model.trim()) {
|
|
2451
2536
|
throw new Error(
|
|
2452
2537
|
"\u672A\u6307\u5B9A\u6A21\u578B\uFF1A\u8BF7\u5148\u9009\u62E9\u6A21\u578B\uFF08CLI \u8FD0\u884C /connect\uFF1B\u63A7\u5236\u53F0\u5728\u300C\u8BBE\u7F6E \u2192 AI \u6A21\u578B\u300D\u4E2D\u6DFB\u52A0\u4F9B\u5E94\u5546\u5E76\u9009\u62E9\u6A21\u578B\uFF09"
|
|
@@ -2469,12 +2554,15 @@ ${notice}` : text,
|
|
|
2469
2554
|
this._cancel = false;
|
|
2470
2555
|
this._producedFiles = [];
|
|
2471
2556
|
this._compactStalledAt = -1;
|
|
2557
|
+
this._overflowElide = false;
|
|
2472
2558
|
this._emitHook((h) => h.onTurnStart?.(userInput));
|
|
2473
2559
|
yield {
|
|
2474
2560
|
type: "turn_start" /* TURN_START */,
|
|
2475
2561
|
data: {
|
|
2476
2562
|
taskId: this.taskId,
|
|
2477
2563
|
input: userInput,
|
|
2564
|
+
// 谁发起的本轮:会话详情据此标注(本地/旧网关没有该字段)
|
|
2565
|
+
...actor ? { actor } : {},
|
|
2478
2566
|
// 只报个数:附件字节不进事件流(事件会落盘,base64 会把日志撑爆)
|
|
2479
2567
|
...attachments?.length ? { attachmentCount: attachments.length } : {},
|
|
2480
2568
|
// 落盘引用足够小,随事件带给控制台渲染缩略图 / 详情回看
|
|
@@ -2778,6 +2866,12 @@ ${notice}` : text,
|
|
|
2778
2866
|
type: "compacting" /* COMPACTING */,
|
|
2779
2867
|
data: { taskId: this.taskId, ...startInfo }
|
|
2780
2868
|
};
|
|
2869
|
+
let elided = false;
|
|
2870
|
+
if (this._elisionEnabled) {
|
|
2871
|
+
const before = this._estimateContextTokens();
|
|
2872
|
+
this._overflowElide = true;
|
|
2873
|
+
elided = this._estimateContextTokens() < before;
|
|
2874
|
+
}
|
|
2781
2875
|
const result = await this._compactNow(overflowReqId, true);
|
|
2782
2876
|
if (result.notice) {
|
|
2783
2877
|
const notice = result.notice;
|
|
@@ -2816,6 +2910,11 @@ ${notice}` : text,
|
|
|
2816
2910
|
}
|
|
2817
2911
|
continue;
|
|
2818
2912
|
}
|
|
2913
|
+
if (elided) {
|
|
2914
|
+
this._appendNotice("compacted", "\u4E0A\u4E0B\u6587\u6EA2\u51FA \u2014 \u5DF2\u6DD8\u6C70\u65E7\u5DE5\u5177\u7ED3\u679C\u540E\u91CD\u8BD5");
|
|
2915
|
+
continue;
|
|
2916
|
+
}
|
|
2917
|
+
this._overflowElide = false;
|
|
2819
2918
|
}
|
|
2820
2919
|
if (!this._cancel && !streamed && isTransientNetworkError(exc) && netRetries < netMax) {
|
|
2821
2920
|
netRetries++;
|
|
@@ -2886,6 +2985,7 @@ ${notice}` : text,
|
|
|
2886
2985
|
return;
|
|
2887
2986
|
}
|
|
2888
2987
|
netRetries = 0;
|
|
2988
|
+
this._overflowElide = false;
|
|
2889
2989
|
if (this._cancel && turn === null) {
|
|
2890
2990
|
yield* this._finishInterrupted({
|
|
2891
2991
|
iterations,
|
|
@@ -2944,6 +3044,7 @@ ${notice}` : text,
|
|
|
2944
3044
|
data: {
|
|
2945
3045
|
text: s.text,
|
|
2946
3046
|
taskId: this.taskId,
|
|
3047
|
+
...s.actor ? { actor: s.actor } : {},
|
|
2947
3048
|
...s.attachmentRefs?.length ? { attachments: s.attachmentRefs } : {}
|
|
2948
3049
|
}
|
|
2949
3050
|
};
|
|
@@ -3008,6 +3109,7 @@ ${notice}` : text,
|
|
|
3008
3109
|
data: {
|
|
3009
3110
|
text: s.text,
|
|
3010
3111
|
taskId: this.taskId,
|
|
3112
|
+
...s.actor ? { actor: s.actor } : {},
|
|
3011
3113
|
...s.attachmentRefs?.length ? { attachments: s.attachmentRefs } : {}
|
|
3012
3114
|
}
|
|
3013
3115
|
};
|
|
@@ -3432,13 +3534,14 @@ ${notice}` : text,
|
|
|
3432
3534
|
const deduped = this._dedupEnabled ? applyReadFileDedup(base).messages : base;
|
|
3433
3535
|
let view = this._finalizeOutbound(deduped);
|
|
3434
3536
|
if (!this._elisionEnabled) return view;
|
|
3435
|
-
|
|
3537
|
+
const soft = this._softTriggerTokens();
|
|
3538
|
+
if (!this._overflowElide && estimateTokens(view) < soft) {
|
|
3436
3539
|
return view;
|
|
3437
3540
|
}
|
|
3438
3541
|
const oneShot = applyOneShotElision(deduped);
|
|
3439
3542
|
if (oneShot.freedChars > 0) {
|
|
3440
3543
|
view = this._finalizeOutbound(oneShot.messages);
|
|
3441
|
-
if (estimateTokens(view) <
|
|
3544
|
+
if (!this._overflowElide && estimateTokens(view) < soft) {
|
|
3442
3545
|
return view;
|
|
3443
3546
|
}
|
|
3444
3547
|
}
|
|
@@ -3447,7 +3550,8 @@ ${notice}` : text,
|
|
|
3447
3550
|
this._getContextWindow(),
|
|
3448
3551
|
this._thresholdPct,
|
|
3449
3552
|
this._capTokens
|
|
3450
|
-
)
|
|
3553
|
+
),
|
|
3554
|
+
this._overflowElide ? OVERFLOW_ELIDE_KEEP_FRACTION : ELIDE_KEEP_FRACTION
|
|
3451
3555
|
);
|
|
3452
3556
|
const elided = applyToolResultElision(
|
|
3453
3557
|
oneShot.messages,
|
|
@@ -3646,7 +3750,8 @@ ${notice}` : text,
|
|
|
3646
3750
|
const trimmed = trimState(
|
|
3647
3751
|
this.messages,
|
|
3648
3752
|
this.compactionState,
|
|
3649
|
-
force ? OVERFLOW_TRIM_FRACTION : 0.25
|
|
3753
|
+
force ? OVERFLOW_TRIM_FRACTION : 0.25,
|
|
3754
|
+
this.lang
|
|
3650
3755
|
);
|
|
3651
3756
|
if (!trimmed) break;
|
|
3652
3757
|
this.compactionState = trimmed;
|
|
@@ -3691,9 +3796,9 @@ ${notice}` : text,
|
|
|
3691
3796
|
return;
|
|
3692
3797
|
}
|
|
3693
3798
|
if (result && typeof result === "object") {
|
|
3694
|
-
const
|
|
3695
|
-
if (
|
|
3696
|
-
this._producedFiles.push(
|
|
3799
|
+
const path13 = result.path;
|
|
3800
|
+
if (path13) {
|
|
3801
|
+
this._producedFiles.push(path13);
|
|
3697
3802
|
return;
|
|
3698
3803
|
}
|
|
3699
3804
|
const changed = result.changed_files;
|
|
@@ -4232,62 +4337,196 @@ var PermissionEngine = class {
|
|
|
4232
4337
|
};
|
|
4233
4338
|
|
|
4234
4339
|
// src/tools/files.ts
|
|
4340
|
+
var fs6 = __toESM(require("fs"), 1);
|
|
4341
|
+
var path8 = __toESM(require("path"), 1);
|
|
4342
|
+
var import_node_crypto = require("crypto");
|
|
4343
|
+
var import_node_string_decoder = require("string_decoder");
|
|
4344
|
+
|
|
4345
|
+
// src/tools/ignore.ts
|
|
4235
4346
|
var fs5 = __toESM(require("fs"), 1);
|
|
4236
4347
|
var path7 = __toESM(require("path"), 1);
|
|
4348
|
+
var ALWAYS_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
4349
|
+
// JS / TS
|
|
4350
|
+
"node_modules",
|
|
4351
|
+
"dist",
|
|
4352
|
+
"build",
|
|
4353
|
+
"out",
|
|
4354
|
+
".next",
|
|
4355
|
+
".nuxt",
|
|
4356
|
+
".cache",
|
|
4357
|
+
// JVM
|
|
4358
|
+
"target",
|
|
4359
|
+
".gradle",
|
|
4360
|
+
".mvn",
|
|
4361
|
+
// .NET
|
|
4362
|
+
"bin",
|
|
4363
|
+
"obj",
|
|
4364
|
+
".vs",
|
|
4365
|
+
"TestResults",
|
|
4366
|
+
// Python / Ruby / PHP
|
|
4367
|
+
"__pycache__",
|
|
4368
|
+
".venv",
|
|
4369
|
+
"venv",
|
|
4370
|
+
".pytest_cache",
|
|
4371
|
+
".mypy_cache",
|
|
4372
|
+
"vendor",
|
|
4373
|
+
// 移动端
|
|
4374
|
+
"Pods",
|
|
4375
|
+
".dart_tool",
|
|
4376
|
+
"DerivedData",
|
|
4377
|
+
// 覆盖率 / 通用
|
|
4378
|
+
"coverage",
|
|
4379
|
+
// 版本库
|
|
4380
|
+
".git",
|
|
4381
|
+
".svn",
|
|
4382
|
+
".hg"
|
|
4383
|
+
]);
|
|
4384
|
+
function loadGitignore(dir) {
|
|
4385
|
+
const file = path7.join(dir, ".gitignore");
|
|
4386
|
+
let text;
|
|
4387
|
+
try {
|
|
4388
|
+
const stat = fs5.statSync(file);
|
|
4389
|
+
if (stat.size > 64 * 1024) return [];
|
|
4390
|
+
text = fs5.readFileSync(file, "utf-8");
|
|
4391
|
+
} catch {
|
|
4392
|
+
return [];
|
|
4393
|
+
}
|
|
4394
|
+
const matchers = [];
|
|
4395
|
+
for (const rawLine of text.split("\n")) {
|
|
4396
|
+
let line = rawLine.replace(/\r$/, "").trim();
|
|
4397
|
+
if (!line || line.startsWith("#")) continue;
|
|
4398
|
+
if (line.startsWith("!")) continue;
|
|
4399
|
+
const anchored = rawLine.trim().startsWith("/");
|
|
4400
|
+
const dirOnly = /\/\s*$/.test(rawLine.trim());
|
|
4401
|
+
line = line.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
4402
|
+
if (!line) continue;
|
|
4403
|
+
const pattern = line.split("").map((ch) => {
|
|
4404
|
+
if (ch === "*") return ".*";
|
|
4405
|
+
if (ch === "?") return ".";
|
|
4406
|
+
return ch.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
4407
|
+
}).join("");
|
|
4408
|
+
const re = new RegExp(line.includes("/") || anchored ? `^${pattern}$` : `(^|/)${pattern}$`);
|
|
4409
|
+
matchers.push((rel, isDir) => {
|
|
4410
|
+
if (dirOnly && !isDir) return false;
|
|
4411
|
+
return re.test(rel);
|
|
4412
|
+
});
|
|
4413
|
+
}
|
|
4414
|
+
return matchers;
|
|
4415
|
+
}
|
|
4416
|
+
function makeIgnoreFilter(root) {
|
|
4417
|
+
const matchers = loadGitignore(root);
|
|
4418
|
+
return (rel, isDir) => {
|
|
4419
|
+
const name = rel.slice(rel.lastIndexOf("/") + 1);
|
|
4420
|
+
if (name.startsWith(".")) return true;
|
|
4421
|
+
if (isDir && ALWAYS_SKIP_DIRS.has(name)) return true;
|
|
4422
|
+
return matchers.some((m) => m(rel, isDir));
|
|
4423
|
+
};
|
|
4424
|
+
}
|
|
4425
|
+
|
|
4426
|
+
// src/tools/files.ts
|
|
4237
4427
|
var DEFAULT_MAX_LINES = 2e3;
|
|
4238
4428
|
var MULTI_READ_MAX_TOTAL_LINES = 1500;
|
|
4239
4429
|
var MAX_LINE_CHARS = 500;
|
|
4430
|
+
var READ_CHUNK_BYTES = 64 * 1024;
|
|
4431
|
+
var RESULT_META_RESERVE = 800;
|
|
4240
4432
|
function makeReadFile(workspace, guard) {
|
|
4241
|
-
const root =
|
|
4242
|
-
function
|
|
4433
|
+
const root = path8.resolve(workspace);
|
|
4434
|
+
function readWindow(target, startLine, maxLines, charBudget, onDigest) {
|
|
4435
|
+
const fd = fs6.openSync(target, "r");
|
|
4436
|
+
try {
|
|
4437
|
+
const decoder = new import_node_string_decoder.StringDecoder("utf-8");
|
|
4438
|
+
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
4439
|
+
const buf = Buffer.allocUnsafe(READ_CHUNK_BYTES);
|
|
4440
|
+
const lines = [];
|
|
4441
|
+
let lineNo = 0;
|
|
4442
|
+
let pending = "";
|
|
4443
|
+
let chars = 0;
|
|
4444
|
+
let capped = false;
|
|
4445
|
+
let pos = 0;
|
|
4446
|
+
const takeLine = (text) => {
|
|
4447
|
+
lineNo += 1;
|
|
4448
|
+
if (capped || lineNo < startLine || lines.length >= maxLines) return;
|
|
4449
|
+
const clipped = text.length > MAX_LINE_CHARS ? text.slice(0, MAX_LINE_CHARS) + "\u2026 (line truncated)" : text;
|
|
4450
|
+
const rendered = `${lineNo}|${clipped}`;
|
|
4451
|
+
if (chars + rendered.length + 1 > charBudget) {
|
|
4452
|
+
capped = true;
|
|
4453
|
+
return;
|
|
4454
|
+
}
|
|
4455
|
+
chars += rendered.length + 1;
|
|
4456
|
+
lines.push(rendered);
|
|
4457
|
+
};
|
|
4458
|
+
for (; ; ) {
|
|
4459
|
+
const n = fs6.readSync(fd, buf, 0, READ_CHUNK_BYTES, pos);
|
|
4460
|
+
if (n <= 0) break;
|
|
4461
|
+
pos += n;
|
|
4462
|
+
const decoded = decoder.write(buf.subarray(0, n));
|
|
4463
|
+
hash.update(decoded, "utf8");
|
|
4464
|
+
const text = pending + decoded;
|
|
4465
|
+
let from = 0;
|
|
4466
|
+
for (; ; ) {
|
|
4467
|
+
const idx = text.indexOf("\n", from);
|
|
4468
|
+
if (idx < 0) break;
|
|
4469
|
+
takeLine(text.slice(from, idx).replace(/\r$/, ""));
|
|
4470
|
+
from = idx + 1;
|
|
4471
|
+
}
|
|
4472
|
+
pending = text.slice(from);
|
|
4473
|
+
}
|
|
4474
|
+
const rest = decoder.end();
|
|
4475
|
+
if (rest) hash.update(rest, "utf8");
|
|
4476
|
+
const tail = pending + rest;
|
|
4477
|
+
if (tail.length > 0) takeLine(tail.replace(/\r$/, ""));
|
|
4478
|
+
onDigest(hash.digest("hex").slice(0, 16));
|
|
4479
|
+
return { lines, totalLines: lineNo, capped };
|
|
4480
|
+
} finally {
|
|
4481
|
+
fs6.closeSync(fd);
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4484
|
+
function readOne(filePath, startLine, maxLines, charBudget) {
|
|
4243
4485
|
const resolved = resolveWithinRoot(root, filePath);
|
|
4244
4486
|
if (!resolved) {
|
|
4245
4487
|
return { path: filePath, error: "\u8DEF\u5F84\u5728\u5DE5\u4F5C\u533A\u4E4B\u5916" };
|
|
4246
4488
|
}
|
|
4247
4489
|
const target = resolved.real;
|
|
4248
|
-
if (!
|
|
4490
|
+
if (!fs6.existsSync(target) || !fs6.statSync(target).isFile()) {
|
|
4249
4491
|
return { path: filePath, error: `\u4E0D\u662F\u6587\u4EF6: ${filePath}` };
|
|
4250
4492
|
}
|
|
4251
|
-
|
|
4252
|
-
let total = 0;
|
|
4493
|
+
let read;
|
|
4253
4494
|
try {
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
total = lines.length;
|
|
4258
|
-
for (let i = startLine - 1; i < Math.min(startLine - 1 + maxLines, lines.length); i++) {
|
|
4259
|
-
let text = lines[i];
|
|
4260
|
-
if (text.length > MAX_LINE_CHARS) {
|
|
4261
|
-
text = text.slice(0, MAX_LINE_CHARS) + "\u2026 (line truncated)";
|
|
4262
|
-
}
|
|
4263
|
-
selected.push(`${i + 1}|${text}`);
|
|
4264
|
-
}
|
|
4495
|
+
read = readWindow(target, startLine, maxLines, charBudget, (digest) => {
|
|
4496
|
+
guard?.noteReadDigest(target, digest);
|
|
4497
|
+
});
|
|
4265
4498
|
} catch (exc) {
|
|
4266
4499
|
return { path: filePath, error: `\u8BFB\u53D6\u5931\u8D25: ${String(exc)}` };
|
|
4267
4500
|
}
|
|
4501
|
+
const { lines: selected, totalLines: total, capped } = read;
|
|
4268
4502
|
const end = startLine + selected.length - 1;
|
|
4269
4503
|
const result = {
|
|
4270
|
-
path:
|
|
4504
|
+
path: path8.relative(resolved.root, target),
|
|
4271
4505
|
start_line: startLine,
|
|
4272
4506
|
end_line: end,
|
|
4273
4507
|
total_lines: total,
|
|
4274
4508
|
content: selected.join("\n")
|
|
4275
4509
|
};
|
|
4276
|
-
if (
|
|
4510
|
+
if (capped) {
|
|
4511
|
+
result.note = `\u5DF2\u8FD4\u56DE\u7B2C ${startLine}-${end} \u884C\uFF08\u672C\u6B21\u5DF2\u8FBE\u5355\u6B21\u8BFB\u53D6\u4E0A\u9650\u7EA6 ${charBudget} \u5B57\u7B26\uFF0C\u5171 ${total} \u884C\uFF09\uFF1B\u8C03\u7528 read_file(start_line=${end + 1}) \u7EE7\u7EED\u9605\u8BFB`;
|
|
4512
|
+
} else if (end < total) {
|
|
4277
4513
|
result.note = `\u663E\u793A\u7B2C ${startLine}-${end} \u884C\uFF0C\u5171 ${total} \u884C\uFF1B\u8C03\u7528 read_file(start_line=${end + 1}) \u7EE7\u7EED\u9605\u8BFB`;
|
|
4278
4514
|
}
|
|
4279
4515
|
return result;
|
|
4280
4516
|
}
|
|
4281
4517
|
return function read_file(args) {
|
|
4282
4518
|
const startLine = Math.max(1, Number(args.start_line ?? 1));
|
|
4283
|
-
const
|
|
4519
|
+
const requestedLines = Number(args.max_lines ?? DEFAULT_MAX_LINES);
|
|
4520
|
+
const maxLines = Number.isFinite(requestedLines) ? Math.min(Math.max(1, Math.floor(requestedLines)), DEFAULT_MAX_LINES) : DEFAULT_MAX_LINES;
|
|
4521
|
+
const fullBudget = Math.max(1e3, toolResultBudget("read_file") - RESULT_META_RESERVE);
|
|
4284
4522
|
const paths = Array.isArray(args.paths) ? args.paths.map((p) => String(p ?? "")).filter(Boolean) : [];
|
|
4285
4523
|
if (paths.length > 0) {
|
|
4524
|
+
const perFileBudget = Math.max(1e3, Math.floor(fullBudget / paths.length));
|
|
4286
4525
|
const files = [];
|
|
4287
4526
|
let remainingLines = MULTI_READ_MAX_TOTAL_LINES;
|
|
4288
4527
|
for (const filePath2 of paths) {
|
|
4289
4528
|
const perFile = Math.min(maxLines, Math.max(1, remainingLines));
|
|
4290
|
-
const one = readOne(filePath2, startLine, perFile);
|
|
4529
|
+
const one = readOne(filePath2, startLine, perFile, perFileBudget);
|
|
4291
4530
|
files.push(one);
|
|
4292
4531
|
if (!one.error) remainingLines -= one.content.split("\n").length;
|
|
4293
4532
|
if (remainingLines <= 0) break;
|
|
@@ -4302,31 +4541,79 @@ function makeReadFile(workspace, guard) {
|
|
|
4302
4541
|
if (!filePath) {
|
|
4303
4542
|
return { error: "\u7F3A\u5C11 path\uFF08\u6216 paths\uFF09\u53C2\u6570" };
|
|
4304
4543
|
}
|
|
4305
|
-
return readOne(filePath, startLine, maxLines);
|
|
4544
|
+
return readOne(filePath, startLine, maxLines, fullBudget);
|
|
4306
4545
|
};
|
|
4307
4546
|
}
|
|
4547
|
+
var DEFAULT_LIST_DEPTH = 3;
|
|
4548
|
+
var MAX_LIST_DEPTH = 6;
|
|
4549
|
+
var DEFAULT_RECURSIVE_LIMIT = 400;
|
|
4550
|
+
var MAX_RECURSIVE_LIMIT = 1e3;
|
|
4308
4551
|
function makeListFiles(workspace) {
|
|
4309
|
-
const root =
|
|
4552
|
+
const root = path8.resolve(workspace);
|
|
4310
4553
|
return function list_files(args) {
|
|
4311
4554
|
const dirPath = String(args.path ?? ".");
|
|
4312
|
-
const
|
|
4555
|
+
const recursive = args.recursive === true;
|
|
4556
|
+
const requestedMax = Number(args.max_results ?? (recursive ? DEFAULT_RECURSIVE_LIMIT : 100));
|
|
4557
|
+
const hardCap = recursive ? MAX_RECURSIVE_LIMIT : 100;
|
|
4558
|
+
const maxResults = Number.isFinite(requestedMax) ? Math.max(1, Math.min(Math.floor(requestedMax), hardCap)) : hardCap;
|
|
4559
|
+
const requestedDepth = Number(args.max_depth ?? DEFAULT_LIST_DEPTH);
|
|
4560
|
+
const maxDepth = Number.isFinite(requestedDepth) ? Math.max(1, Math.min(Math.floor(requestedDepth), MAX_LIST_DEPTH)) : DEFAULT_LIST_DEPTH;
|
|
4313
4561
|
const resolved = resolveWithinRoot(root, dirPath);
|
|
4314
4562
|
if (!resolved) return { error: "\u8DEF\u5F84\u5728\u5DE5\u4F5C\u533A\u4E4B\u5916" };
|
|
4315
4563
|
const target = resolved.real;
|
|
4316
|
-
if (!
|
|
4564
|
+
if (!fs6.existsSync(target) || !fs6.statSync(target).isDirectory()) {
|
|
4317
4565
|
return { error: `\u4E0D\u662F\u76EE\u5F55: ${dirPath}` };
|
|
4318
4566
|
}
|
|
4567
|
+
const realRoot = resolved.root;
|
|
4568
|
+
const isIgnored = makeIgnoreFilter(realRoot);
|
|
4319
4569
|
try {
|
|
4320
|
-
|
|
4570
|
+
if (!recursive) {
|
|
4571
|
+
const results2 = [];
|
|
4572
|
+
for (const e of fs6.readdirSync(target, { withFileTypes: true })) {
|
|
4573
|
+
if (results2.length >= maxResults) break;
|
|
4574
|
+
const rel = path8.relative(realRoot, path8.join(target, e.name)).split(path8.sep).join("/");
|
|
4575
|
+
if (isIgnored(rel, e.isDirectory())) continue;
|
|
4576
|
+
results2.push(e.isDirectory() ? `${e.name}/` : e.name);
|
|
4577
|
+
}
|
|
4578
|
+
results2.sort();
|
|
4579
|
+
return { path: path8.relative(realRoot, target), entries: results2.slice(0, maxResults) };
|
|
4580
|
+
}
|
|
4321
4581
|
const results = [];
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4582
|
+
let truncated = false;
|
|
4583
|
+
const queue = [{ dir: target, depth: 1 }];
|
|
4584
|
+
while (queue.length > 0) {
|
|
4585
|
+
const { dir, depth } = queue.shift();
|
|
4586
|
+
let entries;
|
|
4587
|
+
try {
|
|
4588
|
+
entries = fs6.readdirSync(dir, { withFileTypes: true });
|
|
4589
|
+
} catch {
|
|
4590
|
+
continue;
|
|
4591
|
+
}
|
|
4592
|
+
entries.sort((a, b) => {
|
|
4593
|
+
if (a.isDirectory() !== b.isDirectory()) return a.isDirectory() ? -1 : 1;
|
|
4594
|
+
return a.name.localeCompare(b.name, "zh");
|
|
4595
|
+
});
|
|
4596
|
+
for (const e of entries) {
|
|
4597
|
+
if (results.length >= maxResults) {
|
|
4598
|
+
truncated = true;
|
|
4599
|
+
break;
|
|
4600
|
+
}
|
|
4601
|
+
const full = path8.join(dir, e.name);
|
|
4602
|
+
const rel = path8.relative(realRoot, full).split(path8.sep).join("/");
|
|
4603
|
+
const isDir = e.isDirectory();
|
|
4604
|
+
if (isIgnored(rel, isDir)) continue;
|
|
4605
|
+
results.push(isDir ? `${rel}/` : rel);
|
|
4606
|
+
if (isDir && depth < maxDepth) queue.push({ dir: full, depth: depth + 1 });
|
|
4607
|
+
}
|
|
4608
|
+
if (truncated) break;
|
|
4327
4609
|
}
|
|
4328
|
-
|
|
4329
|
-
|
|
4610
|
+
return {
|
|
4611
|
+
path: path8.relative(realRoot, target),
|
|
4612
|
+
entries: results,
|
|
4613
|
+
...truncated ? {
|
|
4614
|
+
note: `\u5DF2\u8FBE\u5230\u6761\u76EE\u4E0A\u9650 ${maxResults}\uFF0C\u7ED3\u679C\u88AB\u622A\u65AD\uFF1B\u8BF7\u7F29\u5C0F path \u5230\u5177\u4F53\u5B50\u76EE\u5F55\uFF0C\u6216\u964D\u4F4E max_depth\uFF08\u5F53\u524D ${maxDepth}\uFF09`
|
|
4615
|
+
} : {}
|
|
4616
|
+
};
|
|
4330
4617
|
} catch (exc) {
|
|
4331
4618
|
return { error: `\u5217\u51FA\u6587\u4EF6\u5931\u8D25: ${String(exc)}` };
|
|
4332
4619
|
}
|
|
@@ -4366,12 +4653,23 @@ function registerReadOnlyFileTools(registry, workspace, guard) {
|
|
|
4366
4653
|
type: "function",
|
|
4367
4654
|
function: {
|
|
4368
4655
|
name: "list_files",
|
|
4369
|
-
description: "\u5217\u51FA\u76EE\u5F55\u4E0B\u7684\u6587\u4EF6\u548C\u5B50\u76EE\u5F55\u3002\u8DF3\u8FC7\u9690\u85CF\
|
|
4656
|
+
description: "\u5217\u51FA\u76EE\u5F55\u4E0B\u7684\u6587\u4EF6\u548C\u5B50\u76EE\u5F55\u3002\u8DF3\u8FC7\u9690\u85CF\u9879\u3001\u5E38\u89C1\u6784\u5EFA\u4EA7\u7269\u76EE\u5F55\uFF0C\u5E76\u9075\u5B88\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55\u7684 .gitignore\u3002\u4E86\u89E3\u5927\u4ED3\u5E93\u7ED3\u6784\u65F6\u7528 recursive=true \u4E00\u6B21\u62FF\u5230\u6709\u9650\u6DF1\u5EA6\uFF08\u9ED8\u8BA4 3 \u5C42\uFF09\u7684\u6811\uFF0C\u6BD4\u9010\u5C42\u8C03\u7528\u7701\u5F88\u591A\u5F80\u8FD4\uFF1B\u6761\u76EE\u8FC7\u591A\u65F6\u4F1A\u622A\u65AD\u5E76\u63D0\u793A\u3002",
|
|
4370
4657
|
parameters: {
|
|
4371
4658
|
type: "object",
|
|
4372
4659
|
properties: {
|
|
4373
4660
|
path: { type: "string", description: "\u76EE\u5F55\u8DEF\u5F84 (\u76F8\u5BF9\u4E8E\u5DE5\u4F5C\u533A\uFF0C\u9ED8\u8BA4 '.')" },
|
|
4374
|
-
|
|
4661
|
+
recursive: {
|
|
4662
|
+
type: "boolean",
|
|
4663
|
+
description: "\u9012\u5F52\u5217\u51FA\u5B50\u76EE\u5F55\uFF08\u9ED8\u8BA4 false\uFF0C\u53EA\u5217\u4E00\u5C42\uFF09"
|
|
4664
|
+
},
|
|
4665
|
+
max_depth: {
|
|
4666
|
+
type: "integer",
|
|
4667
|
+
description: `\u9012\u5F52\u6DF1\u5EA6 (\u9ED8\u8BA4 ${DEFAULT_LIST_DEPTH}\uFF0C\u4E0A\u9650 ${MAX_LIST_DEPTH}\uFF1B\u4EC5 recursive \u65F6\u751F\u6548)`
|
|
4668
|
+
},
|
|
4669
|
+
max_results: {
|
|
4670
|
+
type: "integer",
|
|
4671
|
+
description: `\u6700\u5927\u7ED3\u679C\u6570\uFF08\u975E\u9012\u5F52\u9ED8\u8BA4 100 / \u4E0A\u9650 100\uFF1B\u9012\u5F52\u9ED8\u8BA4 ${DEFAULT_RECURSIVE_LIMIT} / \u4E0A\u9650 ${MAX_RECURSIVE_LIMIT}\uFF09`
|
|
4672
|
+
}
|
|
4375
4673
|
}
|
|
4376
4674
|
}
|
|
4377
4675
|
}
|
|
@@ -4539,10 +4837,10 @@ function execAsync(file, argv, opts = {}) {
|
|
|
4539
4837
|
}
|
|
4540
4838
|
|
|
4541
4839
|
// src/tools/shellRuntime.ts
|
|
4542
|
-
var
|
|
4840
|
+
var path9 = __toESM(require("path"), 1);
|
|
4543
4841
|
var WINDOWS_SUFFIXES = [".exe", ".cmd", ".bat", ".com", ""];
|
|
4544
4842
|
function pathApi(platform) {
|
|
4545
|
-
return platform === "win32" ?
|
|
4843
|
+
return platform === "win32" ? path9.win32 : path9.posix;
|
|
4546
4844
|
}
|
|
4547
4845
|
function joinPath(platform, ...parts) {
|
|
4548
4846
|
return pathApi(platform).join(...parts);
|
|
@@ -4755,8 +5053,8 @@ function decodeOutput(buf) {
|
|
|
4755
5053
|
var shellTasks = new ShellTaskManager();
|
|
4756
5054
|
|
|
4757
5055
|
// src/tools/nodeGrep.ts
|
|
4758
|
-
var
|
|
4759
|
-
var
|
|
5056
|
+
var fs7 = __toESM(require("fs"), 1);
|
|
5057
|
+
var path10 = __toESM(require("path"), 1);
|
|
4760
5058
|
var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
4761
5059
|
".git",
|
|
4762
5060
|
"node_modules",
|
|
@@ -4781,27 +5079,27 @@ function nodeGrep(opts) {
|
|
|
4781
5079
|
} catch (err) {
|
|
4782
5080
|
throw new Error(`\u65E0\u6548\u7684\u6B63\u5219\u8868\u8FBE\u5F0F: ${opts.pattern}\uFF08${String(err)}\uFF09`);
|
|
4783
5081
|
}
|
|
4784
|
-
const target =
|
|
4785
|
-
if (!
|
|
5082
|
+
const target = path10.resolve(opts.workspace, opts.target);
|
|
5083
|
+
if (!fs7.existsSync(target)) {
|
|
4786
5084
|
throw new Error(`\u641C\u7D22\u8DEF\u5F84\u4E0D\u5B58\u5728: ${opts.target}`);
|
|
4787
5085
|
}
|
|
4788
5086
|
const matches = [];
|
|
4789
5087
|
const scanFile = (file) => {
|
|
4790
5088
|
let stat2;
|
|
4791
5089
|
try {
|
|
4792
|
-
stat2 =
|
|
5090
|
+
stat2 = fs7.statSync(file);
|
|
4793
5091
|
} catch {
|
|
4794
5092
|
return false;
|
|
4795
5093
|
}
|
|
4796
5094
|
if (!stat2.isFile() || stat2.size > maxFileBytes) return false;
|
|
4797
5095
|
let buf;
|
|
4798
5096
|
try {
|
|
4799
|
-
buf =
|
|
5097
|
+
buf = fs7.readFileSync(file);
|
|
4800
5098
|
} catch {
|
|
4801
5099
|
return false;
|
|
4802
5100
|
}
|
|
4803
5101
|
if (looksBinary(buf)) return false;
|
|
4804
|
-
const rel =
|
|
5102
|
+
const rel = path10.relative(opts.workspace, file) || path10.basename(file);
|
|
4805
5103
|
const lines = buf.toString("utf-8").split("\n");
|
|
4806
5104
|
for (let i = 0; i < lines.length; i++) {
|
|
4807
5105
|
const raw = lines[i].replace(/\r$/, "");
|
|
@@ -4812,7 +5110,7 @@ function nodeGrep(opts) {
|
|
|
4812
5110
|
}
|
|
4813
5111
|
return false;
|
|
4814
5112
|
};
|
|
4815
|
-
const stat =
|
|
5113
|
+
const stat = fs7.statSync(target);
|
|
4816
5114
|
if (stat.isFile()) {
|
|
4817
5115
|
scanFile(target);
|
|
4818
5116
|
return matches;
|
|
@@ -4822,12 +5120,12 @@ function nodeGrep(opts) {
|
|
|
4822
5120
|
const dir = stack.pop();
|
|
4823
5121
|
let entries;
|
|
4824
5122
|
try {
|
|
4825
|
-
entries =
|
|
5123
|
+
entries = fs7.readdirSync(dir, { withFileTypes: true });
|
|
4826
5124
|
} catch {
|
|
4827
5125
|
continue;
|
|
4828
5126
|
}
|
|
4829
5127
|
for (const entry of entries) {
|
|
4830
|
-
const full =
|
|
5128
|
+
const full = path10.join(dir, entry.name);
|
|
4831
5129
|
if (entry.isDirectory()) {
|
|
4832
5130
|
if (!SKIP_DIRS.has(entry.name)) stack.push(full);
|
|
4833
5131
|
} else if (entry.isFile()) {
|
|
@@ -4839,22 +5137,22 @@ function nodeGrep(opts) {
|
|
|
4839
5137
|
}
|
|
4840
5138
|
|
|
4841
5139
|
// src/tools/ripgrep.ts
|
|
4842
|
-
var
|
|
5140
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
4843
5141
|
var os3 = __toESM(require("os"), 1);
|
|
4844
|
-
var
|
|
5142
|
+
var path11 = __toESM(require("path"), 1);
|
|
4845
5143
|
var import_node_module = require("module");
|
|
4846
5144
|
var cached;
|
|
4847
5145
|
function extractBundledRipgrep() {
|
|
4848
5146
|
try {
|
|
4849
|
-
const req = typeof require === "function" ? require : (0, import_node_module.createRequire)(
|
|
5147
|
+
const req = typeof require === "function" ? require : (0, import_node_module.createRequire)(path11.join(process.cwd(), "__zqagent__.js"));
|
|
4850
5148
|
const sea = req("node:sea");
|
|
4851
5149
|
if (!sea?.isSea?.() || typeof sea.getAsset !== "function") return null;
|
|
4852
5150
|
const asset = sea.getAsset("rg");
|
|
4853
5151
|
if (!asset) return null;
|
|
4854
|
-
const dir =
|
|
4855
|
-
const file =
|
|
4856
|
-
|
|
4857
|
-
|
|
5152
|
+
const dir = fs8.mkdtempSync(path11.join(os3.tmpdir(), "zqagent-rg-"));
|
|
5153
|
+
const file = path11.join(dir, process.platform === "win32" ? "rg.exe" : "rg");
|
|
5154
|
+
fs8.writeFileSync(file, Buffer.from(asset));
|
|
5155
|
+
fs8.chmodSync(file, 493);
|
|
4858
5156
|
return file;
|
|
4859
5157
|
} catch {
|
|
4860
5158
|
return null;
|
|
@@ -4863,7 +5161,7 @@ function extractBundledRipgrep() {
|
|
|
4863
5161
|
function resolveRipgrep() {
|
|
4864
5162
|
if (cached !== void 0) return cached;
|
|
4865
5163
|
const explicit = (process.env.ZQAGENT_RG ?? "").trim();
|
|
4866
|
-
if (explicit &&
|
|
5164
|
+
if (explicit && fs8.existsSync(explicit)) {
|
|
4867
5165
|
cached = explicit;
|
|
4868
5166
|
return cached;
|
|
4869
5167
|
}
|
|
@@ -4877,7 +5175,7 @@ function resolveRipgrep() {
|
|
|
4877
5175
|
env: process.env,
|
|
4878
5176
|
fileExists: (p) => {
|
|
4879
5177
|
try {
|
|
4880
|
-
return
|
|
5178
|
+
return fs8.statSync(p).isFile();
|
|
4881
5179
|
} catch {
|
|
4882
5180
|
return false;
|
|
4883
5181
|
}
|
|
@@ -4887,12 +5185,61 @@ function resolveRipgrep() {
|
|
|
4887
5185
|
}
|
|
4888
5186
|
|
|
4889
5187
|
// src/tools/search.ts
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
5188
|
+
var DEFAULT_MAX_RESULTS = 50;
|
|
5189
|
+
var MAX_RESULTS_CAP = 200;
|
|
5190
|
+
var MAX_TEXT_CHARS = 200;
|
|
5191
|
+
var RG_TIMEOUT_MS = 1e4;
|
|
5192
|
+
function parseRgOutput(result, limit) {
|
|
5193
|
+
const out = [];
|
|
5194
|
+
for (const raw of result.split("\n")) {
|
|
5195
|
+
if (out.length >= limit) break;
|
|
5196
|
+
const line = raw.replace(/\r$/, "");
|
|
5197
|
+
if (!line) continue;
|
|
5198
|
+
const m = /^(.+?)[:-](\d+)[:-](.*)$/.exec(line);
|
|
5199
|
+
if (!m) continue;
|
|
5200
|
+
out.push({
|
|
5201
|
+
file: m[1],
|
|
5202
|
+
line: Number(m[2]),
|
|
5203
|
+
text: m[3].trim().slice(0, MAX_TEXT_CHARS)
|
|
5204
|
+
});
|
|
5205
|
+
}
|
|
5206
|
+
return out;
|
|
5207
|
+
}
|
|
5208
|
+
function parseRgFiles(result, limit) {
|
|
5209
|
+
const files = [];
|
|
5210
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5211
|
+
for (const raw of result.split("\n")) {
|
|
5212
|
+
if (files.length >= limit) break;
|
|
5213
|
+
const f = raw.replace(/\r$/, "").trim();
|
|
5214
|
+
if (!f || seen.has(f)) continue;
|
|
5215
|
+
seen.add(f);
|
|
5216
|
+
files.push(f);
|
|
5217
|
+
}
|
|
5218
|
+
return files;
|
|
5219
|
+
}
|
|
5220
|
+
function rgArgs(opts) {
|
|
5221
|
+
const args = [];
|
|
5222
|
+
if (opts.filesOnly) {
|
|
5223
|
+
args.push("--files-with-matches");
|
|
5224
|
+
} else {
|
|
5225
|
+
args.push("--with-filename", "--line-number", "--no-heading");
|
|
5226
|
+
args.push("--max-count", String(Math.max(opts.maxResults, 1)));
|
|
5227
|
+
}
|
|
5228
|
+
if (opts.ignoreCase) args.push("--ignore-case");
|
|
5229
|
+
if (opts.glob) args.push("--glob", opts.glob);
|
|
5230
|
+
if (opts.contextLines > 0 && !opts.filesOnly) {
|
|
5231
|
+
args.push("--context", String(opts.contextLines));
|
|
5232
|
+
}
|
|
5233
|
+
args.push("--", opts.pattern, opts.path);
|
|
5234
|
+
return args;
|
|
5235
|
+
}
|
|
5236
|
+
function rgFailureHint(res) {
|
|
5237
|
+
if (res.timedOut) {
|
|
5238
|
+
return `\u641C\u7D22\u8D85\u65F6\uFF08${RG_TIMEOUT_MS / 1e3}s\uFF09\u3002\u5927\u4ED3\u5E93\u5168\u91CF\u641C\u7D22\u5F88\u5BB9\u6613\u8D85\u65F6\uFF1A\u8BF7\u7F29\u5C0F path \u5230\u5177\u4F53\u5B50\u76EE\u5F55\uFF0C\u6216\u7528 glob \u53C2\u6570\u9650\u5236\u6587\u4EF6\u7C7B\u578B\uFF08\u5982 "*.ts"\uFF09\u540E\u91CD\u8BD5`;
|
|
5239
|
+
}
|
|
5240
|
+
if (res.aborted) return "\u641C\u7D22\u5DF2\u4E2D\u65AD";
|
|
5241
|
+
const stderr = decodeOutput(res.stderr).trim().slice(0, 300);
|
|
5242
|
+
return `\u641C\u7D22\u5931\u8D25\uFF08rg \u9000\u51FA\u7801 ${String(res.status)}\uFF09${stderr ? `\uFF1A${stderr}` : ""}`;
|
|
4896
5243
|
}
|
|
4897
5244
|
function makeGrep(workspace) {
|
|
4898
5245
|
return async function grep(args) {
|
|
@@ -4901,37 +5248,50 @@ function makeGrep(workspace) {
|
|
|
4901
5248
|
if (!pattern.trim()) {
|
|
4902
5249
|
return { error: "\u641C\u7D22\u6A21\u5F0F\u4E0D\u80FD\u4E3A\u7A7A" };
|
|
4903
5250
|
}
|
|
5251
|
+
const filesOnly = args.files_only === true;
|
|
5252
|
+
const ignoreCase = args.ignore_case === true;
|
|
5253
|
+
const glob = typeof args.glob === "string" && args.glob.trim() ? args.glob.trim() : void 0;
|
|
5254
|
+
const contextLines = Math.max(
|
|
5255
|
+
0,
|
|
5256
|
+
Math.min(Number(args.context_lines ?? 0) || 0, 5)
|
|
5257
|
+
);
|
|
5258
|
+
const maxResults = Math.max(
|
|
5259
|
+
1,
|
|
5260
|
+
Math.min(Number(args.max_results ?? DEFAULT_MAX_RESULTS) || DEFAULT_MAX_RESULTS, MAX_RESULTS_CAP)
|
|
5261
|
+
);
|
|
4904
5262
|
const rg = resolveRipgrep();
|
|
4905
5263
|
if (rg) {
|
|
4906
5264
|
const res = await execAsync(
|
|
4907
5265
|
rg,
|
|
4908
|
-
|
|
4909
|
-
// --with-filename:单文件模式下 rg 默认不输出文件名前缀,会导致
|
|
4910
|
-
// "行号:内容" 被误当成 "文件:行号:内容" 解析而错位;显式要求带文件名。
|
|
4911
|
-
"--with-filename",
|
|
4912
|
-
"--line-number",
|
|
4913
|
-
"--no-heading",
|
|
4914
|
-
"--max-count",
|
|
4915
|
-
"50",
|
|
4916
|
-
pattern,
|
|
4917
|
-
filePath
|
|
4918
|
-
],
|
|
5266
|
+
rgArgs({ pattern, path: filePath, filesOnly, ignoreCase, glob, contextLines, maxResults }),
|
|
4919
5267
|
{
|
|
4920
5268
|
cwd: workspace,
|
|
4921
|
-
timeoutMs:
|
|
5269
|
+
timeoutMs: RG_TIMEOUT_MS,
|
|
4922
5270
|
maxBuffer: 1024 * 1024 * 2
|
|
4923
5271
|
}
|
|
4924
5272
|
);
|
|
4925
5273
|
if (res.status === 0) {
|
|
4926
|
-
const
|
|
4927
|
-
return { query: pattern, engine: "ripgrep",
|
|
5274
|
+
const out = decodeOutput(res.stdout);
|
|
5275
|
+
return filesOnly ? { query: pattern, engine: "ripgrep", files: parseRgFiles(out, maxResults) } : (() => {
|
|
5276
|
+
const matches = parseRgOutput(out, maxResults);
|
|
5277
|
+
return { query: pattern, engine: "ripgrep", matches, count: matches.length };
|
|
5278
|
+
})();
|
|
4928
5279
|
}
|
|
4929
5280
|
if (res.status === 1) {
|
|
4930
|
-
return { query: pattern, engine: "ripgrep", matches: [], count: 0 };
|
|
5281
|
+
return filesOnly ? { query: pattern, engine: "ripgrep", files: [], count: 0 } : { query: pattern, engine: "ripgrep", matches: [], count: 0 };
|
|
5282
|
+
}
|
|
5283
|
+
if (!res.error) {
|
|
5284
|
+
return { query: pattern, error: rgFailureHint(res) };
|
|
4931
5285
|
}
|
|
4932
5286
|
}
|
|
5287
|
+
if (filesOnly || glob || ignoreCase || contextLines > 0) {
|
|
5288
|
+
return {
|
|
5289
|
+
query: pattern,
|
|
5290
|
+
error: "\u5F53\u524D\u8282\u70B9\u672A\u5B89\u88C5 ripgrep\uFF0Cfiles_only / glob / ignore_case / context_lines \u9700\u8981 ripgrep \u624D\u80FD\u751F\u6548\uFF1B\u8BF7\u53BB\u6389\u8FD9\u4E9B\u53C2\u6570\u540E\u91CD\u8BD5\uFF0C\u6216\u5148\u5B89\u88C5 ripgrep"
|
|
5291
|
+
};
|
|
5292
|
+
}
|
|
4933
5293
|
try {
|
|
4934
|
-
const matches = nodeGrep({ pattern, target: filePath, workspace });
|
|
5294
|
+
const matches = nodeGrep({ pattern, target: filePath, workspace, maxMatches: maxResults });
|
|
4935
5295
|
return { query: pattern, engine: "node", matches, count: matches.length };
|
|
4936
5296
|
} catch (exc) {
|
|
4937
5297
|
return { error: `\u641C\u7D22\u5931\u8D25: ${String(exc instanceof Error ? exc.message : exc)}` };
|
|
@@ -4947,12 +5307,29 @@ function registerSearchTool(registry, workspace) {
|
|
|
4947
5307
|
type: "function",
|
|
4948
5308
|
function: {
|
|
4949
5309
|
name: "grep",
|
|
4950
|
-
description: "\u5728\u6587\u4EF6\u4E2D\u641C\u7D22\u6587\u672C\u6A21\u5F0F\uFF08\u652F\u6301\u5B8C\u6574 JS \u6B63\u5219\u8BED\u6CD5\uFF09\u3002\u8FD4\u56DE\u5339\u914D\u7684\u6587\u4EF6\u540D\u3001\u884C\u53F7\u548C\u5185\u5BB9\
|
|
5310
|
+
description: "\u5728\u6587\u4EF6\u4E2D\u641C\u7D22\u6587\u672C\u6A21\u5F0F\uFF08\u652F\u6301\u5B8C\u6574 JS \u6B63\u5219\u8BED\u6CD5\uFF09\u3002\u9ED8\u8BA4\u8FD4\u56DE\u5339\u914D\u7684\u6587\u4EF6\u540D\u3001\u884C\u53F7\u548C\u5185\u5BB9\uFF08\u6700\u591A 50 \u6761\uFF09\u3002\u5B9A\u4F4D\u4EE3\u7801\u4F4D\u7F6E\u65F6\u4F18\u5148\u7528 files_only=true \u53EA\u53D6\u6587\u4EF6\u5217\u8868\uFF08\u4F53\u79EF\u5C0F\u4E00\u4E2A\u6570\u91CF\u7EA7\uFF09\uFF0C\u518D\u7528 read_file \u7CBE\u51C6\u8BFB\u53D6\uFF1B\u5927\u4ED3\u5E93\u8BF7\u914D\u5408 path \u7F29\u5C0F\u8303\u56F4\u6216 glob \u9650\u5236\u6587\u4EF6\u7C7B\u578B\uFF0C\u907F\u514D\u5168\u91CF\u626B\u63CF\u8D85\u65F6\u3002",
|
|
4951
5311
|
parameters: {
|
|
4952
5312
|
type: "object",
|
|
4953
5313
|
properties: {
|
|
4954
5314
|
pattern: { type: "string", description: "\u641C\u7D22\u6A21\u5F0F (\u6587\u672C\u6216\u6B63\u5219\u8868\u8FBE\u5F0F)" },
|
|
4955
|
-
path: { type: "string", description: "\u641C\u7D22\u8DEF\u5F84 (\u6587\u4EF6\u6216\u76EE\u5F55\uFF0C\u9ED8\u8BA4 '.')" }
|
|
5315
|
+
path: { type: "string", description: "\u641C\u7D22\u8DEF\u5F84 (\u6587\u4EF6\u6216\u76EE\u5F55\uFF0C\u9ED8\u8BA4 '.'\uFF1B\u5927\u4ED3\u5E93\u5EFA\u8BAE\u5148\u7F29\u5C0F\u5230\u5B50\u76EE\u5F55)" },
|
|
5316
|
+
files_only: {
|
|
5317
|
+
type: "boolean",
|
|
5318
|
+
description: "\u53EA\u8FD4\u56DE\u5339\u914D\u7684\u6587\u4EF6\u8DEF\u5F84\uFF0C\u4E0D\u8FD4\u56DE\u884C\u5185\u5BB9\uFF08\u63A8\u8350\u7528\u4E8E\u5B9A\u4F4D\uFF0C\u663E\u8457\u8282\u7701\u4E0A\u4E0B\u6587\uFF09"
|
|
5319
|
+
},
|
|
5320
|
+
glob: {
|
|
5321
|
+
type: "string",
|
|
5322
|
+
description: '\u6587\u4EF6\u8FC7\u6EE4\uFF0C\u5982 "*.ts" \u6216 "!*.min.js"\uFF08\u53EF\u591A\u6B21\u6392\u9664\u9700\u81EA\u884C\u7EC4\u5408\u4E3A {a,b} \u5F62\u5F0F\uFF09'
|
|
5323
|
+
},
|
|
5324
|
+
ignore_case: { type: "boolean", description: "\u5FFD\u7565\u5927\u5C0F\u5199" },
|
|
5325
|
+
context_lines: {
|
|
5326
|
+
type: "integer",
|
|
5327
|
+
description: "\u6BCF\u6761\u547D\u4E2D\u9644\u5E26\u7684\u524D\u540E\u4E0A\u4E0B\u6587\u884C\u6570\uFF080-5\uFF0C\u9ED8\u8BA4 0\uFF09"
|
|
5328
|
+
},
|
|
5329
|
+
max_results: {
|
|
5330
|
+
type: "integer",
|
|
5331
|
+
description: `\u6700\u591A\u8FD4\u56DE\u6761\u6570\uFF08\u9ED8\u8BA4 ${DEFAULT_MAX_RESULTS}\uFF0C\u4E0A\u9650 ${MAX_RESULTS_CAP}\uFF09`
|
|
5332
|
+
}
|
|
4956
5333
|
},
|
|
4957
5334
|
required: ["pattern"]
|
|
4958
5335
|
}
|
|
@@ -4962,8 +5339,8 @@ function registerSearchTool(registry, workspace) {
|
|
|
4962
5339
|
}
|
|
4963
5340
|
|
|
4964
5341
|
// src/tools/git.ts
|
|
4965
|
-
var
|
|
4966
|
-
var
|
|
5342
|
+
var fs9 = __toESM(require("fs"), 1);
|
|
5343
|
+
var path12 = __toESM(require("path"), 1);
|
|
4967
5344
|
async function runGit(repoDir, args, timeout = 15e3) {
|
|
4968
5345
|
const res = await execAsync("git", ["-c", "core.quotepath=false", ...args], {
|
|
4969
5346
|
cwd: repoDir,
|
|
@@ -4980,9 +5357,9 @@ async function runGit(repoDir, args, timeout = 15e3) {
|
|
|
4980
5357
|
async function resolveRepoRoot(workspace, pathArg) {
|
|
4981
5358
|
let dir = workspace;
|
|
4982
5359
|
if (pathArg) {
|
|
4983
|
-
const abs =
|
|
5360
|
+
const abs = path12.resolve(workspace, pathArg);
|
|
4984
5361
|
try {
|
|
4985
|
-
dir =
|
|
5362
|
+
dir = fs9.statSync(abs).isDirectory() ? abs : path12.dirname(abs);
|
|
4986
5363
|
} catch {
|
|
4987
5364
|
dir = abs;
|
|
4988
5365
|
}
|
|
@@ -4995,22 +5372,22 @@ function repoDirArg(workspace, raw) {
|
|
|
4995
5372
|
if (typeof raw !== "string") return void 0;
|
|
4996
5373
|
const v = raw.trim();
|
|
4997
5374
|
if (!v) return void 0;
|
|
4998
|
-
const base =
|
|
4999
|
-
const abs =
|
|
5000
|
-
const rel =
|
|
5375
|
+
const base = path12.resolve(workspace);
|
|
5376
|
+
const abs = path12.resolve(base, v);
|
|
5377
|
+
const rel = path12.relative(base, abs);
|
|
5001
5378
|
if (!isInsideRelative(rel)) return void 0;
|
|
5002
5379
|
return abs;
|
|
5003
5380
|
}
|
|
5004
5381
|
function toPathspec(repoRoot, workspace, pathArg) {
|
|
5005
5382
|
if (!pathArg) return null;
|
|
5006
|
-
const abs =
|
|
5007
|
-
let rel =
|
|
5383
|
+
const abs = path12.resolve(workspace, pathArg);
|
|
5384
|
+
let rel = path12.relative(repoRoot, abs);
|
|
5008
5385
|
if (rel === "") return ".";
|
|
5009
5386
|
if (!isInsideRelative(rel)) {
|
|
5010
5387
|
try {
|
|
5011
|
-
const realRepo =
|
|
5012
|
-
const realAbs =
|
|
5013
|
-
const rel2 =
|
|
5388
|
+
const realRepo = fs9.realpathSync(repoRoot);
|
|
5389
|
+
const realAbs = fs9.realpathSync(abs);
|
|
5390
|
+
const rel2 = path12.relative(realRepo, realAbs);
|
|
5014
5391
|
if (rel2 === "") return ".";
|
|
5015
5392
|
if (isInsideRelative(rel2)) return rel2;
|
|
5016
5393
|
} catch {
|