nolo-cli 0.25.2 → 0.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +9 -18
  2. package/{_executeModel-LXNDVFT2.js → _executeModel-ZPNYAEFW.js} +18 -18
  3. package/{agentDeleteCommand-DMAYEVOP.js → agentDeleteCommand-5ZV4433K.js} +12 -12
  4. package/{agentEmailCommands-RVGRDAD6.js → agentEmailCommands-Z7KOYDVQ.js} +23 -23
  5. package/{agentListCommands-SMW3NENV.js → agentListCommands-UQUXJYUN.js} +14 -14
  6. package/{agentMachineCommands-VGE5A52U.js → agentMachineCommands-53O6P6L5.js} +12 -12
  7. package/{agentRecordCommands-UHFL5OLB.js → agentRecordCommands-ZRYNBSSS.js} +22 -22
  8. package/{agentRunCommand-GG4Z735K.js → agentRunCommand-B73MKVOG.js} +22 -22
  9. package/{agentRuntimeLocal-7N2SUWO2.js → agentRuntimeLocal-GVNERRKQ.js} +11 -9
  10. package/{agentSlice-WY7SEYXO.js → agentSlice-OJBHIL34.js} +1 -1
  11. package/{appDeleteCommands-AUC7KDHU.js → appDeleteCommands-23Z3Z6KE.js} +13 -13
  12. package/{appDeployCommands-OVYWXTNP.js → appDeployCommands-3MFAR4Z7.js} +13 -13
  13. package/{appDeployStatusCommands-DNUCH3KK.js → appDeployStatusCommands-JHU6GSN4.js} +13 -13
  14. package/{appGetCommands-4DLM2P37.js → appGetCommands-24J55H2Y.js} +13 -13
  15. package/{appListCommands-CL4VLCZW.js → appListCommands-HE5KP3PH.js} +13 -13
  16. package/{authCommand-W2BDNL4D.js → authCommand-KGRK6MNU.js} +8 -8
  17. package/{authCommands-NYZM2B2I.js → authCommands-JSOG2H4E.js} +2 -2
  18. package/{chunk-OBO5YB35.js → chunk-5DWZ46RJ.js} +1 -1
  19. package/{chunk-E2VQTGUO.js → chunk-5EDKWSQN.js} +8 -8
  20. package/{chunk-B6RCQ4BM.js → chunk-AAWJ5S3G.js} +1 -1
  21. package/{chunk-THN2YFSR.js → chunk-ADE6577S.js} +62 -17
  22. package/{chunk-SDDOGQ6M.js → chunk-AOPOTHFK.js} +1 -1
  23. package/{chunk-OTIS3VY6.js → chunk-AZW5AHMW.js} +1 -1
  24. package/{chunk-7HD7MCCZ.js → chunk-CV6BM7LU.js} +1 -1
  25. package/{chunk-ACBCDO2E.js → chunk-CWTT2NZ6.js} +2 -2
  26. package/{chunk-OHK3HE4G.js → chunk-CZHE6LLV.js} +74 -11
  27. package/{chunk-35RYGII3.js → chunk-FXFGNOT2.js} +67 -1
  28. package/{chunk-T3EOQH72.js → chunk-G36SUBHA.js} +14 -4
  29. package/{chunk-QJZJW65A.js → chunk-GD23ZX7Z.js} +3 -3
  30. package/{chunk-DXJS7VSG.js → chunk-GE6IWA5N.js} +9 -2
  31. package/{chunk-P5AVCQF3.js → chunk-GGB6MPHD.js} +19 -18
  32. package/{chunk-NZXRTSOY.js → chunk-GNGOZMU2.js} +2 -2
  33. package/{chunk-6NUG4BJE.js → chunk-J2WT5CEO.js} +1 -1
  34. package/{chunk-XJBAAOKS.js → chunk-JJ2WUBFN.js} +1 -1
  35. package/{chunk-ONGWRXVA.js → chunk-KURQBS7S.js} +1 -1
  36. package/{chunk-J6MEBHAT.js → chunk-LEHTC2FI.js} +1 -1
  37. package/{chunk-6OMNSBFW.js → chunk-LLDGWLML.js} +8 -8
  38. package/{chunk-MSBHAQVV.js → chunk-MCXQNEJ3.js} +1 -1
  39. package/{chunk-WV3WZRYZ.js → chunk-P3RZ6DHN.js} +74 -15
  40. package/{chunk-5IIJMMC3.js → chunk-PMCKFQYC.js} +1 -1
  41. package/{chunk-UTADKKM7.js → chunk-PTKI7TIN.js} +101 -23
  42. package/{chunk-5UI2CDQG.js → chunk-PXPISYEH.js} +14 -9
  43. package/{chunk-LWHK7TZR.js → chunk-PY7VGC5M.js} +24 -5
  44. package/{chunk-C4JWF4EX.js → chunk-RM464B7I.js} +2 -2
  45. package/{chunk-2KPE5HQM.js → chunk-S7AV3NCK.js} +47 -14
  46. package/{chunk-5TAM6OX3.js → chunk-SIUEKVK4.js} +136 -41
  47. package/{chunk-XR6PNQ3N.js → chunk-TLYHUIWF.js} +3 -3
  48. package/{chunk-RRJD2ZUV.js → chunk-TNM27YZ7.js} +3 -3
  49. package/{chunk-J3HWN4B5.js → chunk-TWA4L7J7.js} +1 -1
  50. package/{chunk-UZH44DWK.js → chunk-WCP5FDTF.js} +13 -20
  51. package/{chunk-4POUK2BV.js → chunk-WSQLK2KR.js} +1 -1
  52. package/{chunk-OMWJXZSZ.js → chunk-XNZJVYFS.js} +1 -1
  53. package/{chunk-KF3VWOQ6.js → chunk-YJY7HODU.js} +1 -1
  54. package/{chunk-DZNONG7L.js → chunk-ZFL3LTU7.js} +2 -2
  55. package/{createAgentAutomationAction-B5G57KMG.js → createAgentAutomationAction-PO62NUR7.js} +6 -6
  56. package/{createDialogAction-SYKO3ACQ.js → createDialogAction-ORFRYI3C.js} +7 -7
  57. package/{createPageAction-UBO6CXTT.js → createPageAction-XWVMNTYH.js} +6 -6
  58. package/{dialogCommands-FQPSK7QE.js → dialogCommands-XTJHROXM.js} +13 -13
  59. package/{dialogSlice-OFGPXYFS.js → dialogSlice-DJXC53YW.js} +6 -6
  60. package/{docCreateCommands-ELKBZBHI.js → docCreateCommands-T2XRVXYS.js} +12 -12
  61. package/{docDeleteCommands-R6X3FKHX.js → docDeleteCommands-L7RXFXY3.js} +13 -13
  62. package/{docReadCommands-QNVUXQNM.js → docReadCommands-M5PYNADQ.js} +12 -12
  63. package/{docStore-WFMCDOGV.js → docStore-6LKLLFDW.js} +7 -7
  64. package/{docUpdateCommands-OOR4CWYI.js → docUpdateCommands-OA5EGPLQ.js} +12 -12
  65. package/{getPricing-ZOASM7TQ.js → getPricing-6C3C47Y4.js} +3 -3
  66. package/{handleSendMessageAction-R3AP5MQY.js → handleSendMessageAction-ILFGZTN5.js} +6 -6
  67. package/index.js +68 -68
  68. package/{machineCommands-FPZ2UVCS.js → machineCommands-AKAQGPAO.js} +21 -21
  69. package/{machineWsRunDispatch-XAVKPZLL.js → machineWsRunDispatch-RSBERM64.js} +21 -21
  70. package/{models-DUNBMXRQ.js → models-ILWKIX2Y.js} +2 -2
  71. package/package.json +1 -1
  72. package/{readlineWorkspace-O3D2LRYG.js → readlineWorkspace-TUH3SFHO.js} +112 -62
  73. package/{runAgentClientLoop-UWNABHIZ.js → runAgentClientLoop-C3QB2EXV.js} +15 -15
  74. package/{spaceCommands-L6R7DD2L.js → spaceCommands-SXYOFGUJ.js} +12 -12
  75. package/{spaceSlice-2UQAI6GT.js → spaceSlice-6BHMRP5O.js} +6 -6
  76. package/{streamAgentChatTurn-SS62OWZZ.js → streamAgentChatTurn-GF5W5OIP.js} +18 -18
  77. package/{tableCommands-HEQYT2KP.js → tableCommands-QSZILI7I.js} +1 -1
  78. package/{tools-NVSLAOK4.js → tools-KBCLJ43G.js} +11 -11
  79. package/{tuiSummaryLlmCaller-A7OO23I4.js → tuiSummaryLlmCaller-ARIMGILF.js} +4 -4
  80. package/{updateCommands-HTCOBXCA.js → updateCommands-AK2RDOFR.js} +8 -2
  81. package/{updateDialogTitleAction-WMWZQ764.js → updateDialogTitleAction-LMHZUY4Q.js} +6 -6
@@ -4,10 +4,10 @@ import {
4
4
  providerHttpFailure,
5
5
  readSseFrames,
6
6
  throwIfChatCompletionStreamFailed
7
- } from "./chunk-MSBHAQVV.js";
7
+ } from "./chunk-MCXQNEJ3.js";
8
8
  import {
9
9
  parseToolArgumentsJson
10
- } from "./chunk-WV3WZRYZ.js";
10
+ } from "./chunk-P3RZ6DHN.js";
11
11
  import {
12
12
  createThinkParserState,
13
13
  createToolCallAccumulator,
@@ -26,13 +26,13 @@ import {
26
26
  import {
27
27
  buildProviderAuthHeaders,
28
28
  buildProviderExecutionPlan
29
- } from "./chunk-5UI2CDQG.js";
29
+ } from "./chunk-PXPISYEH.js";
30
30
  import {
31
31
  NOLO_WORKSPACE_TOOL_NAMES,
32
32
  buildNoloWorkspaceCommandArgs,
33
33
  noloStringArg,
34
34
  parseNoloWorkspaceToolArguments
35
- } from "./chunk-UZH44DWK.js";
35
+ } from "./chunk-WCP5FDTF.js";
36
36
  import {
37
37
  buildDialogFallbackTitleFromUserInput
38
38
  } from "./chunk-2MBTWINN.js";
@@ -73,6 +73,44 @@ import {
73
73
  asOptionalTrimmedString
74
74
  } from "./chunk-G3SUCT4W.js";
75
75
 
76
+ // packages/agent-runtime/agentAvailability.ts
77
+ var DEFAULT_PROVIDER_RETRY_MS = 5 * 60 * 1e3;
78
+ function parseResetText(value) {
79
+ const m = value.match(/(?:resets?\s+in|retry[- ]after)\s*(?:(\d+)\s*hr)?\s*(?:(\d+)\s*min)?\s*(?:(\d+)\s*sec)?/i);
80
+ if (!m) return void 0;
81
+ return (Number(m[1] ?? 0) * 3600 + Number(m[2] ?? 0) * 60 + Number(m[3] ?? 0)) * 1e3;
82
+ }
83
+ function resolveAgentNextAvailableAt(body, now = Date.now()) {
84
+ const root = body && typeof body === "object" ? body : {};
85
+ const error = root.error && typeof root.error === "object" ? root.error : root;
86
+ const details = error.details && typeof error.details === "object" ? error.details : void 0;
87
+ const retryRaw = error.retryAfter ?? error.retry_after ?? error["Retry-After"];
88
+ if (typeof retryRaw === "number" && Number.isFinite(retryRaw)) {
89
+ return retryRaw > 1e12 ? retryRaw : now + Math.max(0, retryRaw) * 1e3;
90
+ }
91
+ if (typeof retryRaw === "string") {
92
+ const numeric = Number(retryRaw.trim());
93
+ if (Number.isFinite(numeric)) return now + Math.max(0, numeric) * 1e3;
94
+ const date = Date.parse(retryRaw);
95
+ if (Number.isFinite(date) && date > now) return date;
96
+ }
97
+ const resetRaw = error.resets_at ?? error.resetsAt ?? details?.resets_at ?? details?.resetsAt;
98
+ if (typeof resetRaw === "number" && Number.isFinite(resetRaw)) {
99
+ const absolute = resetRaw > 1e12 ? resetRaw : resetRaw * 1e3;
100
+ if (absolute > now) return absolute;
101
+ }
102
+ if (typeof resetRaw === "string") {
103
+ const parsed = Date.parse(resetRaw);
104
+ if (Number.isFinite(parsed) && parsed > now) return parsed;
105
+ }
106
+ const text = typeof body === "string" ? body : JSON.stringify(body ?? "");
107
+ return now + (parseResetText(text) ?? DEFAULT_PROVIDER_RETRY_MS);
108
+ }
109
+ function isAgentCoolingDown(agent, now = Date.now()) {
110
+ const at = agent && typeof agent === "object" ? agent.nextAvailableAt : void 0;
111
+ return typeof at === "number" && Number.isFinite(at) && at > now;
112
+ }
113
+
76
114
  // packages/agent-runtime/kimiUserAgent.ts
77
115
  var KIMI_CODE_CLI_VERSION = "0.29.2";
78
116
  var KIMI_CODE_USER_AGENT = `kimi-code-cli/${KIMI_CODE_CLI_VERSION} (nolo)`;
@@ -723,6 +761,11 @@ function shouldCacheHybridRemoteRecord(remoteRecord, localRecord) {
723
761
  if (!localRecord || typeof localRecord !== "object") return true;
724
762
  return shouldReplaceWithHybridRecord(remoteRecord, localRecord);
725
763
  }
764
+ function parseSyncServersEnv(env) {
765
+ const raw = env?.NOLO_SYNC_SERVERS?.trim();
766
+ if (!raw) return [];
767
+ return raw.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
768
+ }
726
769
  function createHybridRecordStore(deps) {
727
770
  const fetchImpl = deps.fetchImpl ?? fetch;
728
771
  return {
@@ -1438,7 +1481,8 @@ function tokenizeShellPrefix(command) {
1438
1481
  function buildWorkspacePathProperty() {
1439
1482
  return {
1440
1483
  type: "string",
1441
- description: "Path relative to the workspace root."
1484
+ minLength: 1,
1485
+ description: "Path relative to the workspace root. Required and must be non-empty for readFile/writeFile/editFile; for listFiles/searchFiles/globFiles it is optional and defaults to the workspace root when omitted."
1442
1486
  };
1443
1487
  }
1444
1488
  function buildListWorkspaceDescription(variant) {
@@ -1446,12 +1490,12 @@ function buildListWorkspaceDescription(variant) {
1446
1490
  return "List files and directories inside a workspace directory.";
1447
1491
  }
1448
1492
  if (variant === "workflow") {
1449
- return "List a bounded directory overview inside the workspace. Use first when you need to understand nearby structure, choose a subdirectory, or inspect a non-code project. Then use globFiles for path-pattern discovery, searchFiles for text/content discovery, and readFile only for the specific files or line ranges you need.";
1493
+ return "List directory overview inside workspace. Then use globFiles for path patterns, searchFiles for text discovery, and readFile for content.";
1450
1494
  }
1451
1495
  if (variant === "antiShell") {
1452
- return "List a bounded directory overview inside the workspace. Do not use execShell with ls/find/tree for normal directory overviews when listFiles can show the needed depth and limit. Use globFiles for path-pattern discovery and searchFiles for content search.";
1496
+ return "List directory overview inside workspace. Prefer listFiles over shell ls/find commands.";
1453
1497
  }
1454
- return "List a bounded directory overview inside the workspace. Use for scanning nearby structure, not for path-pattern discovery across the repo. Prefer globFiles for finding files by name/extension and searchFiles for text inside files.";
1498
+ return "List files and directories inside a workspace folder. Defaults to shallow overview (depth 1).";
1455
1499
  }
1456
1500
  function buildListWorkspaceParameters(variant) {
1457
1501
  const path = buildWorkspacePathProperty();
@@ -1508,18 +1552,18 @@ function buildReadWorkspaceDescription(variant) {
1508
1552
  return "Read a UTF-8 text file inside the workspace.";
1509
1553
  }
1510
1554
  if (variant === "workflow") {
1511
- return 'Read a UTF-8 text file inside the workspace after listFiles, globFiles, or searchFiles has narrowed the target. Use lines with a range from searchFiles matches, or lines: "-50" for logs and generated output. Read the whole file only when the task truly needs all content or exact edit context.';
1555
+ return 'Read a UTF-8 text file inside the workspace. Use lines with a range from searchFiles matches, or lines: "-50" for logs. Read the whole file only when the task needs all content.';
1512
1556
  }
1513
1557
  if (variant === "antiShell") {
1514
- return "Read a UTF-8 text file inside the workspace. Do not use execShell with cat/sed/head/tail for normal text reads when readFile can return the needed file or line range. Use searchFiles first for content search, then readFile only the relevant lines when possible.";
1558
+ return "Read a UTF-8 text file inside the workspace. Prefer readFile over shell commands (cat/head/tail).";
1515
1559
  }
1516
- return "Read a UTF-8 text file inside the workspace. Read before editing when you need exact text for editFile. For discovery or classification tasks, avoid batch-reading every candidate; report candidate paths first, or read only one to three representative files with a small lines count. Use lines ranges for large code, docs, data, configs, and logs after searchFiles returns line numbers. Read the whole file only when the task truly needs all content or exact edit context.";
1560
+ return "Read a UTF-8 text file inside the workspace. Use lines for focused range reads after searchFiles to save tokens.";
1517
1561
  }
1518
1562
  function buildReadWorkspaceParameters(variant) {
1519
1563
  const path = buildWorkspacePathProperty();
1520
1564
  const lines = {
1521
1565
  type: "string",
1522
- description: 'Which lines to return: "40-120" for a range (1-based, inclusive), "120-" from a line to the end, "-50" for the last N lines (logs, generated output), "50" for the first N. Omit to read the whole file. Use a range after searchFiles gives a line number, and a small count to preview candidates instead of reading many whole files. When the user gives a read/preview budget, each readFile preview consumes one budget slot.'
1566
+ description: 'Line slice: "40-120" (range, 1-based, inclusive), "120-" (from line to end), "-50" (tail N lines), "50" (head N lines). Omit to read full file.'
1523
1567
  };
1524
1568
  if (variant === "minimal") {
1525
1569
  return {
@@ -1549,7 +1593,7 @@ function buildWriteWorkspaceFileTool() {
1549
1593
  type: "function",
1550
1594
  function: {
1551
1595
  name: "writeFile",
1552
- description: "Write full UTF-8 file content inside the workspace. For new files or deliberate whole-file rewrites only. For existing files, prefer editFile for targeted edits. Warn that whole-file rewrites can cause line-ending churn.",
1596
+ description: "Write full UTF-8 file content inside the workspace (new files or whole-file rewrites). Prefer editFile for targeted edits.",
1553
1597
  parameters: {
1554
1598
  type: "object",
1555
1599
  properties: {
@@ -1569,7 +1613,7 @@ function buildReplaceWorkspaceTextTool() {
1569
1613
  type: "function",
1570
1614
  function: {
1571
1615
  name: "editFile",
1572
- description: "Use for small, exact edits in one workspace file without constructing a patch. Read the file first when you need the exact oldText; set expectedReplacements to avoid accidental broad edits. When expected replacement count fails, report a blocker instead of falling back to a full-file rewrite.",
1616
+ description: "Replace exact text occurrences in a workspace file. If expected replacement count fails, report the error instead of falling back to a whole-file rewrite.",
1573
1617
  parameters: {
1574
1618
  type: "object",
1575
1619
  properties: {
@@ -1597,35 +1641,35 @@ function buildSearchWorkspaceDescription(variant) {
1597
1641
  return "Search workspace file contents.";
1598
1642
  }
1599
1643
  if (variant === "workflow") {
1600
- return "Search file contents inside the current workspace after listFiles or globFiles has scoped the likely area, or directly when the task names text to find. Use for code, docs, data, configs, logs, and other text files. Return line numbers, then use readFile with focused ranges for interpretation or editing.";
1644
+ return "Search file contents inside workspace. Returns line numbers; use readFile with line ranges for focused reading.";
1601
1645
  }
1602
1646
  if (variant === "antiShell") {
1603
- return "Search text inside workspace files for code, docs, data, configs, logs, or other text-like assets. Do not use execShell for content search when searchFiles can directly find matching lines. Use globFiles instead for path-only discovery, then readFile for exact surrounding content when needed.";
1647
+ return "Search text inside workspace files using ripgrep. Prefer searchFiles over shell grep.";
1604
1648
  }
1605
- return "Search file contents inside the current workspace using ripgrep when available. Use for grep-like text or regex search across code, docs, data, configs, logs, and other text files. Use globFiles instead when you only need to find files by name or extension before readFile.";
1649
+ return "Search file contents inside the workspace using ripgrep. Returns matching lines and line numbers. Prefer globFiles when only finding file paths.";
1606
1650
  }
1607
1651
  function buildSearchWorkspaceParameters(variant) {
1608
1652
  const query = {
1609
1653
  type: "string",
1610
- description: "Search query. Treated as a regular expression unless literal is true."
1654
+ description: "Search query (regex or literal string)."
1611
1655
  };
1612
1656
  const path = buildWorkspacePathProperty();
1613
1657
  const includeIgnored = {
1614
1658
  type: "boolean",
1615
- description: "When true, search files ignored by .gitignore such as .tmp. Defaults to false. Build artifacts (dist/, *.tsbuildinfo, *.min.js, etc.) are always excluded regardless of this flag. .git and node_modules remain excluded."
1659
+ description: "When true, search gitignored files. Build artifacts (dist/, node_modules, .git) remain excluded."
1616
1660
  };
1617
1661
  const exclude = {
1618
1662
  type: "array",
1619
1663
  items: { type: "string" },
1620
- description: "Glob patterns to exclude from content search, for example ['dist/**', 'build/**', 'exports/**', '*.log']."
1664
+ description: "Glob patterns to exclude from content search (e.g. ['dist/**', '*.log'])."
1621
1665
  };
1622
1666
  const maxResults = {
1623
1667
  type: "integer",
1624
- description: "Maximum number of matching output lines to return. Use a small value when you only need candidate files or examples."
1668
+ description: "Max matching output lines to return."
1625
1669
  };
1626
1670
  const literal = {
1627
1671
  type: "boolean",
1628
- description: "When true, search for query as literal text instead of a regular expression."
1672
+ description: "When true, search query as literal text instead of regex."
1629
1673
  };
1630
1674
  const caseSensitive = {
1631
1675
  type: "boolean",
@@ -1633,7 +1677,7 @@ function buildSearchWorkspaceParameters(variant) {
1633
1677
  };
1634
1678
  const contextLines = {
1635
1679
  type: "integer",
1636
- description: "Number of surrounding context lines to include around each match. Defaults to 0."
1680
+ description: "Number of surrounding context lines around each match. Defaults to 0."
1637
1681
  };
1638
1682
  if (variant === "minimal") {
1639
1683
  return {
@@ -1684,31 +1728,31 @@ function buildGlobWorkspaceDescription(variant) {
1684
1728
  return "Find workspace files by path glob without reading file contents.";
1685
1729
  }
1686
1730
  if (variant === "workflow") {
1687
- return "Find files by glob pattern inside the current workspace without reading file contents. Use after listFiles when you know the likely area, or first when the task names a filename, extension, asset type, config, or document pattern. Then use searchFiles for text inside candidates or readFile for the specific candidate paths.";
1731
+ return "Find files by glob pattern. Use searchFiles for text inside candidates, and readFile for specific paths.";
1688
1732
  }
1689
1733
  if (variant === "antiShell") {
1690
- return "Find workspace files by path glob without reading file contents. Use for code, docs, data, images, configs, logs, or any file discovery task. Do not use execShell or listFiles for path discovery when globFiles can directly narrow candidate files. Use before opening or reading files, and use searchFiles instead for searching text inside files.";
1734
+ return "Find workspace files by path glob. Prefer globFiles over shell find/ls commands.";
1691
1735
  }
1692
- return "Find files by glob pattern inside the current workspace without reading file contents. Use for code, docs, data, images, configs, logs, or any file discovery task. Use one bounded glob with brace groups before repeated narrow globs when a task names several extensions or config names, for example **/*.{png,jpg,svg}, **/{package.json,bunfig.toml,tsconfig*.json}, or src/**/*.ts. Prefer searchFiles for searching text inside files, and readFile only after candidate paths are narrow enough.";
1736
+ return "Find file paths by glob pattern without reading file contents. Use brace groups (e.g. '**/*.{ts,tsx}') to match multiple patterns in one call.";
1693
1737
  }
1694
1738
  function buildGlobWorkspaceParameters(variant) {
1695
1739
  const pattern = {
1696
1740
  type: "string",
1697
- description: "Glob pattern for files. For candidate discovery, combine related names or extensions in one brace-group pattern before making repeated narrow calls, for example '**/*.ts', 'packages/**/local*.test.ts', '**/*.{png,jpg,svg}', or '**/{package.json,bunfig.toml,tsconfig*.json}'."
1741
+ description: "Glob pattern for files (supports brace groups like '**/*.{ts,tsx}', '**/{package.json,tsconfig*.json}')."
1698
1742
  };
1699
1743
  const path = buildWorkspacePathProperty();
1700
1744
  const includeIgnored = {
1701
1745
  type: "boolean",
1702
- description: "When true, include files ignored by .gitignore. Defaults to false; .git and node_modules remain excluded."
1746
+ description: "When true, include gitignored files (.git and node_modules remain excluded)."
1703
1747
  };
1704
1748
  const maxResults = {
1705
1749
  type: "integer",
1706
- description: "Maximum number of file paths to return. Use a small value when you only need candidate paths before readFile; if results are truncated, report that and narrow the pattern or path before reading."
1750
+ description: "Max file paths to return."
1707
1751
  };
1708
1752
  const exclude = {
1709
1753
  type: "array",
1710
1754
  items: { type: "string" },
1711
- description: "Glob patterns to exclude from results, for example ['dist/**', 'build/**', 'exports/**', '*.tmp']."
1755
+ description: "Glob patterns to exclude from results."
1712
1756
  };
1713
1757
  if (variant === "minimal") {
1714
1758
  return {
@@ -1736,7 +1780,7 @@ function buildGlobWorkspaceParameters(variant) {
1736
1780
  pattern,
1737
1781
  glob: {
1738
1782
  type: "string",
1739
- description: "Alias for pattern, kept for compatibility with codeSearch-style prompts."
1783
+ description: "Alias for pattern, kept for compatibility."
1740
1784
  },
1741
1785
  path,
1742
1786
  exclude,
@@ -1807,17 +1851,17 @@ function buildExecShellTool(toolName) {
1807
1851
  type: "function",
1808
1852
  function: {
1809
1853
  name: toolName,
1810
- description: "Run a shell command in the local workspace. Commands already execute from the workspace root; do not cd into guessed paths such as /workspace, /repo, /home/user, or /home/user/workspace. Prefer one command that performs a complete verification or related git operation instead of many tiny commands. For branch setup, prefer idempotent commands such as git switch -C <branch> when replacing or recreating a benchmark branch is acceptable. Use portable POSIX commands for macOS/BSD shells; avoid GNU-only flags such as cat -A. Do not use cat -A. Do not use brittle byte-offset commands such as xxd -s -32. For separator lines, use echo or printf '%s\\n'. For text-file content or trailing-newline checks, prefer readFile over shell byte inspection when that tool is available. Do not run repeated git status, git log, git rev-parse, or branch checks after a successful command already returned the needed clean status and commit information; use one final verification command. If a command fails, use the error output to adjust the next command rather than repeating the same shape. For long-running commands that should keep running in the background (dev servers, watchers, REPLs, `--watch`/`serve`/`dev` scripts), prefer launchProcess. Obviously long-running commands run via execShell (sleep over 5s, tail -f, watch, infinite loops, dev/serve/watch scripts) are moved to the background automatically and return {detached: true, pid, label} \u2014 use listProcesses to inspect or stop them, and tell the user the command is running in the background. Any other command blocks until it exits, so keep those short.",
1854
+ description: `Execute a shell command from the workspace root. Prefer one compound command (e.g. 'git status && git diff --stat') to perform complete verification instead of multiple small roundtrips. Do not cd into guessed paths (e.g. /workspace, /repo, /home/user); commands already run from the workspace root. Use portable POSIX commands for macOS/BSD shells; do not use cat -A or brittle byte-offset tools such as xxd -s -32. For text-file content or trailing-newline checks, prefer readFile over shell byte inspection. After a successful command returned the needed status/commit info, do not run repeated git status/log/rev-parse checks; use one final verification command. Commands block until exit. Long-running commands (sleep over ${IMMEDIATE_DETACH_SLEEP_THRESHOLD_SECONDS}s, dev servers, watchers) automatically detach to background returning {detached: true, pid, label}; for persistent services, prefer launchProcess.`,
1811
1855
  parameters: {
1812
1856
  type: "object",
1813
1857
  properties: {
1814
1858
  cmd: {
1815
1859
  type: "string",
1816
- description: "Shell command to run."
1860
+ description: "Shell command to run. Must be a non-empty command string \u2014 never pass an empty string, whitespace-only text, or null."
1817
1861
  },
1818
1862
  command: {
1819
1863
  type: "string",
1820
- description: "Shell command to run."
1864
+ description: "Shell command to run. Compatibility field for providers that model the command under this name; the executor reads cmd first, then falls back to command. Must also be non-empty when used."
1821
1865
  }
1822
1866
  }
1823
1867
  }
@@ -1829,7 +1873,7 @@ function buildLaunchProcessTool() {
1829
1873
  type: "function",
1830
1874
  function: {
1831
1875
  name: "launchProcess",
1832
- description: "Launch a long-running process (dev server, watcher, REPL) in the background and return immediately without blocking the conversation. Use this instead of execShell for commands that do not exit on their own. Returns {pid, label, status:'running'}. The process keeps running after the tool returns; use listProcesses to check status or the host UI (/procs, /stop) to stop it.",
1876
+ description: "Start a long-running background process (dev server, watcher, REPL) and return immediately with {pid, label, status}. Use listProcesses to inspect or stop it.",
1833
1877
  parameters: {
1834
1878
  type: "object",
1835
1879
  properties: {
@@ -1843,7 +1887,7 @@ function buildLaunchProcessTool() {
1843
1887
  },
1844
1888
  persist: {
1845
1889
  type: "boolean",
1846
- description: "Mark the process as persistent so it survives the current TUI/session exit (kept running in the background when the conversation closes). Defaults to false. Use for long-lived services (e.g. a desktop dev server) you want to keep alive after the session ends."
1890
+ description: "Keep process alive after session/conversation closes. Defaults to false."
1847
1891
  }
1848
1892
  },
1849
1893
  required: ["command"]
@@ -1856,7 +1900,7 @@ function buildListProcessesTool() {
1856
1900
  type: "function",
1857
1901
  function: {
1858
1902
  name: "listProcesses",
1859
- description: "List currently registered background processes launched via launchProcess. Returns array of {pid, label, command, status, startedAt, persist}.",
1903
+ description: "List active background processes launched via launchProcess. Returns {pid, label, command, status, startedAt, persist}[].",
1860
1904
  parameters: {
1861
1905
  type: "object",
1862
1906
  properties: {}
@@ -2247,7 +2291,7 @@ function isPathInsideWorkspace(args) {
2247
2291
  const relativePath = relative(args.workspaceRoot, args.targetPath);
2248
2292
  return relativePath === "" || !relativePath.startsWith("..") && !relativePath.includes(`..${sep}`);
2249
2293
  }
2250
- var PATH_FIELD_ALIASES = ["path", "file_path", "filePath", "filename", "file", "target_file", "targetFile", "file_to_read", "fileToRead"];
2294
+ var PATH_FIELD_ALIASES = ["path", "file_path", "filePath", "filename", "file", "target_file", "targetFile", "file_to_read", "fileToRead", "target_path", "read_path", "path_to_read", "pathToRead"];
2251
2295
  var OLD_TEXT_FIELD_ALIASES = ["oldText", "old_string", "oldString", "search", "search_string", "find", "match"];
2252
2296
  var NEW_TEXT_FIELD_ALIASES = ["newText", "new_string", "newString", "replacement", "replace"];
2253
2297
  var SEARCH_QUERY_FIELD_ALIASES = ["query", "search_query", "searchQuery", "q", "pattern", "search"];
@@ -3011,6 +3055,48 @@ async function resolveLocalWorkspaceToolPath(args) {
3011
3055
  }
3012
3056
  return targetPath;
3013
3057
  }
3058
+ var READ_FILE_MAX_CHAR_LIMIT = 32e3;
3059
+ function defensivelyTruncateReadFile(args) {
3060
+ const limit = args.limit ?? READ_FILE_MAX_CHAR_LIMIT;
3061
+ if (args.content.length <= limit) {
3062
+ return { content: args.content, truncatedByCharLimit: false };
3063
+ }
3064
+ const maxBudget = Math.floor(limit * 0.4);
3065
+ const lines = splitTextLines(args.content);
3066
+ if (lines.length <= 10) {
3067
+ const head2 = args.content.slice(0, maxBudget);
3068
+ const tail2 = args.content.slice(-maxBudget);
3069
+ const omitted = args.content.length - head2.length - tail2.length;
3070
+ return {
3071
+ content: `${head2}
3072
+
3073
+ [... ${omitted} characters omitted. Content exceeds limit (${args.content.length} chars). Use lines slice or searchFiles to inspect specific parts. ...]
3074
+
3075
+ ${tail2}`,
3076
+ truncatedByCharLimit: true
3077
+ };
3078
+ }
3079
+ const headLinesCount = Math.min(150, Math.floor(lines.length * 0.4));
3080
+ const tailLinesCount = Math.min(50, Math.floor(lines.length * 0.2));
3081
+ let head = lines.slice(0, headLinesCount).join("\n");
3082
+ let tail = lines.slice(-tailLinesCount).join("\n");
3083
+ if (head.length > maxBudget) {
3084
+ head = head.slice(0, maxBudget);
3085
+ }
3086
+ if (tail.length > maxBudget) {
3087
+ tail = tail.slice(-maxBudget);
3088
+ }
3089
+ const omittedLines = lines.length - headLinesCount - tailLinesCount;
3090
+ const omittedChars = args.content.length - head.length - tail.length;
3091
+ return {
3092
+ content: `${head}
3093
+
3094
+ [... Omitted ${Math.max(1, omittedLines)} lines (${omittedChars} chars). File exceeds safety limit (${args.content.length} chars, ${args.totalLines} lines). Use lines="start-end" (e.g. lines="151-300") or searchFiles to read specific sections. ...]
3095
+
3096
+ ${tail}`,
3097
+ truncatedByCharLimit: true
3098
+ };
3099
+ }
3014
3100
  async function readFileTool(args) {
3015
3101
  const parsed = parseWorkspaceToolArguments(args.call.arguments);
3016
3102
  const requestedPath = requireWorkspaceToolPath(parsed);
@@ -3026,19 +3112,25 @@ async function readFileTool(args) {
3026
3112
  content,
3027
3113
  ...sliceArgs
3028
3114
  });
3029
- return {
3115
+ const truncatedRead = defensivelyTruncateReadFile({
3030
3116
  content: sliced.content,
3117
+ totalLines: sliced.totalLines
3118
+ });
3119
+ const isTruncated = sliced.truncated || truncatedRead.truncatedByCharLimit;
3120
+ return {
3121
+ content: truncatedRead.content,
3031
3122
  metadata: {
3032
3123
  path: normalizeWorkspaceRelativePath({
3033
3124
  workspaceRoot: resolve(args.workspaceRoot),
3034
3125
  targetPath: absolutePath
3035
3126
  }),
3036
- bytes: Buffer.byteLength(sliced.content),
3127
+ bytes: Buffer.byteLength(truncatedRead.content),
3037
3128
  totalBytes: Buffer.byteLength(content),
3038
3129
  startLine: sliced.startLine,
3039
3130
  endLine: sliced.endLine,
3040
3131
  totalLines: sliced.totalLines,
3041
- truncated: sliced.truncated,
3132
+ truncated: isTruncated,
3133
+ ...truncatedRead.truncatedByCharLimit ? { truncatedByByteLimit: true, truncatedByCharLimit: true } : {},
3042
3134
  ...sliceArgs.maxLines ? { maxLines: sliceArgs.maxLines } : {},
3043
3135
  ...sliceArgs.tailLines ? { tailLines: sliceArgs.tailLines } : {},
3044
3136
  ...warnings.length ? { warnings: [...warnings, buildReadFileSliceHint(sliced.totalLines)] } : {},
@@ -3977,6 +4069,8 @@ Available skills: ${available.join(", ")}`;
3977
4069
  }
3978
4070
 
3979
4071
  export {
4072
+ resolveAgentNextAvailableAt,
4073
+ isAgentCoolingDown,
3980
4074
  parseSseDataLineJson,
3981
4075
  parseSseDataLineObject,
3982
4076
  buildOpenAiCompatibleChatCompletionRequest,
@@ -3989,6 +4083,7 @@ export {
3989
4083
  dialogMessageRecordToAgentRuntimeMessage,
3990
4084
  buildAgentRuntimeDialogWritePlan,
3991
4085
  shouldCacheHybridRemoteRecord,
4086
+ parseSyncServersEnv,
3992
4087
  createHybridRecordStore,
3993
4088
  isDestructiveShellCommand,
3994
4089
  evaluateShellCommandPolicy,
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  createCliLocalRuntimeAdapter,
3
3
  summarizeEndpoint
4
- } from "./chunk-UTADKKM7.js";
4
+ } from "./chunk-PTKI7TIN.js";
5
5
  import {
6
6
  clipMultilineText
7
- } from "./chunk-P5AVCQF3.js";
7
+ } from "./chunk-GGB6MPHD.js";
8
8
  import {
9
9
  runLocalAgentTurn
10
- } from "./chunk-WV3WZRYZ.js";
10
+ } from "./chunk-P3RZ6DHN.js";
11
11
  import {
12
12
  resolveLocalRuntimeEnvFromPolicy
13
13
  } from "./chunk-5CS33IBL.js";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  listUserRecordsFromServers,
3
3
  readLiveDbRecordAfterTombstoneMerge
4
- } from "./chunk-5IIJMMC3.js";
4
+ } from "./chunk-PMCKFQYC.js";
5
5
  import {
6
6
  agentRecordHasConfiguredCredential
7
- } from "./chunk-6NUG4BJE.js";
7
+ } from "./chunk-J2WT5CEO.js";
8
8
  import {
9
9
  toSafeAgentSummary
10
- } from "./chunk-B6RCQ4BM.js";
10
+ } from "./chunk-AAWJ5S3G.js";
11
11
 
12
12
  // packages/cli/agentListHelpers.ts
13
13
  function parseAgentRecordId(privateKey, explicitId) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getAntigravityUserAgent
3
- } from "./chunk-OMWJXZSZ.js";
3
+ } from "./chunk-XNZJVYFS.js";
4
4
  import {
5
5
  writeOAuthCredential
6
6
  } from "./chunk-JZPBVBIY.js";
@@ -173,26 +173,23 @@ function buildNoloWorkspaceOpenAiTools(args) {
173
173
  limit: { type: "integer", description: "Maximum dialogs to return." },
174
174
  space: stringToolParam("Optional space id or URL.")
175
175
  });
176
- add("readDialog", [
177
- "Read one persisted dialog in the Nolo workspace.",
178
- "Prefer the full dialog dbKey (dialog-<userId>-<id>) or a dialog URL; a bare id only resolves for the currently logged-in user and cannot reliably read other users' or cross-server dialogs. Use listDialogs first when the target dialog is unclear."
179
- ].join("\n"), {
176
+ add("readDialog", "Read one persisted dialog in the Nolo workspace by full dbKey (dialog-<userId>-<id>) or URL. Use listDialogs first if target is unclear; bare id works for current user only.", {
180
177
  dialog: stringToolParam("Dialog dbKey (dialog-<userId>-<id>), dialog URL, or bare id (current user only)."),
181
178
  limit: { type: "integer", description: "Optional message limit." }
182
179
  }, ["dialog"]);
183
180
  add("queryDialogsBySubjectRef", "Query persisted dialog evidence by a generic dialog.subjectRefs target.", {
184
- rowDbKey: stringToolParam("Optional convenience alias for subjectKind=table-row, subjectId=<rowDbKey>, subjectRole=task."),
185
- subjectKind: stringToolParam("Generic subject ref kind, for example table-row, page, file, commit, or artifact."),
186
- subjectId: stringToolParam("Generic subject ref id."),
181
+ rowDbKey: stringToolParam("Optional alias for subjectKind=table-row, subjectId=<rowDbKey>, subjectRole=task."),
182
+ subjectKind: stringToolParam("Subject ref kind (e.g. table-row, page, file, commit, artifact)."),
183
+ subjectId: stringToolParam("Subject ref id."),
187
184
  subjectRole: stringToolParam("Optional subject ref role."),
188
185
  limit: { type: "integer", description: "Maximum matching dialog summaries to return." },
189
- status: stringToolParam("Optional dialog status filter, for example running, done, or failed."),
186
+ status: stringToolParam("Optional dialog status filter (running, done, failed)."),
190
187
  checkpointStatus: stringToolParam("Optional runtimeCheckpoint.status filter."),
191
188
  hasArtifacts: { type: "boolean", description: "When true, only return dialogs with artifact evidence." },
192
- excludeDialogId: stringToolParam("Optional dialog id or dialog dbKey to exclude from evidence results, typically the current caller dialog.")
189
+ excludeDialogId: stringToolParam("Optional dialog id to exclude from results.")
193
190
  });
194
- add("deleteDialogs", "Find and delete the current user's dialogs by title/id/dbKey. This is destructive: preview matches first and wait for explicit user confirmation before deleting.", {
195
- query: stringToolParam("Dialog title/id/dbKey search text, for example \u4E2D\u533B\u8BC4\u6D4B or a dialog id."),
191
+ add("deleteDialogs", "Find and delete dialogs by title/id/dbKey. Preview matches and wait for user confirmation before deleting.", {
192
+ query: stringToolParam("Dialog title/id/dbKey search text."),
196
193
  matchMode: {
197
194
  type: "string",
198
195
  enum: ["contains", "exact", "prefix", "dialogId"],
@@ -204,16 +201,12 @@ function buildNoloWorkspaceOpenAiTools(args) {
204
201
  description: "Confirmed dialog ids or dbKeys to delete."
205
202
  }
206
203
  }, ["query"]);
207
- add("listAgents", "List the current user's agents as safe summaries; use readAgent to resolve the runnable agentKey before delegation.", {
204
+ add("listAgents", "List the current user's agents with runnable agentKey for delegation. Copy the agentKey verbatim; do not infer it from the display name.", {
208
205
  space: stringToolParam("Optional space id or URL."),
209
206
  publicOnly: { type: "boolean", description: "Only show public agents." }
210
- // 端间差异(LOW-R2-3):CLI 命令 `nolo agent list` 无 --limit(parseAgentListArgs
211
- // 仅支持 --json/--public-only/--ids-only),本地缓存全量列出;web 端
212
- // listAgentsFunc 另有 limit(默认 100,最大 500)。如后续对齐需在
213
- // parseAgentListArgs / agentListCommands 增加 --limit 透传。
214
207
  });
215
- add("readAgent", "Read one agent's full config from the Nolo workspace. Accepts an agent dbKey (agent-xxx), plain id, alias, or agent URL; resolves it (including public agents via agent-pub-<id>; the server runtime also falls back to handle lookup) and returns the runnable agentKey plus a redacted record with fields such as model, provider, apiSource, tools, prompt, inputPrice, outputPrice, and isPublic. Use it before delegation to confirm an agent's identity and capabilities, or to resolve the agentKey that startAgentRun requires.", {
216
- agent: stringToolParam("Agent dbKey (e.g. agent-xxx), agent id, alias, or agent URL.")
208
+ add("readAgent", "Read one agent's full config by exact agentKey returned by listAgents (agent-<userId>-<id> or agent-pub-<id>); do not use the display name.", {
209
+ agent: stringToolParam("Exact agentKey from listAgents (preferred; copy verbatim; plain id or URL are compatibility fallbacks).")
217
210
  }, ["agent"]);
218
211
  add("listSpaces", "List joined spaces in the Nolo workspace.", {});
219
212
  add("readSpace", "Read one space in the Nolo workspace.", {
@@ -227,8 +220,8 @@ function buildNoloWorkspaceOpenAiTools(args) {
227
220
  add("readSkillDoc", "Read one skill doc in the Nolo workspace.", {
228
221
  doc: stringToolParam("Skill doc/page key.")
229
222
  }, ["doc"]);
230
- add("loadSkill", "Load a Skill by name from the workspace skill directory (.agents/skills/<name>/SKILL.md) and return its full SKILL.md content inline so you can follow its instructions. Use this instead of readFile when you want to activate a skill. On an unknown name the tool returns a plain text list of available skill names rather than failing.", {
231
- name: stringToolParam("Skill name (the name advertised in the skill-discovery layer).")
223
+ add("loadSkill", "Load a skill by name (.agents/skills/<name>/SKILL.md) and return its full instructions inline. Returns available skills if not found.", {
224
+ name: stringToolParam("Skill name advertised in skill discovery.")
232
225
  }, ["name"]);
233
226
  add("listTables", "List tables in the current user scope or an optional space scope.", {
234
227
  limit: { type: "integer", description: "Maximum tables to return." },
@@ -11,7 +11,7 @@ import {
11
11
  getDefaultProfileConfigPath,
12
12
  loadProfileConfig,
13
13
  saveDefaultProfile
14
- } from "./chunk-DXJS7VSG.js";
14
+ } from "./chunk-GE6IWA5N.js";
15
15
  import {
16
16
  resolveAuthTokenFromEnv
17
17
  } from "./chunk-A7GB5UGH.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  trimTrailingSlash
3
- } from "./chunk-5UI2CDQG.js";
3
+ } from "./chunk-PXPISYEH.js";
4
4
  import {
5
5
  asTrimmedLowercaseString
6
6
  } from "./chunk-QSJ3HFEF.js";
@@ -7,7 +7,7 @@ import {
7
7
  listUserRecordsFromServers,
8
8
  readDbRecordFromServers,
9
9
  readLiveDbRecordAfterTombstoneMerge
10
- } from "./chunk-5IIJMMC3.js";
10
+ } from "./chunk-PMCKFQYC.js";
11
11
  import {
12
12
  buildDialogAttachmentPlan,
13
13
  extractFileContentIds
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  i18n_default,
3
3
  toolRegistry
4
- } from "./chunk-P5AVCQF3.js";
4
+ } from "./chunk-GGB6MPHD.js";
5
5
  import {
6
6
  canonicalizeToolNames
7
7
  } from "./chunk-ZZ2MH7LE.js";
8
8
  import {
9
9
  isNoloHostedProvider
10
- } from "./chunk-OHK3HE4G.js";
10
+ } from "./chunk-CZHE6LLV.js";
11
11
  import {
12
12
  asTrimmedLowercaseString
13
13
  } from "./chunk-QSJ3HFEF.js";
@@ -1,27 +1,27 @@
1
1
  import {
2
2
  addContentToSpace
3
- } from "./chunk-THN2YFSR.js";
3
+ } from "./chunk-ADE6577S.js";
4
4
  import "./chunk-XOIF2TNF.js";
5
5
  import "./chunk-MRC4Q34M.js";
6
6
  import "./chunk-SIZQB7BD.js";
7
- import "./chunk-QJZJW65A.js";
7
+ import "./chunk-GD23ZX7Z.js";
8
8
  import "./chunk-YYLHWIW6.js";
9
9
  import "./chunk-CWMSB67P.js";
10
10
  import "./chunk-ROJI6DRT.js";
11
11
  import "./chunk-5RGU3J7P.js";
12
12
  import "./chunk-M76ECQRD.js";
13
13
  import "./chunk-L65QKSVJ.js";
14
- import "./chunk-LWHK7TZR.js";
14
+ import "./chunk-PY7VGC5M.js";
15
15
  import "./chunk-5MMAK75Q.js";
16
16
  import "./chunk-5CS33IBL.js";
17
17
  import "./chunk-JZPBVBIY.js";
18
- import "./chunk-J6MEBHAT.js";
18
+ import "./chunk-LEHTC2FI.js";
19
19
  import "./chunk-ZHXJ6M7T.js";
20
20
  import "./chunk-3ASDTTEI.js";
21
21
  import "./chunk-DWLEOOGR.js";
22
22
  import "./chunk-HNMXYYJR.js";
23
- import "./chunk-T3EOQH72.js";
24
- import "./chunk-OHK3HE4G.js";
23
+ import "./chunk-G36SUBHA.js";
24
+ import "./chunk-CZHE6LLV.js";
25
25
  import "./chunk-S6KVFOUG.js";
26
26
  import "./chunk-Y5GCAMGP.js";
27
27
  import "./chunk-UZ6XXCVR.js";