dominds 1.28.0 → 1.28.1

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 (2) hide show
  1. package/dist/tools/txt.js +115 -70
  2. package/package.json +1 -1
package/dist/tools/txt.js CHANGED
@@ -14,11 +14,40 @@ const driver_messages_1 = require("../runtime/driver-messages");
14
14
  const work_language_1 = require("../runtime/work-language");
15
15
  const tool_1 = require("../tool");
16
16
  const output_limit_1 = require("./output-limit");
17
- function ok(result, messages) {
18
- return { status: 'completed', result: (0, tool_1.toolSuccess)(result), messages };
17
+ function limitTxtToolOutputContent(content, toolName) {
18
+ return (0, output_limit_1.truncateToolOutputText)(content, { toolName }).text;
19
19
  }
20
- function failed(result, messages) {
21
- return { status: 'failed', result: (0, tool_1.toolFailure)(result), messages };
20
+ function limitTxtToolMessages(messages, originalContent, limitedContent) {
21
+ if (messages === undefined || originalContent === limitedContent)
22
+ return messages;
23
+ return messages.map((message) => {
24
+ if ('content' in message && message.content === originalContent) {
25
+ return { ...message, content: limitedContent };
26
+ }
27
+ return message;
28
+ });
29
+ }
30
+ function limitedToolSuccess(content, toolName) {
31
+ return (0, tool_1.toolSuccess)(limitTxtToolOutputContent(content, toolName));
32
+ }
33
+ function limitedToolFailure(content, toolName) {
34
+ return (0, tool_1.toolFailure)(limitTxtToolOutputContent(content, toolName));
35
+ }
36
+ function ok(result, messages, toolName = 'ws_mod') {
37
+ const limitedResult = limitTxtToolOutputContent(result, toolName);
38
+ return {
39
+ status: 'completed',
40
+ result: (0, tool_1.toolSuccess)(limitedResult),
41
+ messages: limitTxtToolMessages(messages, result, limitedResult),
42
+ };
43
+ }
44
+ function failed(result, messages, toolName = 'ws_mod') {
45
+ const limitedResult = limitTxtToolOutputContent(result, toolName);
46
+ return {
47
+ status: 'failed',
48
+ result: (0, tool_1.toolFailure)(limitedResult),
49
+ messages: limitTxtToolMessages(messages, result, limitedResult),
50
+ };
22
51
  }
23
52
  function ensureInsideWorkspace(rel) {
24
53
  const cwd = (0, rtws_1.domindsRtwsRootAbs)();
@@ -554,11 +583,11 @@ exports.wsModPadReminderOwner = {
554
583
  };
555
584
  },
556
585
  };
557
- function okYaml(yaml) {
558
- return (0, tool_1.toolSuccess)(formatYamlCodeBlock(yaml));
586
+ function okYaml(yaml, toolName = 'ws_mod') {
587
+ return limitedToolSuccess(formatYamlCodeBlock(yaml), toolName);
559
588
  }
560
- function failYaml(yaml) {
561
- return (0, tool_1.toolFailure)(formatYamlCodeBlock(yaml));
589
+ function failYaml(yaml, toolName = 'ws_mod') {
590
+ return limitedToolFailure(formatYamlCodeBlock(yaml), toolName);
562
591
  }
563
592
  function splitFileTextToLines(fileText) {
564
593
  const parts = fileText.split('\n');
@@ -732,6 +761,17 @@ function yamlFlowNumberArray(values) {
732
761
  return '[]';
733
762
  return `[${values.join(', ')}]`;
734
763
  }
764
+ const OCCURRENCE_INDEX_PREVIEW_LIMIT = 200;
765
+ function pushOccurrenceIndexListYaml(lines, key, values) {
766
+ const shown = values.slice(0, OCCURRENCE_INDEX_PREVIEW_LIMIT);
767
+ lines.push(`${key}: ${yamlFlowNumberArray(shown)}`);
768
+ if (shown.length < values.length) {
769
+ lines.push(`${key}_truncated: true`, `${key}_shown_count: ${shown.length}`, `${key}_omitted_count: ${values.length - shown.length}`, `${key}_last: ${values[values.length - 1] ?? 0}`);
770
+ }
771
+ else {
772
+ lines.push(`${key}_truncated: false`);
773
+ }
774
+ }
735
775
  function findLiteralOccurrenceIndexes(text, needle) {
736
776
  const matches = [];
737
777
  let fromIndex = 0;
@@ -2382,6 +2422,7 @@ exports.fileRangeEditTool = {
2382
2422
  argsValidation: 'dominds',
2383
2423
  call: async (dlg, caller, args) => {
2384
2424
  const language = (0, work_language_1.getWorkLanguage)();
2425
+ const mode = 'file_range_edit';
2385
2426
  try {
2386
2427
  const filePath = requireNonEmptyStringArg(args, 'path');
2387
2428
  const rangeSpec = requireNonEmptyStringArg(args, 'range');
@@ -2390,7 +2431,7 @@ exports.fileRangeEditTool = {
2390
2431
  const source = resolveFileRangeEditSource(dlg, args);
2391
2432
  const replacementText = fileRangeEditSourceText(source);
2392
2433
  if (!(0, access_control_1.hasWriteAccess)(caller, filePath)) {
2393
- return (0, tool_1.toolFailure)((0, access_control_1.getAccessDeniedMessage)('write', filePath, language));
2434
+ return limitedToolFailure((0, access_control_1.getAccessDeniedMessage)('write', filePath, language), mode);
2394
2435
  }
2395
2436
  const absPath = ensureInsideWorkspace(filePath);
2396
2437
  const absKey = path_1.default.resolve(absPath);
@@ -2410,7 +2451,7 @@ exports.fileRangeEditTool = {
2410
2451
  `path: ${yamlQuote(filePath)}`,
2411
2452
  `error: FILE_NOT_FOUND`,
2412
2453
  `summary: ${yamlQuote(language === 'zh' ? '文件不存在。' : 'File not found.')}`,
2413
- ].join('\n'));
2454
+ ].join('\n'), mode);
2414
2455
  }
2415
2456
  throw error;
2416
2457
  }
@@ -2421,7 +2462,7 @@ exports.fileRangeEditTool = {
2421
2462
  `path: ${yamlQuote(filePath)}`,
2422
2463
  `error: NOT_A_FILE`,
2423
2464
  `summary: ${yamlQuote(language === 'zh' ? '路径不是文件。' : 'Path is not a file.')}`,
2424
- ].join('\n'));
2465
+ ].join('\n'), mode);
2425
2466
  }
2426
2467
  const currentContent = fs_1.default.readFileSync(absPath, 'utf8');
2427
2468
  const currentLines = splitFileTextToLines(currentContent);
@@ -2434,7 +2475,7 @@ exports.fileRangeEditTool = {
2434
2475
  `range: ${yamlQuote(rangeSpec)}`,
2435
2476
  `error: INVALID_RANGE`,
2436
2477
  `summary: ${yamlQuote(parsed.error)}`,
2437
- ].join('\n'));
2478
+ ].join('\n'), mode);
2438
2479
  }
2439
2480
  const range = parsed.range;
2440
2481
  const startIndex0 = range.kind === 'append' ? rangeTotalLines(currentLines) : range.startLine - 1;
@@ -2473,10 +2514,10 @@ exports.fileRangeEditTool = {
2473
2514
  : `${preview ? 'Previewed' : 'Wrote'}: ${action} ${filePath}:${rangeSpec}; old=${deleteCount}, new=${replacementLines.length}.`)}`);
2474
2515
  const yaml = yamlLines.join('\n');
2475
2516
  if (!showDiff) {
2476
- return okYaml(yaml);
2517
+ return okYaml(yaml, mode);
2477
2518
  }
2478
2519
  const unifiedDiff = buildUnifiedSingleHunkDiff(filePath, currentLines, startIndex0, deleteCount, replacementLines);
2479
- return (0, tool_1.toolSuccess)(`${formatYamlCodeBlock(yaml)}\n\n\`\`\`diff\n${unifiedDiff}\`\`\``);
2520
+ return limitedToolSuccess(`${formatYamlCodeBlock(yaml)}\n\n\`\`\`diff\n${unifiedDiff}\`\`\``, mode);
2480
2521
  };
2481
2522
  return await new Promise((resolve) => {
2482
2523
  enqueueFileApply(absKey, {
@@ -2492,7 +2533,7 @@ exports.fileRangeEditTool = {
2492
2533
  `mode: file_range_edit`,
2493
2534
  `error: WRITE_FAILED`,
2494
2535
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
2495
- ].join('\n')));
2536
+ ].join('\n'), mode));
2496
2537
  }
2497
2538
  },
2498
2539
  });
@@ -2505,7 +2546,7 @@ exports.fileRangeEditTool = {
2505
2546
  `mode: file_range_edit`,
2506
2547
  `error: INVALID_ARGS`,
2507
2548
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
2508
- ].join('\n'));
2549
+ ].join('\n'), mode);
2509
2550
  }
2510
2551
  },
2511
2552
  };
@@ -2563,12 +2604,12 @@ exports.prepareOccurrenceReplaceTool = {
2563
2604
  `path: ${yamlQuote(filePath)}`,
2564
2605
  `error: INVALID_OCCURRENCE_INDEXES`,
2565
2606
  `summary: ${yamlQuote(selectedParsed.error)}`,
2566
- ].join('\n'));
2607
+ ].join('\n'), mode);
2567
2608
  }
2568
2609
  const source = resolveFileRangeEditSource(dlg, args);
2569
2610
  const replacementText = fileRangeEditSourceText(source);
2570
2611
  if (!(0, access_control_1.hasWriteAccess)(caller, filePath)) {
2571
- return (0, tool_1.toolFailure)((0, access_control_1.getAccessDeniedMessage)('write', filePath, language));
2612
+ return limitedToolFailure((0, access_control_1.getAccessDeniedMessage)('write', filePath, language), mode);
2572
2613
  }
2573
2614
  const absPath = ensureInsideWorkspace(filePath);
2574
2615
  if (!fs_1.default.existsSync(absPath)) {
@@ -2578,7 +2619,7 @@ exports.prepareOccurrenceReplaceTool = {
2578
2619
  `path: ${yamlQuote(filePath)}`,
2579
2620
  `error: FILE_NOT_FOUND`,
2580
2621
  `summary: ${yamlQuote(language === 'zh' ? '文件不存在。' : 'File not found.')}`,
2581
- ].join('\n'));
2622
+ ].join('\n'), mode);
2582
2623
  }
2583
2624
  if (!fs_1.default.statSync(absPath).isFile()) {
2584
2625
  return failYaml([
@@ -2587,7 +2628,7 @@ exports.prepareOccurrenceReplaceTool = {
2587
2628
  `path: ${yamlQuote(filePath)}`,
2588
2629
  `error: NOT_A_FILE`,
2589
2630
  `summary: ${yamlQuote(language === 'zh' ? '路径不是文件。' : 'Path is not a file.')}`,
2590
- ].join('\n'));
2631
+ ].join('\n'), mode);
2591
2632
  }
2592
2633
  const currentContent = fs_1.default.readFileSync(absPath, 'utf8');
2593
2634
  const occurrenceOffsets = findLiteralOccurrenceIndexes(currentContent, findText);
@@ -2601,7 +2642,7 @@ exports.prepareOccurrenceReplaceTool = {
2601
2642
  `summary: ${yamlQuote(language === 'zh'
2602
2643
  ? '没有找到要替换的 occurrence。'
2603
2644
  : 'No occurrence was found for the requested literal text.')}`,
2604
- ].join('\n'));
2645
+ ].join('\n'), mode);
2605
2646
  }
2606
2647
  const selectedOccurrences = selectedParsed.indexes ?? occurrenceOffsets.map((_offset, index0) => index0 + 1);
2607
2648
  const outOfRange = selectedOccurrences.find((index1) => index1 > totalOccurrences);
@@ -2615,7 +2656,7 @@ exports.prepareOccurrenceReplaceTool = {
2615
2656
  `summary: ${yamlQuote(language === 'zh'
2616
2657
  ? `occurrence_indexes 包含超范围值:${outOfRange}。`
2617
2658
  : `occurrence_indexes contains an out-of-range value: ${outOfRange}.`)}`,
2618
- ].join('\n'));
2659
+ ].join('\n'), mode);
2619
2660
  }
2620
2661
  const nextContent = replaceSelectedLiteralOccurrences(currentContent, occurrenceOffsets, selectedOccurrences, findText, replacementText);
2621
2662
  const currentLines = splitTextToLinesForEditing(currentContent);
@@ -2662,7 +2703,9 @@ exports.prepareOccurrenceReplaceTool = {
2662
2703
  `plan_id: ${yamlQuote(planId)}`,
2663
2704
  ];
2664
2705
  pushOccurrenceReplaceSourceYaml(yamlLines, plan.source, showDiff);
2665
- yamlLines.push(`expires_at_ms: ${plan.expiresAtMs}`, `find: ${yamlQuote(findText)}`, `occurrences_found: ${totalOccurrences}`, `selected_occurrences: ${yamlFlowNumberArray(selectedOccurrences)}`, `selected_count: ${selectedOccurrences.length}`, `file:`, ` old_total_lines: ${plan.oldTotalLines}`, ` old_total_bytes: ${plan.oldTotalBytes}`, ` old_hash: ${yamlQuote(plan.oldFileHash)}`, ` new_total_lines: ${plan.newTotalLines}`, ` new_total_bytes: ${plan.newTotalBytes}`, ` new_hash: ${yamlQuote(plan.newFileHash)}`, `match_preview: ${yamlBlockScalarLines(previewRows, ' ')}`, `next: ${yamlQuote(`apply_occurrence_replace({ "plan_id": "${planId}" })`)}`, `summary: ${yamlQuote(language === 'zh'
2706
+ yamlLines.push(`expires_at_ms: ${plan.expiresAtMs}`, `find: ${yamlQuote(findText)}`, `occurrences_found: ${totalOccurrences}`);
2707
+ pushOccurrenceIndexListYaml(yamlLines, 'selected_occurrences', selectedOccurrences);
2708
+ yamlLines.push(`selected_count: ${selectedOccurrences.length}`, `file:`, ` old_total_lines: ${plan.oldTotalLines}`, ` old_total_bytes: ${plan.oldTotalBytes}`, ` old_hash: ${yamlQuote(plan.oldFileHash)}`, ` new_total_lines: ${plan.newTotalLines}`, ` new_total_bytes: ${plan.newTotalBytes}`, ` new_hash: ${yamlQuote(plan.newFileHash)}`, `match_preview: ${yamlBlockScalarLines(previewRows, ' ')}`, `next: ${yamlQuote(`apply_occurrence_replace({ "plan_id": "${planId}" })`)}`, `summary: ${yamlQuote(language === 'zh'
2666
2709
  ? `已规划 ${selectedOccurrences.length}/${totalOccurrences} 个 occurrence 的替换;plan_id=${planId}.`
2667
2710
  : `Planned replacement for ${selectedOccurrences.length}/${totalOccurrences} occurrence(s); plan_id=${planId}.`)}`);
2668
2711
  if (selectedOccurrences.length < 2) {
@@ -2672,9 +2715,9 @@ exports.prepareOccurrenceReplaceTool = {
2672
2715
  }
2673
2716
  const yaml = yamlLines.join('\n');
2674
2717
  if (!showDiff)
2675
- return okYaml(yaml);
2718
+ return okYaml(yaml, mode);
2676
2719
  const diff = buildUnifiedSingleHunkDiff(filePath, currentLines, 0, currentLines.length, nextLines);
2677
- return (0, tool_1.toolSuccess)(`${formatYamlCodeBlock(yaml)}\n\n\`\`\`diff\n${diff}\`\`\``);
2720
+ return limitedToolSuccess(`${formatYamlCodeBlock(yaml)}\n\n\`\`\`diff\n${diff}\`\`\``, mode);
2678
2721
  }
2679
2722
  catch (error) {
2680
2723
  return failYaml([
@@ -2682,7 +2725,7 @@ exports.prepareOccurrenceReplaceTool = {
2682
2725
  `mode: ${mode}`,
2683
2726
  `error: INVALID_ARGS`,
2684
2727
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
2685
- ].join('\n'));
2728
+ ].join('\n'), mode);
2686
2729
  }
2687
2730
  },
2688
2731
  };
@@ -2720,7 +2763,7 @@ exports.applyOccurrenceReplaceTool = {
2720
2763
  `plan_id: ${yamlQuote(planId)}`,
2721
2764
  `error: INVALID_PLAN_ID`,
2722
2765
  `summary: ${yamlQuote('Invalid plan_id format.')}`,
2723
- ].join('\n'));
2766
+ ].join('\n'), mode);
2724
2767
  }
2725
2768
  pruneExpiredOccurrenceReplacePlans(Date.now());
2726
2769
  const plan = occurrenceReplacePlansById.get(planId);
@@ -2733,7 +2776,7 @@ exports.applyOccurrenceReplaceTool = {
2733
2776
  `summary: ${yamlQuote(language === 'zh'
2734
2777
  ? 'plan_id 不存在,可能已过期、已应用或进程已重启。请重新 prepare。'
2735
2778
  : 'plan_id was not found; it may have expired, been applied, or been lost after restart. Re-run prepare.')}`,
2736
- ].join('\n'));
2779
+ ].join('\n'), mode);
2737
2780
  }
2738
2781
  if (plan.plannedBy !== caller.id) {
2739
2782
  return failYaml([
@@ -2744,10 +2787,10 @@ exports.applyOccurrenceReplaceTool = {
2744
2787
  `summary: ${yamlQuote(language === 'zh'
2745
2788
  ? '该 plan 不是由当前成员创建,不能应用。'
2746
2789
  : 'This plan was created by a different member and cannot be applied by this caller.')}`,
2747
- ].join('\n'));
2790
+ ].join('\n'), mode);
2748
2791
  }
2749
2792
  if (!(0, access_control_1.hasWriteAccess)(caller, plan.relPath)) {
2750
- return (0, tool_1.toolFailure)((0, access_control_1.getAccessDeniedMessage)('write', plan.relPath, language));
2793
+ return limitedToolFailure((0, access_control_1.getAccessDeniedMessage)('write', plan.relPath, language), mode);
2751
2794
  }
2752
2795
  const res = await new Promise((resolve) => {
2753
2796
  enqueueFileApply(plan.absPath, {
@@ -2766,7 +2809,7 @@ exports.applyOccurrenceReplaceTool = {
2766
2809
  `summary: ${yamlQuote(language === 'zh'
2767
2810
  ? 'plan_id 不存在,可能已过期或已应用。请重新 prepare。'
2768
2811
  : 'plan_id was not found; it may have expired or been applied. Re-run prepare.')}`,
2769
- ].join('\n')));
2812
+ ].join('\n'), mode));
2770
2813
  return;
2771
2814
  }
2772
2815
  if (!fs_1.default.existsSync(currentPlan.absPath)) {
@@ -2777,7 +2820,7 @@ exports.applyOccurrenceReplaceTool = {
2777
2820
  `plan_id: ${yamlQuote(planId)}`,
2778
2821
  `error: FILE_NOT_FOUND`,
2779
2822
  `summary: ${yamlQuote(language === 'zh' ? '文件不存在。' : 'File not found.')}`,
2780
- ].join('\n')));
2823
+ ].join('\n'), mode));
2781
2824
  return;
2782
2825
  }
2783
2826
  if (!fs_1.default.statSync(currentPlan.absPath).isFile()) {
@@ -2788,7 +2831,7 @@ exports.applyOccurrenceReplaceTool = {
2788
2831
  `plan_id: ${yamlQuote(planId)}`,
2789
2832
  `error: NOT_A_FILE`,
2790
2833
  `summary: ${yamlQuote(language === 'zh' ? '路径不是文件。' : 'Path is not a file.')}`,
2791
- ].join('\n')));
2834
+ ].join('\n'), mode));
2792
2835
  return;
2793
2836
  }
2794
2837
  const currentContent = fs_1.default.readFileSync(currentPlan.absPath, 'utf8');
@@ -2805,7 +2848,7 @@ exports.applyOccurrenceReplaceTool = {
2805
2848
  `summary: ${yamlQuote(language === 'zh'
2806
2849
  ? '文件在 prepare 后发生变化,拒绝应用;请重新 prepare。'
2807
2850
  : 'File changed since prepare; refusing to apply. Re-run prepare.')}`,
2808
- ].join('\n')));
2851
+ ].join('\n'), mode));
2809
2852
  return;
2810
2853
  }
2811
2854
  const occurrenceOffsets = findLiteralOccurrenceIndexes(currentContent, currentPlan.findText);
@@ -2819,18 +2862,20 @@ exports.applyOccurrenceReplaceTool = {
2819
2862
  `plan_id: ${yamlQuote(planId)}`,
2820
2863
  ];
2821
2864
  pushOccurrenceReplaceSourceYaml(yamlLines, currentPlan.source, showDiff);
2822
- yamlLines.push(`find: ${yamlQuote(currentPlan.findText)}`, `selected_occurrences: ${yamlFlowNumberArray(currentPlan.selectedOccurrences)}`, `selected_count: ${currentPlan.selectedOccurrences.length}`, `file:`, ` old_total_lines: ${currentPlan.oldTotalLines}`, ` old_total_bytes: ${currentPlan.oldTotalBytes}`, ` old_hash: ${yamlQuote(currentPlan.oldFileHash)}`, ` new_total_lines: ${currentPlan.newTotalLines}`, ` new_total_bytes: ${currentPlan.newTotalBytes}`, ` new_hash: ${yamlQuote(currentPlan.newFileHash)}`, `summary: ${yamlQuote(language === 'zh'
2865
+ yamlLines.push(`find: ${yamlQuote(currentPlan.findText)}`);
2866
+ pushOccurrenceIndexListYaml(yamlLines, 'selected_occurrences', currentPlan.selectedOccurrences);
2867
+ yamlLines.push(`selected_count: ${currentPlan.selectedOccurrences.length}`, `file:`, ` old_total_lines: ${currentPlan.oldTotalLines}`, ` old_total_bytes: ${currentPlan.oldTotalBytes}`, ` old_hash: ${yamlQuote(currentPlan.oldFileHash)}`, ` new_total_lines: ${currentPlan.newTotalLines}`, ` new_total_bytes: ${currentPlan.newTotalBytes}`, ` new_hash: ${yamlQuote(currentPlan.newFileHash)}`, `summary: ${yamlQuote(language === 'zh'
2823
2868
  ? `已应用 ${currentPlan.selectedOccurrences.length} 个 occurrence 的替换。`
2824
2869
  : `Applied replacement for ${currentPlan.selectedOccurrences.length} occurrence(s).`)}`);
2825
2870
  const yaml = yamlLines.join('\n');
2826
2871
  if (!showDiff) {
2827
- resolve(okYaml(yaml));
2872
+ resolve(okYaml(yaml, mode));
2828
2873
  return;
2829
2874
  }
2830
2875
  const oldLines = splitTextToLinesForEditing(currentContent);
2831
2876
  const newLines = splitTextToLinesForEditing(nextContent);
2832
2877
  const diff = buildUnifiedSingleHunkDiff(currentPlan.relPath, oldLines, 0, oldLines.length, newLines);
2833
- resolve((0, tool_1.toolSuccess)(`${formatYamlCodeBlock(yaml)}\n\n\`\`\`diff\n${diff}\`\`\``));
2878
+ resolve(limitedToolSuccess(`${formatYamlCodeBlock(yaml)}\n\n\`\`\`diff\n${diff}\`\`\``, mode));
2834
2879
  }
2835
2880
  catch (error) {
2836
2881
  resolve(failYaml([
@@ -2839,7 +2884,7 @@ exports.applyOccurrenceReplaceTool = {
2839
2884
  `plan_id: ${yamlQuote(planId)}`,
2840
2885
  `error: FAILED`,
2841
2886
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
2842
- ].join('\n')));
2887
+ ].join('\n'), mode));
2843
2888
  }
2844
2889
  },
2845
2890
  });
@@ -2853,7 +2898,7 @@ exports.applyOccurrenceReplaceTool = {
2853
2898
  `mode: ${mode}`,
2854
2899
  `error: INVALID_ARGS`,
2855
2900
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
2856
- ].join('\n'));
2901
+ ].join('\n'), mode);
2857
2902
  }
2858
2903
  },
2859
2904
  };
@@ -3045,11 +3090,11 @@ async function runFileAppend(caller, filePath, source, options) {
3045
3090
  `error: PATH_REQUIRED`,
3046
3091
  `summary: ${yamlQuote(language === 'zh' ? '需要提供文件路径。' : 'File path is required.')}`,
3047
3092
  ].join('\n'));
3048
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3093
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3049
3094
  }
3050
3095
  if (!(0, access_control_1.hasWriteAccess)(caller, filePath)) {
3051
3096
  const content = (0, access_control_1.getAccessDeniedMessage)('write', filePath, language);
3052
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3097
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3053
3098
  }
3054
3099
  if (inputBody === '') {
3055
3100
  const content = formatYamlCodeBlock([
@@ -3059,7 +3104,7 @@ async function runFileAppend(caller, filePath, source, options) {
3059
3104
  `error: CONTENT_REQUIRED`,
3060
3105
  `summary: ${yamlQuote(language === 'zh' ? '正文不能为空(需要提供要追加的内容)。' : 'Content is required.')}`,
3061
3106
  ].join('\n'));
3062
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3107
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3063
3108
  }
3064
3109
  const create = options.create;
3065
3110
  const preview = options.preview;
@@ -3084,7 +3129,7 @@ async function runFileAppend(caller, filePath, source, options) {
3084
3129
  ? '文件不存在(create=false),无法追加。'
3085
3130
  : 'File does not exist (create=false); cannot append.')}`,
3086
3131
  ].join('\n'));
3087
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3132
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3088
3133
  return;
3089
3134
  }
3090
3135
  if (fileExists && !fs_1.default.statSync(fullPath).isFile()) {
@@ -3095,7 +3140,7 @@ async function runFileAppend(caller, filePath, source, options) {
3095
3140
  `error: NOT_A_FILE`,
3096
3141
  `summary: ${yamlQuote(language === 'zh' ? '路径不是文件。' : 'Path is not a file.')}`,
3097
3142
  ].join('\n'));
3098
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3143
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3099
3144
  return;
3100
3145
  }
3101
3146
  const existingContent = fileExists ? fs_1.default.readFileSync(fullPath, 'utf8') : '';
@@ -3160,7 +3205,7 @@ async function runFileAppend(caller, filePath, source, options) {
3160
3205
  const content = showDiff
3161
3206
  ? `${formatYamlCodeBlock(yaml)}\n\n\`\`\`diff\n${unifiedDiff}\`\`\``
3162
3207
  : formatYamlCodeBlock(yaml);
3163
- resolve(ok(content, [{ type: 'environment_msg', role: 'user', content }]));
3208
+ resolve(ok(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3164
3209
  }
3165
3210
  catch (error) {
3166
3211
  const content = formatYamlCodeBlock([
@@ -3170,7 +3215,7 @@ async function runFileAppend(caller, filePath, source, options) {
3170
3215
  `error: FAILED`,
3171
3216
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
3172
3217
  ].join('\n'));
3173
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3218
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3174
3219
  }
3175
3220
  },
3176
3221
  });
@@ -3186,7 +3231,7 @@ async function runFileAppend(caller, filePath, source, options) {
3186
3231
  `error: FAILED`,
3187
3232
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
3188
3233
  ].join('\n'));
3189
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3234
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3190
3235
  }
3191
3236
  }
3192
3237
  async function runFileInsertionCommon(position, caller, options) {
@@ -3209,11 +3254,11 @@ async function runFileInsertionCommon(position, caller, options) {
3209
3254
  ? `需要提供 path 与 anchor。请调用函数工具:${mode}({ path, anchor, content, ...options })`
3210
3255
  : `path and anchor are required. Call the function tool: ${mode}({ path, anchor, content, ...options })`)}`,
3211
3256
  ].join('\n'));
3212
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3257
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3213
3258
  }
3214
3259
  if (!(0, access_control_1.hasWriteAccess)(caller, filePath)) {
3215
3260
  const content = (0, access_control_1.getAccessDeniedMessage)('write', filePath, language);
3216
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3261
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3217
3262
  }
3218
3263
  if (inputBody === '') {
3219
3264
  const content = formatYamlCodeBlock([
@@ -3225,7 +3270,7 @@ async function runFileInsertionCommon(position, caller, options) {
3225
3270
  ? '正文不能为空(需要提供要插入的内容)。'
3226
3271
  : 'Content is required in the body.')}`,
3227
3272
  ].join('\n'));
3228
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3273
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3229
3274
  }
3230
3275
  try {
3231
3276
  const fullPath = ensureInsideWorkspace(filePath);
@@ -3244,7 +3289,7 @@ async function runFileInsertionCommon(position, caller, options) {
3244
3289
  `error: FILE_NOT_FOUND`,
3245
3290
  `summary: ${yamlQuote(language === 'zh' ? '文件不存在,无法插入。' : 'File does not exist.')}`,
3246
3291
  ].join('\n'));
3247
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3292
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3248
3293
  return;
3249
3294
  }
3250
3295
  if (!fs_1.default.statSync(fullPath).isFile()) {
@@ -3255,7 +3300,7 @@ async function runFileInsertionCommon(position, caller, options) {
3255
3300
  `error: NOT_A_FILE`,
3256
3301
  `summary: ${yamlQuote(language === 'zh' ? '路径不是文件。' : 'Path is not a file.')}`,
3257
3302
  ].join('\n'));
3258
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3303
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3259
3304
  return;
3260
3305
  }
3261
3306
  const existingContent = fs_1.default.readFileSync(fullPath, 'utf8');
@@ -3281,7 +3326,7 @@ async function runFileInsertionCommon(position, caller, options) {
3281
3326
  ? '锚点出现多次且未指定 occurrence;拒绝写入。请指定 occurrence 或改用 file_range_edit。'
3282
3327
  : 'Anchor appears multiple times and occurrence is not specified; refusing to write. Specify occurrence or use file_range_edit.')}`,
3283
3328
  ].join('\n'));
3284
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3329
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3285
3330
  return;
3286
3331
  }
3287
3332
  if (matchLines.length === 0) {
@@ -3295,7 +3340,7 @@ async function runFileInsertionCommon(position, caller, options) {
3295
3340
  ? '锚点未找到;请改用 file_range_edit 或选择更可靠的 anchor。'
3296
3341
  : 'Anchor not found; use file_range_edit or choose a different anchor.')}`,
3297
3342
  ].join('\n'));
3298
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3343
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3299
3344
  return;
3300
3345
  }
3301
3346
  const anchorIndex0 = occurrence.kind === 'last'
@@ -3311,7 +3356,7 @@ async function runFileInsertionCommon(position, caller, options) {
3311
3356
  `candidates_count: ${matchLines.length}`,
3312
3357
  `summary: ${yamlQuote(language === 'zh' ? 'occurrence 超出范围。' : 'Occurrence out of range.')}`,
3313
3358
  ].join('\n'));
3314
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3359
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3315
3360
  return;
3316
3361
  }
3317
3362
  const occurrenceResolved = matchLines.length === 1
@@ -3379,7 +3424,7 @@ async function runFileInsertionCommon(position, caller, options) {
3379
3424
  const content = showDiff
3380
3425
  ? `${formatYamlCodeBlock(yaml)}\n\n\`\`\`diff\n${unifiedDiff}\`\`\``
3381
3426
  : formatYamlCodeBlock(yaml);
3382
- resolve(ok(content, [{ type: 'environment_msg', role: 'user', content }]));
3427
+ resolve(ok(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3383
3428
  }
3384
3429
  catch (error) {
3385
3430
  const content = formatYamlCodeBlock([
@@ -3389,7 +3434,7 @@ async function runFileInsertionCommon(position, caller, options) {
3389
3434
  `error: FAILED`,
3390
3435
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
3391
3436
  ].join('\n'));
3392
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3437
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3393
3438
  }
3394
3439
  },
3395
3440
  });
@@ -3405,7 +3450,7 @@ async function runFileInsertionCommon(position, caller, options) {
3405
3450
  `error: FAILED`,
3406
3451
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
3407
3452
  ].join('\n'));
3408
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3453
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3409
3454
  }
3410
3455
  }
3411
3456
  exports.fileInsertAfterTool = {
@@ -3610,11 +3655,11 @@ async function runFileBlockReplace(caller, options) {
3610
3655
  ? '需要提供 path、start_anchor、end_anchor。'
3611
3656
  : 'path, start_anchor, and end_anchor are required.')}`,
3612
3657
  ].join('\n'));
3613
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3658
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3614
3659
  }
3615
3660
  if (!(0, access_control_1.hasWriteAccess)(caller, filePath)) {
3616
3661
  const content = (0, access_control_1.getAccessDeniedMessage)('write', filePath, language);
3617
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3662
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3618
3663
  }
3619
3664
  if (inputBody === '') {
3620
3665
  const content = formatYamlCodeBlock([
@@ -3626,7 +3671,7 @@ async function runFileBlockReplace(caller, options) {
3626
3671
  ? '正文不能为空(需要提供要写入块内的新内容)。'
3627
3672
  : 'Content is required in the body (new block content).')}`,
3628
3673
  ].join('\n'));
3629
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3674
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3630
3675
  }
3631
3676
  try {
3632
3677
  const fullPath = ensureInsideWorkspace(filePath);
@@ -3645,7 +3690,7 @@ async function runFileBlockReplace(caller, options) {
3645
3690
  `error: FILE_NOT_FOUND`,
3646
3691
  `summary: ${yamlQuote(language === 'zh' ? '文件不存在。' : 'File does not exist.')}`,
3647
3692
  ].join('\n'));
3648
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3693
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3649
3694
  return;
3650
3695
  }
3651
3696
  if (!fs_1.default.statSync(fullPath).isFile()) {
@@ -3656,7 +3701,7 @@ async function runFileBlockReplace(caller, options) {
3656
3701
  `error: NOT_A_FILE`,
3657
3702
  `summary: ${yamlQuote(language === 'zh' ? '路径不是文件。' : 'Path is not a file.')}`,
3658
3703
  ].join('\n'));
3659
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3704
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3660
3705
  return;
3661
3706
  }
3662
3707
  const existing = fs_1.default.readFileSync(fullPath, 'utf8');
@@ -3695,7 +3740,7 @@ async function runFileBlockReplace(caller, options) {
3695
3740
  ? '锚点未找到或无法配对。请改用 file_range_edit(行号范围精确编辑)。'
3696
3741
  : 'Anchors not found or not paired. Use file_range_edit (line-range precise edits).')}`,
3697
3742
  ].join('\n'));
3698
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3743
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3699
3744
  return;
3700
3745
  }
3701
3746
  if (!occurrenceSpecified && requireUnique && candidatesCount !== 1 && strict) {
@@ -3711,7 +3756,7 @@ async function runFileBlockReplace(caller, options) {
3711
3756
  ? `锚点歧义:存在 ${candidatesCount} 个候选块。请指定 occurrence=<n|last>,或改用 file_range_edit(行号范围)。`
3712
3757
  : `Ambiguous anchors: ${candidatesCount} candidate block(s). Specify occurrence=<n|last>, or use file_range_edit (line range).`)}`,
3713
3758
  ].join('\n'));
3714
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3759
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3715
3760
  return;
3716
3761
  }
3717
3762
  const selected = (() => {
@@ -3732,7 +3777,7 @@ async function runFileBlockReplace(caller, options) {
3732
3777
  `error: OCCURRENCE_OUT_OF_RANGE`,
3733
3778
  `summary: ${yamlQuote(language === 'zh' ? 'occurrence 超出范围。' : 'occurrence is out of range.')}`,
3734
3779
  ].join('\n'));
3735
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3780
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3736
3781
  return;
3737
3782
  }
3738
3783
  const nestedStart = startMatches.some((s) => s > selected.start0 && s < selected.end0);
@@ -3750,7 +3795,7 @@ async function runFileBlockReplace(caller, options) {
3750
3795
  ? '检测到嵌套/歧义锚点,拒绝写入。请先规范 anchors,或改用 file_range_edit(行号范围)。'
3751
3796
  : 'Nested/ambiguous anchors detected. Refusing to write; normalize anchors or use file_range_edit (line range).')}`,
3752
3797
  ].join('\n'));
3753
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3798
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3754
3799
  return;
3755
3800
  }
3756
3801
  const occurrenceResolved = candidatesCount === 1
@@ -3798,7 +3843,7 @@ async function runFileBlockReplace(caller, options) {
3798
3843
  const content = showDiff
3799
3844
  ? `${formatYamlCodeBlock(yaml)}\n\n\`\`\`diff\n${unifiedDiff}\`\`\``
3800
3845
  : formatYamlCodeBlock(yaml);
3801
- resolve(ok(content, [{ type: 'environment_msg', role: 'user', content }]));
3846
+ resolve(ok(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3802
3847
  }
3803
3848
  catch (error) {
3804
3849
  const content = formatYamlCodeBlock([
@@ -3808,7 +3853,7 @@ async function runFileBlockReplace(caller, options) {
3808
3853
  `error: FAILED`,
3809
3854
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
3810
3855
  ].join('\n'));
3811
- resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }]));
3856
+ resolve(failed(content, [{ type: 'environment_msg', role: 'user', content }], mode));
3812
3857
  }
3813
3858
  },
3814
3859
  });
@@ -3824,7 +3869,7 @@ async function runFileBlockReplace(caller, options) {
3824
3869
  `error: FAILED`,
3825
3870
  `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
3826
3871
  ].join('\n'));
3827
- return failed(content, [{ type: 'environment_msg', role: 'user', content }]);
3872
+ return failed(content, [{ type: 'environment_msg', role: 'user', content }], mode);
3828
3873
  }
3829
3874
  }
3830
3875
  exports.fileBlockReplaceTool = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dominds",
3
- "version": "1.28.0",
3
+ "version": "1.28.1",
4
4
  "description": "Dominds CLI and aggregation shell for the LongRun AI kernel/runtime packages.",
5
5
  "type": "commonjs",
6
6
  "publishConfig": {