@agentuity/cli 0.0.48 → 0.0.50

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 (282) hide show
  1. package/bin/cli.ts +26 -5
  2. package/dist/banner.d.ts +1 -1
  3. package/dist/banner.d.ts.map +1 -1
  4. package/dist/cli-logger.d.ts +27 -0
  5. package/dist/cli-logger.d.ts.map +1 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cmd/agents/index.d.ts +2 -0
  8. package/dist/cmd/agents/index.d.ts.map +1 -0
  9. package/dist/cmd/auth/index.d.ts.map +1 -1
  10. package/dist/cmd/auth/login.d.ts.map +1 -1
  11. package/dist/cmd/auth/logout.d.ts.map +1 -1
  12. package/dist/cmd/auth/signup.d.ts.map +1 -1
  13. package/dist/cmd/auth/ssh/add.d.ts.map +1 -1
  14. package/dist/cmd/auth/ssh/delete.d.ts.map +1 -1
  15. package/dist/cmd/auth/ssh/index.d.ts +1 -2
  16. package/dist/cmd/auth/ssh/index.d.ts.map +1 -1
  17. package/dist/cmd/auth/ssh/list.d.ts.map +1 -1
  18. package/dist/cmd/auth/whoami.d.ts.map +1 -1
  19. package/dist/cmd/bundle/ast.d.ts +3 -1
  20. package/dist/cmd/bundle/ast.d.ts.map +1 -1
  21. package/dist/cmd/bundle/index.d.ts.map +1 -1
  22. package/dist/cmd/bundle/plugin.d.ts.map +1 -1
  23. package/dist/cmd/capabilities/index.d.ts +4 -0
  24. package/dist/cmd/capabilities/index.d.ts.map +1 -0
  25. package/dist/cmd/capabilities/show.d.ts +20 -0
  26. package/dist/cmd/capabilities/show.d.ts.map +1 -0
  27. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  28. package/dist/cmd/cloud/deployment/index.d.ts.map +1 -1
  29. package/dist/cmd/cloud/deployment/list.d.ts.map +1 -1
  30. package/dist/cmd/cloud/deployment/remove.d.ts.map +1 -1
  31. package/dist/cmd/cloud/deployment/rollback.d.ts.map +1 -1
  32. package/dist/cmd/cloud/deployment/show.d.ts.map +1 -1
  33. package/dist/cmd/cloud/deployment/undeploy.d.ts.map +1 -1
  34. package/dist/cmd/cloud/deployment/utils.d.ts +4 -2
  35. package/dist/cmd/cloud/deployment/utils.d.ts.map +1 -1
  36. package/dist/cmd/cloud/domain.d.ts.map +1 -1
  37. package/dist/cmd/cloud/index.d.ts.map +1 -1
  38. package/dist/cmd/cloud/resource/add.d.ts.map +1 -1
  39. package/dist/cmd/cloud/resource/delete.d.ts.map +1 -1
  40. package/dist/cmd/cloud/resource/index.d.ts +1 -2
  41. package/dist/cmd/cloud/resource/index.d.ts.map +1 -1
  42. package/dist/cmd/cloud/resource/list.d.ts.map +1 -1
  43. package/dist/cmd/cloud/scp/download.d.ts.map +1 -1
  44. package/dist/cmd/cloud/scp/index.d.ts +1 -2
  45. package/dist/cmd/cloud/scp/index.d.ts.map +1 -1
  46. package/dist/cmd/cloud/scp/upload.d.ts.map +1 -1
  47. package/dist/cmd/cloud/session/get.d.ts +2 -0
  48. package/dist/cmd/cloud/session/get.d.ts.map +1 -0
  49. package/dist/cmd/cloud/session/index.d.ts +2 -0
  50. package/dist/cmd/cloud/session/index.d.ts.map +1 -0
  51. package/dist/cmd/cloud/session/list.d.ts +2 -0
  52. package/dist/cmd/cloud/session/list.d.ts.map +1 -0
  53. package/dist/cmd/cloud/session/logs.d.ts +2 -0
  54. package/dist/cmd/cloud/session/logs.d.ts.map +1 -0
  55. package/dist/cmd/cloud/ssh.d.ts.map +1 -1
  56. package/dist/cmd/dev/agents.d.ts +2 -0
  57. package/dist/cmd/dev/agents.d.ts.map +1 -0
  58. package/dist/cmd/dev/index.d.ts.map +1 -1
  59. package/dist/cmd/dev/sync.d.ts +12 -0
  60. package/dist/cmd/dev/sync.d.ts.map +1 -0
  61. package/dist/cmd/env/delete.d.ts.map +1 -1
  62. package/dist/cmd/env/get.d.ts.map +1 -1
  63. package/dist/cmd/env/import.d.ts.map +1 -1
  64. package/dist/cmd/env/index.d.ts.map +1 -1
  65. package/dist/cmd/env/list.d.ts.map +1 -1
  66. package/dist/cmd/env/pull.d.ts.map +1 -1
  67. package/dist/cmd/env/push.d.ts.map +1 -1
  68. package/dist/cmd/env/set.d.ts.map +1 -1
  69. package/dist/cmd/index.d.ts.map +1 -1
  70. package/dist/cmd/kv/create-namespace.d.ts +3 -0
  71. package/dist/cmd/kv/create-namespace.d.ts.map +1 -0
  72. package/dist/cmd/kv/delete-namespace.d.ts +3 -0
  73. package/dist/cmd/kv/delete-namespace.d.ts.map +1 -0
  74. package/dist/cmd/kv/delete.d.ts +3 -0
  75. package/dist/cmd/kv/delete.d.ts.map +1 -0
  76. package/dist/cmd/kv/get.d.ts +3 -0
  77. package/dist/cmd/kv/get.d.ts.map +1 -0
  78. package/dist/cmd/kv/index.d.ts +2 -0
  79. package/dist/cmd/kv/index.d.ts.map +1 -0
  80. package/dist/cmd/kv/keys.d.ts +3 -0
  81. package/dist/cmd/kv/keys.d.ts.map +1 -0
  82. package/dist/cmd/kv/list-namespaces.d.ts +3 -0
  83. package/dist/cmd/kv/list-namespaces.d.ts.map +1 -0
  84. package/dist/cmd/kv/repl.d.ts +3 -0
  85. package/dist/cmd/kv/repl.d.ts.map +1 -0
  86. package/dist/cmd/kv/search.d.ts +3 -0
  87. package/dist/cmd/kv/search.d.ts.map +1 -0
  88. package/dist/cmd/kv/set.d.ts +3 -0
  89. package/dist/cmd/kv/set.d.ts.map +1 -0
  90. package/dist/cmd/kv/stats.d.ts +3 -0
  91. package/dist/cmd/kv/stats.d.ts.map +1 -0
  92. package/dist/cmd/kv/util.d.ts +8 -0
  93. package/dist/cmd/kv/util.d.ts.map +1 -0
  94. package/dist/cmd/objectstore/delete-bucket.d.ts +3 -0
  95. package/dist/cmd/objectstore/delete-bucket.d.ts.map +1 -0
  96. package/dist/cmd/objectstore/delete.d.ts +3 -0
  97. package/dist/cmd/objectstore/delete.d.ts.map +1 -0
  98. package/dist/cmd/objectstore/get.d.ts +3 -0
  99. package/dist/cmd/objectstore/get.d.ts.map +1 -0
  100. package/dist/cmd/objectstore/index.d.ts +2 -0
  101. package/dist/cmd/objectstore/index.d.ts.map +1 -0
  102. package/dist/cmd/objectstore/list-buckets.d.ts +3 -0
  103. package/dist/cmd/objectstore/list-buckets.d.ts.map +1 -0
  104. package/dist/cmd/objectstore/list-keys.d.ts +3 -0
  105. package/dist/cmd/objectstore/list-keys.d.ts.map +1 -0
  106. package/dist/cmd/objectstore/put.d.ts +3 -0
  107. package/dist/cmd/objectstore/put.d.ts.map +1 -0
  108. package/dist/cmd/objectstore/repl.d.ts +3 -0
  109. package/dist/cmd/objectstore/repl.d.ts.map +1 -0
  110. package/dist/cmd/objectstore/url.d.ts +3 -0
  111. package/dist/cmd/objectstore/url.d.ts.map +1 -0
  112. package/dist/cmd/objectstore/util.d.ts +8 -0
  113. package/dist/cmd/objectstore/util.d.ts.map +1 -0
  114. package/dist/cmd/profile/create.d.ts.map +1 -1
  115. package/dist/cmd/profile/delete.d.ts.map +1 -1
  116. package/dist/cmd/profile/index.d.ts.map +1 -1
  117. package/dist/cmd/profile/list.d.ts +1 -2
  118. package/dist/cmd/profile/list.d.ts.map +1 -1
  119. package/dist/cmd/profile/show.d.ts.map +1 -1
  120. package/dist/cmd/profile/use.d.ts.map +1 -1
  121. package/dist/cmd/project/create.d.ts.map +1 -1
  122. package/dist/cmd/project/delete.d.ts.map +1 -1
  123. package/dist/cmd/project/index.d.ts.map +1 -1
  124. package/dist/cmd/project/list.d.ts.map +1 -1
  125. package/dist/cmd/project/show.d.ts.map +1 -1
  126. package/dist/cmd/project/template-flow.d.ts +1 -1
  127. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  128. package/dist/cmd/prompt/index.d.ts +4 -0
  129. package/dist/cmd/prompt/index.d.ts.map +1 -0
  130. package/dist/cmd/prompt/llm.d.ts +3 -0
  131. package/dist/cmd/prompt/llm.d.ts.map +1 -0
  132. package/dist/cmd/repl/index.d.ts +3 -0
  133. package/dist/cmd/repl/index.d.ts.map +1 -0
  134. package/dist/cmd/schema/index.d.ts +4 -0
  135. package/dist/cmd/schema/index.d.ts.map +1 -0
  136. package/dist/cmd/schema/show.d.ts +3 -0
  137. package/dist/cmd/schema/show.d.ts.map +1 -0
  138. package/dist/cmd/secret/delete.d.ts.map +1 -1
  139. package/dist/cmd/secret/get.d.ts.map +1 -1
  140. package/dist/cmd/secret/import.d.ts.map +1 -1
  141. package/dist/cmd/secret/index.d.ts.map +1 -1
  142. package/dist/cmd/secret/list.d.ts.map +1 -1
  143. package/dist/cmd/secret/pull.d.ts.map +1 -1
  144. package/dist/cmd/secret/push.d.ts.map +1 -1
  145. package/dist/cmd/secret/set.d.ts.map +1 -1
  146. package/dist/cmd/version/index.d.ts.map +1 -1
  147. package/dist/config.d.ts +1 -1
  148. package/dist/config.d.ts.map +1 -1
  149. package/dist/errors.d.ts +83 -0
  150. package/dist/errors.d.ts.map +1 -0
  151. package/dist/explain.d.ts +47 -0
  152. package/dist/explain.d.ts.map +1 -0
  153. package/dist/index.d.ts +6 -0
  154. package/dist/index.d.ts.map +1 -1
  155. package/dist/json.d.ts +3 -0
  156. package/dist/json.d.ts.map +1 -0
  157. package/dist/output.d.ts +136 -0
  158. package/dist/output.d.ts.map +1 -0
  159. package/dist/repl.d.ts +120 -0
  160. package/dist/repl.d.ts.map +1 -0
  161. package/dist/schema-generator.d.ts +67 -0
  162. package/dist/schema-generator.d.ts.map +1 -0
  163. package/dist/tui.d.ts +35 -1
  164. package/dist/tui.d.ts.map +1 -1
  165. package/dist/types.d.ts +77 -6
  166. package/dist/types.d.ts.map +1 -1
  167. package/dist/utils/format.d.ts +9 -0
  168. package/dist/utils/format.d.ts.map +1 -0
  169. package/package.json +12 -4
  170. package/src/banner.ts +7 -7
  171. package/src/cli-logger.ts +80 -0
  172. package/src/cli.ts +192 -58
  173. package/src/cmd/agents/index.ts +147 -0
  174. package/src/cmd/auth/index.ts +1 -0
  175. package/src/cmd/auth/login.ts +7 -2
  176. package/src/cmd/auth/logout.ts +4 -0
  177. package/src/cmd/auth/signup.ts +7 -2
  178. package/src/cmd/auth/ssh/add.ts +20 -3
  179. package/src/cmd/auth/ssh/delete.ts +57 -4
  180. package/src/cmd/auth/ssh/index.ts +4 -3
  181. package/src/cmd/auth/ssh/list.ts +38 -27
  182. package/src/cmd/auth/whoami.ts +32 -21
  183. package/src/cmd/bundle/ast.test.ts +2 -2
  184. package/src/cmd/bundle/ast.ts +112 -22
  185. package/src/cmd/bundle/index.ts +20 -0
  186. package/src/cmd/bundle/plugin.ts +60 -14
  187. package/src/cmd/capabilities/index.ts +12 -0
  188. package/src/cmd/capabilities/show.ts +256 -0
  189. package/src/cmd/cloud/deploy.ts +54 -0
  190. package/src/cmd/cloud/deployment/index.ts +1 -0
  191. package/src/cmd/cloud/deployment/list.ts +66 -25
  192. package/src/cmd/cloud/deployment/remove.ts +26 -2
  193. package/src/cmd/cloud/deployment/rollback.ts +35 -4
  194. package/src/cmd/cloud/deployment/show.ts +37 -2
  195. package/src/cmd/cloud/deployment/undeploy.ts +12 -1
  196. package/src/cmd/cloud/deployment/utils.ts +5 -2
  197. package/src/cmd/cloud/domain.ts +3 -2
  198. package/src/cmd/cloud/index.ts +10 -1
  199. package/src/cmd/cloud/resource/add.ts +19 -0
  200. package/src/cmd/cloud/resource/delete.ts +24 -3
  201. package/src/cmd/cloud/resource/index.ts +4 -3
  202. package/src/cmd/cloud/resource/list.ts +36 -10
  203. package/src/cmd/cloud/scp/download.ts +27 -1
  204. package/src/cmd/cloud/scp/index.ts +4 -3
  205. package/src/cmd/cloud/scp/upload.ts +27 -1
  206. package/src/cmd/cloud/session/get.ts +164 -0
  207. package/src/cmd/cloud/session/index.ts +11 -0
  208. package/src/cmd/cloud/session/list.ts +145 -0
  209. package/src/cmd/cloud/session/logs.ts +68 -0
  210. package/src/cmd/cloud/ssh.ts +12 -0
  211. package/src/cmd/dev/agents.ts +122 -0
  212. package/src/cmd/dev/index.ts +106 -8
  213. package/src/cmd/dev/sync.ts +414 -0
  214. package/src/cmd/dev/templates.ts +1 -1
  215. package/src/cmd/env/delete.ts +17 -0
  216. package/src/cmd/env/get.ts +17 -1
  217. package/src/cmd/env/import.ts +47 -3
  218. package/src/cmd/env/index.ts +1 -0
  219. package/src/cmd/env/list.ts +13 -1
  220. package/src/cmd/env/pull.ts +20 -0
  221. package/src/cmd/env/push.ts +33 -1
  222. package/src/cmd/env/set.ts +25 -1
  223. package/src/cmd/index.ts +9 -2
  224. package/src/cmd/kv/create-namespace.ts +45 -0
  225. package/src/cmd/kv/delete-namespace.ts +73 -0
  226. package/src/cmd/kv/delete.ts +51 -0
  227. package/src/cmd/kv/get.ts +65 -0
  228. package/src/cmd/kv/index.ts +31 -0
  229. package/src/cmd/kv/keys.ts +57 -0
  230. package/src/cmd/kv/list-namespaces.ts +43 -0
  231. package/src/cmd/kv/repl.ts +284 -0
  232. package/src/cmd/kv/search.ts +80 -0
  233. package/src/cmd/kv/set.ts +63 -0
  234. package/src/cmd/kv/stats.ts +96 -0
  235. package/src/cmd/kv/util.ts +32 -0
  236. package/src/cmd/objectstore/delete-bucket.ts +72 -0
  237. package/src/cmd/objectstore/delete.ts +59 -0
  238. package/src/cmd/objectstore/get.ts +64 -0
  239. package/src/cmd/objectstore/index.ts +27 -0
  240. package/src/cmd/objectstore/list-buckets.ts +45 -0
  241. package/src/cmd/objectstore/list-keys.ts +60 -0
  242. package/src/cmd/objectstore/put.ts +62 -0
  243. package/src/cmd/objectstore/repl.ts +235 -0
  244. package/src/cmd/objectstore/url.ts +59 -0
  245. package/src/cmd/objectstore/util.ts +28 -0
  246. package/src/cmd/profile/create.ts +28 -2
  247. package/src/cmd/profile/delete.ts +17 -2
  248. package/src/cmd/profile/index.ts +1 -0
  249. package/src/cmd/profile/list.ts +7 -3
  250. package/src/cmd/profile/show.ts +20 -5
  251. package/src/cmd/profile/use.ts +8 -0
  252. package/src/cmd/project/create.ts +31 -0
  253. package/src/cmd/project/delete.ts +24 -2
  254. package/src/cmd/project/index.ts +1 -0
  255. package/src/cmd/project/list.ts +24 -10
  256. package/src/cmd/project/show.ts +28 -9
  257. package/src/cmd/project/template-flow.ts +10 -6
  258. package/src/cmd/prompt/index.ts +12 -0
  259. package/src/cmd/prompt/llm.ts +368 -0
  260. package/src/cmd/repl/index.ts +477 -0
  261. package/src/cmd/schema/index.ts +12 -0
  262. package/src/cmd/schema/show.ts +27 -0
  263. package/src/cmd/secret/delete.ts +17 -0
  264. package/src/cmd/secret/get.ts +20 -1
  265. package/src/cmd/secret/import.ts +45 -2
  266. package/src/cmd/secret/index.ts +1 -0
  267. package/src/cmd/secret/list.ts +10 -1
  268. package/src/cmd/secret/pull.ts +20 -0
  269. package/src/cmd/secret/push.ts +33 -1
  270. package/src/cmd/secret/set.ts +20 -0
  271. package/src/cmd/version/index.ts +15 -2
  272. package/src/config.ts +17 -4
  273. package/src/errors.ts +222 -0
  274. package/src/explain.ts +126 -0
  275. package/src/index.ts +51 -0
  276. package/src/json.ts +28 -0
  277. package/src/output.ts +307 -0
  278. package/src/repl.ts +1507 -0
  279. package/src/schema-generator.ts +389 -0
  280. package/src/tui.ts +178 -13
  281. package/src/types.ts +75 -22
  282. package/src/utils/format.ts +17 -0
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { createStorageAdapter } from './util';
5
+ import { getCommand } from '../../command-prefix';
6
+
7
+ const NamespaceListResponseSchema = z.array(z.string().describe('Namespace name'));
8
+
9
+ export const listNamespacesSubcommand = createCommand({
10
+ name: 'list-namespaces',
11
+ aliases: ['namespaces', 'ns'],
12
+ description: 'List all keyvalue namespaces',
13
+ tags: ['read-only', 'fast', 'requires-auth'],
14
+ requires: { auth: true, project: true },
15
+ examples: [
16
+ `${getCommand('kv list-namespaces')} - List all namespaces`,
17
+ `${getCommand('kv namespaces')} - List namespaces (using alias)`,
18
+ `${getCommand('kv ns')} - List namespaces (short alias)`,
19
+ ],
20
+ schema: {
21
+ response: NamespaceListResponseSchema,
22
+ },
23
+ idempotent: true,
24
+
25
+ async handler(ctx) {
26
+ const storage = await createStorageAdapter(ctx);
27
+ const namespaces = await storage.getNamespaces();
28
+
29
+ if (namespaces.length === 0) {
30
+ tui.info('No namespaces found');
31
+ return [];
32
+ }
33
+
34
+ tui.info(`Found ${namespaces.length} namespace(s):`);
35
+ for (const name of namespaces) {
36
+ tui.arrow(name);
37
+ }
38
+
39
+ return namespaces;
40
+ },
41
+ });
42
+
43
+ export default listNamespacesSubcommand;
@@ -0,0 +1,284 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../types';
3
+ import { createRepl, type ReplCommand } from '../../repl';
4
+ import { showBanner } from '../../banner';
5
+ import * as tui from '../../tui';
6
+ import { isPossiblyJSON, tryParseJSON } from '../../json';
7
+ import { createStorageAdapter } from './util';
8
+ import { getCommand } from '../../command-prefix';
9
+
10
+ export const replSubcommand = createCommand({
11
+ name: 'repl',
12
+ description: 'Start an interactive repl for working with keyvalue database',
13
+ tags: ['slow', 'requires-auth'],
14
+ idempotent: false,
15
+ requires: { auth: true, project: true },
16
+ examples: [`${getCommand('kv repl')} - Start interactive KV session`],
17
+
18
+ async handler(ctx) {
19
+ showBanner(undefined, true);
20
+ tui.info('Managing keyvalue store for project');
21
+ tui.newline();
22
+ console.log(tui.bold('Org:'.padEnd(10, ' ')), ' ', tui.muted(ctx.project.orgId));
23
+ console.log(tui.bold('Project:'.padEnd(10, ' ')), ' ', tui.muted(ctx.project.projectId));
24
+ tui.newline();
25
+
26
+ const storage = await createStorageAdapter(ctx);
27
+
28
+ const commands: ReplCommand[] = [
29
+ {
30
+ name: 'set',
31
+ aliases: ['put'],
32
+ description: 'Set a value for a namespace',
33
+ schema: {
34
+ args: z.tuple([
35
+ z.string().min(1),
36
+ z.string().min(1),
37
+ z.string().min(1),
38
+ z.coerce.number().min(60).optional(),
39
+ ]),
40
+ argNames: ['namespace', 'key', 'value', 'ttl'],
41
+ },
42
+ handler: async (ctx) => {
43
+ ctx.setProgress('saving');
44
+ const started = Date.now();
45
+ const contentType = isPossiblyJSON(ctx.parsed.args[2]!)
46
+ ? 'application/json'
47
+ : 'text/plain';
48
+ const ttl = ctx.parsed.args.length > 3 ? parseInt(ctx.parsed.args[3]!) : undefined;
49
+ await storage.set(ctx.parsed.args[0]!, ctx.parsed.args[1]!, ctx.parsed.args[2]!, {
50
+ contentType,
51
+ ttl,
52
+ });
53
+ ctx.success(`saved in ${(Date.now() - started).toFixed(1)}ms (${contentType})`);
54
+ },
55
+ },
56
+ {
57
+ name: 'get',
58
+ description: 'Get a value for a namespace and key',
59
+ schema: {
60
+ args: z.tuple([z.string().min(1), z.string().min(1)]),
61
+ argNames: ['namespace', 'key'],
62
+ },
63
+ handler: async (ctx) => {
64
+ ctx.setProgress('fetching');
65
+ const started = Date.now();
66
+ const res = await storage.get(ctx.parsed.args[0]!, ctx.parsed.args[1]!);
67
+ if (res.exists) {
68
+ if (res.data) {
69
+ if (res.contentType?.includes('json')) {
70
+ const val = tryParseJSON(res.data as unknown as string);
71
+ ctx.json(val);
72
+ } else if (res.contentType?.includes('text')) {
73
+ ctx.write(String(res.data));
74
+ } else {
75
+ const b = res.data as ArrayBuffer;
76
+ ctx.info(`Read ${b.byteLength} bytes (${res.contentType})`);
77
+ }
78
+ ctx.success(
79
+ `retrieved in ${(Date.now() - started).toFixed(1)}ms (${res.contentType})`
80
+ );
81
+ } else {
82
+ ctx.warning(
83
+ `${ctx.parsed.args[1]!} returned empty data for ${ctx.parsed.args[0]!}`
84
+ );
85
+ }
86
+ } else {
87
+ ctx.warning(`${ctx.parsed.args[1]!} does not exist in ${ctx.parsed.args[0]!}`);
88
+ }
89
+ },
90
+ },
91
+ {
92
+ name: 'delete',
93
+ aliases: ['rm', 'remove', 'del'],
94
+ description: 'Delete a value for a namespace and key',
95
+ schema: {
96
+ args: z.tuple([z.string().min(1), z.string().min(1)]),
97
+ argNames: ['namespace', 'key'],
98
+ },
99
+ handler: async (ctx) => {
100
+ ctx.setProgress('deleting');
101
+ const started = Date.now();
102
+ await storage.delete(ctx.parsed.args[0]!, ctx.parsed.args[1]!);
103
+ ctx.success(`deleted in ${(Date.now() - started).toFixed(1)}ms`);
104
+ },
105
+ },
106
+ {
107
+ name: 'stats',
108
+ description: 'Get statistics for a namespace or all namespaces',
109
+ schema: {
110
+ args: z.tuple([z.string().min(1).optional()]),
111
+ argNames: ['namespace'],
112
+ },
113
+ handler: async (ctx) => {
114
+ ctx.setProgress('fetching stats');
115
+ const started = Date.now();
116
+ if (ctx.parsed.args.length > 0 && ctx.parsed.args[0]) {
117
+ const stats = await storage.getStats(ctx.parsed.args[0]!);
118
+ ctx.info(`Statistics for ${tui.bold(ctx.parsed.args[0]!)}:`);
119
+ ctx.write(` Keys: ${stats.count}`);
120
+ const sizeMB = (stats.sum / (1024 * 1024)).toFixed(2);
121
+ ctx.write(` Total size: ${sizeMB} MB`);
122
+ if (stats.createdAt) {
123
+ ctx.write(` Created: ${new Date(stats.createdAt).toLocaleString()}`);
124
+ }
125
+ if (stats.lastUsedAt) {
126
+ ctx.write(` Last used: ${new Date(stats.lastUsedAt).toLocaleString()}`);
127
+ }
128
+ } else {
129
+ const allStats = await storage.getAllStats();
130
+ const entries = Object.entries(allStats);
131
+ if (entries.length === 0) {
132
+ ctx.info('No namespaces found');
133
+ } else {
134
+ ctx.info(`Found ${entries.length} namespace(s):`);
135
+ for (const [name, stats] of entries) {
136
+ const sizeMB = (stats.sum / (1024 * 1024)).toFixed(2);
137
+ ctx.write(` ${tui.bold(name)}: ${stats.count} keys, ${sizeMB} MB`);
138
+ }
139
+ }
140
+ }
141
+ ctx.success(`retrieved in ${(Date.now() - started).toFixed(1)}ms`);
142
+ },
143
+ },
144
+ {
145
+ name: 'search',
146
+ description: 'Search for keys matching a keyword',
147
+ schema: {
148
+ args: z.tuple([z.string().min(1), z.string().min(1)]),
149
+ argNames: ['namespace', 'keyword'],
150
+ },
151
+ handler: async (ctx) => {
152
+ ctx.setProgress('searching');
153
+ const started = Date.now();
154
+ const results = await storage.search(ctx.parsed.args[0]!, ctx.parsed.args[1]!);
155
+ const keys = Object.keys(results);
156
+ if (keys.length === 0) {
157
+ ctx.info(
158
+ `No keys found matching ${tui.bold(ctx.parsed.args[1]!)} in ${tui.bold(ctx.parsed.args[0]!)}`
159
+ );
160
+ } else {
161
+ ctx.info(
162
+ `Found ${keys.length} key(s) matching ${tui.bold(ctx.parsed.args[1]!)}:`
163
+ );
164
+ for (const key of keys) {
165
+ const item = results[key];
166
+ if (!item) continue;
167
+ const sizeMB = (item.size / (1024 * 1024)).toFixed(2);
168
+ const date = new Date(item.updated_at).toLocaleString();
169
+ ctx.write(
170
+ ` ${tui.bold(key)}: ${sizeMB} MB, ${item.contentType}, updated ${date}`
171
+ );
172
+ }
173
+ }
174
+ ctx.success(`retrieved in ${(Date.now() - started).toFixed(1)}ms`);
175
+ },
176
+ },
177
+ {
178
+ name: 'keys',
179
+ aliases: ['ls', 'list'],
180
+ description: 'List all keys in a namespace',
181
+ schema: {
182
+ args: z.tuple([z.string().min(1)]),
183
+ argNames: ['namespace'],
184
+ },
185
+ handler: async (ctx) => {
186
+ ctx.setProgress('listing keys');
187
+ const started = Date.now();
188
+ const keys = await storage.getKeys(ctx.parsed.args[0]!);
189
+ if (keys.length === 0) {
190
+ ctx.info(`No keys found in namespace ${tui.bold(ctx.parsed.args[0]!)}`);
191
+ } else {
192
+ ctx.info(`Found ${keys.length} key(s) in ${tui.bold(ctx.parsed.args[0]!)}:`);
193
+ for (const key of keys) {
194
+ ctx.write(` ${key}`);
195
+ }
196
+ }
197
+ ctx.success(`retrieved in ${(Date.now() - started).toFixed(1)}ms`);
198
+ },
199
+ },
200
+ {
201
+ name: 'namespaces',
202
+ aliases: ['ns', 'list-namespaces'],
203
+ description: 'List all namespaces',
204
+ handler: async (ctx) => {
205
+ ctx.setProgress('listing namespaces');
206
+ const started = Date.now();
207
+ const namespaces = await storage.getNamespaces();
208
+ if (namespaces.length === 0) {
209
+ ctx.info('No namespaces found');
210
+ } else {
211
+ ctx.info(`Found ${namespaces.length} namespace(s):`);
212
+ for (const name of namespaces) {
213
+ ctx.write(` ${name}`);
214
+ }
215
+ }
216
+ ctx.success(`retrieved in ${(Date.now() - started).toFixed(1)}ms`);
217
+ },
218
+ },
219
+ {
220
+ name: 'create-namespace',
221
+ aliases: ['create', 'mkns'],
222
+ description: 'Create a new namespace',
223
+ schema: {
224
+ args: z.tuple([z.string().min(1)]),
225
+ argNames: ['namespace'],
226
+ },
227
+ handler: async (ctx) => {
228
+ ctx.setProgress('creating namespace');
229
+ const started = Date.now();
230
+ await storage.createNamespace(ctx.parsed.args[0]!);
231
+ ctx.success(`created in ${(Date.now() - started).toFixed(1)}ms`);
232
+ },
233
+ },
234
+ {
235
+ name: 'delete-namespace',
236
+ aliases: ['rmns', 'delns'],
237
+ description: 'Delete a namespace and all its keys',
238
+ schema: {
239
+ args: z.tuple([z.string().min(1)]),
240
+ argNames: ['namespace'],
241
+ },
242
+ handler: async (ctx) => {
243
+ ctx.warning(
244
+ `This will delete namespace ${tui.bold(ctx.parsed.args[0]!)} and ALL its keys.`
245
+ );
246
+ const confirm = await new Promise<boolean>((resolve) => {
247
+ process.stdout.write('Are you sure? (yes/no): ');
248
+ process.stdin.once('data', (data) => {
249
+ const answer = data.toString().trim().toLowerCase();
250
+ resolve(answer === 'yes' || answer === 'y');
251
+ });
252
+ });
253
+ if (!confirm) {
254
+ ctx.info('Cancelled');
255
+ return;
256
+ }
257
+ ctx.setProgress('deleting namespace');
258
+ const started = Date.now();
259
+ await storage.deleteNamespace(ctx.parsed.args[0]!);
260
+ ctx.success(`deleted in ${(Date.now() - started).toFixed(1)}ms`);
261
+ },
262
+ },
263
+ {
264
+ name: 'exit',
265
+ aliases: ['quit'],
266
+ description: 'Exit the repl',
267
+ handler: async (ctx) => {
268
+ return ctx.exit();
269
+ },
270
+ },
271
+ ];
272
+
273
+ // Start the REPL
274
+ await createRepl({
275
+ name: 'keyvalue',
276
+ prompt: '> ',
277
+ welcome: tui.muted('Type "help" or / for available commands.'),
278
+ exitMessage: 'Goodbye!',
279
+ commands,
280
+ });
281
+ },
282
+ });
283
+
284
+ export default replSubcommand;
@@ -0,0 +1,80 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { createStorageAdapter } from './util';
5
+ import { getCommand } from '../../command-prefix';
6
+
7
+ const KVSearchResponseSchema = z.object({
8
+ namespace: z.string().describe('Namespace name'),
9
+ keyword: z.string().describe('Search keyword used'),
10
+ results: z.array(
11
+ z.object({
12
+ key: z.string().describe('Key name'),
13
+ size: z.number().describe('Size in bytes'),
14
+ contentType: z.string().describe('Content type'),
15
+ updatedAt: z.string().describe('Last updated timestamp'),
16
+ })
17
+ ),
18
+ });
19
+
20
+ export const searchSubcommand = createCommand({
21
+ name: 'search',
22
+ description: 'Search for keys matching a keyword in a keyvalue namespace',
23
+ tags: ['read-only', 'slow', 'requires-auth'],
24
+ requires: { auth: true, project: true },
25
+ idempotent: true,
26
+ examples: [
27
+ `${getCommand('kv search production user')} - Find all user-related keys`,
28
+ `${getCommand('kv search cache session')} - Find all session keys in cache`,
29
+ `${getCommand('kv search staging config')} - Find all config keys`,
30
+ ],
31
+ schema: {
32
+ args: z.object({
33
+ name: z.string().min(1).describe('the namespace name'),
34
+ keyword: z.string().min(1).describe('keyword to use for filtering'),
35
+ }),
36
+ response: KVSearchResponseSchema,
37
+ },
38
+
39
+ async handler(ctx) {
40
+ const { args } = ctx;
41
+ const kv = await createStorageAdapter(ctx);
42
+
43
+ const results = await kv.search(args.name, args.keyword);
44
+ const keys = Object.keys(results);
45
+
46
+ if (keys.length === 0) {
47
+ tui.info(`No keys found matching ${tui.bold(args.keyword)} in ${tui.bold(args.name)}`);
48
+ return {
49
+ namespace: args.name,
50
+ keyword: args.keyword,
51
+ results: [],
52
+ };
53
+ }
54
+
55
+ tui.info(`Found ${keys.length} key(s) matching ${tui.bold(args.keyword)}:`);
56
+ for (const key of keys) {
57
+ const item = results[key];
58
+ if (!item) continue;
59
+ const sizeMB = (item.size / (1024 * 1024)).toFixed(2);
60
+ const date = new Date(item.updated_at).toLocaleString();
61
+ tui.info(` ${tui.bold(key)}: ${sizeMB} MB, ${item.contentType}, updated ${date}`);
62
+ }
63
+
64
+ return {
65
+ namespace: args.name,
66
+ keyword: args.keyword,
67
+ results: keys.map((key) => {
68
+ const item = results[key]!;
69
+ return {
70
+ key,
71
+ size: item.size,
72
+ contentType: item.contentType,
73
+ updatedAt: item.updated_at,
74
+ };
75
+ }),
76
+ };
77
+ },
78
+ });
79
+
80
+ export default searchSubcommand;
@@ -0,0 +1,63 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { isPossiblyJSON } from '../../json';
5
+ import { createStorageAdapter } from './util';
6
+ import { getCommand } from '../../command-prefix';
7
+
8
+ const KVSetResponseSchema = z.object({
9
+ success: z.boolean().describe('Whether the operation succeeded'),
10
+ namespace: z.string().describe('Namespace name'),
11
+ key: z.string().describe('Key name'),
12
+ contentType: z.string().describe('Content type (application/json or text/plain)'),
13
+ durationMs: z.number().describe('Operation duration in milliseconds'),
14
+ ttl: z.number().optional().describe('TTL in seconds if set'),
15
+ });
16
+
17
+ export const setSubcommand = createCommand({
18
+ name: 'set',
19
+ aliases: ['put'],
20
+ description: 'Set a key and value in the keyvalue storage',
21
+ tags: ['mutating', 'updates-resource', 'slow', 'requires-auth'],
22
+ idempotent: true,
23
+ requires: { auth: true, project: true },
24
+ examples: [
25
+ `${getCommand('kv set production user:123 \'{"name":"Alice","email":"alice@example.com"}\'')} - Store user data`,
26
+ `${getCommand('kv set cache session:abc "session-data-here" --ttl 3600')} - Store session with 1h TTL`,
27
+ `${getCommand('kv set staging cache:homepage "<!DOCTYPE html>..." --ttl 600')} - Cache homepage for 10m`,
28
+ ],
29
+ schema: {
30
+ args: z.object({
31
+ namespace: z.string().min(1).max(64).describe('the namespace name'),
32
+ key: z.string().min(1).max(64).describe('the key name'),
33
+ value: z.string().min(1).describe('the value'),
34
+ ttl: z.coerce.number().min(60).optional().describe('the optional expiration in seconds'),
35
+ }),
36
+ response: KVSetResponseSchema,
37
+ },
38
+
39
+ async handler(ctx) {
40
+ const { args } = ctx;
41
+ const started = Date.now();
42
+ const storage = await createStorageAdapter(ctx);
43
+ const contentType = isPossiblyJSON(args.value) ? 'application/json' : 'text/plain';
44
+ const ttl = args.ttl;
45
+ await storage.set(args.namespace, args.key, args.value, {
46
+ contentType,
47
+ ttl,
48
+ });
49
+ const durationMs = Date.now() - started;
50
+ tui.success(`saved in ${durationMs.toFixed(1)}ms (${contentType})`);
51
+
52
+ return {
53
+ success: true,
54
+ namespace: args.namespace,
55
+ key: args.key,
56
+ contentType,
57
+ durationMs,
58
+ ttl,
59
+ };
60
+ },
61
+ });
62
+
63
+ export default setSubcommand;
@@ -0,0 +1,96 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { createStorageAdapter } from './util';
5
+ import { getCommand } from '../../command-prefix';
6
+
7
+ const KVStatsResponseSchema = z.union([
8
+ z.object({
9
+ namespace: z.string().describe('Namespace name'),
10
+ count: z.number().describe('Number of keys'),
11
+ sum: z.number().describe('Total size in bytes'),
12
+ createdAt: z.string().optional().describe('Creation timestamp'),
13
+ lastUsedAt: z.string().optional().describe('Last used timestamp'),
14
+ }),
15
+ z.record(
16
+ z.string(),
17
+ z.object({
18
+ count: z.number().describe('Number of keys'),
19
+ sum: z.number().describe('Total size in bytes'),
20
+ createdAt: z.string().optional().describe('Creation timestamp'),
21
+ lastUsedAt: z.string().optional().describe('Last used timestamp'),
22
+ })
23
+ ),
24
+ ]);
25
+
26
+ export const statsSubcommand = createCommand({
27
+ name: 'stats',
28
+ description: 'Get statistics for keyvalue storage',
29
+ tags: ['read-only', 'fast', 'requires-auth'],
30
+ requires: { auth: true, project: true },
31
+ idempotent: true,
32
+ examples: [
33
+ `${getCommand('kv stats')} - Show stats for all namespaces`,
34
+ `${getCommand('kv stats production')} - Show stats for production namespace`,
35
+ `${getCommand('kv stats cache')} - Show stats for cache namespace`,
36
+ ],
37
+ schema: {
38
+ args: z.object({
39
+ name: z.string().optional().describe('the keyvalue namespace'),
40
+ }),
41
+ response: KVStatsResponseSchema,
42
+ },
43
+
44
+ async handler(ctx) {
45
+ const { args } = ctx;
46
+ const kv = await createStorageAdapter(ctx);
47
+
48
+ if (args.name) {
49
+ const stats = await kv.getStats(args.name);
50
+ tui.info(`Statistics for ${tui.bold(args.name)}:`);
51
+ tui.info(` Keys: ${stats.count}`);
52
+ const sizeDisplay =
53
+ stats.sum < 1024 * 1024
54
+ ? `${stats.sum.toLocaleString()} bytes`
55
+ : `${(stats.sum / (1024 * 1024)).toFixed(2)} MB`;
56
+ tui.info(` Total size: ${sizeDisplay} (raw: ${stats.sum})`);
57
+ if (stats.createdAt) {
58
+ tui.info(` Created: ${new Date(stats.createdAt).toLocaleString()}`);
59
+ }
60
+ if (stats.lastUsedAt) {
61
+ tui.info(` Last used: ${new Date(stats.lastUsedAt).toLocaleString()}`);
62
+ }
63
+
64
+ return {
65
+ namespace: args.name,
66
+ count: stats.count,
67
+ sum: stats.sum,
68
+ createdAt: stats.createdAt,
69
+ lastUsedAt: stats.lastUsedAt,
70
+ };
71
+ } else {
72
+ const allStats = await kv.getAllStats();
73
+ const entries = Object.entries(allStats);
74
+
75
+ if (entries.length === 0) {
76
+ tui.info('No namespaces found');
77
+ return {};
78
+ }
79
+
80
+ tui.info(
81
+ `Found ${entries.length} ${tui.plural(entries.length, 'namespace', 'namespaces')}:`
82
+ );
83
+ for (const [name, stats] of entries) {
84
+ const sizeDisplay =
85
+ stats.sum < 1024 * 1024
86
+ ? `${stats.sum.toLocaleString()} bytes`
87
+ : `${(stats.sum / (1024 * 1024)).toFixed(2)} MB`;
88
+ tui.arrow(`${tui.bold(name.padEnd(15, ' '))}: ${stats.count} keys, ${sizeDisplay}`);
89
+ }
90
+
91
+ return allStats;
92
+ }
93
+ },
94
+ });
95
+
96
+ export default statsSubcommand;
@@ -0,0 +1,32 @@
1
+ import { KeyValueStorageService, Logger } from '@agentuity/core';
2
+ import { createServerFetchAdapter } from '@agentuity/server';
3
+ import { loadProjectSDKKey } from '../../config';
4
+ import { ErrorCode } from '../../errors';
5
+ import type { Config } from '../../types';
6
+ import * as tui from '../../tui';
7
+
8
+ export async function createStorageAdapter(ctx: {
9
+ logger: Logger;
10
+ projectDir: string;
11
+ config: Config | null;
12
+ }) {
13
+ const sdkKey = await loadProjectSDKKey(ctx.projectDir);
14
+ if (!sdkKey) {
15
+ tui.fatal(
16
+ `Couldn't find the AGENTUITY_SDK_KEY in ${ctx.projectDir} .env file`,
17
+ ErrorCode.CONFIG_NOT_FOUND
18
+ );
19
+ }
20
+
21
+ const adapter = createServerFetchAdapter(
22
+ {
23
+ headers: {
24
+ Authorization: `Bearer ${sdkKey}`,
25
+ },
26
+ },
27
+ ctx.logger
28
+ );
29
+
30
+ const baseUrl = ctx.config?.overrides?.catalyst_url ?? 'https://catalyst.agentuity.cloud';
31
+ return new KeyValueStorageService(baseUrl, adapter);
32
+ }
@@ -0,0 +1,72 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { createStorageAdapter } from './util';
5
+ import { getCommand } from '../../command-prefix';
6
+
7
+ export const deleteBucketSubcommand = createCommand({
8
+ name: 'delete-bucket',
9
+ description: 'Delete an object storage bucket and all its contents',
10
+ tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
11
+ idempotent: true,
12
+ requires: { auth: true, project: true },
13
+ examples: [
14
+ `${getCommand('objectstore delete-bucket temp')} - Delete temp bucket (interactive)`,
15
+ `${getCommand('objectstore delete-bucket old-uploads --confirm')} - Force delete without confirmation`,
16
+ ],
17
+ schema: {
18
+ args: z.object({
19
+ bucket: z.string().min(1).max(64).describe('the name of the bucket'),
20
+ confirm: z
21
+ .boolean()
22
+ .optional()
23
+ .default(false)
24
+ .describe('if true will not prompt for confirmation'),
25
+ }),
26
+ response: z.object({
27
+ success: z.boolean().describe('Whether the deletion succeeded'),
28
+ bucket: z.string().describe('Deleted bucket name'),
29
+ message: z.string().optional().describe('Confirmation message'),
30
+ }),
31
+ },
32
+
33
+ async handler(ctx) {
34
+ const { args } = ctx;
35
+ const objectStore = await createStorageAdapter(ctx);
36
+
37
+ if (!args.confirm) {
38
+ if (!process.stdin.isTTY) {
39
+ tui.fatal('No TTY and --confirm is not set. Refusing to delete');
40
+ }
41
+ tui.warning(`This will delete bucket ${tui.bold(args.bucket)} and ALL its contents.`);
42
+ const confirm = await new Promise<boolean>((resolve) => {
43
+ process.stdout.write('Are you sure? (yes/no): ');
44
+ process.stdin.once('data', (data) => {
45
+ const answer = data.toString().trim().toLowerCase();
46
+ resolve(answer === 'yes' || answer === 'y');
47
+ });
48
+ });
49
+
50
+ if (!confirm) {
51
+ tui.info('Cancelled');
52
+ return { success: false, bucket: args.bucket, message: 'Cancelled' };
53
+ }
54
+ }
55
+
56
+ const deleted = await objectStore.deleteBucket(args.bucket);
57
+
58
+ if (deleted) {
59
+ tui.success(`Bucket ${tui.bold(args.bucket)} deleted`);
60
+ } else {
61
+ tui.error(`Bucket ${tui.bold(args.bucket)} not found`);
62
+ }
63
+
64
+ return {
65
+ success: deleted,
66
+ bucket: args.bucket,
67
+ message: deleted ? `Bucket ${args.bucket} deleted` : `Bucket ${args.bucket} not found`,
68
+ };
69
+ },
70
+ });
71
+
72
+ export default deleteBucketSubcommand;