snow-ai 0.8.8 → 0.8.10

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/bundle/cli.mjs CHANGED
@@ -1485,7 +1485,7 @@ var require_react_development = __commonJS({
1485
1485
  }
1486
1486
  return false;
1487
1487
  }
1488
- function memo11(type, compare) {
1488
+ function memo12(type, compare) {
1489
1489
  {
1490
1490
  if (!isValidElementType(type)) {
1491
1491
  error42("memo: The first argument must be a component. Instead received: %s", type === null ? "null" : typeof type);
@@ -1565,7 +1565,7 @@ var require_react_development = __commonJS({
1565
1565
  var dispatcher = resolveDispatcher();
1566
1566
  return dispatcher.useCallback(callback, deps);
1567
1567
  }
1568
- function useMemo52(create3, deps) {
1568
+ function useMemo53(create3, deps) {
1569
1569
  var dispatcher = resolveDispatcher();
1570
1570
  return dispatcher.useMemo(create3, deps);
1571
1571
  }
@@ -2325,7 +2325,7 @@ var require_react_development = __commonJS({
2325
2325
  exports2.forwardRef = forwardRef3;
2326
2326
  exports2.isValidElement = isValidElement3;
2327
2327
  exports2.lazy = lazy6;
2328
- exports2.memo = memo11;
2328
+ exports2.memo = memo12;
2329
2329
  exports2.startTransition = startTransition;
2330
2330
  exports2.unstable_act = act;
2331
2331
  exports2.useCallback = useCallback77;
@@ -2337,7 +2337,7 @@ var require_react_development = __commonJS({
2337
2337
  exports2.useImperativeHandle = useImperativeHandle2;
2338
2338
  exports2.useInsertionEffect = useInsertionEffect;
2339
2339
  exports2.useLayoutEffect = useLayoutEffect2;
2340
- exports2.useMemo = useMemo52;
2340
+ exports2.useMemo = useMemo53;
2341
2341
  exports2.useReducer = useReducer8;
2342
2342
  exports2.useRef = useRef36;
2343
2343
  exports2.useState = useState102;
@@ -46749,6 +46749,7 @@ var init_en = __esm({
46749
46749
  deeperSearchHint: "More directories not scanned \xB7 press \u2193 on the last item to search deeper",
46750
46750
  multiSelectHint: "Space toggle \xB7 Enter insert \xB7 select multiple files at once",
46751
46751
  multiSelectActiveHint: "{count} selected \xB7 Space toggle \xB7 Enter insert all",
46752
+ workspaceFilterHint: "Workspace: {filter} \xB7 searching in selected dir only",
46752
46753
  contentSearchHeader: "\u2261 Content Search",
46753
46754
  filesHeader: "\u2261 Files [{mode} \u2022 Ctrl+T]",
46754
46755
  treeMode: "Tree",
@@ -47082,6 +47083,7 @@ var init_en = __esm({
47082
47083
  commandMessage: "Command",
47083
47084
  discontinuedMessage: "\u2514\u2500 user discontinue",
47084
47085
  aiCompletionTimeMessage: "\u2514\u2500 AI finished at {time}",
47086
+ aiCompletionTimeWithDurationMessage: "\u2514\u2500 AI finished at {time} ({duration})",
47085
47087
  compressionSummaryAutoTitle: "Auto-compressed summary collapsed",
47086
47088
  compressionSummaryManualTitle: "Manual compressed summary collapsed",
47087
47089
  compressionSummaryStats: "{lines} lines \xB7 {chars} chars",
@@ -47314,6 +47316,7 @@ var init_en = __esm({
47314
47316
  modeLabel: "Creation Mode:",
47315
47317
  modeAi: "AI Generate (describe requirement)",
47316
47318
  modeManual: "Manual (create templates)",
47319
+ modeInstall: "Install from GitHub",
47317
47320
  requirementLabel: "Requirement:",
47318
47321
  requirementHint: "Describe what you want this Skill to do (content will follow this language)",
47319
47322
  requirementPlaceholder: "e.g., Generate a Skill for releasing npm packages...",
@@ -47562,7 +47565,7 @@ var init_en = __esm({
47562
47565
  emptyHint: "No background processes"
47563
47566
  },
47564
47567
  fileRollback: {
47565
- title: "File Rollback Confirmation",
47568
+ title: "Rollback Confirmation",
47566
47569
  description: "This checkpoint has",
47567
47570
  filesCount: "{count} file(s) will be rolled back",
47568
47571
  filesCountWithSelection: "{count} file(s) will be rolled back ({selected}/{total} selected)",
@@ -48974,6 +48977,7 @@ var init_zh = __esm({
48974
48977
  deeperSearchHint: "\u5C1A\u6709\u66F4\u6DF1\u76EE\u5F55\u672A\u626B\u63CF \xB7 \u5728\u672B\u9879\u6309 \u2193 \u7EE7\u7EED\u6DF1\u5165\u641C\u7D22",
48975
48978
  multiSelectHint: "\u7A7A\u683C \u52FE\u9009 \xB7 Enter \u4E00\u6B21\u63D2\u5165 \xB7 \u652F\u6301\u591A\u9009",
48976
48979
  multiSelectActiveHint: "\u5DF2\u52FE\u9009 {count} \u9879 \xB7 \u7A7A\u683C \u5207\u6362 \xB7 Enter \u4E00\u6B21\u63D2\u5165",
48980
+ workspaceFilterHint: "\u5DE5\u4F5C\u533A: {filter} \xB7 \u4EC5\u641C\u7D22\u6240\u9009\u76EE\u5F55",
48977
48981
  contentSearchHeader: "\u2261 \u5185\u5BB9\u641C\u7D22",
48978
48982
  filesHeader: "\u2261 \u6587\u4EF6 [{mode} \u2022 Ctrl+T]",
48979
48983
  treeMode: "\u6811\u5F62",
@@ -49307,6 +49311,7 @@ var init_zh = __esm({
49307
49311
  commandMessage: "\u547D\u4EE4",
49308
49312
  discontinuedMessage: "\u2514\u2500 \u7528\u6237\u4E2D\u65AD",
49309
49313
  aiCompletionTimeMessage: "\u2514\u2500 AI \u7ED3\u675F\u65F6\u95F4\uFF1A{time}",
49314
+ aiCompletionTimeWithDurationMessage: "\u2514\u2500 AI \u7ED3\u675F\u65F6\u95F4\uFF1A{time} (\u8017\u65F6 {duration})",
49310
49315
  compressionSummaryAutoTitle: "\u81EA\u52A8\u538B\u7F29\u6458\u8981\u5DF2\u6298\u53E0",
49311
49316
  compressionSummaryManualTitle: "\u624B\u52A8\u538B\u7F29\u6458\u8981\u5DF2\u6298\u53E0",
49312
49317
  compressionSummaryStats: "{lines} \u884C \xB7 {chars} \u5B57\u7B26",
@@ -49538,6 +49543,7 @@ var init_zh = __esm({
49538
49543
  modeLabel: "\u9009\u62E9\u521B\u5EFA\u65B9\u5F0F:",
49539
49544
  modeAi: "AI \u751F\u6210\uFF08\u8F93\u5165\u9700\u6C42\u5373\u53EF\uFF09",
49540
49545
  modeManual: "\u624B\u52A8\u521B\u5EFA\uFF08\u751F\u6210\u6A21\u677F\uFF09",
49546
+ modeInstall: "\u4ECE GitHub \u5B89\u88C5\u6280\u80FD",
49541
49547
  requirementLabel: "\u6280\u80FD\u9700\u6C42:",
49542
49548
  requirementHint: "\u7B80\u8981\u63CF\u8FF0\u4F60\u5E0C\u671B\u8BE5\u6280\u80FD\u5B8C\u6210\u4EC0\u4E48\uFF08\u751F\u6210\u5185\u5BB9\u5C06\u8DDF\u968F\u6B64\u8BED\u8A00\uFF09",
49543
49549
  requirementPlaceholder: "\u4F8B\u5982\uFF1A\u751F\u6210\u4E00\u4E2A\u7528\u4E8E\u53D1\u5E03 npm \u5305\u7684\u6280\u80FD\u2026",
@@ -49786,7 +49792,7 @@ var init_zh = __esm({
49786
49792
  emptyHint: "\u65E0\u540E\u53F0\u8FDB\u7A0B"
49787
49793
  },
49788
49794
  fileRollback: {
49789
- title: "\u6587\u4EF6\u56DE\u6EDA\u786E\u8BA4",
49795
+ title: "\u56DE\u6EDA\u786E\u8BA4",
49790
49796
  description: "\u6B64\u68C0\u67E5\u70B9\u5305\u542B",
49791
49797
  filesCount: "{count} \u4E2A\u6587\u4EF6\u5C06\u88AB\u56DE\u6EDA",
49792
49798
  filesCountWithSelection: "{count} \u4E2A\u6587\u4EF6\u5C06\u88AB\u56DE\u6EDA ({selected}/{total} \u5DF2\u9009\u62E9)",
@@ -51198,6 +51204,7 @@ var init_zh_TW = __esm({
51198
51204
  deeperSearchHint: "\u5C1A\u6709\u66F4\u6DF1\u76EE\u9304\u672A\u6383\u63CF \xB7 \u5728\u672B\u9805\u6309 \u2193 \u7E7C\u7E8C\u6DF1\u5165\u641C\u5C0B",
51199
51205
  multiSelectHint: "\u7A7A\u767D\u9375 \u52FE\u9078 \xB7 Enter \u4E00\u6B21\u63D2\u5165 \xB7 \u652F\u63F4\u591A\u9078",
51200
51206
  multiSelectActiveHint: "\u5DF2\u52FE\u9078 {count} \u9805 \xB7 \u7A7A\u767D\u9375 \u5207\u63DB \xB7 Enter \u4E00\u6B21\u63D2\u5165",
51207
+ workspaceFilterHint: "\u5DE5\u4F5C\u5340: {filter} \xB7 \u50C5\u641C\u5C0B\u6240\u9078\u76EE\u9304",
51201
51208
  contentSearchHeader: "\u2261 \u5167\u5BB9\u641C\u5C0B",
51202
51209
  filesHeader: "\u2261 \u6A94\u6848 [{mode} \u2022 Ctrl+T]",
51203
51210
  treeMode: "\u6A39\u72C0",
@@ -51531,6 +51538,7 @@ var init_zh_TW = __esm({
51531
51538
  commandMessage: "\u547D\u4EE4",
51532
51539
  discontinuedMessage: "\u2514\u2500 \u4F7F\u7528\u8005\u4E2D\u65B7",
51533
51540
  aiCompletionTimeMessage: "\u2514\u2500 AI \u7D50\u675F\u6642\u9593\uFF1A{time}",
51541
+ aiCompletionTimeWithDurationMessage: "\u2514\u2500 AI \u7D50\u675F\u6642\u9593\uFF1A{time} (\u8017\u6642 {duration})",
51534
51542
  compressionSummaryAutoTitle: "\u81EA\u52D5\u58D3\u7E2E\u6458\u8981\u5DF2\u647A\u758A",
51535
51543
  compressionSummaryManualTitle: "\u624B\u52D5\u58D3\u7E2E\u6458\u8981\u5DF2\u647A\u758A",
51536
51544
  compressionSummaryStats: "{lines} \u884C \xB7 {chars} \u5B57\u5143",
@@ -51762,6 +51770,7 @@ var init_zh_TW = __esm({
51762
51770
  modeLabel: "\u9078\u64C7\u5275\u5EFA\u65B9\u5F0F:",
51763
51771
  modeAi: "AI \u751F\u6210\uFF08\u8F38\u5165\u9700\u6C42\u5373\u53EF\uFF09",
51764
51772
  modeManual: "\u624B\u52D5\u5275\u5EFA\uFF08\u751F\u6210\u6A21\u677F\uFF09",
51773
+ modeInstall: "\u5F9E GitHub \u5B89\u88DD\u6280\u80FD",
51765
51774
  requirementLabel: "\u6280\u80FD\u9700\u6C42:",
51766
51775
  requirementHint: "\u7C21\u8981\u63CF\u8FF0\u4F60\u5E0C\u671B\u8A72\u6280\u80FD\u5B8C\u6210\u4EC0\u9EBC\uFF08\u751F\u6210\u5167\u5BB9\u5C07\u8DDF\u96A8\u6B64\u8A9E\u8A00\uFF09",
51767
51776
  requirementPlaceholder: "\u4F8B\u5982\uFF1A\u751F\u6210\u4E00\u500B\u7528\u65BC\u767C\u4F48 npm \u5957\u4EF6\u7684\u6280\u80FD\u2026",
@@ -52009,7 +52018,7 @@ var init_zh_TW = __esm({
52009
52018
  emptyHint: "\u7121\u80CC\u666F\u8655\u7406\u7A0B\u5E8F"
52010
52019
  },
52011
52020
  fileRollback: {
52012
- title: "\u6A94\u6848\u56DE\u6EFE\u78BA\u8A8D",
52021
+ title: "\u56DE\u6EFE\u78BA\u8A8D",
52013
52022
  description: "\u6B64\u6AA2\u67E5\u9EDE\u5305\u542B",
52014
52023
  filesCount: "{count} \u500B\u6A94\u6848\u5C07\u88AB\u56DE\u6EFE",
52015
52024
  filesCountWithSelection: "{count} \u500B\u6A94\u6848\u5C07\u88AB\u56DE\u6EFE ({selected}/{total} \u5DF2\u9078\u64C7)",
@@ -95688,7 +95697,7 @@ var require_import_in_the_middle = __commonJS({
95688
95697
  "node_modules/import-in-the-middle/index.js"(exports2, module2) {
95689
95698
  var path68 = __require("path");
95690
95699
  var moduleDetailsFromPath = require_module_details_from_path();
95691
- var { fileURLToPath: fileURLToPath7 } = __require("url");
95700
+ var { fileURLToPath: fileURLToPath8 } = __require("url");
95692
95701
  var { MessageChannel: MessageChannel2 } = __require("worker_threads");
95693
95702
  var { isBuiltin } = __require("module");
95694
95703
  if (!isBuiltin) {
@@ -95782,7 +95791,7 @@ var require_import_in_the_middle = __commonJS({
95782
95791
  const stackTraceLimit = Error.stackTraceLimit;
95783
95792
  Error.stackTraceLimit = 0;
95784
95793
  try {
95785
- filePath = fileURLToPath7(name);
95794
+ filePath = fileURLToPath8(name);
95786
95795
  name = filePath;
95787
95796
  } catch (e) {
95788
95797
  }
@@ -131276,9 +131285,9 @@ var init_logger = __esm({
131276
131285
  rotateLog(filePath) {
131277
131286
  const timestamp = Date.now();
131278
131287
  const ext = path10.extname(filePath);
131279
- const basename9 = path10.basename(filePath, ext);
131280
- const dirname13 = path10.dirname(filePath);
131281
- const rotatedPath = path10.join(dirname13, `${basename9}-${timestamp}${ext}`);
131288
+ const basename10 = path10.basename(filePath, ext);
131289
+ const dirname14 = path10.dirname(filePath);
131290
+ const rotatedPath = path10.join(dirname14, `${basename10}-${timestamp}${ext}`);
131282
131291
  fs9.renameSync(filePath, rotatedPath);
131283
131292
  }
131284
131293
  writeLog(level, message, meta) {
@@ -145763,7 +145772,7 @@ var require_snapshot_recorder = __commonJS({
145763
145772
  "node_modules/undici/lib/mock/snapshot-recorder.js"(exports2, module2) {
145764
145773
  "use strict";
145765
145774
  var { writeFile: writeFile6, readFile: readFile6, mkdir: mkdir6 } = __require("node:fs/promises");
145766
- var { dirname: dirname13, resolve: resolve15 } = __require("node:path");
145775
+ var { dirname: dirname14, resolve: resolve15 } = __require("node:path");
145767
145776
  var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
145768
145777
  var { InvalidArgumentError, UndiciError } = require_errors3();
145769
145778
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -145987,7 +145996,7 @@ var require_snapshot_recorder = __commonJS({
145987
145996
  throw new InvalidArgumentError("Snapshot path is required");
145988
145997
  }
145989
145998
  const resolvedPath = resolve15(path68);
145990
- await mkdir6(dirname13(resolvedPath), { recursive: true });
145999
+ await mkdir6(dirname14(resolvedPath), { recursive: true });
145991
146000
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
145992
146001
  hash,
145993
146002
  snapshot
@@ -157655,8 +157664,8 @@ function toGeminiImagePart(image2) {
157655
157664
  return {
157656
157665
  inlineData: {
157657
157666
  mimeType: dataUrlMatch[1] || image2.mimeType || "image/png",
157658
- data: image2.data
157659
- // 保留完整的 data URL
157667
+ data: dataUrlMatch[2]
157668
+ // 只保留纯 base64 数据
157660
157669
  }
157661
157670
  };
157662
157671
  }
@@ -157664,8 +157673,8 @@ function toGeminiImagePart(image2) {
157664
157673
  return {
157665
157674
  inlineData: {
157666
157675
  mimeType,
157667
- data: `data:${mimeType};base64,${data}`
157668
- // 补齐 data:
157676
+ data
157677
+ // base64 数据
157669
157678
  }
157670
157679
  };
157671
157680
  }
@@ -285588,7 +285597,7 @@ ${frame}`;
285588
285597
  let index = 0;
285589
285598
  let depth = 0;
285590
285599
  let value;
285591
- let memo11 = {};
285600
+ let memo12 = {};
285592
285601
  const advance = () => input2[index++];
285593
285602
  const push2 = (node) => {
285594
285603
  if (node.type === "text" && prev.type === "dot") {
@@ -295016,8 +295025,8 @@ ${fromBody}`;
295016
295025
  }
295017
295026
  exports22.endsWithSlashGlobStar = endsWithSlashGlobStar;
295018
295027
  function isAffectDepthOfReadingPattern(pattern) {
295019
- const basename9 = path68.basename(pattern);
295020
- return endsWithSlashGlobStar(pattern) || isStaticPattern(basename9);
295028
+ const basename10 = path68.basename(pattern);
295029
+ return endsWithSlashGlobStar(pattern) || isStaticPattern(basename10);
295021
295030
  }
295022
295031
  exports22.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
295023
295032
  function expandPatternsWithBraceExpansion(patterns) {
@@ -326583,13 +326592,13 @@ var init_after = __esm({
326583
326592
 
326584
326593
  // node_modules/underscore/modules/before.js
326585
326594
  function before(times2, func) {
326586
- var memo11;
326595
+ var memo12;
326587
326596
  return function() {
326588
326597
  if (--times2 > 0) {
326589
- memo11 = func.apply(this, arguments);
326598
+ memo12 = func.apply(this, arguments);
326590
326599
  }
326591
326600
  if (times2 <= 1) func = null;
326592
- return memo11;
326601
+ return memo12;
326593
326602
  };
326594
326603
  }
326595
326604
  var init_before = __esm({
@@ -326801,21 +326810,21 @@ var init_map = __esm({
326801
326810
 
326802
326811
  // node_modules/underscore/modules/_createReduce.js
326803
326812
  function createReduce(dir) {
326804
- var reducer2 = function(obj2, iteratee2, memo11, initial2) {
326813
+ var reducer2 = function(obj2, iteratee2, memo12, initial2) {
326805
326814
  var _keys = !isArrayLike_default(obj2) && keys(obj2), length = (_keys || obj2).length, index = dir > 0 ? 0 : length - 1;
326806
326815
  if (!initial2) {
326807
- memo11 = obj2[_keys ? _keys[index] : index];
326816
+ memo12 = obj2[_keys ? _keys[index] : index];
326808
326817
  index += dir;
326809
326818
  }
326810
326819
  for (; index >= 0 && index < length; index += dir) {
326811
326820
  var currentKey = _keys ? _keys[index] : index;
326812
- memo11 = iteratee2(memo11, obj2[currentKey], currentKey, obj2);
326821
+ memo12 = iteratee2(memo12, obj2[currentKey], currentKey, obj2);
326813
326822
  }
326814
- return memo11;
326823
+ return memo12;
326815
326824
  };
326816
- return function(obj2, iteratee2, memo11, context3) {
326825
+ return function(obj2, iteratee2, memo12, context3) {
326817
326826
  var initial2 = arguments.length >= 3;
326818
- return reducer2(obj2, optimizeCb(iteratee2, context3, 4), memo11, initial2);
326827
+ return reducer2(obj2, optimizeCb(iteratee2, context3, 4), memo12, initial2);
326819
326828
  };
326820
326829
  }
326821
326830
  var init_createReduce = __esm({
@@ -352643,7 +352652,7 @@ var require_files = __commonJS({
352643
352652
  var fs61 = __require("fs");
352644
352653
  var url2 = __require("url");
352645
352654
  var os30 = __require("os");
352646
- var dirname13 = __require("path").dirname;
352655
+ var dirname14 = __require("path").dirname;
352647
352656
  var resolvePath = __require("path").resolve;
352648
352657
  var isAbsolutePath = require_path_is_absolute();
352649
352658
  var promises2 = require_promises();
@@ -352658,7 +352667,7 @@ var require_files = __commonJS({
352658
352667
  }
352659
352668
  };
352660
352669
  }
352661
- var base = options3.relativeToFile ? dirname13(options3.relativeToFile) : null;
352670
+ var base = options3.relativeToFile ? dirname14(options3.relativeToFile) : null;
352662
352671
  function read2(uri, encoding) {
352663
352672
  return resolveUri(uri).then(function(path68) {
352664
352673
  return readFile6(path68, encoding).caught(function(error42) {
@@ -354342,9 +354351,9 @@ var require_rules2 = __commonJS({
354342
354351
  exports2.sequence = function() {
354343
354352
  var parsers = Array.prototype.slice.call(arguments, 0);
354344
354353
  var rule = function(input2) {
354345
- var result2 = _3.foldl(parsers, function(memo11, parser3) {
354346
- var result3 = memo11.result;
354347
- var hasCut = memo11.hasCut;
354354
+ var result2 = _3.foldl(parsers, function(memo12, parser3) {
354355
+ var result3 = memo12.result;
354356
+ var hasCut = memo12.hasCut;
354348
354357
  if (!result3.isSuccess()) {
354349
354358
  return { result: result3, hasCut };
354350
354359
  }
@@ -360580,8 +360589,8 @@ var require_xlsx = __commonJS({
360580
360589
  }
360581
360590
  return L.length - R.length;
360582
360591
  }
360583
- function dirname13(p) {
360584
- if (p.charAt(p.length - 1) == "/") return p.slice(0, -1).indexOf("/") === -1 ? p : dirname13(p.slice(0, -1));
360592
+ function dirname14(p) {
360593
+ if (p.charAt(p.length - 1) == "/") return p.slice(0, -1).indexOf("/") === -1 ? p : dirname14(p.slice(0, -1));
360585
360594
  var c = p.lastIndexOf("/");
360586
360595
  return c === -1 ? p : p.slice(0, c + 1);
360587
360596
  }
@@ -361002,7 +361011,7 @@ var require_xlsx = __commonJS({
361002
361011
  data.push([cfb.FullPaths[i2], cfb.FileIndex[i2]]);
361003
361012
  }
361004
361013
  for (i2 = 0; i2 < data.length; ++i2) {
361005
- var dad = dirname13(data[i2][0]);
361014
+ var dad = dirname14(data[i2][0]);
361006
361015
  s = fullPaths[dad];
361007
361016
  if (!s) {
361008
361017
  data.push([dad, {
@@ -361038,13 +361047,13 @@ var require_xlsx = __commonJS({
361038
361047
  elt.size = 0;
361039
361048
  elt.type = 5;
361040
361049
  } else if (nm.slice(-1) == "/") {
361041
- for (j = i2 + 1; j < data.length; ++j) if (dirname13(cfb.FullPaths[j]) == nm) break;
361050
+ for (j = i2 + 1; j < data.length; ++j) if (dirname14(cfb.FullPaths[j]) == nm) break;
361042
361051
  elt.C = j >= data.length ? -1 : j;
361043
- for (j = i2 + 1; j < data.length; ++j) if (dirname13(cfb.FullPaths[j]) == dirname13(nm)) break;
361052
+ for (j = i2 + 1; j < data.length; ++j) if (dirname14(cfb.FullPaths[j]) == dirname14(nm)) break;
361044
361053
  elt.R = j >= data.length ? -1 : j;
361045
361054
  elt.type = 1;
361046
361055
  } else {
361047
- if (dirname13(cfb.FullPaths[i2 + 1] || "") == dirname13(nm)) elt.R = i2 + 1;
361056
+ if (dirname14(cfb.FullPaths[i2 + 1] || "") == dirname14(nm)) elt.R = i2 + 1;
361048
361057
  elt.type = 2;
361049
361058
  }
361050
361059
  }
@@ -366916,7 +366925,7 @@ var require_xlsx = __commonJS({
366916
366925
  }
366917
366926
  prep_blob(d, 0);
366918
366927
  var ft = d.read_shift(1);
366919
- var memo11 = !!(ft & 136);
366928
+ var memo12 = !!(ft & 136);
366920
366929
  var vfp = false, l7 = false;
366921
366930
  switch (ft) {
366922
366931
  case 2:
@@ -366927,12 +366936,12 @@ var require_xlsx = __commonJS({
366927
366936
  // dBASE III
366928
366937
  case 48:
366929
366938
  vfp = true;
366930
- memo11 = true;
366939
+ memo12 = true;
366931
366940
  break;
366932
366941
  // VFP
366933
366942
  case 49:
366934
366943
  vfp = true;
366935
- memo11 = true;
366944
+ memo12 = true;
366936
366945
  break;
366937
366946
  // VFP with autoincrement
366938
366947
  // 0x43 dBASE IV SQL table files
@@ -367076,7 +367085,7 @@ var require_xlsx = __commonJS({
367076
367085
  }
367077
367086
  break;
367078
367087
  case "M":
367079
- if (!memo11) throw new Error("DBF Unexpected MEMO for type " + ft.toString(16));
367088
+ if (!memo12) throw new Error("DBF Unexpected MEMO for type " + ft.toString(16));
367080
367089
  out[R][C] = "##MEMO##" + (l7 ? parseInt(s.trim(), 10) : dd.read_shift(4));
367081
367090
  break;
367082
367091
  case "N":
@@ -422263,6 +422272,41 @@ ${exportList}`);
422263
422272
  * @throws Error if file creation fails
422264
422273
  */
422265
422274
  async createFile(filePath, content, createDirectories = true, overwrite = false) {
422275
+ if (Array.isArray(filePath)) {
422276
+ return await executeBatchOperation(filePath, (fileItem) => {
422277
+ if (typeof fileItem === "string") {
422278
+ if (content === void 0) {
422279
+ throw new Error("content is required when filePath is an array of strings");
422280
+ }
422281
+ return {
422282
+ path: fileItem,
422283
+ content,
422284
+ createDirectories,
422285
+ overwrite
422286
+ };
422287
+ }
422288
+ return {
422289
+ path: fileItem.path,
422290
+ content: fileItem.content,
422291
+ createDirectories: fileItem.createDirectories ?? createDirectories,
422292
+ overwrite: fileItem.overwrite ?? overwrite
422293
+ };
422294
+ }, (path68, fileContent, fileCreateDirs, fileOverwrite) => this.createFileSingle(path68, fileContent, fileCreateDirs, fileOverwrite), (path68, result2) => ({
422295
+ path: path68,
422296
+ content: result2.content
422297
+ }));
422298
+ }
422299
+ if (content === void 0 || content === null) {
422300
+ throw new Error("content is required for single file mode");
422301
+ }
422302
+ const singleResult = await this.createFileSingle(filePath, content, createDirectories, overwrite);
422303
+ return singleResult.message;
422304
+ }
422305
+ /**
422306
+ * Internal method: Create a single file
422307
+ * @private
422308
+ */
422309
+ async createFileSingle(filePath, content, createDirectories = true, overwrite = false) {
422266
422310
  try {
422267
422311
  const fullPath = this.resolvePath(filePath);
422268
422312
  let fileExisted = false;
@@ -422298,7 +422342,7 @@ ${exportList}`);
422298
422342
  }
422299
422343
  } catch {
422300
422344
  }
422301
- return message;
422345
+ return { message, filePath, content };
422302
422346
  } catch (error42) {
422303
422347
  throw new Error(`Failed to create file ${filePath}: ${error42 instanceof Error ? error42.message : "Unknown error"}`);
422304
422348
  }
@@ -422533,17 +422577,47 @@ ${exportList}`);
422533
422577
  },
422534
422578
  {
422535
422579
  name: "filesystem-create",
422536
- description: 'Create a new file with content. **PATH REQUIREMENT**: Use EXACT non-empty string path, never undefined/null/empty/placeholders like "path/to/file". Set `overwrite` to true to replace an existing file (original content is backed up for rollback). Automatically creates parent directories.',
422580
+ description: 'Create a new file with content. **PATH REQUIREMENT**: Use EXACT non-empty string path, never undefined/null/empty/placeholders like "path/to/file". Set `overwrite` to true to replace an existing file (original content is backed up for rollback). Automatically creates parent directories. **BATCH**: `filePath` may be a string (single file with top-level `content`), or an array of `{path, content, overwrite?, createDirectories?}` objects for batch creation.',
422537
422581
  inputSchema: {
422538
422582
  type: "object",
422539
422583
  properties: {
422540
422584
  filePath: {
422541
- type: "string",
422542
- description: "Path where the file should be created"
422585
+ oneOf: [
422586
+ {
422587
+ type: "string",
422588
+ description: "Path where the file should be created"
422589
+ },
422590
+ {
422591
+ type: "array",
422592
+ items: {
422593
+ type: "object",
422594
+ properties: {
422595
+ path: {
422596
+ type: "string",
422597
+ description: "Path where the file should be created"
422598
+ },
422599
+ content: {
422600
+ type: "string",
422601
+ description: "Content to write to the file"
422602
+ },
422603
+ overwrite: {
422604
+ type: "boolean",
422605
+ description: "Whether to overwrite the file if it already exists"
422606
+ },
422607
+ createDirectories: {
422608
+ type: "boolean",
422609
+ description: "Whether to create parent directories if they don't exist"
422610
+ }
422611
+ },
422612
+ required: ["path", "content"]
422613
+ },
422614
+ description: "Array of file configs for batch creation"
422615
+ }
422616
+ ]
422543
422617
  },
422544
422618
  content: {
422545
422619
  type: "string",
422546
- description: "Content to write to the file"
422620
+ description: "Content to write to the file (required for single file mode; ignored in batch mode where each item has its own content)"
422547
422621
  },
422548
422622
  overwrite: {
422549
422623
  type: "boolean",
@@ -422555,7 +422629,7 @@ ${exportList}`);
422555
422629
  default: true
422556
422630
  }
422557
422631
  },
422558
- required: ["filePath", "content", "overwrite"]
422632
+ required: ["filePath", "overwrite"]
422559
422633
  }
422560
422634
  },
422561
422635
  {
@@ -422680,12 +422754,7 @@ ${exportList}`);
422680
422754
  description: 'New content to write (for replace and insert_after). Pass empty string "" for delete. Do NOT include line numbers or hashes.'
422681
422755
  }
422682
422756
  },
422683
- required: [
422684
- "type",
422685
- "startAnchor",
422686
- "endAnchor",
422687
- "content"
422688
- ]
422757
+ required: ["type", "startAnchor", "endAnchor", "content"]
422689
422758
  },
422690
422759
  description: "Array of edit operations for this file"
422691
422760
  }
@@ -498155,10 +498224,10 @@ var require_tiktoken = __commonJS({
498155
498224
  imports["./tiktoken_bg.js"] = wasm;
498156
498225
  var path68 = __require("path");
498157
498226
  var fs61 = __require("fs");
498158
- var candidates = __dirname.split(path68.sep).reduce((memo11, _3, index, array2) => {
498227
+ var candidates = __dirname.split(path68.sep).reduce((memo12, _3, index, array2) => {
498159
498228
  const prefix = array2.slice(0, index + 1).join(path68.sep) + path68.sep;
498160
498229
  if (!prefix.includes("node_modules" + path68.sep)) {
498161
- memo11.unshift(
498230
+ memo12.unshift(
498162
498231
  path68.join(
498163
498232
  prefix,
498164
498233
  "node_modules",
@@ -498168,7 +498237,7 @@ var require_tiktoken = __commonJS({
498168
498237
  )
498169
498238
  );
498170
498239
  }
498171
- return memo11;
498240
+ return memo12;
498172
498241
  }, []);
498173
498242
  candidates.unshift(path68.join(__dirname, "./tiktoken_bg.wasm"));
498174
498243
  var bytes = null;
@@ -506595,7 +506664,8 @@ ${plan}`);
506595
506664
  // dist/utils/execution/agentChildProcess.js
506596
506665
  import { fork } from "node:child_process";
506597
506666
  import { existsSync as existsSync18 } from "node:fs";
506598
- import { resolve as resolve9 } from "node:path";
506667
+ import { basename as basename4, dirname as dirname7, resolve as resolve9 } from "node:path";
506668
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
506599
506669
  function buildChildPayloadWithConversationContext(payload) {
506600
506670
  const conversationContext = getConversationContext();
506601
506671
  if (!conversationContext) {
@@ -506604,14 +506674,20 @@ function buildChildPayloadWithConversationContext(payload) {
506604
506674
  return { ...payload, conversationContext };
506605
506675
  }
506606
506676
  function getCliEntryPath() {
506677
+ const moduleFile = fileURLToPath6(import.meta.url);
506678
+ const moduleDir = dirname7(moduleFile);
506679
+ const devEntry = resolve9(moduleDir, "..", "..", "cli.js");
506680
+ if (moduleFile.endsWith(".js") && existsSync18(devEntry)) {
506681
+ return devEntry;
506682
+ }
506683
+ const moduleBaseName = basename4(moduleFile);
506684
+ if ((moduleBaseName === "cli.mjs" || moduleBaseName === "cli.js") && existsSync18(moduleFile)) {
506685
+ return moduleFile;
506686
+ }
506607
506687
  const argvEntry = process.argv[1];
506608
506688
  if (argvEntry && existsSync18(argvEntry)) {
506609
506689
  return argvEntry;
506610
506690
  }
506611
- const fallback = resolve9(process.cwd(), "dist/cli.js");
506612
- if (existsSync18(fallback)) {
506613
- return fallback;
506614
- }
506615
506691
  throw new Error("Unable to locate Snow CLI entrypoint for child-process agent execution");
506616
506692
  }
506617
506693
  function safeSend(child, message) {
@@ -506760,7 +506836,7 @@ async function runAgentChildProcess(options3) {
506760
506836
  abortKillTimer = setTimeout(() => {
506761
506837
  if (!child.killed)
506762
506838
  child.kill("SIGTERM");
506763
- }, 1500);
506839
+ }, 5e3);
506764
506840
  };
506765
506841
  if ((_a20 = options3.abortSignal) == null ? void 0 : _a20.aborted) {
506766
506842
  abortChild();
@@ -506812,6 +506888,10 @@ async function runAgentChildProcess(options3) {
506812
506888
  if (settled)
506813
506889
  return;
506814
506890
  const aborted2 = (_a21 = options3.abortSignal) == null ? void 0 : _a21.aborted;
506891
+ if (aborted2 && options3.abortResult !== void 0) {
506892
+ finish(() => resolvePromise(options3.abortResult));
506893
+ return;
506894
+ }
506815
506895
  const details = stderr.trim() ? `
506816
506896
  Child stderr:
506817
506897
  ${stderr.trim()}` : "";
@@ -506861,7 +506941,11 @@ async function executeTeammateInChildProcess(memberId, memberName, prompt, workt
506861
506941
  addToAlwaysApproved: options3.addToAlwaysApproved,
506862
506942
  requestUserQuestion: options3.requestUserQuestion,
506863
506943
  messagePump: createTeammateMessagePump(instanceId),
506864
- abortErrorMessage: "Teammate execution aborted"
506944
+ abortErrorMessage: "Teammate execution aborted",
506945
+ abortResult: {
506946
+ success: true,
506947
+ result: ""
506948
+ }
506865
506949
  });
506866
506950
  }
506867
506951
  var init_agentChildProcess = __esm({
@@ -508638,7 +508722,7 @@ __export(teamTaskList_exports, {
508638
508722
  updateTaskStatus: () => updateTaskStatus
508639
508723
  });
508640
508724
  import { existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync11, renameSync } from "fs";
508641
- import { join as join21, dirname as dirname7 } from "path";
508725
+ import { join as join21, dirname as dirname8 } from "path";
508642
508726
  import { homedir as homedir11 } from "os";
508643
508727
  import { randomUUID as randomUUID6 } from "crypto";
508644
508728
  function getTaskListPath(teamName) {
@@ -508662,7 +508746,7 @@ function readTaskList(teamName) {
508662
508746
  }
508663
508747
  function writeTaskList(teamName, data) {
508664
508748
  const filePath = getTaskListPath(teamName);
508665
- ensureDir4(dirname7(filePath));
508749
+ ensureDir4(dirname8(filePath));
508666
508750
  const tmpPath = filePath + ".tmp." + process.pid;
508667
508751
  data.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
508668
508752
  writeFileSync11(tmpPath, JSON.stringify(data, null, 2));
@@ -509431,7 +509515,7 @@ function isFilesystemEditDiffData(value) {
509431
509515
  return typeof data["oldContent"] === "string" && typeof data["newContent"] === "string" || Array.isArray(data["batchResults"]);
509432
509516
  }
509433
509517
  function extractFilesystemEditDiffFromRawResult(toolName, toolResult) {
509434
- if (toolName !== "filesystem-edit" && toolName !== "filesystem-replaceedit") {
509518
+ if (toolName !== "filesystem-edit" && toolName !== "filesystem-replaceedit" && toolName !== "filesystem-create") {
509435
509519
  return void 0;
509436
509520
  }
509437
509521
  if (!toolResult || typeof toolResult !== "object") {
@@ -509473,7 +509557,7 @@ function extractFilesystemEditDiffFromRawResult(toolName, toolResult) {
509473
509557
  return void 0;
509474
509558
  }
509475
509559
  function extractFilesystemEditDiffDataForPersistence(toolName, content) {
509476
- if (toolName !== "filesystem-edit" && toolName !== "filesystem-replaceedit" || content.startsWith("Error:")) {
509560
+ if (toolName !== "filesystem-edit" && toolName !== "filesystem-replaceedit" && toolName !== "filesystem-create" || content.startsWith("Error:")) {
509477
509561
  return void 0;
509478
509562
  }
509479
509563
  try {
@@ -509846,59 +509930,10 @@ var init_subAgentMessageHandler = __esm({
509846
509930
  this.updateGlobalTokenCount();
509847
509931
  state.lastTokenFlushTime = now;
509848
509932
  }
509849
- emitStreamLine(lines, state, subAgentMessage, content, isThinking) {
509933
+ emitStreamLine(_lines, _state, _subAgentMessage, _content, _isThinking) {
509850
509934
  if (!this.streamingEnabled)
509851
509935
  return;
509852
- const isFirst = state.isFirstStreamLine;
509853
- const isFirstContent = !isThinking && !state.hasStartedContent;
509854
- if (isFirst)
509855
- state.isFirstStreamLine = false;
509856
- if (isFirstContent)
509857
- state.hasStartedContent = true;
509858
- state.hasEmittedStreamLine = true;
509859
- const msg = {
509860
- role: "assistant",
509861
- content,
509862
- streamingLine: true,
509863
- isThinkingLine: isThinking,
509864
- isFirstStreamLine: isFirst,
509865
- isFirstContentLine: isFirstContent,
509866
- subAgent: {
509867
- agentId: subAgentMessage.agentId,
509868
- agentName: subAgentMessage.agentName,
509869
- isComplete: false
509870
- },
509871
- subAgentInternal: true
509872
- };
509873
- const agentId = subAgentMessage.agentId;
509874
- if (this.activeDisplayAgentId === null) {
509875
- this.activeDisplayAgentId = agentId;
509876
- this.emitAgentTitle(lines, subAgentMessage);
509877
- lines.push(msg);
509878
- } else if (agentId === this.activeDisplayAgentId) {
509879
- lines.push(msg);
509880
- } else {
509881
- if (!this.displayQueue.includes(agentId)) {
509882
- this.displayQueue.push(agentId);
509883
- }
509884
- const buf = this.bufferedStreamLines.get(agentId) || [];
509885
- buf.push(msg);
509886
- this.bufferedStreamLines.set(agentId, buf);
509887
- }
509888
- }
509889
- emitAgentTitle(lines, subAgentMessage) {
509890
- const name = subAgentMessage.agentName;
509891
- lines.push({
509892
- role: "subagent",
509893
- content: `\x1B[36m\u2687 ${name}\x1B[0m`,
509894
- streaming: false,
509895
- subAgent: {
509896
- agentId: subAgentMessage.agentId,
509897
- agentName: name,
509898
- isComplete: false
509899
- },
509900
- subAgentInternal: true
509901
- });
509936
+ return;
509902
509937
  }
509903
509938
  /**
509904
509939
  * When the active display agent finishes, flush the next queued agent(s).
@@ -510081,17 +510116,7 @@ var init_subAgentMessageHandler = __esm({
510081
510116
  if (state.hasReceivedContentChunk || !this.streamingEnabled) {
510082
510117
  return prev;
510083
510118
  }
510084
- const newLines = [];
510085
- state.thinkingLineBuffer += incomingDelta;
510086
- const thinkLines = state.thinkingLineBuffer.split("\n");
510087
- for (let i = 0; i < thinkLines.length - 1; i++) {
510088
- const cleaned = this.cleanThinkingContent(thinkLines[i] ?? "");
510089
- if (cleaned || state.hasEmittedStreamLine) {
510090
- this.emitStreamLine(newLines, state, subAgentMessage, cleaned, true);
510091
- }
510092
- }
510093
- state.thinkingLineBuffer = thinkLines[thinkLines.length - 1] ?? "";
510094
- return newLines.length > 0 ? [...prev, ...newLines] : prev;
510119
+ return prev;
510095
510120
  }
510096
510121
  handleToolCallDelta(prev, subAgentMessage) {
510097
510122
  const state = this.getStreamState(subAgentMessage.agentId);
@@ -510430,7 +510455,7 @@ var init_subAgentMessageHandler = __esm({
510430
510455
  }
510431
510456
  let fileToolData;
510432
510457
  if (!isError2 && (msg.tool_name === "filesystem-create" || msg.tool_name === "filesystem-edit" || msg.tool_name === "filesystem-replaceedit")) {
510433
- if (msg.editDiffData && (typeof msg.editDiffData.oldContent === "string" || Array.isArray(msg.editDiffData.batchResults))) {
510458
+ if (msg.editDiffData && (typeof msg.editDiffData.oldContent === "string" || typeof msg.editDiffData.content === "string" || Array.isArray(msg.editDiffData.batchResults))) {
510434
510459
  fileToolData = {
510435
510460
  name: msg.tool_name,
510436
510461
  arguments: msg.editDiffData
@@ -510512,22 +510537,11 @@ var init_subAgentMessageHandler = __esm({
510512
510537
  if (this.shouldFlush(state, now)) {
510513
510538
  this.flushTokenCount(subAgentMessage.agentId, now);
510514
510539
  }
510515
- const isFirstContentChunk = !state.hasReceivedContentChunk;
510516
510540
  state.hasReceivedContentChunk = true;
510517
510541
  if (!this.streamingEnabled) {
510518
510542
  return prev;
510519
510543
  }
510520
- const newLines = [];
510521
- if (isFirstContentChunk) {
510522
- this.flushThinkingBuffer(state, newLines, subAgentMessage);
510523
- }
510524
- state.contentLineBuffer += incomingContent;
510525
- const contentLines = state.contentLineBuffer.split("\n");
510526
- for (let i = 0; i < contentLines.length - 1; i++) {
510527
- this.processContentLine(state, newLines, contentLines[i] ?? "", subAgentMessage);
510528
- }
510529
- state.contentLineBuffer = contentLines[contentLines.length - 1] ?? "";
510530
- return newLines.length > 0 ? [...prev, ...newLines] : prev;
510544
+ return prev;
510531
510545
  }
510532
510546
  handleDone(prev, subAgentMessage) {
510533
510547
  const state = this.getStreamState(subAgentMessage.agentId);
@@ -515122,7 +515136,7 @@ __export(skills_exports, {
515122
515136
  listAvailableSkills: () => listAvailableSkills,
515123
515137
  mcpTools: () => mcpTools11
515124
515138
  });
515125
- import { dirname as dirname8, join as join24, relative as relative7 } from "path";
515139
+ import { dirname as dirname9, join as join24, relative as relative7 } from "path";
515126
515140
  import { existsSync as existsSync25 } from "fs";
515127
515141
  import { readFile } from "fs/promises";
515128
515142
  import { homedir as homedir13 } from "os";
@@ -515197,7 +515211,7 @@ async function loadSkillsFromDirectory(skills, baseSkillsDir, location, source2
515197
515211
  continue;
515198
515212
  }
515199
515213
  const skillFile = join24(currentDir, entry.name);
515200
- const skillDir = dirname8(skillFile);
515214
+ const skillDir = dirname9(skillFile);
515201
515215
  const rawSkillId = relative7(baseSkillsDir, skillDir);
515202
515216
  const skillId = normalizeSkillId(rawSkillId);
515203
515217
  if (!skillId || skillId === ".") {
@@ -520605,6 +520619,10 @@ function stripFilesystemDiffPayload(result2) {
520605
520619
  const { oldContent: _oldContent, newContent: _newContent, completeOldContent: _completeOldContent, completeNewContent: _completeNewContent, replacedContent: _replacedContent, ...rest2 } = result2;
520606
520620
  return rest2;
520607
520621
  }
520622
+ if (result2.content !== void 0 && result2.message !== void 0) {
520623
+ const { content: _content, ...rest2 } = result2;
520624
+ return rest2;
520625
+ }
520608
520626
  if (Array.isArray(result2.results)) {
520609
520627
  return {
520610
520628
  ...result2,
@@ -520612,7 +520630,7 @@ function stripFilesystemDiffPayload(result2) {
520612
520630
  if (!item || typeof item !== "object") {
520613
520631
  return item;
520614
520632
  }
520615
- const { oldContent: _oldContent, newContent: _newContent, completeOldContent: _completeOldContent, completeNewContent: _completeNewContent, replacedContent: _replacedContent, ...rest2 } = item;
520633
+ const { oldContent: _oldContent, newContent: _newContent, completeOldContent: _completeOldContent, completeNewContent: _completeNewContent, replacedContent: _replacedContent, content: _content, ...rest2 } = item;
520616
520634
  return rest2;
520617
520635
  })
520618
520636
  };
@@ -520620,7 +520638,7 @@ function stripFilesystemDiffPayload(result2) {
520620
520638
  return result2;
520621
520639
  }
520622
520640
  function isFilesystemEditToolName(toolName) {
520623
- return toolName === "filesystem-edit" || toolName === "filesystem-replaceedit";
520641
+ return toolName === "filesystem-edit" || toolName === "filesystem-replaceedit" || toolName === "filesystem-create";
520624
520642
  }
520625
520643
  function isTokenLimitBypassToolName(toolName) {
520626
520644
  return toolName === "skill-execute";
@@ -521522,14 +521540,43 @@ AI Tip: Make sure to provide the 'filePath' parameter as a string.`);
521522
521540
  if (!args2.filePath) {
521523
521541
  throw new Error(`Missing required parameter 'filePath' for filesystem-create tool.
521524
521542
  Received args: ${JSON.stringify(args2, null, 2)}
521525
- AI Tip: Make sure to provide the 'filePath' parameter as a string.`);
521543
+ AI Tip: Make sure to provide the 'filePath' parameter as a string or array.`);
521526
521544
  }
521527
- if (args2.content === void 0 || args2.content === null) {
521528
- throw new Error(`Missing required parameter 'content' for filesystem-create tool.
521545
+ if (Array.isArray(args2.filePath)) {
521546
+ for (let i = 0; i < args2.filePath.length; i++) {
521547
+ const item = args2.filePath[i];
521548
+ if (!item || typeof item !== "object" || !item.path) {
521549
+ throw new Error(`Invalid item at index ${i} in filePath array for filesystem-create tool.
521550
+ Each item must be an object with 'path' and 'content' properties.
521551
+ Received args: ${JSON.stringify(args2, null, 2)}`);
521552
+ }
521553
+ if (item.content === void 0 || item.content === null) {
521554
+ throw new Error(`Missing 'content' in filePath[${i}] for filesystem-create tool.
521555
+ Received args: ${JSON.stringify(args2, null, 2)}`);
521556
+ }
521557
+ if (typeof item.content !== "string") {
521558
+ throw new Error(`Invalid type for 'content' in filePath[${i}] for filesystem-create tool. Expected string but received ${typeof item.content}.
521559
+ AI Tip: The 'content' field must be a string. If you need to write JSON, serialize it first using JSON.stringify().`);
521560
+ }
521561
+ }
521562
+ result2 = await filesystemService2.createFile(args2.filePath, void 0, args2.createDirectories, args2.overwrite);
521563
+ } else {
521564
+ if (typeof args2.filePath !== "string") {
521565
+ throw new Error(`Invalid type for parameter 'filePath' for filesystem-create tool. Expected string or array but received ${typeof args2.filePath}.
521566
+ Received args: ${JSON.stringify(args2, null, 2)}`);
521567
+ }
521568
+ if (args2.content === void 0 || args2.content === null) {
521569
+ throw new Error(`Missing required parameter 'content' for filesystem-create tool.
521529
521570
  Received args: ${JSON.stringify(args2, null, 2)}
521530
521571
  AI Tip: Make sure to provide the 'content' parameter as a string (can be empty string "").`);
521572
+ }
521573
+ if (typeof args2.content !== "string") {
521574
+ throw new Error(`Invalid type for parameter 'content' in filesystem-create tool. Expected string but received ${typeof args2.content}.
521575
+ Received args: ${JSON.stringify(args2, null, 2)}
521576
+ AI Tip: The 'content' parameter must be a string. If you need to write JSON, serialize it first using JSON.stringify(). For example: content: JSON.stringify({ ... }) instead of content: { ... }.`);
521577
+ }
521578
+ result2 = await filesystemService2.createFile(args2.filePath, args2.content, args2.createDirectories, args2.overwrite);
521531
521579
  }
521532
- result2 = await filesystemService2.createFile(args2.filePath, args2.content, args2.createDirectories, args2.overwrite);
521533
521580
  break;
521534
521581
  case "edit":
521535
521582
  if (!args2.filePath) {
@@ -521542,12 +521589,27 @@ AI Tip: Make sure to provide the 'filePath' parameter as a string or array.`);
521542
521589
  Received args: ${JSON.stringify(args2, null, 2)}
521543
521590
  AI Tip: Provide an array of {type, startAnchor, endAnchor, content} operations (endAnchor required; same as startAnchor for single-line edits).`);
521544
521591
  }
521592
+ for (let i = 0; i < args2.operations.length; i++) {
521593
+ const op2 = args2.operations[i];
521594
+ if (op2 && op2.content !== void 0 && op2.content !== null && typeof op2.content !== "string") {
521595
+ throw new Error(`Invalid type for 'content' in operations[${i}] for filesystem-edit tool. Expected string but received ${typeof op2.content}.
521596
+ AI Tip: The 'content' field in each operation must be a string. If you need to write JSON, serialize it first using JSON.stringify().`);
521597
+ }
521598
+ }
521545
521599
  result2 = await filesystemService2.editFile(args2.filePath, args2.operations, args2.contextLines);
521546
521600
  break;
521547
521601
  case "replaceedit":
521548
521602
  if (!args2.filePath) {
521549
521603
  throw new Error(`Missing required parameter 'filePath' for filesystem-replaceedit tool.
521550
521604
  Received args: ${JSON.stringify(args2, null, 2)}`);
521605
+ }
521606
+ if (args2.searchContent !== void 0 && args2.searchContent !== null && typeof args2.searchContent !== "string") {
521607
+ throw new Error(`Invalid type for parameter 'searchContent' in filesystem-replaceedit tool. Expected string but received ${typeof args2.searchContent}.
521608
+ AI Tip: The 'searchContent' parameter must be a string. If you need to write JSON, serialize it first using JSON.stringify().`);
521609
+ }
521610
+ if (args2.replaceContent !== void 0 && args2.replaceContent !== null && typeof args2.replaceContent !== "string") {
521611
+ throw new Error(`Invalid type for parameter 'replaceContent' in filesystem-replaceedit tool. Expected string but received ${typeof args2.replaceContent}.
521612
+ AI Tip: The 'replaceContent' parameter must be a string. If you need to write JSON, serialize it first using JSON.stringify().`);
521551
521613
  }
521552
521614
  result2 = await filesystemService2.editFileBySearch(args2.filePath, args2.searchContent, args2.replaceContent, args2.occurrence ?? 1, args2.contextLines);
521553
521615
  break;
@@ -521876,7 +521938,13 @@ Received: ${JSON.stringify(args2.description)}`
521876
521938
  throw error42;
521877
521939
  }
521878
521940
  const { extractFilesystemEditDiffFromRawResult: extractFilesystemEditDiffFromRawResult2 } = await Promise.resolve().then(() => (init_toolDisplayConfig(), toolDisplayConfig_exports));
521879
- const preservedEditDiffData = extractFilesystemEditDiffFromRawResult2(toolName, result2);
521941
+ let preservedEditDiffData = extractFilesystemEditDiffFromRawResult2(toolName, result2);
521942
+ if (!preservedEditDiffData && toolName === "filesystem-create" && args2 && typeof args2.filePath === "string" && typeof args2.content === "string") {
521943
+ preservedEditDiffData = {
521944
+ content: args2.content,
521945
+ path: args2.filePath
521946
+ };
521947
+ }
521880
521948
  const { wrapToolResultWithTokenLimit: wrapToolResultWithTokenLimit2 } = await Promise.resolve().then(() => (init_tokenLimiter(), tokenLimiter_exports));
521881
521949
  result2 = await wrapToolResultWithTokenLimit2(result2, toolName);
521882
521950
  if (preservedEditDiffData) {
@@ -530317,6 +530385,13 @@ function restoreConversationContext(payload) {
530317
530385
  }
530318
530386
  setConversationContext(conversationContext.sessionId, conversationContext.messageIndex);
530319
530387
  }
530388
+ function ensureIdeConnection() {
530389
+ if (!ideConnectionReady) {
530390
+ ideConnectionReady = vscodeConnection.start().catch(() => {
530391
+ });
530392
+ }
530393
+ return ideConnectionReady;
530394
+ }
530320
530395
  function send(message) {
530321
530396
  if (process.send) {
530322
530397
  process.send(message);
@@ -530513,6 +530588,7 @@ async function runAgentChildProcessWorker() {
530513
530588
  installMessageInjectionHandlers();
530514
530589
  abortController = new AbortController();
530515
530590
  send({ type: "ready" });
530591
+ void ensureIdeConnection();
530516
530592
  await new Promise((resolve15) => {
530517
530593
  let started = false;
530518
530594
  process.on("message", (message) => {
@@ -530526,6 +530602,7 @@ async function runAgentChildProcessWorker() {
530526
530602
  void (async () => {
530527
530603
  try {
530528
530604
  const payload = message.payload;
530605
+ await ensureIdeConnection();
530529
530606
  const result2 = payload.kind === "subagent" ? await runSubAgentPayload(payload) : await runTeammatePayload(payload);
530530
530607
  await sendAndWaitForAck({ type: "result", result: result2 });
530531
530608
  } catch (error42) {
@@ -530541,7 +530618,7 @@ async function runAgentChildProcessWorker() {
530541
530618
  });
530542
530619
  });
530543
530620
  }
530544
- var pendingRequests, requestCounter2, abortController;
530621
+ var pendingRequests, requestCounter2, abortController, ideConnectionReady;
530545
530622
  var init_agentChildProcessWorker = __esm({
530546
530623
  "dist/utils/execution/agentChildProcessWorker.js"() {
530547
530624
  "use strict";
@@ -530550,6 +530627,7 @@ var init_agentChildProcessWorker = __esm({
530550
530627
  init_conversationContext();
530551
530628
  init_runningSubAgentTracker();
530552
530629
  init_teamTracker();
530630
+ init_vscodeConnection();
530553
530631
  pendingRequests = /* @__PURE__ */ new Map();
530554
530632
  requestCounter2 = 0;
530555
530633
  }
@@ -532478,10 +532556,10 @@ var init_esm5 = __esm({
532478
532556
  }
532479
532557
  async _formatEntry(dirent, path68) {
532480
532558
  let entry;
532481
- const basename9 = this._isDirent ? dirent.name : dirent;
532559
+ const basename10 = this._isDirent ? dirent.name : dirent;
532482
532560
  try {
532483
- const fullPath = presolve(pjoin(path68, basename9));
532484
- entry = { path: prelative(this._root, fullPath), fullPath, basename: basename9 };
532561
+ const fullPath = presolve(pjoin(path68, basename10));
532562
+ entry = { path: prelative(this._root, fullPath), fullPath, basename: basename10 };
532485
532563
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
532486
532564
  } catch (err) {
532487
532565
  this._onError(err);
@@ -533009,9 +533087,9 @@ var init_handler = __esm({
533009
533087
  _watchWithNodeFs(path68, listener) {
533010
533088
  const opts = this.fsw.options;
533011
533089
  const directory = sysPath.dirname(path68);
533012
- const basename9 = sysPath.basename(path68);
533090
+ const basename10 = sysPath.basename(path68);
533013
533091
  const parent = this.fsw._getWatchedDir(directory);
533014
- parent.add(basename9);
533092
+ parent.add(basename10);
533015
533093
  const absolutePath = sysPath.resolve(path68);
533016
533094
  const options3 = {
533017
533095
  persistent: opts.persistent
@@ -533021,7 +533099,7 @@ var init_handler = __esm({
533021
533099
  let closer;
533022
533100
  if (opts.usePolling) {
533023
533101
  const enableBin = opts.interval !== opts.binaryInterval;
533024
- options3.interval = enableBin && isBinaryPath(basename9) ? opts.binaryInterval : opts.interval;
533102
+ options3.interval = enableBin && isBinaryPath(basename10) ? opts.binaryInterval : opts.interval;
533025
533103
  closer = setFsWatchFileListener(path68, absolutePath, options3, {
533026
533104
  listener,
533027
533105
  rawEmitter: this.fsw._emitRaw
@@ -533043,11 +533121,11 @@ var init_handler = __esm({
533043
533121
  if (this.fsw.closed) {
533044
533122
  return;
533045
533123
  }
533046
- const dirname13 = sysPath.dirname(file2);
533047
- const basename9 = sysPath.basename(file2);
533048
- const parent = this.fsw._getWatchedDir(dirname13);
533124
+ const dirname14 = sysPath.dirname(file2);
533125
+ const basename10 = sysPath.basename(file2);
533126
+ const parent = this.fsw._getWatchedDir(dirname14);
533049
533127
  let prevStats = stats;
533050
- if (parent.has(basename9))
533128
+ if (parent.has(basename10))
533051
533129
  return;
533052
533130
  const listener = async (path68, newStats) => {
533053
533131
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
@@ -533072,9 +533150,9 @@ var init_handler = __esm({
533072
533150
  prevStats = newStats2;
533073
533151
  }
533074
533152
  } catch (error42) {
533075
- this.fsw._remove(dirname13, basename9);
533153
+ this.fsw._remove(dirname14, basename10);
533076
533154
  }
533077
- } else if (parent.has(basename9)) {
533155
+ } else if (parent.has(basename10)) {
533078
533156
  const at = newStats.atimeMs;
533079
533157
  const mt = newStats.mtimeMs;
533080
533158
  if (!at || at <= mt || mt !== prevStats.mtimeMs) {
@@ -535017,7 +535095,7 @@ __export(custom_exports, {
535017
535095
  saveCustomCommand: () => saveCustomCommand
535018
535096
  });
535019
535097
  import { homedir as homedir17 } from "os";
535020
- import { dirname as dirname11, join as join32 } from "path";
535098
+ import { dirname as dirname12, join as join32 } from "path";
535021
535099
  import { readdir as readdir4, readFile as readFile2, writeFile, mkdir as mkdir3, unlink as unlink3 } from "fs/promises";
535022
535100
  import { existsSync as existsSync30 } from "fs";
535023
535101
  function isRecord3(value) {
@@ -535199,7 +535277,7 @@ async function saveCustomCommand(name, command, type, description, location = "g
535199
535277
  await ensureCommandsDir(location, projectRoot);
535200
535278
  const dir = getCustomCommandsDir(location, projectRoot);
535201
535279
  const filePath = getCommandJsonFilePath(dir, name);
535202
- await mkdir3(dirname11(filePath), { recursive: true });
535280
+ await mkdir3(dirname12(filePath), { recursive: true });
535203
535281
  const data = { name, command, type, description, location };
535204
535282
  await writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
535205
535283
  }
@@ -535246,7 +535324,7 @@ async function importCustomCommandsForLocation(commands, location, projectRoot)
535246
535324
  throw new Error(`Command name "${command.name}" conflicts with an existing built-in command`);
535247
535325
  }
535248
535326
  const filePath = getCommandJsonFilePath(dir, command.name);
535249
- await mkdir3(dirname11(filePath), { recursive: true });
535327
+ await mkdir3(dirname12(filePath), { recursive: true });
535250
535328
  await writeFile(filePath, JSON.stringify(command, null, 2), "utf-8");
535251
535329
  }
535252
535330
  }
@@ -537387,7 +537465,7 @@ function cleanThinkingContent3(content) {
537387
537465
  function isValidTimestamp(timestamp) {
537388
537466
  return typeof timestamp === "number" && Number.isFinite(timestamp);
537389
537467
  }
537390
- function appendAiCompletionTimeMessage(uiMessages, timestamp) {
537468
+ function appendAiCompletionTimeMessage(uiMessages, timestamp, durationMs) {
537391
537469
  if (!isValidTimestamp(timestamp)) {
537392
537470
  return;
537393
537471
  }
@@ -537395,7 +537473,8 @@ function appendAiCompletionTimeMessage(uiMessages, timestamp) {
537395
537473
  role: "assistant",
537396
537474
  content: "",
537397
537475
  streaming: false,
537398
- aiCompletionTime: new Date(timestamp)
537476
+ aiCompletionTime: new Date(timestamp),
537477
+ aiCompletionDurationMs: typeof durationMs === "number" && Number.isFinite(durationMs) && durationMs >= 0 ? durationMs : void 0
537399
537478
  });
537400
537479
  }
537401
537480
  function convertSessionMessagesToUI(sessionMessages) {
@@ -537531,7 +537610,7 @@ function convertSessionMessagesToUI(sessionMessages) {
537531
537610
  let fileToolData = void 0;
537532
537611
  if (!isError2 && (toolName === "filesystem-create" || toolName === "filesystem-edit" || toolName === "filesystem-replaceedit")) {
537533
537612
  const editDiffData = msg.editDiffData;
537534
- if (editDiffData && (typeof editDiffData.oldContent === "string" || Array.isArray(editDiffData.batchResults))) {
537613
+ if (editDiffData && (typeof editDiffData.oldContent === "string" || typeof editDiffData.content === "string" || Array.isArray(editDiffData.batchResults))) {
537535
537614
  fileToolData = {
537536
537615
  name: toolName,
537537
537616
  arguments: editDiffData
@@ -537671,14 +537750,21 @@ function convertSessionMessagesToUI(sessionMessages) {
537671
537750
  } catch (e) {
537672
537751
  toolArgs = {};
537673
537752
  }
537674
- if ((toolName === "filesystem-edit" || toolName === "filesystem-replaceedit") && !isError2) {
537675
- if (msg.editDiffData && (typeof msg.editDiffData.oldContent === "string" || Array.isArray(msg.editDiffData.batchResults))) {
537753
+ if ((toolName === "filesystem-edit" || toolName === "filesystem-replaceedit" || toolName === "filesystem-create") && !isError2) {
537754
+ if (msg.editDiffData && (typeof msg.editDiffData.oldContent === "string" || typeof msg.editDiffData.content === "string" || Array.isArray(msg.editDiffData.batchResults))) {
537676
537755
  editDiffData = msg.editDiffData;
537677
537756
  toolArgs = { ...toolArgs, ...msg.editDiffData };
537678
537757
  }
537679
537758
  try {
537680
537759
  const resultData = JSON.parse(msg.content);
537681
- if (resultData.oldContent && resultData.newContent) {
537760
+ if (resultData.content) {
537761
+ editDiffData = {
537762
+ content: resultData.content,
537763
+ path: resultData.path || resultData.filename
537764
+ };
537765
+ toolArgs.content = resultData.content;
537766
+ toolArgs.path = resultData.path || resultData.filename;
537767
+ } else if (resultData.oldContent && resultData.newContent) {
537682
537768
  editDiffData = {
537683
537769
  oldContent: resultData.oldContent,
537684
537770
  newContent: resultData.newContent,
@@ -537771,7 +537857,24 @@ function convertSessionMessagesToUI(sessionMessages) {
537771
537857
  editorContext: msg.role === "user" ? msg.editorContext : void 0
537772
537858
  });
537773
537859
  if (msg.role === "assistant") {
537774
- appendAiCompletionTimeMessage(uiMessages, msg.timestamp);
537860
+ let durationMs;
537861
+ const assistantTimestamp = msg.timestamp;
537862
+ if (isValidTimestamp(assistantTimestamp)) {
537863
+ for (let j = i - 1; j >= 0; j--) {
537864
+ const prevMsg = sessionMessages[j];
537865
+ if (prevMsg && prevMsg.role === "user" && !prevMsg.subAgentInternal) {
537866
+ const userTimestamp = prevMsg.timestamp;
537867
+ if (isValidTimestamp(userTimestamp)) {
537868
+ const diff2 = assistantTimestamp - userTimestamp;
537869
+ if (diff2 >= 0) {
537870
+ durationMs = diff2;
537871
+ }
537872
+ }
537873
+ break;
537874
+ }
537875
+ }
537876
+ }
537877
+ appendAiCompletionTimeMessage(uiMessages, assistantTimestamp, durationMs);
537775
537878
  }
537776
537879
  continue;
537777
537880
  }
@@ -537960,7 +538063,8 @@ var init_tpsTracker = __esm({
537960
538063
  writable: true,
537961
538064
  value: {
537962
538065
  tps: 0,
537963
- peakTps: 0
538066
+ peakTps: 0,
538067
+ ttftMs: null
537964
538068
  }
537965
538069
  });
537966
538070
  Object.defineProperty(this, "tokenBuckets", {
@@ -537981,6 +538085,24 @@ var init_tpsTracker = __esm({
537981
538085
  writable: true,
537982
538086
  value: 0
537983
538087
  });
538088
+ Object.defineProperty(this, "sessionStartTime", {
538089
+ enumerable: true,
538090
+ configurable: true,
538091
+ writable: true,
538092
+ value: 0
538093
+ });
538094
+ Object.defineProperty(this, "ttftMs", {
538095
+ enumerable: true,
538096
+ configurable: true,
538097
+ writable: true,
538098
+ value: null
538099
+ });
538100
+ Object.defineProperty(this, "hasFirstToken", {
538101
+ enumerable: true,
538102
+ configurable: true,
538103
+ writable: true,
538104
+ value: false
538105
+ });
537984
538106
  Object.defineProperty(this, "snapshotRef", {
537985
538107
  enumerable: true,
537986
538108
  configurable: true,
@@ -538047,6 +538169,10 @@ var init_tpsTracker = __esm({
538047
538169
  return;
538048
538170
  }
538049
538171
  const now = Date.now();
538172
+ if (!this.hasFirstToken) {
538173
+ this.hasFirstToken = true;
538174
+ this.ttftMs = now - this.sessionStartTime;
538175
+ }
538050
538176
  const second = Math.floor(now / 1e3);
538051
538177
  if (this.currentSecond !== 0 && this.currentSecond !== second) {
538052
538178
  if (this.currentSecondTokens > 0) {
@@ -538077,9 +538203,13 @@ var init_tpsTracker = __esm({
538077
538203
  this.tokenBuckets.clear();
538078
538204
  this.currentSecond = 0;
538079
538205
  this.currentSecondTokens = 0;
538206
+ this.sessionStartTime = Date.now();
538207
+ this.ttftMs = null;
538208
+ this.hasFirstToken = false;
538080
538209
  this.snapshot = {
538081
538210
  tps: 0,
538082
- peakTps: 0
538211
+ peakTps: 0,
538212
+ ttftMs: null
538083
538213
  };
538084
538214
  this.snapshotRef = this.snapshot;
538085
538215
  }
@@ -538119,7 +538249,8 @@ var init_tpsTracker = __esm({
538119
538249
  }
538120
538250
  this.snapshot = {
538121
538251
  tps,
538122
- peakTps
538252
+ peakTps,
538253
+ ttftMs: this.ttftMs
538123
538254
  };
538124
538255
  this.snapshotRef = this.snapshot;
538125
538256
  this.emitChange();
@@ -538440,6 +538571,7 @@ async function processStreamRound(ctx) {
538440
538571
  signal: controller.signal,
538441
538572
  onRetry
538442
538573
  });
538574
+ tpsTracker.resetSession();
538443
538575
  for await (const chunk2 of streamGenerator) {
538444
538576
  if (controller.signal.aborted) {
538445
538577
  break;
@@ -547474,7 +547606,7 @@ function buildToolResultMessages(toolResults, receivedToolCalls, parallelGroupId
547474
547606
  return resultMessages;
547475
547607
  }
547476
547608
  function extractEditDiffData(toolCall, result2) {
547477
- if (toolCall.function.name !== "filesystem-edit" && toolCall.function.name !== "filesystem-replaceedit") {
547609
+ if (toolCall.function.name !== "filesystem-edit" && toolCall.function.name !== "filesystem-replaceedit" && toolCall.function.name !== "filesystem-create") {
547478
547610
  return void 0;
547479
547611
  }
547480
547612
  const isError2 = result2.content.startsWith("Error:");
@@ -547500,6 +547632,18 @@ function extractEditDiffData(toolCall, result2) {
547500
547632
  }
547501
547633
  } catch {
547502
547634
  }
547635
+ if (toolCall.function.name === "filesystem-create") {
547636
+ try {
547637
+ const callArgs = JSON.parse(toolCall.function.arguments);
547638
+ if (typeof callArgs.filePath === "string" && typeof callArgs.content === "string") {
547639
+ return {
547640
+ content: callArgs.content,
547641
+ path: callArgs.filePath
547642
+ };
547643
+ }
547644
+ } catch {
547645
+ }
547646
+ }
547503
547647
  return void 0;
547504
547648
  }
547505
547649
  var init_toolResultDisplay = __esm({
@@ -558316,13 +558460,16 @@ You can also update manually:
558316
558460
  function getNpmRegistry() {
558317
558461
  const result2 = spawnSync8("npm", ["config", "get", "registry"], {
558318
558462
  encoding: "utf8",
558319
- stdio: ["ignore", "pipe", "pipe"]
558463
+ stdio: ["ignore", "pipe", "pipe"],
558464
+ // On Windows, `npm` is actually `npm.cmd`; without a shell spawnSync
558465
+ // cannot resolve it (ENOENT) and result.stdout/stderr are null.
558466
+ shell: process.platform === "win32"
558320
558467
  });
558321
558468
  if (result2.error || typeof result2.status === "number" && result2.status !== 0) {
558322
558469
  console.warn("Unable to check npm registry before updating. Continuing anyway.");
558323
558470
  return null;
558324
558471
  }
558325
- return result2.stdout.trim();
558472
+ return (result2.stdout ?? "").trim();
558326
558473
  }
558327
558474
  function warnIfUsingMirrorRegistry() {
558328
558475
  const registry2 = getNpmRegistry();
@@ -558338,7 +558485,11 @@ function runNpmStep(step) {
558338
558485
  console.log(`
558339
558486
  ${step.label}...`);
558340
558487
  const result2 = spawnSync8("npm", step.args, {
558341
- stdio: "inherit"
558488
+ stdio: "inherit",
558489
+ // On Windows, `npm` is actually `npm.cmd`; without a shell spawnSync
558490
+ // cannot resolve it (ENOENT), aborting the update with
558491
+ // "spawnSync npm ENOENT".
558492
+ shell: process.platform === "win32"
558342
558493
  });
558343
558494
  if (result2.error) {
558344
558495
  console.error(`
@@ -609809,6 +609960,9 @@ function expandTabsForDisplay(line, tabWidth = 2) {
609809
609960
  return out;
609810
609961
  }
609811
609962
  function stripLineNumbers(content) {
609963
+ if (typeof content !== "string") {
609964
+ return "";
609965
+ }
609812
609966
  const hashlineRe = /^\s*\d+:[0-9a-fA-F]{2}→(.*)$/;
609813
609967
  const lineNumArrowRe = /^\s*\d+→(.*)$/;
609814
609968
  return content.split("\n").map((line) => {
@@ -612664,8 +612818,8 @@ var require_utils19 = __commonJS({
612664
612818
  let code = codeRegex();
612665
612819
  let stripped = ("" + str2).replace(code, "");
612666
612820
  let split = stripped.split("\n");
612667
- return split.reduce(function(memo11, s) {
612668
- return stringWidth5(s) > memo11 ? stringWidth5(s) : memo11;
612821
+ return split.reduce(function(memo12, s) {
612822
+ return stringWidth5(s) > memo12 ? stringWidth5(s) : memo12;
612669
612823
  }, 0);
612670
612824
  }
612671
612825
  function repeat(str2, times2) {
@@ -642422,10 +642576,13 @@ function compactThinkingContent2(content, maxLength = 200) {
642422
642576
  const tail = trimmed.slice(-tailLength).trimStart();
642423
642577
  return `${head}${ellipsis}${tail}`;
642424
642578
  }
642425
- function MessageRenderer({ message, index, filteredMessages, terminalWidth, showThinking = true, toolDisplayMode = "full", thinkDisplayMode = "compact" }) {
642426
- var _a20, _b14, _c6, _d4, _e2, _f;
642579
+ function MessageRendererImpl({ message, terminalWidth, isFirstInGroup = false, isLastInGroup = false, showThinking = true, toolDisplayMode = "full", thinkDisplayMode = "compact" }) {
642580
+ var _a20, _b14, _c6, _d4;
642427
642581
  const { theme: theme14 } = useTheme();
642428
642582
  const { t } = useI18n();
642583
+ if (message.subAgentContent === true) {
642584
+ return null;
642585
+ }
642429
642586
  if (message.streamingLine) {
642430
642587
  if (message.isThinkingLine && !showThinking)
642431
642588
  return null;
@@ -642509,7 +642666,7 @@ function MessageRenderer({ message, index, filteredMessages, terminalWidth, show
642509
642666
  const formatCommandResultLines = (content) => {
642510
642667
  const afterSkill = maskSkillInjectedText(content || "");
642511
642668
  const displayContent = maskGitLineText(afterSkill.displayText).displayText;
642512
- return displayContent.split("\n").map((line, index2) => parseAnsiCommandLine(`${index2 === 0 ? "\u2514\u2500 " : " "}${line || " "}`));
642669
+ return displayContent.split("\n").map((line, index) => parseAnsiCommandLine(`${index === 0 ? "\u2514\u2500 " : " "}${line || " "}`));
642513
642670
  };
642514
642671
  const formatCompactCount = (value) => {
642515
642672
  if (value >= 1e3) {
@@ -642545,27 +642702,44 @@ function MessageRenderer({ message, index, filteredMessages, terminalWidth, show
642545
642702
  return date5.toLocaleTimeString(void 0, {
642546
642703
  hour: "2-digit",
642547
642704
  minute: "2-digit",
642548
- second: "2-digit"
642705
+ second: "2-digit",
642706
+ hour12: false
642549
642707
  });
642550
642708
  };
642709
+ const formatAiCompletionDuration = (ms) => {
642710
+ if (!Number.isFinite(ms) || ms < 0) {
642711
+ return "";
642712
+ }
642713
+ const totalSeconds = Math.floor(ms / 1e3);
642714
+ if (totalSeconds < 60) {
642715
+ return `${totalSeconds}s`;
642716
+ }
642717
+ const minutes = Math.floor(totalSeconds / 60);
642718
+ const seconds = totalSeconds % 60;
642719
+ if (minutes < 60) {
642720
+ return `${minutes}m${seconds.toString().padStart(2, "0")}s`;
642721
+ }
642722
+ const hours = Math.floor(minutes / 60);
642723
+ const remainMinutes = minutes % 60;
642724
+ return `${hours}h${remainMinutes.toString().padStart(2, "0")}m`;
642725
+ };
642551
642726
  if (message.aiCompletionTime) {
642552
642727
  const completionTime = formatAiCompletionTime(message.aiCompletionTime);
642728
+ const durationStr = typeof message.aiCompletionDurationMs === "number" && Number.isFinite(message.aiCompletionDurationMs) && message.aiCompletionDurationMs >= 0 ? formatAiCompletionDuration(message.aiCompletionDurationMs) : "";
642729
+ const displayText = durationStr ? t.chatScreen.aiCompletionTimeWithDurationMessage.replace("{time}", completionTime).replace("{duration}", durationStr) : t.chatScreen.aiCompletionTimeMessage.replace("{time}", completionTime);
642553
642730
  return import_react88.default.createElement(
642554
642731
  Box_default,
642555
642732
  { paddingX: 1, width: terminalWidth, marginBottom: 1 },
642556
- import_react88.default.createElement(Text, { color: theme14.colors.menuSecondary, dimColor: true }, t.chatScreen.aiCompletionTimeMessage.replace("{time}", completionTime))
642733
+ import_react88.default.createElement(Text, { color: theme14.colors.menuSecondary, dimColor: true }, displayText)
642557
642734
  );
642558
642735
  }
642559
642736
  let toolStatusColor = "cyan";
642560
642737
  const isInParallelGroup = message.parallelGroup !== void 0 && message.parallelGroup !== null;
642561
642738
  const isTimeConsumingTool = message.toolPending || message.messageStatus === "pending";
642562
642739
  const shouldShowParallelIndicator = isInParallelGroup && !isTimeConsumingTool;
642563
- const isFirstInGroup = shouldShowParallelIndicator && (index === 0 || ((_a20 = filteredMessages[index - 1]) == null ? void 0 : _a20.parallelGroup) !== message.parallelGroup || // Previous message is time-consuming tool, so this is the first non-time-consuming one
642564
- ((_b14 = filteredMessages[index - 1]) == null ? void 0 : _b14.toolPending) || ((_c6 = filteredMessages[index - 1]) == null ? void 0 : _c6.messageStatus) === "pending");
642565
- const nextMessage = filteredMessages[index + 1];
642566
- const nextInSameGroup = nextMessage && nextMessage.parallelGroup !== void 0 && nextMessage.parallelGroup !== null && nextMessage.parallelGroup === message.parallelGroup;
642567
- const isLastInGroup = shouldShowParallelIndicator && !nextInSameGroup;
642568
- const leadingIndicator = shouldShowParallelIndicator && !isFirstInGroup ? "\u2502" : "";
642740
+ const effectiveIsFirstInGroup = shouldShowParallelIndicator && isFirstInGroup;
642741
+ const effectiveIsLastInGroup = shouldShowParallelIndicator && isLastInGroup;
642742
+ const leadingIndicator = shouldShowParallelIndicator && !effectiveIsFirstInGroup ? "\u2502" : "";
642569
642743
  const messageIcon = message.role === "user" ? message.subAgentDirected ? "\xBB" : "\u276F" : message.role === "command" ? "\u2318" : "\u2746";
642570
642744
  const messagePrefix = `${leadingIndicator}${messageIcon}`;
642571
642745
  const contentColumnWidth = Math.max(terminalWidth - 2 - visualWidth(messagePrefix) - 1, 1);
@@ -642577,17 +642751,17 @@ function MessageRenderer({ message, index, filteredMessages, terminalWidth, show
642577
642751
  } else if (message.messageStatus === "error") {
642578
642752
  toolStatusColor = "red";
642579
642753
  } else {
642580
- if (message.subAgentContent === true || message.role === "subagent" && message.subAgentInternal === true) {
642754
+ if (message.role === "subagent" && message.subAgentInternal === true) {
642581
642755
  toolStatusColor = "cyan";
642582
642756
  } else {
642583
642757
  toolStatusColor = message.role === "subagent" ? "magenta" : "blue";
642584
642758
  }
642585
642759
  }
642586
642760
  }
642587
- return import_react88.default.createElement(Box_default, { key: `msg-${index}`, marginTop: message.role === "user" ? 1 : 0, marginBottom: 1, paddingX: 1, flexDirection: "column", width: terminalWidth }, message.plainOutput ? import_react88.default.createElement(Text, { color: message.role === "user" ? theme14.colors.userMessageText : toolStatusColor }, getDisplayContent(message.content)) : import_react88.default.createElement(
642761
+ return import_react88.default.createElement(Box_default, { marginTop: message.role === "user" ? 1 : 0, marginBottom: 1, paddingX: 1, flexDirection: "column", width: terminalWidth }, message.plainOutput ? import_react88.default.createElement(Text, { color: message.role === "user" ? theme14.colors.userMessageText : toolStatusColor }, getDisplayContent(message.content)) : import_react88.default.createElement(
642588
642762
  import_react88.default.Fragment,
642589
642763
  null,
642590
- isFirstInGroup && import_react88.default.createElement(
642764
+ effectiveIsFirstInGroup && import_react88.default.createElement(
642591
642765
  Box_default,
642592
642766
  { marginBottom: 0 },
642593
642767
  import_react88.default.createElement(Text, { color: theme14.colors.menuInfo, dimColor: true }, t.chatScreen.parallelStart)
@@ -642647,8 +642821,7 @@ function MessageRenderer({ message, index, filteredMessages, terminalWidth, show
642647
642821
  }
642648
642822
  const hasToolStatus = message.messageStatus !== void 0;
642649
642823
  const isSubAgentInternal = message.subAgentInternal === true;
642650
- const isSubAgentContent = message.subAgentContent === true;
642651
- if ((hasToolStatus || isSubAgentInternal && !isSubAgentContent) && (message.role === "assistant" || message.role === "subagent")) {
642824
+ if ((hasToolStatus || isSubAgentInternal) && (message.role === "assistant" || message.role === "subagent")) {
642652
642825
  const content = message.content || " ";
642653
642826
  const lines = content.split("\n");
642654
642827
  const titleLine = lines[0] || "";
@@ -642726,7 +642899,7 @@ function MessageRenderer({ message, index, filteredMessages, terminalWidth, show
642726
642899
  ": ",
642727
642900
  arg.value
642728
642901
  ))),
642729
- message.toolCall && message.toolCall.name === "filesystem-create" && message.toolCall.arguments.content && import_react88.default.createElement(
642902
+ message.toolCall && message.toolCall.name === "filesystem-create" && !message.toolCall.arguments.isBatch && message.toolCall.arguments.content && import_react88.default.createElement(
642730
642903
  Box_default,
642731
642904
  { marginTop: 1 },
642732
642905
  import_react88.default.createElement(DiffViewer, { newContent: message.toolCall.arguments.content, filename: message.toolCall.arguments.path })
@@ -642736,20 +642909,31 @@ function MessageRenderer({ message, index, filteredMessages, terminalWidth, show
642736
642909
  { marginTop: 1 },
642737
642910
  import_react88.default.createElement(DiffViewer, { oldContent: message.toolCall.arguments.oldContent, newContent: message.toolCall.arguments.newContent, filename: message.toolCall.arguments.filename, completeOldContent: message.toolCall.arguments.completeOldContent, completeNewContent: message.toolCall.arguments.completeNewContent, startLineNumber: message.toolCall.arguments.contextStartLine })
642738
642911
  ),
642739
- message.toolCall && (message.toolCall.name === "filesystem-edit" || message.toolCall.name === "filesystem-replaceedit") && message.toolCall.arguments.isBatch && message.toolCall.arguments.batchResults && Array.isArray(message.toolCall.arguments.batchResults) && import_react88.default.createElement(Box_default, { marginTop: 1, flexDirection: "column" }, message.toolCall.arguments.batchResults.map((fileResult, index2) => {
642912
+ message.toolCall && (message.toolCall.name === "filesystem-edit" || message.toolCall.name === "filesystem-replaceedit") && message.toolCall.arguments.isBatch && message.toolCall.arguments.batchResults && Array.isArray(message.toolCall.arguments.batchResults) && import_react88.default.createElement(Box_default, { marginTop: 1, flexDirection: "column" }, message.toolCall.arguments.batchResults.map((fileResult, index) => {
642740
642913
  if (fileResult.success && fileResult.oldContent && fileResult.newContent) {
642741
642914
  return import_react88.default.createElement(
642742
642915
  Box_default,
642743
- { key: index2, flexDirection: "column", marginBottom: 1 },
642744
- import_react88.default.createElement(Text, { bold: true, color: "cyan" }, `File ${index2 + 1}: ${fileResult.path}`),
642916
+ { key: index, flexDirection: "column", marginBottom: 1 },
642917
+ import_react88.default.createElement(Text, { bold: true, color: "cyan" }, `File ${index + 1}: ${fileResult.path}`),
642745
642918
  import_react88.default.createElement(DiffViewer, { oldContent: fileResult.oldContent, newContent: fileResult.newContent, filename: fileResult.path, showFilenameInHeader: false, completeOldContent: fileResult.completeOldContent, completeNewContent: fileResult.completeNewContent, startLineNumber: fileResult.contextStartLine })
642746
642919
  );
642747
642920
  }
642748
642921
  return null;
642749
642922
  })),
642923
+ message.toolCall && message.toolCall.name === "filesystem-create" && message.toolCall.arguments.isBatch && message.toolCall.arguments.batchResults && Array.isArray(message.toolCall.arguments.batchResults) && import_react88.default.createElement(Box_default, { marginTop: 1, flexDirection: "column" }, message.toolCall.arguments.batchResults.map((fileResult, index) => {
642924
+ if (fileResult.success && fileResult.content) {
642925
+ return import_react88.default.createElement(
642926
+ Box_default,
642927
+ { key: index, flexDirection: "column", marginBottom: 1 },
642928
+ import_react88.default.createElement(Text, { bold: true, color: "cyan" }, `File ${index + 1}: ${fileResult.path}`),
642929
+ import_react88.default.createElement(DiffViewer, { newContent: fileResult.content, filename: fileResult.path, showFilenameInHeader: false })
642930
+ );
642931
+ }
642932
+ return null;
642933
+ })),
642750
642934
  message.messageStatus === "success" && message.toolResult && // 只在没有 diff 数据时显示预览(有 diff 的工具会用 DiffViewer 显示)
642751
- !(message.toolCall && (((_d4 = message.toolCall.arguments) == null ? void 0 : _d4.oldContent) || ((_e2 = message.toolCall.arguments) == null ? void 0 : _e2.batchResults))) && // Hide result preview in compact mode
642752
- toolDisplayMode === "full" && import_react88.default.createElement(ToolResultPreview, { toolName: ((_f = (message.content || "").replace(/^✓\s*/, "").replace(/^⚇✓\s*/, "").replace(/.*⚇✓\s*/, "").replace(/\x1b\[[0-9;]*m/g, "").split("\n")[0]) == null ? void 0 : _f.trim()) || "", result: message.toolResult, maxLines: 5, isSubAgentInternal: message.role === "subagent" || message.subAgentInternal === true }),
642935
+ !(message.toolCall && (((_a20 = message.toolCall.arguments) == null ? void 0 : _a20.oldContent) || ((_b14 = message.toolCall.arguments) == null ? void 0 : _b14.content) || ((_c6 = message.toolCall.arguments) == null ? void 0 : _c6.batchResults))) && // Hide result preview in compact mode
642936
+ toolDisplayMode === "full" && import_react88.default.createElement(ToolResultPreview, { toolName: ((_d4 = (message.content || "").replace(/^✓\s*/, "").replace(/^⚇✓\s*/, "").replace(/.*⚇✓\s*/, "").replace(/\x1b\[[0-9;]*m/g, "").split("\n")[0]) == null ? void 0 : _d4.trim()) || "", result: message.toolResult, maxLines: 5, isSubAgentInternal: message.role === "subagent" || message.subAgentInternal === true }),
642753
642937
  message.files && message.files.length > 0 && import_react88.default.createElement(Box_default, { flexDirection: "column" }, message.files.map((file2, fileIndex) => import_react88.default.createElement(
642754
642938
  Text,
642755
642939
  { key: fileIndex, color: theme14.colors.menuSecondary, dimColor: true },
@@ -642768,14 +642952,50 @@ function MessageRenderer({ message, index, filteredMessages, terminalWidth, show
642768
642952
  )
642769
642953
  )
642770
642954
  ),
642771
- !message.plainOutput && isLastInGroup && import_react88.default.createElement(
642955
+ !message.plainOutput && effectiveIsLastInGroup && import_react88.default.createElement(
642772
642956
  Box_default,
642773
642957
  { marginTop: 0 },
642774
642958
  import_react88.default.createElement(Text, { color: theme14.colors.menuInfo, dimColor: true }, t.chatScreen.parallelEnd)
642775
642959
  )
642776
642960
  ));
642777
642961
  }
642778
- var import_react88;
642962
+ function areMessageRendererPropsEqual(prev, next) {
642963
+ if (prev.message !== next.message)
642964
+ return false;
642965
+ if (prev.terminalWidth !== next.terminalWidth)
642966
+ return false;
642967
+ if (prev.showThinking !== next.showThinking)
642968
+ return false;
642969
+ if (prev.toolDisplayMode !== next.toolDisplayMode)
642970
+ return false;
642971
+ if (prev.thinkDisplayMode !== next.thinkDisplayMode)
642972
+ return false;
642973
+ if (prev.isFirstInGroup !== next.isFirstInGroup)
642974
+ return false;
642975
+ if (prev.isLastInGroup !== next.isLastInGroup)
642976
+ return false;
642977
+ return true;
642978
+ }
642979
+ function computeParallelGroupEdges(messages) {
642980
+ const len = messages.length;
642981
+ const isFirstInGroup = new Array(len).fill(false);
642982
+ const isLastInGroup = new Array(len).fill(false);
642983
+ for (let i = 0; i < len; i++) {
642984
+ const msg = messages[i];
642985
+ const isInParallelGroup = msg.parallelGroup !== void 0 && msg.parallelGroup !== null;
642986
+ const isTimeConsumingTool = msg.toolPending || msg.messageStatus === "pending";
642987
+ const shouldShowParallelIndicator = isInParallelGroup && !isTimeConsumingTool;
642988
+ if (!shouldShowParallelIndicator)
642989
+ continue;
642990
+ const prev = i > 0 ? messages[i - 1] : void 0;
642991
+ isFirstInGroup[i] = !prev || prev.parallelGroup !== msg.parallelGroup || prev.toolPending || prev.messageStatus === "pending";
642992
+ const next = i < len - 1 ? messages[i + 1] : void 0;
642993
+ const nextInSameGroup = next && next.parallelGroup !== void 0 && next.parallelGroup !== null && next.parallelGroup === msg.parallelGroup;
642994
+ isLastInGroup[i] = !nextInSameGroup;
642995
+ }
642996
+ return { isFirstInGroup, isLastInGroup };
642997
+ }
642998
+ var import_react88, MessageRenderer, MessageRenderer_default;
642779
642999
  var init_MessageRenderer = __esm({
642780
643000
  async "dist/ui/components/chat/MessageRenderer.js"() {
642781
643001
  "use strict";
@@ -642792,6 +643012,9 @@ var init_MessageRenderer = __esm({
642792
643012
  init_gitLineMask();
642793
643013
  init_textUtils();
642794
643014
  init_compressionSummaryDisplay();
643015
+ MessageRenderer = (0, import_react88.memo)(MessageRendererImpl, areMessageRendererPropsEqual);
643016
+ MessageRenderer.displayName = "MessageRenderer";
643017
+ MessageRenderer_default = MessageRenderer;
642795
643018
  }
642796
643019
  });
642797
643020
 
@@ -642802,8 +643025,7 @@ function UserMessagePreview({ content }) {
642802
643025
  role: "user",
642803
643026
  content
642804
643027
  }), [content]);
642805
- const filteredMessages = (0, import_react89.useMemo)(() => [message], [message]);
642806
- return import_react89.default.createElement(MessageRenderer, { message, index: 0, filteredMessages, terminalWidth, showThinking: false });
643028
+ return import_react89.default.createElement(MessageRenderer_default, { message, terminalWidth, isFirstInGroup: false, isLastInGroup: false, showThinking: false });
642807
643029
  }
642808
643030
  var import_react89;
642809
643031
  var init_UserMessagePreview = __esm({
@@ -647262,7 +647484,8 @@ function filePickerReducer(state, action) {
647262
647484
  fileSelectedIndex: 0,
647263
647485
  fileQuery: action.query,
647264
647486
  atSymbolPosition: action.position,
647265
- searchMode: action.searchMode
647487
+ searchMode: action.searchMode,
647488
+ workspaceFilter: action.workspaceFilter !== void 0 ? action.workspaceFilter : state.workspaceFilter
647266
647489
  };
647267
647490
  case "HIDE":
647268
647491
  return {
@@ -647270,7 +647493,8 @@ function filePickerReducer(state, action) {
647270
647493
  showFilePicker: false,
647271
647494
  fileSelectedIndex: 0,
647272
647495
  fileQuery: "",
647273
- atSymbolPosition: -1
647496
+ atSymbolPosition: -1,
647497
+ workspaceFilter: null
647274
647498
  };
647275
647499
  case "SELECT_FILE":
647276
647500
  return {
@@ -647278,7 +647502,8 @@ function filePickerReducer(state, action) {
647278
647502
  showFilePicker: false,
647279
647503
  fileSelectedIndex: 0,
647280
647504
  fileQuery: "",
647281
- atSymbolPosition: -1
647505
+ atSymbolPosition: -1,
647506
+ workspaceFilter: null
647282
647507
  };
647283
647508
  case "SET_SELECTED_INDEX":
647284
647509
  return {
@@ -647301,7 +647526,8 @@ function useFilePicker(buffer, triggerUpdate) {
647301
647526
  fileQuery: "",
647302
647527
  atSymbolPosition: -1,
647303
647528
  filteredFileCount: 0,
647304
- searchMode: "file"
647529
+ searchMode: "file",
647530
+ workspaceFilter: null
647305
647531
  });
647306
647532
  const fileListRef = (0, import_react98.useRef)(null);
647307
647533
  const updateFilePickerState = (0, import_react98.useCallback)((_text, cursorPos) => {
@@ -647371,13 +647597,35 @@ function useFilePicker(buffer, triggerUpdate) {
647371
647597
  state.atSymbolPosition,
647372
647598
  state.searchMode
647373
647599
  ]);
647374
- const handleFileSelect = (0, import_react98.useCallback)(async (filePath) => {
647600
+ const handleFileSelect = (0, import_react98.useCallback)(async (filePath, displayName) => {
647375
647601
  if (state.atSymbolPosition !== -1) {
647376
647602
  const displayText = buffer.text;
647377
647603
  const cursorPos = buffer.getCursorPosition();
647604
+ const isWorkspaceSelection = state.fileQuery.startsWith(":");
647378
647605
  const beforeAt = displayText.slice(0, state.atSymbolPosition);
647379
647606
  const afterCursor = displayText.slice(cursorPos);
647380
647607
  const prefix = state.searchMode === "content" ? "@@" : "@";
647608
+ if (isWorkspaceSelection) {
647609
+ const tag2 = displayName || filePath.replace(/\/$/, "").split("/").pop() || filePath;
647610
+ const tagText = `${prefix}[${tag2}]`;
647611
+ const newText2 = beforeAt + tagText + afterCursor;
647612
+ buffer.setText(newText2);
647613
+ const targetPos2 = state.atSymbolPosition + tagText.length;
647614
+ for (let i = 0; i < targetPos2; i++) {
647615
+ if (i < buffer.text.length) {
647616
+ buffer.moveRight();
647617
+ }
647618
+ }
647619
+ dispatch({
647620
+ type: "SHOW",
647621
+ query: "",
647622
+ position: state.atSymbolPosition,
647623
+ searchMode: state.searchMode,
647624
+ workspaceFilter: filePath
647625
+ });
647626
+ triggerUpdate();
647627
+ return;
647628
+ }
647381
647629
  const isDirectoryContinuation = state.searchMode === "file" && filePath.endsWith("/");
647382
647630
  const suffix = isDirectoryContinuation ? "" : " ";
647383
647631
  const newText = beforeAt + prefix + filePath + suffix + afterCursor;
@@ -647401,7 +647649,13 @@ function useFilePicker(buffer, triggerUpdate) {
647401
647649
  }
647402
647650
  triggerUpdate();
647403
647651
  }
647404
- }, [state.atSymbolPosition, state.searchMode, buffer, triggerUpdate]);
647652
+ }, [
647653
+ state.atSymbolPosition,
647654
+ state.searchMode,
647655
+ state.fileQuery,
647656
+ buffer,
647657
+ triggerUpdate
647658
+ ]);
647405
647659
  const handleMultipleFileSelect = (0, import_react98.useCallback)(async (filePaths) => {
647406
647660
  if (filePaths.length === 0) {
647407
647661
  return;
@@ -647464,6 +647718,7 @@ function useFilePicker(buffer, triggerUpdate) {
647464
647718
  },
647465
647719
  filteredFileCount: state.filteredFileCount,
647466
647720
  searchMode: state.searchMode,
647721
+ workspaceFilter: state.workspaceFilter,
647467
647722
  updateFilePickerState,
647468
647723
  handleFileSelect,
647469
647724
  handleMultipleFileSelect,
@@ -648944,7 +649199,7 @@ var init_deleteAndBackspace = __esm({
648944
649199
 
648945
649200
  // dist/hooks/input/keyboard/handlers/pickers/filePicker.js
648946
649201
  function filePickerHandler(ctx) {
648947
- var _a20, _b14, _c6, _d4, _e2, _f, _g, _h, _i;
649202
+ var _a20, _b14, _c6, _d4, _e2, _f, _g, _h, _i, _j, _k;
648948
649203
  const { input: input2, key, options: options3 } = ctx;
648949
649204
  const { showFilePicker, filteredFileCount, fileSelectedIndex, setFileSelectedIndex, fileListRef, handleFileSelect, handleMultipleFileSelect } = options3;
648950
649205
  if (!showFilePicker)
@@ -648985,7 +649240,8 @@ function filePickerHandler(ctx) {
648985
649240
  }
648986
649241
  const selectedFile = (_i = fileListRef.current) == null ? void 0 : _i.getSelectedFile();
648987
649242
  if (selectedFile) {
648988
- handleFileSelect(selectedFile);
649243
+ const displayName = (_k = (_j = fileListRef.current) == null ? void 0 : _j.getSelectedDisplayName) == null ? void 0 : _k.call(_j);
649244
+ handleFileSelect(selectedFile, displayName ?? void 0);
648989
649245
  }
648990
649246
  }
648991
649247
  return true;
@@ -651863,7 +652119,7 @@ __export(FileList_exports, {
651863
652119
  });
651864
652120
  import fs55 from "fs";
651865
652121
  import path64 from "path";
651866
- var import_react111, SEARCH_RESULT_TTL_MS, getDisplayItemKey, getNormalizedItemPath, getLookupKey, getRelativeTreePath, getTreeDepth, compareTreeItems, buildTreeDisplayItems, getFullFilePath, AGENT_PREVIEW_VIEWPORT_HEIGHT, AGENT_PREVIEW_INDENT_WIDTH, AGENT_PREVIEW_RESERVED_COLUMNS, AGENT_PREVIEW_PANEL_PADDING, normalizeAgentPreviewContent, sliceByVisualWidth, getSafeAgentPreviewLineWidth, buildAgentPreviewLines, buildSafeAgentPreviewTitle, FileList, FileList_default;
652122
+ var import_react111, SEARCH_RESULT_TTL_MS, getDisplayItemKey, getNormalizedItemPath, getLookupKey, getRelativeTreePath, getTreeDepth, getSourceDirName, compareTreeItems, buildTreeDisplayItems, getFullFilePath, AGENT_PREVIEW_VIEWPORT_HEIGHT, AGENT_PREVIEW_INDENT_WIDTH, AGENT_PREVIEW_RESERVED_COLUMNS, AGENT_PREVIEW_PANEL_PADDING, normalizeAgentPreviewContent, sliceByVisualWidth, getSafeAgentPreviewLineWidth, buildAgentPreviewLines, buildSafeAgentPreviewTitle, FileList, FileList_default;
651867
652123
  var init_FileList = __esm({
651868
652124
  async "dist/ui/components/tools/FileList.js"() {
651869
652125
  "use strict";
@@ -651894,6 +652150,16 @@ var init_FileList = __esm({
651894
652150
  }
651895
652151
  return relativePath.split("/").filter(Boolean).length;
651896
652152
  };
652153
+ getSourceDirName = (sourceDir) => {
652154
+ if (sourceDir.startsWith("ssh://")) {
652155
+ const sshInfo = parseSSHUrl(sourceDir);
652156
+ if (sshInfo) {
652157
+ return sshInfo.path.split("/").pop() || sshInfo.host;
652158
+ }
652159
+ return sourceDir;
652160
+ }
652161
+ return path64.basename(sourceDir) || sourceDir;
652162
+ };
651897
652163
  compareTreeItems = (a, b) => {
651898
652164
  const sourceCompare = (a.sourceDir || "").localeCompare(b.sourceDir || "");
651899
652165
  if (sourceCompare !== 0) {
@@ -652019,7 +652285,7 @@ var init_FileList = __esm({
652019
652285
  buildSafeAgentPreviewTitle = (title, terminalWidth) => {
652020
652286
  return sliceByVisualWidth(title, Math.max(1, terminalWidth - 1)) || " ";
652021
652287
  };
652022
- FileList = (0, import_react111.memo)((0, import_react111.forwardRef)(({ query, selectedIndex, visible, maxItems = 10, rootPath = process.cwd(), onFilteredCountChange, searchMode = "file" }, ref) => {
652288
+ FileList = (0, import_react111.memo)((0, import_react111.forwardRef)(({ query, selectedIndex, visible, maxItems = 10, rootPath = process.cwd(), onFilteredCountChange, searchMode = "file", workspaceFilter = null }, ref) => {
652023
652289
  const { t } = useI18n();
652024
652290
  const { theme: theme14 } = useTheme();
652025
652291
  const [files, setFiles] = (0, import_react111.useState)([]);
@@ -652038,7 +652304,9 @@ var init_FileList = __esm({
652038
652304
  const [agentError, setAgentError] = (0, import_react111.useState)(null);
652039
652305
  const agentAbortRef = (0, import_react111.useRef)(null);
652040
652306
  const wasAgentModeRef = (0, import_react111.useRef)(false);
652041
- const isAgentMode = query.startsWith("??");
652307
+ const isWorkspaceSelectionMode = query.startsWith(":");
652308
+ const normalizedQuery = isWorkspaceSelectionMode ? "" : workspaceFilter && query.startsWith("[") ? query.replace(/^\[[^\]]*\]/, "") : query;
652309
+ const isAgentMode = normalizedQuery.startsWith("??");
652042
652310
  const { columns: terminalWidth } = useTerminalSize();
652043
652311
  const agentPreviewLabels = (0, import_react111.useMemo)(() => ({
652044
652312
  assistantPrefix: t.fileList.agentPreviewAssistantPrefix,
@@ -652066,7 +652334,8 @@ var init_FileList = __esm({
652066
652334
  return maxItems ? Math.min(maxItems, MAX_DISPLAY_ITEMS2) : MAX_DISPLAY_ITEMS2;
652067
652335
  }, [maxItems]);
652068
652336
  const loadFiles = (0, import_react111.useCallback)(async () => {
652069
- const workingDirs = await getWorkingDirectories();
652337
+ const allDirs = await getWorkingDirectories();
652338
+ const workingDirs = workspaceFilter ? allDirs.filter((d) => d.path === workspaceFilter || d.path === workspaceFilter.replace(/\/$/, "")) : allDirs;
652070
652339
  const collected = [];
652071
652340
  let depthLimitHit = false;
652072
652341
  const FLUSH_INTERVAL_MS = 80;
@@ -652218,7 +652487,7 @@ var init_FileList = __esm({
652218
652487
  flush(true);
652219
652488
  setHasMoreDepth(depthLimitHit);
652220
652489
  setIsLoading(false);
652221
- }, [searchDepth]);
652490
+ }, [searchDepth, workspaceFilter]);
652222
652491
  const searchFileContent = (0, import_react111.useCallback)(async (query2) => {
652223
652492
  if (!query2.trim()) {
652224
652493
  return [];
@@ -652286,6 +652555,39 @@ var init_FileList = __esm({
652286
652555
  loadFiles();
652287
652556
  }, [visible, rootPath, loadFiles]);
652288
652557
  const [allFilteredFiles, setAllFilteredFiles] = (0, import_react111.useState)([]);
652558
+ const [workspaceDirs, setWorkspaceDirs] = (0, import_react111.useState)([]);
652559
+ (0, import_react111.useEffect)(() => {
652560
+ if (!visible || !isWorkspaceSelectionMode) {
652561
+ return;
652562
+ }
652563
+ let cancelled = false;
652564
+ (async () => {
652565
+ const dirs = await getWorkingDirectories();
652566
+ if (cancelled)
652567
+ return;
652568
+ const items = dirs.map((dir) => {
652569
+ const dirName = dir.displayName || getSourceDirName(dir.path);
652570
+ return {
652571
+ name: dirName,
652572
+ path: dir.path.endsWith("/") ? dir.path : `${dir.path}/`,
652573
+ isDirectory: true,
652574
+ sourceDir: dir.path
652575
+ };
652576
+ });
652577
+ setWorkspaceDirs(items);
652578
+ })();
652579
+ return () => {
652580
+ cancelled = true;
652581
+ };
652582
+ }, [visible, isWorkspaceSelectionMode]);
652583
+ const filteredWorkspaceDirs = (0, import_react111.useMemo)(() => {
652584
+ if (!isWorkspaceSelectionMode)
652585
+ return [];
652586
+ const filterText = query.slice(1).toLowerCase();
652587
+ if (!filterText)
652588
+ return workspaceDirs;
652589
+ return workspaceDirs.filter((dir) => dir.name.toLowerCase().includes(filterText) || (dir.sourceDir || "").toLowerCase().includes(filterText));
652590
+ }, [isWorkspaceSelectionMode, query, workspaceDirs]);
652289
652591
  (0, import_react111.useEffect)(() => {
652290
652592
  if (visible) {
652291
652593
  return;
@@ -652305,20 +652607,20 @@ var init_FileList = __esm({
652305
652607
  return;
652306
652608
  }
652307
652609
  const performSearch = async () => {
652308
- if (!query.trim()) {
652610
+ if (!normalizedQuery.trim()) {
652309
652611
  setAllFilteredFiles(files);
652310
652612
  return;
652311
652613
  }
652312
652614
  if (searchMode === "content") {
652313
- const results = await searchFileContent(query);
652615
+ const results = await searchFileContent(normalizedQuery);
652314
652616
  setAllFilteredFiles(results);
652315
- if (!isLoading && results.length === 0 && query.trim().length > 0 && hasMoreDepth) {
652617
+ if (!isLoading && results.length === 0 && normalizedQuery.trim().length > 0 && hasMoreDepth) {
652316
652618
  setSearchDepth((d) => d + 3);
652317
652619
  setIsIncreasingDepth(true);
652318
652620
  setTimeout(() => setIsIncreasingDepth(false), 400);
652319
652621
  }
652320
652622
  } else {
652321
- const queryLower = query.toLowerCase().replace(/\\/g, "/");
652623
+ const queryLower = normalizedQuery.toLowerCase().replace(/\\/g, "/");
652322
652624
  const filtered = files.filter((file2) => {
652323
652625
  const fileName = file2.name.toLowerCase();
652324
652626
  const filePath = file2.path.toLowerCase().replace(/\\/g, "/");
@@ -652349,7 +652651,7 @@ var init_FileList = __esm({
652349
652651
  return a.name.localeCompare(b.name);
652350
652652
  });
652351
652653
  setAllFilteredFiles(filtered);
652352
- if (!isLoading && filtered.length === 0 && query.trim().length > 0 && hasMoreDepth) {
652654
+ if (!isLoading && filtered.length === 0 && normalizedQuery.trim().length > 0 && hasMoreDepth) {
652353
652655
  setSearchDepth((d) => d + 3);
652354
652656
  setIsIncreasingDepth(true);
652355
652657
  setTimeout(() => setIsIncreasingDepth(false), 400);
@@ -652363,7 +652665,7 @@ var init_FileList = __esm({
652363
652665
  return () => clearTimeout(timer2);
652364
652666
  }, [
652365
652667
  files,
652366
- query,
652668
+ normalizedQuery,
652367
652669
  searchMode,
652368
652670
  searchFileContent,
652369
652671
  isLoading,
@@ -652372,7 +652674,7 @@ var init_FileList = __esm({
652372
652674
  agentResults
652373
652675
  ]);
652374
652676
  (0, import_react111.useEffect)(() => {
652375
- const agentQuery = isAgentMode ? query.slice(2).trim() : "";
652677
+ const agentQuery = isAgentMode ? normalizedQuery.slice(2).trim() : "";
652376
652678
  if (!visible || !isAgentMode || !agentQuery) {
652377
652679
  if (wasAgentModeRef.current) {
652378
652680
  wasAgentModeRef.current = false;
@@ -652406,7 +652708,8 @@ var init_FileList = __esm({
652406
652708
  setAgentRound(0);
652407
652709
  setAgentPreviewContent("");
652408
652710
  try {
652409
- const workingDirs = await getWorkingDirectories();
652711
+ const allDirs = await getWorkingDirectories();
652712
+ const workingDirs = workspaceFilter ? allDirs.filter((d) => d.path === workspaceFilter || d.path === workspaceFilter.replace(/\/$/, "")) : allDirs;
652410
652713
  const generator = fileSearchAgent.search(agentQuery, searchMode, workingDirs, controller.signal, agentPreviewLabels);
652411
652714
  for await (const event of generator) {
652412
652715
  if (controller.signal.aborted) {
@@ -652438,7 +652741,14 @@ var init_FileList = __esm({
652438
652741
  clearTimeout(timer2);
652439
652742
  controller.abort();
652440
652743
  };
652441
- }, [query, searchMode, visible, isAgentMode, agentPreviewLabels]);
652744
+ }, [
652745
+ normalizedQuery,
652746
+ searchMode,
652747
+ visible,
652748
+ isAgentMode,
652749
+ agentPreviewLabels,
652750
+ workspaceFilter
652751
+ ]);
652442
652752
  const displayItems = (0, import_react111.useMemo)(() => {
652443
652753
  if (isAgentMode || searchMode === "content") {
652444
652754
  return allFilteredFiles.map((file2) => ({
@@ -652449,7 +652759,7 @@ var init_FileList = __esm({
652449
652759
  }));
652450
652760
  }
652451
652761
  if (displayMode === "tree") {
652452
- return buildTreeDisplayItems(allFilteredFiles, files, query);
652762
+ return buildTreeDisplayItems(allFilteredFiles, files, normalizedQuery);
652453
652763
  }
652454
652764
  return allFilteredFiles.map((file2) => ({
652455
652765
  file: file2,
@@ -652462,7 +652772,7 @@ var init_FileList = __esm({
652462
652772
  files,
652463
652773
  displayMode,
652464
652774
  searchMode,
652465
- query,
652775
+ normalizedQuery,
652466
652776
  isAgentMode
652467
652777
  ]);
652468
652778
  const normalizedSelectedIndex = (0, import_react111.useMemo)(() => {
@@ -652496,9 +652806,15 @@ var init_FileList = __esm({
652496
652806
  const hiddenBelowCount = Math.max(0, displayItems.length - fileWindow.endIndex);
652497
652807
  (0, import_react111.useEffect)(() => {
652498
652808
  if (onFilteredCountChange) {
652499
- onFilteredCountChange(displayItems.length);
652809
+ const count = isWorkspaceSelectionMode ? filteredWorkspaceDirs.length : displayItems.length;
652810
+ onFilteredCountChange(count);
652500
652811
  }
652501
- }, [displayItems.length, onFilteredCountChange]);
652812
+ }, [
652813
+ displayItems.length,
652814
+ onFilteredCountChange,
652815
+ isWorkspaceSelectionMode,
652816
+ filteredWorkspaceDirs.length
652817
+ ]);
652502
652818
  const resolveInsertionPath = (0, import_react111.useCallback)((entry) => {
652503
652819
  if (!entry) {
652504
652820
  return null;
@@ -652515,12 +652831,25 @@ var init_FileList = __esm({
652515
652831
  }, [rootPath, searchMode]);
652516
652832
  (0, import_react111.useImperativeHandle)(ref, () => ({
652517
652833
  getSelectedFile: () => {
652834
+ if (isWorkspaceSelectionMode) {
652835
+ const wsIndex = Math.min(selectedIndex, Math.max(0, filteredWorkspaceDirs.length - 1));
652836
+ const wsItem = filteredWorkspaceDirs[wsIndex];
652837
+ return wsItem ? wsItem.path : null;
652838
+ }
652518
652839
  const selectedEntry = displayItems[normalizedSelectedIndex];
652519
652840
  if (!selectedEntry) {
652520
652841
  return null;
652521
652842
  }
652522
652843
  return resolveInsertionPath(selectedEntry);
652523
652844
  },
652845
+ getSelectedDisplayName: () => {
652846
+ if (isWorkspaceSelectionMode) {
652847
+ const wsIndex = Math.min(selectedIndex, Math.max(0, filteredWorkspaceDirs.length - 1));
652848
+ const wsItem = filteredWorkspaceDirs[wsIndex];
652849
+ return wsItem ? wsItem.name : null;
652850
+ }
652851
+ return null;
652852
+ },
652524
652853
  toggleDisplayMode: () => {
652525
652854
  if (searchMode !== "file") {
652526
652855
  return false;
@@ -652593,7 +652922,10 @@ var init_FileList = __esm({
652593
652922
  isIncreasingDepth,
652594
652923
  displayMode,
652595
652924
  selectedKeys,
652596
- resolveInsertionPath
652925
+ resolveInsertionPath,
652926
+ isWorkspaceSelectionMode,
652927
+ filteredWorkspaceDirs,
652928
+ selectedIndex
652597
652929
  ]);
652598
652930
  const displaySelectedIndex = filteredFiles.length === 0 ? -1 : normalizedSelectedIndex - fileWindow.startIndex;
652599
652931
  const selectedFileFullPath = (0, import_react111.useMemo)(() => {
@@ -652606,6 +652938,47 @@ var init_FileList = __esm({
652606
652938
  if (!visible) {
652607
652939
  return null;
652608
652940
  }
652941
+ if (isWorkspaceSelectionMode) {
652942
+ const wsItems = filteredWorkspaceDirs;
652943
+ const wsSelectedIndex = Math.min(selectedIndex, Math.max(0, wsItems.length - 1));
652944
+ const wsWindow = wsItems.slice(0, effectiveMaxItems);
652945
+ if (wsItems.length === 0) {
652946
+ return import_react111.default.createElement(
652947
+ Box_default,
652948
+ { paddingX: 1, marginTop: 1 },
652949
+ import_react111.default.createElement(Text, { color: theme14.colors.menuSecondary, dimColor: true }, t.fileList.noFilesFound)
652950
+ );
652951
+ }
652952
+ return import_react111.default.createElement(
652953
+ Box_default,
652954
+ { paddingX: 1, marginTop: 1, flexDirection: "column" },
652955
+ import_react111.default.createElement(
652956
+ Box_default,
652957
+ { marginBottom: 1 },
652958
+ import_react111.default.createElement(Text, { color: theme14.colors.menuInfo, bold: true }, t.fileList.workspaceFilterHint.replace("{filter}", query.slice(1) || "*"))
652959
+ ),
652960
+ wsWindow.map((item, index) => {
652961
+ const isSelected = index === wsSelectedIndex;
652962
+ return import_react111.default.createElement(
652963
+ Text,
652964
+ { key: `${item.sourceDir}::${item.path}`, backgroundColor: isSelected ? theme14.colors.menuSelected : void 0, color: isSelected ? theme14.colors.menuNormal : theme14.colors.warning, wrap: "truncate-end" },
652965
+ isSelected ? "\u276F " : " ",
652966
+ "\u25C7 ",
652967
+ item.name
652968
+ );
652969
+ }),
652970
+ wsItems.length > effectiveMaxItems && import_react111.default.createElement(
652971
+ Box_default,
652972
+ { marginTop: 1 },
652973
+ import_react111.default.createElement(
652974
+ Text,
652975
+ { color: theme14.colors.menuSecondary, dimColor: true },
652976
+ t.commandPanel.scrollHint,
652977
+ t.commandPanel.moreBelow.replace("{count}", (wsItems.length - effectiveMaxItems).toString())
652978
+ )
652979
+ )
652980
+ );
652981
+ }
652609
652982
  if (isAgentMode) {
652610
652983
  if (isAgentSearching && displayItems.length === 0) {
652611
652984
  const agentSearchStatus = t.fileList.agentSearching.replace("{round}", String(agentRound || 1));
@@ -652641,12 +653014,12 @@ var init_FileList = __esm({
652641
653014
  );
652642
653015
  }
652643
653016
  }
652644
- const stillSearching = isLoading || isIncreasingDepth || query.trim().length > 0 && hasMoreDepth;
653017
+ const stillSearching = isLoading || isIncreasingDepth || normalizedQuery.trim().length > 0 && hasMoreDepth;
652645
653018
  if (!isAgentMode && stillSearching && displayItems.length === 0) {
652646
653019
  return import_react111.default.createElement(
652647
653020
  Box_default,
652648
653021
  { paddingX: 1, marginTop: 1 },
652649
- import_react111.default.createElement(Text, { color: "blue", dimColor: true }, isIncreasingDepth || query.trim().length > 0 && hasMoreDepth ? t.fileList.searchingDeeper.replace("{depth}", searchDepth.toString()) : t.fileList.loadingFiles)
653022
+ import_react111.default.createElement(Text, { color: "blue", dimColor: true }, isIncreasingDepth || normalizedQuery.trim().length > 0 && hasMoreDepth ? t.fileList.searchingDeeper.replace("{depth}", searchDepth.toString()) : t.fileList.loadingFiles)
652650
653023
  );
652651
653024
  }
652652
653025
  if (displayItems.length === 0) {
@@ -652670,6 +653043,11 @@ var init_FileList = __esm({
652670
653043
  displayItems.length > effectiveMaxItems && `(${normalizedSelectedIndex + 1}/${displayItems.length})`
652671
653044
  )
652672
653045
  ),
653046
+ workspaceFilter && !isWorkspaceSelectionMode && import_react111.default.createElement(
653047
+ Box_default,
653048
+ null,
653049
+ import_react111.default.createElement(Text, { color: theme14.colors.menuInfo, bold: true }, t.fileList.workspaceFilterHint.replace("{filter}", getSourceDirName(workspaceFilter)))
653050
+ ),
652673
653051
  filteredFiles.map((item, index) => {
652674
653052
  const file2 = item.file;
652675
653053
  const isSelected = index === displaySelectedIndex;
@@ -653826,7 +654204,7 @@ function ChatInput({ onSubmit, onCommand, placeholder = "Type your message...",
653826
654204
  const options3 = getCommandArgsOptions(cmd, text2);
653827
654205
  return { commandName: cmd, options: options3 };
653828
654206
  }, [buffer, buffer.text]);
653829
- const { showFilePicker, setShowFilePicker, fileSelectedIndex, setFileSelectedIndex, fileQuery, setFileQuery, atSymbolPosition, setAtSymbolPosition, filteredFileCount, searchMode, updateFilePickerState, handleFileSelect, handleMultipleFileSelect, handleFilteredCountChange, fileListRef } = useFilePicker(buffer, triggerUpdate);
654207
+ const { showFilePicker, setShowFilePicker, fileSelectedIndex, setFileSelectedIndex, fileQuery, setFileQuery, atSymbolPosition, setAtSymbolPosition, filteredFileCount, searchMode, workspaceFilter, updateFilePickerState, handleFileSelect, handleMultipleFileSelect, handleFilteredCountChange, fileListRef } = useFilePicker(buffer, triggerUpdate);
653830
654208
  const { showHistoryMenu, setShowHistoryMenu, historySelectedIndex, setHistorySelectedIndex, escapeKeyCount, setEscapeKeyCount, escapeKeyTimer, getUserMessages, handleHistorySelect, currentHistoryIndex, navigateHistoryUp, navigateHistoryDown, resetHistoryNavigation, saveToHistory } = useHistoryNavigation(buffer, triggerUpdate, chatHistory, onHistorySelect);
653831
654209
  const { showAgentPicker, setShowAgentPicker, agentSelectedIndex, setAgentSelectedIndex, updateAgentPickerState, getFilteredAgents, handleAgentSelect } = useAgentPicker(buffer, triggerUpdate);
653832
654210
  const { showTodoPicker, setShowTodoPicker, todoSelectedIndex, setTodoSelectedIndex, todos, selectedTodos, toggleTodoSelection, confirmTodoSelection, isLoading: todoIsLoading, searchQuery: todoSearchQuery, setSearchQuery: setTodoSearchQuery, totalTodoCount } = useTodoPicker(buffer, triggerUpdate, process.cwd());
@@ -654345,7 +654723,7 @@ function ChatInput({ onSubmit, onCommand, placeholder = "Type your message...",
654345
654723
  import_react120.default.createElement(
654346
654724
  import_react120.Suspense,
654347
654725
  { fallback: null },
654348
- import_react120.default.createElement(FileList2, { ref: fileListRef, query: fileQuery, selectedIndex: fileSelectedIndex, visible: showFilePicker, maxItems: 10, rootPath: process.cwd(), onFilteredCountChange: handleFilteredCountChange, searchMode })
654726
+ import_react120.default.createElement(FileList2, { ref: fileListRef, query: fileQuery, selectedIndex: fileSelectedIndex, visible: showFilePicker, maxItems: 10, rootPath: process.cwd(), onFilteredCountChange: handleFilteredCountChange, searchMode, workspaceFilter })
654349
654727
  ),
654350
654728
  import_react120.default.createElement(
654351
654729
  import_react120.Suspense,
@@ -655067,7 +655445,8 @@ function StatusLine({ yoloMode = false, planMode = false, vulnerabilityHuntingMo
655067
655445
  speedometer: {
655068
655446
  enabled: tpsTracker.isActive(),
655069
655447
  tps: tpsSnapshot.tps,
655070
- peakTps: tpsSnapshot.peakTps
655448
+ peakTps: tpsSnapshot.peakTps,
655449
+ ttftMs: tpsSnapshot.ttftMs
655071
655450
  }
655072
655451
  }
655073
655452
  };
@@ -655291,8 +655670,13 @@ function StatusLine({ yoloMode = false, planMode = false, vulnerabilityHuntingMo
655291
655670
  });
655292
655671
  }
655293
655672
  if (tpsTracker.isActive() && !isBuiltinOverridden(BUILTIN_STATUSLINE_IDS.speedometer)) {
655673
+ let speedometerText = `\u23F1 ${tpsSnapshot.tps} tok/s`;
655674
+ if (tpsSnapshot.ttftMs !== null) {
655675
+ const ttftSec = (tpsSnapshot.ttftMs / 1e3).toFixed(1);
655676
+ speedometerText += ` \xB7 ttft ${ttftSec}s`;
655677
+ }
655294
655678
  statusItems.push({
655295
- text: `\u23F1 ${tpsSnapshot.tps} tok/s`,
655679
+ text: speedometerText,
655296
655680
  color: tpsSnapshot.tps > 0 ? theme14.colors.cyan : theme14.colors.menuSecondary
655297
655681
  });
655298
655682
  }
@@ -655356,7 +655740,18 @@ function StatusLine({ yoloMode = false, planMode = false, vulnerabilityHuntingMo
655356
655740
  import_react123.default.createElement(Text, { color: tpsSnapshot.tps > 0 ? theme14.colors.cyan : theme14.colors.menuSecondary, bold: true }, tpsSnapshot.tps),
655357
655741
  " tok/s",
655358
655742
  " \xB7 peak ",
655359
- import_react123.default.createElement(Text, { color: theme14.colors.warning }, tpsSnapshot.peakTps)
655743
+ import_react123.default.createElement(Text, { color: theme14.colors.warning }, tpsSnapshot.peakTps),
655744
+ tpsSnapshot.ttftMs !== null && import_react123.default.createElement(
655745
+ import_react123.default.Fragment,
655746
+ null,
655747
+ " \xB7 ttft ",
655748
+ import_react123.default.createElement(
655749
+ Text,
655750
+ { color: theme14.colors.menuInfo },
655751
+ (tpsSnapshot.ttftMs / 1e3).toFixed(1),
655752
+ "s"
655753
+ )
655754
+ )
655360
655755
  )
655361
655756
  ),
655362
655757
  yoloMode && !isBuiltinOverridden(BUILTIN_STATUSLINE_IDS.modeYolo) && import_react123.default.createElement(
@@ -655656,8 +656051,11 @@ function LoadingIndicator({ isStreaming, isStopping, isSaving, isCompressing, is
655656
656051
  ].join("|");
655657
656052
  const previousStreamActivityMarkerRef = (0, import_react126.useRef)(null);
655658
656053
  const lastStreamActivityElapsedSecondsRef = (0, import_react126.useRef)(elapsedSeconds);
656054
+ const wasStreamingRef = (0, import_react126.useRef)(false);
656055
+ const isStreamingStarted = isStreaming && !wasStreamingRef.current;
656056
+ wasStreamingRef.current = isStreaming;
655659
656057
  const shouldIgnoreStreamDelay = isCompressing || isAutoCompressing;
655660
- if (!isStreaming || shouldIgnoreStreamDelay || previousStreamActivityMarkerRef.current !== streamActivityMarker) {
656058
+ if (!isStreaming || shouldIgnoreStreamDelay || isStreamingStarted || previousStreamActivityMarkerRef.current !== streamActivityMarker) {
655661
656059
  previousStreamActivityMarkerRef.current = streamActivityMarker;
655662
656060
  lastStreamActivityElapsedSecondsRef.current = elapsedSeconds;
655663
656061
  }
@@ -659284,6 +659682,32 @@ function SkillsListPanel({ onClose }) {
659284
659682
  }
659285
659683
  return `${description.slice(0, NON_FOCUSED_SKILL_DESC_MAX_LEN - 3)}...`;
659286
659684
  };
659685
+ const { columns } = useTerminalSize();
659686
+ const panelContentWidth = Math.max(1, columns - 6);
659687
+ const wrapTextToWidth = (0, import_react134.useCallback)((text2, maxWidth) => {
659688
+ if (!text2)
659689
+ return [""];
659690
+ const chars = [...text2];
659691
+ const result2 = [];
659692
+ let current = "";
659693
+ let currentWidth = 0;
659694
+ for (const ch of chars) {
659695
+ const chWidth = Math.max(1, visualWidth(ch));
659696
+ if (currentWidth + chWidth > maxWidth) {
659697
+ result2.push(current || " ");
659698
+ current = ch;
659699
+ currentWidth = chWidth;
659700
+ } else {
659701
+ current += ch;
659702
+ currentWidth += chWidth;
659703
+ }
659704
+ }
659705
+ if (current.length > 0) {
659706
+ result2.push(current);
659707
+ }
659708
+ return result2.length > 0 ? result2 : [""];
659709
+ }, []);
659710
+ const wrappedUpdateMessage = (0, import_react134.useMemo)(() => updateMessage ? wrapTextToWidth(updateMessage, panelContentWidth) : [], [updateMessage, wrapTextToWidth, panelContentWidth]);
659287
659711
  const handleUpdate = (0, import_react134.useCallback)(async () => {
659288
659712
  var _a21, _b15, _c7, _d5, _e3, _f2;
659289
659713
  if (updateStatus === "updating")
@@ -659435,11 +659859,7 @@ function SkillsListPanel({ onClose }) {
659435
659859
  Box_default,
659436
659860
  { flexDirection: "column" },
659437
659861
  import_react134.default.createElement(Text, { color: theme14.colors.menuSecondary, dimColor: true }, ((_c6 = t.skillsListPanel) == null ? void 0 : _c6.noSkills) || "No skills available"),
659438
- updateStatus !== "idle" && updateMessage && import_react134.default.createElement(
659439
- Box_default,
659440
- { marginTop: 1 },
659441
- import_react134.default.createElement(Text, { color: updateStatus === "error" ? theme14.colors.error : updateStatus === "updating" ? theme14.colors.warning : theme14.colors.success }, updateMessage)
659442
- ),
659862
+ updateStatus !== "idle" && updateMessage && import_react134.default.createElement(Box_default, { marginTop: 1, flexDirection: "column" }, wrappedUpdateMessage.map((line, i) => import_react134.default.createElement(Text, { key: i, color: updateStatus === "error" ? theme14.colors.error : updateStatus === "updating" ? theme14.colors.warning : theme14.colors.success }, line))),
659443
659863
  import_react134.default.createElement(
659444
659864
  Box_default,
659445
659865
  { marginTop: 1 },
@@ -659499,16 +659919,15 @@ function SkillsListPanel({ onClose }) {
659499
659919
  );
659500
659920
  }),
659501
659921
  hiddenBelowCount > 0 && import_react134.default.createElement(Text, { color: theme14.colors.menuSecondary, dimColor: true }, (((_g = t.skillsListPanel) == null ? void 0 : _g.moreBelow) || "\u2193 {count} more below").replace("{count}", String(hiddenBelowCount))),
659502
- updateStatus !== "idle" && updateMessage && import_react134.default.createElement(
659503
- Box_default,
659504
- { marginTop: 1 },
659505
- import_react134.default.createElement(
659922
+ updateStatus !== "idle" && updateMessage && import_react134.default.createElement(Box_default, { marginTop: 1, flexDirection: "column" }, wrappedUpdateMessage.map((line, i) => {
659923
+ const prefix = i === 0 ? updateStatus === "updating" ? "\u27F3 " : updateStatus === "done" ? "\u2713 " : "\u2717 " : "";
659924
+ return import_react134.default.createElement(
659506
659925
  Text,
659507
- { color: updateStatus === "error" ? theme14.colors.error : updateStatus === "updating" ? theme14.colors.warning : theme14.colors.success },
659508
- updateStatus === "updating" ? "\u27F3 " : updateStatus === "done" ? "\u2713 " : "\u2717 ",
659509
- updateMessage
659510
- )
659511
- ),
659926
+ { key: i, color: updateStatus === "error" ? theme14.colors.error : updateStatus === "updating" ? theme14.colors.warning : theme14.colors.success },
659927
+ prefix,
659928
+ line
659929
+ );
659930
+ })),
659512
659931
  import_react134.default.createElement(
659513
659932
  Box_default,
659514
659933
  { marginTop: 1 },
@@ -659525,6 +659944,8 @@ var init_SkillsListPanel = __esm({
659525
659944
  await init_src();
659526
659945
  init_ThemeContext();
659527
659946
  init_I18nContext();
659947
+ init_useTerminalSize();
659948
+ init_textUtils();
659528
659949
  init_disabledSkills();
659529
659950
  init_githubSkillInstaller();
659530
659951
  UPDATE_TIMEOUT_MS = 12e4;
@@ -660030,14 +660451,15 @@ function useMessageProcessing(props) {
660030
660451
  (0, import_react138.useEffect)(() => {
660031
660452
  hasFocusRef.current = hasFocus ?? true;
660032
660453
  }, [hasFocus]);
660033
- const appendAiCompletionTimeMessage2 = () => {
660454
+ const appendAiCompletionTimeMessage2 = (durationMs) => {
660034
660455
  setMessages((prev) => [
660035
660456
  ...prev,
660036
660457
  {
660037
660458
  role: "assistant",
660038
660459
  content: "",
660039
660460
  streaming: false,
660040
- aiCompletionTime: /* @__PURE__ */ new Date()
660461
+ aiCompletionTime: /* @__PURE__ */ new Date(),
660462
+ aiCompletionDurationMs: typeof durationMs === "number" && Number.isFinite(durationMs) && durationMs >= 0 ? durationMs : void 0
660041
660463
  }
660042
660464
  ]);
660043
660465
  };
@@ -660048,6 +660470,7 @@ function useMessageProcessing(props) {
660048
660470
  };
660049
660471
  const processMessage = async (message, images, useBasicModel, hideUserMessage) => {
660050
660472
  var _a20, _b14, _c6, _d4, _e2, _f, _g, _h;
660473
+ const turnStartTime = Date.now();
660051
660474
  const autoCompressConfig = getSnowConfig();
660052
660475
  if (autoCompressConfig.enableAutoCompress !== false && shouldAutoCompress(currentContextPercentageRef.current, autoCompressConfig.autoCompressThreshold ?? DEFAULT_AUTO_COMPRESS_THRESHOLD)) {
660053
660476
  setIsCompressing(true);
@@ -660308,7 +660731,7 @@ ${continuationPrompt}` : continuationPrompt;
660308
660731
  streamingState.setIsStopping(false);
660309
660732
  }
660310
660733
  if (!wasCutInterrupt) {
660311
- appendAiCompletionTimeMessage2();
660734
+ appendAiCompletionTimeMessage2(Date.now() - turnStartTime);
660312
660735
  }
660313
660736
  streamingState.setIsStreaming(false);
660314
660737
  streamingState.setAbortController(null);
@@ -660507,6 +660930,7 @@ ${messageWithoutTargets}`);
660507
660930
  const pendingMessages = pendingMessagesRef.current;
660508
660931
  if (pendingMessages.length === 0)
660509
660932
  return;
660933
+ const turnStartTime = Date.now();
660510
660934
  streamingState.setRetryStatus(null);
660511
660935
  const messagesToProcess = [...pendingMessages];
660512
660936
  setPendingMessages([]);
@@ -660662,7 +661086,7 @@ ${messageWithoutTargets}`);
660662
661086
  userInterruptedRef.current = false;
660663
661087
  streamingState.setIsStopping(false);
660664
661088
  }
660665
- appendAiCompletionTimeMessage2();
661089
+ appendAiCompletionTimeMessage2(Date.now() - turnStartTime);
660666
661090
  streamingState.setIsStreaming(false);
660667
661091
  streamingState.setAbortController(null);
660668
661092
  streamingState.setStreamTokenCount(0);
@@ -660796,6 +661220,8 @@ function useRollback(props) {
660796
661220
  snapshotState.setPendingRollback(null);
660797
661221
  return;
660798
661222
  }
661223
+ streamingState.setContextUsage(null);
661224
+ currentContextPercentageRef.current = 0;
660799
661225
  if (currentSession) {
660800
661226
  const messagesAfterSelected = messages.slice(selectedIndex);
660801
661227
  const uiUserMessagesToDelete = messagesAfterSelected.filter((msg) => msg.role === "user").length;
@@ -660884,6 +661310,7 @@ function useRollback(props) {
660884
661310
  clearSavedMessages();
660885
661311
  setMessages(uiMessages);
660886
661312
  streamingState.setContextUsage(originalSession.contextUsage ?? null);
661313
+ currentContextPercentageRef.current = 0;
660887
661314
  const snapshots = await hashBasedSnapshotManager.listSnapshots(originalSession.id);
660888
661315
  const counts = /* @__PURE__ */ new Map();
660889
661316
  for (const snapshot of snapshots) {
@@ -660911,8 +661338,6 @@ function useRollback(props) {
660911
661338
  }
660912
661339
  };
660913
661340
  const handleHistorySelect = async (selectedIndex, message, images) => {
660914
- streamingState.setContextUsage(null);
660915
- currentContextPercentageRef.current = 0;
660916
661341
  const currentSession = sessionManager.getCurrentSession();
660917
661342
  if (!currentSession)
660918
661343
  return;
@@ -664409,12 +664834,14 @@ var init_ThinkingStatus = __esm({
664409
664834
  // dist/ui/pages/chatScreen/ChatScreenConversationView.js
664410
664835
  function ChatScreenConversationView({ remountKey, terminalWidth, workingDirectory, simpleMode, messages, showThinking, toolDisplayMode, thinkDisplayMode, pendingMessages, pendingToolConfirmation, pendingUserQuestion, bashSensitiveCommand, terminalExecutionState, schedulerExecutionState, customCommandExecution, bashMode, hookError, handleUserQuestionAnswer, setHookError, compressionStatus, thinkingStatus }) {
664411
664836
  var _a20, _b14;
664837
+ const staticMessages = (0, import_react156.useMemo)(() => messages.filter((m) => !m.streaming), [messages]);
664838
+ const { isFirstInGroup, isLastInGroup } = (0, import_react156.useMemo)(() => computeParallelGroupEdges(staticMessages), [staticMessages]);
664412
664839
  return import_react156.default.createElement(
664413
664840
  import_react156.default.Fragment,
664414
664841
  null,
664415
664842
  import_react156.default.createElement(Static, { key: remountKey, items: [
664416
664843
  import_react156.default.createElement(ChatHeader, { key: "header", terminalWidth, simpleMode, workingDirectory }),
664417
- ...messages.filter((m) => !m.streaming).map((message, index, filteredMessages) => import_react156.default.createElement(MessageRenderer, { key: `msg-${index}`, message, index, filteredMessages, terminalWidth, showThinking, toolDisplayMode, thinkDisplayMode }))
664844
+ ...staticMessages.map((message, index) => import_react156.default.createElement(MessageRenderer_default, { key: `msg-${index}`, message, terminalWidth, isFirstInGroup: isFirstInGroup[index], isLastInGroup: isLastInGroup[index], showThinking, toolDisplayMode, thinkDisplayMode }))
664418
664845
  ] }, (item) => item),
664419
664846
  import_react156.default.createElement(
664420
664847
  Box_default,
@@ -664990,7 +665417,7 @@ var init_SkillsCreationPanel = __esm({
664990
665417
  init_ThemeContext();
664991
665418
  init_I18nContext();
664992
665419
  init_skills2();
664993
- SkillsCreationPanel = ({ onSave, onCancel, projectRoot }) => {
665420
+ SkillsCreationPanel = ({ onSave, onCancel, onInstall, projectRoot }) => {
664994
665421
  const { theme: theme14 } = useTheme();
664995
665422
  const { t } = useI18n();
664996
665423
  const [step, setStep] = (0, import_react158.useState)("mode");
@@ -665150,6 +665577,8 @@ var init_SkillsCreationPanel = __esm({
665150
665577
  setDescription("");
665151
665578
  setGenerated(void 0);
665152
665579
  setStep("ai-requirement");
665580
+ } else if (input2.toLowerCase() === "i" && onInstall) {
665581
+ onInstall();
665153
665582
  }
665154
665583
  return;
665155
665584
  }
@@ -665240,6 +665669,17 @@ var init_SkillsCreationPanel = __esm({
665240
665669
  " ",
665241
665670
  t.skillsCreation.modeManual
665242
665671
  )
665672
+ ),
665673
+ onInstall && import_react158.default.createElement(
665674
+ Box_default,
665675
+ null,
665676
+ import_react158.default.createElement(Text, { color: theme14.colors.menuInfo, bold: true }, "[I]"),
665677
+ import_react158.default.createElement(
665678
+ Text,
665679
+ { color: theme14.colors.text },
665680
+ " ",
665681
+ t.skillsCreation.modeInstall
665682
+ )
665243
665683
  )
665244
665684
  ),
665245
665685
  import_react158.default.createElement(
@@ -670844,7 +671284,10 @@ function PanelsManager({ terminalWidth, workingDirectory, showSessionPanel, show
670844
671284
  showSkillsCreation && import_react175.default.createElement(
670845
671285
  Box_default,
670846
671286
  { paddingX: 1, flexDirection: "column", width: terminalWidth },
670847
- import_react175.default.createElement(SkillsCreationPanel, { projectRoot: workingDirectory, onSave: onSkillsSave, onCancel: () => setShowSkillsCreation(false) })
671287
+ import_react175.default.createElement(SkillsCreationPanel, { projectRoot: workingDirectory, onSave: onSkillsSave, onCancel: () => setShowSkillsCreation(false), onInstall: () => {
671288
+ setShowSkillsCreation(false);
671289
+ setShowSkillsInstall(true);
671290
+ } })
670848
671291
  ),
670849
671292
  showSkillsInstall && import_react175.default.createElement(
670850
671293
  Box_default,
@@ -679186,7 +679629,7 @@ __export(daemonLogger_exports, {
679186
679629
  DaemonLogger: () => DaemonLogger
679187
679630
  });
679188
679631
  import { existsSync as existsSync47, statSync as statSync2, renameSync as renameSync2, writeFileSync as writeFileSync25, appendFileSync as appendFileSync2, mkdirSync as mkdirSync24 } from "fs";
679189
- import { join as join51, dirname as dirname12, basename as basename8 } from "path";
679632
+ import { join as join51, dirname as dirname13, basename as basename9 } from "path";
679190
679633
  var DaemonLogger;
679191
679634
  var init_daemonLogger = __esm({
679192
679635
  "dist/utils/sse/daemonLogger.js"() {
@@ -679220,7 +679663,7 @@ var init_daemonLogger = __esm({
679220
679663
  * 确保日志目录和归档目录存在
679221
679664
  */
679222
679665
  ensureLogDirectory() {
679223
- const logDir = dirname12(this.logFilePath);
679666
+ const logDir = dirname13(this.logFilePath);
679224
679667
  const archiveDir = join51(logDir, "archive");
679225
679668
  if (!existsSync47(logDir)) {
679226
679669
  mkdirSync24(logDir, { recursive: true });
@@ -679276,8 +679719,8 @@ var init_daemonLogger = __esm({
679276
679719
  * 归档到 archive/YYYY-MM-DD/ 目录下
679277
679720
  */
679278
679721
  rotate() {
679279
- const logDir = dirname12(this.logFilePath);
679280
- const logFileName = basename8(this.logFilePath);
679722
+ const logDir = dirname13(this.logFilePath);
679723
+ const logFileName = basename9(this.logFilePath);
679281
679724
  const dateDir = this.getDateDirectory();
679282
679725
  const archiveDateDir = join51(logDir, "archive", dateDir);
679283
679726
  if (!existsSync47(archiveDateDir)) {
@@ -692626,7 +693069,7 @@ var require_package4 = __commonJS({
692626
693069
  "package.json"(exports2, module2) {
692627
693070
  module2.exports = {
692628
693071
  name: "snow-ai",
692629
- version: "0.8.8",
693072
+ version: "0.8.10",
692630
693073
  description: "Agentic coding in your terminal",
692631
693074
  license: "MIT",
692632
693075
  bin: {
@@ -694860,7 +695303,7 @@ ${heading2(t.summary)}: ${success2(formatTemplate(t.summaryOk, { count: okCount
694860
695303
  // dist/cli.js
694861
695304
  import { readFileSync as readFileSync34 } from "fs";
694862
695305
  import { join as join52 } from "path";
694863
- import { fileURLToPath as fileURLToPath6 } from "url";
695306
+ import { fileURLToPath as fileURLToPath7 } from "url";
694864
695307
 
694865
695308
  // dist/utils/config/legacyConfigMigration.js
694866
695309
  init_unifiedSettings();
@@ -695168,7 +695611,7 @@ try {
695168
695611
  runLegacyConfigMigration();
695169
695612
  } catch {
695170
695613
  }
695171
- var __dirname2 = fileURLToPath6(new URL(".", import.meta.url));
695614
+ var __dirname2 = fileURLToPath7(new URL(".", import.meta.url));
695172
695615
  var packageJson = JSON.parse(readFileSync34(join52(__dirname2, "../package.json"), "utf-8"));
695173
695616
  var VERSION4 = packageJson.version;
695174
695617
  async function loadDependencies() {