nolo-cli 0.63.0-alpha.1 → 0.63.0-alpha.3

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-PKOMYDRS.js} +22 -86
  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";
package/index.js CHANGED
@@ -127,7 +127,7 @@ function createDaemonShortcutCommand(path, description, command2) {
127
127
  // packages/cli/agentInternalCommandEntries.ts
128
128
  function getAgentInternalCommandEntries() {
129
129
  const createAgentRunCommand = (path, description) => createContextCommand(path, description, async (args2, ctx) => {
130
- const { runAgentRunCommand } = await import("./agentRunCommand-7MIBF4J7.js");
130
+ const { runAgentRunCommand } = await import("./agentRunCommand-GT5ZTYRM.js");
131
131
  return runAgentRunCommand(args2, {
132
132
  env: ctx.env,
133
133
  scriptDir: ctx.scriptDir,
@@ -139,11 +139,11 @@ function getAgentInternalCommandEntries() {
139
139
  createAgentRunCommand(["run"], "Run a no-login local agent in this workspace"),
140
140
  createAgentRunCommand(["chat"], "Chat with an agent"),
141
141
  createEnvCommand(["agent", "list"], "List owned agents", async (args2, deps) => {
142
- const { runAgentListCommand } = await import("./agentListCommands-43NKDIUT.js");
142
+ const { runAgentListCommand } = await import("./agentListCommands-XJU3JJQO.js");
143
143
  return runAgentListCommand(args2, deps);
144
144
  }),
145
145
  createEnvCommand(["agent", "create"], "Create a new agent", async (args2, deps) => {
146
- const { runAgentCreateCommand } = await import("./agentRecordCommands-UUYNJGVC.js");
146
+ const { runAgentCreateCommand } = await import("./agentRecordCommands-VIEINDIV.js");
147
147
  return runAgentCreateCommand(args2, deps);
148
148
  }),
149
149
  createEnvCommand(["agent", "models"], "List models available on an OpenAI-compatible provider", async (args2, deps) => {
@@ -155,7 +155,7 @@ function getAgentInternalCommandEntries() {
155
155
  return runAgentPullCommand(args2, deps);
156
156
  }),
157
157
  createEnvCommand(["agent", "read"], "Read a single agent", async (args2, deps) => {
158
- const { runAgentReadCommand } = await import("./agentRecordCommands-UUYNJGVC.js");
158
+ const { runAgentReadCommand } = await import("./agentRecordCommands-VIEINDIV.js");
159
159
  return runAgentReadCommand(args2, deps);
160
160
  }),
161
161
  createAgentRunCommand(["agent", "run"], "Run an agent"),
@@ -184,31 +184,31 @@ function getAgentInternalCommandEntries() {
184
184
  return runSetupOfflineMarxistsAgentCommand(args2, deps);
185
185
  }),
186
186
  createEnvCommand(["agent", "update"], "Update agent fields", async (args2, deps) => {
187
- const { runAgentUpdateCommand } = await import("./agentRecordCommands-UUYNJGVC.js");
187
+ const { runAgentUpdateCommand } = await import("./agentRecordCommands-VIEINDIV.js");
188
188
  return runAgentUpdateCommand(args2, deps);
189
189
  }),
190
190
  createEnvCommand(["agent", "email", "provision"], "Provision a controlled inbox for an agent", async (args2, deps) => {
191
- const { runAgentEmailProvisionCommand } = await import("./agentEmailCommands-D74ZOQXN.js");
191
+ const { runAgentEmailProvisionCommand } = await import("./agentEmailCommands-AKENZOKO.js");
192
192
  return runAgentEmailProvisionCommand(args2, deps);
193
193
  }),
194
194
  createEnvCommand(["agent", "email", "bind"], "Bind an existing email address to an agent", async (args2, deps) => {
195
- const { runAgentEmailBindCommand } = await import("./agentEmailCommands-D74ZOQXN.js");
195
+ const { runAgentEmailBindCommand } = await import("./agentEmailCommands-AKENZOKO.js");
196
196
  return runAgentEmailBindCommand(args2, deps);
197
197
  }),
198
198
  createEnvCommand(["agent", "email", "transfer"], "Transfer an email identity from one agent to another (cross-account)", async (args2, deps) => {
199
- const { runAgentEmailTransferCommand } = await import("./agentEmailCommands-D74ZOQXN.js");
199
+ const { runAgentEmailTransferCommand } = await import("./agentEmailCommands-AKENZOKO.js");
200
200
  return runAgentEmailTransferCommand(args2, deps);
201
201
  }),
202
202
  createEnvCommand(
203
203
  ["agent", "email", "create-and-provision"],
204
204
  "Create an agent and provision its controlled inbox",
205
205
  async (args2, deps) => {
206
- const { runAgentEmailCreateAndProvisionCommand } = await import("./agentEmailCommands-D74ZOQXN.js");
206
+ const { runAgentEmailCreateAndProvisionCommand } = await import("./agentEmailCommands-AKENZOKO.js");
207
207
  return runAgentEmailCreateAndProvisionCommand(args2, deps);
208
208
  }
209
209
  ),
210
210
  createEnvCommand(["agent", "delete"], "Hard-delete an agent's private and public records", async (args2, deps) => {
211
- const { runAgentDeleteCommand } = await import("./agentDeleteCommand-NTUC5X4H.js");
211
+ const { runAgentDeleteCommand } = await import("./agentDeleteCommand-6R6EXQOR.js");
212
212
  return runAgentDeleteCommand(args2, deps);
213
213
  }),
214
214
  createEnvCommand(["agent", "grant"], "Grant another user access to this agent's owner credentials", async (args2, deps) => {
@@ -224,15 +224,15 @@ function getAgentInternalCommandEntries() {
224
224
  return runAgentRevokeGrantCommand(args2, deps);
225
225
  }),
226
226
  createEnvCommand(["agent", "bind-current"], "Bind an agent to this machine", async (args2, deps) => {
227
- const { runAgentBindCurrentCommand } = await import("./agentMachineCommands-5MPEQQMR.js");
227
+ const { runAgentBindCurrentCommand } = await import("./agentMachineCommands-V7IJDPAY.js");
228
228
  return runAgentBindCurrentCommand(args2, deps);
229
229
  }),
230
230
  createEnvCommand(["agent", "smoke-current"], "Smoke test a bound agent through this machine", async (args2, deps) => {
231
- const { runAgentSmokeCurrentCommand } = await import("./agentMachineCommands-5MPEQQMR.js");
231
+ const { runAgentSmokeCurrentCommand } = await import("./agentMachineCommands-V7IJDPAY.js");
232
232
  return runAgentSmokeCurrentCommand(args2, deps);
233
233
  }),
234
234
  createEnvCommand(["agent", "runtime-doctor"], "Diagnose current machine runtime compatibility", async (args2, deps) => {
235
- const { runAgentRuntimeDoctorCommand } = await import("./agentMachineCommands-5MPEQQMR.js");
235
+ const { runAgentRuntimeDoctorCommand } = await import("./agentMachineCommands-V7IJDPAY.js");
236
236
  return runAgentRuntimeDoctorCommand(args2, deps);
237
237
  }),
238
238
  createAgentRunCommand(["agent", "chat"], "Chat with an agent")
@@ -243,23 +243,23 @@ function getAgentInternalCommandEntries() {
243
243
  function getAppInternalCommandEntries() {
244
244
  return [
245
245
  createEnvCommand(["app", "list"], "List your apps", async (args2, deps) => {
246
- const { runAppListCommand } = await import("./appListCommands-5BMCSU66.js");
246
+ const { runAppListCommand } = await import("./appListCommands-5NGZQ6IK.js");
247
247
  return runAppListCommand(args2, deps);
248
248
  }),
249
249
  createEnvCommand(["app", "get"], "Get app details", async (args2, deps) => {
250
- const { runAppGetCommand } = await import("./appGetCommands-GRO6QDM3.js");
250
+ const { runAppGetCommand } = await import("./appGetCommands-NQYXHVJL.js");
251
251
  return runAppGetCommand(args2, deps);
252
252
  }),
253
253
  createEnvCommand(["app", "deploy"], "Deploy an app", async (args2, deps) => {
254
- const { runAppDeployCommand } = await import("./appDeployCommands-LOACOW26.js");
254
+ const { runAppDeployCommand } = await import("./appDeployCommands-PABMVMN2.js");
255
255
  return runAppDeployCommand(args2, deps);
256
256
  }),
257
257
  createEnvCommand(["app", "deploy", "status"], "Check app deploy status", async (args2, deps) => {
258
- const { runAppDeployStatusCommand } = await import("./appDeployStatusCommands-2RKASRYO.js");
258
+ const { runAppDeployStatusCommand } = await import("./appDeployStatusCommands-X7WEU4TU.js");
259
259
  return runAppDeployStatusCommand(args2, deps);
260
260
  }),
261
261
  createEnvCommand(["app", "delete"], "Delete an app", async (args2, deps) => {
262
- const { runAppDeleteCommand } = await import("./appDeleteCommands-VTIDMUUS.js");
262
+ const { runAppDeleteCommand } = await import("./appDeleteCommands-VG2UVW4T.js");
263
263
  return runAppDeleteCommand(args2, deps);
264
264
  })
265
265
  ];
@@ -269,23 +269,23 @@ function getAppInternalCommandEntries() {
269
269
  function getDialogInternalCommandEntries() {
270
270
  return [
271
271
  createEnvCommand(["dialog", "list"], "List dialogs (default --limit 50; --all/--limit 0 full; --jsonl streams)", async (args2, deps) => {
272
- const { runDialogListCommand } = await import("./dialogCommands-PPONZF6D.js");
272
+ const { runDialogListCommand } = await import("./dialogCommands-HGMV4NQJ.js");
273
273
  return runDialogListCommand(args2, deps);
274
274
  }),
275
275
  createEnvCommand(["dialog", "delete"], "Delete one or more dialogs", async (args2, deps) => {
276
- const { runDialogDeleteCommand } = await import("./dialogCommands-PPONZF6D.js");
276
+ const { runDialogDeleteCommand } = await import("./dialogCommands-HGMV4NQJ.js");
277
277
  return runDialogDeleteCommand(args2, deps);
278
278
  }),
279
279
  createEnvCommand(["dialog", "query"], "Query dialogs by subject refs (default --limit 50; --all full; --jsonl streams)", async (args2, deps) => {
280
- const { runDialogQueryCommand } = await import("./dialogCommands-PPONZF6D.js");
280
+ const { runDialogQueryCommand } = await import("./dialogCommands-HGMV4NQJ.js");
281
281
  return runDialogQueryCommand(args2, deps);
282
282
  }),
283
283
  createEnvCommand(["dialog", "read"], "Read a dialog", async (args2, deps) => {
284
- const { runDialogReadCommand } = await import("./dialogCommands-PPONZF6D.js");
284
+ const { runDialogReadCommand } = await import("./dialogCommands-HGMV4NQJ.js");
285
285
  return runDialogReadCommand(args2, deps);
286
286
  }),
287
287
  createEnvCommand(["dialog", "status"], "Read compact dialog status", async (args2, deps) => {
288
- const { runDialogStatusCommand } = await import("./dialogCommands-PPONZF6D.js");
288
+ const { runDialogStatusCommand } = await import("./dialogCommands-HGMV4NQJ.js");
289
289
  return runDialogStatusCommand(args2, deps);
290
290
  })
291
291
  ];
@@ -295,39 +295,39 @@ function getDialogInternalCommandEntries() {
295
295
  function getDocInternalCommandEntries() {
296
296
  return [
297
297
  createEnvCommand(["doc", "create"], "Create a normal doc", async (args2, deps) => {
298
- const { runDocCreateCommand } = await import("./docCreateCommands-SJSQAX4J.js");
298
+ const { runDocCreateCommand } = await import("./docCreateCommands-WQT5EZG2.js");
299
299
  return runDocCreateCommand(args2, deps);
300
300
  }),
301
301
  createEnvCommand(["doc", "read"], "Read a normal doc", async (args2, deps) => {
302
- const { runDocReadCommand } = await import("./docReadCommands-RHD6RPV7.js");
302
+ const { runDocReadCommand } = await import("./docReadCommands-T6FDDKJ3.js");
303
303
  return runDocReadCommand(args2, deps);
304
304
  }),
305
305
  createEnvCommand(["doc", "update"], "Update a normal doc", async (args2, deps) => {
306
- const { runDocUpdateCommand } = await import("./docUpdateCommands-5OLZXCEB.js");
306
+ const { runDocUpdateCommand } = await import("./docUpdateCommands-GBWGXG2G.js");
307
307
  return runDocUpdateCommand(args2, deps);
308
308
  }),
309
309
  createEnvCommand(["doc", "delete"], "Delete a normal doc", async (args2, deps) => {
310
- const { runDocDeleteCommand } = await import("./docDeleteCommands-T4IFYPWR.js");
310
+ const { runDocDeleteCommand } = await import("./docDeleteCommands-GUMELBKM.js");
311
311
  return runDocDeleteCommand(args2, deps);
312
312
  }),
313
313
  createEnvCommand(["skill-doc", "create"], "Create a skill-backed doc", async (args2, deps) => {
314
- const { runSkillDocCreateCommand } = await import("./docCreateCommands-SJSQAX4J.js");
314
+ const { runSkillDocCreateCommand } = await import("./docCreateCommands-WQT5EZG2.js");
315
315
  return runSkillDocCreateCommand(args2, deps);
316
316
  }),
317
317
  createEnvCommand(["skill", "create-doc"], "Create a skill-backed doc", async (args2, deps) => {
318
- const { runSkillDocCreateCommand } = await import("./docCreateCommands-SJSQAX4J.js");
318
+ const { runSkillDocCreateCommand } = await import("./docCreateCommands-WQT5EZG2.js");
319
319
  return runSkillDocCreateCommand(args2, deps);
320
320
  }),
321
321
  createEnvCommand(["skill-doc", "read"], "Read a skill doc", async (args2, deps) => {
322
- const { runSkillDocReadCommand } = await import("./docReadCommands-RHD6RPV7.js");
322
+ const { runSkillDocReadCommand } = await import("./docReadCommands-T6FDDKJ3.js");
323
323
  return runSkillDocReadCommand(args2, deps);
324
324
  }),
325
325
  createEnvCommand(["skill-doc", "update"], "Update a skill doc", async (args2, deps) => {
326
- const { runSkillDocUpdateCommand } = await import("./docUpdateCommands-5OLZXCEB.js");
326
+ const { runSkillDocUpdateCommand } = await import("./docUpdateCommands-GBWGXG2G.js");
327
327
  return runSkillDocUpdateCommand(args2, deps);
328
328
  }),
329
329
  createEnvCommand(["skill-doc", "delete"], "Delete a skill doc", async (args2, deps) => {
330
- const { runSkillDocDeleteCommand } = await import("./docDeleteCommands-T4IFYPWR.js");
330
+ const { runSkillDocDeleteCommand } = await import("./docDeleteCommands-GUMELBKM.js");
331
331
  return runSkillDocDeleteCommand(args2, deps);
332
332
  })
333
333
  ];
@@ -355,19 +355,19 @@ function getMemoryInternalCommandEntries() {
355
355
  function getSpaceInternalCommandEntries() {
356
356
  return [
357
357
  createEnvCommand(["space", "create"], "Create a space", async (args2, deps) => {
358
- const { runSpaceCreateCommand } = await import("./spaceCommands-OAKDKTZV.js");
358
+ const { runSpaceCreateCommand } = await import("./spaceCommands-76ECKNFH.js");
359
359
  return runSpaceCreateCommand(args2, deps);
360
360
  }),
361
361
  createEnvCommand(["space", "invite"], "Invite an existing user to a space", async (args2, deps) => {
362
- const { runSpaceInviteCommand } = await import("./spaceCommands-OAKDKTZV.js");
362
+ const { runSpaceInviteCommand } = await import("./spaceCommands-76ECKNFH.js");
363
363
  return runSpaceInviteCommand(args2, deps);
364
364
  }),
365
365
  createEnvCommand(["space", "accept-invite"], "Accept a space invite", async (args2, deps) => {
366
- const { runSpaceAcceptInviteCommand } = await import("./spaceCommands-OAKDKTZV.js");
366
+ const { runSpaceAcceptInviteCommand } = await import("./spaceCommands-76ECKNFH.js");
367
367
  return runSpaceAcceptInviteCommand(args2, deps);
368
368
  }),
369
369
  createEnvCommand(["space", "upload"], "Upload a file to a space", async (args2, deps) => {
370
- const { runSpaceUploadCommand } = await import("./spaceCommands-OAKDKTZV.js");
370
+ const { runSpaceUploadCommand } = await import("./spaceCommands-76ECKNFH.js");
371
371
  return runSpaceUploadCommand(args2, deps);
372
372
  })
373
373
  ];
@@ -417,15 +417,15 @@ function getSystemInternalCommandEntries(renderHelpText2) {
417
417
  return runWhoamiCommand({ args: args2, env: ctx.env });
418
418
  }),
419
419
  createEntrypointEnvCommand(["connect"], "Send machine heartbeats or hold a connector websocket", async (args2, deps) => {
420
- const { runMachineConnectCommand } = await import("./machineCommands-Y6NJLJ77.js");
420
+ const { runMachineConnectCommand } = await import("./machineCommands-SCGLQQCA.js");
421
421
  return runMachineConnectCommand(args2, deps);
422
422
  }),
423
423
  createDaemonShortcutCommand(["daemon"], "Run the connector daemon shortcut", async (args2, deps) => {
424
- const { runMachineConnectCommand } = await import("./machineCommands-Y6NJLJ77.js");
424
+ const { runMachineConnectCommand } = await import("./machineCommands-SCGLQQCA.js");
425
425
  return runMachineConnectCommand(args2, deps);
426
426
  }),
427
427
  createEnvCommand(["machine", "status"], "List machines registered to the current profile", async (args2, deps) => {
428
- const { runMachineStatusCommand } = await import("./machineCommands-Y6NJLJ77.js");
428
+ const { runMachineStatusCommand } = await import("./machineCommands-SCGLQQCA.js");
429
429
  return runMachineStatusCommand(args2, deps);
430
430
  }),
431
431
  createEnvCommand(["doctor", "runtime"], "Diagnose local-first agent runtime selection", async (args2, deps) => {
@@ -815,11 +815,13 @@ async function runScript(script, forwardedArgs, env) {
815
815
  return proc.exited;
816
816
  }
817
817
  async function launchTuiWorkspace(args2) {
818
- const { startTuiWorkspace } = await import("./readlineWorkspace-F3IYM37K.js");
818
+ const { startTuiWorkspace } = await import("./readlineWorkspace-PKOMYDRS.js");
819
819
  const { createTuiSummaryLlmCaller } = await import("./tuiSummaryLlmCaller-F3DPFFZM.js");
820
820
  return startTuiWorkspace({
821
821
  ...args2,
822
- summaryLlmCaller: createTuiSummaryLlmCaller(args2.env)
822
+ // Big dialogs produce ~300KB+ summary prompts that routinely take 25–30s+;
823
+ // the old 30s abort made manual /compact silently degrade to fork-only.
824
+ summaryLlmCaller: createTuiSummaryLlmCaller(args2.env, { timeoutMs: 9e4 })
823
825
  });
824
826
  }
825
827
  var args = process.argv.slice(2);
@@ -2,13 +2,13 @@ import {
2
2
  buildMachinePermissionPromptBlock,
3
3
  handleConnectorRunMessage,
4
4
  resolveMachineRunPermissionPolicy
5
- } from "./chunk-CGUUOBD2.js";
5
+ } from "./chunk-URHZKKK7.js";
6
6
  import {
7
7
  isConnectorWebSocketAuthError,
8
8
  isConnectorWebSocketRetryableError,
9
9
  resolveConnectorWebSocketTarget
10
10
  } from "./chunk-ALXHV7NK.js";
11
- import "./chunk-Y4AIZ4N2.js";
11
+ import "./chunk-LJ6OKZ6D.js";
12
12
  import "./chunk-MXUDQZXQ.js";
13
13
  import "./chunk-EADNWBAZ.js";
14
14
  import "./chunk-45YO6H7P.js";
@@ -66,7 +66,7 @@ import "./chunk-KHCLMKZZ.js";
66
66
  import {
67
67
  PATH_FIELD_ALIASES,
68
68
  createLocalWorkspaceToolExecutors
69
- } from "./chunk-ECSQC7UV.js";
69
+ } from "./chunk-3ROJR3TG.js";
70
70
  import "./chunk-7A3RRUCQ.js";
71
71
  import "./chunk-ZNFJWEN4.js";
72
72
  import "./chunk-XOKOSO35.js";
@@ -11,8 +11,8 @@ import {
11
11
  runtimeWorkspacePermissionPolicy,
12
12
  scopePermissionPolicyToRuntimeWorkspace,
13
13
  summarizeAgentConfigForLogs
14
- } from "./chunk-CGUUOBD2.js";
15
- import "./chunk-Y4AIZ4N2.js";
14
+ } from "./chunk-URHZKKK7.js";
15
+ import "./chunk-LJ6OKZ6D.js";
16
16
  import "./chunk-MXUDQZXQ.js";
17
17
  import "./chunk-EADNWBAZ.js";
18
18
  import "./chunk-45YO6H7P.js";
@@ -62,7 +62,7 @@ import "./chunk-E3YVTQWT.js";
62
62
  import "./chunk-ZRSJ3JEH.js";
63
63
  import "./chunk-AETZ7AD6.js";
64
64
  import "./chunk-KHCLMKZZ.js";
65
- import "./chunk-ECSQC7UV.js";
65
+ import "./chunk-3ROJR3TG.js";
66
66
  import "./chunk-7A3RRUCQ.js";
67
67
  import "./chunk-ZNFJWEN4.js";
68
68
  import "./chunk-XOKOSO35.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nolo-cli",
3
- "version": "0.63.0-alpha.1",
3
+ "version": "0.63.0-alpha.3",
4
4
  "type": "module",
5
5
  "description": "Agent-first terminal workspace for Nolo",
6
6
  "bin": {
@@ -72,7 +72,7 @@ import {
72
72
  wrapTextToLines,
73
73
  wrapTranscriptLine,
74
74
  wrapTranscriptLineWithLayout
75
- } from "./chunk-JNDDM6BU.js";
75
+ } from "./chunk-BWIPK2PD.js";
76
76
  import "./chunk-S7Z2HMCN.js";
77
77
  import {
78
78
  listFavoriteAgentIdsAcrossServers,
@@ -89,6 +89,7 @@ import {
89
89
  import "./chunk-JYYZCK2Z.js";
90
90
  import {
91
91
  RUN_WAKE_CHANNEL_ENV,
92
+ appendTurnBillingAudit,
92
93
  createCliLocalRuntimeAdapter,
93
94
  dailyWelcomeTip,
94
95
  initCliLocale,
@@ -96,7 +97,7 @@ import {
96
97
  readTimestamp,
97
98
  setCliLocale,
98
99
  t
99
- } from "./chunk-Y4AIZ4N2.js";
100
+ } from "./chunk-LJ6OKZ6D.js";
100
101
  import "./chunk-MXUDQZXQ.js";
101
102
  import "./chunk-EADNWBAZ.js";
102
103
  import {
@@ -170,8 +171,7 @@ import "./chunk-DWYSDNOH.js";
170
171
  import "./chunk-N6HLMLKE.js";
171
172
  import "./chunk-ZJ7UHBJS.js";
172
173
  import {
173
- extractReferenceKeysFromMessage,
174
- normalizeUsage
174
+ extractReferenceKeysFromMessage
175
175
  } from "./chunk-TBHAHL33.js";
176
176
  import "./chunk-EVBFYPDC.js";
177
177
  import "./chunk-HQUORJTM.js";
@@ -202,7 +202,7 @@ import {
202
202
  buildLocalWorkspaceToolset,
203
203
  getProcessRegistry,
204
204
  readCommandActionGatePayload
205
- } from "./chunk-ECSQC7UV.js";
205
+ } from "./chunk-3ROJR3TG.js";
206
206
  import "./chunk-7A3RRUCQ.js";
207
207
  import "./chunk-ZNFJWEN4.js";
208
208
  import "./chunk-XOKOSO35.js";
@@ -6241,7 +6241,7 @@ ${t("autoUsage")}`
6241
6241
  }
6242
6242
  return {
6243
6243
  nextState: state,
6244
- output: "Compacting current dialog...",
6244
+ output: t("compactingDialog"),
6245
6245
  action: { type: "compact", dialogId: state.dialogId }
6246
6246
  };
6247
6247
  case "/agent":
@@ -6689,66 +6689,6 @@ function normalizeStatus(raw) {
6689
6689
  return "failed";
6690
6690
  }
6691
6691
 
6692
- // packages/cli/client/turnBillingAudit.ts
6693
- import { appendFileSync, mkdirSync as mkdirSync2 } from "node:fs";
6694
- import { homedir as homedir4 } from "node:os";
6695
- import { join as join3 } from "node:path";
6696
- function projectUsageForAudit(usage) {
6697
- if (!usage || typeof usage !== "object") return null;
6698
- const normalized = normalizeUsage(usage);
6699
- const projected = {
6700
- input_tokens: normalized.input_tokens,
6701
- output_tokens: normalized.output_tokens,
6702
- cache_read_input_tokens: normalized.cache_read_input_tokens,
6703
- cache_creation_input_tokens: normalized.cache_creation_input_tokens
6704
- };
6705
- if (typeof usage.cost === "number" && Number.isFinite(usage.cost)) {
6706
- projected.cost = usage.cost;
6707
- }
6708
- if (typeof usage.billing_unit === "string" && usage.billing_unit.trim()) {
6709
- projected.billing_unit = usage.billing_unit;
6710
- }
6711
- if (typeof usage.provider_call_id === "string" && usage.provider_call_id.trim()) {
6712
- projected.provider_call_id = usage.provider_call_id.trim();
6713
- }
6714
- return projected;
6715
- }
6716
- function resolveTurnBillingAuditLogPath(env = process.env) {
6717
- const noloHome = env.NOLO_HOME?.trim() || join3(homedir4(), ".nolo");
6718
- return join3(noloHome, "logs", "turn-billing.jsonl");
6719
- }
6720
- function appendTurnBillingAudit(input) {
6721
- try {
6722
- if (process.env.NOLO_TURN_BILLING_AUDIT === "0") return;
6723
- const calls = (input.usageRecords ?? []).map((record) => {
6724
- const usage = projectUsageForAudit(record?.usage);
6725
- if (!usage) return null;
6726
- return {
6727
- ...record?.callId ? { callId: record.callId } : {},
6728
- ...record?.model ? { model: record.model } : {},
6729
- ...record?.provider ? { provider: record.provider } : {},
6730
- ...usage
6731
- };
6732
- }).filter((call) => call !== null);
6733
- if (calls.length === 0 && (input.turnCredits === void 0 || input.turnCredits === null)) {
6734
- return;
6735
- }
6736
- const row = {
6737
- ts: Date.now(),
6738
- ...input.dialogId ? { dialogId: input.dialogId } : {},
6739
- ...input.agentKey ? { agentKey: input.agentKey } : {},
6740
- ...input.turnCredits !== void 0 && input.turnCredits !== null ? { turnCredits: input.turnCredits } : {},
6741
- ...input.aborted ? { aborted: true } : {},
6742
- calls
6743
- };
6744
- const logPath = resolveTurnBillingAuditLogPath();
6745
- mkdirSync2(join3(logPath, ".."), { recursive: true });
6746
- appendFileSync(logPath, `${JSON.stringify(row)}
6747
- `);
6748
- } catch {
6749
- }
6750
- }
6751
-
6752
6692
  // packages/ai/tools/askChoiceState.ts
6753
6693
  function normalizeAskChoiceArgs(args) {
6754
6694
  const blocking = args.blocking !== false;
@@ -8282,17 +8222,8 @@ function createTuiRender(host) {
8282
8222
  import { ulid } from "ulid";
8283
8223
  var DB_PATH = "/api/v1/db";
8284
8224
  function parseTokenUserId(token) {
8285
- try {
8286
- const parts = token.split(".");
8287
- if (parts.length < 2) return null;
8288
- const payloadBase64 = parts[1];
8289
- const payload = JSON.parse(
8290
- Buffer.from(payloadBase64, "base64").toString("utf8")
8291
- );
8292
- return typeof payload?.userId === "string" ? payload.userId : null;
8293
- } catch {
8294
- return null;
8295
- }
8225
+ const userId = parseUserIdFromAuthToken(token);
8226
+ return userId || null;
8296
8227
  }
8297
8228
  async function readDialogRecord(fetchImpl, serverUrl, authToken, dialogKey) {
8298
8229
  const res = await fetchImpl(`${serverUrl}${DB_PATH}/read/${dialogKey}`, {
@@ -8327,7 +8258,7 @@ async function patchDialog(fetchImpl, serverUrl, authToken, dialogKey, changes)
8327
8258
  "Content-Type": "application/json",
8328
8259
  Authorization: `Bearer ${authToken}`
8329
8260
  },
8330
- body: JSON.stringify({ data: changes })
8261
+ body: JSON.stringify(changes)
8331
8262
  });
8332
8263
  if (!res.ok) {
8333
8264
  throw new Error(`Failed to patch dialog "${dialogKey}": HTTP ${res.status}`);
@@ -8433,12 +8364,13 @@ async function resolveContextWindow(fetchImpl, serverUrl, authToken, agentKey) {
8433
8364
  }
8434
8365
  async function compactDialog(options) {
8435
8366
  const fetchImpl = options.fetchImpl ?? fetch;
8436
- const userId = parseTokenUserId(options.authToken);
8367
+ const userId = options.userId || parseTokenUserId(options.authToken);
8437
8368
  if (!userId) {
8438
8369
  throw new Error(
8439
8370
  "[nolo] compact: cannot compact \u2014 invalid or missing auth token"
8440
8371
  );
8441
8372
  }
8373
+ options.onProgress?.("reading");
8442
8374
  const dialogKey = `dialog-${userId}-${options.dialogId}`;
8443
8375
  const current = await readDialogRecord(
8444
8376
  fetchImpl,
@@ -8472,6 +8404,7 @@ async function compactDialog(options) {
8472
8404
  reason: "manual"
8473
8405
  });
8474
8406
  if (plan.shouldCompress && plan.msgsToCompress.length > 0) {
8407
+ options.onProgress?.("summarizing");
8475
8408
  const previousSummary = current.summary || "";
8476
8409
  const messagesText = formatMessagesForSummaryWithTruncation(plan.msgsToCompress);
8477
8410
  const fileOpsText = formatFileOperationsFromMessages(
@@ -8520,6 +8453,7 @@ async function compactDialog(options) {
8520
8453
  }
8521
8454
  }
8522
8455
  }
8456
+ options.onProgress?.("forking");
8523
8457
  const next = buildForkedDialogRecord(current, userId);
8524
8458
  await writeDialogRecord(fetchImpl, options.serverUrl, options.authToken, next);
8525
8459
  await addDialogToSpaceIfNeeded(
@@ -9483,7 +9417,13 @@ async function runSubmittedSlashLine(line, host, actionGateHandler, confirmDestr
9483
9417
  serverUrl: host.state.serverUrl,
9484
9418
  authToken,
9485
9419
  dialogId: result.action.dialogId,
9486
- summaryLlmCaller: options.summaryLlmCaller
9420
+ summaryLlmCaller: options.summaryLlmCaller,
9421
+ onProgress: (phase) => {
9422
+ const phaseText = phase === "reading" ? t("compactPhaseReading") : phase === "summarizing" ? t("compactPhaseSummarizing") : phase === "forking" ? t("compactPhaseForking") : void 0;
9423
+ if (phaseText) {
9424
+ emitCommandOutput(phaseText);
9425
+ }
9426
+ }
9487
9427
  });
9488
9428
  const elapsedSec = ((Date.now() - compactStart) / 1e3).toFixed(1);
9489
9429
  host.state = {
@@ -9532,13 +9472,9 @@ async function runSubmittedSlashLine(line, host, actionGateHandler, confirmDestr
9532
9472
  compactResult.dialogId,
9533
9473
  elapsed
9534
9474
  );
9535
- output.write(`${message}
9536
- `);
9475
+ emitCommandOutput(message);
9537
9476
  } catch (error) {
9538
- output.write(
9539
- `[nolo] Compact failed: ${toErrorMessage(error)}
9540
- `
9541
- );
9477
+ emitCommandOutput(t("compactFailed", toErrorMessage(error)));
9542
9478
  }
9543
9479
  }
9544
9480
  if (result.action?.type === "self-update") {
@@ -11,7 +11,7 @@ import {
11
11
  import "./chunk-CTCW7U7N.js";
12
12
  import "./chunk-SPAQ4PVV.js";
13
13
  import "./chunk-KQHGZWSV.js";
14
- import "./chunk-ECSQC7UV.js";
14
+ import "./chunk-3ROJR3TG.js";
15
15
  import "./chunk-7A3RRUCQ.js";
16
16
  import "./chunk-ZNFJWEN4.js";
17
17
  import "./chunk-XOKOSO35.js";