@agentuity/cli 0.0.51 → 0.0.53

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 (299) hide show
  1. package/dist/api.js +68 -0
  2. package/dist/api.js.map +1 -0
  3. package/dist/auth.js +225 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/banner.js +35 -0
  6. package/dist/banner.js.map +1 -0
  7. package/dist/cli-logger.js +72 -0
  8. package/dist/cli-logger.js.map +1 -0
  9. package/dist/cli.js +822 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/cmd/ai/capabilities/index.js +10 -0
  12. package/dist/cmd/ai/capabilities/index.js.map +1 -0
  13. package/dist/cmd/ai/capabilities/show.js +221 -0
  14. package/dist/cmd/ai/capabilities/show.js.map +1 -0
  15. package/dist/cmd/ai/index.js +11 -0
  16. package/dist/cmd/ai/index.js.map +1 -0
  17. package/dist/cmd/ai/prompt/index.js +10 -0
  18. package/dist/cmd/ai/prompt/index.js.map +1 -0
  19. package/dist/cmd/ai/prompt/llm.js +365 -0
  20. package/dist/cmd/ai/prompt/llm.js.map +1 -0
  21. package/dist/cmd/ai/schema/index.js +10 -0
  22. package/dist/cmd/ai/schema/index.js.map +1 -0
  23. package/dist/cmd/ai/schema/show.js +23 -0
  24. package/dist/cmd/ai/schema/show.js.map +1 -0
  25. package/dist/cmd/auth/api.js +85 -0
  26. package/dist/cmd/auth/api.js.map +1 -0
  27. package/dist/cmd/auth/index.js +13 -0
  28. package/dist/cmd/auth/index.js.map +1 -0
  29. package/dist/cmd/auth/login.js +84 -0
  30. package/dist/cmd/auth/login.js.map +1 -0
  31. package/dist/cmd/auth/logout.js +17 -0
  32. package/dist/cmd/auth/logout.js.map +1 -0
  33. package/dist/cmd/auth/signup.js +55 -0
  34. package/dist/cmd/auth/signup.js.map +1 -0
  35. package/dist/cmd/auth/ssh/add.js +239 -0
  36. package/dist/cmd/auth/ssh/add.js.map +1 -0
  37. package/dist/cmd/auth/ssh/api.js +53 -0
  38. package/dist/cmd/auth/ssh/api.js.map +1 -0
  39. package/dist/cmd/auth/ssh/delete.js +126 -0
  40. package/dist/cmd/auth/ssh/delete.js.map +1 -0
  41. package/dist/cmd/auth/ssh/index.js +11 -0
  42. package/dist/cmd/auth/ssh/index.js.map +1 -0
  43. package/dist/cmd/auth/ssh/list.js +70 -0
  44. package/dist/cmd/auth/ssh/list.js.map +1 -0
  45. package/dist/cmd/auth/whoami.js +68 -0
  46. package/dist/cmd/auth/whoami.js.map +1 -0
  47. package/dist/cmd/build/ast.js +608 -0
  48. package/dist/cmd/build/ast.js.map +1 -0
  49. package/dist/cmd/build/ast.test.js +389 -0
  50. package/dist/cmd/build/ast.test.js.map +1 -0
  51. package/dist/cmd/build/bundler.js +304 -0
  52. package/dist/cmd/build/bundler.js.map +1 -0
  53. package/dist/cmd/build/file.js +10 -0
  54. package/dist/cmd/build/file.js.map +1 -0
  55. package/dist/cmd/build/fix-duplicate-exports.js +167 -0
  56. package/dist/cmd/build/fix-duplicate-exports.js.map +1 -0
  57. package/dist/cmd/build/fix-duplicate-exports.test.js +300 -0
  58. package/dist/cmd/build/fix-duplicate-exports.test.js.map +1 -0
  59. package/dist/cmd/build/index.d.ts.map +1 -1
  60. package/dist/cmd/build/index.js +81 -0
  61. package/dist/cmd/build/index.js.map +1 -0
  62. package/dist/cmd/build/patch/_util.js +42 -0
  63. package/dist/cmd/build/patch/_util.js.map +1 -0
  64. package/dist/cmd/build/patch/aisdk.js +65 -0
  65. package/dist/cmd/build/patch/aisdk.js.map +1 -0
  66. package/dist/cmd/build/patch/index.js +97 -0
  67. package/dist/cmd/build/patch/index.js.map +1 -0
  68. package/dist/cmd/build/patch/llm.js +18 -0
  69. package/dist/cmd/build/patch/llm.js.map +1 -0
  70. package/dist/cmd/build/plugin.d.ts.map +1 -1
  71. package/dist/cmd/build/plugin.js +581 -0
  72. package/dist/cmd/build/plugin.js.map +1 -0
  73. package/dist/cmd/cloud/agents/index.js +133 -0
  74. package/dist/cmd/cloud/agents/index.js.map +1 -0
  75. package/dist/cmd/cloud/deploy.js +341 -0
  76. package/dist/cmd/cloud/deploy.js.map +1 -0
  77. package/dist/cmd/cloud/deployment/index.js +20 -0
  78. package/dist/cmd/cloud/deployment/index.js.map +1 -0
  79. package/dist/cmd/cloud/deployment/list.js +89 -0
  80. package/dist/cmd/cloud/deployment/list.js.map +1 -0
  81. package/dist/cmd/cloud/deployment/remove.js +60 -0
  82. package/dist/cmd/cloud/deployment/remove.js.map +1 -0
  83. package/dist/cmd/cloud/deployment/rollback.js +80 -0
  84. package/dist/cmd/cloud/deployment/rollback.js.map +1 -0
  85. package/dist/cmd/cloud/deployment/show.js +106 -0
  86. package/dist/cmd/cloud/deployment/show.js.map +1 -0
  87. package/dist/cmd/cloud/deployment/undeploy.js +45 -0
  88. package/dist/cmd/cloud/deployment/undeploy.js.map +1 -0
  89. package/dist/cmd/cloud/deployment/utils.js +10 -0
  90. package/dist/cmd/cloud/deployment/utils.js.map +1 -0
  91. package/dist/cmd/cloud/domain.js +77 -0
  92. package/dist/cmd/cloud/domain.js.map +1 -0
  93. package/dist/cmd/cloud/env/delete.js +50 -0
  94. package/dist/cmd/cloud/env/delete.js.map +1 -0
  95. package/dist/cmd/cloud/env/get.js +65 -0
  96. package/dist/cmd/cloud/env/get.js.map +1 -0
  97. package/dist/cmd/cloud/env/import.js +113 -0
  98. package/dist/cmd/cloud/env/import.js.map +1 -0
  99. package/dist/cmd/cloud/env/index.js +24 -0
  100. package/dist/cmd/cloud/env/index.js.map +1 -0
  101. package/dist/cmd/cloud/env/list.js +58 -0
  102. package/dist/cmd/cloud/env/list.js.map +1 -0
  103. package/dist/cmd/cloud/env/pull.js +81 -0
  104. package/dist/cmd/cloud/env/pull.js.map +1 -0
  105. package/dist/cmd/cloud/env/push.js +61 -0
  106. package/dist/cmd/cloud/env/push.js.map +1 -0
  107. package/dist/cmd/cloud/env/set.js +73 -0
  108. package/dist/cmd/cloud/env/set.js.map +1 -0
  109. package/dist/cmd/cloud/index.js +31 -0
  110. package/dist/cmd/cloud/index.js.map +1 -0
  111. package/dist/cmd/cloud/keyvalue/create-namespace.js +41 -0
  112. package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -0
  113. package/dist/cmd/cloud/keyvalue/delete-namespace.js +64 -0
  114. package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -0
  115. package/dist/cmd/cloud/keyvalue/delete.js +47 -0
  116. package/dist/cmd/cloud/keyvalue/delete.js.map +1 -0
  117. package/dist/cmd/cloud/keyvalue/get.js +65 -0
  118. package/dist/cmd/cloud/keyvalue/get.js.map +1 -0
  119. package/dist/cmd/cloud/keyvalue/index.js +32 -0
  120. package/dist/cmd/cloud/keyvalue/index.js.map +1 -0
  121. package/dist/cmd/cloud/keyvalue/keys.js +50 -0
  122. package/dist/cmd/cloud/keyvalue/keys.js.map +1 -0
  123. package/dist/cmd/cloud/keyvalue/list-namespaces.js +37 -0
  124. package/dist/cmd/cloud/keyvalue/list-namespaces.js.map +1 -0
  125. package/dist/cmd/cloud/keyvalue/repl.js +277 -0
  126. package/dist/cmd/cloud/keyvalue/repl.js.map +1 -0
  127. package/dist/cmd/cloud/keyvalue/search.js +72 -0
  128. package/dist/cmd/cloud/keyvalue/search.js.map +1 -0
  129. package/dist/cmd/cloud/keyvalue/set.js +59 -0
  130. package/dist/cmd/cloud/keyvalue/set.js.map +1 -0
  131. package/dist/cmd/cloud/keyvalue/stats.js +82 -0
  132. package/dist/cmd/cloud/keyvalue/stats.js.map +1 -0
  133. package/dist/cmd/cloud/keyvalue/util.js +19 -0
  134. package/dist/cmd/cloud/keyvalue/util.js.map +1 -0
  135. package/dist/cmd/cloud/objectstore/delete-bucket.js +66 -0
  136. package/dist/cmd/cloud/objectstore/delete-bucket.js.map +1 -0
  137. package/dist/cmd/cloud/objectstore/delete.js +56 -0
  138. package/dist/cmd/cloud/objectstore/delete.js.map +1 -0
  139. package/dist/cmd/cloud/objectstore/get.js +64 -0
  140. package/dist/cmd/cloud/objectstore/get.js.map +1 -0
  141. package/dist/cmd/cloud/objectstore/index.js +28 -0
  142. package/dist/cmd/cloud/objectstore/index.js.map +1 -0
  143. package/dist/cmd/cloud/objectstore/list-buckets.js +37 -0
  144. package/dist/cmd/cloud/objectstore/list-buckets.js.map +1 -0
  145. package/dist/cmd/cloud/objectstore/list-keys.js +52 -0
  146. package/dist/cmd/cloud/objectstore/list-keys.js.map +1 -0
  147. package/dist/cmd/cloud/objectstore/put.js +57 -0
  148. package/dist/cmd/cloud/objectstore/put.js.map +1 -0
  149. package/dist/cmd/cloud/objectstore/repl.js +219 -0
  150. package/dist/cmd/cloud/objectstore/repl.js.map +1 -0
  151. package/dist/cmd/cloud/objectstore/url.js +55 -0
  152. package/dist/cmd/cloud/objectstore/url.js.map +1 -0
  153. package/dist/cmd/cloud/objectstore/util.js +18 -0
  154. package/dist/cmd/cloud/objectstore/util.js.map +1 -0
  155. package/dist/cmd/cloud/resource/add.js +70 -0
  156. package/dist/cmd/cloud/resource/add.js.map +1 -0
  157. package/dist/cmd/cloud/resource/delete.js +126 -0
  158. package/dist/cmd/cloud/resource/delete.js.map +1 -0
  159. package/dist/cmd/cloud/resource/index.js +12 -0
  160. package/dist/cmd/cloud/resource/index.js.map +1 -0
  161. package/dist/cmd/cloud/resource/list.js +89 -0
  162. package/dist/cmd/cloud/resource/list.js.map +1 -0
  163. package/dist/cmd/cloud/scp/download.js +72 -0
  164. package/dist/cmd/cloud/scp/download.js.map +1 -0
  165. package/dist/cmd/cloud/scp/index.js +10 -0
  166. package/dist/cmd/cloud/scp/index.js.map +1 -0
  167. package/dist/cmd/cloud/scp/upload.js +75 -0
  168. package/dist/cmd/cloud/scp/upload.js.map +1 -0
  169. package/dist/cmd/cloud/secret/delete.js +50 -0
  170. package/dist/cmd/cloud/secret/delete.js.map +1 -0
  171. package/dist/cmd/cloud/secret/get.js +69 -0
  172. package/dist/cmd/cloud/secret/get.js.map +1 -0
  173. package/dist/cmd/cloud/secret/import.js +88 -0
  174. package/dist/cmd/cloud/secret/import.js.map +1 -0
  175. package/dist/cmd/cloud/secret/index.js +24 -0
  176. package/dist/cmd/cloud/secret/index.js.map +1 -0
  177. package/dist/cmd/cloud/secret/list.js +58 -0
  178. package/dist/cmd/cloud/secret/list.js.map +1 -0
  179. package/dist/cmd/cloud/secret/pull.js +81 -0
  180. package/dist/cmd/cloud/secret/pull.js.map +1 -0
  181. package/dist/cmd/cloud/secret/push.js +61 -0
  182. package/dist/cmd/cloud/secret/push.js.map +1 -0
  183. package/dist/cmd/cloud/secret/set.js +57 -0
  184. package/dist/cmd/cloud/secret/set.js.map +1 -0
  185. package/dist/cmd/cloud/session/get.d.ts.map +1 -1
  186. package/dist/cmd/cloud/session/get.js +155 -0
  187. package/dist/cmd/cloud/session/get.js.map +1 -0
  188. package/dist/cmd/cloud/session/index.js +11 -0
  189. package/dist/cmd/cloud/session/index.js.map +1 -0
  190. package/dist/cmd/cloud/session/list.js +132 -0
  191. package/dist/cmd/cloud/session/list.js.map +1 -0
  192. package/dist/cmd/cloud/session/logs.js +56 -0
  193. package/dist/cmd/cloud/session/logs.js.map +1 -0
  194. package/dist/cmd/cloud/ssh.js +67 -0
  195. package/dist/cmd/cloud/ssh.js.map +1 -0
  196. package/dist/cmd/dev/agents.js +103 -0
  197. package/dist/cmd/dev/agents.js.map +1 -0
  198. package/dist/cmd/dev/api.js +26 -0
  199. package/dist/cmd/dev/api.js.map +1 -0
  200. package/dist/cmd/dev/download.js +77 -0
  201. package/dist/cmd/dev/download.js.map +1 -0
  202. package/dist/cmd/dev/index.js +745 -0
  203. package/dist/cmd/dev/index.js.map +1 -0
  204. package/dist/cmd/dev/sync.js +229 -0
  205. package/dist/cmd/dev/sync.js.map +1 -0
  206. package/dist/cmd/dev/templates.js +75 -0
  207. package/dist/cmd/dev/templates.js.map +1 -0
  208. package/dist/cmd/index.js +49 -0
  209. package/dist/cmd/index.js.map +1 -0
  210. package/dist/cmd/profile/create.js +89 -0
  211. package/dist/cmd/profile/create.js.map +1 -0
  212. package/dist/cmd/profile/delete.js +63 -0
  213. package/dist/cmd/profile/delete.js.map +1 -0
  214. package/dist/cmd/profile/index.js +14 -0
  215. package/dist/cmd/profile/index.js.map +1 -0
  216. package/dist/cmd/profile/list.js +28 -0
  217. package/dist/cmd/profile/list.js.map +1 -0
  218. package/dist/cmd/profile/show.js +68 -0
  219. package/dist/cmd/profile/show.js.map +1 -0
  220. package/dist/cmd/profile/use.js +37 -0
  221. package/dist/cmd/profile/use.js.map +1 -0
  222. package/dist/cmd/project/create.js +92 -0
  223. package/dist/cmd/project/create.js.map +1 -0
  224. package/dist/cmd/project/delete.js +117 -0
  225. package/dist/cmd/project/delete.js.map +1 -0
  226. package/dist/cmd/project/download.js +217 -0
  227. package/dist/cmd/project/download.js.map +1 -0
  228. package/dist/cmd/project/index.js +12 -0
  229. package/dist/cmd/project/index.js.map +1 -0
  230. package/dist/cmd/project/list.js +51 -0
  231. package/dist/cmd/project/list.js.map +1 -0
  232. package/dist/cmd/project/show.js +54 -0
  233. package/dist/cmd/project/show.js.map +1 -0
  234. package/dist/cmd/project/template-flow.js +315 -0
  235. package/dist/cmd/project/template-flow.js.map +1 -0
  236. package/dist/cmd/project/templates.js +31 -0
  237. package/dist/cmd/project/templates.js.map +1 -0
  238. package/dist/cmd/repl/index.js +444 -0
  239. package/dist/cmd/repl/index.js.map +1 -0
  240. package/dist/cmd/version/index.js +29 -0
  241. package/dist/cmd/version/index.js.map +1 -0
  242. package/dist/command-prefix.js +37 -0
  243. package/dist/command-prefix.js.map +1 -0
  244. package/dist/config.js +536 -0
  245. package/dist/config.js.map +1 -0
  246. package/dist/crypto/box.js +382 -0
  247. package/dist/crypto/box.js.map +1 -0
  248. package/dist/crypto/box.test.js +317 -0
  249. package/dist/crypto/box.test.js.map +1 -0
  250. package/dist/download.js +64 -0
  251. package/dist/download.js.map +1 -0
  252. package/dist/env-util.js +219 -0
  253. package/dist/env-util.js.map +1 -0
  254. package/dist/env-util.test.js +146 -0
  255. package/dist/env-util.test.js.map +1 -0
  256. package/dist/errors.js +177 -0
  257. package/dist/errors.js.map +1 -0
  258. package/dist/explain.js +90 -0
  259. package/dist/explain.js.map +1 -0
  260. package/dist/index.js +23 -0
  261. package/dist/index.js.map +1 -0
  262. package/dist/json.js +29 -0
  263. package/dist/json.js.map +1 -0
  264. package/dist/legacy-check.js +104 -0
  265. package/dist/legacy-check.js.map +1 -0
  266. package/dist/output.js +207 -0
  267. package/dist/output.js.map +1 -0
  268. package/dist/repl.js +1176 -0
  269. package/dist/repl.js.map +1 -0
  270. package/dist/runtime.js +19 -0
  271. package/dist/runtime.js.map +1 -0
  272. package/dist/schema-generator.js +289 -0
  273. package/dist/schema-generator.js.map +1 -0
  274. package/dist/schema-parser.js +145 -0
  275. package/dist/schema-parser.js.map +1 -0
  276. package/dist/sound.js +44 -0
  277. package/dist/sound.js.map +1 -0
  278. package/dist/steps.js +293 -0
  279. package/dist/steps.js.map +1 -0
  280. package/dist/terminal.js +130 -0
  281. package/dist/terminal.js.map +1 -0
  282. package/dist/tui.js +1124 -0
  283. package/dist/tui.js.map +1 -0
  284. package/dist/types.js +163 -0
  285. package/dist/types.js.map +1 -0
  286. package/dist/utils/detectSubagent.js +25 -0
  287. package/dist/utils/detectSubagent.js.map +1 -0
  288. package/dist/utils/format.js +21 -0
  289. package/dist/utils/format.js.map +1 -0
  290. package/dist/utils/zip.js +33 -0
  291. package/dist/utils/zip.js.map +1 -0
  292. package/dist/version.js +24 -0
  293. package/dist/version.js.map +1 -0
  294. package/package.json +6 -6
  295. package/src/banner.ts +1 -1
  296. package/src/cmd/build/index.ts +18 -22
  297. package/src/cmd/build/plugin.ts +95 -64
  298. package/src/cmd/cloud/session/get.ts +20 -14
  299. package/src/cmd/cloud/session/list.ts +1 -1
@@ -0,0 +1,55 @@
1
+ import { createSubcommand } from '../../types';
2
+ import { getAppBaseURL, UpgradeRequiredError } from '@agentuity/server';
3
+ import { saveAuth } from '../../config';
4
+ import { generateSignupOTP, pollForSignupCompletion } from './api';
5
+ import * as tui from '../../tui';
6
+ import { getCommand } from '../../command-prefix';
7
+ import { ErrorCode } from '../../errors';
8
+ export const signupCommand = createSubcommand({
9
+ name: 'signup',
10
+ description: 'Create a new Agentuity Cloud Platform account',
11
+ tags: ['mutating', 'creates-resource', 'slow', 'api-intensive'],
12
+ toplevel: true,
13
+ idempotent: false,
14
+ requires: { apiClient: true },
15
+ examples: [getCommand('auth signup'), getCommand('signup')],
16
+ async handler(ctx) {
17
+ const { logger, config, apiClient } = ctx;
18
+ const appUrl = getAppBaseURL(config?.overrides);
19
+ try {
20
+ const otp = generateSignupOTP();
21
+ const signupURL = `${appUrl}/sign-up?code=${otp}`;
22
+ const bannerBody = `Please open the URL in your browser:\n\n${tui.link(signupURL)}\n\n${tui.muted('Once you have completed the signup process, you will be given a one-time password to complete the signup process.')}`;
23
+ tui.banner('Signup for Agentuity', bannerBody);
24
+ tui.newline();
25
+ await tui.spinner({
26
+ message: 'Waiting for signup to complete...',
27
+ clearOnSuccess: true,
28
+ callback: async () => {
29
+ const result = await pollForSignupCompletion(apiClient, otp);
30
+ await saveAuth({
31
+ apiKey: result.apiKey,
32
+ userId: result.userId,
33
+ expires: result.expires,
34
+ });
35
+ },
36
+ });
37
+ tui.newline();
38
+ tui.success('Welcome to Agentuity! You are now logged in');
39
+ }
40
+ catch (error) {
41
+ if (error instanceof UpgradeRequiredError) {
42
+ const bannerBody = `${error.message}\n\nVisit: ${tui.link('https://agentuity.dev/CLI/installation')}`;
43
+ tui.banner('CLI Upgrade Required', bannerBody);
44
+ process.exit(1);
45
+ }
46
+ else if (error instanceof Error) {
47
+ logger.fatal(`Signup failed: ${error.message}`, ErrorCode.AUTH_FAILED);
48
+ }
49
+ else {
50
+ logger.fatal('Signup failed', ErrorCode.AUTH_FAILED);
51
+ }
52
+ }
53
+ },
54
+ });
55
+ //# sourceMappingURL=signup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signup.js","sourceRoot":"","sources":["../../../src/cmd/auth/signup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,OAAO,CAAC;AACnE,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAAC;IAC7C,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,+CAA+C;IAC5D,IAAI,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,MAAM,EAAE,eAAe,CAAC;IAC/D,QAAQ,EAAE,IAAI;IACd,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE;IAC7B,QAAQ,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAE3D,KAAK,CAAC,OAAO,CAAC,GAAG;QAChB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC;QAC1C,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAEhD,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;YAEhC,MAAM,SAAS,GAAG,GAAG,MAAM,iBAAiB,GAAG,EAAE,CAAC;YAElD,MAAM,UAAU,GAAG,2CAA2C,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,mHAAmH,CAAC,EAAE,CAAC;YAEzN,GAAG,CAAC,MAAM,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAC;YAC/C,GAAG,CAAC,OAAO,EAAE,CAAC;YAEd,MAAM,GAAG,CAAC,OAAO,CAAC;gBACjB,OAAO,EAAE,mCAAmC;gBAC5C,cAAc,EAAE,IAAI;gBACpB,QAAQ,EAAE,KAAK,IAAI,EAAE;oBACpB,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;oBAE7D,MAAM,QAAQ,CAAC;wBACd,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,OAAO,EAAE,MAAM,CAAC,OAAO;qBACvB,CAAC,CAAC;gBACJ,CAAC;aACD,CAAC,CAAC;YAEH,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,GAAG,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,KAAK,YAAY,oBAAoB,EAAE,CAAC;gBAC3C,MAAM,UAAU,GAAG,GAAG,KAAK,CAAC,OAAO,cAAc,GAAG,CAAC,IAAI,CAAC,wCAAwC,CAAC,EAAE,CAAC;gBACtG,GAAG,CAAC,MAAM,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAC;gBAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjB,CAAC;iBAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBACnC,MAAM,CAAC,KAAK,CAAC,kBAAkB,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;YACtD,CAAC;QACF,CAAC;IACF,CAAC;CACD,CAAC,CAAC"}
@@ -0,0 +1,239 @@
1
+ import { createSubcommand } from '../../../types';
2
+ import { addSSHKey, computeSSHKeyFingerprint, listSSHKeys } from './api';
3
+ import * as tui from '../../../tui';
4
+ import { getCommand } from '../../../command-prefix';
5
+ import enquirer from 'enquirer';
6
+ import { readFileSync, readdirSync, statSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+ import { z } from 'zod';
10
+ import { ErrorCode } from '../../../errors';
11
+ const optionsSchema = z.object({
12
+ file: z.string().optional().describe('File containing the public key'),
13
+ });
14
+ const SSHAddResponseSchema = z.object({
15
+ success: z.boolean().describe('Whether the operation succeeded'),
16
+ fingerprint: z.string().describe('SSH key fingerprint'),
17
+ keyType: z.string().describe('SSH key type (e.g., ssh-rsa, ssh-ed25519)'),
18
+ added: z.number().describe('Number of keys added'),
19
+ });
20
+ /**
21
+ * Scan ~/.ssh directory for valid SSH public keys
22
+ */
23
+ function discoverSSHKeys() {
24
+ const sshDir = join(homedir(), '.ssh');
25
+ const keys = [];
26
+ const seenFingerprints = new Set();
27
+ try {
28
+ const files = readdirSync(sshDir);
29
+ for (const file of files) {
30
+ // Only look at .pub files (public keys)
31
+ if (!file.endsWith('.pub')) {
32
+ continue;
33
+ }
34
+ const filePath = join(sshDir, file);
35
+ try {
36
+ const stat = statSync(filePath);
37
+ if (!stat.isFile()) {
38
+ continue;
39
+ }
40
+ const content = readFileSync(filePath, 'utf-8').trim();
41
+ // Validate it's a valid SSH key
42
+ const fingerprint = computeSSHKeyFingerprint(content);
43
+ // Skip duplicate fingerprints
44
+ if (seenFingerprints.has(fingerprint)) {
45
+ continue;
46
+ }
47
+ seenFingerprints.add(fingerprint);
48
+ // Extract comment if present (last part of the key)
49
+ const parts = content.split(/\s+/);
50
+ const comment = parts.length >= 3 ? parts.slice(2).join(' ') : '';
51
+ keys.push({
52
+ path: filePath,
53
+ filename: file,
54
+ publicKey: content,
55
+ fingerprint,
56
+ comment,
57
+ });
58
+ }
59
+ catch {
60
+ // Skip invalid keys
61
+ continue;
62
+ }
63
+ }
64
+ }
65
+ catch {
66
+ // If we can't read ~/.ssh, just return empty array
67
+ return [];
68
+ }
69
+ // Sort by filename for predictable ordering
70
+ return keys.sort((a, b) => a.filename.localeCompare(b.filename));
71
+ }
72
+ /**
73
+ * Read stdin once if non-TTY and return its contents, or null when there is
74
+ * no piped data (e.g. timeout).
75
+ * This helper should be the only place that consumes Bun.stdin.
76
+ */
77
+ async function readStdinIfPiped() {
78
+ if (process.stdin.isTTY) {
79
+ return null;
80
+ }
81
+ try {
82
+ const stdin = await Promise.race([
83
+ Bun.stdin.text(),
84
+ new Promise((resolve) => setTimeout(() => resolve(null), 1000)),
85
+ ]);
86
+ return stdin !== null && stdin.trim().length > 0 ? stdin : null;
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
92
+ export const addCommand = createSubcommand({
93
+ name: 'add',
94
+ aliases: ['create'],
95
+ description: 'Add an SSH public key to your account (reads from file or stdin)',
96
+ tags: ['mutating', 'creates-resource', 'slow', 'requires-auth'],
97
+ idempotent: false,
98
+ requires: { apiClient: true, auth: true },
99
+ examples: [
100
+ getCommand('auth ssh add'),
101
+ getCommand('auth ssh add --file ~/.ssh/id_ed25519.pub'),
102
+ getCommand('auth ssh add --file ./deploy_key.pub'),
103
+ 'cat ~/.ssh/id_rsa.pub | ' + getCommand('auth ssh add'),
104
+ ],
105
+ schema: {
106
+ options: optionsSchema,
107
+ response: SSHAddResponseSchema,
108
+ },
109
+ async handler(ctx) {
110
+ const { logger, apiClient, opts } = ctx;
111
+ if (!apiClient) {
112
+ logger.fatal('API client is not available', ErrorCode.INTERNAL_ERROR);
113
+ }
114
+ try {
115
+ let publicKey = '';
116
+ if (opts.file) {
117
+ // Read from file
118
+ try {
119
+ publicKey = readFileSync(opts.file, 'utf-8').trim();
120
+ }
121
+ catch (error) {
122
+ logger.fatal(`Error reading file: ${error instanceof Error ? error.message : 'Unknown error'}`);
123
+ }
124
+ }
125
+ else {
126
+ const stdin = await readStdinIfPiped();
127
+ if (stdin) {
128
+ // Read from stdin if data is piped
129
+ publicKey = stdin.trim();
130
+ }
131
+ else {
132
+ // No file or stdin - discover SSH keys
133
+ const discoveredKeys = discoverSSHKeys();
134
+ if (discoveredKeys.length === 0) {
135
+ logger.fatal('No SSH public keys found in ~/.ssh/\n' +
136
+ 'Please specify a file with --file or pipe the key via stdin');
137
+ return;
138
+ }
139
+ // Fetch existing keys from server to filter out already-added ones
140
+ const existingKeys = await tui.spinner({
141
+ type: 'simple',
142
+ message: 'Checking existing SSH keys...',
143
+ callback: () => listSSHKeys(apiClient),
144
+ clearOnSuccess: true,
145
+ });
146
+ const existingFingerprints = new Set(existingKeys.map((k) => k.fingerprint));
147
+ const newKeys = discoveredKeys.filter((k) => !existingFingerprints.has(k.fingerprint));
148
+ if (newKeys.length === 0) {
149
+ const cmd = getCommand('auth ssh add');
150
+ const boldcmd = tui.bold('cat key.pub | ' + cmd);
151
+ tui.info('All local SSH keys in ~/.ssh/ have already been added to your account');
152
+ tui.newline();
153
+ console.log('To add a different key:');
154
+ tui.bullet(`Use ${tui.bold('--file <path>')} to specify a key file`);
155
+ tui.bullet(`Pipe the key via stdin: ${boldcmd}`);
156
+ return;
157
+ }
158
+ if (!process.stdin.isTTY) {
159
+ logger.fatal('Interactive selection required but cannot prompt in non-TTY environment. Use --file or pipe the key via stdin.');
160
+ return;
161
+ }
162
+ const response = await enquirer.prompt({
163
+ type: 'multiselect',
164
+ name: 'keys',
165
+ message: 'Select SSH keys to add (Space to select, Enter to confirm)',
166
+ choices: newKeys.map((key) => {
167
+ const keyType = key.publicKey.split(/\s+/)[0] || 'unknown';
168
+ return {
169
+ name: key.fingerprint,
170
+ message: `${keyType.padEnd(12)} ${key.fingerprint} ${tui.muted(key.comment || key.filename)}`,
171
+ };
172
+ }),
173
+ });
174
+ const selectedFingerprints = response.keys;
175
+ if (selectedFingerprints.length === 0) {
176
+ tui.newline();
177
+ tui.info('No keys selected');
178
+ return;
179
+ }
180
+ // Build Map for O(1) lookups
181
+ const keyMap = new Map(newKeys.map((k) => [k.fingerprint, k]));
182
+ // Add all selected keys
183
+ for (const fingerprint of selectedFingerprints) {
184
+ const key = keyMap.get(fingerprint);
185
+ if (!key)
186
+ continue;
187
+ try {
188
+ const result = await tui.spinner({
189
+ type: 'simple',
190
+ message: `Adding SSH key ${fingerprint}...`,
191
+ callback: () => addSSHKey(apiClient, key.publicKey),
192
+ clearOnSuccess: true,
193
+ });
194
+ tui.success(`SSH key added: ${tui.muted(result.fingerprint)}`);
195
+ }
196
+ catch (error) {
197
+ tui.newline();
198
+ if (error instanceof Error) {
199
+ tui.error(`Failed to add ${fingerprint}: ${error.message}`);
200
+ }
201
+ else {
202
+ tui.error(`Failed to add ${fingerprint}`);
203
+ }
204
+ }
205
+ }
206
+ return;
207
+ }
208
+ }
209
+ // Only process single key if we got here (from --file or stdin)
210
+ if (!publicKey) {
211
+ logger.fatal('No public key provided');
212
+ }
213
+ // Validate key format
214
+ try {
215
+ computeSSHKeyFingerprint(publicKey);
216
+ }
217
+ catch (error) {
218
+ logger.fatal(`Invalid SSH key format: ${error instanceof Error ? error.message : 'Unknown error'}`);
219
+ }
220
+ const result = await tui.spinner({
221
+ type: 'simple',
222
+ message: 'Adding SSH key...',
223
+ callback: () => addSSHKey(apiClient, publicKey),
224
+ clearOnSuccess: true,
225
+ });
226
+ tui.success(`SSH key added: ${tui.muted(result.fingerprint)}`);
227
+ }
228
+ catch (error) {
229
+ logger.trace(error);
230
+ if (error instanceof Error) {
231
+ logger.fatal(`Failed to add SSH key: ${error.message}`, ErrorCode.API_ERROR);
232
+ }
233
+ else {
234
+ logger.fatal('Failed to add SSH key', ErrorCode.API_ERROR);
235
+ }
236
+ }
237
+ },
238
+ });
239
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../../../src/cmd/auth/ssh/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+ import { APIResponseSchema } from '@agentuity/server';
3
+ import { createHash } from 'crypto';
4
+ // Zod schemas for API validation
5
+ const SSHKeySchema = z.object({
6
+ fingerprint: z.string(),
7
+ keyType: z.string(),
8
+ comment: z.string(),
9
+ publicKey: z.string(),
10
+ });
11
+ const AddSSHKeyResponseSchema = z.object({
12
+ fingerprint: z.string(),
13
+ added: z.boolean(),
14
+ });
15
+ const RemoveSSHKeyResponseSchema = z.object({
16
+ removed: z.boolean(),
17
+ });
18
+ export function computeSSHKeyFingerprint(publicKey) {
19
+ // Parse the key (format: "ssh-ed25519 AAAAC3... [comment]")
20
+ const parts = publicKey.trim().split(/\s+/);
21
+ if (parts.length < 2) {
22
+ throw new Error('Invalid SSH public key format');
23
+ }
24
+ const keyData = parts[1]; // Base64-encoded key data
25
+ const buffer = Buffer.from(keyData, 'base64');
26
+ const fingerprint = createHash('sha256').update(buffer).digest('base64');
27
+ return `SHA256:${fingerprint.replace(/=+$/, '')}`;
28
+ }
29
+ export async function addSSHKey(apiClient, publicKey) {
30
+ const resp = await apiClient.request('POST', '/cli/auth/ssh-keys', APIResponseSchema(AddSSHKeyResponseSchema), { publicKey });
31
+ if (!resp.success) {
32
+ throw new Error(resp.message);
33
+ }
34
+ if (!resp.data) {
35
+ throw new Error('No data returned from server');
36
+ }
37
+ return resp.data;
38
+ }
39
+ export async function listSSHKeys(apiClient) {
40
+ const resp = await apiClient.request('GET', '/cli/auth/ssh-keys', APIResponseSchema(z.array(SSHKeySchema)));
41
+ if (!resp.success) {
42
+ throw new Error(resp.message);
43
+ }
44
+ return resp.data ?? [];
45
+ }
46
+ export async function removeSSHKey(apiClient, fingerprint) {
47
+ const resp = await apiClient.request('DELETE', '/cli/auth/ssh-keys', APIResponseSchema(RemoveSSHKeyResponseSchema), { fingerprint });
48
+ if (!resp.success) {
49
+ throw new Error(resp.message);
50
+ }
51
+ return resp.data?.removed ?? false;
52
+ }
53
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../src/cmd/auth/ssh/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,iCAAiC;AACjC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAC;AAEH,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;CAClB,CAAC,CAAC;AAEH,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;CACpB,CAAC,CAAC;AAeH,MAAM,UAAU,wBAAwB,CAAC,SAAiB;IACzD,4DAA4D;IAC5D,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,0BAA0B;IACpD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzE,OAAO,UAAU,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,SAAoB,EAAE,SAAiB;IACtE,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CACnC,MAAM,EACN,oBAAoB,EACpB,iBAAiB,CAAC,uBAAuB,CAAC,EAC1C,EAAE,SAAS,EAAE,CACb,CAAC;IAEF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAoB;IACrD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CACnC,KAAK,EACL,oBAAoB,EACpB,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CACxC,CAAC;IAEF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAoB,EAAE,WAAmB;IAC3E,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CACnC,QAAQ,EACR,oBAAoB,EACpB,iBAAiB,CAAC,0BAA0B,CAAC,EAC7C,EAAE,WAAW,EAAE,CACf,CAAC;IAEF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,CAAC;AACpC,CAAC"}
@@ -0,0 +1,126 @@
1
+ import { createSubcommand } from '../../../types';
2
+ import { removeSSHKey, listSSHKeys } from './api';
3
+ import * as tui from '../../../tui';
4
+ import enquirer from 'enquirer';
5
+ import { z } from 'zod';
6
+ import { isExplainMode, isDryRunMode, outputExplain, outputDryRun } from '../../../explain';
7
+ import { getCommand } from '../../../command-prefix';
8
+ import { ErrorCode } from '../../../errors';
9
+ const SSHDeleteResponseSchema = z.object({
10
+ success: z.boolean().describe('Whether the operation succeeded'),
11
+ removed: z.number().describe('Number of keys removed'),
12
+ fingerprints: z.array(z.string()).describe('Fingerprints of removed keys'),
13
+ });
14
+ export const deleteCommand = createSubcommand({
15
+ name: 'delete',
16
+ aliases: ['rm', 'del', 'remove'],
17
+ description: 'Delete an SSH key from your account',
18
+ tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
19
+ requires: { apiClient: true, auth: true },
20
+ idempotent: false,
21
+ examples: [
22
+ getCommand('auth ssh delete'),
23
+ getCommand('auth ssh delete <fingerprint>'),
24
+ getCommand('--explain auth ssh delete abc123'),
25
+ getCommand('--dry-run auth ssh delete abc123'),
26
+ ],
27
+ schema: {
28
+ args: z.object({
29
+ fingerprints: z.array(z.string()).optional().describe('SSH key fingerprint(s) to remove'),
30
+ }),
31
+ options: z.object({
32
+ confirm: z.boolean().default(true).describe('prompt for confirmation before deletion'),
33
+ }),
34
+ response: SSHDeleteResponseSchema,
35
+ },
36
+ async handler(ctx) {
37
+ const { logger, apiClient, args, opts, options } = ctx;
38
+ if (!apiClient) {
39
+ logger.fatal('API client is not available', ErrorCode.INTERNAL_ERROR);
40
+ }
41
+ const shouldConfirm = process.stdin.isTTY ? opts.confirm : false;
42
+ try {
43
+ let fingerprintsToRemove = [];
44
+ if (args.fingerprints && args.fingerprints.length > 0) {
45
+ fingerprintsToRemove = args.fingerprints;
46
+ }
47
+ else {
48
+ const keys = await tui.spinner('Fetching SSH keys...', () => listSSHKeys(apiClient));
49
+ if (keys.length === 0) {
50
+ tui.newline();
51
+ tui.info('No SSH keys found');
52
+ return;
53
+ }
54
+ if (!process.stdin.isTTY) {
55
+ logger.fatal('Interactive selection required but cannot prompt in non-TTY environment. Provide fingerprint as argument.');
56
+ }
57
+ tui.newline();
58
+ const response = await enquirer.prompt({
59
+ type: 'multiselect',
60
+ name: 'keys',
61
+ message: 'Select SSH keys to remove (Space to select, Enter to confirm)',
62
+ choices: keys.map((key) => ({
63
+ name: key.fingerprint,
64
+ message: `${key.keyType.padEnd(12)} ${key.fingerprint} ${tui.muted(key.comment || '(no comment)')}`,
65
+ })),
66
+ });
67
+ fingerprintsToRemove = response.keys;
68
+ if (fingerprintsToRemove.length === 0) {
69
+ tui.newline();
70
+ tui.info('No keys selected');
71
+ return;
72
+ }
73
+ }
74
+ // If in explain mode, show what would happen
75
+ if (isExplainMode(options)) {
76
+ outputExplain({
77
+ command: 'auth ssh delete',
78
+ description: 'Delete SSH keys from your account',
79
+ steps: fingerprintsToRemove.map((fp) => ({
80
+ action: `Remove SSH key with fingerprint: ${fp}`,
81
+ })),
82
+ warnings: ['This action cannot be undone'],
83
+ }, options);
84
+ return;
85
+ }
86
+ if (shouldConfirm) {
87
+ tui.newline();
88
+ const confirmed = await tui.confirm(`Remove ${fingerprintsToRemove.length} SSH key${fingerprintsToRemove.length > 1 ? 's' : ''}?`, false);
89
+ if (!confirmed) {
90
+ tui.info('Cancelled');
91
+ return;
92
+ }
93
+ }
94
+ // Handle dry-run mode
95
+ if (isDryRunMode(options)) {
96
+ for (const fingerprint of fingerprintsToRemove) {
97
+ outputDryRun(`Would remove SSH key: ${fingerprint}`, options);
98
+ }
99
+ tui.newline();
100
+ tui.info(`[DRY RUN] Would remove ${fingerprintsToRemove.length} SSH key${fingerprintsToRemove.length > 1 ? 's' : ''}`);
101
+ return;
102
+ }
103
+ // Actually execute the deletion
104
+ for (const fingerprint of fingerprintsToRemove) {
105
+ await tui.spinner(`Removing SSH key ${fingerprint}...`, () => removeSSHKey(apiClient, fingerprint));
106
+ }
107
+ tui.newline();
108
+ tui.success(`Removed ${fingerprintsToRemove.length} SSH key${fingerprintsToRemove.length > 1 ? 's' : ''}`);
109
+ return {
110
+ success: true,
111
+ removed: fingerprintsToRemove.length,
112
+ fingerprints: fingerprintsToRemove,
113
+ };
114
+ }
115
+ catch (error) {
116
+ logger.trace(error);
117
+ if (error instanceof Error) {
118
+ logger.fatal(`Failed to remove SSH key: ${error.message}`, ErrorCode.API_ERROR);
119
+ }
120
+ else {
121
+ logger.fatal('Failed to remove SSH key', ErrorCode.API_ERROR);
122
+ }
123
+ }
124
+ },
125
+ });
126
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../../src/cmd/auth/ssh/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAChE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IACtD,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;CAC1E,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAAC;IAC7C,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC;IAChC,WAAW,EAAE,qCAAqC;IAClD,IAAI,EAAE,CAAC,aAAa,EAAE,kBAAkB,EAAE,MAAM,EAAE,eAAe,CAAC;IAClE,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;IACzC,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE;QACT,UAAU,CAAC,iBAAiB,CAAC;QAC7B,UAAU,CAAC,+BAA+B,CAAC;QAC3C,UAAU,CAAC,kCAAkC,CAAC;QAC9C,UAAU,CAAC,kCAAkC,CAAC;KAC9C;IACD,MAAM,EAAE;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YACd,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;SACzF,CAAC;QACF,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;YACjB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,yCAAyC,CAAC;SACtF,CAAC;QACF,QAAQ,EAAE,uBAAuB;KACjC;IACD,KAAK,CAAC,OAAO,CAAC,GAAG;QAChB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC;QAEvD,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QAEjE,IAAI,CAAC;YACJ,IAAI,oBAAoB,GAAa,EAAE,CAAC;YAExC,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvD,oBAAoB,GAAG,IAAI,CAAC,YAAY,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACP,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;gBAErF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,GAAG,CAAC,OAAO,EAAE,CAAC;oBACd,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;oBAC9B,OAAO;gBACR,CAAC;gBAED,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;oBAC1B,MAAM,CAAC,KAAK,CACX,2GAA2G,CAC3G,CAAC;gBACH,CAAC;gBAED,GAAG,CAAC,OAAO,EAAE,CAAC;gBAEd,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAqB;oBAC1D,IAAI,EAAE,aAAa;oBACnB,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,+DAA+D;oBACxE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;wBAC3B,IAAI,EAAE,GAAG,CAAC,WAAW;wBACrB,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,cAAc,CAAC,EAAE;qBACnG,CAAC,CAAC;iBACH,CAAC,CAAC;gBAEH,oBAAoB,GAAG,QAAQ,CAAC,IAAI,CAAC;gBAErC,IAAI,oBAAoB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvC,GAAG,CAAC,OAAO,EAAE,CAAC;oBACd,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;oBAC7B,OAAO;gBACR,CAAC;YACF,CAAC;YAED,6CAA6C;YAC7C,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,aAAa,CACZ;oBACC,OAAO,EAAE,iBAAiB;oBAC1B,WAAW,EAAE,mCAAmC;oBAChD,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;wBACxC,MAAM,EAAE,oCAAoC,EAAE,EAAE;qBAChD,CAAC,CAAC;oBACH,QAAQ,EAAE,CAAC,8BAA8B,CAAC;iBAC1C,EACD,OAAO,CACP,CAAC;gBACF,OAAO;YACR,CAAC;YAED,IAAI,aAAa,EAAE,CAAC;gBACnB,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,OAAO,CAClC,UAAU,oBAAoB,CAAC,MAAM,WAAW,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAC7F,KAAK,CACL,CAAC;gBAEF,IAAI,CAAC,SAAS,EAAE,CAAC;oBAChB,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;oBACtB,OAAO;gBACR,CAAC;YACF,CAAC;YAED,sBAAsB;YACtB,IAAI,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3B,KAAK,MAAM,WAAW,IAAI,oBAAoB,EAAE,CAAC;oBAChD,YAAY,CAAC,yBAAyB,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC;gBAC/D,CAAC;gBACD,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,GAAG,CAAC,IAAI,CACP,0BAA0B,oBAAoB,CAAC,MAAM,WAAW,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC5G,CAAC;gBACF,OAAO;YACR,CAAC;YAED,gCAAgC;YAChC,KAAK,MAAM,WAAW,IAAI,oBAAoB,EAAE,CAAC;gBAChD,MAAM,GAAG,CAAC,OAAO,CAAC,oBAAoB,WAAW,KAAK,EAAE,GAAG,EAAE,CAC5D,YAAY,CAAC,SAAS,EAAE,WAAW,CAAC,CACpC,CAAC;YACH,CAAC;YAED,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,GAAG,CAAC,OAAO,CACV,WAAW,oBAAoB,CAAC,MAAM,WAAW,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7F,CAAC;YAEF,OAAO;gBACN,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,oBAAoB,CAAC,MAAM;gBACpC,YAAY,EAAE,oBAAoB;aAClC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC5B,MAAM,CAAC,KAAK,CAAC,6BAA6B,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;YACjF,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;YAC/D,CAAC;QACF,CAAC;IACF,CAAC;CACD,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { createCommand } from '../../../types';
2
+ import { listCommand } from './list';
3
+ import { addCommand } from './add';
4
+ import { deleteCommand } from './delete';
5
+ export const sshSubcommand = createCommand({
6
+ name: 'ssh',
7
+ description: 'Manage SSH keys',
8
+ tags: ['fast', 'requires-auth'],
9
+ subcommands: [listCommand, addCommand, deleteCommand],
10
+ });
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cmd/auth/ssh/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;IAC1C,IAAI,EAAE,KAAK;IACX,WAAW,EAAE,iBAAiB;IAC9B,IAAI,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC;IAC/B,WAAW,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,aAAa,CAAC;CACrD,CAAC,CAAC"}
@@ -0,0 +1,70 @@
1
+ import { createSubcommand } from '../../../types';
2
+ import { listSSHKeys } from './api';
3
+ import * as tui from '../../../tui';
4
+ import { getCommand } from '../../../command-prefix';
5
+ import { ErrorCode } from '../../../errors';
6
+ import { z } from 'zod';
7
+ const SSHListResponseSchema = z.array(z.object({
8
+ id: z.string().describe('SSH key ID'),
9
+ fingerprint: z.string().describe('SSH key fingerprint'),
10
+ keyType: z.string().describe('SSH key type (e.g., ssh-rsa, ssh-ed25519)'),
11
+ comment: z.string().optional().describe('SSH key comment'),
12
+ createdAt: z.string().optional().describe('Creation timestamp'),
13
+ }));
14
+ export const listCommand = createSubcommand({
15
+ name: 'list',
16
+ aliases: ['ls'],
17
+ description: 'List all SSH keys on your account',
18
+ tags: ['read-only', 'fast', 'requires-auth'],
19
+ requires: { apiClient: true, auth: true },
20
+ idempotent: true,
21
+ examples: [
22
+ getCommand('auth ssh list'),
23
+ getCommand('auth ssh ls'),
24
+ getCommand('--json auth ssh list'),
25
+ ],
26
+ schema: {
27
+ response: SSHListResponseSchema,
28
+ },
29
+ async handler(ctx) {
30
+ const { logger, apiClient, options } = ctx;
31
+ if (!apiClient) {
32
+ logger.fatal('API client is not available', ErrorCode.INTERNAL_ERROR);
33
+ }
34
+ try {
35
+ const keys = await tui.spinner('Fetching SSH keys...', () => listSSHKeys(apiClient));
36
+ if (options.json) {
37
+ console.log(JSON.stringify(keys, null, 2));
38
+ return keys;
39
+ }
40
+ tui.newline();
41
+ if (keys.length === 0) {
42
+ console.log('No SSH keys found');
43
+ return [];
44
+ }
45
+ console.log(tui.bold('SSH Keys:'));
46
+ tui.newline();
47
+ const tableData = keys.map((key) => ({
48
+ TYPE: key.keyType,
49
+ FINGERPRINT: key.fingerprint,
50
+ COMMENT: key.comment || tui.muted('(no comment)'),
51
+ }));
52
+ tui.table(tableData, [
53
+ { name: 'TYPE', alignment: 'left' },
54
+ { name: 'FINGERPRINT', alignment: 'left' },
55
+ { name: 'COMMENT', alignment: 'left' },
56
+ ]);
57
+ return keys;
58
+ }
59
+ catch (error) {
60
+ logger.trace(error);
61
+ if (error instanceof Error) {
62
+ logger.fatal(`Failed to list SSH keys: ${error.message}`, ErrorCode.API_ERROR);
63
+ }
64
+ else {
65
+ logger.fatal('Failed to list SSH keys', ErrorCode.API_ERROR);
66
+ }
67
+ }
68
+ },
69
+ });
70
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/cmd/auth/ssh/list.ts"],"names":[],"mappings":"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"}