@agentuity/cli 0.0.48 → 0.0.49
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.
- package/bin/cli.ts +26 -5
- package/dist/banner.d.ts +1 -1
- package/dist/banner.d.ts.map +1 -1
- package/dist/cli-logger.d.ts +27 -0
- package/dist/cli-logger.d.ts.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cmd/auth/index.d.ts.map +1 -1
- package/dist/cmd/auth/login.d.ts.map +1 -1
- package/dist/cmd/auth/logout.d.ts.map +1 -1
- package/dist/cmd/auth/signup.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/add.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/delete.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/index.d.ts +1 -2
- package/dist/cmd/auth/ssh/index.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/list.d.ts.map +1 -1
- package/dist/cmd/auth/whoami.d.ts.map +1 -1
- package/dist/cmd/bundle/ast.d.ts.map +1 -1
- package/dist/cmd/bundle/index.d.ts.map +1 -1
- package/dist/cmd/bundle/plugin.d.ts.map +1 -1
- package/dist/cmd/capabilities/index.d.ts +4 -0
- package/dist/cmd/capabilities/index.d.ts.map +1 -0
- package/dist/cmd/capabilities/show.d.ts +20 -0
- package/dist/cmd/capabilities/show.d.ts.map +1 -0
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/index.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/list.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/remove.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/rollback.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/show.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/undeploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/utils.d.ts +4 -2
- package/dist/cmd/cloud/deployment/utils.d.ts.map +1 -1
- package/dist/cmd/cloud/domain.d.ts.map +1 -1
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/resource/add.d.ts.map +1 -1
- package/dist/cmd/cloud/resource/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/resource/index.d.ts +1 -2
- package/dist/cmd/cloud/resource/index.d.ts.map +1 -1
- package/dist/cmd/cloud/resource/list.d.ts.map +1 -1
- package/dist/cmd/cloud/scp/download.d.ts.map +1 -1
- package/dist/cmd/cloud/scp/index.d.ts +1 -2
- package/dist/cmd/cloud/scp/index.d.ts.map +1 -1
- package/dist/cmd/cloud/scp/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/ssh.d.ts.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/env/delete.d.ts.map +1 -1
- package/dist/cmd/env/get.d.ts.map +1 -1
- package/dist/cmd/env/import.d.ts.map +1 -1
- package/dist/cmd/env/index.d.ts.map +1 -1
- package/dist/cmd/env/list.d.ts.map +1 -1
- package/dist/cmd/env/pull.d.ts.map +1 -1
- package/dist/cmd/env/push.d.ts.map +1 -1
- package/dist/cmd/env/set.d.ts.map +1 -1
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/kv/create-namespace.d.ts +3 -0
- package/dist/cmd/kv/create-namespace.d.ts.map +1 -0
- package/dist/cmd/kv/delete-namespace.d.ts +3 -0
- package/dist/cmd/kv/delete-namespace.d.ts.map +1 -0
- package/dist/cmd/kv/delete.d.ts +3 -0
- package/dist/cmd/kv/delete.d.ts.map +1 -0
- package/dist/cmd/kv/get.d.ts +3 -0
- package/dist/cmd/kv/get.d.ts.map +1 -0
- package/dist/cmd/kv/index.d.ts +2 -0
- package/dist/cmd/kv/index.d.ts.map +1 -0
- package/dist/cmd/kv/keys.d.ts +3 -0
- package/dist/cmd/kv/keys.d.ts.map +1 -0
- package/dist/cmd/kv/list-namespaces.d.ts +3 -0
- package/dist/cmd/kv/list-namespaces.d.ts.map +1 -0
- package/dist/cmd/kv/repl.d.ts +3 -0
- package/dist/cmd/kv/repl.d.ts.map +1 -0
- package/dist/cmd/kv/search.d.ts +3 -0
- package/dist/cmd/kv/search.d.ts.map +1 -0
- package/dist/cmd/kv/set.d.ts +3 -0
- package/dist/cmd/kv/set.d.ts.map +1 -0
- package/dist/cmd/kv/stats.d.ts +3 -0
- package/dist/cmd/kv/stats.d.ts.map +1 -0
- package/dist/cmd/kv/util.d.ts +8 -0
- package/dist/cmd/kv/util.d.ts.map +1 -0
- package/dist/cmd/objectstore/delete-bucket.d.ts +3 -0
- package/dist/cmd/objectstore/delete-bucket.d.ts.map +1 -0
- package/dist/cmd/objectstore/delete.d.ts +3 -0
- package/dist/cmd/objectstore/delete.d.ts.map +1 -0
- package/dist/cmd/objectstore/get.d.ts +3 -0
- package/dist/cmd/objectstore/get.d.ts.map +1 -0
- package/dist/cmd/objectstore/index.d.ts +2 -0
- package/dist/cmd/objectstore/index.d.ts.map +1 -0
- package/dist/cmd/objectstore/list-buckets.d.ts +3 -0
- package/dist/cmd/objectstore/list-buckets.d.ts.map +1 -0
- package/dist/cmd/objectstore/list-keys.d.ts +3 -0
- package/dist/cmd/objectstore/list-keys.d.ts.map +1 -0
- package/dist/cmd/objectstore/put.d.ts +3 -0
- package/dist/cmd/objectstore/put.d.ts.map +1 -0
- package/dist/cmd/objectstore/repl.d.ts +3 -0
- package/dist/cmd/objectstore/repl.d.ts.map +1 -0
- package/dist/cmd/objectstore/url.d.ts +3 -0
- package/dist/cmd/objectstore/url.d.ts.map +1 -0
- package/dist/cmd/objectstore/util.d.ts +8 -0
- package/dist/cmd/objectstore/util.d.ts.map +1 -0
- package/dist/cmd/profile/create.d.ts.map +1 -1
- package/dist/cmd/profile/delete.d.ts.map +1 -1
- package/dist/cmd/profile/index.d.ts.map +1 -1
- package/dist/cmd/profile/list.d.ts +1 -2
- package/dist/cmd/profile/list.d.ts.map +1 -1
- package/dist/cmd/profile/show.d.ts.map +1 -1
- package/dist/cmd/profile/use.d.ts.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/delete.d.ts.map +1 -1
- package/dist/cmd/project/index.d.ts.map +1 -1
- package/dist/cmd/project/list.d.ts.map +1 -1
- package/dist/cmd/project/show.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.d.ts +1 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/prompt/index.d.ts +4 -0
- package/dist/cmd/prompt/index.d.ts.map +1 -0
- package/dist/cmd/prompt/llm.d.ts +3 -0
- package/dist/cmd/prompt/llm.d.ts.map +1 -0
- package/dist/cmd/repl/index.d.ts +3 -0
- package/dist/cmd/repl/index.d.ts.map +1 -0
- package/dist/cmd/schema/index.d.ts +4 -0
- package/dist/cmd/schema/index.d.ts.map +1 -0
- package/dist/cmd/schema/show.d.ts +3 -0
- package/dist/cmd/schema/show.d.ts.map +1 -0
- package/dist/cmd/secret/delete.d.ts.map +1 -1
- package/dist/cmd/secret/get.d.ts.map +1 -1
- package/dist/cmd/secret/import.d.ts.map +1 -1
- package/dist/cmd/secret/index.d.ts.map +1 -1
- package/dist/cmd/secret/list.d.ts.map +1 -1
- package/dist/cmd/secret/pull.d.ts.map +1 -1
- package/dist/cmd/secret/push.d.ts.map +1 -1
- package/dist/cmd/secret/set.d.ts.map +1 -1
- package/dist/cmd/version/index.d.ts.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/errors.d.ts +83 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/explain.d.ts +47 -0
- package/dist/explain.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/json.d.ts +3 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/output.d.ts +136 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/repl.d.ts +124 -0
- package/dist/repl.d.ts.map +1 -0
- package/dist/schema-generator.d.ts +67 -0
- package/dist/schema-generator.d.ts.map +1 -0
- package/dist/tui.d.ts +11 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/types.d.ts +65 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -4
- package/src/banner.ts +7 -7
- package/src/cli-logger.ts +80 -0
- package/src/cli.ts +186 -54
- package/src/cmd/auth/index.ts +1 -0
- package/src/cmd/auth/login.ts +7 -2
- package/src/cmd/auth/logout.ts +4 -0
- package/src/cmd/auth/signup.ts +7 -2
- package/src/cmd/auth/ssh/add.ts +20 -3
- package/src/cmd/auth/ssh/delete.ts +57 -4
- package/src/cmd/auth/ssh/index.ts +4 -3
- package/src/cmd/auth/ssh/list.ts +29 -12
- package/src/cmd/auth/whoami.ts +32 -21
- package/src/cmd/bundle/ast.ts +27 -5
- package/src/cmd/bundle/index.ts +20 -0
- package/src/cmd/bundle/plugin.ts +36 -12
- package/src/cmd/capabilities/index.ts +12 -0
- package/src/cmd/capabilities/show.ts +256 -0
- package/src/cmd/cloud/deploy.ts +54 -0
- package/src/cmd/cloud/deployment/index.ts +1 -0
- package/src/cmd/cloud/deployment/list.ts +50 -3
- package/src/cmd/cloud/deployment/remove.ts +26 -2
- package/src/cmd/cloud/deployment/rollback.ts +35 -4
- package/src/cmd/cloud/deployment/show.ts +37 -2
- package/src/cmd/cloud/deployment/undeploy.ts +12 -1
- package/src/cmd/cloud/deployment/utils.ts +5 -2
- package/src/cmd/cloud/domain.ts +3 -2
- package/src/cmd/cloud/index.ts +8 -1
- package/src/cmd/cloud/resource/add.ts +19 -0
- package/src/cmd/cloud/resource/delete.ts +24 -3
- package/src/cmd/cloud/resource/index.ts +4 -3
- package/src/cmd/cloud/resource/list.ts +36 -10
- package/src/cmd/cloud/scp/download.ts +27 -1
- package/src/cmd/cloud/scp/index.ts +4 -3
- package/src/cmd/cloud/scp/upload.ts +27 -1
- package/src/cmd/cloud/ssh.ts +12 -0
- package/src/cmd/dev/index.ts +11 -7
- package/src/cmd/dev/templates.ts +1 -1
- package/src/cmd/env/delete.ts +17 -0
- package/src/cmd/env/get.ts +17 -1
- package/src/cmd/env/import.ts +47 -3
- package/src/cmd/env/index.ts +1 -0
- package/src/cmd/env/list.ts +13 -1
- package/src/cmd/env/pull.ts +20 -0
- package/src/cmd/env/push.ts +33 -1
- package/src/cmd/env/set.ts +25 -1
- package/src/cmd/index.ts +9 -2
- package/src/cmd/kv/create-namespace.ts +45 -0
- package/src/cmd/kv/delete-namespace.ts +73 -0
- package/src/cmd/kv/delete.ts +51 -0
- package/src/cmd/kv/get.ts +65 -0
- package/src/cmd/kv/index.ts +31 -0
- package/src/cmd/kv/keys.ts +57 -0
- package/src/cmd/kv/list-namespaces.ts +43 -0
- package/src/cmd/kv/repl.ts +284 -0
- package/src/cmd/kv/search.ts +80 -0
- package/src/cmd/kv/set.ts +63 -0
- package/src/cmd/kv/stats.ts +96 -0
- package/src/cmd/kv/util.ts +32 -0
- package/src/cmd/objectstore/delete-bucket.ts +72 -0
- package/src/cmd/objectstore/delete.ts +59 -0
- package/src/cmd/objectstore/get.ts +64 -0
- package/src/cmd/objectstore/index.ts +27 -0
- package/src/cmd/objectstore/list-buckets.ts +45 -0
- package/src/cmd/objectstore/list-keys.ts +60 -0
- package/src/cmd/objectstore/put.ts +62 -0
- package/src/cmd/objectstore/repl.ts +235 -0
- package/src/cmd/objectstore/url.ts +59 -0
- package/src/cmd/objectstore/util.ts +28 -0
- package/src/cmd/profile/create.ts +28 -2
- package/src/cmd/profile/delete.ts +17 -2
- package/src/cmd/profile/index.ts +1 -0
- package/src/cmd/profile/list.ts +7 -3
- package/src/cmd/profile/show.ts +20 -5
- package/src/cmd/profile/use.ts +8 -0
- package/src/cmd/project/create.ts +31 -0
- package/src/cmd/project/delete.ts +24 -2
- package/src/cmd/project/index.ts +1 -0
- package/src/cmd/project/list.ts +23 -9
- package/src/cmd/project/show.ts +27 -8
- package/src/cmd/project/template-flow.ts +10 -6
- package/src/cmd/prompt/index.ts +12 -0
- package/src/cmd/prompt/llm.ts +368 -0
- package/src/cmd/repl/index.ts +477 -0
- package/src/cmd/schema/index.ts +12 -0
- package/src/cmd/schema/show.ts +27 -0
- package/src/cmd/secret/delete.ts +17 -0
- package/src/cmd/secret/get.ts +20 -1
- package/src/cmd/secret/import.ts +45 -2
- package/src/cmd/secret/index.ts +1 -0
- package/src/cmd/secret/list.ts +10 -1
- package/src/cmd/secret/pull.ts +20 -0
- package/src/cmd/secret/push.ts +33 -1
- package/src/cmd/secret/set.ts +20 -0
- package/src/cmd/version/index.ts +15 -2
- package/src/config.ts +17 -4
- package/src/errors.ts +222 -0
- package/src/explain.ts +126 -0
- package/src/index.ts +51 -0
- package/src/json.ts +28 -0
- package/src/output.ts +307 -0
- package/src/repl.ts +1517 -0
- package/src/schema-generator.ts +389 -0
- package/src/tui.ts +84 -13
- package/src/types.ts +62 -12
|
@@ -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;
|
|
@@ -0,0 +1,59 @@
|
|
|
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 ObjectStoreDeleteResponseSchema = z.object({
|
|
8
|
+
success: z.boolean().describe('Whether the operation succeeded'),
|
|
9
|
+
bucket: z.string().describe('Bucket name'),
|
|
10
|
+
key: z.string().describe('Object key'),
|
|
11
|
+
deleted: z
|
|
12
|
+
.boolean()
|
|
13
|
+
.describe('Whether the object was actually deleted (false if it did not exist)'),
|
|
14
|
+
durationMs: z.number().describe('Operation duration in milliseconds'),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const deleteSubcommand = createCommand({
|
|
18
|
+
name: 'delete',
|
|
19
|
+
aliases: ['del', 'rm', 'remove'],
|
|
20
|
+
description: 'Delete an object from the object storage',
|
|
21
|
+
tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
|
|
22
|
+
idempotent: true,
|
|
23
|
+
requires: { auth: true, project: true },
|
|
24
|
+
examples: [
|
|
25
|
+
`${getCommand('objectstore delete uploads images/old-logo.png')} - Delete old logo`,
|
|
26
|
+
`${getCommand('objectstore rm assets data/temp.json')} - Remove temp file (using alias)`,
|
|
27
|
+
`${getCommand('objectstore delete backups db-2023.sql')} - Delete old backup`,
|
|
28
|
+
],
|
|
29
|
+
schema: {
|
|
30
|
+
args: z.object({
|
|
31
|
+
bucket: z.string().min(1).describe('the bucket name'),
|
|
32
|
+
key: z.string().min(1).describe('the key name'),
|
|
33
|
+
}),
|
|
34
|
+
response: ObjectStoreDeleteResponseSchema,
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async handler(ctx) {
|
|
38
|
+
const { args } = ctx;
|
|
39
|
+
const started = Date.now();
|
|
40
|
+
const storage = await createStorageAdapter(ctx);
|
|
41
|
+
const deleted = await storage.delete(args.bucket, args.key);
|
|
42
|
+
const durationMs = Date.now() - started;
|
|
43
|
+
if (deleted) {
|
|
44
|
+
tui.success(`deleted in ${durationMs.toFixed(1)}ms`);
|
|
45
|
+
} else {
|
|
46
|
+
tui.warning(`${args.key} did not exist in bucket ${args.bucket}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
success: true,
|
|
51
|
+
bucket: args.bucket,
|
|
52
|
+
key: args.key,
|
|
53
|
+
deleted,
|
|
54
|
+
durationMs,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export default deleteSubcommand;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCommand } from '../../types';
|
|
3
|
+
import * as tui from '../../tui';
|
|
4
|
+
import { tryParseJSON } from '../../json';
|
|
5
|
+
import { createStorageAdapter } from './util';
|
|
6
|
+
import { getCommand } from '../../command-prefix';
|
|
7
|
+
|
|
8
|
+
const ObjectGetResponseSchema = z.object({
|
|
9
|
+
exists: z.boolean().describe('Whether the object exists'),
|
|
10
|
+
data: z.any().optional().describe('Object data (binary)'),
|
|
11
|
+
contentType: z.string().optional().describe('Content type'),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const getSubcommand = createCommand({
|
|
15
|
+
name: 'get',
|
|
16
|
+
description: 'Get an object from the object storage',
|
|
17
|
+
tags: ['read-only', 'slow', 'requires-auth'],
|
|
18
|
+
requires: { auth: true, project: true },
|
|
19
|
+
examples: [
|
|
20
|
+
`${getCommand('objectstore get uploads images/logo.png')} - Download logo image`,
|
|
21
|
+
`${getCommand('objectstore get assets data/export.json')} - Get JSON export`,
|
|
22
|
+
`${getCommand('objectstore get backups db-2024.sql')} - Get database backup`,
|
|
23
|
+
],
|
|
24
|
+
schema: {
|
|
25
|
+
args: z.object({
|
|
26
|
+
bucket: z.string().min(1).describe('the bucket name'),
|
|
27
|
+
key: z.string().min(1).describe('the key name'),
|
|
28
|
+
}),
|
|
29
|
+
response: ObjectGetResponseSchema,
|
|
30
|
+
},
|
|
31
|
+
idempotent: true,
|
|
32
|
+
|
|
33
|
+
async handler(ctx) {
|
|
34
|
+
const { args } = ctx;
|
|
35
|
+
const storage = await createStorageAdapter(ctx);
|
|
36
|
+
const started = Date.now();
|
|
37
|
+
const res = await storage.get(args.bucket, args.key);
|
|
38
|
+
if (res.exists) {
|
|
39
|
+
if (res.data) {
|
|
40
|
+
if (res.contentType?.includes('json')) {
|
|
41
|
+
const val = tryParseJSON(new TextDecoder().decode(res.data));
|
|
42
|
+
tui.json(val);
|
|
43
|
+
} else if (res.contentType?.includes('text')) {
|
|
44
|
+
console.log(new TextDecoder().decode(res.data));
|
|
45
|
+
} else {
|
|
46
|
+
tui.info(`Read ${res.data.byteLength} bytes (${res.contentType})`);
|
|
47
|
+
}
|
|
48
|
+
tui.success(`retrieved in ${(Date.now() - started).toFixed(1)}ms (${res.contentType})`);
|
|
49
|
+
} else {
|
|
50
|
+
tui.warning(`${args.key} returned empty data for bucket ${args.bucket}`);
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
tui.warning(`${args.key} does not exist in bucket ${args.bucket}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
exists: res.exists,
|
|
58
|
+
data: res.data,
|
|
59
|
+
contentType: res.exists ? res.contentType : undefined,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export default getSubcommand;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createCommand } from '../../types';
|
|
2
|
+
import { deleteSubcommand } from './delete';
|
|
3
|
+
import { deleteBucketSubcommand } from './delete-bucket';
|
|
4
|
+
import { getSubcommand } from './get';
|
|
5
|
+
import { listBucketsSubcommand } from './list-buckets';
|
|
6
|
+
import { listKeysSubcommand } from './list-keys';
|
|
7
|
+
import { putSubcommand } from './put';
|
|
8
|
+
import { replSubcommand } from './repl';
|
|
9
|
+
import { urlSubcommand } from './url';
|
|
10
|
+
|
|
11
|
+
export const command = createCommand({
|
|
12
|
+
name: 'objectstore',
|
|
13
|
+
aliases: ['object', 'obj'],
|
|
14
|
+
description: 'Manage object storage for your projects',
|
|
15
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
16
|
+
subcommands: [
|
|
17
|
+
replSubcommand,
|
|
18
|
+
getSubcommand,
|
|
19
|
+
putSubcommand,
|
|
20
|
+
deleteSubcommand,
|
|
21
|
+
urlSubcommand,
|
|
22
|
+
listBucketsSubcommand,
|
|
23
|
+
listKeysSubcommand,
|
|
24
|
+
deleteBucketSubcommand,
|
|
25
|
+
],
|
|
26
|
+
requires: { auth: true, project: true },
|
|
27
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
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 BucketListResponseSchema = z.array(
|
|
8
|
+
z.object({
|
|
9
|
+
name: z.string().describe('Bucket name'),
|
|
10
|
+
object_count: z.number().describe('Number of objects in bucket'),
|
|
11
|
+
total_bytes: z.number().describe('Total size in bytes'),
|
|
12
|
+
})
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export const listBucketsSubcommand = createCommand({
|
|
16
|
+
name: 'list-buckets',
|
|
17
|
+
description: 'List all object storage buckets',
|
|
18
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
19
|
+
requires: { auth: true, project: true },
|
|
20
|
+
schema: {
|
|
21
|
+
response: BucketListResponseSchema,
|
|
22
|
+
},
|
|
23
|
+
idempotent: true,
|
|
24
|
+
examples: [`${getCommand('objectstore list-buckets')} - List all buckets with stats`],
|
|
25
|
+
|
|
26
|
+
async handler(ctx) {
|
|
27
|
+
const storage = await createStorageAdapter(ctx);
|
|
28
|
+
const buckets = await storage.listBuckets();
|
|
29
|
+
|
|
30
|
+
if (buckets.length === 0) {
|
|
31
|
+
tui.info('No buckets found');
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
tui.info(`Found ${buckets.length} bucket(s):`);
|
|
36
|
+
for (const bucket of buckets) {
|
|
37
|
+
const sizeMB = (bucket.total_bytes / (1024 * 1024)).toFixed(2);
|
|
38
|
+
tui.info(` ${tui.bold(bucket.name)}: ${bucket.object_count} objects, ${sizeMB} MB`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return buckets;
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export default listBucketsSubcommand;
|
|
@@ -0,0 +1,60 @@
|
|
|
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 listKeysSubcommand = createCommand({
|
|
8
|
+
name: 'list-keys',
|
|
9
|
+
aliases: ['ls', 'list'],
|
|
10
|
+
description: 'List all keys in an object storage bucket',
|
|
11
|
+
tags: ['read-only', 'slow', 'requires-auth'],
|
|
12
|
+
requires: { auth: true, project: true },
|
|
13
|
+
idempotent: true,
|
|
14
|
+
examples: [
|
|
15
|
+
`${getCommand('objectstore list-keys uploads')} - List all uploaded files`,
|
|
16
|
+
`${getCommand('objectstore ls assets')} - List assets (using alias)`,
|
|
17
|
+
`${getCommand('objectstore list backups')} - List all backups`,
|
|
18
|
+
],
|
|
19
|
+
schema: {
|
|
20
|
+
args: z.object({
|
|
21
|
+
bucket: z.string().min(1),
|
|
22
|
+
}),
|
|
23
|
+
response: z.object({
|
|
24
|
+
bucket: z.string().describe('Bucket name'),
|
|
25
|
+
objects: z
|
|
26
|
+
.array(
|
|
27
|
+
z.object({
|
|
28
|
+
key: z.string().describe('Object key'),
|
|
29
|
+
size: z.number().describe('Object size in bytes'),
|
|
30
|
+
updated_at: z.string().describe('Last update timestamp'),
|
|
31
|
+
})
|
|
32
|
+
)
|
|
33
|
+
.describe('List of objects in the bucket'),
|
|
34
|
+
count: z.number().describe('Number of objects found'),
|
|
35
|
+
}),
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async handler(ctx) {
|
|
39
|
+
const { args } = ctx;
|
|
40
|
+
const objectStore = await createStorageAdapter(ctx);
|
|
41
|
+
|
|
42
|
+
const objects = await objectStore.listKeys(args.bucket);
|
|
43
|
+
|
|
44
|
+
if (objects.length === 0) {
|
|
45
|
+
tui.info(`No objects found in bucket ${tui.bold(args.bucket)}`);
|
|
46
|
+
return { bucket: args.bucket, objects: [], count: 0 };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
tui.info(`Found ${objects.length} object(s) in ${tui.bold(args.bucket)}:`);
|
|
50
|
+
for (const obj of objects) {
|
|
51
|
+
const sizeMB = (obj.size / (1024 * 1024)).toFixed(2);
|
|
52
|
+
const date = new Date(obj.updated_at).toLocaleString();
|
|
53
|
+
tui.info(` ${tui.bold(obj.key)}: ${sizeMB} MB, updated ${date}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { bucket: args.bucket, objects, count: objects.length };
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export default listKeysSubcommand;
|
|
@@ -0,0 +1,62 @@
|
|
|
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 ObjectStorePutResponseSchema = z.object({
|
|
9
|
+
success: z.boolean().describe('Whether the operation succeeded'),
|
|
10
|
+
bucket: z.string().describe('Bucket name'),
|
|
11
|
+
key: z.string().describe('Object key'),
|
|
12
|
+
size: z.number().describe('Size in bytes'),
|
|
13
|
+
contentType: z.string().describe('Content type'),
|
|
14
|
+
durationMs: z.number().describe('Operation duration in milliseconds'),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const putSubcommand = createCommand({
|
|
18
|
+
name: 'put',
|
|
19
|
+
description: 'Put an object into the object storage',
|
|
20
|
+
tags: ['mutating', 'creates-resource', 'slow', 'requires-auth'],
|
|
21
|
+
idempotent: true,
|
|
22
|
+
requires: { auth: true, project: true },
|
|
23
|
+
examples: [
|
|
24
|
+
`${getCommand('objectstore put uploads images/logo.png @./logo.png')} - Upload logo from file`,
|
|
25
|
+
`${getCommand('objectstore put assets data/config.json \'{"api":"https://api.example.com"}\'')} - Store JSON config`,
|
|
26
|
+
`${getCommand('objectstore put backups db-2024.sql @~/Downloads/backup.sql --content-type application/sql')} - Upload SQL backup`,
|
|
27
|
+
],
|
|
28
|
+
schema: {
|
|
29
|
+
args: z.object({
|
|
30
|
+
bucket: z.string().min(1).max(64).describe('the bucket name'),
|
|
31
|
+
key: z.string().min(1).max(64).describe('the key name'),
|
|
32
|
+
value: z.string().min(1).describe('the value'),
|
|
33
|
+
contentType: z.string().optional().describe('an optional content type'),
|
|
34
|
+
}),
|
|
35
|
+
response: ObjectStorePutResponseSchema,
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async handler(ctx) {
|
|
39
|
+
const { args } = ctx;
|
|
40
|
+
const started = Date.now();
|
|
41
|
+
const storage = await createStorageAdapter(ctx);
|
|
42
|
+
const contentType =
|
|
43
|
+
args.contentType ?? (isPossiblyJSON(args.value) ? 'application/json' : 'text/plain');
|
|
44
|
+
const data = new TextEncoder().encode(args.value);
|
|
45
|
+
await storage.put(args.bucket, args.key, data, {
|
|
46
|
+
contentType,
|
|
47
|
+
});
|
|
48
|
+
const durationMs = Date.now() - started;
|
|
49
|
+
tui.success(`saved in ${durationMs.toFixed(1)}ms (${contentType})`);
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
success: true,
|
|
53
|
+
bucket: args.bucket,
|
|
54
|
+
key: args.key,
|
|
55
|
+
size: data.length,
|
|
56
|
+
contentType,
|
|
57
|
+
durationMs,
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export default putSubcommand;
|