@agentuity/cli 0.0.58 → 0.0.59

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 (143) hide show
  1. package/dist/cmd/build/bundler.d.ts +1 -1
  2. package/dist/cmd/cloud/agent/get.d.ts +2 -0
  3. package/dist/cmd/cloud/agent/get.d.ts.map +1 -0
  4. package/dist/cmd/cloud/agent/get.js +97 -0
  5. package/dist/cmd/cloud/agent/get.js.map +1 -0
  6. package/dist/cmd/cloud/agent/index.d.ts +2 -0
  7. package/dist/cmd/cloud/agent/index.d.ts.map +1 -0
  8. package/dist/cmd/cloud/agent/index.js +11 -0
  9. package/dist/cmd/cloud/agent/index.js.map +1 -0
  10. package/dist/cmd/cloud/agent/list.d.ts +2 -0
  11. package/dist/cmd/cloud/agent/list.d.ts.map +1 -0
  12. package/dist/cmd/cloud/agent/list.js +101 -0
  13. package/dist/cmd/cloud/agent/list.js.map +1 -0
  14. package/dist/cmd/cloud/agent/schema.d.ts +4 -0
  15. package/dist/cmd/cloud/agent/schema.d.ts.map +1 -0
  16. package/dist/cmd/cloud/agent/schema.js +22 -0
  17. package/dist/cmd/cloud/agent/schema.js.map +1 -0
  18. package/dist/cmd/cloud/apikey/create.d.ts +2 -0
  19. package/dist/cmd/cloud/apikey/create.d.ts.map +1 -0
  20. package/dist/cmd/cloud/apikey/create.js +100 -0
  21. package/dist/cmd/cloud/apikey/create.js.map +1 -0
  22. package/dist/cmd/cloud/apikey/delete.d.ts +2 -0
  23. package/dist/cmd/cloud/apikey/delete.d.ts.map +1 -0
  24. package/dist/cmd/cloud/apikey/delete.js +55 -0
  25. package/dist/cmd/cloud/apikey/delete.js.map +1 -0
  26. package/dist/cmd/cloud/apikey/get.d.ts +2 -0
  27. package/dist/cmd/cloud/apikey/get.d.ts.map +1 -0
  28. package/dist/cmd/cloud/apikey/get.js +57 -0
  29. package/dist/cmd/cloud/apikey/get.js.map +1 -0
  30. package/dist/cmd/cloud/apikey/index.d.ts.map +1 -0
  31. package/dist/cmd/cloud/apikey/index.js +13 -0
  32. package/dist/cmd/cloud/apikey/index.js.map +1 -0
  33. package/dist/cmd/cloud/apikey/list.d.ts +2 -0
  34. package/dist/cmd/cloud/apikey/list.d.ts.map +1 -0
  35. package/dist/cmd/cloud/apikey/list.js +53 -0
  36. package/dist/cmd/cloud/apikey/list.js.map +1 -0
  37. package/dist/cmd/cloud/deployment/index.d.ts.map +1 -1
  38. package/dist/cmd/cloud/deployment/index.js +2 -0
  39. package/dist/cmd/cloud/deployment/index.js.map +1 -1
  40. package/dist/cmd/cloud/deployment/logs.d.ts +2 -0
  41. package/dist/cmd/cloud/deployment/logs.d.ts.map +1 -0
  42. package/dist/cmd/cloud/deployment/logs.js +70 -0
  43. package/dist/cmd/cloud/deployment/logs.js.map +1 -0
  44. package/dist/cmd/cloud/index.d.ts.map +1 -1
  45. package/dist/cmd/cloud/index.js +8 -2
  46. package/dist/cmd/cloud/index.js.map +1 -1
  47. package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
  48. package/dist/cmd/cloud/session/logs.js +12 -9
  49. package/dist/cmd/cloud/session/logs.js.map +1 -1
  50. package/dist/cmd/cloud/stream/delete.d.ts +3 -0
  51. package/dist/cmd/cloud/stream/delete.d.ts.map +1 -0
  52. package/dist/cmd/cloud/stream/delete.js +42 -0
  53. package/dist/cmd/cloud/stream/delete.js.map +1 -0
  54. package/dist/cmd/cloud/stream/get.d.ts +3 -0
  55. package/dist/cmd/cloud/stream/get.d.ts.map +1 -0
  56. package/dist/cmd/cloud/stream/get.js +110 -0
  57. package/dist/cmd/cloud/stream/get.js.map +1 -0
  58. package/dist/cmd/cloud/stream/index.d.ts +3 -0
  59. package/dist/cmd/cloud/stream/index.d.ts.map +1 -0
  60. package/dist/cmd/cloud/stream/index.js +13 -0
  61. package/dist/cmd/cloud/stream/index.js.map +1 -0
  62. package/dist/cmd/cloud/stream/list.d.ts +3 -0
  63. package/dist/cmd/cloud/stream/list.d.ts.map +1 -0
  64. package/dist/cmd/cloud/stream/list.js +131 -0
  65. package/dist/cmd/cloud/stream/list.js.map +1 -0
  66. package/dist/cmd/cloud/stream/util.d.ts +8 -0
  67. package/dist/cmd/cloud/stream/util.d.ts.map +1 -0
  68. package/dist/cmd/cloud/stream/util.js +19 -0
  69. package/dist/cmd/cloud/stream/util.js.map +1 -0
  70. package/dist/cmd/cloud/vector/delete.d.ts +3 -0
  71. package/dist/cmd/cloud/vector/delete.d.ts.map +1 -0
  72. package/dist/cmd/cloud/vector/delete.js +90 -0
  73. package/dist/cmd/cloud/vector/delete.js.map +1 -0
  74. package/dist/cmd/cloud/vector/get.d.ts +3 -0
  75. package/dist/cmd/cloud/vector/get.d.ts.map +1 -0
  76. package/dist/cmd/cloud/vector/get.js +80 -0
  77. package/dist/cmd/cloud/vector/get.js.map +1 -0
  78. package/dist/cmd/cloud/vector/index.d.ts +3 -0
  79. package/dist/cmd/cloud/vector/index.d.ts.map +1 -0
  80. package/dist/cmd/cloud/vector/index.js +14 -0
  81. package/dist/cmd/cloud/vector/index.js.map +1 -0
  82. package/dist/cmd/cloud/vector/search.d.ts +3 -0
  83. package/dist/cmd/cloud/vector/search.d.ts.map +1 -0
  84. package/dist/cmd/cloud/vector/search.js +136 -0
  85. package/dist/cmd/cloud/vector/search.js.map +1 -0
  86. package/dist/cmd/cloud/vector/util.d.ts +8 -0
  87. package/dist/cmd/cloud/vector/util.d.ts.map +1 -0
  88. package/dist/cmd/cloud/vector/util.js +18 -0
  89. package/dist/cmd/cloud/vector/util.js.map +1 -0
  90. package/dist/cmd/dev/agents.d.ts.map +1 -1
  91. package/dist/cmd/dev/agents.js +3 -2
  92. package/dist/cmd/dev/agents.js.map +1 -1
  93. package/dist/cmd/dev/index.js +3 -3
  94. package/dist/cmd/dev/index.js.map +1 -1
  95. package/dist/cmd/index.d.ts.map +1 -1
  96. package/dist/cmd/index.js +38 -42
  97. package/dist/cmd/index.js.map +1 -1
  98. package/dist/schema-parser.d.ts.map +1 -1
  99. package/dist/schema-parser.js +3 -1
  100. package/dist/schema-parser.js.map +1 -1
  101. package/dist/tui.d.ts +10 -1
  102. package/dist/tui.d.ts.map +1 -1
  103. package/dist/tui.js +58 -31
  104. package/dist/tui.js.map +1 -1
  105. package/dist/utils/date.d.ts +14 -0
  106. package/dist/utils/date.d.ts.map +1 -0
  107. package/dist/utils/date.js +51 -0
  108. package/dist/utils/date.js.map +1 -0
  109. package/package.json +6 -6
  110. package/src/cmd/cloud/agent/get.ts +105 -0
  111. package/src/cmd/cloud/agent/index.ts +11 -0
  112. package/src/cmd/cloud/agent/list.ts +107 -0
  113. package/src/cmd/cloud/agent/schema.ts +25 -0
  114. package/src/cmd/cloud/apikey/create.ts +114 -0
  115. package/src/cmd/cloud/apikey/delete.ts +66 -0
  116. package/src/cmd/cloud/apikey/get.ts +62 -0
  117. package/src/cmd/cloud/apikey/index.ts +13 -0
  118. package/src/cmd/cloud/apikey/list.ts +58 -0
  119. package/src/cmd/cloud/deployment/index.ts +2 -0
  120. package/src/cmd/cloud/deployment/logs.ts +75 -0
  121. package/src/cmd/cloud/index.ts +8 -2
  122. package/src/cmd/cloud/session/logs.ts +12 -11
  123. package/src/cmd/cloud/stream/delete.ts +49 -0
  124. package/src/cmd/cloud/stream/get.ts +118 -0
  125. package/src/cmd/cloud/stream/index.ts +14 -0
  126. package/src/cmd/cloud/stream/list.ts +146 -0
  127. package/src/cmd/cloud/stream/util.ts +32 -0
  128. package/src/cmd/cloud/vector/delete.ts +105 -0
  129. package/src/cmd/cloud/vector/get.ts +94 -0
  130. package/src/cmd/cloud/vector/index.ts +15 -0
  131. package/src/cmd/cloud/vector/search.ts +156 -0
  132. package/src/cmd/cloud/vector/util.ts +28 -0
  133. package/src/cmd/dev/agents.ts +4 -3
  134. package/src/cmd/dev/index.ts +3 -3
  135. package/src/cmd/index.ts +38 -42
  136. package/src/schema-parser.ts +3 -1
  137. package/src/tui.ts +69 -36
  138. package/src/utils/date.ts +57 -0
  139. package/dist/cmd/cloud/agents/index.d.ts.map +0 -1
  140. package/dist/cmd/cloud/agents/index.js +0 -133
  141. package/dist/cmd/cloud/agents/index.js.map +0 -1
  142. package/src/cmd/cloud/agents/index.ts +0 -148
  143. /package/dist/cmd/cloud/{agents → apikey}/index.d.ts +0 -0
@@ -0,0 +1,146 @@
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
+ function formatBytes(bytes: number): string {
8
+ if (bytes === 0) return '0 B';
9
+ if (bytes < 1024) return `${bytes} B`;
10
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
11
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
12
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
13
+ }
14
+
15
+ const StreamInfoSchema = z.object({
16
+ id: z.string().describe('Stream ID'),
17
+ name: z.string().describe('Stream name'),
18
+ metadata: z.record(z.string(), z.string()).describe('Stream metadata'),
19
+ url: z.string().describe('Public URL'),
20
+ sizeBytes: z.number().describe('Size in bytes'),
21
+ });
22
+
23
+ const ListStreamsResponseSchema = z.object({
24
+ streams: z.array(StreamInfoSchema).describe('List of streams'),
25
+ total: z.number().describe('Total count of matching streams'),
26
+ });
27
+
28
+ export const listSubcommand = createCommand({
29
+ name: 'list',
30
+ aliases: ['ls'],
31
+ description: 'List recent streams with optional filtering',
32
+ tags: ['read-only', 'slow', 'requires-auth'],
33
+ requires: { auth: true, project: true },
34
+ idempotent: true,
35
+ examples: [
36
+ `${getCommand('stream list')} - List all streams`,
37
+ `${getCommand('stream ls --size 50')} - List 50 most recent streams`,
38
+ `${getCommand('stream list --name agent-logs')} - Filter by name`,
39
+ `${getCommand('stream list --metadata type=export')} - Filter by metadata`,
40
+ `${getCommand('stream ls --json')} - Output as JSON`,
41
+ ],
42
+ schema: {
43
+ options: z.object({
44
+ size: z.number().optional().describe('maximum number of streams to return (default: 100)'),
45
+ offset: z.number().optional().describe('number of streams to skip for pagination'),
46
+ name: z.string().optional().describe('filter by stream name'),
47
+ metadata: z
48
+ .string()
49
+ .optional()
50
+ .describe('filter by metadata (format: key=value or key1=value1,key2=value2)'),
51
+ }),
52
+ response: ListStreamsResponseSchema,
53
+ },
54
+
55
+ async handler(ctx) {
56
+ const { opts, options } = ctx;
57
+ const storage = await createStorageAdapter(ctx);
58
+
59
+ // Parse metadata filter if provided
60
+ let metadataFilter: Record<string, string> | undefined;
61
+ if (opts.metadata) {
62
+ const validPairs: Record<string, string> = {};
63
+ const malformed: string[] = [];
64
+ const pairs = opts.metadata.split(',');
65
+
66
+ for (const pair of pairs) {
67
+ const trimmedPair = pair.trim();
68
+ if (!trimmedPair) continue;
69
+
70
+ const firstEqualIdx = trimmedPair.indexOf('=');
71
+ if (firstEqualIdx === -1) {
72
+ malformed.push(trimmedPair);
73
+ continue;
74
+ }
75
+
76
+ const key = trimmedPair.substring(0, firstEqualIdx).trim();
77
+ const value = trimmedPair.substring(firstEqualIdx + 1).trim();
78
+
79
+ if (!key || !value) {
80
+ malformed.push(trimmedPair);
81
+ continue;
82
+ }
83
+
84
+ validPairs[key] = value;
85
+ }
86
+
87
+ if (malformed.length > 0) {
88
+ ctx.logger.warn(`Skipping malformed metadata pairs: ${malformed.join(', ')}`);
89
+ }
90
+
91
+ if (Object.keys(validPairs).length > 0) {
92
+ metadataFilter = validPairs;
93
+ }
94
+ }
95
+
96
+ const result = await storage.list({
97
+ limit: opts.size,
98
+ offset: opts.offset,
99
+ name: opts.name,
100
+ metadata: metadataFilter,
101
+ });
102
+
103
+ if (options.json) {
104
+ console.log(JSON.stringify(result, null, 2));
105
+ return {
106
+ streams: result.streams,
107
+ total: result.total,
108
+ };
109
+ }
110
+
111
+ if (result.streams.length === 0) {
112
+ tui.info('No streams found');
113
+ } else {
114
+ const tableData = result.streams.map((stream) => {
115
+ const sizeBytes = stream.sizeBytes ?? 0;
116
+ const metadataStr =
117
+ Object.keys(stream.metadata).length > 0 ? JSON.stringify(stream.metadata) : '-';
118
+ return {
119
+ Name: stream.name,
120
+ ID: stream.id,
121
+ Size: formatBytes(sizeBytes),
122
+ Metadata:
123
+ metadataStr.length > 40 ? metadataStr.substring(0, 37) + '...' : metadataStr,
124
+ URL: tui.link(stream.url),
125
+ };
126
+ });
127
+
128
+ tui.table(tableData, [
129
+ { name: 'Name', alignment: 'left' },
130
+ { name: 'ID', alignment: 'left' },
131
+ { name: 'Size', alignment: 'right' },
132
+ { name: 'Metadata', alignment: 'left' },
133
+ { name: 'URL', alignment: 'left' },
134
+ ]);
135
+
136
+ tui.info(`Total: ${result.total} stream(s)`);
137
+ }
138
+
139
+ return {
140
+ streams: result.streams,
141
+ total: result.total,
142
+ };
143
+ },
144
+ });
145
+
146
+ export default listSubcommand;
@@ -0,0 +1,32 @@
1
+ import { StreamStorageService, 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?.stream_url ?? 'https://stream.agentuity.cloud';
31
+ return new StreamStorageService(baseUrl, adapter);
32
+ }
@@ -0,0 +1,105 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../../types';
3
+ import { ErrorCode } from '../../../errors';
4
+ import * as tui from '../../../tui';
5
+ import { createStorageAdapter } from './util';
6
+ import { getCommand } from '../../../command-prefix';
7
+
8
+ const VectorDeleteResponseSchema = z.object({
9
+ success: z.boolean().describe('Whether the operation succeeded'),
10
+ namespace: z.string().describe('Namespace name'),
11
+ keys: z.array(z.string()).describe('Keys that were deleted'),
12
+ deleted: z.number().describe('Number of vectors deleted'),
13
+ durationMs: z.number().describe('Operation duration in milliseconds'),
14
+ message: z.string().optional().describe('Confirmation message'),
15
+ });
16
+
17
+ export const deleteSubcommand = createCommand({
18
+ name: 'delete',
19
+ aliases: ['del', 'rm'],
20
+ description: 'Delete one or more vectors by key',
21
+ tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
22
+ requires: { auth: true, project: true },
23
+ idempotent: true,
24
+ examples: [
25
+ `${getCommand('vector delete products chair-001')} - Delete a single vector (interactive)`,
26
+ `${getCommand('vector rm knowledge-base doc-123 doc-456 --confirm')} - Delete multiple vectors without confirmation`,
27
+ `${getCommand('vector del embeddings old-profile-1 old-profile-2 --confirm')} - Bulk delete without confirmation`,
28
+ ],
29
+ schema: {
30
+ args: z.object({
31
+ namespace: z.string().min(1).describe('the vector storage namespace'),
32
+ keys: z.array(z.string().min(1)).min(1).describe('one or more keys to delete'),
33
+ }),
34
+ options: z.object({
35
+ confirm: z
36
+ .boolean()
37
+ .optional()
38
+ .default(false)
39
+ .describe('if true will not prompt for confirmation'),
40
+ }),
41
+ response: VectorDeleteResponseSchema,
42
+ },
43
+
44
+ async handler(ctx) {
45
+ const { args, options, opts } = ctx;
46
+
47
+ if (!opts.confirm) {
48
+ if (!process.stdin.isTTY) {
49
+ tui.fatal(
50
+ 'No TTY and --confirm is not set. Refusing to delete',
51
+ ErrorCode.VALIDATION_FAILED
52
+ );
53
+ }
54
+ const keyList = args.keys.length > 3 ? `${args.keys.slice(0, 3).join(', ')}...` : args.keys.join(', ');
55
+ tui.warning(`This will delete ${args.keys.length} vector(s) from ${tui.bold(args.namespace)}: ${keyList}`);
56
+ const confirm = await new Promise<boolean>((resolve) => {
57
+ process.stdout.write('Are you sure? (yes/no): ');
58
+ process.stdin.once('data', (data) => {
59
+ const answer = data.toString().trim().toLowerCase();
60
+ resolve(answer === 'yes' || answer === 'y');
61
+ });
62
+ });
63
+
64
+ if (!confirm) {
65
+ tui.info('Cancelled');
66
+ return {
67
+ success: false,
68
+ namespace: args.namespace,
69
+ keys: args.keys,
70
+ deleted: 0,
71
+ durationMs: 0,
72
+ message: 'Cancelled',
73
+ };
74
+ }
75
+ }
76
+
77
+ const storage = await createStorageAdapter(ctx);
78
+ const started = Date.now();
79
+
80
+ const deleted = await storage.delete(args.namespace, ...args.keys);
81
+ const durationMs = Date.now() - started;
82
+
83
+ if (!options.json) {
84
+ if (deleted > 0) {
85
+ tui.success(
86
+ `Deleted ${deleted} vector(s) from ${tui.bold(args.namespace)} (${durationMs}ms)`
87
+ );
88
+ } else {
89
+ tui.warning(
90
+ `No vectors were deleted from ${tui.bold(args.namespace)} (keys may not exist)`
91
+ );
92
+ }
93
+ }
94
+
95
+ return {
96
+ success: true,
97
+ namespace: args.namespace,
98
+ keys: args.keys,
99
+ deleted,
100
+ durationMs,
101
+ };
102
+ },
103
+ });
104
+
105
+ export default deleteSubcommand;
@@ -0,0 +1,94 @@
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 VectorGetResponseSchema = z.object({
8
+ exists: z.boolean().describe('Whether the vector exists'),
9
+ key: z.string().optional().describe('Vector key'),
10
+ id: z.string().optional().describe('Vector ID'),
11
+ metadata: z.record(z.string(), z.unknown()).optional().describe('Vector metadata'),
12
+ document: z.string().optional().describe('Original document text'),
13
+ similarity: z.number().optional().describe('Similarity score'),
14
+ });
15
+
16
+ export const getSubcommand = createCommand({
17
+ name: 'get',
18
+ description: 'Get a specific vector entry by key',
19
+ tags: ['read-only', 'fast', 'requires-auth'],
20
+ requires: { auth: true, project: true },
21
+ idempotent: true,
22
+ examples: [
23
+ `${getCommand('vector get products chair-001')} - Get a specific product vector`,
24
+ `${getCommand('vector get knowledge-base doc-123')} - Get a document from knowledge base`,
25
+ `${getCommand('vector get embeddings user-profile-456')} - Get user profile embedding`,
26
+ ],
27
+ schema: {
28
+ args: z.object({
29
+ namespace: z.string().min(1).describe('the vector storage namespace'),
30
+ key: z.string().min(1).describe('the key of the vector to retrieve'),
31
+ }),
32
+ response: VectorGetResponseSchema,
33
+ },
34
+
35
+ async handler(ctx) {
36
+ const { args, options } = ctx;
37
+ const storage = await createStorageAdapter(ctx);
38
+ const started = Date.now();
39
+
40
+ const result = await storage.get(args.namespace, args.key);
41
+ const durationMs = Date.now() - started;
42
+
43
+ if (!options.json) {
44
+ if (result.exists) {
45
+ tui.success(
46
+ `Found vector "${tui.bold(args.key)}" in ${tui.bold(args.namespace)} (${durationMs}ms)`
47
+ );
48
+
49
+ const data = result.data;
50
+ tui.info(` ID: ${data.id}`);
51
+ tui.info(` Key: ${data.key}`);
52
+
53
+ if (data.similarity !== undefined) {
54
+ tui.info(` Similarity: ${(data.similarity * 100).toFixed(1)}%`);
55
+ }
56
+
57
+ if (data.document) {
58
+ const docPreview =
59
+ data.document.length > 200
60
+ ? data.document.substring(0, 197) + '...'
61
+ : data.document;
62
+ tui.info(` Document: ${docPreview}`);
63
+ }
64
+
65
+ if (data.metadata && Object.keys(data.metadata).length > 0) {
66
+ tui.info(` Metadata: ${JSON.stringify(data.metadata, null, 2)}`);
67
+ }
68
+
69
+ if (data.embeddings) {
70
+ tui.info(` Embeddings: [${data.embeddings.length} dimensions]`);
71
+ }
72
+ } else {
73
+ tui.warning(`Vector "${tui.bold(args.key)}" not found in ${tui.bold(args.namespace)}`);
74
+ }
75
+ }
76
+
77
+ if (result.exists) {
78
+ return {
79
+ exists: true,
80
+ key: result.data.key,
81
+ id: result.data.id,
82
+ metadata: result.data.metadata,
83
+ document: result.data.document,
84
+ similarity: result.data.similarity,
85
+ };
86
+ }
87
+
88
+ return {
89
+ exists: false,
90
+ };
91
+ },
92
+ });
93
+
94
+ export default getSubcommand;
@@ -0,0 +1,15 @@
1
+ import { createCommand } from '../../../types';
2
+ import { deleteSubcommand } from './delete';
3
+ import { getSubcommand } from './get';
4
+ import { searchSubcommand } from './search';
5
+
6
+ export const vectorCommand = createCommand({
7
+ name: 'vector',
8
+ aliases: ['vec'],
9
+ description: 'Manage vector storage for your projects',
10
+ tags: ['requires-auth', 'destructive', 'deletes-resource', 'slow'],
11
+ subcommands: [searchSubcommand, getSubcommand, deleteSubcommand],
12
+ requires: { auth: true, project: true },
13
+ });
14
+
15
+ export default vectorCommand;
@@ -0,0 +1,156 @@
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 VectorSearchResultSchema = z.object({
8
+ id: z.string().describe('Vector ID'),
9
+ key: z.string().describe('Vector key'),
10
+ similarity: z.number().describe('Similarity score (0-1)'),
11
+ metadata: z.record(z.string(), z.unknown()).optional().describe('Vector metadata'),
12
+ });
13
+
14
+ const VectorSearchResponseSchema = z.object({
15
+ namespace: z.string().describe('Namespace name'),
16
+ query: z.string().describe('Search query used'),
17
+ results: z.array(VectorSearchResultSchema).describe('Search results'),
18
+ count: z.number().describe('Number of results found'),
19
+ });
20
+
21
+ export const searchSubcommand = createCommand({
22
+ name: 'search',
23
+ aliases: ['list', 'ls'],
24
+ description: 'Search for vectors using semantic similarity',
25
+ tags: ['read-only', 'slow', 'requires-auth'],
26
+ requires: { auth: true, project: true },
27
+ idempotent: true,
28
+ examples: [
29
+ `${getCommand('vector search products "comfortable office chair"')} - Search for similar products`,
30
+ `${getCommand('vector list knowledge-base "machine learning"')} - Search knowledge base`,
31
+ `${getCommand('vector search docs "API documentation" --limit 5')} - Limit results`,
32
+ `${getCommand('vector search products "ergonomic" --similarity 0.8')} - Set minimum similarity`,
33
+ `${getCommand('vector ls embeddings "neural networks" --metadata category=ai')} - Filter by metadata`,
34
+ ],
35
+ schema: {
36
+ args: z.object({
37
+ namespace: z.string().min(1).describe('the vector storage namespace'),
38
+ query: z.string().min(1).describe('the search query text'),
39
+ }),
40
+ options: z.object({
41
+ limit: z.number().optional().describe('maximum number of results to return (default: 10)'),
42
+ similarity: z
43
+ .number()
44
+ .min(0)
45
+ .max(1)
46
+ .optional()
47
+ .describe('minimum similarity threshold (0.0-1.0)'),
48
+ metadata: z
49
+ .string()
50
+ .optional()
51
+ .describe('filter by metadata (format: key=value or key1=value1,key2=value2)'),
52
+ }),
53
+ response: VectorSearchResponseSchema,
54
+ },
55
+
56
+ async handler(ctx) {
57
+ const { args, opts, options } = ctx;
58
+ const storage = await createStorageAdapter(ctx);
59
+ const started = Date.now();
60
+
61
+ // Parse metadata filter if provided
62
+ let metadataFilter: Record<string, unknown> | undefined;
63
+ if (opts.metadata) {
64
+ const validPairs: Record<string, unknown> = {};
65
+ const malformed: string[] = [];
66
+ const pairs = opts.metadata.split(',');
67
+
68
+ for (const pair of pairs) {
69
+ const trimmedPair = pair.trim();
70
+ if (!trimmedPair) continue;
71
+
72
+ const firstEqualIdx = trimmedPair.indexOf('=');
73
+ if (firstEqualIdx === -1) {
74
+ malformed.push(trimmedPair);
75
+ continue;
76
+ }
77
+
78
+ const key = trimmedPair.substring(0, firstEqualIdx).trim();
79
+ const value = trimmedPair.substring(firstEqualIdx + 1).trim();
80
+
81
+ if (!key || !value) {
82
+ malformed.push(trimmedPair);
83
+ continue;
84
+ }
85
+
86
+ // Try to parse as JSON for complex values, otherwise use as string
87
+ try {
88
+ validPairs[key] = JSON.parse(value);
89
+ } catch {
90
+ validPairs[key] = value;
91
+ }
92
+ }
93
+
94
+ if (malformed.length > 0) {
95
+ ctx.logger.warn(`Skipping malformed metadata pairs: ${malformed.join(', ')}`);
96
+ }
97
+
98
+ if (Object.keys(validPairs).length > 0) {
99
+ metadataFilter = validPairs;
100
+ }
101
+ }
102
+
103
+ const results = await storage.search(args.namespace, {
104
+ query: args.query,
105
+ limit: opts.limit,
106
+ similarity: opts.similarity,
107
+ metadata: metadataFilter,
108
+ });
109
+
110
+ const durationMs = Date.now() - started;
111
+
112
+ if (!options.json) {
113
+ if (results.length === 0) {
114
+ tui.info(
115
+ `No vectors found matching "${tui.bold(args.query)}" in ${tui.bold(args.namespace)}`
116
+ );
117
+ } else {
118
+ tui.info(
119
+ `Found ${results.length} result(s) in ${tui.bold(args.namespace)} (${durationMs}ms):`
120
+ );
121
+
122
+ const tableData = results.map((result) => {
123
+ const metadataStr = result.metadata ? JSON.stringify(result.metadata) : '-';
124
+ return {
125
+ Key: result.key,
126
+ ID: result.id,
127
+ Similarity: `${(result.similarity * 100).toFixed(1)}%`,
128
+ Metadata:
129
+ metadataStr.length > 50 ? metadataStr.substring(0, 47) + '...' : metadataStr,
130
+ };
131
+ });
132
+
133
+ tui.table(tableData, [
134
+ { name: 'Key', alignment: 'left' },
135
+ { name: 'ID', alignment: 'left' },
136
+ { name: 'Similarity', alignment: 'right' },
137
+ { name: 'Metadata', alignment: 'left' },
138
+ ]);
139
+ }
140
+ }
141
+
142
+ return {
143
+ namespace: args.namespace,
144
+ query: args.query,
145
+ results: results.map((r) => ({
146
+ id: r.id,
147
+ key: r.key,
148
+ similarity: r.similarity,
149
+ metadata: r.metadata,
150
+ })),
151
+ count: results.length,
152
+ };
153
+ },
154
+ });
155
+
156
+ export default searchSubcommand;
@@ -0,0 +1,28 @@
1
+ import { Logger, VectorStorageService } from '@agentuity/core';
2
+ import { createServerFetchAdapter } from '@agentuity/server';
3
+ import { loadProjectSDKKey } from '../../../config';
4
+ import type { Config } from '../../../types';
5
+ import * as tui from '../../../tui';
6
+
7
+ export async function createStorageAdapter(ctx: {
8
+ logger: Logger;
9
+ projectDir: string;
10
+ config: Config | null;
11
+ }) {
12
+ const sdkKey = await loadProjectSDKKey(ctx.projectDir);
13
+ if (!sdkKey) {
14
+ tui.fatal(`Couldn't find the AGENTUITY_SDK_KEY in ${ctx.projectDir} .env file`);
15
+ }
16
+
17
+ const adapter = createServerFetchAdapter(
18
+ {
19
+ headers: {
20
+ Authorization: `Bearer ${sdkKey}`,
21
+ },
22
+ },
23
+ ctx.logger
24
+ );
25
+
26
+ const baseUrl = ctx.config?.overrides?.catalyst_url ?? 'https://catalyst.agentuity.cloud';
27
+ return new VectorStorageService(baseUrl, adapter);
28
+ }
@@ -8,7 +8,7 @@ const AgentSchema = z.object({
8
8
  id: z.string(),
9
9
  name: z.string(),
10
10
  description: z.string().nullable(),
11
- identifier: z.string(),
11
+ identifier: z.string().nullable(), // nullable for legacy records
12
12
  version: z.string().nullable(),
13
13
  deploymentId: z.string().nullable(),
14
14
  devmode: z.boolean(),
@@ -75,7 +75,8 @@ export const agentsSubcommand = createSubcommand({
75
75
  tui.fatal(`Failed to fetch agents: ${response.message ?? 'Unknown error'}`);
76
76
  }
77
77
 
78
- const agents = response.data;
78
+ // Filter out legacy agents without identifiers
79
+ const agents = response.data.filter((agent) => agent.identifier !== null);
79
80
 
80
81
  if (format === 'json' && !options.json) {
81
82
  console.log(JSON.stringify(agents, null, 2));
@@ -91,7 +92,7 @@ export const agentsSubcommand = createSubcommand({
91
92
  agents.map((agent) => ({
92
93
  name: agent.name,
93
94
  id: verbose ? agent.id : abbreviate(agent.id, 20),
94
- identifier: verbose ? agent.identifier : abbreviate(agent.identifier, 20),
95
+ identifier: verbose ? agent.identifier! : abbreviate(agent.identifier!, 20),
95
96
  deployment: abbreviate(agent.deploymentId, 20),
96
97
  version: verbose
97
98
  ? (agent.version ?? 'N/A')
@@ -110,7 +110,7 @@ export const command = createCommand({
110
110
  );
111
111
  const deploymentId = getDevmodeDeploymentId(project?.projectId ?? '', devmode?.id ?? '');
112
112
 
113
- if (devmode) {
113
+ if (devmode && opts.public) {
114
114
  const configDir = getDefaultConfigDir();
115
115
  const gravityDir = join(configDir, 'gravity');
116
116
  let mustCheck = true;
@@ -242,7 +242,7 @@ export const command = createCommand({
242
242
  if (!sdkKey) {
243
243
  tui.warning(`Couldn't find the AGENTUITY_SDK_KEY in ${rootDir} .env file`);
244
244
  }
245
- const gravityBinExists = gravityBin ? await Bun.file(gravityBin).exists() : undefined;
245
+ const gravityBinExists = gravityBin ? await Bun.file(gravityBin).exists() : true;
246
246
  if (!gravityBinExists) {
247
247
  logger.error(`Gravity binary not found at ${gravityBin}, skipping gravity client startup`);
248
248
  }
@@ -252,7 +252,7 @@ export const command = createCommand({
252
252
  gravityClient.kill('SIGINT');
253
253
  gravityClient.kill();
254
254
  }
255
- if (!devmode) {
255
+ if (!devmode || !opts.public) {
256
256
  return;
257
257
  }
258
258
  try {