@agentuity/cli 1.0.1 → 1.0.3

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 (331) hide show
  1. package/AGENTS.md +40 -24
  2. package/bin/cli.ts +47 -22
  3. package/dist/agent-detection.d.ts +23 -38
  4. package/dist/agent-detection.d.ts.map +1 -1
  5. package/dist/agent-detection.js +412 -153
  6. package/dist/agent-detection.js.map +1 -1
  7. package/dist/ai-help.d.ts +23 -0
  8. package/dist/ai-help.d.ts.map +1 -0
  9. package/dist/ai-help.js +328 -0
  10. package/dist/ai-help.js.map +1 -0
  11. package/dist/api.js +1 -1
  12. package/dist/api.js.map +1 -1
  13. package/dist/auth.d.ts +10 -1
  14. package/dist/auth.d.ts.map +1 -1
  15. package/dist/auth.js +176 -16
  16. package/dist/auth.js.map +1 -1
  17. package/dist/banner.d.ts.map +1 -1
  18. package/dist/banner.js +5 -0
  19. package/dist/banner.js.map +1 -1
  20. package/dist/cache/agent-intro.d.ts +13 -0
  21. package/dist/cache/agent-intro.d.ts.map +1 -0
  22. package/dist/cache/agent-intro.js +54 -0
  23. package/dist/cache/agent-intro.js.map +1 -0
  24. package/dist/cache/index.d.ts +1 -0
  25. package/dist/cache/index.d.ts.map +1 -1
  26. package/dist/cache/index.js +1 -0
  27. package/dist/cache/index.js.map +1 -1
  28. package/dist/cache/resource-region.d.ts +3 -2
  29. package/dist/cache/resource-region.d.ts.map +1 -1
  30. package/dist/cache/resource-region.js +13 -4
  31. package/dist/cache/resource-region.js.map +1 -1
  32. package/dist/catalyst.d.ts +7 -0
  33. package/dist/catalyst.d.ts.map +1 -0
  34. package/dist/catalyst.js +15 -0
  35. package/dist/catalyst.js.map +1 -0
  36. package/dist/cli.d.ts +12 -1
  37. package/dist/cli.d.ts.map +1 -1
  38. package/dist/cli.js +290 -67
  39. package/dist/cli.js.map +1 -1
  40. package/dist/cmd/ai/detect.d.ts +3 -0
  41. package/dist/cmd/ai/detect.d.ts.map +1 -0
  42. package/dist/cmd/ai/detect.js +49 -0
  43. package/dist/cmd/ai/detect.js.map +1 -0
  44. package/dist/cmd/ai/index.d.ts.map +1 -1
  45. package/dist/cmd/ai/index.js +18 -1
  46. package/dist/cmd/ai/index.js.map +1 -1
  47. package/dist/cmd/ai/intro.d.ts +7 -0
  48. package/dist/cmd/ai/intro.d.ts.map +1 -0
  49. package/dist/cmd/ai/intro.js +141 -0
  50. package/dist/cmd/ai/intro.js.map +1 -0
  51. package/dist/cmd/ai/opencode/run.d.ts.map +1 -1
  52. package/dist/cmd/ai/opencode/run.js +5 -0
  53. package/dist/cmd/ai/opencode/run.js.map +1 -1
  54. package/dist/cmd/build/ast.d.ts.map +1 -1
  55. package/dist/cmd/build/ast.js +79 -0
  56. package/dist/cmd/build/ast.js.map +1 -1
  57. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  58. package/dist/cmd/build/vite/bun-dev-server.js +2 -0
  59. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  60. package/dist/cmd/build/vite/docs-generator.d.ts.map +1 -1
  61. package/dist/cmd/build/vite/docs-generator.js +15 -1
  62. package/dist/cmd/build/vite/docs-generator.js.map +1 -1
  63. package/dist/cmd/build/vite/env-types-generator.d.ts +26 -0
  64. package/dist/cmd/build/vite/env-types-generator.d.ts.map +1 -0
  65. package/dist/cmd/build/vite/env-types-generator.js +110 -0
  66. package/dist/cmd/build/vite/env-types-generator.js.map +1 -0
  67. package/dist/cmd/build/vite/index.d.ts +2 -0
  68. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  69. package/dist/cmd/build/vite/index.js +12 -1
  70. package/dist/cmd/build/vite/index.js.map +1 -1
  71. package/dist/cmd/build/vite/public-asset-path-plugin.d.ts.map +1 -1
  72. package/dist/cmd/build/vite/public-asset-path-plugin.js.map +1 -1
  73. package/dist/cmd/build/vite/vite-builder.d.ts +2 -0
  74. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  75. package/dist/cmd/build/vite/vite-builder.js +10 -1
  76. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  77. package/dist/cmd/cloud/db/create.js.map +1 -1
  78. package/dist/cmd/cloud/db/delete.js.map +1 -1
  79. package/dist/cmd/cloud/db/get.d.ts.map +1 -1
  80. package/dist/cmd/cloud/db/get.js +27 -12
  81. package/dist/cmd/cloud/db/get.js.map +1 -1
  82. package/dist/cmd/cloud/deploy-fork.d.ts.map +1 -1
  83. package/dist/cmd/cloud/deploy-fork.js +2 -0
  84. package/dist/cmd/cloud/deploy-fork.js.map +1 -1
  85. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  86. package/dist/cmd/cloud/deploy.js +17 -0
  87. package/dist/cmd/cloud/deploy.js.map +1 -1
  88. package/dist/cmd/cloud/env/import.js.map +1 -1
  89. package/dist/cmd/cloud/env/list.js.map +1 -1
  90. package/dist/cmd/cloud/env/push.js.map +1 -1
  91. package/dist/cmd/cloud/keyvalue/util.d.ts.map +1 -1
  92. package/dist/cmd/cloud/keyvalue/util.js +3 -3
  93. package/dist/cmd/cloud/keyvalue/util.js.map +1 -1
  94. package/dist/cmd/cloud/machine/list.js +3 -3
  95. package/dist/cmd/cloud/machine/list.js.map +1 -1
  96. package/dist/cmd/cloud/region/index.js.map +1 -1
  97. package/dist/cmd/cloud/region-lookup.d.ts +7 -4
  98. package/dist/cmd/cloud/region-lookup.d.ts.map +1 -1
  99. package/dist/cmd/cloud/region-lookup.js +59 -14
  100. package/dist/cmd/cloud/region-lookup.js.map +1 -1
  101. package/dist/cmd/cloud/sandbox/cp.d.ts.map +1 -1
  102. package/dist/cmd/cloud/sandbox/cp.js +7 -5
  103. package/dist/cmd/cloud/sandbox/cp.js.map +1 -1
  104. package/dist/cmd/cloud/sandbox/create.js +2 -2
  105. package/dist/cmd/cloud/sandbox/create.js.map +1 -1
  106. package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -1
  107. package/dist/cmd/cloud/sandbox/delete.js +8 -7
  108. package/dist/cmd/cloud/sandbox/delete.js.map +1 -1
  109. package/dist/cmd/cloud/sandbox/download.d.ts.map +1 -1
  110. package/dist/cmd/cloud/sandbox/download.js +7 -5
  111. package/dist/cmd/cloud/sandbox/download.js.map +1 -1
  112. package/dist/cmd/cloud/sandbox/env.d.ts.map +1 -1
  113. package/dist/cmd/cloud/sandbox/env.js +7 -5
  114. package/dist/cmd/cloud/sandbox/env.js.map +1 -1
  115. package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
  116. package/dist/cmd/cloud/sandbox/exec.js +7 -5
  117. package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
  118. package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
  119. package/dist/cmd/cloud/sandbox/get.js +12 -7
  120. package/dist/cmd/cloud/sandbox/get.js.map +1 -1
  121. package/dist/cmd/cloud/sandbox/list.d.ts.map +1 -1
  122. package/dist/cmd/cloud/sandbox/list.js +40 -63
  123. package/dist/cmd/cloud/sandbox/list.js.map +1 -1
  124. package/dist/cmd/cloud/sandbox/ls.d.ts.map +1 -1
  125. package/dist/cmd/cloud/sandbox/ls.js +7 -5
  126. package/dist/cmd/cloud/sandbox/ls.js.map +1 -1
  127. package/dist/cmd/cloud/sandbox/mkdir.d.ts.map +1 -1
  128. package/dist/cmd/cloud/sandbox/mkdir.js +7 -5
  129. package/dist/cmd/cloud/sandbox/mkdir.js.map +1 -1
  130. package/dist/cmd/cloud/sandbox/rm.d.ts.map +1 -1
  131. package/dist/cmd/cloud/sandbox/rm.js +7 -5
  132. package/dist/cmd/cloud/sandbox/rm.js.map +1 -1
  133. package/dist/cmd/cloud/sandbox/rmdir.d.ts.map +1 -1
  134. package/dist/cmd/cloud/sandbox/rmdir.js +7 -5
  135. package/dist/cmd/cloud/sandbox/rmdir.js.map +1 -1
  136. package/dist/cmd/cloud/sandbox/run.js +1 -1
  137. package/dist/cmd/cloud/sandbox/run.js.map +1 -1
  138. package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
  139. package/dist/cmd/cloud/sandbox/snapshot/get.js.map +1 -1
  140. package/dist/cmd/cloud/sandbox/upload.d.ts.map +1 -1
  141. package/dist/cmd/cloud/sandbox/upload.js +7 -5
  142. package/dist/cmd/cloud/sandbox/upload.js.map +1 -1
  143. package/dist/cmd/cloud/sandbox/util.d.ts +2 -2
  144. package/dist/cmd/cloud/sandbox/util.d.ts.map +1 -1
  145. package/dist/cmd/cloud/sandbox/util.js +14 -13
  146. package/dist/cmd/cloud/sandbox/util.js.map +1 -1
  147. package/dist/cmd/cloud/ssh.d.ts.map +1 -1
  148. package/dist/cmd/cloud/ssh.js +3 -3
  149. package/dist/cmd/cloud/ssh.js.map +1 -1
  150. package/dist/cmd/cloud/storage/create.js.map +1 -1
  151. package/dist/cmd/cloud/storage/delete.js.map +1 -1
  152. package/dist/cmd/cloud/storage/get.d.ts.map +1 -1
  153. package/dist/cmd/cloud/storage/get.js +5 -11
  154. package/dist/cmd/cloud/storage/get.js.map +1 -1
  155. package/dist/cmd/cloud/storage/list.d.ts.map +1 -1
  156. package/dist/cmd/cloud/storage/list.js +6 -6
  157. package/dist/cmd/cloud/storage/list.js.map +1 -1
  158. package/dist/cmd/cloud/stream/create.d.ts.map +1 -1
  159. package/dist/cmd/cloud/stream/create.js +7 -4
  160. package/dist/cmd/cloud/stream/create.js.map +1 -1
  161. package/dist/cmd/cloud/stream/delete.d.ts.map +1 -1
  162. package/dist/cmd/cloud/stream/delete.js +25 -4
  163. package/dist/cmd/cloud/stream/delete.js.map +1 -1
  164. package/dist/cmd/cloud/stream/get.d.ts.map +1 -1
  165. package/dist/cmd/cloud/stream/get.js +91 -62
  166. package/dist/cmd/cloud/stream/get.js.map +1 -1
  167. package/dist/cmd/cloud/stream/list.d.ts.map +1 -1
  168. package/dist/cmd/cloud/stream/list.js +66 -38
  169. package/dist/cmd/cloud/stream/list.js.map +1 -1
  170. package/dist/cmd/cloud/stream/util.d.ts +20 -0
  171. package/dist/cmd/cloud/stream/util.d.ts.map +1 -1
  172. package/dist/cmd/cloud/stream/util.js +27 -3
  173. package/dist/cmd/cloud/stream/util.js.map +1 -1
  174. package/dist/cmd/cloud/vector/util.d.ts.map +1 -1
  175. package/dist/cmd/cloud/vector/util.js +3 -3
  176. package/dist/cmd/cloud/vector/util.js.map +1 -1
  177. package/dist/cmd/dev/index.js.map +1 -1
  178. package/dist/cmd/git/account/add.js.map +1 -1
  179. package/dist/cmd/git/list.js.map +1 -1
  180. package/dist/cmd/project/add/database.d.ts +2 -0
  181. package/dist/cmd/project/add/database.d.ts.map +1 -0
  182. package/dist/cmd/project/add/database.js +123 -0
  183. package/dist/cmd/project/add/database.js.map +1 -0
  184. package/dist/cmd/project/add/domain.d.ts +2 -0
  185. package/dist/cmd/project/add/domain.d.ts.map +1 -0
  186. package/dist/cmd/project/add/domain.js +152 -0
  187. package/dist/cmd/project/add/domain.js.map +1 -0
  188. package/dist/cmd/project/add/index.d.ts +2 -0
  189. package/dist/cmd/project/add/index.d.ts.map +1 -0
  190. package/dist/cmd/project/add/index.js +35 -0
  191. package/dist/cmd/project/add/index.js.map +1 -0
  192. package/dist/cmd/project/add/storage.d.ts +2 -0
  193. package/dist/cmd/project/add/storage.d.ts.map +1 -0
  194. package/dist/cmd/project/add/storage.js +123 -0
  195. package/dist/cmd/project/add/storage.js.map +1 -0
  196. package/dist/cmd/project/auth/init.js.map +1 -1
  197. package/dist/cmd/project/index.d.ts.map +1 -1
  198. package/dist/cmd/project/index.js +7 -0
  199. package/dist/cmd/project/index.js.map +1 -1
  200. package/dist/cmd/project/reconcile.d.ts.map +1 -1
  201. package/dist/cmd/project/reconcile.js +32 -0
  202. package/dist/cmd/project/reconcile.js.map +1 -1
  203. package/dist/cmd/support/report.js.map +1 -1
  204. package/dist/cmd/support/system.js +2 -2
  205. package/dist/cmd/support/system.js.map +1 -1
  206. package/dist/config.d.ts +6 -3
  207. package/dist/config.d.ts.map +1 -1
  208. package/dist/config.js +31 -7
  209. package/dist/config.js.map +1 -1
  210. package/dist/errors.d.ts +2 -1
  211. package/dist/errors.d.ts.map +1 -1
  212. package/dist/errors.js +5 -0
  213. package/dist/errors.js.map +1 -1
  214. package/dist/index.d.ts +4 -1
  215. package/dist/index.d.ts.map +1 -1
  216. package/dist/index.js +3 -0
  217. package/dist/index.js.map +1 -1
  218. package/dist/repl.js +2 -1
  219. package/dist/repl.js.map +1 -1
  220. package/dist/tui/box.d.ts +3 -1
  221. package/dist/tui/box.d.ts.map +1 -1
  222. package/dist/tui/box.js +22 -7
  223. package/dist/tui/box.js.map +1 -1
  224. package/dist/tui/colors.d.ts +0 -3
  225. package/dist/tui/colors.d.ts.map +1 -1
  226. package/dist/tui/colors.js +76 -23
  227. package/dist/tui/colors.js.map +1 -1
  228. package/dist/tui/prompt.d.ts +2 -0
  229. package/dist/tui/prompt.d.ts.map +1 -1
  230. package/dist/tui/prompt.js +44 -3
  231. package/dist/tui/prompt.js.map +1 -1
  232. package/dist/tui/symbols.d.ts +0 -4
  233. package/dist/tui/symbols.d.ts.map +1 -1
  234. package/dist/tui/symbols.js +5 -0
  235. package/dist/tui/symbols.js.map +1 -1
  236. package/dist/tui.d.ts +8 -0
  237. package/dist/tui.d.ts.map +1 -1
  238. package/dist/tui.js +54 -9
  239. package/dist/tui.js.map +1 -1
  240. package/dist/types.d.ts +37 -2
  241. package/dist/types.d.ts.map +1 -1
  242. package/dist/types.js +1 -0
  243. package/dist/types.js.map +1 -1
  244. package/dist/version-check.d.ts.map +1 -1
  245. package/dist/version-check.js +5 -0
  246. package/dist/version-check.js.map +1 -1
  247. package/package.json +6 -6
  248. package/src/agent-detection.ts +457 -160
  249. package/src/ai-help.ts +393 -0
  250. package/src/api.ts +1 -1
  251. package/src/auth.ts +226 -17
  252. package/src/banner.ts +5 -0
  253. package/src/cache/agent-intro.ts +62 -0
  254. package/src/cache/index.ts +2 -0
  255. package/src/cache/resource-region.ts +28 -7
  256. package/src/catalyst.ts +16 -0
  257. package/src/cli.ts +375 -93
  258. package/src/cmd/ai/detect.ts +54 -0
  259. package/src/cmd/ai/index.ts +18 -1
  260. package/src/cmd/ai/intro.ts +154 -0
  261. package/src/cmd/ai/opencode/run.ts +5 -0
  262. package/src/cmd/build/ast.ts +97 -0
  263. package/src/cmd/build/vite/bun-dev-server.ts +2 -0
  264. package/src/cmd/build/vite/docs-generator.ts +15 -1
  265. package/src/cmd/build/vite/env-types-generator.ts +145 -0
  266. package/src/cmd/build/vite/index.ts +15 -0
  267. package/src/cmd/build/vite/public-asset-path-plugin.ts +8 -2
  268. package/src/cmd/build/vite/vite-builder.ts +31 -11
  269. package/src/cmd/cloud/db/create.ts +16 -16
  270. package/src/cmd/cloud/db/delete.ts +19 -19
  271. package/src/cmd/cloud/db/get.ts +32 -17
  272. package/src/cmd/cloud/deploy-fork.ts +2 -0
  273. package/src/cmd/cloud/deploy.ts +17 -0
  274. package/src/cmd/cloud/env/import.ts +6 -6
  275. package/src/cmd/cloud/env/list.ts +11 -11
  276. package/src/cmd/cloud/env/push.ts +6 -6
  277. package/src/cmd/cloud/keyvalue/util.ts +3 -3
  278. package/src/cmd/cloud/machine/list.ts +3 -3
  279. package/src/cmd/cloud/region/index.ts +3 -3
  280. package/src/cmd/cloud/region-lookup.ts +82 -22
  281. package/src/cmd/cloud/sandbox/cp.ts +9 -4
  282. package/src/cmd/cloud/sandbox/create.ts +2 -2
  283. package/src/cmd/cloud/sandbox/delete.ts +10 -7
  284. package/src/cmd/cloud/sandbox/download.ts +8 -5
  285. package/src/cmd/cloud/sandbox/env.ts +8 -5
  286. package/src/cmd/cloud/sandbox/exec.ts +10 -5
  287. package/src/cmd/cloud/sandbox/get.ts +13 -7
  288. package/src/cmd/cloud/sandbox/list.ts +47 -73
  289. package/src/cmd/cloud/sandbox/ls.ts +9 -5
  290. package/src/cmd/cloud/sandbox/mkdir.ts +9 -5
  291. package/src/cmd/cloud/sandbox/rm.ts +9 -5
  292. package/src/cmd/cloud/sandbox/rmdir.ts +9 -5
  293. package/src/cmd/cloud/sandbox/run.ts +1 -1
  294. package/src/cmd/cloud/sandbox/snapshot/build.ts +31 -31
  295. package/src/cmd/cloud/sandbox/snapshot/get.ts +17 -17
  296. package/src/cmd/cloud/sandbox/upload.ts +8 -5
  297. package/src/cmd/cloud/sandbox/util.ts +15 -14
  298. package/src/cmd/cloud/ssh.ts +2 -4
  299. package/src/cmd/cloud/storage/create.ts +16 -16
  300. package/src/cmd/cloud/storage/delete.ts +19 -19
  301. package/src/cmd/cloud/storage/get.ts +5 -16
  302. package/src/cmd/cloud/storage/list.ts +12 -6
  303. package/src/cmd/cloud/stream/create.ts +8 -4
  304. package/src/cmd/cloud/stream/delete.ts +28 -4
  305. package/src/cmd/cloud/stream/get.ts +102 -64
  306. package/src/cmd/cloud/stream/list.ts +76 -44
  307. package/src/cmd/cloud/stream/util.ts +39 -3
  308. package/src/cmd/cloud/vector/util.ts +3 -3
  309. package/src/cmd/dev/index.ts +4 -4
  310. package/src/cmd/git/account/add.ts +5 -5
  311. package/src/cmd/git/list.ts +7 -7
  312. package/src/cmd/project/add/database.ts +145 -0
  313. package/src/cmd/project/add/domain.ts +181 -0
  314. package/src/cmd/project/add/index.ts +35 -0
  315. package/src/cmd/project/add/storage.ts +147 -0
  316. package/src/cmd/project/auth/init.ts +6 -6
  317. package/src/cmd/project/index.ts +7 -0
  318. package/src/cmd/project/reconcile.ts +40 -0
  319. package/src/cmd/support/report.ts +5 -5
  320. package/src/cmd/support/system.ts +2 -2
  321. package/src/config.ts +40 -12
  322. package/src/errors.ts +7 -0
  323. package/src/index.ts +11 -0
  324. package/src/repl.ts +4 -1
  325. package/src/tui/box.ts +24 -9
  326. package/src/tui/colors.ts +83 -26
  327. package/src/tui/prompt.ts +55 -3
  328. package/src/tui/symbols.ts +6 -0
  329. package/src/tui.ts +55 -9
  330. package/src/types.ts +46 -2
  331. package/src/version-check.ts +6 -0
@@ -0,0 +1,147 @@
1
+ import { z } from 'zod';
2
+ import { listResources } from '@agentuity/server';
3
+ import { createSubcommand } from '../../../types';
4
+ import * as tui from '../../../tui';
5
+ import { createPrompt } from '../../../tui';
6
+ import { getCatalystAPIClient } from '../../../config';
7
+ import { getCommand } from '../../../command-prefix';
8
+ import { isDryRunMode, outputDryRun } from '../../../explain';
9
+ import { ErrorCode } from '../../../errors';
10
+ import { addResourceEnvVars } from '../../../env-util';
11
+
12
+ export const storageSubcommand = createSubcommand({
13
+ name: 'storage',
14
+ aliases: ['bucket', 's3'],
15
+ description: 'Link an existing storage bucket to the current project',
16
+ tags: ['mutating', 'fast', 'requires-auth', 'requires-project'],
17
+ idempotent: true,
18
+ requires: { auth: true, org: true, region: true, project: true },
19
+ examples: [
20
+ {
21
+ command: getCommand('project add storage'),
22
+ description: 'Select a storage bucket interactively',
23
+ },
24
+ {
25
+ command: getCommand('project add bucket my-bucket'),
26
+ description: 'Link a specific bucket by name',
27
+ },
28
+ {
29
+ command: getCommand('--dry-run project add storage my-bucket'),
30
+ description: 'Preview linking without making changes',
31
+ },
32
+ ],
33
+ schema: {
34
+ args: z.object({
35
+ name: z.string().optional().describe('Storage bucket name to link'),
36
+ }),
37
+ options: z.object({}),
38
+ response: z.object({
39
+ success: z.boolean().describe('Whether linking succeeded'),
40
+ name: z.string().describe('Linked bucket name'),
41
+ }),
42
+ },
43
+
44
+ async handler(ctx) {
45
+ const { logger, args, orgId, region, auth, options, projectDir } = ctx;
46
+
47
+ if (isDryRunMode(options)) {
48
+ const message = args.name
49
+ ? `Would link storage bucket "${args.name}" to project in ${projectDir}`
50
+ : `Would prompt to select a storage bucket to link to project in ${projectDir}`;
51
+ outputDryRun(message, options);
52
+ if (!options.json) {
53
+ tui.newline();
54
+ tui.info('[DRY RUN] Storage linking skipped');
55
+ }
56
+ return {
57
+ success: false,
58
+ name: args.name || 'dry-run-bucket',
59
+ };
60
+ }
61
+
62
+ const catalystClient = getCatalystAPIClient(logger, auth, region);
63
+
64
+ const resources = await tui.spinner({
65
+ message: 'Fetching storage buckets',
66
+ clearOnSuccess: true,
67
+ callback: async () => {
68
+ return listResources(catalystClient, orgId, region);
69
+ },
70
+ });
71
+
72
+ const availableBuckets = resources.s3.filter((bucket) => !bucket.internal);
73
+
74
+ if (availableBuckets.length === 0) {
75
+ tui.fatal(
76
+ 'No storage buckets available. Create one first with: ' +
77
+ tui.bold(getCommand('cloud storage create')),
78
+ ErrorCode.RESOURCE_NOT_FOUND
79
+ );
80
+ }
81
+
82
+ let selectedBucket: (typeof availableBuckets)[0] | undefined;
83
+
84
+ if (args.name) {
85
+ selectedBucket = availableBuckets.find((bucket) => bucket.bucket_name === args.name);
86
+ if (!selectedBucket) {
87
+ const availableNames = availableBuckets.map((bucket) => bucket.bucket_name).join(', ');
88
+ tui.fatal(
89
+ `Storage bucket "${args.name}" not found. Available buckets: ${availableNames}`,
90
+ ErrorCode.RESOURCE_NOT_FOUND
91
+ );
92
+ }
93
+ } else {
94
+ const isHeadless = !process.stdin.isTTY || !process.stdout.isTTY;
95
+ if (isHeadless) {
96
+ tui.fatal(
97
+ 'Bucket name is required in non-interactive mode. Usage: ' +
98
+ tui.bold(getCommand('project add storage <name>')),
99
+ ErrorCode.MISSING_ARGUMENT
100
+ );
101
+ }
102
+
103
+ const prompt = createPrompt();
104
+ const selected = await prompt.select<string>({
105
+ message: 'Select a storage bucket to link',
106
+ options: availableBuckets.map((bucket) => ({
107
+ value: bucket.bucket_name,
108
+ label: `${tui.tuiColors.primary(bucket.bucket_name)}`,
109
+ })),
110
+ });
111
+
112
+ // Ensure stdin is paused so process can exit
113
+ if (process.stdin.isTTY) {
114
+ process.stdin.pause();
115
+ }
116
+
117
+ if (!selected) {
118
+ tui.fatal('Operation cancelled', ErrorCode.USER_CANCELLED);
119
+ }
120
+
121
+ selectedBucket = availableBuckets.find((bucket) => bucket.bucket_name === selected);
122
+ }
123
+
124
+ if (!selectedBucket) {
125
+ tui.fatal('Failed to select storage bucket', ErrorCode.INTERNAL_ERROR);
126
+ }
127
+
128
+ if (selectedBucket.env && Object.keys(selectedBucket.env).length > 0) {
129
+ await addResourceEnvVars(projectDir, selectedBucket.env);
130
+ if (!options.json) {
131
+ tui.success(`Linked storage bucket: ${tui.bold(selectedBucket.bucket_name)}`);
132
+ tui.info('Environment variables written to .env');
133
+ }
134
+ } else {
135
+ if (!options.json) {
136
+ tui.warning(
137
+ `Storage bucket "${selectedBucket.bucket_name}" has no environment variables to add`
138
+ );
139
+ }
140
+ }
141
+
142
+ return {
143
+ success: true,
144
+ name: selectedBucket.bucket_name,
145
+ };
146
+ },
147
+ });
@@ -73,14 +73,14 @@ export const initSubcommand = createSubcommand({
73
73
  if (!databaseUrl) {
74
74
  // Check .env file
75
75
  const envPath = path.join(projectDir, '.env');
76
- if (fs.existsSync(envPath)) {
77
- const envContent = fs.readFileSync(envPath, 'utf-8');
78
- const match = envContent.match(/^DATABASE_URL=(.+)$/m);
79
- if (match?.[1]) {
80
- databaseUrl = match[1].trim().replace(/^["']|["']$/g, '');
76
+ if (fs.existsSync(envPath)) {
77
+ const envContent = fs.readFileSync(envPath, 'utf-8');
78
+ const match = envContent.match(/^DATABASE_URL=(.+)$/m);
79
+ if (match?.[1]) {
80
+ databaseUrl = match[1].trim().replace(/^["']|["']$/g, '');
81
+ }
81
82
  }
82
83
  }
83
- }
84
84
 
85
85
  // Show database picker (with existing as first option if configured)
86
86
  const dbInfo = await selectOrCreateDatabase({
@@ -5,6 +5,7 @@ import { listSubcommand } from './list';
5
5
  import { deleteSubcommand } from './delete';
6
6
  import { showSubcommand } from './show';
7
7
  import { authCommand } from './auth';
8
+ import { addCommand } from './add';
8
9
  import { getCommand } from '../../command-prefix';
9
10
 
10
11
  export const command = createCommand({
@@ -16,6 +17,11 @@ export const command = createCommand({
16
17
  { command: getCommand('project import'), description: 'Import an existing project' },
17
18
  { command: getCommand('project list'), description: 'List all projects' },
18
19
  { command: getCommand('project auth init'), description: 'Set up Agentuity Auth' },
20
+ { command: getCommand('project add database'), description: 'Link an existing database' },
21
+ {
22
+ command: getCommand('project add storage'),
23
+ description: 'Link an existing storage bucket',
24
+ },
19
25
  ],
20
26
  subcommands: [
21
27
  createProjectSubcommand,
@@ -24,5 +30,6 @@ export const command = createCommand({
24
30
  deleteSubcommand,
25
31
  showSubcommand,
26
32
  authCommand,
33
+ addCommand,
27
34
  ],
28
35
  });
@@ -222,6 +222,30 @@ async function selectRegion(regions: RegionList, defaultRegion?: string): Promis
222
222
  return firstRegion.region;
223
223
  }
224
224
 
225
+ // Check for non-interactive mode before prompting
226
+ const isNonInteractive = !process.stdin.isTTY || !process.stdout.isTTY;
227
+ if (isNonInteractive) {
228
+ // In non-interactive mode, validate defaultRegion against available regions
229
+ if (defaultRegion) {
230
+ const isValidRegion = regions.some((r) => r.region === defaultRegion);
231
+ if (isValidRegion) {
232
+ return defaultRegion;
233
+ }
234
+ const supportedRegions = regions.map((r) => r.region).join(', ');
235
+ tui.fatal(
236
+ `Region "${defaultRegion}" is not supported. ` +
237
+ `Available regions: ${supportedRegions}. ` +
238
+ 'Use --region flag or set AGENTUITY_REGION environment variable with a valid region.'
239
+ );
240
+ }
241
+ const supportedRegions = regions.map((r) => r.region).join(', ');
242
+ tui.fatal(
243
+ 'Cannot select region in non-interactive mode. ' +
244
+ `Available regions: ${supportedRegions}. ` +
245
+ 'Use --region flag or set AGENTUITY_REGION environment variable.'
246
+ );
247
+ }
248
+
225
249
  // Build options from API regions
226
250
  const options = regions.map((r) => ({
227
251
  value: r.region,
@@ -255,6 +279,22 @@ async function textPrompt(options: {
255
279
  initial?: string;
256
280
  validate?: (value: string) => boolean | string;
257
281
  }): Promise<string> {
282
+ // Check for non-interactive mode before prompting
283
+ const isNonInteractive = !process.stdin.isTTY || !process.stdout.isTTY;
284
+ if (isNonInteractive) {
285
+ // In non-interactive mode, use initial value if available and valid
286
+ if (options.initial) {
287
+ const validationResult = options.validate?.(options.initial);
288
+ if (validationResult === true || validationResult === undefined) {
289
+ return options.initial;
290
+ }
291
+ }
292
+ tui.fatal(
293
+ 'Cannot prompt for input in non-interactive mode. ' +
294
+ 'Use --name flag to specify the project name.'
295
+ );
296
+ }
297
+
258
298
  const prompt = createPrompt();
259
299
  return prompt.text({
260
300
  message: options.message,
@@ -335,11 +335,11 @@ export default createSubcommand({
335
335
  // Debug: log the response
336
336
  logger.debug('Upload response received', { uploadResponse });
337
337
 
338
- if (!uploadResponse.success) {
339
- const errorMsg = uploadResponse.message || 'Failed to create upload URL';
340
- logger.error('Upload URL creation failed', { uploadResponse, errorMsg });
341
- throw new UploadUrlCreationError({ message: errorMsg });
342
- }
338
+ if (!uploadResponse.success) {
339
+ const errorMsg = uploadResponse.message || 'Failed to create upload URL';
340
+ logger.error('Upload URL creation failed', { uploadResponse, errorMsg });
341
+ throw new UploadUrlCreationError({ message: errorMsg });
342
+ }
343
343
 
344
344
  const { presigned_url, url: reportUrl, report_id: reportId } = uploadResponse.data;
345
345
 
@@ -7,7 +7,7 @@ import { getLatestLogSession } from '../../internal-logger';
7
7
  import * as tui from '../../tui';
8
8
  import { getVersion, getPackageName } from '../../version';
9
9
  import { getAuth } from '../../config';
10
- import { isExecutingFromAgent } from '../../agent-detection';
10
+ import { getExecutingAgent } from '../../agent-detection';
11
11
 
12
12
  const argsSchema = z.object({});
13
13
 
@@ -77,7 +77,7 @@ export default createSubcommand({
77
77
  }
78
78
 
79
79
  // Get detected agent (if any)
80
- const detectedAgent = await isExecutingFromAgent();
80
+ const detectedAgent = getExecutingAgent();
81
81
 
82
82
  // Gather system information
83
83
  const systemInfo = {
package/src/config.ts CHANGED
@@ -1,12 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  import { existsSync, mkdirSync } from 'node:fs';
3
3
  import { StructuredError, type Logger } from '@agentuity/core';
4
- import {
5
- BuildMetadataSchema,
6
- type BuildMetadata,
7
- getServiceUrls,
8
- APIClient as ServerAPIClient,
9
- } from '@agentuity/server';
4
+ import { BuildMetadataSchema, type BuildMetadata, getServiceUrls } from '@agentuity/server';
5
+ import { APIClient as ServerAPIClient } from '@agentuity/server';
10
6
  import { YAML } from 'bun';
11
7
  import { join, extname, basename, resolve, normalize } from 'node:path';
12
8
  import { homedir } from 'node:os';
@@ -15,6 +11,7 @@ import JSON5 from 'json5';
15
11
  import type { Config, Profile, AuthData } from './types';
16
12
  import { ConfigSchema, ProjectSchema } from './types';
17
13
  import * as tui from './tui';
14
+ import { getCatalystUrl } from './catalyst';
18
15
  import {
19
16
  isMacOS,
20
17
  saveAuthToKeychain,
@@ -51,8 +48,21 @@ export async function saveProfile(path: string): Promise<void> {
51
48
  await writeFile(getProfilePath(), path, { mode: 0o600 });
52
49
  }
53
50
 
54
- export async function getProfile(): Promise<string> {
55
- // Check environment variable first
51
+ export async function getProfile(profileFromFlag?: string): Promise<string> {
52
+ // Check --profile flag first (highest priority)
53
+ if (profileFromFlag) {
54
+ const flagProfilePath = join(getDefaultConfigDir(), `${profileFromFlag}.yaml`);
55
+ const flagFile = Bun.file(flagProfilePath);
56
+ if (await flagFile.exists()) {
57
+ return flagProfilePath;
58
+ }
59
+ // If --profile flag was explicitly provided but file doesn't exist, throw an error
60
+ throw new Error(
61
+ `Profile '${profileFromFlag}' not found. Expected file at: ${flagProfilePath}`
62
+ );
63
+ }
64
+
65
+ // Check environment variable second
56
66
  if (process.env.AGENTUITY_PROFILE) {
57
67
  const profileName = process.env.AGENTUITY_PROFILE;
58
68
  const envProfilePath = join(getDefaultConfigDir(), `${profileName}.yaml`);
@@ -127,12 +137,16 @@ function expandTilde(path: string): string {
127
137
 
128
138
  let cachedConfig: Config | null | undefined;
129
139
 
130
- export async function loadConfig(customPath?: string, skipCache = false): Promise<Config | null> {
140
+ export async function loadConfig(
141
+ customPath?: string,
142
+ skipCache = false,
143
+ profileFromFlag?: string
144
+ ): Promise<Config | null> {
131
145
  // Use cache if available and not skipped
132
146
  if (!skipCache && cachedConfig !== undefined) {
133
147
  return cachedConfig;
134
148
  }
135
- const configPath = customPath ? expandTilde(customPath) : await getProfile();
149
+ const configPath = customPath ? expandTilde(customPath) : await getProfile(profileFromFlag);
136
150
 
137
151
  try {
138
152
  const file = Bun.file(configPath);
@@ -359,6 +373,13 @@ export async function saveOrgId(orgId: string): Promise<void> {
359
373
  await saveConfig(config);
360
374
  }
361
375
 
376
+ export async function saveProjectId(projectId: string): Promise<void> {
377
+ const config = await getOrInitConfig();
378
+ config.preferences = config.preferences || {};
379
+ (config.preferences as Record<string, unknown>).projectId = projectId;
380
+ await saveConfig(config);
381
+ }
382
+
362
383
  export async function clearOrgId(): Promise<void> {
363
384
  const config = await getOrInitConfig();
364
385
  if (config.preferences) {
@@ -367,6 +388,14 @@ export async function clearOrgId(): Promise<void> {
367
388
  }
368
389
  }
369
390
 
391
+ export async function clearProjectId(): Promise<void> {
392
+ const config = await getOrInitConfig();
393
+ if (config.preferences) {
394
+ delete (config.preferences as Record<string, unknown>).projectId;
395
+ await saveConfig(config);
396
+ }
397
+ }
398
+
370
399
  export async function saveRegion(region: string): Promise<void> {
371
400
  const config = await getOrInitConfig();
372
401
  config.preferences = config.preferences || {};
@@ -739,8 +768,7 @@ export function getCatalystAPIClient(
739
768
  region: string,
740
769
  orgId?: string
741
770
  ) {
742
- const serviceUrls = getServiceUrls(region);
743
- const catalystUrl = serviceUrls.catalyst;
771
+ const catalystUrl = getCatalystUrl(region);
744
772
  const headers: Record<string, string> = {};
745
773
  if (orgId) {
746
774
  headers['x-agentuity-orgid'] = orgId;
package/src/errors.ts CHANGED
@@ -82,6 +82,9 @@ export enum ErrorCode {
82
82
 
83
83
  // Upgrade of the software is required to continue
84
84
  UPGRADE_REQUIRED = 'UPGRADE_REQUIRED',
85
+
86
+ // Payment required - user needs to upgrade their plan
87
+ PAYMENT_REQUIRED = 'PAYMENT_REQUIRED',
85
88
  }
86
89
 
87
90
  /**
@@ -147,6 +150,10 @@ export function getExitCode(errorCode: ErrorCode): ExitCode {
147
150
  case ErrorCode.MALWARE_DETECTED:
148
151
  return ExitCode.SECURITY_ERROR;
149
152
 
153
+ // Payment required - user needs to upgrade their plan
154
+ case ErrorCode.PAYMENT_REQUIRED:
155
+ return ExitCode.GENERAL_ERROR;
156
+
150
157
  // Resource conflicts and other errors
151
158
  case ErrorCode.RESOURCE_ALREADY_EXISTS:
152
159
  case ErrorCode.RESOURCE_CONFLICT:
package/src/index.ts CHANGED
@@ -1,4 +1,13 @@
1
1
  export { createCLI, registerCommands } from './cli';
2
+ export { generateAIHelp, type DashdashConfig } from './ai-help';
3
+ export {
4
+ getExecutingAgent,
5
+ getAgentEnv,
6
+ getAgentDisplayName,
7
+ KNOWN_AGENTS,
8
+ AGENT_DISPLAY_NAMES,
9
+ type KnownAgent,
10
+ } from './agent-detection';
2
11
  export { validateRuntime, isBun } from './runtime';
3
12
  export { ensureBunOnPath } from './bun-path';
4
13
  export { isGitAvailable, getDefaultBranch } from './git-helper';
@@ -73,6 +82,7 @@ export {
73
82
  getAuth,
74
83
  } from './config';
75
84
  export { APIClient, getAPIBaseURL, getAppBaseURL } from './api';
85
+ export { getCatalystUrl } from './catalyst';
76
86
  export {
77
87
  ConsoleLogger,
78
88
  createLogger,
@@ -111,6 +121,7 @@ export type {
111
121
  Profile,
112
122
  AuthData,
113
123
  CommandSchemas,
124
+ ResourceSelectionRule,
114
125
  BuildPhase,
115
126
  BuildContext,
116
127
  BuildConfig,
package/src/repl.ts CHANGED
@@ -1030,7 +1030,10 @@ async function readLine(
1030
1030
  const searchHistory = (query: string, startFrom: number): number => {
1031
1031
  for (let i = startFrom - 1; i >= 0; i--) {
1032
1032
  const historyEntry = history[i];
1033
- if (historyEntry !== undefined && historyEntry.toLowerCase().includes(query.toLowerCase())) {
1033
+ if (
1034
+ historyEntry !== undefined &&
1035
+ historyEntry.toLowerCase().includes(query.toLowerCase())
1036
+ ) {
1034
1037
  return i;
1035
1038
  }
1036
1039
  }
package/src/tui/box.ts CHANGED
@@ -201,8 +201,10 @@ export function note(message: string, title = ''): void {
201
201
 
202
202
  /**
203
203
  * Draw an error box with red border
204
+ * @param withGuide - If true (default), shows guide bar at top and connector at bottom for use in flows.
205
+ * If false, renders as a standalone box with proper corners.
204
206
  */
205
- export function errorBox(title: string, message: string): void {
207
+ export function errorBox(title: string, message: string, withGuide = true): void {
206
208
  const termWidth = getTerminalWidth();
207
209
  const maxWidth = termWidth - 3;
208
210
  const boxWidth = Math.min(60, maxWidth);
@@ -212,15 +214,22 @@ export function errorBox(title: string, message: string): void {
212
214
 
213
215
  const lines: string[] = [];
214
216
 
215
- // Title line with error symbol
216
- const errorSymbol = colors.error('✗');
217
+ // Top border with title
218
+ const errorSymbol = colors.error(symbols.error);
217
219
  const titleText = colors.error(title);
218
220
  const titleTextWidth = 1 + stringWidth(title); // symbol + title
219
221
  const barsNeeded = Math.max(innerWidth - titleTextWidth - 3, 1);
220
- const titleLine = `${errorSymbol} ${titleText} ${colors.error(symbols.barH.repeat(barsNeeded) + symbols.cornerTR)}`;
221
222
 
222
- lines.push(colors.error(symbols.bar));
223
- lines.push(titleLine);
223
+ if (withGuide) {
224
+ // Guide style: bar at top, then title line without top-left corner
225
+ lines.push(colors.error(symbols.bar));
226
+ const titleLine = `${errorSymbol} ${titleText} ${colors.error(symbols.barH.repeat(barsNeeded) + symbols.cornerTR)}`;
227
+ lines.push(titleLine);
228
+ } else {
229
+ // Standalone style: title line with top-left corner
230
+ const titleLine = `${colors.error(symbols.cornerTL)}${errorSymbol} ${titleText} ${colors.error(symbols.barH.repeat(barsNeeded) + symbols.cornerTR)}`;
231
+ lines.push(titleLine);
232
+ }
224
233
 
225
234
  // Empty line
226
235
  const emptyLine = `${colors.error(symbols.bar)}${' '.repeat(contentWidth)}${colors.error(symbols.bar)}`;
@@ -244,9 +253,15 @@ export function errorBox(title: string, message: string): void {
244
253
  lines.push(emptyLine);
245
254
 
246
255
  // Bottom border
247
- lines.push(
248
- colors.error(symbols.connect + symbols.barH.repeat(innerWidth - 1) + symbols.cornerBR)
249
- );
256
+ if (withGuide) {
257
+ lines.push(
258
+ colors.error(symbols.connect + symbols.barH.repeat(innerWidth - 1) + symbols.cornerBR)
259
+ );
260
+ } else {
261
+ lines.push(
262
+ colors.error(symbols.cornerBL + symbols.barH.repeat(innerWidth - 1) + symbols.cornerBR)
263
+ );
264
+ }
250
265
 
251
266
  console.log(lines.join('\n'));
252
267
  }
package/src/tui/colors.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Color utilities for TUI components using existing tui.ts color system
3
3
  */
4
+ import { getExecutingAgent } from '../agent-detection';
4
5
 
5
6
  // ANSI escape codes for additional colors not in main tui.ts
6
7
  const RESET = '\x1b[0m';
@@ -17,6 +18,36 @@ const BG_CYAN = '\x1b[46m';
17
18
  const BLACK = '\x1b[30m';
18
19
  const WHITE = '\x1b[37m';
19
20
 
21
+ /**
22
+ * Check if colors should be used.
23
+ * Disabled for: AI agents, CI, NO_COLOR, dumb terminals, non-TTY, piped output.
24
+ * FORCE_COLOR=1 overrides all checks.
25
+ */
26
+ function shouldUseColors(): boolean {
27
+ // FORCE_COLOR overrides all checks
28
+ if (process.env.FORCE_COLOR === '1') {
29
+ return true;
30
+ }
31
+ // Disable for AI coding agents
32
+ if (getExecutingAgent()) {
33
+ return false;
34
+ }
35
+ // Disable for NO_COLOR, CI, dumb terminals, or non-TTY
36
+ if (process.env.NO_COLOR) {
37
+ return false;
38
+ }
39
+ if (process.env.CI) {
40
+ return false;
41
+ }
42
+ if (process.env.TERM === 'dumb') {
43
+ return false;
44
+ }
45
+ if (!process.stdout.isTTY) {
46
+ return false;
47
+ }
48
+ return true;
49
+ }
50
+
20
51
  /**
21
52
  * Detect if terminal is in dark mode
22
53
  */
@@ -27,29 +58,55 @@ function isDarkMode(): boolean {
27
58
  return true;
28
59
  }
29
60
 
30
- export const colors = {
31
- // State colors - using simple ANSI codes (consistent with tui.ts approach)
32
- active: (text: string) => `${CYAN}${text}${RESET}`,
33
- completed: (text: string) => `${GRAY}${text}${RESET}`,
34
- error: (text: string) => `${RED}${text}${RESET}`,
35
- warning: (text: string) => `${YELLOW}${text}${RESET}`,
36
- success: (text: string) => `${GREEN}${text}${RESET}`,
37
- info: (text: string) => `${BLUE}${text}${RESET}`,
38
-
39
- // Text formatting
40
- muted: (text: string) => `${DIM}${text}${RESET}`,
41
- bold: (text: string) => `${BOLD}${text}${RESET}`,
42
- underline: (text: string) => `${UNDERLINE}${text}${RESET}`,
43
- reset: (text: string) => `${RESET}${text}`,
44
-
45
- // Semantic colors
46
- primary: (text: string) => `${CYAN}${text}${RESET}`,
47
- secondary: (text: string) => `${GRAY}${text}${RESET}`,
48
- link: (text: string) => `${CYAN}${UNDERLINE}${text}${RESET}`,
49
-
50
- // Inversed colors (adapt to light/dark mode)
51
- inverseCyan: (text: string) => {
52
- const dark = isDarkMode();
53
- return dark ? `${BG_CYAN}${BLACK}${text}${RESET}` : `${BG_CYAN}${WHITE}${text}${RESET}`;
54
- },
55
- };
61
+ // No-op color function for when colors are disabled
62
+ const noColor = (text: string) => text;
63
+
64
+ function createColors() {
65
+ if (!shouldUseColors()) {
66
+ return {
67
+ active: noColor,
68
+ completed: noColor,
69
+ error: noColor,
70
+ warning: noColor,
71
+ success: noColor,
72
+ info: noColor,
73
+ muted: noColor,
74
+ bold: noColor,
75
+ underline: noColor,
76
+ reset: noColor,
77
+ primary: noColor,
78
+ secondary: noColor,
79
+ link: noColor,
80
+ inverseCyan: noColor,
81
+ };
82
+ }
83
+
84
+ return {
85
+ // State colors - using simple ANSI codes (consistent with tui.ts approach)
86
+ active: (text: string) => `${CYAN}${text}${RESET}`,
87
+ completed: (text: string) => `${GRAY}${text}${RESET}`,
88
+ error: (text: string) => `${RED}${text}${RESET}`,
89
+ warning: (text: string) => `${YELLOW}${text}${RESET}`,
90
+ success: (text: string) => `${GREEN}${text}${RESET}`,
91
+ info: (text: string) => `${BLUE}${text}${RESET}`,
92
+
93
+ // Text formatting
94
+ muted: (text: string) => `${DIM}${text}${RESET}`,
95
+ bold: (text: string) => `${BOLD}${text}${RESET}`,
96
+ underline: (text: string) => `${UNDERLINE}${text}${RESET}`,
97
+ reset: (text: string) => `${RESET}${text}`,
98
+
99
+ // Semantic colors
100
+ primary: (text: string) => `${CYAN}${text}${RESET}`,
101
+ secondary: (text: string) => `${GRAY}${text}${RESET}`,
102
+ link: (text: string) => `${CYAN}${UNDERLINE}${text}${RESET}`,
103
+
104
+ // Inversed colors (adapt to light/dark mode)
105
+ inverseCyan: (text: string) => {
106
+ const dark = isDarkMode();
107
+ return dark ? `${BG_CYAN}${BLACK}${text}${RESET}` : `${BG_CYAN}${WHITE}${text}${RESET}`;
108
+ },
109
+ };
110
+ }
111
+
112
+ export const colors = createColors();