@nodetool-ai/cli 0.8.2 → 0.8.4-a24.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 (317) hide show
  1. package/README.md +27 -0
  2. package/dist/.nodetool-build-stamp +1 -1
  3. package/dist/affected/affected.d.ts +4 -1
  4. package/dist/affected/affected.d.ts.map +1 -1
  5. package/dist/affected/affected.js +9 -2
  6. package/dist/affected/affected.js.map +1 -1
  7. package/dist/app-debug/harness.js +1 -1
  8. package/dist/app-debug/harness.js.map +1 -1
  9. package/dist/child-exit.d.ts +3 -0
  10. package/dist/child-exit.d.ts.map +1 -0
  11. package/dist/child-exit.js +17 -0
  12. package/dist/child-exit.js.map +1 -0
  13. package/dist/command-errors.d.ts +7 -9
  14. package/dist/command-errors.d.ts.map +1 -1
  15. package/dist/command-errors.js +36 -2
  16. package/dist/command-errors.js.map +1 -1
  17. package/dist/commands/__tests__/jtbd.test.js +1 -1
  18. package/dist/commands/__tests__/jtbd.test.js.map +1 -1
  19. package/dist/commands/__tests__/runtime.test.d.ts +2 -0
  20. package/dist/commands/__tests__/runtime.test.d.ts.map +1 -0
  21. package/dist/commands/__tests__/runtime.test.js +128 -0
  22. package/dist/commands/__tests__/runtime.test.js.map +1 -0
  23. package/dist/commands/affected.d.ts.map +1 -1
  24. package/dist/commands/affected.js +10 -5
  25. package/dist/commands/affected.js.map +1 -1
  26. package/dist/commands/agent.d.ts.map +1 -1
  27. package/dist/commands/agent.js +11 -2
  28. package/dist/commands/agent.js.map +1 -1
  29. package/dist/commands/app.d.ts.map +1 -1
  30. package/dist/commands/app.js +3 -5
  31. package/dist/commands/app.js.map +1 -1
  32. package/dist/commands/apps.d.ts.map +1 -1
  33. package/dist/commands/apps.js +128 -34
  34. package/dist/commands/apps.js.map +1 -1
  35. package/dist/commands/authorized-pack-install.d.ts +7 -0
  36. package/dist/commands/authorized-pack-install.d.ts.map +1 -0
  37. package/dist/commands/authorized-pack-install.js +20 -0
  38. package/dist/commands/authorized-pack-install.js.map +1 -0
  39. package/dist/commands/debug.d.ts.map +1 -1
  40. package/dist/commands/debug.js +15 -3
  41. package/dist/commands/debug.js.map +1 -1
  42. package/dist/commands/deploy-helpers.d.ts +2 -1
  43. package/dist/commands/deploy-helpers.d.ts.map +1 -1
  44. package/dist/commands/eval.d.ts.map +1 -1
  45. package/dist/commands/eval.js +4 -3
  46. package/dist/commands/eval.js.map +1 -1
  47. package/dist/commands/game-benchmark.d.ts +4 -0
  48. package/dist/commands/game-benchmark.d.ts.map +1 -1
  49. package/dist/commands/game-benchmark.js +8 -0
  50. package/dist/commands/game-benchmark.js.map +1 -1
  51. package/dist/commands/game-smoke.d.ts.map +1 -1
  52. package/dist/commands/game-smoke.js +3 -3
  53. package/dist/commands/game-smoke.js.map +1 -1
  54. package/dist/commands/game.d.ts.map +1 -1
  55. package/dist/commands/game.js +112 -23
  56. package/dist/commands/game.js.map +1 -1
  57. package/dist/commands/harness.d.ts +21 -0
  58. package/dist/commands/harness.d.ts.map +1 -1
  59. package/dist/commands/harness.js +203 -13
  60. package/dist/commands/harness.js.map +1 -1
  61. package/dist/commands/install-missing-packs.d.ts +21 -0
  62. package/dist/commands/install-missing-packs.d.ts.map +1 -0
  63. package/dist/commands/install-missing-packs.js +48 -0
  64. package/dist/commands/install-missing-packs.js.map +1 -0
  65. package/dist/commands/js-script.d.ts.map +1 -1
  66. package/dist/commands/js-script.js +11 -9
  67. package/dist/commands/js-script.js.map +1 -1
  68. package/dist/commands/mcp.d.ts.map +1 -1
  69. package/dist/commands/mcp.js +2 -0
  70. package/dist/commands/mcp.js.map +1 -1
  71. package/dist/commands/node.d.ts.map +1 -1
  72. package/dist/commands/node.js +15 -3
  73. package/dist/commands/node.js.map +1 -1
  74. package/dist/commands/output.d.ts +8 -0
  75. package/dist/commands/output.d.ts.map +1 -1
  76. package/dist/commands/output.js +18 -0
  77. package/dist/commands/output.js.map +1 -1
  78. package/dist/commands/pack-install-authorization.d.ts +40 -0
  79. package/dist/commands/pack-install-authorization.d.ts.map +1 -0
  80. package/dist/commands/pack-install-authorization.js +131 -0
  81. package/dist/commands/pack-install-authorization.js.map +1 -0
  82. package/dist/commands/pack-management.d.ts +26 -0
  83. package/dist/commands/pack-management.d.ts.map +1 -0
  84. package/dist/commands/pack-management.js +74 -0
  85. package/dist/commands/pack-management.js.map +1 -0
  86. package/dist/commands/packs.d.ts +2 -1
  87. package/dist/commands/packs.d.ts.map +1 -1
  88. package/dist/commands/packs.js +7 -2
  89. package/dist/commands/packs.js.map +1 -1
  90. package/dist/commands/projects.d.ts +11 -0
  91. package/dist/commands/projects.d.ts.map +1 -0
  92. package/dist/commands/projects.js +145 -0
  93. package/dist/commands/projects.js.map +1 -0
  94. package/dist/commands/resource-read.d.ts.map +1 -1
  95. package/dist/commands/resource-read.js +11 -13
  96. package/dist/commands/resource-read.js.map +1 -1
  97. package/dist/commands/runs.js +1 -1
  98. package/dist/commands/runs.js.map +1 -1
  99. package/dist/commands/runtime.d.ts +3 -0
  100. package/dist/commands/runtime.d.ts.map +1 -0
  101. package/dist/commands/runtime.js +122 -0
  102. package/dist/commands/runtime.js.map +1 -0
  103. package/dist/commands/sketch.d.ts.map +1 -1
  104. package/dist/commands/sketch.js +2 -4
  105. package/dist/commands/sketch.js.map +1 -1
  106. package/dist/commands/timeline-render.d.ts +0 -10
  107. package/dist/commands/timeline-render.d.ts.map +1 -1
  108. package/dist/commands/timeline-render.js +20 -29
  109. package/dist/commands/timeline-render.js.map +1 -1
  110. package/dist/commands/timeline-score.d.ts.map +1 -1
  111. package/dist/commands/timeline-score.js +4 -4
  112. package/dist/commands/timeline-score.js.map +1 -1
  113. package/dist/commands/timeline.d.ts.map +1 -1
  114. package/dist/commands/timeline.js +2 -4
  115. package/dist/commands/timeline.js.map +1 -1
  116. package/dist/commands/validate.d.ts +2 -0
  117. package/dist/commands/validate.d.ts.map +1 -1
  118. package/dist/commands/validate.js +8 -3
  119. package/dist/commands/validate.js.map +1 -1
  120. package/dist/commands/version-commands.d.ts +2 -5
  121. package/dist/commands/version-commands.d.ts.map +1 -1
  122. package/dist/commands/version-commands.js +5 -10
  123. package/dist/commands/version-commands.js.map +1 -1
  124. package/dist/debug/server-runner.d.ts.map +1 -1
  125. package/dist/debug/server-runner.js +15 -1
  126. package/dist/debug/server-runner.js.map +1 -1
  127. package/dist/debug/target.d.ts.map +1 -1
  128. package/dist/debug/target.js +2 -11
  129. package/dist/debug/target.js.map +1 -1
  130. package/dist/debug-bundle.d.ts +12 -0
  131. package/dist/debug-bundle.d.ts.map +1 -0
  132. package/dist/debug-bundle.js +23 -0
  133. package/dist/debug-bundle.js.map +1 -0
  134. package/dist/document-json.d.ts +11 -0
  135. package/dist/document-json.d.ts.map +1 -0
  136. package/dist/document-json.js +27 -0
  137. package/dist/document-json.js.map +1 -0
  138. package/dist/evals/graph-runner.d.ts +1 -1
  139. package/dist/evals/graph-runner.d.ts.map +1 -1
  140. package/dist/evals/graph-runner.js +2 -2
  141. package/dist/evals/graph-runner.js.map +1 -1
  142. package/dist/harness/capability-coverage.d.ts +1 -1
  143. package/dist/harness/capability-coverage.d.ts.map +1 -1
  144. package/dist/harness/capability-coverage.js +1 -1
  145. package/dist/harness/capability-coverage.js.map +1 -1
  146. package/dist/harness/capability-table.d.ts.map +1 -1
  147. package/dist/harness/capability-table.js +87 -17
  148. package/dist/harness/capability-table.js.map +1 -1
  149. package/dist/harness/registry.d.ts.map +1 -1
  150. package/dist/harness/registry.js +183 -6
  151. package/dist/harness/registry.js.map +1 -1
  152. package/dist/index.js +13 -5
  153. package/dist/index.js.map +1 -1
  154. package/dist/install-lock.d.ts +12 -0
  155. package/dist/install-lock.d.ts.map +1 -0
  156. package/dist/install-lock.js +139 -0
  157. package/dist/install-lock.js.map +1 -0
  158. package/dist/js-script-debug/harness.d.ts +22 -0
  159. package/dist/js-script-debug/harness.d.ts.map +1 -1
  160. package/dist/js-script-debug/harness.js +14 -35
  161. package/dist/js-script-debug/harness.js.map +1 -1
  162. package/dist/js-script-debug/target.d.ts.map +1 -1
  163. package/dist/js-script-debug/target.js +1 -24
  164. package/dist/js-script-debug/target.js.map +1 -1
  165. package/dist/node/run-node.d.ts +3 -0
  166. package/dist/node/run-node.d.ts.map +1 -1
  167. package/dist/node/run-node.js +18 -2
  168. package/dist/node/run-node.js.map +1 -1
  169. package/dist/node-registry.d.ts +6 -4
  170. package/dist/node-registry.d.ts.map +1 -1
  171. package/dist/node-registry.js +10 -5
  172. package/dist/node-registry.js.map +1 -1
  173. package/dist/nodetool-main.js +114 -76
  174. package/dist/nodetool-main.js.map +1 -1
  175. package/dist/nodetool.js +8 -1
  176. package/dist/nodetool.js.map +1 -1
  177. package/dist/npm-runner.d.ts +23 -0
  178. package/dist/npm-runner.d.ts.map +1 -0
  179. package/dist/npm-runner.js +159 -0
  180. package/dist/npm-runner.js.map +1 -0
  181. package/dist/optional-node-root.d.ts +10 -0
  182. package/dist/optional-node-root.d.ts.map +1 -0
  183. package/dist/optional-node-root.js +26 -0
  184. package/dist/optional-node-root.js.map +1 -0
  185. package/dist/package-assets.d.ts +8 -0
  186. package/dist/package-assets.d.ts.map +1 -0
  187. package/dist/package-assets.js +21 -0
  188. package/dist/package-assets.js.map +1 -0
  189. package/dist/packs/command-service.d.ts +14 -0
  190. package/dist/packs/command-service.d.ts.map +1 -0
  191. package/dist/packs/command-service.js +190 -0
  192. package/dist/packs/command-service.js.map +1 -0
  193. package/dist/packs/doctor-lock.d.ts +8 -0
  194. package/dist/packs/doctor-lock.d.ts.map +1 -0
  195. package/dist/packs/doctor-lock.js +50 -0
  196. package/dist/packs/doctor-lock.js.map +1 -0
  197. package/dist/packs/doctor.d.ts +25 -0
  198. package/dist/packs/doctor.d.ts.map +1 -0
  199. package/dist/packs/doctor.js +12 -0
  200. package/dist/packs/doctor.js.map +1 -0
  201. package/dist/packs/global-bootstrap.d.ts +11 -0
  202. package/dist/packs/global-bootstrap.d.ts.map +1 -0
  203. package/dist/packs/global-bootstrap.js +72 -0
  204. package/dist/packs/global-bootstrap.js.map +1 -0
  205. package/dist/packs/host.d.ts +17 -0
  206. package/dist/packs/host.d.ts.map +1 -0
  207. package/dist/packs/host.js +79 -0
  208. package/dist/packs/host.js.map +1 -0
  209. package/dist/packs/install-manifests.d.ts +2 -0
  210. package/dist/packs/install-manifests.d.ts.map +1 -0
  211. package/dist/packs/install-manifests.js +30 -0
  212. package/dist/packs/install-manifests.js.map +1 -0
  213. package/dist/packs/install-process.d.ts +4 -0
  214. package/dist/packs/install-process.d.ts.map +1 -0
  215. package/dist/packs/install-process.js +11 -0
  216. package/dist/packs/install-process.js.map +1 -0
  217. package/dist/packs/install-selection.d.ts +39 -0
  218. package/dist/packs/install-selection.d.ts.map +1 -0
  219. package/dist/packs/install-selection.js +67 -0
  220. package/dist/packs/install-selection.js.map +1 -0
  221. package/dist/packs/install-state.d.ts +21 -0
  222. package/dist/packs/install-state.d.ts.map +1 -0
  223. package/dist/packs/install-state.js +44 -0
  224. package/dist/packs/install-state.js.map +1 -0
  225. package/dist/packs/install-tree.d.ts +35 -0
  226. package/dist/packs/install-tree.d.ts.map +1 -0
  227. package/dist/packs/install-tree.js +253 -0
  228. package/dist/packs/install-tree.js.map +1 -0
  229. package/dist/packs/install-verification.d.ts +12 -0
  230. package/dist/packs/install-verification.d.ts.map +1 -0
  231. package/dist/packs/install-verification.js +76 -0
  232. package/dist/packs/install-verification.js.map +1 -0
  233. package/dist/packs/installed.d.ts +36 -0
  234. package/dist/packs/installed.d.ts.map +1 -0
  235. package/dist/packs/installed.js +87 -0
  236. package/dist/packs/installed.js.map +1 -0
  237. package/dist/packs/installer-load-check.d.ts +4 -0
  238. package/dist/packs/installer-load-check.d.ts.map +1 -0
  239. package/dist/packs/installer-load-check.js +52 -0
  240. package/dist/packs/installer-load-check.js.map +1 -0
  241. package/dist/packs/installer.d.ts +16 -0
  242. package/dist/packs/installer.d.ts.map +1 -0
  243. package/dist/packs/installer.js +142 -0
  244. package/dist/packs/installer.js.map +1 -0
  245. package/dist/packs/management.d.ts +51 -0
  246. package/dist/packs/management.d.ts.map +1 -0
  247. package/dist/packs/management.js +81 -0
  248. package/dist/packs/management.js.map +1 -0
  249. package/dist/packs/mode.d.ts +42 -0
  250. package/dist/packs/mode.d.ts.map +1 -0
  251. package/dist/packs/mode.js +215 -0
  252. package/dist/packs/mode.js.map +1 -0
  253. package/dist/packs/owned-replay-plan.d.ts +5 -0
  254. package/dist/packs/owned-replay-plan.d.ts.map +1 -0
  255. package/dist/packs/owned-replay-plan.js +68 -0
  256. package/dist/packs/owned-replay-plan.js.map +1 -0
  257. package/dist/packs/removal-selection.d.ts +12 -0
  258. package/dist/packs/removal-selection.d.ts.map +1 -0
  259. package/dist/packs/removal-selection.js +169 -0
  260. package/dist/packs/removal-selection.js.map +1 -0
  261. package/dist/packs/removal.d.ts +12 -0
  262. package/dist/packs/removal.d.ts.map +1 -0
  263. package/dist/packs/removal.js +138 -0
  264. package/dist/packs/removal.js.map +1 -0
  265. package/dist/packs/repair.d.ts +2 -0
  266. package/dist/packs/repair.d.ts.map +1 -0
  267. package/dist/packs/repair.js +2 -0
  268. package/dist/packs/repair.js.map +1 -0
  269. package/dist/packs/serve.d.ts +2 -0
  270. package/dist/packs/serve.d.ts.map +1 -0
  271. package/dist/packs/serve.js +14 -0
  272. package/dist/packs/serve.js.map +1 -0
  273. package/dist/providers.d.ts +1 -1
  274. package/dist/providers.d.ts.map +1 -1
  275. package/dist/providers.js +46 -6
  276. package/dist/providers.js.map +1 -1
  277. package/dist/run-dsl-supervised.d.ts.map +1 -1
  278. package/dist/run-dsl-supervised.js +8 -1
  279. package/dist/run-dsl-supervised.js.map +1 -1
  280. package/dist/runtime-env.d.ts +4 -0
  281. package/dist/runtime-env.d.ts.map +1 -0
  282. package/dist/runtime-env.js +31 -0
  283. package/dist/runtime-env.js.map +1 -0
  284. package/dist/sandbox-catalog.d.ts +3 -1
  285. package/dist/sandbox-catalog.d.ts.map +1 -1
  286. package/dist/sandbox-catalog.js +7 -2
  287. package/dist/sandbox-catalog.js.map +1 -1
  288. package/dist/settings.d.ts.map +1 -1
  289. package/dist/settings.js +2 -0
  290. package/dist/settings.js.map +1 -1
  291. package/dist/sketch-debug/harness.d.ts +15 -1
  292. package/dist/sketch-debug/harness.d.ts.map +1 -1
  293. package/dist/sketch-debug/harness.js +11 -38
  294. package/dist/sketch-debug/harness.js.map +1 -1
  295. package/dist/sketch-debug/target.d.ts.map +1 -1
  296. package/dist/sketch-debug/target.js +1 -24
  297. package/dist/sketch-debug/target.js.map +1 -1
  298. package/dist/stdin.d.ts +6 -1
  299. package/dist/stdin.d.ts.map +1 -1
  300. package/dist/stdin.js +8 -0
  301. package/dist/stdin.js.map +1 -1
  302. package/dist/timeline-debug/harness.d.ts +14 -0
  303. package/dist/timeline-debug/harness.d.ts.map +1 -1
  304. package/dist/timeline-debug/harness.js +9 -31
  305. package/dist/timeline-debug/harness.js.map +1 -1
  306. package/dist/timeline-debug/target.d.ts.map +1 -1
  307. package/dist/timeline-debug/target.js +1 -24
  308. package/dist/timeline-debug/target.js.map +1 -1
  309. package/dist/validate/index.d.ts +3 -2
  310. package/dist/validate/index.d.ts.map +1 -1
  311. package/dist/validate/index.js +30 -2
  312. package/dist/validate/index.js.map +1 -1
  313. package/dist/workflow-file.d.ts +3 -0
  314. package/dist/workflow-file.d.ts.map +1 -0
  315. package/dist/workflow-file.js +176 -0
  316. package/dist/workflow-file.js.map +1 -0
  317. package/package.json +34 -40
@@ -16,16 +16,16 @@ import { createRequire } from "node:module";
16
16
  import { fileURLToPath } from "node:url";
17
17
  import { dirname, resolve } from "node:path";
18
18
  import { spawnSync } from "node:child_process";
19
- import { createInterface } from "node:readline";
20
- import { workflowToDsl } from "@nodetool-ai/dsl";
19
+ import { workflowToDsl, workflowToScript } from "@nodetool-ai/dsl";
21
20
  import { initDb, migrateSqliteDb, Workflow, Asset, Secret, getSecret } from "@nodetool-ai/models";
22
21
  import { readCachedHfModels, searchCachedHfModels } from "@nodetool-ai/huggingface";
23
22
  import { initMasterKey } from "@nodetool-ai/security";
24
23
  import { installLocalModelInterfaces } from "./local-model-interfaces.js";
25
24
  import { getDefaultDbPath, getDefaultAssetsPath } from "@nodetool-ai/config";
26
- import { ExecutionSession, isExecutionPreflightError } from "@nodetool-ai/execution";
25
+ import { ExecutionSession } from "@nodetool-ai/execution";
27
26
  import { NodeRegistry, createGraphNodeTypeResolver } from "@nodetool-ai/node-sdk";
28
- import { registerBuiltinPacks } from "@nodetool-ai/base-nodes/builtin-packs";
27
+ import { registerCliPacks } from "./packs/host.js";
28
+ import { refusePackInstallsInProcess } from "./packs/install-process.js";
29
29
  import { CLI_LOCAL_BUILTIN_PACK_POLICY, CLI_DSL_BUILTIN_PACK_POLICY } from "./node-registry.js";
30
30
  import { ProcessingContext, createLocalWorkspace, initTelemetry, onPythonBridgeCreated } from "@nodetool-ai/runtime";
31
31
  import { FileStorageAdapter } from "@nodetool-ai/storage";
@@ -33,6 +33,8 @@ import { mkdirSync } from "node:fs";
33
33
  import { addSupervisorOptions, createSupervisorHandle, parseSupervisorFlags, printSupervisedSummary, recordSupervisorCost, streamInterventionLines } from "./supervisor.js";
34
34
  import { registerPackageCommands } from "./commands/package.js";
35
35
  import { registerPackCommands } from "./commands/packs.js";
36
+ import { installMissingPacksAndReexec } from "./commands/install-missing-packs.js";
37
+ import { registerRuntimeCommands } from "./commands/runtime.js";
36
38
  import { registerDeployCommands } from "./commands/deploy.js";
37
39
  import { registerHfCommands } from "./commands/models-hf.js";
38
40
  import { registerWorkerCommands } from "./commands/worker.js";
@@ -61,6 +63,7 @@ import { registerCostsCommands } from "./commands/costs.js";
61
63
  import { registerErrorsCommands } from "./commands/errors.js";
62
64
  import { registerGenerationsCommands } from "./commands/generations.js";
63
65
  import { registerRunsCommands } from "./commands/runs.js";
66
+ import { registerProjectCommands } from "./commands/projects.js";
64
67
  import { registerGameCommands } from "./commands/game.js";
65
68
  import { registerAuthCommands } from "./commands/auth.js";
66
69
  import { registerTelegramCommands } from "./commands/telegram.js";
@@ -68,8 +71,9 @@ import { registerResourceReadCommands } from "./commands/resource-read.js";
68
71
  import { createApiClient } from "./api-client.js";
69
72
  import { listAllModels, listConfiguredProviderInfo, listOllamaModels, listProviderModels } from "./providers.js";
70
73
  import { isString } from "./predicates.js";
71
- import { printTable, asJson } from "./commands/output.js";
72
- import { printCommandError } from "./command-errors.js";
74
+ import { printTable, asJson, readSecretValue } from "./commands/output.js";
75
+ import { printCommandError, commandMissingRuntime, commandMissingPack } from "./command-errors.js";
76
+ import { childExitCode } from "./child-exit.js";
73
77
  const __filename = fileURLToPath(import.meta.url);
74
78
  const __dirname = dirname(__filename);
75
79
  /**
@@ -93,7 +97,9 @@ function ensureDb() {
93
97
  initDb(getDefaultDbPath());
94
98
  }
95
99
  async function setupDb() {
96
- ensureDb();
100
+ const dbPath = getDefaultDbPath();
101
+ await migrateSqliteDb(dbPath);
102
+ initDb(dbPath);
97
103
  // Resolve the master encryption key from keychain / env / AWS so that
98
104
  // both encryption (Secret.upsert) and decryption (Secret.getDecryptedValue)
99
105
  // use the same persistent key. Without this, a fresh process would
@@ -211,14 +217,6 @@ async function makeLocalAssetFetcher() {
211
217
  // other. The interfaces touch the database only when a node calls them, so
212
218
  // installing them before `setupDb()` is safe.
213
219
  await installLocalModelInterfaces();
214
- /**
215
- * What to print when a run command fails. A preflight refusal already reads as
216
- * a complete explanation — printing the error class in front of it only buries
217
- * the secret name the user has to go set.
218
- */
219
- function describeRunFailure(error) {
220
- return isExecutionPreflightError(error) ? error.message : String(error);
221
- }
222
220
  // ---------------------------------------------------------------------------
223
221
  // info
224
222
  // ---------------------------------------------------------------------------
@@ -267,12 +265,13 @@ function parseTraceStdout(v) {
267
265
  addSupervisorOptions(program
268
266
  .command("run <dsl-file>")
269
267
  .description("Run a TypeScript/JavaScript DSL workflow file")
270
- .option("--json", "Output results as JSON (default: pretty-print)")).action(async (dslFile, opts) => {
268
+ .option("--json", "Output results as JSON (default: pretty-print)")
269
+ .option("--install-missing", "Authorize missing node pack installation, then re-execute once")).action(async (dslFile, opts) => {
271
270
  try {
272
271
  const { resolve } = await import("node:path");
273
272
  const { runDslFile } = await import("./run-dsl.js");
274
273
  const { NodeRegistry } = await import("@nodetool-ai/node-sdk");
275
- registerBuiltinPacks(NodeRegistry.global, CLI_DSL_BUILTIN_PACK_POLICY);
274
+ await registerCliPacks(NodeRegistry.global, CLI_DSL_BUILTIN_PACK_POLICY);
276
275
  const supervisorConfig = parseSupervisorFlags(opts);
277
276
  const absolutePath = resolve(dslFile);
278
277
  let results;
@@ -305,8 +304,11 @@ addSupervisorOptions(program
305
304
  }
306
305
  }
307
306
  catch (e) {
308
- console.error(describeRunFailure(e));
309
- process.exit(1);
307
+ const exit = await installMissingPacksAndReexec(e, { command: "run", installMissing: opts.installMissing });
308
+ if (exit !== null) {
309
+ process.exit(exit);
310
+ }
311
+ process.exit(printCommandError(e, opts.json));
310
312
  }
311
313
  });
312
314
  program
@@ -364,14 +366,17 @@ program
364
366
  .option("--host <host>", "Host to bind", "127.0.0.1")
365
367
  .option("--port <port>", "Port to listen on", "7777")
366
368
  .action((opts) => {
367
- const serverPath = resolve(__dirname, "../../websocket/dist/server.js");
369
+ refusePackInstallsInProcess("serve");
370
+ const serverPath = resolve(__dirname, "../dist/packs/serve.js");
368
371
  process.env["HOST"] = opts.host;
369
372
  process.env["PORT"] = opts.port;
370
- const result = spawnSync("node", [serverPath], {
373
+ const result = spawnSync(process.execPath, [serverPath], {
371
374
  stdio: "inherit",
372
375
  env: { ...process.env }
373
376
  });
374
- process.exit(result.status ?? 0);
377
+ if (result.error)
378
+ console.error(`Could not start the server: ${result.error.message}`);
379
+ process.exit(childExitCode(result));
375
380
  });
376
381
  // ---------------------------------------------------------------------------
377
382
  // chat
@@ -398,7 +403,7 @@ program
398
403
  stdio: "inherit",
399
404
  env: { ...process.env }
400
405
  });
401
- process.exit(result.status ?? 1);
406
+ process.exit(childExitCode(result));
402
407
  });
403
408
  // ---------------------------------------------------------------------------
404
409
  // workflows
@@ -411,6 +416,7 @@ addSupervisorOptions(workflows
411
416
  .description("Run a workflow by ID, JSON file, or TypeScript DSL file")
412
417
  .option("--params <json>", "JSON params string")
413
418
  .option("--json", "Output as JSON")
419
+ .option("--install-missing", "Authorize missing node pack installation, then re-execute once")
414
420
  .option("--asset-output-mode <mode>", "How media outputs are materialized: native | raw | data_uri | workspace | storage_url | temp_url", "native")
415
421
  .option("--workspace <dir>", "Workspace directory for workspace-mode asset output (default: ./nodetool-output)")
416
422
  .option("--trigger-event <json>", 'Wake a trigger node as the scheduler/webhook adapter would: \'{"node_id":"watch","payload":{"path":"/tmp/a.csv","event":"created"}}\'. ' +
@@ -453,14 +459,8 @@ addSupervisorOptions(workflows
453
459
  /** A DSL/JSON workflow file: the graph, optionally wrapped. */
454
460
  let raw;
455
461
  if (idOrFile.endsWith(".ts") || idOrFile.endsWith(".tsx")) {
456
- // Execute DSL file via tsx and capture JSON output
457
- const { execFileSync } = await import("node:child_process");
458
- const output = execFileSync("npx", ["tsx", resolve(idOrFile)], {
459
- encoding: "utf8",
460
- cwd: dirname(resolve(idOrFile)),
461
- timeout: 30000
462
- });
463
- raw = JSON.parse(output.trim());
462
+ const { readFileTarget } = await import("./debug/target.js");
463
+ raw = (await readFileTarget(idOrFile)).raw;
464
464
  }
465
465
  else {
466
466
  const { readFileSync } = await import("node:fs");
@@ -486,7 +486,7 @@ addSupervisorOptions(workflows
486
486
  // the graph through `normalizeGraph` (@nodetool-ai/execution) — no
487
487
  // need to duplicate that here.
488
488
  const registry = new NodeRegistry();
489
- registerBuiltinPacks(registry, CLI_LOCAL_BUILTIN_PACK_POLICY);
489
+ await registerCliPacks(registry, CLI_LOCAL_BUILTIN_PACK_POLICY);
490
490
  const jobId = `job-${Date.now()}`;
491
491
  // Resolve asset URIs (e.g. /api/storage/<key>) against the local
492
492
  // assets directory, so workflows referencing stored assets run the
@@ -582,6 +582,13 @@ addSupervisorOptions(workflows
582
582
  ? streamInterventionLines(session.messages)
583
583
  : Promise.resolve();
584
584
  const result = await session.result;
585
+ if (result.status === "failed" && (commandMissingRuntime(result) || commandMissingPack(result))) {
586
+ const exit = await installMissingPacksAndReexec(result, { command: "workflows-run", installMissing: opts.installMissing });
587
+ if (exit !== null) {
588
+ process.exit(exit);
589
+ }
590
+ process.exit(printCommandError(result, opts.json));
591
+ }
585
592
  await interventionLines;
586
593
  supervisor?.handle.close();
587
594
  const interventions = result.interventions ?? [];
@@ -618,8 +625,58 @@ addSupervisorOptions(workflows
618
625
  process.exit(result.status === "completed" ? 0 : 1);
619
626
  }
620
627
  catch (e) {
621
- console.error(describeRunFailure(e));
622
- process.exit(1);
628
+ const exit = await installMissingPacksAndReexec(e, { command: "workflows-run", installMissing: opts.installMissing });
629
+ if (exit !== null) {
630
+ process.exit(exit);
631
+ }
632
+ process.exit(printCommandError(e, opts.json));
633
+ }
634
+ });
635
+ workflows
636
+ .command("export-script <workflow_id_or_file>")
637
+ .description("Convert a workflow into a JavaScript script that calls each node in order (local DB by id, or a JSON file)")
638
+ .option("-t, --target <target>", "sandbox (a JS script document or Code node body) or node (a standalone Node.js .mjs)", "sandbox")
639
+ .option("-o, --output <file>", "Write the script to a file")
640
+ .action(async (idOrFile, opts) => {
641
+ try {
642
+ if (opts.target !== "sandbox" && opts.target !== "node") {
643
+ throw new Error(`Unknown target "${opts.target}": use "sandbox" or "node"`);
644
+ }
645
+ let graph;
646
+ let name;
647
+ if (idOrFile.endsWith(".json") ||
648
+ idOrFile.includes("/") ||
649
+ idOrFile.includes("\\")) {
650
+ const { readFileSync } = await import("node:fs");
651
+ const raw = JSON.parse(readFileSync(idOrFile, "utf8"));
652
+ graph = (raw.graph ?? raw);
653
+ name = isString(raw.name) ? raw.name : null;
654
+ }
655
+ else {
656
+ ensureDb();
657
+ const wf = await Workflow.find(LOCAL_USER_ID, idOrFile);
658
+ if (!wf)
659
+ throw new Error(`Workflow not found: ${idOrFile}`);
660
+ graph = wf.getGraph();
661
+ name = isString(wf.name) ? wf.name : null;
662
+ }
663
+ const script = workflowToScript(graph, {
664
+ target: opts.target,
665
+ workflowName: name
666
+ });
667
+ for (const issue of script.unsupported) {
668
+ console.error(`warning: ${issue.node_type} (${issue.node_id}) ${issue.message}`);
669
+ }
670
+ if (opts.output) {
671
+ const { writeFile } = await import("node:fs/promises");
672
+ await writeFile(opts.output, script.code, "utf8");
673
+ console.log(opts.output);
674
+ return;
675
+ }
676
+ console.log(script.code);
677
+ }
678
+ catch (e) {
679
+ process.exit(printCommandError(e));
623
680
  }
624
681
  });
625
682
  workflows
@@ -662,8 +719,7 @@ workflows
662
719
  console.log(source);
663
720
  }
664
721
  catch (e) {
665
- printCommandError(e);
666
- process.exit(1);
722
+ process.exit(printCommandError(e));
667
723
  }
668
724
  });
669
725
  workflows
@@ -774,8 +830,7 @@ workflows
774
830
  console.log(outPath);
775
831
  }
776
832
  catch (e) {
777
- printCommandError(e);
778
- process.exit(1);
833
+ process.exit(printCommandError(e));
779
834
  }
780
835
  });
781
836
  workflows
@@ -856,8 +911,7 @@ workflows
856
911
  console.log(outPath);
857
912
  }
858
913
  catch (e) {
859
- printCommandError(e);
860
- process.exit(1);
914
+ process.exit(printCommandError(e));
861
915
  }
862
916
  });
863
917
  workflows
@@ -912,8 +966,7 @@ workflows
912
966
  }
913
967
  }
914
968
  catch (e) {
915
- printCommandError(e, opts.json);
916
- process.exit(1);
969
+ process.exit(printCommandError(e, opts.json));
917
970
  }
918
971
  });
919
972
  // ---------------------------------------------------------------------------
@@ -963,8 +1016,7 @@ models
963
1016
  printTable(rows.map(modelRow));
964
1017
  }
965
1018
  catch (e) {
966
- printCommandError(e, opts.json);
967
- process.exit(1);
1019
+ process.exit(printCommandError(e, opts.json));
968
1020
  }
969
1021
  });
970
1022
  models
@@ -985,8 +1037,7 @@ models
985
1037
  })));
986
1038
  }
987
1039
  catch (e) {
988
- printCommandError(e, opts.json);
989
- process.exit(1);
1040
+ process.exit(printCommandError(e, opts.json));
990
1041
  }
991
1042
  });
992
1043
  registerRecommendedCommand(models);
@@ -1014,8 +1065,7 @@ models
1014
1065
  printTable(rows.map(modelRow));
1015
1066
  }
1016
1067
  catch (e) {
1017
- printCommandError(e, opts.json);
1018
- process.exit(1);
1068
+ process.exit(printCommandError(e, opts.json));
1019
1069
  }
1020
1070
  });
1021
1071
  models
@@ -1061,8 +1111,7 @@ models
1061
1111
  printTable(rows.map(modelRow));
1062
1112
  }
1063
1113
  catch (e) {
1064
- printCommandError(e, opts.json);
1065
- process.exit(1);
1114
+ process.exit(printCommandError(e, opts.json));
1066
1115
  }
1067
1116
  });
1068
1117
  models
@@ -1086,8 +1135,7 @@ models
1086
1135
  printTable(rows.map(modelRow));
1087
1136
  }
1088
1137
  catch (e) {
1089
- printCommandError(e, opts.json);
1090
- process.exit(1);
1138
+ process.exit(printCommandError(e, opts.json));
1091
1139
  }
1092
1140
  });
1093
1141
  // ---------------------------------------------------------------------------
@@ -1123,8 +1171,7 @@ storage
1123
1171
  process.exit(1);
1124
1172
  }
1125
1173
  catch (e) {
1126
- printCommandError(e, opts.json);
1127
- process.exit(1);
1174
+ process.exit(printCommandError(e, opts.json));
1128
1175
  }
1129
1176
  });
1130
1177
  workflows
@@ -1154,8 +1201,7 @@ workflows
1154
1201
  process.exit(1);
1155
1202
  }
1156
1203
  catch (e) {
1157
- printCommandError(e, opts.json);
1158
- process.exit(1);
1204
+ process.exit(printCommandError(e, opts.json));
1159
1205
  }
1160
1206
  });
1161
1207
  // ---------------------------------------------------------------------------
@@ -1179,8 +1225,7 @@ secrets
1179
1225
  printTable(items.map((s) => ({ key: s.key, updated_at: s.updated_at ?? "" })));
1180
1226
  }
1181
1227
  catch (e) {
1182
- printCommandError(e);
1183
- process.exit(1);
1228
+ process.exit(printCommandError(e));
1184
1229
  }
1185
1230
  });
1186
1231
  secrets
@@ -1190,18 +1235,11 @@ secrets
1190
1235
  .option("--description <desc>", "Optional description")
1191
1236
  .action(async (key, opts) => {
1192
1237
  await setupDb();
1193
- const rl = createInterface({
1194
- input: process.stdin,
1195
- output: process.stderr
1196
- });
1197
- const value = await new Promise((resolve) => {
1198
- process.stderr.write(`Enter value for '${key}': `);
1199
- rl.question("", (ans) => {
1200
- rl.close();
1201
- resolve(ans);
1202
- });
1203
- });
1204
1238
  try {
1239
+ // Hidden on a TTY: an echoed value stays in the terminal scrollback.
1240
+ const value = await readSecretValue(`Enter value for '${key}': `);
1241
+ if (!value)
1242
+ throw new Error(`No value given for '${key}'; nothing stored.`);
1205
1243
  await Secret.upsert({
1206
1244
  userId: opts.userId,
1207
1245
  key,
@@ -1211,8 +1249,7 @@ secrets
1211
1249
  console.log(`Secret '${key}' stored.`);
1212
1250
  }
1213
1251
  catch (e) {
1214
- printCommandError(e);
1215
- process.exit(1);
1252
+ process.exit(printCommandError(e));
1216
1253
  }
1217
1254
  });
1218
1255
  secrets
@@ -1230,8 +1267,7 @@ secrets
1230
1267
  console.log(value);
1231
1268
  }
1232
1269
  catch (e) {
1233
- printCommandError(e);
1234
- process.exit(1);
1270
+ process.exit(printCommandError(e));
1235
1271
  }
1236
1272
  });
1237
1273
  // ---------------------------------------------------------------------------
@@ -1292,6 +1328,7 @@ mcp
1292
1328
  "MCP protocol channel.")
1293
1329
  .action(async () => {
1294
1330
  try {
1331
+ refusePackInstallsInProcess("mcp serve");
1295
1332
  const { createMcpServer, createMcpStdioTransport, forwardMcpStdioToLocalServer } = await import("@nodetool-ai/websocket");
1296
1333
  if (await forwardMcpStdioToLocalServer()) {
1297
1334
  process.stderr.write("NodeTool MCP forwarding to the local API server.\n");
@@ -1301,7 +1338,7 @@ mcp
1301
1338
  // A local TS-node registry powers list_nodes / search_nodes /
1302
1339
  // validate_workflow without spinning up a Python worker.
1303
1340
  const registry = new NodeRegistry();
1304
- registerBuiltinPacks(registry, CLI_LOCAL_BUILTIN_PACK_POLICY);
1341
+ await registerCliPacks(registry, CLI_LOCAL_BUILTIN_PACK_POLICY);
1305
1342
  // stdio serves exactly one local user; "1" is the local single-user id.
1306
1343
  const server = createMcpServer({
1307
1344
  registry,
@@ -1314,15 +1351,16 @@ mcp
1314
1351
  // closes the connection.
1315
1352
  }
1316
1353
  catch (e) {
1317
- printCommandError(e);
1318
- process.exit(1);
1354
+ process.exit(printCommandError(e));
1319
1355
  }
1320
1356
  });
1321
1357
  // ---------------------------------------------------------------------------
1322
1358
  // package
1323
1359
  // ---------------------------------------------------------------------------
1360
+ registerProjectCommands(program);
1324
1361
  registerPackageCommands(program);
1325
1362
  registerPackCommands(program);
1363
+ registerRuntimeCommands(program);
1326
1364
  registerWorkerCommands(program);
1327
1365
  // Any command that opens a remote Python bridge keeps the attached worker's
1328
1366
  // idle clock fresh, so the reaper doesn't pause a GPU that is mid-job.