@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,105 @@
1
+ import { connectToDaemon, getDaemonHost } from "../../utils/client.js";
2
+ import { permitResponseSchema } from "./allow.js";
3
+ export async function runDenyCommand(agentIdOrPrefix, reqId, options, _command) {
4
+ const host = getDaemonHost({ host: options.host });
5
+ // Validate arguments
6
+ if (!options.all && !reqId) {
7
+ const error = {
8
+ code: "MISSING_ARGUMENT",
9
+ message: "Request ID is required unless --all is specified",
10
+ details: "Usage: paseo permit deny <agent> <req_id> or paseo permit deny <agent> --all",
11
+ };
12
+ throw error;
13
+ }
14
+ let client;
15
+ try {
16
+ client = await connectToDaemon({ host: options.host });
17
+ }
18
+ catch (err) {
19
+ const message = err instanceof Error ? err.message : String(err);
20
+ const error = {
21
+ code: "DAEMON_NOT_RUNNING",
22
+ message: `Cannot connect to daemon at ${host}: ${message}`,
23
+ details: "Start the daemon with: paseo daemon start",
24
+ };
25
+ throw error;
26
+ }
27
+ try {
28
+ const fetchResult = await client.fetchAgent({ agentId: agentIdOrPrefix });
29
+ if (!fetchResult) {
30
+ await client.close();
31
+ const error = {
32
+ code: "AGENT_NOT_FOUND",
33
+ message: `Agent not found: ${agentIdOrPrefix}`,
34
+ details: 'Use "paseo ls" to list available agents',
35
+ };
36
+ throw error;
37
+ }
38
+ const agent = fetchResult.agent;
39
+ const resolvedAgentId = agent.id;
40
+ // Get pending permissions for this agent
41
+ const pendingPermissions = agent.pendingPermissions || [];
42
+ if (pendingPermissions.length === 0) {
43
+ await client.close();
44
+ const error = {
45
+ code: "NO_PENDING_PERMISSIONS",
46
+ message: `No pending permissions for agent ${agent.id.slice(0, 7)}`,
47
+ };
48
+ throw error;
49
+ }
50
+ // Determine which permissions to deny
51
+ let permissionsToDeny;
52
+ if (options.all) {
53
+ permissionsToDeny = pendingPermissions;
54
+ }
55
+ else {
56
+ // Find permission by ID prefix
57
+ const permission = pendingPermissions.find((p) => p.id === reqId || p.id.startsWith(reqId));
58
+ if (!permission) {
59
+ await client.close();
60
+ const error = {
61
+ code: "PERMISSION_NOT_FOUND",
62
+ message: `Permission request not found: ${reqId}`,
63
+ details: `Available requests: ${pendingPermissions.map((p) => p.id.slice(0, 8)).join(", ")}`,
64
+ };
65
+ throw error;
66
+ }
67
+ permissionsToDeny = [permission];
68
+ }
69
+ // Deny permissions
70
+ const results = await Promise.all(permissionsToDeny.map(async (permission) => {
71
+ await client.respondToPermission(resolvedAgentId, permission.id, {
72
+ behavior: "deny",
73
+ ...(options.message ? { message: options.message } : {}),
74
+ ...(options.interrupt ? { interrupt: true } : {}),
75
+ });
76
+ return {
77
+ requestId: permission.id.slice(0, 8),
78
+ agentId: resolvedAgentId,
79
+ agentShortId: resolvedAgentId.slice(0, 7),
80
+ name: permission.name,
81
+ result: "denied",
82
+ };
83
+ }));
84
+ await client.close();
85
+ return {
86
+ type: "list",
87
+ data: results,
88
+ schema: permitResponseSchema,
89
+ };
90
+ }
91
+ catch (err) {
92
+ await client.close().catch(() => { });
93
+ // Re-throw CommandErrors
94
+ if (err && typeof err === "object" && "code" in err) {
95
+ throw err;
96
+ }
97
+ const message = err instanceof Error ? err.message : String(err);
98
+ const error = {
99
+ code: "DENY_PERMISSION_FAILED",
100
+ message: `Failed to deny permission: ${message}`,
101
+ };
102
+ throw error;
103
+ }
104
+ }
105
+ //# sourceMappingURL=deny.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createPermitCommand(): Command;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,27 @@
1
+ import { Command } from "commander";
2
+ import { runLsCommand } from "./ls.js";
3
+ import { runAllowCommand } from "./allow.js";
4
+ import { runDenyCommand } from "./deny.js";
5
+ import { withOutput } from "../../output/index.js";
6
+ import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
7
+ export function createPermitCommand() {
8
+ const permit = new Command("permit").description("Manage permission requests");
9
+ addJsonAndDaemonHostOptions(permit.command("ls").description("List all pending permissions")).action(withOutput(runLsCommand));
10
+ addJsonAndDaemonHostOptions(permit
11
+ .command("allow")
12
+ .description("Allow a permission request")
13
+ .argument("<agent>", "Agent ID (or prefix)")
14
+ .argument("[req_id]", "Permission request ID (optional if --all)")
15
+ .option("--all", "Allow all pending permissions for this agent")
16
+ .option("--input <json>", "Modified input parameters (JSON)")).action(withOutput(runAllowCommand));
17
+ addJsonAndDaemonHostOptions(permit
18
+ .command("deny")
19
+ .description("Deny a permission request")
20
+ .argument("<agent>", "Agent ID (or prefix)")
21
+ .argument("[req_id]", "Permission request ID (optional if --all)")
22
+ .option("--all", "Deny all pending permissions for this agent")
23
+ .option("--message <msg>", "Denial reason message")
24
+ .option("--interrupt", "Stop agent after denial")).action(withOutput(runDenyCommand));
25
+ return permit;
26
+ }
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,18 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandOptions, ListResult, OutputSchema } from "../../output/index.js";
3
+ /** Permission list item for display */
4
+ export interface PermissionListItem {
5
+ id: string;
6
+ agentId: string;
7
+ agentShortId: string;
8
+ name: string;
9
+ description: string;
10
+ }
11
+ /** Schema for permit ls output */
12
+ export declare const permitLsSchema: OutputSchema<PermissionListItem>;
13
+ export type PermitLsResult = ListResult<PermissionListItem>;
14
+ export interface PermitLsOptions extends CommandOptions {
15
+ host?: string;
16
+ }
17
+ export declare function runLsCommand(options: PermitLsOptions, _command: Command): Promise<PermitLsResult>;
18
+ //# sourceMappingURL=ls.d.ts.map
@@ -0,0 +1,66 @@
1
+ import { connectToDaemon, getDaemonHost } from "../../utils/client.js";
2
+ /** Schema for permit ls output */
3
+ export const permitLsSchema = {
4
+ idField: "id",
5
+ columns: [
6
+ { header: "AGENT", field: "agentShortId", width: 12 },
7
+ { header: "REQ_ID", field: "id", width: 12 },
8
+ { header: "TOOL", field: "name", width: 20 },
9
+ { header: "DESCRIPTION", field: "description", width: 50 },
10
+ ],
11
+ };
12
+ /** Transform agent snapshot + permission to list item */
13
+ function toListItem(agent, permission) {
14
+ return {
15
+ id: permission.id.slice(0, 8),
16
+ agentId: agent.id,
17
+ agentShortId: agent.id.slice(0, 7),
18
+ name: permission.name,
19
+ description: permission.description ?? "-",
20
+ };
21
+ }
22
+ export async function runLsCommand(options, _command) {
23
+ const host = getDaemonHost({ host: options.host });
24
+ let client;
25
+ try {
26
+ client = await connectToDaemon({ host: options.host });
27
+ }
28
+ catch (err) {
29
+ const message = err instanceof Error ? err.message : String(err);
30
+ const error = {
31
+ code: "DAEMON_NOT_RUNNING",
32
+ message: `Cannot connect to daemon at ${host}: ${message}`,
33
+ details: "Start the daemon with: paseo daemon start",
34
+ };
35
+ throw error;
36
+ }
37
+ try {
38
+ const agentsPayload = await client.fetchAgents({ filter: { includeArchived: true } });
39
+ const agents = agentsPayload.entries.map((entry) => entry.agent);
40
+ await client.close();
41
+ // Collect all pending permissions from all agents
42
+ const items = [];
43
+ for (const agent of agents) {
44
+ if (agent.pendingPermissions && agent.pendingPermissions.length > 0) {
45
+ for (const permission of agent.pendingPermissions) {
46
+ items.push(toListItem(agent, permission));
47
+ }
48
+ }
49
+ }
50
+ return {
51
+ type: "list",
52
+ data: items,
53
+ schema: permitLsSchema,
54
+ };
55
+ }
56
+ catch (err) {
57
+ await client.close().catch(() => { });
58
+ const message = err instanceof Error ? err.message : String(err);
59
+ const error = {
60
+ code: "LIST_PERMISSIONS_FAILED",
61
+ message: `Failed to list permissions: ${message}`,
62
+ };
63
+ throw error;
64
+ }
65
+ }
66
+ //# sourceMappingURL=ls.js.map
@@ -0,0 +1,17 @@
1
+ import { Command } from "commander";
2
+ import type { PluginListItem, PluginLogEntry } from "@camerontaylor/paseo-protocol/messages";
3
+ import type { CommandOptions, ListResult, SingleResult } from "../../output/index.js";
4
+ import { type PluginScaffold } from "./scaffold.js";
5
+ interface PluginOptions extends CommandOptions {
6
+ host?: string;
7
+ id?: string;
8
+ ref?: string;
9
+ path?: string;
10
+ all?: boolean;
11
+ }
12
+ export declare function runPluginInitCommand(directory: string, options: PluginOptions, _command: Command): Promise<SingleResult<PluginScaffold>>;
13
+ export declare function runPluginListCommand(pluginId: string | undefined, options: PluginOptions, _command: Command): Promise<ListResult<PluginListItem>>;
14
+ export declare function runPluginLogsCommand(pluginId: string, options: PluginOptions, _command: Command): Promise<ListResult<PluginLogEntry>>;
15
+ export declare function createPluginCommand(): Command;
16
+ export {};
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,138 @@
1
+ import { Command } from "commander";
2
+ import path from "node:path";
3
+ import { formatPluginSourceReference, parsePluginSourceReference, } from "@camerontaylor/paseo-protocol/plugin-source-reference";
4
+ import { withOutput } from "../../output/index.js";
5
+ import { addJsonAndDaemonHostOptions, addJsonOption } from "../../utils/command-options.js";
6
+ import { scaffoldPluginDirectory } from "./scaffold.js";
7
+ import { withPluginLogsClient, withPluginManagementClient, withPluginSourceClient, } from "./shared.js";
8
+ const pluginSchema = {
9
+ idField: "id",
10
+ columns: [
11
+ { header: "PLUGIN", field: "id", width: 20 },
12
+ { header: "STATUS", field: "status", width: 10 },
13
+ { header: "ENABLED", field: (plugin) => (plugin.enabled ? "yes" : "no"), width: 8 },
14
+ { header: "SOURCE", field: (plugin) => plugin.source ?? "directory", width: 10 },
15
+ { header: "COMMIT", field: (plugin) => shortCommit(plugin.commit), width: 14 },
16
+ { header: "REF", field: (plugin) => plugin.ref ?? "-", width: 24 },
17
+ { header: "DIRECTORY", field: "path", width: 40 },
18
+ { header: "ERROR", field: (plugin) => plugin.error ?? "", width: 40 },
19
+ ],
20
+ };
21
+ const scaffoldSchema = {
22
+ idField: "id",
23
+ columns: [
24
+ { header: "PLUGIN", field: "id", width: 20 },
25
+ { header: "DIRECTORY", field: "directory", width: 60 },
26
+ ],
27
+ };
28
+ const pluginLogsSchema = {
29
+ idField: (entry) => String(entry.sequence),
30
+ columns: [
31
+ { header: "TIME", field: "timestamp", width: 24 },
32
+ { header: "STREAM", field: "stream", width: 8 },
33
+ { header: "MESSAGE", field: "message", width: 80 },
34
+ ],
35
+ };
36
+ function shortCommit(commit) {
37
+ return commit?.slice(0, 12) ?? "-";
38
+ }
39
+ const pluginUpdateSchema = {
40
+ idField: "id",
41
+ columns: [
42
+ { header: "PLUGIN", field: "id", width: 20 },
43
+ { header: "PREVIOUS", field: (plugin) => shortCommit(plugin.previousCommit), width: 14 },
44
+ { header: "CURRENT", field: (plugin) => shortCommit(plugin.currentCommit), width: 14 },
45
+ { header: "COMMITS", field: (plugin) => String(plugin.commits), width: 8 },
46
+ { header: "UPDATED", field: (plugin) => (plugin.updated ? "yes" : "no"), width: 8 },
47
+ ],
48
+ };
49
+ export async function runPluginInitCommand(directory, options, _command) {
50
+ return {
51
+ type: "single",
52
+ data: await scaffoldPluginDirectory(directory, options.id),
53
+ schema: scaffoldSchema,
54
+ };
55
+ }
56
+ export async function runPluginListCommand(pluginId, options, _command) {
57
+ const plugins = await withPluginManagementClient(options.host, (client) => client.listPlugins());
58
+ const data = pluginId ? plugins.filter((plugin) => plugin.id === pluginId) : plugins;
59
+ if (pluginId && data.length === 0)
60
+ throw new Error(`Plugin is not configured: ${pluginId}`);
61
+ return { type: "list", data, schema: pluginSchema };
62
+ }
63
+ export async function runPluginLogsCommand(pluginId, options, _command) {
64
+ const data = await withPluginLogsClient(options.host, (client) => client.getPluginLogs(pluginId));
65
+ return { type: "list", data, schema: pluginLogsSchema };
66
+ }
67
+ async function install(source, options, _command) {
68
+ process.stderr.write("Trusting plugin code: server code and Git build commands run unsandboxed on the daemon host; client code runs inside Paseo. Dependencies and future updates are part of the codebase you trust.\n");
69
+ const isExplicitPath = path.isAbsolute(source) ||
70
+ source === "." ||
71
+ source === ".." ||
72
+ source.startsWith("./") ||
73
+ source.startsWith("../") ||
74
+ source.startsWith(".\\") ||
75
+ source.startsWith("..\\");
76
+ const hasPluginPathSuffix = parsePluginSourceReference(source).pluginPath !== undefined;
77
+ const canUseLegacyDirectoryInstall = isExplicitPath && !hasPluginPathSuffix && !options.ref && !options.path;
78
+ const sourceReference = formatPluginSourceReference(source, options.path);
79
+ const data = canUseLegacyDirectoryInstall
80
+ ? await withPluginManagementClient(options.host, (client) => client.installDirectoryPlugin(source, options.id))
81
+ : await withPluginSourceClient(options.host, (client) => client.installPluginSource({
82
+ source: sourceReference,
83
+ ...(options.id ? { id: options.id } : {}),
84
+ ...(options.ref ? { ref: options.ref } : {}),
85
+ }));
86
+ return { type: "single", data, schema: pluginSchema };
87
+ }
88
+ async function update(pluginId, options, _command) {
89
+ if ((pluginId === undefined) === (options.all !== true)) {
90
+ throw new Error("Choose one plugin ID or pass --all");
91
+ }
92
+ const data = await withPluginSourceClient(options.host, (client) => client.updatePluginSources(pluginId));
93
+ return { type: "list", data, schema: pluginUpdateSchema };
94
+ }
95
+ async function act(action, pluginId, options) {
96
+ const data = await withPluginManagementClient(options.host, (client) => client[`${action}Plugin`](pluginId));
97
+ return { type: "single", data, schema: pluginSchema };
98
+ }
99
+ async function remove(pluginId, options, _command) {
100
+ const data = await withPluginManagementClient(options.host, async (client) => {
101
+ const current = (await client.listPlugins()).find((plugin) => plugin.id === pluginId);
102
+ if (!current)
103
+ throw new Error(`Plugin is not configured: ${pluginId}`);
104
+ await client.removePlugin(pluginId);
105
+ return { ...current, enabled: false, status: "disabled" };
106
+ });
107
+ return { type: "single", data, schema: pluginSchema };
108
+ }
109
+ export function createPluginCommand() {
110
+ const plugin = new Command("plugin").description("Manage trusted, unsandboxed plugins");
111
+ addJsonOption(plugin
112
+ .command("init")
113
+ .description("Create a typecheckable local plugin")
114
+ .argument("<directory>")
115
+ .option("--id <id>", "Manifest plugin ID (defaults to the directory name)")).action(withOutput(runPluginInitCommand));
116
+ addJsonAndDaemonHostOptions(plugin.command("ls").description("List configured plugins").argument("[id]")).action(withOutput(runPluginListCommand));
117
+ addJsonAndDaemonHostOptions(plugin.command("status", { hidden: true }).argument("[id]")).action(withOutput(runPluginListCommand));
118
+ addJsonAndDaemonHostOptions(plugin.command("logs").description("Show recent plugin output").argument("<id>")).action(withOutput(runPluginLogsCommand));
119
+ addJsonAndDaemonHostOptions(plugin
120
+ .command("install")
121
+ .alias("add")
122
+ .description("Trust and install a plugin from a directory or Git repository")
123
+ .argument("<source>", "Host directory, Git source, or Git source:plugin/path")
124
+ .option("--id <id>", "Runtime plugin ID (defaults to paseo-plugin.json id)")
125
+ .option("--ref <ref>", "Git branch, tag, or commit")
126
+ .option("--path <path>", "Legacy form of the :plugin/path source suffix")).action(withOutput(install));
127
+ addJsonAndDaemonHostOptions(plugin
128
+ .command("update")
129
+ .description("Fetch and install Git-managed plugin updates")
130
+ .argument("[id]")
131
+ .option("--all", "Update every Git-managed plugin")).action(withOutput(update));
132
+ for (const action of ["reload", "enable", "disable"]) {
133
+ addJsonAndDaemonHostOptions(plugin.command(action).description(`${action} a plugin`).argument("<id>")).action(withOutput((id, options, _command) => act(action, id, options)));
134
+ }
135
+ addJsonAndDaemonHostOptions(plugin.command("remove").description("Remove plugin configuration").argument("<id>")).action(withOutput(remove));
136
+ return plugin;
137
+ }
138
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,6 @@
1
+ export interface PluginScaffold {
2
+ id: string;
3
+ directory: string;
4
+ }
5
+ export declare function scaffoldPluginDirectory(targetDirectory: string, requestedId?: string): Promise<PluginScaffold>;
6
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1,162 @@
1
+ import { mkdir, readdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { PluginIdSchema } from "@camerontaylor/paseo-protocol/messages";
4
+ import { resolveCliVersion } from "../../version.js";
5
+ const TSCONFIG = {
6
+ compilerOptions: {
7
+ target: "ES2020",
8
+ module: "ESNext",
9
+ moduleResolution: "Bundler",
10
+ lib: ["ES2023"],
11
+ types: ["react"],
12
+ jsx: "react-jsx",
13
+ strict: true,
14
+ skipLibCheck: true,
15
+ noEmit: true,
16
+ esModuleInterop: true,
17
+ allowSyntheticDefaultImports: true,
18
+ },
19
+ include: ["**/*.ts", "**/*.tsx"],
20
+ };
21
+ const CLIENT_ENTRY = `import type { PluginClientContext } from "@camerontaylor/paseo-plugin/client";
22
+ import { GreetingSurface } from "./client/greeting";
23
+
24
+ export default function contribute(client: PluginClientContext) {
25
+ client.addSurface("greeting", GreetingSurface);
26
+ client.addSidebarItem({
27
+ id: "greeting",
28
+ title: "Greeting",
29
+ icon: "MessageCircle",
30
+ surface: "greeting",
31
+ });
32
+ return () => {};
33
+ }
34
+ `;
35
+ const SERVER_ENTRY = `import type { PluginServerContext } from "@camerontaylor/paseo-plugin/server";
36
+ import { createGreeting } from "./server/greeting";
37
+ import { greetingRpc } from "./shared/greeting";
38
+
39
+ export default function contribute(server: PluginServerContext) {
40
+ server.handle(greetingRpc, createGreeting);
41
+ return () => {};
42
+ }
43
+ `;
44
+ const SHARED_GREETING = `import { defineRpc } from "@camerontaylor/paseo-plugin";
45
+ import { z } from "zod";
46
+
47
+ export const greetingRpc = defineRpc({
48
+ name: "greeting.create",
49
+ input: z.object({ name: z.string() }),
50
+ output: z.object({ message: z.string() }),
51
+ });
52
+ `;
53
+ const SERVER_GREETING = `import type { RpcInput } from "@camerontaylor/paseo-plugin";
54
+ import { greetingRpc } from "../shared/greeting";
55
+
56
+ export function createGreeting({ name }: RpcInput<typeof greetingRpc>) {
57
+ return { message: "Hello, " + name + "!" };
58
+ }
59
+ `;
60
+ const CLIENT_GREETING = `import type { PluginSurfaceProps } from "@camerontaylor/paseo-plugin/client";
61
+ import { useRpc } from "@camerontaylor/paseo-plugin/client";
62
+ import { useMutation } from "@tanstack/react-query";
63
+ import { useMemo } from "react";
64
+ import { Pressable, Text, View } from "react-native";
65
+ import { greetingRpc } from "../shared/greeting";
66
+ import { openExternal } from "./web";
67
+
68
+ export function GreetingSurface({ theme, layout }: PluginSurfaceProps) {
69
+ const createGreeting = useRpc(greetingRpc);
70
+ const greeting = useMutation({ mutationFn: createGreeting });
71
+ const styles = useMemo(
72
+ () => ({
73
+ screen: {
74
+ flex: 1,
75
+ padding: layout.compact ? 16 : 24,
76
+ backgroundColor: theme.colors.surface0,
77
+ },
78
+ text: { color: theme.colors.foreground },
79
+ button: { padding: 12, backgroundColor: theme.colors.accent },
80
+ buttonText: { color: theme.colors.accentForeground },
81
+ }),
82
+ [theme, layout.compact],
83
+ );
84
+ return (
85
+ <View style={styles.screen}>
86
+ <Text style={styles.text}>{greeting.data?.message ?? "Ask the daemon for a greeting."}</Text>
87
+ <Pressable
88
+ accessibilityRole="button"
89
+ accessibilityLabel="Create greeting"
90
+ style={styles.button}
91
+ onPress={() => greeting.mutate({ name: "Paseo" })}
92
+ >
93
+ <Text style={styles.buttonText}>Create greeting</Text>
94
+ </Pressable>
95
+ <Pressable
96
+ accessibilityRole="link"
97
+ accessibilityLabel="Open the Paseo website"
98
+ style={styles.button}
99
+ onPress={() => openExternal("https://paseo.sh")}
100
+ >
101
+ <Text style={styles.buttonText}>Open paseo.sh</Text>
102
+ </Pressable>
103
+ </View>
104
+ );
105
+ }
106
+ `;
107
+ const CLIENT_WEB = `import { Linking, Platform } from "react-native";
108
+
109
+ // This plugin typechecks without the DOM library. Declare only what this module uses.
110
+ declare const window: { open(url: string, target: string, features: string): unknown };
111
+
112
+ export async function openExternal(url: string): Promise<void> {
113
+ if (Platform.OS === "web") {
114
+ window.open(url, "_blank", "noopener,noreferrer");
115
+ return;
116
+ }
117
+ await Linking.openURL(url);
118
+ }
119
+ `;
120
+ export async function scaffoldPluginDirectory(targetDirectory, requestedId) {
121
+ const directory = path.resolve(targetDirectory);
122
+ const id = PluginIdSchema.parse(requestedId ?? path.basename(directory));
123
+ await mkdir(directory, { recursive: true });
124
+ const existing = await readdir(directory);
125
+ if (existing.length > 0) {
126
+ throw new Error(`Plugin directory must be empty: ${directory}`);
127
+ }
128
+ const version = resolveCliVersion();
129
+ const packageJson = {
130
+ name: id,
131
+ private: true,
132
+ version: "0.0.0",
133
+ scripts: { typecheck: "tsc --noEmit" },
134
+ devDependencies: {
135
+ "@camerontaylor/paseo-plugin": version,
136
+ "@tanstack/react-query": "^5.90.11",
137
+ "@types/react": "~19.2.0",
138
+ react: "19.1.0",
139
+ "react-native": "0.81.5",
140
+ typescript: "^5.9.3",
141
+ zod: "^4.4.3",
142
+ },
143
+ };
144
+ const files = new Map([
145
+ [
146
+ "paseo-plugin.json",
147
+ `${JSON.stringify({ id, requirements: { paseo: `>=${version}` } }, null, 2)}\n`,
148
+ ],
149
+ ["package.json", `${JSON.stringify(packageJson, null, 2)}\n`],
150
+ ["tsconfig.json", `${JSON.stringify(TSCONFIG, null, 2)}\n`],
151
+ ["index.client.tsx", CLIENT_ENTRY],
152
+ ["index.server.ts", SERVER_ENTRY],
153
+ ["shared/greeting.ts", SHARED_GREETING],
154
+ ["server/greeting.ts", SERVER_GREETING],
155
+ ["client/greeting.tsx", CLIENT_GREETING],
156
+ ["client/web.ts", CLIENT_WEB],
157
+ ]);
158
+ await Promise.all(["shared", "server", "client"].map((name) => mkdir(path.join(directory, name))));
159
+ await Promise.all([...files].map(([filename, contents]) => writeFile(path.join(directory, filename), contents, { flag: "wx" })));
160
+ return { id, directory };
161
+ }
162
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1,5 @@
1
+ import type { DaemonClient } from "@camerontaylor/paseo-client/internal/daemon-client";
2
+ export declare function withPluginManagementClient<T>(host: string | undefined, run: (client: DaemonClient) => Promise<T>): Promise<T>;
3
+ export declare function withPluginLogsClient<T>(host: string | undefined, run: (client: DaemonClient) => Promise<T>): Promise<T>;
4
+ export declare function withPluginSourceClient<T>(host: string | undefined, run: (client: DaemonClient) => Promise<T>): Promise<T>;
5
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1,30 @@
1
+ import { connectToDaemon } from "../../utils/client.js";
2
+ async function withPluginClient(host, feature, updateMessage, run) {
3
+ const client = await connectToDaemon({ host });
4
+ if (client.getLastServerInfoMessage()?.features?.[feature] !== true) {
5
+ await client.close().catch(() => undefined);
6
+ throw {
7
+ code: "DAEMON_UPDATE_REQUIRED",
8
+ message: updateMessage,
9
+ };
10
+ }
11
+ try {
12
+ return await run(client);
13
+ }
14
+ finally {
15
+ await client.close().catch(() => undefined);
16
+ }
17
+ }
18
+ export async function withPluginManagementClient(host, run) {
19
+ // COMPAT(pluginManagement): added in v0.3.1, remove gate after 2027-08-14.
20
+ return withPluginClient(host, "pluginManagement", "Update the host to use plugin management.", run);
21
+ }
22
+ export async function withPluginLogsClient(host, run) {
23
+ // COMPAT(pluginLogs): added in v0.4.0, remove gate after 2027-08-16.
24
+ return withPluginClient(host, "pluginLogs", "Update the host to view plugin logs.", run);
25
+ }
26
+ export async function withPluginSourceClient(host, run) {
27
+ // COMPAT(pluginGitManagement): added in v0.7.0, remove gate after 2027-08-26.
28
+ return withPluginClient(host, "pluginGitManagement", "Update the host to install and update Git plugins.", run);
29
+ }
30
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1,10 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandOptions, SingleResult } from "../../output/index.js";
3
+ import { type ProjectRow } from "./shared.js";
4
+ export declare function resolveProjectPath(input: {
5
+ pathArg?: string;
6
+ cwd: string;
7
+ daemonTarget?: string;
8
+ }): string;
9
+ export declare function runCreateCommand(pathArg: string | undefined, options: CommandOptions, _command: Command): Promise<SingleResult<ProjectRow>>;
10
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1,41 @@
1
+ import path from "node:path";
2
+ import { buildDaemonConnectionCommandError, connectToDaemon } from "../../utils/client.js";
3
+ import { projectSchema, toProjectRow } from "./shared.js";
4
+ export function resolveProjectPath(input) {
5
+ if (input.daemonTarget) {
6
+ if (input.pathArg === undefined) {
7
+ throw {
8
+ code: "MISSING_PATH",
9
+ message: "Project path is required when targeting a daemon explicitly",
10
+ details: "Usage: paseo project create <path> --host <host>",
11
+ };
12
+ }
13
+ return input.pathArg;
14
+ }
15
+ return path.resolve(input.cwd, input.pathArg ?? ".");
16
+ }
17
+ export async function runCreateCommand(pathArg, options, _command) {
18
+ const projectPath = resolveProjectPath({
19
+ pathArg,
20
+ cwd: process.cwd(),
21
+ daemonTarget: options.host ?? process.env.PASEO_HOST,
22
+ });
23
+ const client = await connectToDaemon({ host: options.host }).catch((error) => {
24
+ throw buildDaemonConnectionCommandError({ host: options.host, error });
25
+ });
26
+ try {
27
+ const payload = await client.addProject(projectPath);
28
+ if (!payload.project) {
29
+ throw new Error(payload.error ?? "Project creation failed");
30
+ }
31
+ return { type: "single", data: toProjectRow(payload.project), schema: projectSchema };
32
+ }
33
+ catch (error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ throw { code: "PROJECT_CREATE_FAILED", message };
36
+ }
37
+ finally {
38
+ await client.close().catch(() => undefined);
39
+ }
40
+ }
41
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1,9 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandOptions, SingleResult } from "../../output/index.js";
3
+ interface ProjectDeleteResult {
4
+ projectId: string;
5
+ removedWorkspaceIds: string[];
6
+ }
7
+ export declare function runDeleteCommand(projectId: string, options: CommandOptions, _command: Command): Promise<SingleResult<ProjectDeleteResult>>;
8
+ export {};
9
+ //# sourceMappingURL=delete.d.ts.map