nolo-cli 0.63.1 → 0.64.0-alpha.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 (29) hide show
  1. package/README.md +1 -0
  2. package/{agentDeleteCommand-NTUC5X4H.js → agentDeleteCommand-6R6EXQOR.js} +1 -1
  3. package/{agentEmailCommands-D74ZOQXN.js → agentEmailCommands-AKENZOKO.js} +3 -3
  4. package/{agentListCommands-43NKDIUT.js → agentListCommands-XJU3JJQO.js} +1 -1
  5. package/{agentMachineCommands-5MPEQQMR.js → agentMachineCommands-V7IJDPAY.js} +2 -2
  6. package/{agentRecordCommands-UUYNJGVC.js → agentRecordCommands-VIEINDIV.js} +3 -3
  7. package/{agentRunCommand-7MIBF4J7.js → agentRunCommand-GT5ZTYRM.js} +3 -3
  8. package/{agentRuntimeLocal-WWBWDTTG.js → agentRuntimeLocal-HGJ4D3JF.js} +1 -1
  9. package/{appDeleteCommands-VTIDMUUS.js → appDeleteCommands-VG2UVW4T.js} +1 -1
  10. package/{appDeployCommands-LOACOW26.js → appDeployCommands-PABMVMN2.js} +1 -1
  11. package/{appDeployStatusCommands-2RKASRYO.js → appDeployStatusCommands-X7WEU4TU.js} +1 -1
  12. package/{appGetCommands-GRO6QDM3.js → appGetCommands-NQYXHVJL.js} +1 -1
  13. package/{appListCommands-5BMCSU66.js → appListCommands-5NGZQ6IK.js} +1 -1
  14. package/{chunk-ECSQC7UV.js → chunk-3ROJR3TG.js} +22 -2
  15. package/{chunk-JNDDM6BU.js → chunk-BWIPK2PD.js} +22 -3
  16. package/{chunk-Y4AIZ4N2.js → chunk-LJ6OKZ6D.js} +201 -7
  17. package/{chunk-GJUFAZPF.js → chunk-OOCYHKCV.js} +1 -1
  18. package/{chunk-CGUUOBD2.js → chunk-URHZKKK7.js} +2 -2
  19. package/{dialogCommands-PPONZF6D.js → dialogCommands-HGMV4NQJ.js} +1 -1
  20. package/{docCreateCommands-SJSQAX4J.js → docCreateCommands-WQT5EZG2.js} +1 -1
  21. package/{docDeleteCommands-T4IFYPWR.js → docDeleteCommands-GUMELBKM.js} +1 -1
  22. package/{docReadCommands-RHD6RPV7.js → docReadCommands-T6FDDKJ3.js} +1 -1
  23. package/{docUpdateCommands-5OLZXCEB.js → docUpdateCommands-GBWGXG2G.js} +1 -1
  24. package/index.js +43 -41
  25. package/{machineCommands-Y6NJLJ77.js → machineCommands-SCGLQQCA.js} +3 -3
  26. package/{machineWsRunDispatch-LBSNCUW7.js → machineWsRunDispatch-EAH5VIEL.js} +3 -3
  27. package/package.json +1 -1
  28. package/{readlineWorkspace-F3IYM37K.js → readlineWorkspace-7FNJDYLD.js} +185 -99
  29. package/{spaceCommands-OAKDKTZV.js → spaceCommands-76ECKNFH.js} +1 -1
package/README.md CHANGED
@@ -282,6 +282,7 @@ npm pack
282
282
  - `nolo-cli` 作为入口包,包含一个 Node.js 兼容的 `index.js` 引导脚本
283
283
  - 引导脚本优先调用原生二进制;缺失时回退到 `bun index.ts`
284
284
  - **原生二进制通过 S3 下载站分发**(`install-nolo.sh`),不走 npm 可选依赖——npm 包始终是纯 JS/Bun 版本
285
+ - `install-nolo.sh` 会把安装目录写进 shell 启动文件(已存在的 `~/.zshrc`/`~/.bashrc`/`~/.bash_profile`/`~/.profile`,缺失时创建登录 shell 对应的那个),bash/zsh 新终端开箱即用 `nolo`,无需手动改 PATH;写入以 `# nolo-cli-path` 为标记、可重复执行、可用 `NOLO_NO_MODIFY_PATH=1` 关闭
285
286
 
286
287
  支持的平台:macOS Apple Silicon(`darwin-arm64`)。
287
288
 
@@ -15,7 +15,7 @@ import "./chunk-KQHGZWSV.js";
15
15
  import {
16
16
  Level
17
17
  } from "./chunk-UV6VISQJ.js";
18
- import "./chunk-ECSQC7UV.js";
18
+ import "./chunk-3ROJR3TG.js";
19
19
  import "./chunk-7A3RRUCQ.js";
20
20
  import "./chunk-ZNFJWEN4.js";
21
21
  import "./chunk-XOKOSO35.js";
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-JYYZCK2Z.js";
9
9
  import {
10
10
  runAgentCreateCommand
11
- } from "./chunk-GJUFAZPF.js";
12
- import "./chunk-Y4AIZ4N2.js";
11
+ } from "./chunk-OOCYHKCV.js";
12
+ import "./chunk-LJ6OKZ6D.js";
13
13
  import "./chunk-MXUDQZXQ.js";
14
14
  import "./chunk-EADNWBAZ.js";
15
15
  import "./chunk-45YO6H7P.js";
@@ -68,7 +68,7 @@ import "./chunk-E3YVTQWT.js";
68
68
  import "./chunk-ZRSJ3JEH.js";
69
69
  import "./chunk-AETZ7AD6.js";
70
70
  import "./chunk-KHCLMKZZ.js";
71
- import "./chunk-ECSQC7UV.js";
71
+ import "./chunk-3ROJR3TG.js";
72
72
  import "./chunk-7A3RRUCQ.js";
73
73
  import "./chunk-ZNFJWEN4.js";
74
74
  import "./chunk-XOKOSO35.js";
@@ -38,7 +38,7 @@ import {
38
38
  } from "./chunk-3BLB7QKO.js";
39
39
  import "./chunk-KQHGZWSV.js";
40
40
  import "./chunk-YYLHWIW6.js";
41
- import "./chunk-ECSQC7UV.js";
41
+ import "./chunk-3ROJR3TG.js";
42
42
  import "./chunk-7A3RRUCQ.js";
43
43
  import "./chunk-ZNFJWEN4.js";
44
44
  import "./chunk-XOKOSO35.js";
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-SPAQ4PVV.js";
16
16
  import "./chunk-NF64D32W.js";
17
17
  import "./chunk-3L2WKC3W.js";
18
- import "./chunk-ECSQC7UV.js";
18
+ import "./chunk-3ROJR3TG.js";
19
19
  import "./chunk-7A3RRUCQ.js";
20
20
  import "./chunk-ZNFJWEN4.js";
21
21
  import "./chunk-XOKOSO35.js";
@@ -89,7 +89,7 @@ async function defaultExecuteCli(provider, prompt, options) {
89
89
  return executeCli(provider, prompt, options);
90
90
  }
91
91
  async function forwardConnectorRunMessage(machine, message, pushMessage, executeCli, env, fetchImpl) {
92
- const { handleConnectorRunMessage } = await import("./machineWsRunDispatch-LBSNCUW7.js");
92
+ const { handleConnectorRunMessage } = await import("./machineWsRunDispatch-EAH5VIEL.js");
93
93
  return handleConnectorRunMessage(message, pushMessage, executeCli, env, fetchImpl);
94
94
  }
95
95
  async function detectLaunchableMachineInfo() {
@@ -2,8 +2,8 @@ import {
2
2
  runAgentCreateCommand,
3
3
  runAgentReadCommand,
4
4
  runAgentUpdateCommand
5
- } from "./chunk-GJUFAZPF.js";
6
- import "./chunk-Y4AIZ4N2.js";
5
+ } from "./chunk-OOCYHKCV.js";
6
+ import "./chunk-LJ6OKZ6D.js";
7
7
  import "./chunk-MXUDQZXQ.js";
8
8
  import "./chunk-EADNWBAZ.js";
9
9
  import "./chunk-45YO6H7P.js";
@@ -55,7 +55,7 @@ import "./chunk-E3YVTQWT.js";
55
55
  import "./chunk-ZRSJ3JEH.js";
56
56
  import "./chunk-AETZ7AD6.js";
57
57
  import "./chunk-KHCLMKZZ.js";
58
- import "./chunk-ECSQC7UV.js";
58
+ import "./chunk-3ROJR3TG.js";
59
59
  import "./chunk-7A3RRUCQ.js";
60
60
  import "./chunk-ZNFJWEN4.js";
61
61
  import "./chunk-XOKOSO35.js";
@@ -8,12 +8,12 @@ import {
8
8
  resolveRunSettlementNote,
9
9
  resolveWorkflowReference,
10
10
  runAgentRunCommand
11
- } from "./chunk-JNDDM6BU.js";
11
+ } from "./chunk-BWIPK2PD.js";
12
12
  import "./chunk-S7Z2HMCN.js";
13
13
  import {
14
14
  parseAgentRunArgs
15
15
  } from "./chunk-JYYZCK2Z.js";
16
- import "./chunk-Y4AIZ4N2.js";
16
+ import "./chunk-LJ6OKZ6D.js";
17
17
  import "./chunk-MXUDQZXQ.js";
18
18
  import "./chunk-EADNWBAZ.js";
19
19
  import "./chunk-45YO6H7P.js";
@@ -70,7 +70,7 @@ import "./chunk-E3YVTQWT.js";
70
70
  import "./chunk-ZRSJ3JEH.js";
71
71
  import "./chunk-AETZ7AD6.js";
72
72
  import "./chunk-KHCLMKZZ.js";
73
- import "./chunk-ECSQC7UV.js";
73
+ import "./chunk-3ROJR3TG.js";
74
74
  import "./chunk-7A3RRUCQ.js";
75
75
  import "./chunk-ZNFJWEN4.js";
76
76
  import "./chunk-XOKOSO35.js";
@@ -19,7 +19,7 @@ import {
19
19
  resolveOpenAiCompatibleProviderConfig,
20
20
  runLocalAgentTurn,
21
21
  shouldCacheHybridRemoteRecord
22
- } from "./chunk-ECSQC7UV.js";
22
+ } from "./chunk-3ROJR3TG.js";
23
23
  import {
24
24
  buildPlatformChatCompletionRequest,
25
25
  canUsePlatformChatProvider,
@@ -13,7 +13,7 @@ import "./chunk-FHAGENAS.js";
13
13
  import "./chunk-CTCW7U7N.js";
14
14
  import "./chunk-SPAQ4PVV.js";
15
15
  import "./chunk-VF4K2QE6.js";
16
- import "./chunk-ECSQC7UV.js";
16
+ import "./chunk-3ROJR3TG.js";
17
17
  import "./chunk-7A3RRUCQ.js";
18
18
  import "./chunk-ZNFJWEN4.js";
19
19
  import "./chunk-XOKOSO35.js";
@@ -14,7 +14,7 @@ import "./chunk-FHAGENAS.js";
14
14
  import "./chunk-CTCW7U7N.js";
15
15
  import "./chunk-SPAQ4PVV.js";
16
16
  import "./chunk-VF4K2QE6.js";
17
- import "./chunk-ECSQC7UV.js";
17
+ import "./chunk-3ROJR3TG.js";
18
18
  import "./chunk-7A3RRUCQ.js";
19
19
  import "./chunk-ZNFJWEN4.js";
20
20
  import "./chunk-XOKOSO35.js";
@@ -13,7 +13,7 @@ import "./chunk-FHAGENAS.js";
13
13
  import "./chunk-CTCW7U7N.js";
14
14
  import "./chunk-SPAQ4PVV.js";
15
15
  import "./chunk-VF4K2QE6.js";
16
- import "./chunk-ECSQC7UV.js";
16
+ import "./chunk-3ROJR3TG.js";
17
17
  import "./chunk-7A3RRUCQ.js";
18
18
  import "./chunk-ZNFJWEN4.js";
19
19
  import "./chunk-XOKOSO35.js";
@@ -14,7 +14,7 @@ import "./chunk-FHAGENAS.js";
14
14
  import "./chunk-CTCW7U7N.js";
15
15
  import "./chunk-SPAQ4PVV.js";
16
16
  import "./chunk-VF4K2QE6.js";
17
- import "./chunk-ECSQC7UV.js";
17
+ import "./chunk-3ROJR3TG.js";
18
18
  import "./chunk-7A3RRUCQ.js";
19
19
  import "./chunk-ZNFJWEN4.js";
20
20
  import "./chunk-XOKOSO35.js";
@@ -14,7 +14,7 @@ import "./chunk-FHAGENAS.js";
14
14
  import "./chunk-CTCW7U7N.js";
15
15
  import "./chunk-SPAQ4PVV.js";
16
16
  import "./chunk-VF4K2QE6.js";
17
- import "./chunk-ECSQC7UV.js";
17
+ import "./chunk-3ROJR3TG.js";
18
18
  import "./chunk-7A3RRUCQ.js";
19
19
  import "./chunk-ZNFJWEN4.js";
20
20
  import "./chunk-XOKOSO35.js";
@@ -12491,7 +12491,8 @@ async function maybeAutoCompactLocalHistory(args2) {
12491
12491
  // 防死亡螺旋:用 summary 长度作为上次压缩后的基线。如果新内容没让
12492
12492
  // totalUsed 比 summary 本身增长超过 minNewTokens,不重复触发。
12493
12493
  lastCompactedTokenCount: existingSummary ? estimateTokenCount(existingSummary) : void 0,
12494
- ...coldResume ? { force: true, reason: "context_budget" } : {}
12494
+ ...coldResume ? { force: true, reason: "context_budget" } : {},
12495
+ ...args2.realContextUsagePercent !== void 0 ? { realContextUsagePercent: args2.realContextUsagePercent } : {}
12495
12496
  });
12496
12497
  const projectExisting = () => {
12497
12498
  if (!existingSummary.trim() && !storedStubbedBeforeId) return unchanged();
@@ -13603,6 +13604,24 @@ async function runLocalAgentTurn(input) {
13603
13604
  }
13604
13605
  return resolvedProvider;
13605
13606
  };
13607
+ let realContextUsagePercent;
13608
+ if (input.continueDialogId && typeof input.adapter.loadLastContextUsage === "function") {
13609
+ try {
13610
+ const usage = await input.adapter.loadLastContextUsage(
13611
+ input.continueDialogId
13612
+ );
13613
+ const inputTokens = usage?.inputTokens;
13614
+ const contextWindow = getModelContextWindow(agentConfig.model);
13615
+ if (typeof inputTokens === "number" && Number.isFinite(inputTokens) && inputTokens > 0 && typeof contextWindow === "number" && Number.isFinite(contextWindow) && contextWindow > 0) {
13616
+ realContextUsagePercent = Math.min(
13617
+ 1,
13618
+ Math.max(0, inputTokens / contextWindow)
13619
+ );
13620
+ }
13621
+ } catch (err) {
13622
+ console.warn("[localLoop] loadLastContextUsage failed:", err);
13623
+ }
13624
+ }
13606
13625
  let compactionUsage;
13607
13626
  try {
13608
13627
  const compacted = await maybeAutoCompactLocalHistory({
@@ -13610,7 +13629,8 @@ async function runLocalAgentTurn(input) {
13610
13629
  dialogId: input.continueDialogId,
13611
13630
  history,
13612
13631
  model: agentConfig.model,
13613
- resolveProvider: resolveProviderOnce
13632
+ resolveProvider: resolveProviderOnce,
13633
+ realContextUsagePercent
13614
13634
  });
13615
13635
  history = compacted.history;
13616
13636
  compactionUsage = compacted.usage;
@@ -27,7 +27,7 @@ import {
27
27
  resolveLocalUserId,
28
28
  t,
29
29
  toolLabel
30
- } from "./chunk-Y4AIZ4N2.js";
30
+ } from "./chunk-LJ6OKZ6D.js";
31
31
  import {
32
32
  createRunActivityTracker,
33
33
  popSingleQueueMessage,
@@ -112,7 +112,7 @@ import {
112
112
  LOCAL_AGENT_CONFIG_MISSING_CODE,
113
113
  LOCAL_TURN_ABORTED_CODE,
114
114
  readActionGate
115
- } from "./chunk-ECSQC7UV.js";
115
+ } from "./chunk-3ROJR3TG.js";
116
116
  import {
117
117
  resolveAgentRuntimeConfigFromRecord
118
118
  } from "./chunk-XOKOSO35.js";
@@ -5176,7 +5176,7 @@ function findCollapsedPasteSpanAt(buffer, pos, opts = {}) {
5176
5176
  // packages/cli/client/agentRun.ts
5177
5177
  import { ulid } from "ulid";
5178
5178
  async function loadRunLocalAgentTurn() {
5179
- const { runLocalAgentTurn } = await import("./agentRuntimeLocal-WWBWDTTG.js");
5179
+ const { runLocalAgentTurn } = await import("./agentRuntimeLocal-HGJ4D3JF.js");
5180
5180
  return runLocalAgentTurn;
5181
5181
  }
5182
5182
  var stripDebugNoise = (s) => s.replace(/\s*raw="[\s\S]*"/g, "").replace(/\s*raw=\S+/g, "").replace(/\s*headers=\[[^\]]*\]/g, "").replace(/\s*headers=\S+/g, "").trim();
@@ -5239,6 +5239,19 @@ function parseEmbeddedBalanceDetails(message) {
5239
5239
  return void 0;
5240
5240
  }
5241
5241
  }
5242
+ function parseContextLengthDetails(message) {
5243
+ let max;
5244
+ let requested;
5245
+ const maxMatch = message.match(/maximum context length\s+(?:is|of)\s*(\d+)/i);
5246
+ if (maxMatch) {
5247
+ max = maxMatch[1];
5248
+ }
5249
+ const reqMatch = message.match(/(?:requested|resulted in|request of)\s*(\d+)/i);
5250
+ if (reqMatch) {
5251
+ requested = reqMatch[1];
5252
+ }
5253
+ return { requested, max };
5254
+ }
5242
5255
  async function resolveCurrentMachineId(options) {
5243
5256
  return options.currentMachineIdResolver ? options.currentMachineIdResolver(options.env) : detectCurrentMachineId(options.env);
5244
5257
  }
@@ -5522,6 +5535,12 @@ function describeLocalRunFailure(message, rawError) {
5522
5535
  balanceDetails.current
5523
5536
  ) : extractEmbeddedErrorMessage(cleanedMessage) ?? fallback;
5524
5537
  return `[nolo] ${shownMessage}
5538
+ `;
5539
+ }
5540
+ if (/maximum context length/i.test(message)) {
5541
+ const details = parseContextLengthDetails(message);
5542
+ const shownMessage = details.requested && details.max ? t("contextLengthExceeded", details.requested, details.max) : details.max ? t("contextLengthExceededLimitOnly", details.max) : t("contextLengthExceededGeneric");
5543
+ return `[nolo] ${shownMessage}
5525
5544
  `;
5526
5545
  }
5527
5546
  if (isCliAuthorityBrokerTimeoutError(rawError) || /CLI authority broker .* timed out/i.test(message)) {
@@ -92,6 +92,7 @@ import {
92
92
  import {
93
93
  applyBuiltinAgentRuntimeOverride,
94
94
  applyTokenUsageToDayStats,
95
+ normalizeUsage,
95
96
  prepareTokenUsageData,
96
97
  resolveBuiltinPlatformAgentConfig,
97
98
  runKeyed
@@ -153,7 +154,7 @@ import {
153
154
  resolveOpenAiCompatibleProviderConfig,
154
155
  shouldUseGeminiNativeToolRoute,
155
156
  summarizeToolArguments
156
- } from "./chunk-ECSQC7UV.js";
157
+ } from "./chunk-3ROJR3TG.js";
157
158
  import {
158
159
  PlatformStreamInterruptedError,
159
160
  buildPlatformChatCompletionRequest,
@@ -995,6 +996,38 @@ var STRINGS = {
995
996
  en: "Current dialog: new (nothing to compact yet)",
996
997
  zh: "\u5F53\u524D\u5BF9\u8BDD\u8FD8\u662F\u65B0\u7684\uFF08\u8FD8\u6CA1\u6709\u53EF\u538B\u7F29\u7684\u5185\u5BB9\uFF09"
997
998
  },
999
+ compactingDialog: {
1000
+ en: "Compacting current dialog...",
1001
+ zh: "\u6B63\u5728\u538B\u7F29\u5F53\u524D\u5BF9\u8BDD\u2026"
1002
+ },
1003
+ compactPhaseReading: {
1004
+ en: "Reading dialog messages\u2026",
1005
+ zh: "\u6B63\u5728\u8BFB\u53D6\u5BF9\u8BDD\u6D88\u606F\u2026"
1006
+ },
1007
+ compactPhaseSummarizing: {
1008
+ en: "Generating summary\u2026",
1009
+ zh: "\u6B63\u5728\u751F\u6210\u603B\u7ED3\u2026"
1010
+ },
1011
+ compactPhaseForking: {
1012
+ en: "Forking dialog\u2026",
1013
+ zh: "\u6B63\u5728\u5206\u53C9\u65B0\u5BF9\u8BDD\u2026"
1014
+ },
1015
+ compactFailed: {
1016
+ en: "Compact failed: {0}",
1017
+ zh: "\u538B\u7F29\u5931\u8D25\uFF1A{0}"
1018
+ },
1019
+ contextLengthExceeded: {
1020
+ en: "Model context limit reached (requested {0} tokens / limit {1}). Suggest using /compact to compact current dialog, or /new to start a fresh dialog.",
1021
+ zh: "\u5DF2\u8FBE\u6A21\u578B\u4E0A\u4E0B\u6587\u4E0A\u9650\uFF08\u8BF7\u6C42 {0} tokens / \u4E0A\u9650 {1}\uFF09\u3002\u5EFA\u8BAE\u4F7F\u7528 /compact \u538B\u7F29\u5F53\u524D\u5BF9\u8BDD\uFF0C\u6216\u4F7F\u7528 /new \u5F00\u59CB\u65B0\u5BF9\u8BDD\u3002"
1022
+ },
1023
+ contextLengthExceededLimitOnly: {
1024
+ en: "Model context limit reached (limit {0}). Suggest using /compact to compact current dialog, or /new to start a fresh dialog.",
1025
+ zh: "\u5DF2\u8FBE\u6A21\u578B\u4E0A\u4E0B\u6587\u4E0A\u9650\uFF08\u4E0A\u9650 {0}\uFF09\u3002\u5EFA\u8BAE\u4F7F\u7528 /compact \u538B\u7F29\u5F53\u524D\u5BF9\u8BDD\uFF0C\u6216\u4F7F\u7528 /new \u5F00\u59CB\u65B0\u5BF9\u8BDD\u3002"
1026
+ },
1027
+ contextLengthExceededGeneric: {
1028
+ en: "Model context limit reached. Suggest using /compact to compact current dialog, or /new to start a fresh dialog.",
1029
+ zh: "\u5DF2\u8FBE\u6A21\u578B\u4E0A\u4E0B\u6587\u4E0A\u9650\u3002\u5EFA\u8BAE\u4F7F\u7528 /compact \u538B\u7F29\u5F53\u524D\u5BF9\u8BDD\uFF0C\u6216\u4F7F\u7528 /new \u5F00\u59CB\u65B0\u5BF9\u8BDD\u3002"
1030
+ },
998
1031
  compactDone: {
999
1032
  en: "Compacted dialog {0} \u2192 {1}.",
1000
1033
  zh: "\u5DF2\u538B\u7F29\u5BF9\u8BDD {0} \u2192 {1}\u3002"
@@ -9578,7 +9611,7 @@ async function resolveLocalProvider(ctx) {
9578
9611
  }
9579
9612
 
9580
9613
  // packages/cli/client/localRuntimeAdapter.ts
9581
- import { dirname as dirname2, extname, join as join3 } from "node:path";
9614
+ import { dirname as dirname2, extname, join as join4 } from "node:path";
9582
9615
  import { fileURLToPath } from "node:url";
9583
9616
 
9584
9617
  // packages/cli/client/providerStreamRetry.ts
@@ -10589,12 +10622,12 @@ var nodeFs = {
10589
10622
  readFileSync,
10590
10623
  existsSync
10591
10624
  };
10592
- function resolveNoloHome(env, homedir2) {
10625
+ function resolveNoloHome(env, homedir3) {
10593
10626
  const custom = env?.NOLO_HOME;
10594
10627
  if (custom && custom.trim()) return custom.trim();
10595
10628
  const ambient = process.env.NOLO_HOME?.trim();
10596
10629
  if (ambient) return ambient;
10597
- return join(homedir2(), ".nolo");
10630
+ return join(homedir3(), ".nolo");
10598
10631
  }
10599
10632
  function ensureDir(dir, fs) {
10600
10633
  fs.mkdirSync(dir, { recursive: true });
@@ -10613,9 +10646,9 @@ function writeJson(path, data, fs) {
10613
10646
  }
10614
10647
  function createFileSystemTodoStore(opts = {}) {
10615
10648
  const env = opts.env ?? process.env;
10616
- const homedir2 = opts.homedir ?? nodeHomedir;
10649
+ const homedir3 = opts.homedir ?? nodeHomedir;
10617
10650
  const fs = opts.fs ?? nodeFs;
10618
- const noloHome = resolveNoloHome(env, homedir2);
10651
+ const noloHome = resolveNoloHome(env, homedir3);
10619
10652
  const filePath = opts.filePath ?? join(noloHome, "agent_run_todos.json");
10620
10653
  const oldFilePath = join(noloHome, "todos.json");
10621
10654
  const loadMap = () => {
@@ -12008,6 +12041,25 @@ async function writeLocalTokenRecord(args) {
12008
12041
  }
12009
12042
  return ops;
12010
12043
  }
12044
+ function extractLastProviderInputTokens(input) {
12045
+ if (input.usageRecords && input.usageRecords.length > 0) {
12046
+ for (let i = input.usageRecords.length - 1; i >= 0; i--) {
12047
+ const record = input.usageRecords[i];
12048
+ if (!record?.usage) continue;
12049
+ const normalized = normalizeUsage(record.usage);
12050
+ if (normalized.input_tokens > 0) {
12051
+ return normalized.input_tokens;
12052
+ }
12053
+ }
12054
+ }
12055
+ if (input.result?.usage) {
12056
+ const normalized = normalizeUsage(input.result.usage);
12057
+ if (normalized.input_tokens > 0) {
12058
+ return normalized.input_tokens;
12059
+ }
12060
+ }
12061
+ return void 0;
12062
+ }
12011
12063
  async function writeDialog(args) {
12012
12064
  const __perfEnabled = args.env?.NOLO_CLI_PERF === "1";
12013
12065
  const __perfT0 = __perfEnabled ? performance.now() : 0;
@@ -12057,6 +12109,15 @@ async function writeDialog(args) {
12057
12109
  existingDialog,
12058
12110
  cwd: args.cwd
12059
12111
  });
12112
+ const lastInputTokens = extractLastProviderInputTokens(args.input) ?? (typeof existingDialog?.lastInputTokens === "number" && Number.isFinite(existingDialog.lastInputTokens) && existingDialog.lastInputTokens > 0 ? existingDialog.lastInputTokens : void 0);
12113
+ if (typeof lastInputTokens === "number" && lastInputTokens > 0) {
12114
+ const dialogOp = plan.ops.find(
12115
+ (op) => op.type === "put" && op.key === `dialog-${args.userId}-${plan.dialogId}`
12116
+ );
12117
+ if (dialogOp && dialogOp.value && typeof dialogOp.value === "object") {
12118
+ dialogOp.value.lastInputTokens = lastInputTokens;
12119
+ }
12120
+ }
12060
12121
  await args.store.batch(plan.ops);
12061
12122
  if (__perfEnabled) {
12062
12123
  const ms = (performance.now() - __perfT0).toFixed(1);
@@ -12202,6 +12263,16 @@ async function saveCliDialogSummary(args) {
12202
12263
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
12203
12264
  });
12204
12265
  }
12266
+ async function loadCliDialogLastContextUsage(args) {
12267
+ const dialogKey = resolveCliDialogRecordKey(args.userId, args.dialogId);
12268
+ const record = await args.store.read(dialogKey);
12269
+ if (!record || typeof record !== "object") return null;
12270
+ const lastInputTokens = record.lastInputTokens;
12271
+ if (typeof lastInputTokens === "number" && Number.isFinite(lastInputTokens) && lastInputTokens > 0) {
12272
+ return { inputTokens: lastInputTokens };
12273
+ }
12274
+ return null;
12275
+ }
12205
12276
  function parseTitleUpdatedAtMs(existingDialog) {
12206
12277
  const raw = existingDialog?.titleUpdatedAt;
12207
12278
  if (typeof raw === "number" && !Number.isNaN(raw)) return raw;
@@ -12212,12 +12283,119 @@ function parseTitleUpdatedAtMs(existingDialog) {
12212
12283
  return 0;
12213
12284
  }
12214
12285
 
12286
+ // packages/cli/client/turnBillingAudit.ts
12287
+ import {
12288
+ appendFileSync as appendFileSync2,
12289
+ closeSync,
12290
+ mkdirSync as mkdirSync3,
12291
+ openSync,
12292
+ readSync,
12293
+ statSync
12294
+ } from "node:fs";
12295
+ import { homedir as homedir2 } from "node:os";
12296
+ import { join as join3 } from "node:path";
12297
+ function projectUsageForAudit(usage) {
12298
+ if (!usage || typeof usage !== "object") return null;
12299
+ const normalized = normalizeUsage(usage);
12300
+ const projected = {
12301
+ input_tokens: normalized.input_tokens,
12302
+ output_tokens: normalized.output_tokens,
12303
+ cache_read_input_tokens: normalized.cache_read_input_tokens,
12304
+ cache_creation_input_tokens: normalized.cache_creation_input_tokens
12305
+ };
12306
+ if (typeof usage.cost === "number" && Number.isFinite(usage.cost)) {
12307
+ projected.cost = usage.cost;
12308
+ }
12309
+ if (typeof usage.billing_unit === "string" && usage.billing_unit.trim()) {
12310
+ projected.billing_unit = usage.billing_unit;
12311
+ }
12312
+ if (typeof usage.provider_call_id === "string" && usage.provider_call_id.trim()) {
12313
+ projected.provider_call_id = usage.provider_call_id.trim();
12314
+ }
12315
+ return projected;
12316
+ }
12317
+ function resolveTurnBillingAuditLogPath(env = process.env) {
12318
+ const noloHome = env.NOLO_HOME?.trim() || join3(homedir2(), ".nolo");
12319
+ return join3(noloHome, "logs", "turn-billing.jsonl");
12320
+ }
12321
+ function appendTurnBillingAudit(input) {
12322
+ try {
12323
+ if (process.env.NOLO_TURN_BILLING_AUDIT === "0") return;
12324
+ const calls = (input.usageRecords ?? []).map((record) => {
12325
+ const usage = projectUsageForAudit(record?.usage);
12326
+ if (!usage) return null;
12327
+ return {
12328
+ ...record?.callId ? { callId: record.callId } : {},
12329
+ ...record?.model ? { model: record.model } : {},
12330
+ ...record?.provider ? { provider: record.provider } : {},
12331
+ ...usage
12332
+ };
12333
+ }).filter((call) => call !== null);
12334
+ if (calls.length === 0 && (input.turnCredits === void 0 || input.turnCredits === null)) {
12335
+ return;
12336
+ }
12337
+ const row = {
12338
+ ts: Date.now(),
12339
+ ...input.dialogId ? { dialogId: input.dialogId } : {},
12340
+ ...input.agentKey ? { agentKey: input.agentKey } : {},
12341
+ ...input.turnCredits !== void 0 && input.turnCredits !== null ? { turnCredits: input.turnCredits } : {},
12342
+ ...input.aborted ? { aborted: true } : {},
12343
+ calls
12344
+ };
12345
+ const logPath = resolveTurnBillingAuditLogPath();
12346
+ mkdirSync3(join3(logPath, ".."), { recursive: true });
12347
+ appendFileSync2(logPath, `${JSON.stringify(row)}
12348
+ `);
12349
+ } catch {
12350
+ }
12351
+ }
12352
+ function readLastTurnBillingInputTokens(dialogId, env = process.env) {
12353
+ if (!dialogId || typeof dialogId !== "string") return void 0;
12354
+ try {
12355
+ const logPath = resolveTurnBillingAuditLogPath(env);
12356
+ const stat = statSync(logPath, { throwIfNoEntry: false });
12357
+ if (!stat || !stat.isFile() || stat.size === 0) return void 0;
12358
+ const maxBytesToRead = 64 * 1024;
12359
+ const bytesToRead = Math.min(stat.size, maxBytesToRead);
12360
+ const buffer = Buffer.alloc(bytesToRead);
12361
+ const fd = openSync(logPath, "r");
12362
+ try {
12363
+ readSync(fd, buffer, 0, bytesToRead, stat.size - bytesToRead);
12364
+ } finally {
12365
+ closeSync(fd);
12366
+ }
12367
+ const text = buffer.toString("utf-8");
12368
+ const lines = text.split("\n");
12369
+ for (let i = lines.length - 1; i >= 0; i--) {
12370
+ const line = lines[i].trim();
12371
+ if (!line) continue;
12372
+ try {
12373
+ const parsed = JSON.parse(line);
12374
+ if (parsed && typeof parsed === "object" && parsed.dialogId === dialogId) {
12375
+ if (Array.isArray(parsed.calls) && parsed.calls.length > 0) {
12376
+ for (let j = parsed.calls.length - 1; j >= 0; j--) {
12377
+ const call = parsed.calls[j];
12378
+ if (call && typeof call.input_tokens === "number" && Number.isFinite(call.input_tokens) && call.input_tokens > 0) {
12379
+ return call.input_tokens;
12380
+ }
12381
+ }
12382
+ }
12383
+ }
12384
+ } catch {
12385
+ }
12386
+ }
12387
+ return void 0;
12388
+ } catch {
12389
+ return void 0;
12390
+ }
12391
+ }
12392
+
12215
12393
  // packages/cli/client/localRuntimeAdapter.ts
12216
12394
  var currentMetaFile = fileURLToPath(import.meta.url);
12217
12395
  var isJsBundle = extname(currentMetaFile) === ".js";
12218
12396
  var SOURCE_CLI_DIR = isJsBundle ? dirname2(currentMetaFile) : dirname2(dirname2(currentMetaFile));
12219
12397
  var CLI_DIR = isCompiledBinary() ? dirname2(process.execPath) : SOURCE_CLI_DIR;
12220
- var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile : join3(SOURCE_CLI_DIR, "index.ts");
12398
+ var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile : join4(SOURCE_CLI_DIR, "index.ts");
12221
12399
  async function recordLocalAvailabilityForAgent(args) {
12222
12400
  const now = args.now ?? Date.now;
12223
12401
  const { deps, status } = args;
@@ -12415,6 +12593,21 @@ function createCliLocalRuntimeAdapter(deps) {
12415
12593
  sourceCount: input.sourceCount,
12416
12594
  schemaVersion: input.schemaVersion
12417
12595
  }),
12596
+ loadLastContextUsage: async (dialogId) => {
12597
+ const fromDialog = await loadCliDialogLastContextUsage({
12598
+ store: await getOrCreateSharedStore(deps),
12599
+ userId,
12600
+ dialogId
12601
+ });
12602
+ if (fromDialog?.inputTokens) {
12603
+ return fromDialog;
12604
+ }
12605
+ const fromAudit = readLastTurnBillingInputTokens(dialogId, deps.env);
12606
+ if (typeof fromAudit === "number" && fromAudit > 0) {
12607
+ return { inputTokens: fromAudit };
12608
+ }
12609
+ return null;
12610
+ },
12418
12611
  saveTurn: async (input) => writeDialog({
12419
12612
  store: await getOrCreateSharedStore(deps),
12420
12613
  input,
@@ -12632,5 +12825,6 @@ export {
12632
12825
  t,
12633
12826
  toolLabel,
12634
12827
  agentRunCardLabels,
12828
+ appendTurnBillingAudit,
12635
12829
  createCliLocalRuntimeAdapter
12636
12830
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clearCliLocalRuntimePreparedAgentCache
3
- } from "./chunk-Y4AIZ4N2.js";
3
+ } from "./chunk-LJ6OKZ6D.js";
4
4
  import {
5
5
  getReadableCliDb
6
6
  } from "./chunk-RXX4GDIH.js";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  createCliLocalRuntimeAdapter,
3
3
  summarizeEndpoint
4
- } from "./chunk-Y4AIZ4N2.js";
4
+ } from "./chunk-LJ6OKZ6D.js";
5
5
  import {
6
6
  clipMultilineText
7
7
  } from "./chunk-CQ2OZMLQ.js";
8
8
  import {
9
9
  runLocalAgentTurn
10
- } from "./chunk-ECSQC7UV.js";
10
+ } from "./chunk-3ROJR3TG.js";
11
11
  import {
12
12
  applyToolSurfaceConstraints
13
13
  } from "./chunk-RJ2SAFB5.js";
@@ -23,7 +23,7 @@ import "./chunk-KQHGZWSV.js";
23
23
  import "./chunk-HQUORJTM.js";
24
24
  import "./chunk-URMS4XY2.js";
25
25
  import "./chunk-GLKOYSRU.js";
26
- import "./chunk-ECSQC7UV.js";
26
+ import "./chunk-3ROJR3TG.js";
27
27
  import "./chunk-7A3RRUCQ.js";
28
28
  import "./chunk-ZNFJWEN4.js";
29
29
  import "./chunk-XOKOSO35.js";
@@ -28,7 +28,7 @@ import "./chunk-SPAQ4PVV.js";
28
28
  import "./chunk-VF4K2QE6.js";
29
29
  import "./chunk-AETZ7AD6.js";
30
30
  import "./chunk-KHCLMKZZ.js";
31
- import "./chunk-ECSQC7UV.js";
31
+ import "./chunk-3ROJR3TG.js";
32
32
  import "./chunk-7A3RRUCQ.js";
33
33
  import "./chunk-ZNFJWEN4.js";
34
34
  import "./chunk-XOKOSO35.js";
@@ -21,7 +21,7 @@ import "./chunk-KQHGZWSV.js";
21
21
  import "./chunk-VF4K2QE6.js";
22
22
  import "./chunk-AETZ7AD6.js";
23
23
  import "./chunk-KHCLMKZZ.js";
24
- import "./chunk-ECSQC7UV.js";
24
+ import "./chunk-3ROJR3TG.js";
25
25
  import "./chunk-7A3RRUCQ.js";
26
26
  import "./chunk-ZNFJWEN4.js";
27
27
  import "./chunk-XOKOSO35.js";
@@ -16,7 +16,7 @@ import "./chunk-SPAQ4PVV.js";
16
16
  import "./chunk-VF4K2QE6.js";
17
17
  import "./chunk-AETZ7AD6.js";
18
18
  import "./chunk-KHCLMKZZ.js";
19
- import "./chunk-ECSQC7UV.js";
19
+ import "./chunk-3ROJR3TG.js";
20
20
  import "./chunk-7A3RRUCQ.js";
21
21
  import "./chunk-ZNFJWEN4.js";
22
22
  import "./chunk-XOKOSO35.js";
@@ -30,7 +30,7 @@ import {
30
30
  resolvePageSkillMetadata
31
31
  } from "./chunk-AETZ7AD6.js";
32
32
  import "./chunk-KHCLMKZZ.js";
33
- import "./chunk-ECSQC7UV.js";
33
+ import "./chunk-3ROJR3TG.js";
34
34
  import "./chunk-7A3RRUCQ.js";
35
35
  import "./chunk-ZNFJWEN4.js";
36
36
  import "./chunk-XOKOSO35.js";