@agentuity/cli 0.0.57 → 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/build/bundler.js +8 -9
- package/dist/cmd/build/bundler.js.map +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/get.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.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +103 -55
- 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 +67 -41
- 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/build/bundler.ts +8 -8
- 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/get.ts +5 -5
- 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 +114 -59
- package/src/cmd/index.ts +38 -42
- package/src/schema-parser.ts +3 -1
- package/src/tui.ts +80 -48
- 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,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;
|
|
@@ -238,48 +238,52 @@ export const command = createCommand({
|
|
|
238
238
|
let gravityClient: Bun.Subprocess | undefined;
|
|
239
239
|
let initialStartupComplete = false;
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
logger.error(
|
|
278
|
-
'Failed to spawn gravity client: %s',
|
|
279
|
-
err instanceof Error ? err.message : String(err)
|
|
280
|
-
);
|
|
241
|
+
const sdkKey = await loadProjectSDKKey(rootDir);
|
|
242
|
+
if (!sdkKey) {
|
|
243
|
+
tui.warning(`Couldn't find the AGENTUITY_SDK_KEY in ${rootDir} .env file`);
|
|
244
|
+
}
|
|
245
|
+
const gravityBinExists = gravityBin ? await Bun.file(gravityBin).exists() : true;
|
|
246
|
+
if (!gravityBinExists) {
|
|
247
|
+
logger.error(`Gravity binary not found at ${gravityBin}, skipping gravity client startup`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
async function restartGravityClient() {
|
|
251
|
+
if (gravityClient) {
|
|
252
|
+
gravityClient.kill('SIGINT');
|
|
253
|
+
gravityClient.kill();
|
|
254
|
+
}
|
|
255
|
+
if (!devmode || !opts.public) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
gravityClient = Bun.spawn(
|
|
260
|
+
[
|
|
261
|
+
gravityBin!,
|
|
262
|
+
'--endpoint-id',
|
|
263
|
+
devmode.id,
|
|
264
|
+
'--port',
|
|
265
|
+
env.PORT!,
|
|
266
|
+
'--url',
|
|
267
|
+
config?.overrides?.gravity_url ?? 'grpc://devmode.agentuity.com',
|
|
268
|
+
'--log-level',
|
|
269
|
+
process.env.AGENTUITY_GRAVITY_LOG_LEVEL ?? 'error',
|
|
270
|
+
],
|
|
271
|
+
{
|
|
272
|
+
cwd: rootDir,
|
|
273
|
+
stdout: 'inherit',
|
|
274
|
+
stderr: 'inherit',
|
|
275
|
+
stdin: 'ignore',
|
|
276
|
+
env: { ...env, AGENTUITY_SDK_KEY: sdkKey },
|
|
281
277
|
}
|
|
282
|
-
|
|
278
|
+
);
|
|
279
|
+
gravityClient.exited.then(() => {
|
|
280
|
+
logger.debug('gravity client exited');
|
|
281
|
+
});
|
|
282
|
+
} catch (err) {
|
|
283
|
+
logger.error(
|
|
284
|
+
'Failed to spawn gravity client: %s',
|
|
285
|
+
err instanceof Error ? err.message : String(err)
|
|
286
|
+
);
|
|
283
287
|
}
|
|
284
288
|
}
|
|
285
289
|
|
|
@@ -307,14 +311,42 @@ export const command = createCommand({
|
|
|
307
311
|
}
|
|
308
312
|
}
|
|
309
313
|
|
|
314
|
+
let lastErrorLineCount = 0;
|
|
315
|
+
let showedRestartMessage = false;
|
|
316
|
+
|
|
317
|
+
function clearRestartMessage() {
|
|
318
|
+
if (showedRestartMessage) {
|
|
319
|
+
process.stdout.write('\x1b[1A\x1b[2K');
|
|
320
|
+
showedRestartMessage = false;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
310
324
|
function failure(msg: string) {
|
|
311
325
|
failed = true;
|
|
312
326
|
failures++;
|
|
327
|
+
// Exit immediately on initial startup failure
|
|
328
|
+
if (!initialStartupComplete) {
|
|
329
|
+
tui.fatal(msg);
|
|
330
|
+
}
|
|
331
|
+
// During hot reload, show error but don't exit unless too many failures
|
|
313
332
|
if (failures >= 5) {
|
|
314
333
|
tui.error(msg);
|
|
315
334
|
tui.fatal('too many failures, exiting');
|
|
316
335
|
} else {
|
|
317
|
-
|
|
336
|
+
// Ensure we're on a new line before printing error
|
|
337
|
+
tui.error(msg);
|
|
338
|
+
// Track lines: 1 for "✗ Building..." + 1 for error message
|
|
339
|
+
lastErrorLineCount = 2;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function clearLastError() {
|
|
344
|
+
if (lastErrorLineCount > 0) {
|
|
345
|
+
// Move cursor up and clear each line
|
|
346
|
+
for (let i = 0; i < lastErrorLineCount; i++) {
|
|
347
|
+
process.stdout.write('\x1b[1A\x1b[2K');
|
|
348
|
+
}
|
|
349
|
+
lastErrorLineCount = 0;
|
|
318
350
|
}
|
|
319
351
|
}
|
|
320
352
|
|
|
@@ -406,6 +438,7 @@ export const command = createCommand({
|
|
|
406
438
|
logger.trace('Server is running, killing before restart');
|
|
407
439
|
checkRestartThrottle();
|
|
408
440
|
tui.info('Restarting on file change');
|
|
441
|
+
showedRestartMessage = true;
|
|
409
442
|
await kill();
|
|
410
443
|
logger.trace('Server killed, continuing with restart');
|
|
411
444
|
// Continue with restart after kill completes
|
|
@@ -413,11 +446,16 @@ export const command = createCommand({
|
|
|
413
446
|
logger.trace('Initial server start');
|
|
414
447
|
}
|
|
415
448
|
logger.trace('Starting typecheck and build...');
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
449
|
+
|
|
450
|
+
// Clear any previous error before starting new build
|
|
451
|
+
clearLastError();
|
|
452
|
+
clearRestartMessage();
|
|
453
|
+
|
|
454
|
+
try {
|
|
455
|
+
await tui.spinner({
|
|
456
|
+
message: 'Building...',
|
|
457
|
+
clearOnSuccess: true,
|
|
458
|
+
callback: async () => {
|
|
421
459
|
logger.trace('Bundle starting...');
|
|
422
460
|
building = true;
|
|
423
461
|
await bundle({
|
|
@@ -431,7 +469,7 @@ export const command = createCommand({
|
|
|
431
469
|
buildCompletedAt = Date.now();
|
|
432
470
|
logger.trace('Bundle completed successfully');
|
|
433
471
|
logger.trace('tsc starting...');
|
|
434
|
-
await tui.runCommand({
|
|
472
|
+
const tscExitCode = await tui.runCommand({
|
|
435
473
|
command: 'tsc',
|
|
436
474
|
cmd: ['bunx', 'tsc', '--noEmit'],
|
|
437
475
|
cwd: rootDir,
|
|
@@ -440,15 +478,32 @@ export const command = createCommand({
|
|
|
440
478
|
maxLinesOutput: 2,
|
|
441
479
|
maxLinesOnFailure: 15,
|
|
442
480
|
});
|
|
481
|
+
if (tscExitCode !== 0) {
|
|
482
|
+
logger.trace('tsc failed with exit code %d', tscExitCode);
|
|
483
|
+
failure('Type check failed');
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
443
486
|
logger.trace('tsc completed successfully');
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
487
|
+
await restartGravityClient();
|
|
488
|
+
},
|
|
489
|
+
});
|
|
490
|
+
} catch (error) {
|
|
491
|
+
building = false;
|
|
492
|
+
const e = error as Error;
|
|
493
|
+
if (e.constructor.name === 'AggregateError') {
|
|
494
|
+
const ex = e as AggregateError;
|
|
495
|
+
for (const err of ex.errors) {
|
|
496
|
+
if (err) {
|
|
497
|
+
failure(err);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
449
500
|
}
|
|
450
|
-
|
|
451
|
-
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
504
|
+
failure(errorMsg);
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
452
507
|
|
|
453
508
|
logger.trace('Typecheck and build completed');
|
|
454
509
|
|
|
@@ -457,6 +512,9 @@ export const command = createCommand({
|
|
|
457
512
|
return;
|
|
458
513
|
}
|
|
459
514
|
|
|
515
|
+
// Reset failure counter on successful build
|
|
516
|
+
failures = 0;
|
|
517
|
+
|
|
460
518
|
logger.trace('Checking if app file exists: %s', appPath);
|
|
461
519
|
if (!existsSync(appPath)) {
|
|
462
520
|
logger.trace('App file not found: %s', appPath);
|
|
@@ -548,9 +606,6 @@ export const command = createCommand({
|
|
|
548
606
|
|
|
549
607
|
if (showInitialReadyMessage) {
|
|
550
608
|
showInitialReadyMessage = false;
|
|
551
|
-
// Clear any lingering spinner/command output - clear everything below cursor
|
|
552
|
-
process.stderr.write('\x1B[J'); // Clear from cursor to end of screen
|
|
553
|
-
process.stdout.write('\x1B[J'); // Clear from cursor to end of screen
|
|
554
609
|
logger.info('DevMode ready 🚀');
|
|
555
610
|
logger.trace('Initial ready message logged');
|
|
556
611
|
// Mark initial startup complete immediately to prevent watcher restarts
|
package/src/cmd/index.ts
CHANGED
|
@@ -1,53 +1,49 @@
|
|
|
1
|
-
import { readdir } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
1
|
import type { CommandDefinition } from '../types';
|
|
4
2
|
|
|
3
|
+
// Use dynamic imports for bundler compatibility while maintaining lazy loading
|
|
5
4
|
export async function discoverCommands(): Promise<CommandDefinition[]> {
|
|
6
|
-
const
|
|
7
|
-
|
|
5
|
+
const commandModules = await Promise.all([
|
|
6
|
+
import('./ai').then((m) => m.command),
|
|
7
|
+
import('./auth').then((m) => m.command),
|
|
8
|
+
import('./build').then((m) => m.command),
|
|
9
|
+
import('./cloud').then((m) => m.command),
|
|
10
|
+
import('./dev').then((m) => m.command),
|
|
11
|
+
import('./profile').then((m) => m.command),
|
|
12
|
+
import('./project').then((m) => m.command),
|
|
13
|
+
import('./repl').then((m) => m.command),
|
|
14
|
+
import('./version').then((m) => m.command),
|
|
15
|
+
]);
|
|
8
16
|
|
|
9
17
|
const commands: CommandDefinition[] = [];
|
|
10
18
|
|
|
11
|
-
for (const
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
const modulePath = join(cmdDir, entry.name, 'index.ts');
|
|
15
|
-
const module = await import(modulePath);
|
|
19
|
+
for (const cmd of commandModules) {
|
|
20
|
+
commands.push(cmd);
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
-
examples: (subcommand as any).examples,
|
|
43
|
-
};
|
|
44
|
-
commands.push(alias as CommandDefinition);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
22
|
+
// Auto-create hidden top-level aliases for subcommands with toplevel: true
|
|
23
|
+
if (cmd.subcommands) {
|
|
24
|
+
for (const subcommand of cmd.subcommands) {
|
|
25
|
+
if (subcommand.toplevel) {
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
const alias: any = {
|
|
28
|
+
name: subcommand.name,
|
|
29
|
+
description: subcommand.description,
|
|
30
|
+
aliases: subcommand.aliases,
|
|
31
|
+
hidden: true,
|
|
32
|
+
requires: subcommand.requires,
|
|
33
|
+
optional: subcommand.optional,
|
|
34
|
+
schema: subcommand.schema,
|
|
35
|
+
handler: subcommand.handler,
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
+
idempotent: (subcommand as any).idempotent,
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
+
prerequisites: (subcommand as any).prerequisites,
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
|
+
tags: (subcommand as any).tags,
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
|
+
examples: (subcommand as any).examples,
|
|
44
|
+
};
|
|
45
|
+
commands.push(alias as CommandDefinition);
|
|
48
46
|
}
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.warn(`Warning: Failed to load command from ${entry.name}:`, error);
|
|
51
47
|
}
|
|
52
48
|
}
|
|
53
49
|
}
|
package/src/schema-parser.ts
CHANGED
|
@@ -216,7 +216,9 @@ export function buildValidationInput(
|
|
|
216
216
|
const parsed = parseOptionsSchema(schemas.options);
|
|
217
217
|
for (const opt of parsed) {
|
|
218
218
|
// Only include the option if it has a value - omitting undefined allows Zod to apply defaults
|
|
219
|
-
|
|
219
|
+
// Commander.js converts kebab-case to camelCase, so we need to check both
|
|
220
|
+
const camelCaseName = opt.name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
221
|
+
const value = rawOptions[opt.name] ?? rawOptions[camelCaseName];
|
|
220
222
|
if (value !== undefined) {
|
|
221
223
|
result.options[opt.name] = value;
|
|
222
224
|
}
|