@camerontaylor/paseo-cli 0.8.0-fork.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 (288) hide show
  1. package/bin/paseo +3 -0
  2. package/dist/classify.d.ts +19 -0
  3. package/dist/classify.js +49 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.js +135 -0
  6. package/dist/commands/agent/archive.d.ts +18 -0
  7. package/dist/commands/agent/archive.js +102 -0
  8. package/dist/commands/agent/attach.d.ts +11 -0
  9. package/dist/commands/agent/attach.js +161 -0
  10. package/dist/commands/agent/delete.d.ts +15 -0
  11. package/dist/commands/agent/delete.js +107 -0
  12. package/dist/commands/agent/detach.d.ts +9 -0
  13. package/dist/commands/agent/detach.js +38 -0
  14. package/dist/commands/agent/import.d.ts +14 -0
  15. package/dist/commands/agent/import.js +122 -0
  16. package/dist/commands/agent/index.d.ts +3 -0
  17. package/dist/commands/agent/index.js +56 -0
  18. package/dist/commands/agent/inspect.d.ts +15 -0
  19. package/dist/commands/agent/inspect.js +209 -0
  20. package/dist/commands/agent/logs.d.ts +19 -0
  21. package/dist/commands/agent/logs.js +180 -0
  22. package/dist/commands/agent/ls.d.ts +44 -0
  23. package/dist/commands/agent/ls.js +212 -0
  24. package/dist/commands/agent/mode.d.ts +18 -0
  25. package/dist/commands/agent/mode.js +100 -0
  26. package/dist/commands/agent/open.d.ts +11 -0
  27. package/dist/commands/agent/open.js +61 -0
  28. package/dist/commands/agent/reload.d.ts +15 -0
  29. package/dist/commands/agent/reload.js +75 -0
  30. package/dist/commands/agent/run.d.ts +78 -0
  31. package/dist/commands/agent/run.js +554 -0
  32. package/dist/commands/agent/send.d.ts +19 -0
  33. package/dist/commands/agent/send.js +187 -0
  34. package/dist/commands/agent/stop.d.ts +17 -0
  35. package/dist/commands/agent/stop.js +115 -0
  36. package/dist/commands/agent/update.d.ts +51 -0
  37. package/dist/commands/agent/update.js +186 -0
  38. package/dist/commands/agent/wait.d.ts +17 -0
  39. package/dist/commands/agent/wait.js +158 -0
  40. package/dist/commands/clone.d.ts +17 -0
  41. package/dist/commands/clone.js +65 -0
  42. package/dist/commands/daemon/index.d.ts +3 -0
  43. package/dist/commands/daemon/index.js +60 -0
  44. package/dist/commands/daemon/local-daemon.d.ts +78 -0
  45. package/dist/commands/daemon/local-daemon.js +547 -0
  46. package/dist/commands/daemon/pair.d.ts +35 -0
  47. package/dist/commands/daemon/pair.js +167 -0
  48. package/dist/commands/daemon/reload.d.ts +10 -0
  49. package/dist/commands/daemon/reload.js +36 -0
  50. package/dist/commands/daemon/restart.d.ts +12 -0
  51. package/dist/commands/daemon/restart.js +99 -0
  52. package/dist/commands/daemon/runtime-toolchain.d.ts +6 -0
  53. package/dist/commands/daemon/runtime-toolchain.js +87 -0
  54. package/dist/commands/daemon/set-password.d.ts +17 -0
  55. package/dist/commands/daemon/set-password.js +82 -0
  56. package/dist/commands/daemon/start.d.ts +6 -0
  57. package/dist/commands/daemon/start.js +57 -0
  58. package/dist/commands/daemon/status.d.ts +21 -0
  59. package/dist/commands/daemon/status.js +363 -0
  60. package/dist/commands/daemon/stop.d.ts +15 -0
  61. package/dist/commands/daemon/stop.js +60 -0
  62. package/dist/commands/heartbeat/index.d.ts +3 -0
  63. package/dist/commands/heartbeat/index.js +139 -0
  64. package/dist/commands/hooks.d.ts +19 -0
  65. package/dist/commands/hooks.js +89 -0
  66. package/dist/commands/hub/authority.d.ts +17 -0
  67. package/dist/commands/hub/authority.js +18 -0
  68. package/dist/commands/hub/connect.d.ts +23 -0
  69. package/dist/commands/hub/connect.js +44 -0
  70. package/dist/commands/hub/credentials.d.ts +21 -0
  71. package/dist/commands/hub/credentials.js +143 -0
  72. package/dist/commands/hub/daemon-client.d.ts +40 -0
  73. package/dist/commands/hub/daemon-client.js +14 -0
  74. package/dist/commands/hub/deploy-bundle.d.ts +16 -0
  75. package/dist/commands/hub/deploy-bundle.js +248 -0
  76. package/dist/commands/hub/deploy-triggers.d.ts +6 -0
  77. package/dist/commands/hub/deploy-triggers.js +116 -0
  78. package/dist/commands/hub/deploy.d.ts +50 -0
  79. package/dist/commands/hub/deploy.js +159 -0
  80. package/dist/commands/hub/disconnect.d.ts +16 -0
  81. package/dist/commands/hub/disconnect.js +24 -0
  82. package/dist/commands/hub/error.d.ts +6 -0
  83. package/dist/commands/hub/error.js +9 -0
  84. package/dist/commands/hub/export.d.ts +28 -0
  85. package/dist/commands/hub/export.js +80 -0
  86. package/dist/commands/hub/help.d.ts +3 -0
  87. package/dist/commands/hub/help.js +5 -0
  88. package/dist/commands/hub/hub-client/index.d.ts +22 -0
  89. package/dist/commands/hub/hub-client/index.js +135 -0
  90. package/dist/commands/hub/hub-client/internal/contracts.d.ts +126 -0
  91. package/dist/commands/hub/hub-client/internal/contracts.js +85 -0
  92. package/dist/commands/hub/hub-client/internal/problem.d.ts +3 -0
  93. package/dist/commands/hub/hub-client/internal/problem.js +85 -0
  94. package/dist/commands/hub/hub-client/internal/transport.d.ts +15 -0
  95. package/dist/commands/hub/hub-client/internal/transport.js +30 -0
  96. package/dist/commands/hub/index.d.ts +20 -0
  97. package/dist/commands/hub/index.js +94 -0
  98. package/dist/commands/hub/init-plan.d.ts +33 -0
  99. package/dist/commands/hub/init-plan.js +94 -0
  100. package/dist/commands/hub/init.d.ts +35 -0
  101. package/dist/commands/hub/init.js +524 -0
  102. package/dist/commands/hub/login-flow.d.ts +34 -0
  103. package/dist/commands/hub/login-flow.js +78 -0
  104. package/dist/commands/hub/login.d.ts +23 -0
  105. package/dist/commands/hub/login.js +40 -0
  106. package/dist/commands/hub/logout.d.ts +32 -0
  107. package/dist/commands/hub/logout.js +71 -0
  108. package/dist/commands/hub/origin.d.ts +2 -0
  109. package/dist/commands/hub/origin.js +27 -0
  110. package/dist/commands/hub/permissions.d.ts +21 -0
  111. package/dist/commands/hub/permissions.js +61 -0
  112. package/dist/commands/hub/projects.d.ts +24 -0
  113. package/dist/commands/hub/projects.js +49 -0
  114. package/dist/commands/hub/reporter.d.ts +10 -0
  115. package/dist/commands/hub/reporter.js +11 -0
  116. package/dist/commands/hub/starter-agent-runtime.d.ts +37 -0
  117. package/dist/commands/hub/starter-agent-runtime.js +49 -0
  118. package/dist/commands/hub/starter-trigger.d.ts +10 -0
  119. package/dist/commands/hub/starter-trigger.js +30 -0
  120. package/dist/commands/hub/status-output.d.ts +13 -0
  121. package/dist/commands/hub/status-output.js +30 -0
  122. package/dist/commands/onboard.d.ts +10 -0
  123. package/dist/commands/onboard.js +400 -0
  124. package/dist/commands/open.d.ts +4 -0
  125. package/dist/commands/open.js +89 -0
  126. package/dist/commands/permit/allow.d.ts +20 -0
  127. package/dist/commands/permit/allow.js +133 -0
  128. package/dist/commands/permit/deny.d.ts +12 -0
  129. package/dist/commands/permit/deny.js +105 -0
  130. package/dist/commands/permit/index.d.ts +3 -0
  131. package/dist/commands/permit/index.js +27 -0
  132. package/dist/commands/permit/ls.d.ts +18 -0
  133. package/dist/commands/permit/ls.js +66 -0
  134. package/dist/commands/plugin/index.d.ts +17 -0
  135. package/dist/commands/plugin/index.js +138 -0
  136. package/dist/commands/plugin/scaffold.d.ts +6 -0
  137. package/dist/commands/plugin/scaffold.js +162 -0
  138. package/dist/commands/plugin/shared.d.ts +5 -0
  139. package/dist/commands/plugin/shared.js +30 -0
  140. package/dist/commands/project/create.d.ts +10 -0
  141. package/dist/commands/project/create.js +41 -0
  142. package/dist/commands/project/delete.d.ts +9 -0
  143. package/dist/commands/project/delete.js +33 -0
  144. package/dist/commands/project/index.d.ts +3 -0
  145. package/dist/commands/project/index.js +28 -0
  146. package/dist/commands/project/ls.d.ts +5 -0
  147. package/dist/commands/project/ls.js +19 -0
  148. package/dist/commands/project/rename.d.ts +15 -0
  149. package/dist/commands/project/rename.js +50 -0
  150. package/dist/commands/project/shared.d.ts +11 -0
  151. package/dist/commands/project/shared.js +18 -0
  152. package/dist/commands/provider/add.d.ts +30 -0
  153. package/dist/commands/provider/add.js +123 -0
  154. package/dist/commands/provider/diagnostic.d.ts +12 -0
  155. package/dist/commands/provider/diagnostic.js +31 -0
  156. package/dist/commands/provider/index.d.ts +3 -0
  157. package/dist/commands/provider/index.js +38 -0
  158. package/dist/commands/provider/ls.d.ts +20 -0
  159. package/dist/commands/provider/ls.js +76 -0
  160. package/dist/commands/provider/models.d.ts +20 -0
  161. package/dist/commands/provider/models.js +53 -0
  162. package/dist/commands/provider/rm.d.ts +10 -0
  163. package/dist/commands/provider/rm.js +45 -0
  164. package/dist/commands/provider/shared.d.ts +7 -0
  165. package/dist/commands/provider/shared.js +10 -0
  166. package/dist/commands/schedule/create.d.ts +19 -0
  167. package/dist/commands/schedule/create.js +41 -0
  168. package/dist/commands/schedule/delete.d.ts +10 -0
  169. package/dist/commands/schedule/delete.js +32 -0
  170. package/dist/commands/schedule/index.d.ts +3 -0
  171. package/dist/commands/schedule/index.js +66 -0
  172. package/dist/commands/schedule/inspect.d.ts +6 -0
  173. package/dist/commands/schedule/inspect.js +27 -0
  174. package/dist/commands/schedule/logs.d.ts +6 -0
  175. package/dist/commands/schedule/logs.js +24 -0
  176. package/dist/commands/schedule/ls.d.ts +5 -0
  177. package/dist/commands/schedule/ls.js +25 -0
  178. package/dist/commands/schedule/pause.d.ts +5 -0
  179. package/dist/commands/schedule/pause.js +24 -0
  180. package/dist/commands/schedule/resume.d.ts +5 -0
  181. package/dist/commands/schedule/resume.js +24 -0
  182. package/dist/commands/schedule/run-once.d.ts +5 -0
  183. package/dist/commands/schedule/run-once.js +24 -0
  184. package/dist/commands/schedule/schema.d.ts +21 -0
  185. package/dist/commands/schedule/schema.js +67 -0
  186. package/dist/commands/schedule/shared.d.ts +59 -0
  187. package/dist/commands/schedule/shared.js +358 -0
  188. package/dist/commands/schedule/types.d.ts +165 -0
  189. package/dist/commands/schedule/types.js +2 -0
  190. package/dist/commands/schedule/update.d.ts +21 -0
  191. package/dist/commands/schedule/update.js +40 -0
  192. package/dist/commands/script/index.d.ts +3 -0
  193. package/dist/commands/script/index.js +19 -0
  194. package/dist/commands/script/ls.d.ts +6 -0
  195. package/dist/commands/script/ls.js +20 -0
  196. package/dist/commands/script/schema.d.ts +5 -0
  197. package/dist/commands/script/schema.js +13 -0
  198. package/dist/commands/script/shared.d.ts +11 -0
  199. package/dist/commands/script/shared.js +59 -0
  200. package/dist/commands/script/start.d.ts +6 -0
  201. package/dist/commands/script/start.js +23 -0
  202. package/dist/commands/script/stop.d.ts +6 -0
  203. package/dist/commands/script/stop.js +23 -0
  204. package/dist/commands/speech/index.d.ts +3 -0
  205. package/dist/commands/speech/index.js +5 -0
  206. package/dist/commands/terminal/capture.d.ts +10 -0
  207. package/dist/commands/terminal/capture.js +68 -0
  208. package/dist/commands/terminal/create.d.ts +11 -0
  209. package/dist/commands/terminal/create.js +29 -0
  210. package/dist/commands/terminal/index.d.ts +3 -0
  211. package/dist/commands/terminal/index.js +45 -0
  212. package/dist/commands/terminal/kill.d.ts +6 -0
  213. package/dist/commands/terminal/kill.js +36 -0
  214. package/dist/commands/terminal/ls.d.ts +11 -0
  215. package/dist/commands/terminal/ls.js +21 -0
  216. package/dist/commands/terminal/schema.d.ts +10 -0
  217. package/dist/commands/terminal/schema.js +17 -0
  218. package/dist/commands/terminal/send-keys.d.ts +7 -0
  219. package/dist/commands/terminal/send-keys.js +45 -0
  220. package/dist/commands/terminal/shared.d.ts +12 -0
  221. package/dist/commands/terminal/shared.js +62 -0
  222. package/dist/commands/workspace/archive.d.ts +12 -0
  223. package/dist/commands/workspace/archive.js +41 -0
  224. package/dist/commands/workspace/create.d.ts +49 -0
  225. package/dist/commands/workspace/create.js +114 -0
  226. package/dist/commands/workspace/index.d.ts +3 -0
  227. package/dist/commands/workspace/index.js +45 -0
  228. package/dist/commands/workspace/ls.d.ts +7 -0
  229. package/dist/commands/workspace/ls.js +28 -0
  230. package/dist/commands/workspace/rename.d.ts +22 -0
  231. package/dist/commands/workspace/rename.js +61 -0
  232. package/dist/commands/workspace/setup.d.ts +11 -0
  233. package/dist/commands/workspace/setup.js +41 -0
  234. package/dist/commands/workspace/shared.d.ts +12 -0
  235. package/dist/commands/workspace/shared.js +20 -0
  236. package/dist/commands/worktree/archive.d.ts +20 -0
  237. package/dist/commands/worktree/archive.js +104 -0
  238. package/dist/commands/worktree/create-input.d.ts +15 -0
  239. package/dist/commands/worktree/create-input.js +56 -0
  240. package/dist/commands/worktree/create.d.ts +11 -0
  241. package/dist/commands/worktree/create.js +58 -0
  242. package/dist/commands/worktree/index.d.ts +3 -0
  243. package/dist/commands/worktree/index.js +25 -0
  244. package/dist/commands/worktree/ls.d.ts +19 -0
  245. package/dist/commands/worktree/ls.js +97 -0
  246. package/dist/index.d.ts +2 -0
  247. package/dist/index.js +6 -0
  248. package/dist/output/index.d.ts +45 -0
  249. package/dist/output/index.js +47 -0
  250. package/dist/output/json.d.ts +11 -0
  251. package/dist/output/json.js +37 -0
  252. package/dist/output/pairing.d.ts +8 -0
  253. package/dist/output/pairing.js +24 -0
  254. package/dist/output/quiet.d.ts +9 -0
  255. package/dist/output/quiet.js +22 -0
  256. package/dist/output/render.d.ts +15 -0
  257. package/dist/output/render.js +84 -0
  258. package/dist/output/table.d.ts +13 -0
  259. package/dist/output/table.js +135 -0
  260. package/dist/output/types.d.ts +73 -0
  261. package/dist/output/types.js +8 -0
  262. package/dist/output/with-output.d.ts +41 -0
  263. package/dist/output/with-output.js +85 -0
  264. package/dist/output/yaml.d.ts +11 -0
  265. package/dist/output/yaml.js +38 -0
  266. package/dist/run.d.ts +14 -0
  267. package/dist/run.js +40 -0
  268. package/dist/ssh/ssh-tunnel.d.ts +9 -0
  269. package/dist/ssh/ssh-tunnel.js +79 -0
  270. package/dist/utils/client-id.d.ts +2 -0
  271. package/dist/utils/client-id.js +37 -0
  272. package/dist/utils/client.d.ts +54 -0
  273. package/dist/utils/client.js +363 -0
  274. package/dist/utils/command-options.d.ts +7 -0
  275. package/dist/utils/command-options.js +25 -0
  276. package/dist/utils/duration.d.ts +7 -0
  277. package/dist/utils/duration.js +39 -0
  278. package/dist/utils/errors.d.ts +5 -0
  279. package/dist/utils/errors.js +10 -0
  280. package/dist/utils/paths.d.ts +12 -0
  281. package/dist/utils/paths.js +22 -0
  282. package/dist/utils/provider-model.d.ts +11 -0
  283. package/dist/utils/provider-model.js +49 -0
  284. package/dist/utils/timeline.d.ts +11 -0
  285. package/dist/utils/timeline.js +11 -0
  286. package/dist/version.d.ts +2 -0
  287. package/dist/version.js +10 -0
  288. package/package.json +50 -0
@@ -0,0 +1,167 @@
1
+ import { confirm, isCancel, log } from "@clack/prompts";
2
+ import { Command } from "commander";
3
+ import chalk from "chalk";
4
+ import { generateLocalPairingOffer, getOrCreateServerId, loadConfig, resolvePaseoHome, } from "@camerontaylor/paseo-server";
5
+ import { tryConnectToDaemon } from "../../utils/client.js";
6
+ import { resolveLocalDaemonState } from "./local-daemon.js";
7
+ import { addJsonOption } from "../../utils/command-options.js";
8
+ import { formatPairingInstructions } from "../../output/pairing.js";
9
+ const PAIRING_DAEMON_RPC_TIMEOUT_MS = 1500;
10
+ const RELAY_DOCS_URL = "https://paseo.sh/docs/security";
11
+ function createProcessOutput() {
12
+ return {
13
+ columns: process.stdout.columns,
14
+ writeStdout(message) {
15
+ process.stdout.write(message);
16
+ },
17
+ writeStderr(message) {
18
+ process.stderr.write(message);
19
+ },
20
+ setExitCode(code) {
21
+ process.exitCode = code;
22
+ },
23
+ success(message) {
24
+ log.success(message);
25
+ },
26
+ };
27
+ }
28
+ export function pairCommand() {
29
+ return addJsonOption(new Command("pair").description("Print the daemon pairing QR code and link"))
30
+ .option("--home <path>", "Paseo home directory (default: ~/.paseo)")
31
+ .option("--relay", "Enable relay without prompting")
32
+ .action(async (_options, command) => {
33
+ await runPairCommand(command.optsWithGlobals());
34
+ });
35
+ }
36
+ export async function resolveLocalPairingOffer(options) {
37
+ const state = resolveLocalDaemonState({ home: options.paseoHome });
38
+ const serverId = getOrCreateServerId(state.home);
39
+ const daemonOffer = await resolveDaemonPairingOffer(state.listen, serverId, options.enableRelay);
40
+ if (daemonOffer)
41
+ return daemonOffer;
42
+ if (state.running) {
43
+ throw new Error("The running daemon did not provide a pairing offer. Check daemon connectivity or update the daemon.");
44
+ }
45
+ const config = loadConfig(options.paseoHome);
46
+ if (options.enableRelay && !config.relayEnabled) {
47
+ throw new Error("Start the daemon before enabling relay for pairing.");
48
+ }
49
+ return generateLocalPairingOffer({
50
+ paseoHome: options.paseoHome,
51
+ relayEnabled: config.relayEnabled,
52
+ relayEndpoint: config.relayEndpoint,
53
+ relayPublicEndpoint: config.relayPublicEndpoint,
54
+ relayUseTls: config.relayUseTls,
55
+ relayPublicUseTls: config.relayPublicUseTls,
56
+ appBaseUrl: config.appBaseUrl,
57
+ includeQr: true,
58
+ });
59
+ }
60
+ async function resolveDaemonPairingOffer(listen, expectedServerId, enableRelay) {
61
+ const client = await tryConnectToDaemon({
62
+ host: listen,
63
+ timeout: PAIRING_DAEMON_RPC_TIMEOUT_MS,
64
+ });
65
+ if (!client)
66
+ return null;
67
+ try {
68
+ const serverInfo = client.getLastServerInfoMessage();
69
+ if (serverInfo?.serverId.trim() !== expectedServerId) {
70
+ throw new Error("The reachable daemon belongs to a different Paseo home. Check --home or the daemon listen configuration.");
71
+ }
72
+ if (serverInfo?.features?.daemonStatusRpc !== true) {
73
+ throw new Error("Update the Paseo daemon before pairing from this command.");
74
+ }
75
+ let offer = await client.getDaemonPairingOffer({
76
+ timeout: PAIRING_DAEMON_RPC_TIMEOUT_MS,
77
+ });
78
+ if (!offer.relayEnabled && enableRelay) {
79
+ if (serverInfo.features.relayConfig !== true) {
80
+ throw new Error("Update the Paseo daemon before enabling relay from this command.");
81
+ }
82
+ await client.patchDaemonConfig({ relay: { enabled: true } });
83
+ offer = await client.getDaemonPairingOffer({
84
+ timeout: PAIRING_DAEMON_RPC_TIMEOUT_MS,
85
+ });
86
+ }
87
+ return {
88
+ relayEnabled: offer.relayEnabled,
89
+ url: offer.url || null,
90
+ qr: offer.qr ?? null,
91
+ };
92
+ }
93
+ finally {
94
+ await client.close().catch(() => undefined);
95
+ }
96
+ }
97
+ export async function confirmRelayPairing() {
98
+ log.message("Your connection is end-to-end encrypted. Paseo cannot read your code or messages.");
99
+ log.message(`Learn how it works: ${RELAY_DOCS_URL}`);
100
+ const answer = await confirm({
101
+ message: "Enable relay to pair a device?",
102
+ initialValue: false,
103
+ });
104
+ return !isCancel(answer) && answer;
105
+ }
106
+ export function printDirectConnectionGuidance() {
107
+ console.log("Daemon is running with relay off.");
108
+ console.log("To connect another device directly, use the daemon's TCP address over your LAN, Tailscale, or another VPN.");
109
+ console.log(`Learn more: ${RELAY_DOCS_URL}#direct-connections`);
110
+ }
111
+ export async function runPairCommand(options, dependencyOverrides = {}) {
112
+ if (options.home)
113
+ process.env.PASEO_HOME = options.home;
114
+ const dependencies = {
115
+ resolveOffer: resolveLocalPairingOffer,
116
+ confirmRelay: confirmRelayPairing,
117
+ printDirectGuidance: printDirectConnectionGuidance,
118
+ isInteractive: () => Boolean(process.stdin.isTTY && process.stdout.isTTY),
119
+ output: createProcessOutput(),
120
+ ...dependencyOverrides,
121
+ };
122
+ const paseoHome = resolvePaseoHome();
123
+ let pairing = await dependencies.resolveOffer({
124
+ paseoHome,
125
+ enableRelay: options.relay === true,
126
+ });
127
+ const canPrompt = dependencies.isInteractive() && options.json !== true;
128
+ if (!pairing.relayEnabled && canPrompt) {
129
+ const shouldEnable = await dependencies.confirmRelay();
130
+ if (!shouldEnable) {
131
+ dependencies.printDirectGuidance();
132
+ dependencies.output.writeStderr(`${chalk.yellow("No pairing QR was created.")}\n`);
133
+ dependencies.output.setExitCode(1);
134
+ return;
135
+ }
136
+ pairing = await dependencies.resolveOffer({ paseoHome, enableRelay: true });
137
+ dependencies.output.success("Relay enabled");
138
+ }
139
+ outputPairingResult(pairing, options, dependencies.output);
140
+ }
141
+ function outputPairingResult(pairing, options, output) {
142
+ if (!pairing.relayEnabled || !pairing.url) {
143
+ if (options.json) {
144
+ output.writeStderr(`${JSON.stringify({
145
+ code: "RELAY_DISABLED",
146
+ message: "Relay pairing is disabled for this daemon.",
147
+ action: "Run paseo daemon pair --relay --json to enable it explicitly.",
148
+ })}\n`);
149
+ }
150
+ else {
151
+ output.writeStderr(`${chalk.red("Relay pairing is disabled for this daemon.")}\n`);
152
+ output.writeStderr(`${chalk.yellow("Run paseo daemon pair --relay to enable it.")}\n`);
153
+ }
154
+ output.setExitCode(1);
155
+ return;
156
+ }
157
+ if (options.json) {
158
+ output.writeStdout(`${JSON.stringify({ relayEnabled: pairing.relayEnabled, url: pairing.url, qr: pairing.qr }, null, 2)}\n`);
159
+ return;
160
+ }
161
+ output.writeStdout(formatPairingInstructions({
162
+ url: pairing.url,
163
+ qr: pairing.qr,
164
+ columns: output.columns,
165
+ }));
166
+ }
167
+ //# sourceMappingURL=pair.js.map
@@ -0,0 +1,10 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandOptions, OutputSchema, SingleResult } from "../../output/index.js";
3
+ export interface DaemonReloadResult {
4
+ appliedPaths: string[];
5
+ restartRequiredPaths: string[];
6
+ overrideControlledPaths: string[];
7
+ }
8
+ export declare const daemonReloadSchema: OutputSchema<DaemonReloadResult>;
9
+ export declare function runDaemonReloadCommand(options: CommandOptions, _command: Command): Promise<SingleResult<DaemonReloadResult>>;
10
+ //# sourceMappingURL=reload.d.ts.map
@@ -0,0 +1,36 @@
1
+ import { connectToDaemon } from "../../utils/client.js";
2
+ export const daemonReloadSchema = {
3
+ idField: () => "daemon-config",
4
+ columns: [],
5
+ renderHuman(result) {
6
+ if (result.type !== "single")
7
+ return "";
8
+ const lines = ["Configuration reloaded."];
9
+ if (result.data.restartRequiredPaths.length > 0) {
10
+ lines.push("", "Warning: These changes require a daemon restart:", ...result.data.restartRequiredPaths.map((path) => ` ${path}`), "", "Run: paseo daemon restart");
11
+ }
12
+ if (result.data.overrideControlledPaths.length > 0) {
13
+ lines.push("", "Warning: These settings are controlled by daemon launch overrides:", ...result.data.overrideControlledPaths.map((path) => ` ${path}`));
14
+ }
15
+ return lines.join("\n");
16
+ },
17
+ };
18
+ export async function runDaemonReloadCommand(options, _command) {
19
+ const client = await connectToDaemon({ host: options.host });
20
+ try {
21
+ const payload = await client.reloadDaemonConfig();
22
+ return {
23
+ type: "single",
24
+ data: {
25
+ appliedPaths: payload.appliedPaths,
26
+ restartRequiredPaths: payload.restartRequiredPaths,
27
+ overrideControlledPaths: payload.overrideControlledPaths,
28
+ },
29
+ schema: daemonReloadSchema,
30
+ };
31
+ }
32
+ finally {
33
+ await client.close();
34
+ }
35
+ }
36
+ //# sourceMappingURL=reload.js.map
@@ -0,0 +1,12 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandOptions, SingleResult } from "../../output/index.js";
3
+ interface RestartResult {
4
+ action: "restarted";
5
+ home: string;
6
+ pid: string;
7
+ message: string;
8
+ }
9
+ export type RestartCommandResult = SingleResult<RestartResult>;
10
+ export declare function runRestartCommand(options: CommandOptions, _command: Command): Promise<RestartCommandResult>;
11
+ export {};
12
+ //# sourceMappingURL=restart.d.ts.map
@@ -0,0 +1,99 @@
1
+ import { startLocalDaemonDetached, stopLocalDaemon, DEFAULT_STOP_TIMEOUT_MS, } from "./local-daemon.js";
2
+ const restartResultSchema = {
3
+ idField: "action",
4
+ columns: [
5
+ {
6
+ header: "STATUS",
7
+ field: "action",
8
+ color: () => "green",
9
+ },
10
+ { header: "HOME", field: "home" },
11
+ { header: "PID", field: "pid" },
12
+ { header: "MESSAGE", field: "message" },
13
+ ],
14
+ };
15
+ function parseTimeoutMs(raw) {
16
+ if (typeof raw !== "string" || raw.trim().length === 0) {
17
+ return DEFAULT_STOP_TIMEOUT_MS;
18
+ }
19
+ const seconds = Number(raw);
20
+ if (!Number.isFinite(seconds) || seconds <= 0) {
21
+ const error = {
22
+ code: "INVALID_TIMEOUT",
23
+ message: `Invalid timeout value: ${raw}`,
24
+ details: "Timeout must be a positive number of seconds",
25
+ };
26
+ throw error;
27
+ }
28
+ return Math.ceil(seconds * 1000);
29
+ }
30
+ function toStartOptions(options) {
31
+ const startOptions = {
32
+ home: typeof options.home === "string" ? options.home : undefined,
33
+ listen: typeof options.listen === "string" ? options.listen : undefined,
34
+ port: typeof options.port === "string" ? options.port : undefined,
35
+ relay: typeof options.relay === "boolean" ? options.relay : undefined,
36
+ mcp: typeof options.mcp === "boolean" ? options.mcp : undefined,
37
+ injectMcp: typeof options.injectMcp === "boolean" ? options.injectMcp : undefined,
38
+ webUi: typeof options.webUi === "boolean" ? options.webUi : undefined,
39
+ hostnames: typeof options.hostnames === "string" ? options.hostnames : undefined,
40
+ };
41
+ if (startOptions.listen && startOptions.port) {
42
+ const error = {
43
+ code: "INVALID_OPTIONS",
44
+ message: "Cannot use --listen and --port together",
45
+ };
46
+ throw error;
47
+ }
48
+ return startOptions;
49
+ }
50
+ export async function runRestartCommand(options, _command) {
51
+ const timeoutMs = parseTimeoutMs(options.timeout);
52
+ const force = options.force === true;
53
+ const startOptions = toStartOptions(options);
54
+ try {
55
+ let stopResult;
56
+ try {
57
+ stopResult = await stopLocalDaemon({
58
+ home: startOptions.home,
59
+ timeoutMs,
60
+ force,
61
+ });
62
+ }
63
+ catch (err) {
64
+ const isTimeout = err instanceof Error && err.message.includes("Timed out waiting for daemon PID");
65
+ if (!force && isTimeout) {
66
+ stopResult = await stopLocalDaemon({
67
+ home: startOptions.home,
68
+ timeoutMs,
69
+ force: true,
70
+ });
71
+ }
72
+ else {
73
+ throw err;
74
+ }
75
+ }
76
+ const startup = await startLocalDaemonDetached(startOptions);
77
+ const before = stopResult.pid === null ? "not running" : `PID ${stopResult.pid}`;
78
+ const after = startup.pid === null ? "unknown PID" : `PID ${startup.pid}`;
79
+ return {
80
+ type: "single",
81
+ data: {
82
+ action: "restarted",
83
+ home: stopResult.home,
84
+ pid: startup.pid === null ? "-" : String(startup.pid),
85
+ message: `Local daemon restarted (${before} -> ${after})`,
86
+ },
87
+ schema: restartResultSchema,
88
+ };
89
+ }
90
+ catch (err) {
91
+ const message = err instanceof Error ? err.message : String(err);
92
+ const error = {
93
+ code: "RESTART_FAILED",
94
+ message: `Failed to restart local daemon: ${message}`,
95
+ };
96
+ throw error;
97
+ }
98
+ }
99
+ //# sourceMappingURL=restart.js.map
@@ -0,0 +1,6 @@
1
+ export interface NodePathFromPidResult {
2
+ nodePath: string | null;
3
+ error?: string;
4
+ }
5
+ export declare function resolveNodePathFromPid(pid: number): Promise<NodePathFromPidResult>;
6
+ //# sourceMappingURL=runtime-toolchain.d.ts.map
@@ -0,0 +1,87 @@
1
+ import { platform } from "node:os";
2
+ import { execCommand } from "@camerontaylor/paseo-server";
3
+ function normalizeError(error) {
4
+ if (error instanceof Error) {
5
+ return error.message;
6
+ }
7
+ return String(error);
8
+ }
9
+ async function resolveNodePathFromPidUnix(pid) {
10
+ try {
11
+ const { stdout } = await execCommand("ps", ["-o", "comm=", "-p", String(pid)]);
12
+ const resolved = stdout.trim();
13
+ return resolved
14
+ ? { nodePath: resolved }
15
+ : { nodePath: null, error: "ps returned an empty command path" };
16
+ }
17
+ catch (error) {
18
+ return { nodePath: null, error: `ps failed: ${normalizeError(error)}` };
19
+ }
20
+ }
21
+ async function runProcessProbe(command, args, options) {
22
+ try {
23
+ const { stdout } = await execCommand(command, args, { shell: options?.shell });
24
+ const resolved = stdout.trim();
25
+ return resolved
26
+ ? { resolved }
27
+ : { resolved: null, error: `${command} returned no executable path` };
28
+ }
29
+ catch (error) {
30
+ return { resolved: null, error: `${command} failed: ${normalizeError(error)}` };
31
+ }
32
+ }
33
+ async function resolveNodePathFromPidWindows(pid) {
34
+ const probes = [
35
+ {
36
+ label: "powershell-cim",
37
+ command: "powershell.exe",
38
+ args: [
39
+ "-NoProfile",
40
+ "-Command",
41
+ `(Get-CimInstance Win32_Process -Filter "ProcessId = ${pid}").ExecutablePath`,
42
+ ],
43
+ },
44
+ {
45
+ label: "powershell-process",
46
+ command: "powershell.exe",
47
+ args: ["-NoProfile", "-Command", `(Get-Process -Id ${pid}).Path`],
48
+ },
49
+ {
50
+ label: "wmic",
51
+ command: "wmic",
52
+ args: ["process", "where", `ProcessId=${pid}`, "get", "ExecutablePath", "/VALUE"],
53
+ parseValue: (stdout) => {
54
+ const match = stdout.match(/ExecutablePath=(.+)/);
55
+ return match?.[1]?.trim() ?? null;
56
+ },
57
+ },
58
+ ];
59
+ const errors = [];
60
+ async function tryProbe(index) {
61
+ if (index >= probes.length) {
62
+ return {
63
+ nodePath: null,
64
+ error: errors.join("; ") || "could not resolve executable path from PID",
65
+ };
66
+ }
67
+ const probe = probes[index];
68
+ const result = await runProcessProbe(probe.command, probe.args, { shell: false });
69
+ if (result.resolved) {
70
+ const resolved = probe.parseValue ? probe.parseValue(result.resolved) : result.resolved;
71
+ if (resolved)
72
+ return { nodePath: resolved };
73
+ errors.push(`${probe.label} returned no executable path`);
74
+ }
75
+ else if (result.error) {
76
+ errors.push(`${probe.label}: ${result.error}`);
77
+ }
78
+ return tryProbe(index + 1);
79
+ }
80
+ return tryProbe(0);
81
+ }
82
+ export async function resolveNodePathFromPid(pid) {
83
+ return platform() === "win32"
84
+ ? await resolveNodePathFromPidWindows(pid)
85
+ : await resolveNodePathFromPidUnix(pid);
86
+ }
87
+ //# sourceMappingURL=runtime-toolchain.js.map
@@ -0,0 +1,17 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandOptions, SingleResult } from "../../output/index.js";
3
+ interface SetPasswordResult {
4
+ action: "password_set";
5
+ configPath: string;
6
+ restartCommand: string;
7
+ message: string;
8
+ }
9
+ export type PromptPassword = (message: string) => Promise<string | symbol>;
10
+ export interface SetPasswordOptions {
11
+ home?: string;
12
+ promptPassword?: PromptPassword;
13
+ }
14
+ export declare function setDaemonPasswordInConfig(newPassword: string, options?: SetPasswordOptions): Promise<SetPasswordResult>;
15
+ export declare function runSetPasswordCommand(options: CommandOptions, _command: Command): Promise<SingleResult<SetPasswordResult>>;
16
+ export {};
17
+ //# sourceMappingURL=set-password.d.ts.map
@@ -0,0 +1,82 @@
1
+ import path from "node:path";
2
+ import { isCancel, password as passwordPrompt } from "@clack/prompts";
3
+ import { hashDaemonPassword, loadPersistedConfig, savePersistedConfig, } from "@camerontaylor/paseo-server";
4
+ import { resolveLocalPaseoHome } from "./local-daemon.js";
5
+ const CONFIG_FILENAME = "config.json";
6
+ const setPasswordResultSchema = {
7
+ idField: "action",
8
+ columns: [
9
+ { header: "STATUS", field: "action", color: () => "green" },
10
+ { header: "CONFIG", field: "configPath" },
11
+ { header: "RESTART", field: "restartCommand" },
12
+ ],
13
+ renderHuman: (result, options) => {
14
+ const data = result.data;
15
+ const rows = [
16
+ `Password written to ${data.configPath}`,
17
+ "Restart the daemon for the change to take effect.",
18
+ `Run: ${data.restartCommand}`,
19
+ ];
20
+ if (options.format === "table") {
21
+ return rows.join("\n");
22
+ }
23
+ return data.message;
24
+ },
25
+ };
26
+ function createCommandError(code, message, details) {
27
+ return { code, message, ...(details ? { details } : {}) };
28
+ }
29
+ async function promptForPassword(promptPassword) {
30
+ const first = await promptPassword("New daemon password");
31
+ if (isCancel(first)) {
32
+ throw createCommandError("PASSWORD_CANCELLED", "Password update cancelled");
33
+ }
34
+ if (typeof first !== "string" || first.length === 0) {
35
+ throw createCommandError("PASSWORD_REQUIRED", "Password cannot be empty");
36
+ }
37
+ const second = await promptPassword("Confirm daemon password");
38
+ if (isCancel(second)) {
39
+ throw createCommandError("PASSWORD_CANCELLED", "Password update cancelled");
40
+ }
41
+ if (first !== second) {
42
+ throw createCommandError("PASSWORD_MISMATCH", "Passwords do not match");
43
+ }
44
+ return first;
45
+ }
46
+ export async function setDaemonPasswordInConfig(newPassword, options = {}) {
47
+ const paseoHome = resolveLocalPaseoHome(options.home);
48
+ const configPath = path.join(paseoHome, CONFIG_FILENAME);
49
+ const persisted = loadPersistedConfig(paseoHome);
50
+ const nextConfig = {
51
+ ...persisted,
52
+ daemon: {
53
+ ...persisted.daemon,
54
+ auth: {
55
+ ...persisted.daemon?.auth,
56
+ password: hashDaemonPassword(newPassword),
57
+ },
58
+ },
59
+ };
60
+ savePersistedConfig(paseoHome, nextConfig);
61
+ return {
62
+ action: "password_set",
63
+ configPath,
64
+ restartCommand: "paseo daemon restart",
65
+ message: `Password written to ${configPath}\nRestart the daemon for the change to take effect.\nRun: paseo daemon restart`,
66
+ };
67
+ }
68
+ export async function runSetPasswordCommand(options, _command) {
69
+ const promptPassword = typeof options.promptPassword === "function"
70
+ ? options.promptPassword
71
+ : (message) => passwordPrompt({ message });
72
+ const newPassword = await promptForPassword(promptPassword);
73
+ const result = await setDaemonPasswordInConfig(newPassword, {
74
+ home: typeof options.home === "string" ? options.home : undefined,
75
+ });
76
+ return {
77
+ type: "single",
78
+ data: result,
79
+ schema: setPasswordResultSchema,
80
+ };
81
+ }
82
+ //# sourceMappingURL=set-password.js.map
@@ -0,0 +1,6 @@
1
+ import { Command } from "commander";
2
+ import { type DaemonStartOptions as StartOptions } from "./local-daemon.js";
3
+ export type { DaemonStartOptions as StartOptions } from "./local-daemon.js";
4
+ export declare function startCommand(): Command;
5
+ export declare function runStart(options: StartOptions): Promise<void>;
6
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1,57 @@
1
+ import { Command, Option } from "commander";
2
+ import chalk from "chalk";
3
+ import { startLocalDaemonForeground, startLocalDaemonDetached, } from "./local-daemon.js";
4
+ import { getErrorMessage } from "../../utils/errors.js";
5
+ export function startCommand() {
6
+ return new Command("start")
7
+ .description("Start the local Paseo daemon")
8
+ .option("--listen <listen>", "Listen target (host:port, port, or unix socket path)")
9
+ .option("--port <port>", "Port to listen on (default: 6767)")
10
+ .option("--home <path>", "Paseo home directory (default: ~/.paseo)")
11
+ .option("--foreground", "Run in foreground (don't daemonize)")
12
+ .option("--relay", "Enable relay connection")
13
+ .option("--no-relay", "Disable relay connection")
14
+ .option("--relay-use-tls", "Use wss:// for the relay connection and pairing offers")
15
+ .option("--no-mcp", "Disable the Agent MCP HTTP endpoint")
16
+ .option("--no-inject-mcp", "Disable auto-injecting the Paseo MCP into created agents")
17
+ .option("--web-ui", "Enable the bundled daemon web UI")
18
+ .option("--no-web-ui", "Disable the bundled daemon web UI")
19
+ .option("--hostnames <hosts>", 'Daemon hostnames (comma-separated, e.g. "myhost,.example.com" or "true" for any)')
20
+ .addOption(new Option("--allowed-hosts <hosts>").hideHelp())
21
+ .action(async (options) => {
22
+ await runStart({
23
+ ...options,
24
+ hostnames: options.hostnames ?? options.allowedHosts,
25
+ });
26
+ });
27
+ }
28
+ export async function runStart(options) {
29
+ if (options.listen && options.port) {
30
+ console.error(chalk.red("Cannot use --listen and --port together"));
31
+ process.exit(1);
32
+ }
33
+ if (!options.foreground) {
34
+ try {
35
+ const startup = await startLocalDaemonDetached(options);
36
+ console.log(chalk.green(`Daemon starting in background (PID ${startup.pid ?? "unknown"}).`));
37
+ console.log(chalk.dim(`Logs: ${startup.logPath}`));
38
+ }
39
+ catch (err) {
40
+ exitWithError(getErrorMessage(err));
41
+ }
42
+ return;
43
+ }
44
+ try {
45
+ const status = startLocalDaemonForeground(options);
46
+ process.exit(status);
47
+ }
48
+ catch (err) {
49
+ const message = getErrorMessage(err);
50
+ exitWithError(`Failed to start daemon: ${message}`);
51
+ }
52
+ }
53
+ function exitWithError(message) {
54
+ console.error(chalk.red(message));
55
+ process.exit(1);
56
+ }
57
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1,21 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandOptions, ListResult } from "../../output/index.js";
3
+ interface StatusRow {
4
+ key: string;
5
+ value: string;
6
+ }
7
+ interface RelayStatusConfig {
8
+ enabled: boolean;
9
+ endpoint: string;
10
+ publicEndpoint: string;
11
+ useTls: boolean;
12
+ publicUseTls: boolean;
13
+ }
14
+ export declare function selectRelayStatus(input: {
15
+ persisted: RelayStatusConfig;
16
+ live?: RelayStatusConfig;
17
+ }): string;
18
+ export type StatusResult = ListResult<StatusRow>;
19
+ export declare function runStatusCommand(options: CommandOptions, _command: Command): Promise<StatusResult>;
20
+ export {};
21
+ //# sourceMappingURL=status.d.ts.map