@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.
- package/dist/cmd/build/bundler.d.ts +1 -1
- package/dist/cmd/cloud/agent/get.d.ts +2 -0
- package/dist/cmd/cloud/agent/get.d.ts.map +1 -0
- package/dist/cmd/cloud/agent/get.js +97 -0
- package/dist/cmd/cloud/agent/get.js.map +1 -0
- package/dist/cmd/cloud/agent/index.d.ts +2 -0
- package/dist/cmd/cloud/agent/index.d.ts.map +1 -0
- package/dist/cmd/cloud/agent/index.js +11 -0
- package/dist/cmd/cloud/agent/index.js.map +1 -0
- package/dist/cmd/cloud/agent/list.d.ts +2 -0
- package/dist/cmd/cloud/agent/list.d.ts.map +1 -0
- package/dist/cmd/cloud/agent/list.js +101 -0
- package/dist/cmd/cloud/agent/list.js.map +1 -0
- package/dist/cmd/cloud/agent/schema.d.ts +4 -0
- package/dist/cmd/cloud/agent/schema.d.ts.map +1 -0
- package/dist/cmd/cloud/agent/schema.js +22 -0
- package/dist/cmd/cloud/agent/schema.js.map +1 -0
- package/dist/cmd/cloud/apikey/create.d.ts +2 -0
- package/dist/cmd/cloud/apikey/create.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/create.js +100 -0
- package/dist/cmd/cloud/apikey/create.js.map +1 -0
- package/dist/cmd/cloud/apikey/delete.d.ts +2 -0
- package/dist/cmd/cloud/apikey/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/delete.js +55 -0
- package/dist/cmd/cloud/apikey/delete.js.map +1 -0
- package/dist/cmd/cloud/apikey/get.d.ts +2 -0
- package/dist/cmd/cloud/apikey/get.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/get.js +57 -0
- package/dist/cmd/cloud/apikey/get.js.map +1 -0
- package/dist/cmd/cloud/apikey/index.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/index.js +13 -0
- package/dist/cmd/cloud/apikey/index.js.map +1 -0
- package/dist/cmd/cloud/apikey/list.d.ts +2 -0
- package/dist/cmd/cloud/apikey/list.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/list.js +53 -0
- package/dist/cmd/cloud/apikey/list.js.map +1 -0
- package/dist/cmd/cloud/deployment/index.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/index.js +2 -0
- package/dist/cmd/cloud/deployment/index.js.map +1 -1
- package/dist/cmd/cloud/deployment/logs.d.ts +2 -0
- package/dist/cmd/cloud/deployment/logs.d.ts.map +1 -0
- package/dist/cmd/cloud/deployment/logs.js +70 -0
- package/dist/cmd/cloud/deployment/logs.js.map +1 -0
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/index.js +8 -2
- package/dist/cmd/cloud/index.js.map +1 -1
- package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
- package/dist/cmd/cloud/session/logs.js +12 -9
- package/dist/cmd/cloud/session/logs.js.map +1 -1
- package/dist/cmd/cloud/stream/delete.d.ts +3 -0
- package/dist/cmd/cloud/stream/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/delete.js +42 -0
- package/dist/cmd/cloud/stream/delete.js.map +1 -0
- package/dist/cmd/cloud/stream/get.d.ts +3 -0
- package/dist/cmd/cloud/stream/get.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/get.js +110 -0
- package/dist/cmd/cloud/stream/get.js.map +1 -0
- package/dist/cmd/cloud/stream/index.d.ts +3 -0
- package/dist/cmd/cloud/stream/index.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/index.js +13 -0
- package/dist/cmd/cloud/stream/index.js.map +1 -0
- package/dist/cmd/cloud/stream/list.d.ts +3 -0
- package/dist/cmd/cloud/stream/list.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/list.js +131 -0
- package/dist/cmd/cloud/stream/list.js.map +1 -0
- package/dist/cmd/cloud/stream/util.d.ts +8 -0
- package/dist/cmd/cloud/stream/util.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/util.js +19 -0
- package/dist/cmd/cloud/stream/util.js.map +1 -0
- package/dist/cmd/cloud/vector/delete.d.ts +3 -0
- package/dist/cmd/cloud/vector/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/delete.js +90 -0
- package/dist/cmd/cloud/vector/delete.js.map +1 -0
- package/dist/cmd/cloud/vector/get.d.ts +3 -0
- package/dist/cmd/cloud/vector/get.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/get.js +80 -0
- package/dist/cmd/cloud/vector/get.js.map +1 -0
- package/dist/cmd/cloud/vector/index.d.ts +3 -0
- package/dist/cmd/cloud/vector/index.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/index.js +14 -0
- package/dist/cmd/cloud/vector/index.js.map +1 -0
- package/dist/cmd/cloud/vector/search.d.ts +3 -0
- package/dist/cmd/cloud/vector/search.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/search.js +136 -0
- package/dist/cmd/cloud/vector/search.js.map +1 -0
- package/dist/cmd/cloud/vector/util.d.ts +8 -0
- package/dist/cmd/cloud/vector/util.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/util.js +18 -0
- package/dist/cmd/cloud/vector/util.js.map +1 -0
- package/dist/cmd/dev/agents.d.ts.map +1 -1
- package/dist/cmd/dev/agents.js +3 -2
- package/dist/cmd/dev/agents.js.map +1 -1
- package/dist/cmd/dev/index.js +3 -3
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +38 -42
- package/dist/cmd/index.js.map +1 -1
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/schema-parser.js +3 -1
- package/dist/schema-parser.js.map +1 -1
- package/dist/tui.d.ts +10 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +58 -31
- package/dist/tui.js.map +1 -1
- package/dist/utils/date.d.ts +14 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +51 -0
- package/dist/utils/date.js.map +1 -0
- package/package.json +6 -6
- package/src/cmd/cloud/agent/get.ts +105 -0
- package/src/cmd/cloud/agent/index.ts +11 -0
- package/src/cmd/cloud/agent/list.ts +107 -0
- package/src/cmd/cloud/agent/schema.ts +25 -0
- package/src/cmd/cloud/apikey/create.ts +114 -0
- package/src/cmd/cloud/apikey/delete.ts +66 -0
- package/src/cmd/cloud/apikey/get.ts +62 -0
- package/src/cmd/cloud/apikey/index.ts +13 -0
- package/src/cmd/cloud/apikey/list.ts +58 -0
- package/src/cmd/cloud/deployment/index.ts +2 -0
- package/src/cmd/cloud/deployment/logs.ts +75 -0
- package/src/cmd/cloud/index.ts +8 -2
- package/src/cmd/cloud/session/logs.ts +12 -11
- package/src/cmd/cloud/stream/delete.ts +49 -0
- package/src/cmd/cloud/stream/get.ts +118 -0
- package/src/cmd/cloud/stream/index.ts +14 -0
- package/src/cmd/cloud/stream/list.ts +146 -0
- package/src/cmd/cloud/stream/util.ts +32 -0
- package/src/cmd/cloud/vector/delete.ts +105 -0
- package/src/cmd/cloud/vector/get.ts +94 -0
- package/src/cmd/cloud/vector/index.ts +15 -0
- package/src/cmd/cloud/vector/search.ts +156 -0
- package/src/cmd/cloud/vector/util.ts +28 -0
- package/src/cmd/dev/agents.ts +4 -3
- package/src/cmd/dev/index.ts +3 -3
- package/src/cmd/index.ts +38 -42
- package/src/schema-parser.ts +3 -1
- package/src/tui.ts +69 -36
- package/src/utils/date.ts +57 -0
- package/dist/cmd/cloud/agents/index.d.ts.map +0 -1
- package/dist/cmd/cloud/agents/index.js +0 -133
- package/dist/cmd/cloud/agents/index.js.map +0 -1
- package/src/cmd/cloud/agents/index.ts +0 -148
- /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
|
+
}
|
package/src/cmd/dev/agents.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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')
|
package/src/cmd/dev/index.ts
CHANGED
|
@@ -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() :
|
|
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 {
|