@agentuity/cli 0.0.101 → 0.0.103
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/AGENTS.md +19 -188
- package/bin/cli.ts +21 -14
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +41 -12
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/index.d.ts.map +1 -1
- package/dist/cmd/ai/index.js +6 -1
- package/dist/cmd/ai/index.js.map +1 -1
- package/dist/cmd/ai/prompt/agent.d.ts +7 -0
- package/dist/cmd/ai/prompt/agent.d.ts.map +1 -1
- package/dist/cmd/ai/prompt/agent.js +12 -323
- package/dist/cmd/ai/prompt/agent.js.map +1 -1
- package/dist/cmd/ai/prompt/api.d.ts +7 -0
- package/dist/cmd/ai/prompt/api.d.ts.map +1 -1
- package/dist/cmd/ai/prompt/api.js +12 -260
- package/dist/cmd/ai/prompt/api.js.map +1 -1
- package/dist/cmd/ai/prompt/version.d.ts +35 -0
- package/dist/cmd/ai/prompt/version.d.ts.map +1 -0
- package/dist/cmd/ai/prompt/version.js +55 -0
- package/dist/cmd/ai/prompt/version.js.map +1 -0
- package/dist/cmd/ai/prompt/web.d.ts +7 -0
- package/dist/cmd/ai/prompt/web.d.ts.map +1 -1
- package/dist/cmd/ai/prompt/web.js +12 -283
- package/dist/cmd/ai/prompt/web.js.map +1 -1
- package/dist/cmd/ai/skills/generate.d.ts +3 -0
- package/dist/cmd/ai/skills/generate.d.ts.map +1 -0
- package/dist/cmd/ai/skills/generate.js +65 -0
- package/dist/cmd/ai/skills/generate.js.map +1 -0
- package/dist/cmd/ai/skills/generator.d.ts +4 -0
- package/dist/cmd/ai/skills/generator.d.ts.map +1 -0
- package/dist/cmd/ai/skills/generator.js +402 -0
- package/dist/cmd/ai/skills/generator.js.map +1 -0
- package/dist/cmd/ai/skills/index.d.ts +4 -0
- package/dist/cmd/ai/skills/index.d.ts.map +1 -0
- package/dist/cmd/ai/skills/index.js +21 -0
- package/dist/cmd/ai/skills/index.js.map +1 -0
- package/dist/cmd/auth/signup.d.ts.map +1 -1
- package/dist/cmd/auth/signup.js +1 -0
- package/dist/cmd/auth/signup.js.map +1 -1
- package/dist/cmd/build/entry-generator.d.ts.map +1 -1
- package/dist/cmd/build/entry-generator.js +40 -5
- package/dist/cmd/build/entry-generator.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts +7 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +30 -26
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.js +58 -7
- package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
- package/dist/cmd/build/vite/prompt-generator.d.ts +23 -0
- package/dist/cmd/build/vite/prompt-generator.d.ts.map +1 -0
- package/dist/cmd/build/vite/prompt-generator.js +123 -0
- package/dist/cmd/build/vite/prompt-generator.js.map +1 -0
- package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/registry-generator.js +28 -11
- package/dist/cmd/build/vite/registry-generator.js.map +1 -1
- package/dist/cmd/build/vite/server-bundler.d.ts +4 -0
- package/dist/cmd/build/vite/server-bundler.d.ts.map +1 -1
- package/dist/cmd/build/vite/server-bundler.js +45 -16
- package/dist/cmd/build/vite/server-bundler.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.js +4 -0
- package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +99 -87
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +80 -27
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.js +3 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete-namespace.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete-namespace.js +3 -1
- package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete.js +3 -1
- package/dist/cmd/cloud/keyvalue/delete.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/set.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/set.js +4 -2
- package/dist/cmd/cloud/keyvalue/set.js.map +1 -1
- package/dist/cmd/cloud/stream/get.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/get.js +2 -13
- package/dist/cmd/cloud/stream/get.js.map +1 -1
- package/dist/cmd/cloud/vector/delete-namespace.d.ts +3 -0
- package/dist/cmd/cloud/vector/delete-namespace.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/delete-namespace.js +77 -0
- package/dist/cmd/cloud/vector/delete-namespace.js.map +1 -0
- package/dist/cmd/cloud/vector/index.d.ts.map +1 -1
- package/dist/cmd/cloud/vector/index.js +21 -4
- package/dist/cmd/cloud/vector/index.js.map +1 -1
- package/dist/cmd/cloud/vector/list-namespaces.d.ts +3 -0
- package/dist/cmd/cloud/vector/list-namespaces.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/list-namespaces.js +42 -0
- package/dist/cmd/cloud/vector/list-namespaces.js.map +1 -0
- package/dist/cmd/cloud/vector/stats.d.ts +3 -0
- package/dist/cmd/cloud/vector/stats.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/stats.js +142 -0
- package/dist/cmd/cloud/vector/stats.js.map +1 -0
- package/dist/cmd/cloud/vector/upsert.d.ts +3 -0
- package/dist/cmd/cloud/vector/upsert.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/upsert.js +192 -0
- package/dist/cmd/cloud/vector/upsert.js.map +1 -0
- package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
- package/dist/cmd/dev/file-watcher.js +90 -31
- package/dist/cmd/dev/file-watcher.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +244 -64
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/skills.d.ts +10 -0
- package/dist/cmd/dev/skills.d.ts.map +1 -0
- package/dist/cmd/dev/skills.js +57 -0
- package/dist/cmd/dev/skills.js.map +1 -0
- package/dist/cmd/dev/sync.js +7 -7
- package/dist/cmd/dev/sync.js.map +1 -1
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +1 -0
- package/dist/cmd/index.js.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/create.js +3 -0
- package/dist/cmd/project/create.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts +1 -0
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +30 -5
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/cmd/setup/index.d.ts.map +1 -1
- package/dist/cmd/setup/index.js +1 -0
- package/dist/cmd/setup/index.js.map +1 -1
- package/dist/cmd/upgrade/index.d.ts +15 -0
- package/dist/cmd/upgrade/index.d.ts.map +1 -1
- package/dist/cmd/upgrade/index.js +59 -4
- package/dist/cmd/upgrade/index.js.map +1 -1
- package/dist/domain.d.ts +45 -0
- package/dist/domain.d.ts.map +1 -0
- package/dist/domain.js +200 -0
- package/dist/domain.js.map +1 -0
- package/dist/schema-generator.d.ts +2 -0
- package/dist/schema-generator.d.ts.map +1 -1
- package/dist/schema-generator.js +18 -0
- package/dist/schema-generator.js.map +1 -1
- package/dist/steps.d.ts +1 -1
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +16 -5
- package/dist/steps.js.map +1 -1
- package/dist/tui/prompt.d.ts +1 -2
- package/dist/tui/prompt.d.ts.map +1 -1
- package/dist/tui/prompt.js +8 -4
- package/dist/tui/prompt.js.map +1 -1
- package/dist/tui.d.ts +16 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +23 -2
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +9 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -3
- package/dist/types.js.map +1 -1
- package/package.json +4 -4
- package/src/cli.ts +47 -12
- package/src/cmd/ai/index.ts +6 -1
- package/src/cmd/ai/prompt/agent.md +306 -0
- package/src/cmd/ai/prompt/agent.ts +12 -322
- package/src/cmd/ai/prompt/api.md +360 -0
- package/src/cmd/ai/prompt/api.ts +13 -260
- package/src/cmd/ai/prompt/version.ts +61 -0
- package/src/cmd/ai/prompt/web.md +509 -0
- package/src/cmd/ai/prompt/web.ts +12 -282
- package/src/cmd/ai/skills/generate.ts +75 -0
- package/src/cmd/ai/skills/generator.ts +519 -0
- package/src/cmd/ai/skills/index.ts +23 -0
- package/src/cmd/auth/signup.ts +1 -0
- package/src/cmd/build/entry-generator.ts +43 -7
- package/src/cmd/build/vite/bun-dev-server.ts +31 -28
- package/src/cmd/build/vite/metadata-generator.ts +73 -7
- package/src/cmd/build/vite/prompt-generator.ts +169 -0
- package/src/cmd/build/vite/registry-generator.ts +33 -10
- package/src/cmd/build/vite/server-bundler.ts +53 -22
- package/src/cmd/build/vite/vite-asset-server-config.ts +5 -0
- package/src/cmd/build/vite/vite-builder.ts +107 -87
- package/src/cmd/cloud/deploy.ts +103 -31
- package/src/cmd/cloud/keyvalue/create-namespace.ts +3 -1
- package/src/cmd/cloud/keyvalue/delete-namespace.ts +3 -1
- package/src/cmd/cloud/keyvalue/delete.ts +3 -1
- package/src/cmd/cloud/keyvalue/set.ts +4 -2
- package/src/cmd/cloud/stream/get.ts +2 -9
- package/src/cmd/cloud/vector/delete-namespace.ts +89 -0
- package/src/cmd/cloud/vector/index.ts +21 -4
- package/src/cmd/cloud/vector/list-namespaces.ts +46 -0
- package/src/cmd/cloud/vector/stats.ts +160 -0
- package/src/cmd/cloud/vector/upsert.ts +216 -0
- package/src/cmd/dev/file-watcher.ts +101 -32
- package/src/cmd/dev/index.ts +343 -115
- package/src/cmd/dev/skills.ts +82 -0
- package/src/cmd/dev/sync.ts +7 -7
- package/src/cmd/index.ts +1 -0
- package/src/cmd/project/create.ts +3 -0
- package/src/cmd/project/template-flow.ts +37 -5
- package/src/cmd/setup/index.ts +1 -0
- package/src/cmd/upgrade/index.ts +68 -4
- package/src/domain.ts +273 -0
- package/src/schema-generator.ts +23 -0
- package/src/steps.ts +16 -5
- package/src/tui/prompt.ts +11 -5
- package/src/tui.ts +21 -2
- package/src/types/md.d.ts +8 -0
- package/src/types.ts +12 -3
- package/dist/cmd/cloud/domain.d.ts +0 -17
- package/dist/cmd/cloud/domain.d.ts.map +0 -1
- package/dist/cmd/cloud/domain.js +0 -79
- package/dist/cmd/cloud/domain.js.map +0 -1
- package/src/cmd/cloud/domain.ts +0 -100
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CLISchema,
|
|
3
|
+
SchemaCommand,
|
|
4
|
+
SchemaOption,
|
|
5
|
+
SchemaArgument,
|
|
6
|
+
} from '../../../schema-generator';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
|
|
9
|
+
interface SkillInfo {
|
|
10
|
+
skillPath: string;
|
|
11
|
+
skillName: string;
|
|
12
|
+
command: SchemaCommand;
|
|
13
|
+
fullCommandPath: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const EXCLUDED_COMMANDS = new Set(['ai', 'help', 'version']);
|
|
17
|
+
|
|
18
|
+
function isValidSkillName(name: string): boolean {
|
|
19
|
+
if (name.length < 1 || name.length > 64) return false;
|
|
20
|
+
if (!/^[a-z0-9-]+$/.test(name)) return false;
|
|
21
|
+
if (name.startsWith('-') || name.endsWith('-')) return false;
|
|
22
|
+
if (name.includes('--')) return false;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function toSkillName(parts: string[]): string {
|
|
27
|
+
return parts.join('-').toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function enhanceDescription(command: SchemaCommand, fullPath: string[]): string {
|
|
31
|
+
let description = command.description;
|
|
32
|
+
|
|
33
|
+
const context = getCommandContext(command, fullPath);
|
|
34
|
+
if (context) {
|
|
35
|
+
description = `${description}. ${context}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (description.length > 1024) {
|
|
39
|
+
description = description.substring(0, 1021) + '...';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return description;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getCommandContext(command: SchemaCommand, fullPath: string[]): string {
|
|
46
|
+
const parts: string[] = [];
|
|
47
|
+
|
|
48
|
+
if (command.requires?.auth) {
|
|
49
|
+
parts.push('Requires authentication');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (fullPath.includes('cloud')) {
|
|
53
|
+
parts.push('Use for Agentuity cloud platform operations');
|
|
54
|
+
} else if (fullPath.includes('auth')) {
|
|
55
|
+
parts.push('Use for managing authentication credentials');
|
|
56
|
+
} else if (fullPath.includes('project')) {
|
|
57
|
+
parts.push('Use for project management operations');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return parts.join('. ');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function collectLeafCommands(
|
|
64
|
+
command: SchemaCommand,
|
|
65
|
+
parentPath: string[],
|
|
66
|
+
baseDir: string,
|
|
67
|
+
_isHidden: boolean
|
|
68
|
+
): SkillInfo[] {
|
|
69
|
+
const skills: SkillInfo[] = [];
|
|
70
|
+
const currentPath = [...parentPath, command.name];
|
|
71
|
+
|
|
72
|
+
// Skip commands marked with skipSkill
|
|
73
|
+
if (command.skipSkill) {
|
|
74
|
+
return skills;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Skip toplevel aliases (subcommands that have toplevel: true create duplicates)
|
|
78
|
+
if (command.toplevel && parentPath.length === 0) {
|
|
79
|
+
return skills;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (command.subcommands && command.subcommands.length > 0) {
|
|
83
|
+
for (const sub of command.subcommands) {
|
|
84
|
+
skills.push(...collectLeafCommands(sub, currentPath, baseDir, _isHidden));
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
const skillName = `agentuity-cli-${toSkillName(currentPath)}`;
|
|
88
|
+
|
|
89
|
+
if (!isValidSkillName(skillName)) {
|
|
90
|
+
return skills;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const skillPath = path.join(baseDir, skillName, 'SKILL.md');
|
|
94
|
+
|
|
95
|
+
skills.push({
|
|
96
|
+
skillPath,
|
|
97
|
+
skillName,
|
|
98
|
+
command,
|
|
99
|
+
fullCommandPath: currentPath,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return skills;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function formatPrerequisites(command: SchemaCommand): string[] {
|
|
107
|
+
const prereqs: string[] = [];
|
|
108
|
+
|
|
109
|
+
if (command.requires?.auth) {
|
|
110
|
+
prereqs.push('Authenticated with `agentuity auth login`');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (command.requires?.project) {
|
|
114
|
+
prereqs.push('Project context required (run from project directory or use `--project-id`)');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (command.requires?.org) {
|
|
118
|
+
prereqs.push('Organization context required (`--org-id` or default org)');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (command.prerequisites) {
|
|
122
|
+
prereqs.push(...command.prerequisites);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return prereqs;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function formatOptionsTable(options: SchemaOption[]): string {
|
|
129
|
+
if (options.length === 0) return '';
|
|
130
|
+
|
|
131
|
+
const lines: string[] = [
|
|
132
|
+
'| Option | Type | Required | Default | Description |',
|
|
133
|
+
'|--------|------|----------|---------|-------------|',
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
for (const opt of options) {
|
|
137
|
+
const optName = `\`--${opt.name}\``;
|
|
138
|
+
const optType = opt.enum ? opt.enum.join(' \\| ') : opt.type;
|
|
139
|
+
const required = opt.required ? 'Yes' : 'No';
|
|
140
|
+
const defaultVal = opt.default !== undefined ? `\`${JSON.stringify(opt.default)}\`` : '-';
|
|
141
|
+
const desc = opt.description ?? '-';
|
|
142
|
+
|
|
143
|
+
lines.push(`| ${optName} | ${optType} | ${required} | ${defaultVal} | ${desc} |`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return lines.join('\n');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function formatArgumentsTable(args: SchemaArgument[]): string {
|
|
150
|
+
if (args.length === 0) return '';
|
|
151
|
+
|
|
152
|
+
const lines: string[] = [
|
|
153
|
+
'| Argument | Type | Required | Description |',
|
|
154
|
+
'|----------|------|----------|-------------|',
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
for (const arg of args) {
|
|
158
|
+
const argName = `\`<${arg.name}${arg.variadic ? '...' : ''}>\``;
|
|
159
|
+
const argType = arg.variadic ? 'array' : arg.type;
|
|
160
|
+
const required = arg.required ? 'Yes' : 'No';
|
|
161
|
+
const desc = arg.description ?? '-';
|
|
162
|
+
|
|
163
|
+
lines.push(`| ${argName} | ${argType} | ${required} | ${desc} |`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return lines.join('\n');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function formatExamples(command: SchemaCommand): string {
|
|
170
|
+
if (!command.examples || command.examples.length === 0) {
|
|
171
|
+
return '';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const lines: string[] = [];
|
|
175
|
+
|
|
176
|
+
for (const example of command.examples) {
|
|
177
|
+
lines.push(`${example.description}:`);
|
|
178
|
+
lines.push('');
|
|
179
|
+
lines.push('```bash');
|
|
180
|
+
lines.push(example.command);
|
|
181
|
+
lines.push('```');
|
|
182
|
+
lines.push('');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return lines.join('\n').trim();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function formatResponse(command: SchemaCommand): string {
|
|
189
|
+
if (!command.response) {
|
|
190
|
+
return '';
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const response = command.response as Record<string, unknown>;
|
|
194
|
+
const lines: string[] = [];
|
|
195
|
+
|
|
196
|
+
if (response.type === 'object' && response.properties) {
|
|
197
|
+
const props = response.properties as Record<string, { type?: string; description?: string }>;
|
|
198
|
+
|
|
199
|
+
lines.push('Returns JSON object:');
|
|
200
|
+
lines.push('');
|
|
201
|
+
lines.push('```json');
|
|
202
|
+
const sample: Record<string, string> = {};
|
|
203
|
+
for (const [key, val] of Object.entries(props)) {
|
|
204
|
+
sample[key] = val.type ?? 'unknown';
|
|
205
|
+
}
|
|
206
|
+
lines.push(JSON.stringify(sample, null, 2));
|
|
207
|
+
lines.push('```');
|
|
208
|
+
lines.push('');
|
|
209
|
+
lines.push('| Field | Type | Description |');
|
|
210
|
+
lines.push('|-------|------|-------------|');
|
|
211
|
+
|
|
212
|
+
for (const [key, val] of Object.entries(props)) {
|
|
213
|
+
lines.push(`| \`${key}\` | ${val.type ?? 'unknown'} | ${val.description ?? '-'} |`);
|
|
214
|
+
}
|
|
215
|
+
} else if (response.type) {
|
|
216
|
+
lines.push(`Returns: \`${response.type}\``);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return lines.join('\n');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function buildUsageString(command: SchemaCommand, fullPath: string[]): string {
|
|
223
|
+
const parts = ['agentuity', ...fullPath];
|
|
224
|
+
|
|
225
|
+
if (command.arguments) {
|
|
226
|
+
for (const arg of command.arguments) {
|
|
227
|
+
const argStr = arg.required
|
|
228
|
+
? `<${arg.name}${arg.variadic ? '...' : ''}>`
|
|
229
|
+
: `[${arg.name}${arg.variadic ? '...' : ''}]`;
|
|
230
|
+
parts.push(argStr);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (command.options && command.options.length > 0) {
|
|
235
|
+
parts.push('[options]');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return parts.join(' ');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function escapeYamlString(str: string): string {
|
|
242
|
+
// Check if string needs quoting:
|
|
243
|
+
// - Contains YAML special characters
|
|
244
|
+
// - Has leading/trailing whitespace
|
|
245
|
+
// - Looks like a boolean, null, or number
|
|
246
|
+
// - Contains control characters
|
|
247
|
+
const specialCharsRegex = /[:[\]{}#&*!|>'"%@`,?<>=~-]/;
|
|
248
|
+
// eslint-disable-next-line no-control-regex
|
|
249
|
+
const controlCharsRegex = new RegExp('[\\x00-\\x1f\\x7f]');
|
|
250
|
+
const needsQuoting =
|
|
251
|
+
specialCharsRegex.test(str) ||
|
|
252
|
+
controlCharsRegex.test(str) ||
|
|
253
|
+
str !== str.trim() ||
|
|
254
|
+
/^(true|false|yes|no|on|off|null|~)$/i.test(str) ||
|
|
255
|
+
/^-?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i.test(str) ||
|
|
256
|
+
str === '';
|
|
257
|
+
|
|
258
|
+
if (!needsQuoting) {
|
|
259
|
+
return str;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Escape special characters for double-quoted YAML string
|
|
263
|
+
// eslint-disable-next-line no-control-regex
|
|
264
|
+
const nonPrintableRegex = new RegExp('[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]', 'g');
|
|
265
|
+
const escaped = str
|
|
266
|
+
.replace(/\\/g, '\\\\')
|
|
267
|
+
.replace(/"/g, '\\"')
|
|
268
|
+
.replace(/\n/g, '\\n')
|
|
269
|
+
.replace(/\r/g, '\\r')
|
|
270
|
+
.replace(/\t/g, '\\t')
|
|
271
|
+
.replace(nonPrintableRegex, (char) => {
|
|
272
|
+
const code = char.charCodeAt(0);
|
|
273
|
+
return `\\x${code.toString(16).padStart(2, '0')}`;
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
return `"${escaped}"`;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function buildArgumentHint(command: SchemaCommand): string | null {
|
|
280
|
+
if (!command.arguments || command.arguments.length === 0) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const hints = command.arguments.map((arg) => {
|
|
285
|
+
const name = arg.variadic ? `${arg.name}...` : arg.name;
|
|
286
|
+
return arg.required ? `<${name}>` : `[${name}]`;
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
return hints.join(' ');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function generateSkillContent(skill: SkillInfo, version: string): string {
|
|
293
|
+
const { command, skillName, fullCommandPath } = skill;
|
|
294
|
+
const fullCommand = ['agentuity', ...fullCommandPath].join(' ');
|
|
295
|
+
|
|
296
|
+
const enhancedDescription = enhanceDescription(command, fullCommandPath);
|
|
297
|
+
const tags = command.tags?.join(' ') ?? '';
|
|
298
|
+
const argumentHint = buildArgumentHint(command);
|
|
299
|
+
|
|
300
|
+
const lines: string[] = [
|
|
301
|
+
'---',
|
|
302
|
+
`name: ${skillName}`,
|
|
303
|
+
`description: ${escapeYamlString(enhancedDescription)}`,
|
|
304
|
+
`version: "${version}"`,
|
|
305
|
+
'license: Apache-2.0',
|
|
306
|
+
`allowed-tools: "Bash(agentuity:*)"`,
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
if (argumentHint) {
|
|
310
|
+
lines.push(`argument-hint: "${argumentHint}"`);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
lines.push('metadata:');
|
|
314
|
+
lines.push(` command: "${fullCommand}"`);
|
|
315
|
+
|
|
316
|
+
if (tags) {
|
|
317
|
+
lines.push(` tags: "${tags}"`);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
lines.push('---');
|
|
321
|
+
lines.push('');
|
|
322
|
+
|
|
323
|
+
const title = fullCommandPath.map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(' ');
|
|
324
|
+
lines.push(`# ${title}`);
|
|
325
|
+
lines.push('');
|
|
326
|
+
lines.push(command.description);
|
|
327
|
+
lines.push('');
|
|
328
|
+
|
|
329
|
+
const prerequisites = formatPrerequisites(command);
|
|
330
|
+
if (prerequisites.length > 0) {
|
|
331
|
+
lines.push('## Prerequisites');
|
|
332
|
+
lines.push('');
|
|
333
|
+
for (const prereq of prerequisites) {
|
|
334
|
+
lines.push(`- ${prereq}`);
|
|
335
|
+
}
|
|
336
|
+
lines.push('');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
lines.push('## Usage');
|
|
340
|
+
lines.push('');
|
|
341
|
+
lines.push('```bash');
|
|
342
|
+
lines.push(buildUsageString(command, fullCommandPath));
|
|
343
|
+
lines.push('```');
|
|
344
|
+
lines.push('');
|
|
345
|
+
|
|
346
|
+
if (command.arguments && command.arguments.length > 0) {
|
|
347
|
+
lines.push('## Arguments');
|
|
348
|
+
lines.push('');
|
|
349
|
+
lines.push(formatArgumentsTable(command.arguments));
|
|
350
|
+
lines.push('');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (command.options && command.options.length > 0) {
|
|
354
|
+
lines.push('## Options');
|
|
355
|
+
lines.push('');
|
|
356
|
+
lines.push(formatOptionsTable(command.options));
|
|
357
|
+
lines.push('');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const examples = formatExamples(command);
|
|
361
|
+
if (examples) {
|
|
362
|
+
lines.push('## Examples');
|
|
363
|
+
lines.push('');
|
|
364
|
+
lines.push(examples);
|
|
365
|
+
lines.push('');
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const response = formatResponse(command);
|
|
369
|
+
if (response) {
|
|
370
|
+
lines.push('## Output');
|
|
371
|
+
lines.push('');
|
|
372
|
+
lines.push(response);
|
|
373
|
+
lines.push('');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return lines.join('\n');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function collectAllSkills(
|
|
380
|
+
schema: CLISchema,
|
|
381
|
+
outputDir: string,
|
|
382
|
+
includeHidden: boolean
|
|
383
|
+
): SkillInfo[] {
|
|
384
|
+
const baseDir = path.join(outputDir, 'skills');
|
|
385
|
+
const allSkills: SkillInfo[] = [];
|
|
386
|
+
|
|
387
|
+
for (const command of schema.commands) {
|
|
388
|
+
if (EXCLUDED_COMMANDS.has(command.name)) {
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
393
|
+
const isHidden = (command as any).hidden === true;
|
|
394
|
+
if (isHidden && !includeHidden) {
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const skills = collectLeafCommands(command, [], baseDir, isHidden);
|
|
399
|
+
allSkills.push(...skills);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return allSkills;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function generateReadme(version: string, skills: SkillInfo[]): string {
|
|
406
|
+
const groups = new Map<string, SkillInfo[]>();
|
|
407
|
+
for (const skill of skills) {
|
|
408
|
+
const group = skill.fullCommandPath[0];
|
|
409
|
+
if (!groups.has(group)) {
|
|
410
|
+
groups.set(group, []);
|
|
411
|
+
}
|
|
412
|
+
groups.get(group)!.push(skill);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const lines: string[] = [
|
|
416
|
+
'# Agentuity CLI Skills',
|
|
417
|
+
'',
|
|
418
|
+
'This directory contains auto-generated [Agent Skills](https://agentskills.io) for the Agentuity CLI.',
|
|
419
|
+
'',
|
|
420
|
+
'## What are Agent Skills?',
|
|
421
|
+
'',
|
|
422
|
+
'Agent Skills are modular capabilities that extend AI coding agents. Each skill is a directory',
|
|
423
|
+
'containing a `SKILL.md` file with instructions that agents read when performing relevant tasks.',
|
|
424
|
+
'',
|
|
425
|
+
'Learn more at the [Agent Skills Specification](https://agentskills.io/specification).',
|
|
426
|
+
'',
|
|
427
|
+
'## Generated From',
|
|
428
|
+
'',
|
|
429
|
+
`- **CLI Version**: ${version}`,
|
|
430
|
+
`- **Generated**: ${new Date().toISOString().split('T')[0]}`,
|
|
431
|
+
`- **Total Skills**: ${skills.length}`,
|
|
432
|
+
'',
|
|
433
|
+
'## Available Skills',
|
|
434
|
+
'',
|
|
435
|
+
];
|
|
436
|
+
|
|
437
|
+
for (const [group, groupSkills] of [...groups.entries()].sort()) {
|
|
438
|
+
lines.push(`### ${group}`);
|
|
439
|
+
lines.push('');
|
|
440
|
+
lines.push('| Skill | Command | Description |');
|
|
441
|
+
lines.push('|-------|---------|-------------|');
|
|
442
|
+
|
|
443
|
+
for (const skill of groupSkills.sort((a, b) => a.skillName.localeCompare(b.skillName))) {
|
|
444
|
+
const cmd = `\`agentuity ${skill.fullCommandPath.join(' ')}\``;
|
|
445
|
+
const desc =
|
|
446
|
+
skill.command.description.substring(0, 60) +
|
|
447
|
+
(skill.command.description.length > 60 ? '...' : '');
|
|
448
|
+
lines.push(`| [${skill.skillName}](./${skill.skillName}) | ${cmd} | ${desc} |`);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
lines.push('');
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
lines.push('## Usage');
|
|
455
|
+
lines.push('');
|
|
456
|
+
lines.push(
|
|
457
|
+
'These skills are designed for AI coding agents that support the Agent Skills format.'
|
|
458
|
+
);
|
|
459
|
+
lines.push(
|
|
460
|
+
'Place this directory in your project or install globally for your agent to discover.'
|
|
461
|
+
);
|
|
462
|
+
lines.push('');
|
|
463
|
+
lines.push('## Regenerating');
|
|
464
|
+
lines.push('');
|
|
465
|
+
lines.push('To regenerate these skills with the latest CLI schema:');
|
|
466
|
+
lines.push('');
|
|
467
|
+
lines.push('```bash');
|
|
468
|
+
lines.push('agentuity ai skills generate --output ./skills');
|
|
469
|
+
lines.push('```');
|
|
470
|
+
lines.push('');
|
|
471
|
+
lines.push('---');
|
|
472
|
+
lines.push('');
|
|
473
|
+
lines.push('*This file was auto-generated by the Agentuity CLI. Do not edit manually.*');
|
|
474
|
+
lines.push('');
|
|
475
|
+
|
|
476
|
+
return lines.join('\n');
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
export function collectSkillsForPreview(
|
|
480
|
+
schema: CLISchema,
|
|
481
|
+
outputDir: string,
|
|
482
|
+
includeHidden: boolean
|
|
483
|
+
): string[] {
|
|
484
|
+
const allSkills = collectAllSkills(schema, outputDir, includeHidden);
|
|
485
|
+
return allSkills.map((s) => s.skillPath);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export async function generateSkills(
|
|
489
|
+
schema: CLISchema,
|
|
490
|
+
outputDir: string,
|
|
491
|
+
includeHidden: boolean
|
|
492
|
+
): Promise<number> {
|
|
493
|
+
const allSkills = collectAllSkills(schema, outputDir, includeHidden);
|
|
494
|
+
|
|
495
|
+
if (allSkills.length === 0) {
|
|
496
|
+
return 0;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
const baseDir = path.join(outputDir, 'skills');
|
|
500
|
+
let created = 0;
|
|
501
|
+
|
|
502
|
+
for (const skill of allSkills) {
|
|
503
|
+
const content = generateSkillContent(skill, schema.version);
|
|
504
|
+
const skillDir = path.dirname(skill.skillPath);
|
|
505
|
+
|
|
506
|
+
await Bun.$`mkdir -p ${skillDir}`.quiet();
|
|
507
|
+
await Bun.write(Bun.file(skill.skillPath), content);
|
|
508
|
+
created++;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const readmePath = path.join(baseDir, 'README.md');
|
|
512
|
+
const readmeContent = generateReadme(schema.version, allSkills);
|
|
513
|
+
await Bun.write(Bun.file(readmePath), readmeContent);
|
|
514
|
+
|
|
515
|
+
const versionPath = path.join(baseDir, 'agentuity-version.txt');
|
|
516
|
+
await Bun.write(Bun.file(versionPath), schema.version);
|
|
517
|
+
|
|
518
|
+
return created;
|
|
519
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CommandDefinition } from '../../../types';
|
|
2
|
+
import { createCommand } from '../../../types';
|
|
3
|
+
import { generateSubcommand } from './generate';
|
|
4
|
+
import { getCommand } from '../../../command-prefix';
|
|
5
|
+
|
|
6
|
+
export const skillsCommand: CommandDefinition = createCommand({
|
|
7
|
+
name: 'skills',
|
|
8
|
+
description: 'Generate Agent Skills from CLI schema',
|
|
9
|
+
tags: ['read-only', 'fast'],
|
|
10
|
+
examples: [
|
|
11
|
+
{
|
|
12
|
+
command: getCommand('ai skills generate --output ./skills'),
|
|
13
|
+
description: 'Generate skills to a directory',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
command: getCommand('--dry-run ai skills generate --output ./skills'),
|
|
17
|
+
description: 'Preview without writing files',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
subcommands: [generateSubcommand],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default skillsCommand;
|
package/src/cmd/auth/signup.ts
CHANGED
|
@@ -11,6 +11,7 @@ export const signupCommand = createSubcommand({
|
|
|
11
11
|
description: 'Create a new Agentuity Cloud Platform account',
|
|
12
12
|
tags: ['mutating', 'creates-resource', 'slow', 'api-intensive'],
|
|
13
13
|
toplevel: true,
|
|
14
|
+
skipSkill: true,
|
|
14
15
|
idempotent: false,
|
|
15
16
|
requires: { apiClient: true },
|
|
16
17
|
examples: [
|
|
@@ -53,6 +53,7 @@ export async function generateEntryFile(options: GenerateEntryOptions): Promise<
|
|
|
53
53
|
` createCorsMiddleware,`,
|
|
54
54
|
` createOtelMiddleware,`,
|
|
55
55
|
` createAgentMiddleware,`,
|
|
56
|
+
` createCompressionMiddleware,`,
|
|
56
57
|
` getAppState,`,
|
|
57
58
|
` getAppConfig,`,
|
|
58
59
|
` register,`,
|
|
@@ -130,12 +131,13 @@ app.route('/', workbenchRouter);
|
|
|
130
131
|
`
|
|
131
132
|
: '';
|
|
132
133
|
|
|
133
|
-
// Asset proxy routes -
|
|
134
|
-
const assetProxyRoutes =
|
|
135
|
-
|
|
134
|
+
// Asset proxy routes - generated for dev mode, reads VITE_PORT from env at runtime
|
|
135
|
+
const assetProxyRoutes =
|
|
136
|
+
mode === 'dev'
|
|
137
|
+
? `
|
|
136
138
|
// Asset proxy routes - Development mode only (proxies to Vite asset server)
|
|
137
|
-
if (process.env.
|
|
138
|
-
const VITE_ASSET_PORT = parseInt(process.env.VITE_PORT
|
|
139
|
+
if (isDevelopment() && process.env.VITE_PORT) {
|
|
140
|
+
const VITE_ASSET_PORT = parseInt(process.env.VITE_PORT, 10);
|
|
139
141
|
|
|
140
142
|
const proxyToVite = async (c: Context) => {
|
|
141
143
|
const viteUrl = \`http://127.0.0.1:\${VITE_ASSET_PORT}\${c.req.path}\`;
|
|
@@ -181,7 +183,7 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
181
183
|
// File system access (for Vite's @fs protocol)
|
|
182
184
|
app.get('/@fs/*', proxyToVite);
|
|
183
185
|
|
|
184
|
-
// Module resolution (for Vite's @id protocol)
|
|
186
|
+
// Module resolution (for Vite's @id protocol)
|
|
185
187
|
app.get('/@id/*', proxyToVite);
|
|
186
188
|
|
|
187
189
|
// Any .js, .jsx, .ts, .tsx files (catch remaining modules)
|
|
@@ -192,7 +194,7 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
192
194
|
app.get('/*.css', proxyToVite);
|
|
193
195
|
}
|
|
194
196
|
`
|
|
195
|
-
|
|
197
|
+
: '';
|
|
196
198
|
|
|
197
199
|
// Runtime mode detection helper (defined at top level for reuse)
|
|
198
200
|
// Dynamic property access prevents Bun.build from inlining NODE_ENV at build time
|
|
@@ -294,6 +296,8 @@ if (isDevelopment()) {
|
|
|
294
296
|
const workbenchRoutes = hasWorkbench
|
|
295
297
|
? `
|
|
296
298
|
// Workbench routes - Runtime mode detection
|
|
299
|
+
// Both dev and prod run from .agentuity/app.js (dev bundles before running)
|
|
300
|
+
// So workbench-src is always in the same directory
|
|
297
301
|
const workbenchSrcDir = import.meta.dir + '/workbench-src';
|
|
298
302
|
const workbenchIndexPath = import.meta.dir + '/workbench/index.html';
|
|
299
303
|
const workbenchIndex = existsSync(workbenchIndexPath)
|
|
@@ -373,6 +377,35 @@ if (!isDevelopment()) {
|
|
|
373
377
|
app.get('/_agentuity/idle', idleHandler);
|
|
374
378
|
app.get('/_idle', idleHandler);
|
|
375
379
|
}
|
|
380
|
+
|
|
381
|
+
// Dev readiness check - verifies Vite asset server is ready to serve frontend
|
|
382
|
+
if (isDevelopment()) {
|
|
383
|
+
app.get('/_agentuity/ready', async (c: Context) => {
|
|
384
|
+
const vitePort = process.env.VITE_PORT;
|
|
385
|
+
if (!vitePort) {
|
|
386
|
+
// No Vite port means we're not using Vite proxy
|
|
387
|
+
return c.text('OK', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
// Probe Vite to check if it can serve the main entry point
|
|
392
|
+
// Use @vite/client as a lightweight check - it's always available
|
|
393
|
+
const viteUrl = \`http://127.0.0.1:\${vitePort}/@vite/client\`;
|
|
394
|
+
const res = await fetch(viteUrl, {
|
|
395
|
+
signal: AbortSignal.timeout(5000),
|
|
396
|
+
method: 'HEAD'
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
if (res.ok) {
|
|
400
|
+
return c.text('OK', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
401
|
+
}
|
|
402
|
+
return c.text('VITE_NOT_READY', 503, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
403
|
+
} catch (err) {
|
|
404
|
+
otel.logger.debug('Vite readiness check failed: %s', err instanceof Error ? err.message : String(err));
|
|
405
|
+
return c.text('VITE_NOT_READY', 503, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
376
409
|
`;
|
|
377
410
|
|
|
378
411
|
const code = `// @generated
|
|
@@ -410,6 +443,9 @@ const app = createRouter();
|
|
|
410
443
|
setGlobalRouter(app);
|
|
411
444
|
|
|
412
445
|
// Step 3: Apply middleware in correct order (BEFORE mounting routes)
|
|
446
|
+
// Compression runs first (outermost) so it can compress the final response
|
|
447
|
+
app.use('*', createCompressionMiddleware());
|
|
448
|
+
|
|
413
449
|
app.use('*', createBaseMiddleware({
|
|
414
450
|
logger: otel.logger,
|
|
415
451
|
tracer: otel.tracer,
|