nolo-cli 0.38.0-alpha.2 → 0.47.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 (143) hide show
  1. package/{_executeModel-2S6HNTBF.js → _executeModel-JWAASOOT.js} +43 -45
  2. package/{action-KMBZ3LCZ.js → action-FLLC2SIX.js} +7 -7
  3. package/{addContentAction-KQ44UT2U.js → addContentAction-SVSPUUK4.js} +6 -6
  4. package/{addDialogAgentAction-ILSDCMYL.js → addDialogAgentAction-W3JGU4F7.js} +5 -5
  5. package/{agentDeleteCommand-6XYC7JVL.js → agentDeleteCommand-QL7TF5F2.js} +26 -27
  6. package/{agentEmailCommands-NGL5B3UC.js → agentEmailCommands-AC3XQM53.js} +57 -59
  7. package/{agentListCommands-R7TKN3DL.js → agentListCommands-4YMFHDU6.js} +33 -31
  8. package/{agentMachineCommands-AXOO4OKN.js → agentMachineCommands-MFQKYUV4.js} +25 -26
  9. package/{agentPullCommand-TSWAJPS2.js → agentPullCommand-M552CYSI.js} +2 -2
  10. package/{agentRecordCommands-GJHH5GYI.js → agentRecordCommands-QG3YBSTQ.js} +53 -55
  11. package/{agentRunCommand-4MEMHFT5.js → agentRunCommand-B4PGT36L.js} +56 -58
  12. package/{agentRunControl-7MUPSYDQ.js → agentRunControl-LHXOP4IU.js} +43 -1
  13. package/{agentRuntimeLocal-CPEWDR3Z.js → agentRuntimeLocal-V2UKJPNE.js} +21 -22
  14. package/{agentSlice-LAILHBMM.js → agentSlice-B5O3RTRP.js} +6 -6
  15. package/{agentSuperviseCommands-MKWW3ICX.js → agentSuperviseCommands-IMRZ56RC.js} +2 -2
  16. package/{appDeleteCommands-6SYOAMTR.js → appDeleteCommands-BQCRRHOM.js} +25 -26
  17. package/{appDeployCommands-ZNMFUV2K.js → appDeployCommands-UMJ67TUR.js} +25 -26
  18. package/{appDeployStatusCommands-G5FIZT64.js → appDeployStatusCommands-KASPUR4V.js} +25 -26
  19. package/{appGetCommands-4RIFLLZZ.js → appGetCommands-FFT2LTGF.js} +25 -26
  20. package/{appListCommands-DK2JJ65T.js → appListCommands-TAVWFRZZ.js} +25 -26
  21. package/{authCommand-B2XRHNJH.js → authCommand-OY2E2VQK.js} +12 -12
  22. package/{authCommands-GWABTFMR.js → authCommands-SBQVTD6V.js} +5 -5
  23. package/{chatQueueReduxAdapter-DQWFZYNL.js → chatQueueReduxAdapter-OVDKLHLD.js} +20 -20
  24. package/chunk-25J3BB35.js +6041 -0
  25. package/chunk-2BWU4ORW.js +2574 -0
  26. package/{chunk-U6QQLXWI.js → chunk-2X5S4IBZ.js} +1 -1
  27. package/{chunk-MJWX4JQO.js → chunk-3EEK7T3D.js} +1 -1
  28. package/{chunk-UNHKVD2N.js → chunk-43CXXVJD.js} +1 -1
  29. package/{chunk-WRP5TTM6.js → chunk-4MXGXSYN.js} +83 -3
  30. package/{chunk-2KO5QQFV.js → chunk-5IQX2XPA.js} +2 -2
  31. package/{chunk-ARFXKWJH.js → chunk-5PFBRLJN.js} +157 -51
  32. package/{chunk-W445DPVT.js → chunk-5QRCPERU.js} +1 -1
  33. package/{chunk-GKHV4UH5.js → chunk-5UOBIU5G.js} +31 -3
  34. package/{chunk-BMB563Y6.js → chunk-6BYAXNH5.js} +3 -3
  35. package/{chunk-SMPAUSX5.js → chunk-6FGXGFAH.js} +2 -2
  36. package/{chunk-6XIE5ZGI.js → chunk-6HIGYUBQ.js} +1 -1
  37. package/{chunk-NT3QRCVS.js → chunk-7US2USK7.js} +7 -7
  38. package/{chunk-FTM4KUOZ.js → chunk-7XTC3KRG.js} +1 -1
  39. package/{chunk-IMHO5LC6.js → chunk-7XZ5GXSN.js} +1 -1
  40. package/{chunk-E2OQ5N2F.js → chunk-AEXP2UZT.js} +341 -16
  41. package/{chunk-MZZZYUZS.js → chunk-AV2CELZZ.js} +37 -12
  42. package/{chunk-JI2TIPLP.js → chunk-AYXSUBVC.js} +1 -1
  43. package/{chunk-KR74XLMV.js → chunk-BIMCW2CC.js} +3 -3
  44. package/{chunk-GEGSCLZZ.js → chunk-C5UWCCLI.js} +3 -3
  45. package/{chunk-J6WH4PYZ.js → chunk-CIF4X6ZM.js} +1 -1
  46. package/{chunk-LZZQTQPY.js → chunk-CTXR4SRT.js} +3 -3
  47. package/{chunk-GZRMWK5R.js → chunk-DQLYEGP7.js} +2 -2
  48. package/{chunk-45NBTCS2.js → chunk-DROE55W3.js} +216 -48
  49. package/{chunk-GUYMR3JL.js → chunk-E2QH2AYX.js} +69 -3
  50. package/{chunk-B6H5XCT2.js → chunk-EMEUU5IY.js} +3 -3
  51. package/{chunk-X6EN3KJX.js → chunk-ENYDQKOB.js} +319 -71
  52. package/{chunk-RCFIB45Q.js → chunk-EVBFYPDC.js} +2 -2
  53. package/{chunk-PV734VZX.js → chunk-EXLOROHG.js} +1 -1
  54. package/{chunk-KHCLMKZZ.js → chunk-EY7V7REW.js} +280 -6
  55. package/{chunk-WRN7L5CS.js → chunk-FA4SY4F5.js} +1 -1
  56. package/{chunk-IFS5CUEH.js → chunk-FJHLA6SX.js} +1 -1
  57. package/{chunk-D72M3G32.js → chunk-FM6ZGNMV.js} +12 -12
  58. package/{chunk-T2BZICLK.js → chunk-G46DB6KG.js} +49 -6
  59. package/{chunk-FGLKRJDI.js → chunk-GK74OOFT.js} +2 -2
  60. package/{chunk-LM6IYQ3F.js → chunk-GLKOYSRU.js} +8 -1
  61. package/{chunk-YNAGAUJT.js → chunk-GYSVYO35.js} +61 -49
  62. package/{chunk-JIADXJYU.js → chunk-H2G6JXTR.js} +1 -1
  63. package/{chunk-MGIHZ5CJ.js → chunk-HAPCUPEO.js} +2 -2
  64. package/{chunk-LD6Y6RJY.js → chunk-HGDOIDQ4.js} +2 -2
  65. package/{chunk-IZNJDUJ4.js → chunk-I4JISVWK.js} +1 -1
  66. package/{chunk-N4XRDM26.js → chunk-IA3A5373.js} +2 -2
  67. package/{chunk-X2K2JSO4.js → chunk-IWUMSAQF.js} +5 -1
  68. package/{chunk-GEPHJJW4.js → chunk-L7NG2M6H.js} +1 -1
  69. package/{chunk-XQES6LXQ.js → chunk-LFLWZX76.js} +2 -2
  70. package/{chunk-IIOHYLIG.js → chunk-LGUQHYAL.js} +1 -1
  71. package/{chunk-4AWH4LQA.js → chunk-LYGNQHUW.js} +3 -1
  72. package/{db-3H3JECGY.js → chunk-M5PVFLD4.js} +11 -158
  73. package/{chunk-WN5AJG5I.js → chunk-MKZRKDQM.js} +1 -1
  74. package/{chunk-V5GA74HI.js → chunk-MZXZJVVD.js} +20 -39
  75. package/{chunk-EJAL5LSG.js → chunk-NC3CSWVT.js} +2 -2
  76. package/{chunk-6XG52ZQ6.js → chunk-NI2BS6UD.js} +22 -3
  77. package/{chunk-FXZBSLFK.js → chunk-NSQNNYGW.js} +20 -51
  78. package/{chunk-VOXNBPLB.js → chunk-OFSVXPQS.js} +651 -43
  79. package/{chunk-ZBB3MZR3.js → chunk-OLNC7AWK.js} +7 -4
  80. package/{chunk-J5NMOM35.js → chunk-OYNDYVSE.js} +1 -1
  81. package/{chunk-C6ELZQ7H.js → chunk-OZVGA4SY.js} +1 -1
  82. package/{chunk-K4KIFRIN.js → chunk-Q24S4NDF.js} +1 -1
  83. package/{chunk-HRSIJO5A.js → chunk-RNNAJ34U.js} +1 -1
  84. package/{chunk-JK7UM3LT.js → chunk-SEIOEDBB.js} +110 -49
  85. package/{chunk-2WKUUY2E.js → chunk-SVEUG45B.js} +5 -3
  86. package/{chunk-IZCHPD7T.js → chunk-TNPCQNGQ.js} +11 -6
  87. package/{chunk-4DMPISV6.js → chunk-URBGEE42.js} +2 -2
  88. package/{chunk-23KKIMD5.js → chunk-WVGEBWA6.js} +4 -4
  89. package/{chunk-TH7ZZKPJ.js → chunk-XIRSTDYF.js} +275 -134
  90. package/{chunk-64KIQZA2.js → chunk-XO3G35OV.js} +1 -1
  91. package/{chunk-CVXDBLYH.js → chunk-XOFZEJGM.js} +5 -5
  92. package/{chunk-XT73C4VH.js → chunk-Z5NW3O7V.js} +1 -1
  93. package/{codingSkills-H6N5EKSX.js → codingSkills-QLDAXJRA.js} +3 -4
  94. package/{cooldownCommands-C2SZLEEO.js → cooldownCommands-GI5NNWGL.js} +5 -3
  95. package/{createAgentAutomationAction-767ZITQJ.js → createAgentAutomationAction-TQ7PYONU.js} +21 -21
  96. package/{createDialogAction-H75NDXYH.js → createDialogAction-EOQFCM3K.js} +24 -25
  97. package/{createPageAction-KYJYZPLC.js → createPageAction-ZG5PH6BI.js} +22 -23
  98. package/db-VQSAOWAO.js +162 -0
  99. package/{dbSlice-PIQGICNM.js → dbSlice-XWUM4QOF.js} +5 -5
  100. package/deleteFile-NPZ64DFN.js +1 -1
  101. package/{dialogCommands-SSQLOBRU.js → dialogCommands-DCGMVLBA.js} +29 -27
  102. package/{dialogSlice-YJV3AVFM.js → dialogSlice-YHGPDBAZ.js} +20 -20
  103. package/{docCreateCommands-WYP6MQ56.js → docCreateCommands-A2LVLROP.js} +26 -28
  104. package/{docDeleteCommands-6YNU4LZ7.js → docDeleteCommands-ENMROKH6.js} +27 -29
  105. package/{docReadCommands-PFJMIPYU.js → docReadCommands-XSRUV4EM.js} +26 -28
  106. package/{docStore-JOODSWDW.js → docStore-WIKRGVQJ.js} +22 -22
  107. package/{docUpdateCommands-KAP6JSGT.js → docUpdateCommands-5B5NBORA.js} +26 -28
  108. package/{fetchMessages-CUEFN4GQ.js → fetchMessages-KZQVBXKY.js} +3 -3
  109. package/{getPricing-P3E2WRIH.js → getPricing-X3HXP6VQ.js} +3 -3
  110. package/{handleSendMessageAction-DGL6H4E4.js → handleSendMessageAction-WT4FDMQS.js} +21 -21
  111. package/index.js +70 -70
  112. package/levelLazyShim-GZBKODGI.js +7 -0
  113. package/{localDialogRead-P7CHFMIC.js → localDialogRead-NQ33HBSI.js} +2 -2
  114. package/{localRuntimeAuthority-S77B5QVB.js → localRuntimeAuthority-KQDAE64E.js} +4 -4
  115. package/{localRuntimeDb-N3H3HQ7G.js → localRuntimeDb-PF7CFKDL.js} +2 -2
  116. package/{machineCommands-NAFWPMLI.js → machineCommands-BFLTBAK6.js} +51 -53
  117. package/{machineWsRunDispatch-EWA7J37I.js → machineWsRunDispatch-VCJB5LHO.js} +51 -53
  118. package/{models-L7S2EKPM.js → models-7LWATQFH.js} +2 -2
  119. package/package.json +1 -1
  120. package/{read-6C2XD3YZ.js → read-DQQ75VI3.js} +2 -2
  121. package/{readDocTool-Y7AB365O.js → readDocTool-HCQQFAZD.js} +1 -1
  122. package/{readlineWorkspace-BCQVDX4V.js → readlineWorkspace-VBJLMU6V.js} +5168 -5003
  123. package/{removeDialogAgentAction-KG5WMJRZ.js → removeDialogAgentAction-DNONRKST.js} +7 -7
  124. package/{runAgentClientLoop-B3TTKXIX.js → runAgentClientLoop-4QOEJOJP.js} +41 -42
  125. package/{runtimeDoctorCommands-HT4O2PXL.js → runtimeDoctorCommands-JKTTN723.js} +4 -4
  126. package/serverStoreFactory-YMXDF4NI.js +20 -0
  127. package/{setDialogExtraReferencesAction-O2NLXMSM.js → setDialogExtraReferencesAction-ERHUPT3F.js} +6 -6
  128. package/{setPrimaryDialogAgentAction-FYYUY7PB.js → setPrimaryDialogAgentAction-6C2HYNEC.js} +7 -7
  129. package/{settingSlice-GPLI6E3M.js → settingSlice-YVRJFKQX.js} +6 -6
  130. package/{skillDiscovery-COX56OBO.js → skillDiscovery-GPUDHDTZ.js} +1 -2
  131. package/{spaceCommands-VHOKUADK.js → spaceCommands-FBB7XSAW.js} +24 -25
  132. package/{spaceSlice-ZKUZSVYD.js → spaceSlice-YMDZ4G6H.js} +21 -21
  133. package/{streamAgentChatTurn-PLTB7RMV.js → streamAgentChatTurn-5NBWQHY6.js} +93 -52
  134. package/{switchDialogAgentAction-GH5P6Q3Z.js → switchDialogAgentAction-HP57XYFP.js} +5 -5
  135. package/{tools-KQXDW66A.js → tools-37H5A4OG.js} +34 -35
  136. package/{tuiSummaryLlmCaller-SHRB4RWM.js → tuiSummaryLlmCaller-NBTWT57U.js} +25 -14
  137. package/{updateDialogTitleAction-OTYEQJAK.js → updateDialogTitleAction-XAGMXHW5.js} +24 -23
  138. package/chunk-4APLX2RT.js +0 -1514
  139. package/chunk-AETZ7AD6.js +0 -274
  140. package/chunk-OFZPJ3NT.js +0 -114
  141. package/chunk-P66M7LSQ.js +0 -58
  142. package/{chunk-6WD3OOJS.js → chunk-UV6VISQJ.js} +0 -0
  143. package/{tableCommands-PQUJ55AS.js → tableCommands-P2TXJ3CF.js} +1 -1
@@ -1,8 +1,14 @@
1
1
  import {
2
2
  isOpenAiResponsesModel,
3
3
  resolvePlatformChatCompletionsEndpoint,
4
+ resolvePlatformHostedCredentialProvider,
4
5
  resolvePlatformResponsesEndpoint
5
- } from "./chunk-V5GA74HI.js";
6
+ } from "./chunk-MZXZJVVD.js";
7
+ import {
8
+ CLIENT_VERSION_TOO_OLD_CODE,
9
+ buildClientVersionGateErrorDetail,
10
+ evaluatePlatformHostedClientVersionGate
11
+ } from "./chunk-ENYDQKOB.js";
6
12
  import {
7
13
  asTrimmedLowercaseString
8
14
  } from "./chunk-QSJ3HFEF.js";
@@ -89,6 +95,9 @@ function resolveOpenAiCompatibleApiKey(env) {
89
95
  function resolvePlatformServerUrl(env) {
90
96
  return trimTrailingSlash(env.NOLO_SERVER || env.BASE_URL || "https://nolo.chat");
91
97
  }
98
+ function resolveClientVersion(env) {
99
+ return asOptionalTrimmedString(env.NOLO_CLI_VERSION);
100
+ }
92
101
  function resolvePlatformAuthToken(env) {
93
102
  return env.AUTH_TOKEN || env.AUTH || env.NOLO_MACHINE_API_KEY || env.BENCHMARK_AUTH_TOKEN || "";
94
103
  }
@@ -270,6 +279,21 @@ async function buildProviderExecutionPlan(args) {
270
279
  };
271
280
  }
272
281
  const provider = agentConfig.provider || agentConfig.apiSource || "openai";
282
+ const localClientVersion = resolveClientVersion(env);
283
+ const clientVersionGate = evaluatePlatformHostedClientVersionGate({
284
+ provider,
285
+ model,
286
+ clientVersion: localClientVersion,
287
+ isCustomApi: agentConfig.apiSource === "custom" || Boolean(agentConfig.customProviderUrl?.trim()),
288
+ hasExplicitCredential: Boolean(agentConfig.apiKey?.trim()) || Boolean(agentConfig.apiKeyRef?.trim())
289
+ });
290
+ if (clientVersionGate.blocked) {
291
+ const gateError = new Error(clientVersionGate.message);
292
+ gateError.code = CLIENT_VERSION_TOO_OLD_CODE;
293
+ gateError.detail = buildClientVersionGateErrorDetail(clientVersionGate);
294
+ throw gateError;
295
+ }
296
+ const platformUsageProvider = resolvePlatformHostedCredentialProvider(provider, model);
273
297
  const endpoint = transportDecision.transport === "proxy" ? resolvePlatformProviderEndpoint(agentConfig) : resolveChatCompletionsEndpoint(resolveOpenAiCompatibleBaseUrl(env));
274
298
  if (transportDecision.transport === "proxy") {
275
299
  return {
@@ -282,7 +306,9 @@ async function buildProviderExecutionPlan(args) {
282
306
  serverUrl: resolvePlatformServerUrl(env),
283
307
  authToken: resolvePlatformAuthToken(env),
284
308
  agentKey: agentConfig.key,
285
- ...agentConfig.apiSource ? { apiSource: agentConfig.apiSource } : {}
309
+ ...localClientVersion ? { clientVersion: localClientVersion } : {},
310
+ ...agentConfig.apiSource ? { apiSource: agentConfig.apiSource } : {},
311
+ ...platformUsageProvider ? { usageProvider: platformUsageProvider } : {}
286
312
  // Platform agents use the server-managed provider credential. Never
287
313
  // forward a raw credential from a stale/local agent record through the
288
314
  // platform proxy; credentials are resolved by the platform server.
@@ -321,7 +347,8 @@ async function buildProviderExecutionPlan(args) {
321
347
  provider: agentConfig.provider || "openai-compatible",
322
348
  endpoint,
323
349
  requestOptions,
324
- apiKey
350
+ apiKey,
351
+ ...platformUsageProvider ? { usageProvider: platformUsageProvider } : {}
325
352
  };
326
353
  }
327
354
 
@@ -329,6 +356,7 @@ export {
329
356
  pickAgentRuntimeInferenceOptions,
330
357
  trimTrailingSlash,
331
358
  resolvePlatformServerUrl,
359
+ resolveClientVersion,
332
360
  resolvePlatformAuthToken,
333
361
  canUsePlatformChatProvider,
334
362
  hasDirectOpenAiCompatibleProvider,
@@ -33,9 +33,9 @@ var STREAM_USAGE_PROVIDERS = /* @__PURE__ */ new Set([
33
33
  "deepseek",
34
34
  "ollama",
35
35
  "ollama-cloud",
36
- // OpenAI-compatible /v1/chat/completions endpoint; the hosted branch passes
37
- // "upstream-k3" as the usage provider so K3 streams request the terminal usage
38
- // chunk (same capability decision as deepinfra/vultr).
36
+ // endpoint; the hosted branch passes "upstream-k3" as the usage provider so these
37
+ // streams request the terminal usage chunk (same capability decision as
38
+ // deepinfra/vultr).
39
39
  "upstream-k3",
40
40
  // RunInfra hosted fallback channel: OpenAI-compatible chat.completions
41
41
  // endpoint, supports stream_options.include_usage (measured to return
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-ESHYE7WU.js";
4
4
  import {
5
5
  getDefaultCliLocalRuntimeDb
6
- } from "./chunk-N4XRDM26.js";
6
+ } from "./chunk-IA3A5373.js";
7
7
  import {
8
8
  buildCliRuntimeEnv,
9
9
  clearProfileAuthToken,
@@ -23,7 +23,7 @@ import {
23
23
  createMemoryOwnerIndexKey,
24
24
  createMemorySubjectKindIndexKey,
25
25
  memoryOwnerRange
26
- } from "./chunk-2WKUUY2E.js";
26
+ } from "./chunk-SVEUG45B.js";
27
27
  import {
28
28
  asTrimmedNonEmptyStringArray
29
29
  } from "./chunk-I42VC5KR.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildSkillDocMarkdown
3
- } from "./chunk-AETZ7AD6.js";
3
+ } from "./chunk-EY7V7REW.js";
4
4
 
5
5
  // packages/cli/docPageHelpers.ts
6
6
  import { readFileSync } from "node:fs";
@@ -1,32 +1,32 @@
1
1
  import {
2
2
  addContentToSpace
3
- } from "./chunk-D72M3G32.js";
3
+ } from "./chunk-FM6ZGNMV.js";
4
4
  import {
5
5
  prepareAndPersistMessage,
6
6
  uiAskChoiceFunc,
7
7
  uiAskChoiceFunctionSchema
8
- } from "./chunk-ARFXKWJH.js";
8
+ } from "./chunk-5PFBRLJN.js";
9
9
  import {
10
10
  require_date_fns
11
11
  } from "./chunk-M76ECQRD.js";
12
12
  import {
13
13
  TOOL_PACKS
14
- } from "./chunk-IIOHYLIG.js";
14
+ } from "./chunk-LGUQHYAL.js";
15
15
  import {
16
16
  buildSkillDocMarkdown
17
- } from "./chunk-AETZ7AD6.js";
17
+ } from "./chunk-EY7V7REW.js";
18
18
  import {
19
19
  PLATFORM_HOSTED_DEEPSEEK_FLASH_MODEL,
20
20
  PLATFORM_HOSTED_DEEPSEEK_FLASH_PEAK_PRICE,
21
21
  PLATFORM_HOSTED_KIMI_PROVIDER
22
- } from "./chunk-X6EN3KJX.js";
22
+ } from "./chunk-ENYDQKOB.js";
23
23
  import {
24
24
  read,
25
25
  readAndWait,
26
26
  removeCachedEntity,
27
27
  upsertSSREntity,
28
28
  write
29
- } from "./chunk-23KKIMD5.js";
29
+ } from "./chunk-WVGEBWA6.js";
30
30
  import {
31
31
  createAgentKey,
32
32
  createDialogKey,
@@ -35,7 +35,7 @@ import {
35
35
  dialogMessageRange,
36
36
  memoryOwnerRange,
37
37
  memorySubjectKindRange
38
- } from "./chunk-2WKUUY2E.js";
38
+ } from "./chunk-SVEUG45B.js";
39
39
  import {
40
40
  extractCustomId
41
41
  } from "./chunk-BJIRLHJR.js";
@@ -4,7 +4,7 @@ import {
4
4
  openrouterModels,
5
5
  platformHostedModels,
6
6
  zaiModels
7
- } from "./chunk-X6EN3KJX.js";
7
+ } from "./chunk-ENYDQKOB.js";
8
8
 
9
9
  // packages/ai/llm/modelAbility.ts
10
10
  var MODEL_ABILITY_TABLE = {
@@ -3,7 +3,7 @@ import {
3
3
  resolveRunReportJsonPath,
4
4
  resolveRunReportPath,
5
5
  resolveRunsDir
6
- } from "./chunk-E2OQ5N2F.js";
6
+ } from "./chunk-AEXP2UZT.js";
7
7
 
8
8
  // packages/cli/agentRunReport.ts
9
9
  import { homedir as nodeHomedir } from "node:os";
@@ -35,6 +35,306 @@ function resolveRunRecordPath(runId, env, homedir = nodeHomedir) {
35
35
  function resolveRunLogPath(runId, env, homedir = nodeHomedir) {
36
36
  return join(resolveRunsDir(env, homedir), `${runId}.log`);
37
37
  }
38
+ function resolveRunQueuePath(runId, env, homedir = nodeHomedir) {
39
+ return join(resolveRunsDir(env, homedir), `${runId}.queue.jsonl`);
40
+ }
41
+ function defaultGenerateQueueEntryId() {
42
+ const ts = Date.now().toString(36);
43
+ const rand = Math.random().toString(36).slice(2, 10);
44
+ return `qmsg-${ts}-${rand}`;
45
+ }
46
+ function _parseQueueLines(content) {
47
+ if (!content.trim()) return [];
48
+ const lines = content.split("\n").map((l) => l.trim()).filter(Boolean);
49
+ const entries = [];
50
+ for (const line of lines) {
51
+ try {
52
+ const item = JSON.parse(line);
53
+ if (typeof item?.text === "string" && item.text.trim()) {
54
+ entries.push({
55
+ id: typeof item.id === "string" && item.id.trim() ? item.id.trim() : defaultGenerateQueueEntryId(),
56
+ ts: typeof item.ts === "number" ? item.ts : Date.now(),
57
+ text: item.text.trim()
58
+ });
59
+ }
60
+ } catch {
61
+ if (line.length > 0) {
62
+ entries.push({
63
+ id: defaultGenerateQueueEntryId(),
64
+ ts: Date.now(),
65
+ text: line
66
+ });
67
+ }
68
+ }
69
+ }
70
+ return entries;
71
+ }
72
+ var parseQueueLines = _parseQueueLines;
73
+ function _serializeQueueEntries(entries) {
74
+ if (entries.length === 0) return "";
75
+ return entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
76
+ }
77
+ var serializeQueueEntries = _serializeQueueEntries;
78
+ function _countQueueMessagesLocked(queuePath, fs = nodeFs) {
79
+ if (!fs.existsSync(queuePath)) return 0;
80
+ try {
81
+ const content = fs.readFileSync(queuePath, "utf8");
82
+ return _parseQueueLines(content).length;
83
+ } catch {
84
+ return 0;
85
+ }
86
+ }
87
+ function _readQueueMessagesLocked(queuePath, fs = nodeFs) {
88
+ if (!fs.existsSync(queuePath)) return [];
89
+ try {
90
+ const content = fs.readFileSync(queuePath, "utf8");
91
+ return _parseQueueLines(content).map((e) => e.text);
92
+ } catch {
93
+ return [];
94
+ }
95
+ }
96
+ function _readQueueEntriesLocked(queuePath, fs = nodeFs) {
97
+ if (!fs.existsSync(queuePath)) return [];
98
+ try {
99
+ const content = fs.readFileSync(queuePath, "utf8");
100
+ return _parseQueueLines(content);
101
+ } catch {
102
+ return [];
103
+ }
104
+ }
105
+ function tryUnlinkFile(fs, path) {
106
+ if (typeof path !== "string" || path.length === 0) return true;
107
+ try {
108
+ if (fs.existsSync(path)) {
109
+ fs.unlinkSync(path);
110
+ }
111
+ return true;
112
+ } catch (error) {
113
+ const code = error.code;
114
+ return code === "ENOENT";
115
+ }
116
+ }
117
+ function tryRmdir(fs, path) {
118
+ if (typeof path !== "string" || path.length === 0) return true;
119
+ try {
120
+ if (typeof fs.rmdirSync === "function") {
121
+ fs.rmdirSync(path);
122
+ } else {
123
+ fs.unlinkSync(path);
124
+ }
125
+ return true;
126
+ } catch (error) {
127
+ if (error?.code === "ENOENT") return true;
128
+ return false;
129
+ }
130
+ }
131
+ var QUEUE_LOCK_STALE_MS = 6e4;
132
+ var QUEUE_LOCK_RETRIES = 20;
133
+ var QUEUE_LOCK_RETRY_INTERVAL_MS = 10;
134
+ function defaultGenerateOwnerTokenId() {
135
+ const ts = Date.now().toString(36);
136
+ const rand = Math.random().toString(36).slice(2, 10);
137
+ return `own-${ts}-${rand}`;
138
+ }
139
+ function normalizeQueueDeps(depsOrFs) {
140
+ if (!depsOrFs) return {};
141
+ if ("mkdirSync" in depsOrFs) {
142
+ return { fs: depsOrFs };
143
+ }
144
+ return depsOrFs;
145
+ }
146
+ async function withQueueLock(queuePath, fnOrDeps, depsOrFnOrOpts, maybeOpts) {
147
+ let fn;
148
+ let rawDeps;
149
+ let opts = maybeOpts ?? {};
150
+ if (typeof fnOrDeps === "function") {
151
+ fn = fnOrDeps;
152
+ if (depsOrFnOrOpts && typeof depsOrFnOrOpts === "object" && !("mkdirSync" in depsOrFnOrOpts) && !("fs" in depsOrFnOrOpts) && !("env" in depsOrFnOrOpts)) {
153
+ opts = { ...depsOrFnOrOpts, ...maybeOpts };
154
+ rawDeps = void 0;
155
+ } else {
156
+ rawDeps = depsOrFnOrOpts;
157
+ }
158
+ } else {
159
+ rawDeps = fnOrDeps;
160
+ fn = depsOrFnOrOpts;
161
+ }
162
+ const deps = normalizeQueueDeps(rawDeps);
163
+ const fs = deps.fs ?? nodeFs;
164
+ const now = deps.now ?? (() => /* @__PURE__ */ new Date());
165
+ const staleLockMs = opts.staleLockMs ?? QUEUE_LOCK_STALE_MS;
166
+ const retries = opts.retries ?? QUEUE_LOCK_RETRIES;
167
+ const retryIntervalMs = opts.retryIntervalMs ?? QUEUE_LOCK_RETRY_INTERVAL_MS;
168
+ const lockPath = `${queuePath}.lock`;
169
+ const tokenPath = join(lockPath, "owner.json");
170
+ try {
171
+ fs.mkdirSync(dirname(lockPath), { recursive: true });
172
+ } catch {
173
+ }
174
+ const myOwnerId = defaultGenerateOwnerTokenId();
175
+ let held = false;
176
+ const tryAcquire = () => {
177
+ let created = false;
178
+ try {
179
+ fs.mkdirSync(lockPath);
180
+ created = true;
181
+ } catch {
182
+ try {
183
+ if (typeof fs.statSync === "function") {
184
+ const stat = fs.statSync(lockPath);
185
+ const ageMs = stat ? now().getTime() - stat.mtimeMs : 0;
186
+ if (ageMs > staleLockMs) {
187
+ try {
188
+ tryUnlinkFile(fs, tokenPath);
189
+ tryRmdir(fs, lockPath);
190
+ } catch {
191
+ }
192
+ try {
193
+ fs.mkdirSync(lockPath);
194
+ created = true;
195
+ } catch {
196
+ }
197
+ }
198
+ }
199
+ } catch {
200
+ }
201
+ }
202
+ if (created) {
203
+ try {
204
+ const token = {
205
+ ownerId: myOwnerId,
206
+ pid: process.pid,
207
+ createdAt: now().toISOString(),
208
+ createdAtMs: now().getTime()
209
+ };
210
+ fs.writeFileSync(tokenPath, JSON.stringify(token), "utf8");
211
+ return true;
212
+ } catch (writeTokenErr) {
213
+ tryRmdir(fs, lockPath);
214
+ throw writeTokenErr;
215
+ }
216
+ }
217
+ return false;
218
+ };
219
+ for (let attempt = 0; attempt <= retries; attempt++) {
220
+ if (tryAcquire()) {
221
+ held = true;
222
+ break;
223
+ }
224
+ if (attempt < retries && retryIntervalMs > 0) {
225
+ await new Promise((resolve2) => setTimeout(resolve2, retryIntervalMs));
226
+ }
227
+ }
228
+ if (!held) {
229
+ throw new Error(`queue busy: ${queuePath}`);
230
+ }
231
+ try {
232
+ return await fn();
233
+ } finally {
234
+ if (held) {
235
+ try {
236
+ let currentOwnerId;
237
+ if (fs.existsSync(tokenPath)) {
238
+ try {
239
+ const raw = fs.readFileSync(tokenPath, "utf8");
240
+ const parsed = JSON.parse(raw);
241
+ currentOwnerId = parsed?.ownerId;
242
+ } catch {
243
+ currentOwnerId = void 0;
244
+ }
245
+ }
246
+ if (currentOwnerId === myOwnerId) {
247
+ tryUnlinkFile(fs, tokenPath);
248
+ tryRmdir(fs, lockPath);
249
+ } else {
250
+ console.error(
251
+ `[nolo] Warning: queue lock for ${queuePath} was taken over by another process (owner mismatch: expected ${myOwnerId}, found ${currentOwnerId ?? "none"}). Will not release.`
252
+ );
253
+ }
254
+ } catch (releaseErr) {
255
+ console.error(`[nolo] Warning: failed to release queue lock for ${queuePath}:`, releaseErr);
256
+ }
257
+ }
258
+ }
259
+ }
260
+ async function appendRunQueue(queuePath, input, depsOrFs = {}) {
261
+ const deps = normalizeQueueDeps(depsOrFs);
262
+ const fs = deps.fs ?? nodeFs;
263
+ const now = deps.now ?? (() => /* @__PURE__ */ new Date());
264
+ const text = typeof input === "string" ? input : input.text;
265
+ const entryId = typeof input === "object" && typeof input.id === "string" && input.id.trim() ? input.id.trim() : defaultGenerateQueueEntryId();
266
+ const entry = { id: entryId, ts: now().getTime(), text };
267
+ const line = JSON.stringify(entry) + "\n";
268
+ return await withQueueLock(queuePath, deps, async () => {
269
+ if (typeof fs.appendFileSync === "function") {
270
+ fs.appendFileSync(queuePath, line, "utf8");
271
+ } else {
272
+ const existing = fs.existsSync(queuePath) ? fs.readFileSync(queuePath, "utf8") : "";
273
+ fs.writeFileSync(queuePath, existing + line, "utf8");
274
+ }
275
+ const currentContent = fs.existsSync(queuePath) ? fs.readFileSync(queuePath, "utf8") : line;
276
+ return { queuedCount: _parseQueueLines(currentContent).length, entryId };
277
+ });
278
+ }
279
+ async function countQueueMessages(queuePath, depsOrFs = {}) {
280
+ const deps = normalizeQueueDeps(depsOrFs);
281
+ const fs = deps.fs ?? nodeFs;
282
+ if (!fs.existsSync(queuePath)) return 0;
283
+ return await withQueueLock(queuePath, deps, async () => {
284
+ return _countQueueMessagesLocked(queuePath, fs);
285
+ });
286
+ }
287
+ async function readQueueMessages(queuePath, depsOrFs = {}) {
288
+ const deps = normalizeQueueDeps(depsOrFs);
289
+ const fs = deps.fs ?? nodeFs;
290
+ if (!fs.existsSync(queuePath)) return [];
291
+ return await withQueueLock(queuePath, deps, async () => {
292
+ return _readQueueMessagesLocked(queuePath, fs);
293
+ });
294
+ }
295
+ async function readQueueEntries(queuePath, depsOrFs = {}) {
296
+ const deps = normalizeQueueDeps(depsOrFs);
297
+ const fs = deps.fs ?? nodeFs;
298
+ if (!fs.existsSync(queuePath)) return [];
299
+ return await withQueueLock(queuePath, deps, async () => {
300
+ return _readQueueEntriesLocked(queuePath, fs);
301
+ });
302
+ }
303
+ async function popAllQueueEntries(queuePath, depsOrFs = {}) {
304
+ const deps = normalizeQueueDeps(depsOrFs);
305
+ const fs = deps.fs ?? nodeFs;
306
+ return await withQueueLock(queuePath, deps, async () => {
307
+ if (!fs.existsSync(queuePath)) return [];
308
+ const content = fs.readFileSync(queuePath, "utf8");
309
+ const entries = _parseQueueLines(content);
310
+ tryUnlinkFile(fs, queuePath);
311
+ return entries;
312
+ });
313
+ }
314
+ async function popSingleQueueMessage(queuePath, depsOrFs = {}) {
315
+ const deps = normalizeQueueDeps(depsOrFs);
316
+ const fs = deps.fs ?? nodeFs;
317
+ return await withQueueLock(queuePath, deps, async () => {
318
+ if (!fs.existsSync(queuePath)) return null;
319
+ const content = fs.readFileSync(queuePath, "utf8");
320
+ const entries = _parseQueueLines(content);
321
+ if (entries.length === 0) {
322
+ tryUnlinkFile(fs, queuePath);
323
+ return null;
324
+ }
325
+ const [first, ...rest] = entries;
326
+ if (rest.length === 0) {
327
+ tryUnlinkFile(fs, queuePath);
328
+ } else {
329
+ fs.writeFileSync(queuePath, _serializeQueueEntries(rest), "utf8");
330
+ }
331
+ return first;
332
+ });
333
+ }
334
+ async function popQueueMessages(queuePath, depsOrFs = {}) {
335
+ const entries = await popAllQueueEntries(queuePath, depsOrFs);
336
+ return entries.map((e) => e.text);
337
+ }
38
338
  function resolveRunReportPath(runId, env, homedir = nodeHomedir) {
39
339
  return join(resolveRunsDir(env, homedir), `${runId}.report.md`);
40
340
  }
@@ -269,19 +569,7 @@ function queryRunRecords(query, deps = {}) {
269
569
  return { runs: sliced, total, hasMore };
270
570
  }
271
571
  var DEFAULT_GC_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
272
- function tryUnlinkFile(fs, path) {
273
- if (typeof path !== "string" || path.length === 0) return true;
274
- try {
275
- if (fs.existsSync(path)) {
276
- fs.unlinkSync(path);
277
- }
278
- return true;
279
- } catch (error) {
280
- const code = error.code;
281
- return code === "ENOENT";
282
- }
283
- }
284
- function gcRunRecords(deps = {}, options = {}) {
572
+ async function gcRunRecords(deps = {}, options = {}) {
285
573
  const fs = deps.fs ?? nodeFs;
286
574
  const now = (deps.now ?? (() => /* @__PURE__ */ new Date()))();
287
575
  const nowMs = now instanceof Date ? now.getTime() : Date.parse(String(now));
@@ -296,14 +584,25 @@ function gcRunRecords(deps = {}, options = {}) {
296
584
  if (!Number.isFinite(ageMs) || ageMs < retentionMs) continue;
297
585
  const jsonPath = resolveRunRecordPath(record.runId, deps.env, deps.homedir);
298
586
  const logPath = resolveRunLogPath(record.runId, deps.env, deps.homedir);
587
+ const queuePath = record.queuePath ?? resolveRunQueuePath(record.runId, deps.env, deps.homedir);
299
588
  const reportPath = resolveRunReportPath(record.runId, deps.env, deps.homedir);
300
589
  const reportJsonPath = resolveRunReportJsonPath(record.runId, deps.env, deps.homedir);
301
590
  const msgPath = record.msgFile ?? join(resolveRunsDir(deps.env, deps.homedir), `${record.runId}.msg.md`);
302
591
  const logOk = tryUnlinkFile(fs, logPath);
303
592
  const msgOk = tryUnlinkFile(fs, msgPath);
593
+ let queueOk = true;
594
+ if (fs.existsSync(queuePath)) {
595
+ try {
596
+ await withQueueLock(queuePath, deps, () => {
597
+ tryUnlinkFile(fs, queuePath);
598
+ });
599
+ } catch {
600
+ queueOk = false;
601
+ }
602
+ }
304
603
  tryUnlinkFile(fs, reportPath);
305
604
  tryUnlinkFile(fs, reportJsonPath);
306
- if (!logOk || !msgOk) {
605
+ if (!logOk || !msgOk || !queueOk) {
307
606
  failedIds.push(record.runId);
308
607
  continue;
309
608
  }
@@ -430,6 +729,7 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
430
729
  const runId = generateRunId();
431
730
  const batchId = input.batchId ?? (deps.generateBatchId ?? defaultGenerateBatchId)();
432
731
  const logPath = resolveRunLogPath(runId, env, homedir);
732
+ const queuePath = resolveRunQueuePath(runId, env, homedir);
433
733
  const recordPath = resolveRunRecordPath(runId, env, homedir);
434
734
  const runsDir = resolveRunsDir(env, homedir);
435
735
  fs.mkdirSync(runsDir, { recursive: true });
@@ -473,15 +773,19 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
473
773
  ...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
474
774
  status: "running",
475
775
  logPath,
776
+ queuePath,
476
777
  batchId,
477
778
  ...typeof input.parentDialogId === "string" && input.parentDialogId.trim() ? { parentDialogId: input.parentDialogId.trim() } : {},
478
779
  ...dodCommands && dodCommands.length > 0 ? { dodCommands } : {},
479
780
  ...spawnHead ? { spawnHead } : {}
480
781
  };
481
782
  fs.writeFileSync(recordPath, JSON.stringify(record, null, 2));
783
+ const rawArgsWithQueue = (input.rawArgs ?? []).some(
784
+ (arg) => arg === "--queue-file" || arg.startsWith("--queue-file=")
785
+ ) ? input.rawArgs : [...input.rawArgs ?? [], "--queue-file", queuePath];
482
786
  const { execPath, childArgs } = buildAgentRunChildCommand(
483
787
  {
484
- rawArgs: input.rawArgs,
788
+ rawArgs: rawArgsWithQueue,
485
789
  commandPath: input.commandPath,
486
790
  cliEntrypointPath: input.cliEntrypointPath,
487
791
  messagePath
@@ -507,7 +811,7 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
507
811
  if (processStartedAt) record.processStartedAt = processStartedAt.toISOString();
508
812
  writeRunRecord(record, deps);
509
813
  }
510
- return { runId, pid: proc.pid, logPath, batchId };
814
+ return { runId, pid: proc.pid, logPath, queuePath, batchId };
511
815
  }
512
816
  function ackRunRecord(runId, deps = {}) {
513
817
  withRunRecordLock(runId, deps, () => {
@@ -1053,6 +1357,27 @@ export {
1053
1357
  resolveRunsDir,
1054
1358
  resolveRunRecordPath,
1055
1359
  resolveRunLogPath,
1360
+ resolveRunQueuePath,
1361
+ defaultGenerateQueueEntryId,
1362
+ _parseQueueLines,
1363
+ parseQueueLines,
1364
+ _serializeQueueEntries,
1365
+ serializeQueueEntries,
1366
+ _countQueueMessagesLocked,
1367
+ _readQueueMessagesLocked,
1368
+ _readQueueEntriesLocked,
1369
+ QUEUE_LOCK_STALE_MS,
1370
+ QUEUE_LOCK_RETRIES,
1371
+ QUEUE_LOCK_RETRY_INTERVAL_MS,
1372
+ defaultGenerateOwnerTokenId,
1373
+ withQueueLock,
1374
+ appendRunQueue,
1375
+ countQueueMessages,
1376
+ readQueueMessages,
1377
+ readQueueEntries,
1378
+ popAllQueueEntries,
1379
+ popSingleQueueMessage,
1380
+ popQueueMessages,
1056
1381
  resolveRunReportPath,
1057
1382
  resolveRunReportJsonPath,
1058
1383
  defaultGenerateRunId,