@agentuity/cli 1.0.33 → 1.0.35
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/ai-help.js +60 -0
- package/dist/ai-help.js.map +1 -1
- package/dist/cache/agent-intro.d.ts +10 -0
- package/dist/cache/agent-intro.d.ts.map +1 -1
- package/dist/cache/agent-intro.js +50 -0
- package/dist/cache/agent-intro.js.map +1 -1
- package/dist/cache/index.d.ts +1 -1
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +50 -7
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/intro.d.ts.map +1 -1
- package/dist/cmd/ai/intro.js +26 -6
- package/dist/cmd/ai/intro.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +4 -0
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/queue/consumers.d.ts +3 -0
- package/dist/cmd/cloud/queue/consumers.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/consumers.js +90 -0
- package/dist/cmd/cloud/queue/consumers.js.map +1 -0
- package/dist/cmd/cloud/queue/destinations.d.ts.map +1 -1
- package/dist/cmd/cloud/queue/destinations.js +20 -3
- package/dist/cmd/cloud/queue/destinations.js.map +1 -1
- package/dist/cmd/cloud/queue/index.d.ts.map +1 -1
- package/dist/cmd/cloud/queue/index.js +2 -0
- package/dist/cmd/cloud/queue/index.js.map +1 -1
- package/dist/cmd/project/domain/check.d.ts.map +1 -1
- package/dist/cmd/project/domain/check.js +1 -5
- package/dist/cmd/project/domain/check.js.map +1 -1
- package/dist/domain.d.ts +9 -8
- package/dist/domain.d.ts.map +1 -1
- package/dist/domain.js +19 -62
- package/dist/domain.js.map +1 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +45 -1
- package/dist/output.js.map +1 -1
- package/dist/schema-generator.d.ts +9 -1
- package/dist/schema-generator.d.ts.map +1 -1
- package/dist/schema-generator.js +57 -24
- package/dist/schema-generator.js.map +1 -1
- package/dist/schema-parser.d.ts +2 -2
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/schema-parser.js +44 -3
- package/dist/schema-parser.js.map +1 -1
- package/dist/types.d.ts +5 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -6
- package/src/ai-help.ts +61 -0
- package/src/cache/agent-intro.ts +54 -0
- package/src/cache/index.ts +6 -1
- package/src/cli.ts +84 -11
- package/src/cmd/ai/intro.ts +26 -6
- package/src/cmd/cloud/deploy.ts +5 -0
- package/src/cmd/cloud/queue/consumers.ts +97 -0
- package/src/cmd/cloud/queue/destinations.ts +21 -3
- package/src/cmd/cloud/queue/index.ts +2 -0
- package/src/cmd/project/domain/check.ts +0 -4
- package/src/domain.ts +28 -72
- package/src/output.ts +46 -1
- package/src/schema-generator.ts +62 -27
- package/src/schema-parser.ts +57 -3
- package/src/types.ts +3 -0
package/src/ai-help.ts
CHANGED
|
@@ -91,6 +91,7 @@ function buildContent(schema: CLISchema, config: DashdashConfig): string {
|
|
|
91
91
|
const sections = [
|
|
92
92
|
buildHeader(config),
|
|
93
93
|
buildWhenToUse(),
|
|
94
|
+
buildAgentOptimizedIO(),
|
|
94
95
|
buildQuickReference(schema),
|
|
95
96
|
buildCommandReference(schema),
|
|
96
97
|
buildGlobalOptions(schema),
|
|
@@ -127,6 +128,66 @@ Do NOT use this CLI for:
|
|
|
127
128
|
- Direct database queries (use the SDK or cloud console)`;
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Build Agent-Optimized Input/Output section
|
|
133
|
+
*/
|
|
134
|
+
function buildAgentOptimizedIO(): string {
|
|
135
|
+
return `## Agent-Optimized Input/Output
|
|
136
|
+
|
|
137
|
+
This CLI provides structured input and output modes designed for AI agents:
|
|
138
|
+
|
|
139
|
+
### Structured Input: \`--input <json>\`
|
|
140
|
+
|
|
141
|
+
Pass all arguments and options as a single JSON object instead of individual flags:
|
|
142
|
+
|
|
143
|
+
\`\`\`bash
|
|
144
|
+
# Instead of individual flags:
|
|
145
|
+
agentuity cloud sandbox create --runtime "bun:1" --memory "1Gi" --network --port 8080
|
|
146
|
+
|
|
147
|
+
# Use structured JSON input:
|
|
148
|
+
agentuity cloud sandbox create --input '{"runtime":"bun:1","memory":"1Gi","network":true,"port":8080}'
|
|
149
|
+
\`\`\`
|
|
150
|
+
|
|
151
|
+
JSON keys map to argument and option names from the command schema. CLI flags take precedence over \`--input\` values.
|
|
152
|
+
|
|
153
|
+
### Schema Introspection: \`--describe\`
|
|
154
|
+
|
|
155
|
+
Discover what any command accepts at runtime without executing it:
|
|
156
|
+
|
|
157
|
+
\`\`\`bash
|
|
158
|
+
agentuity cloud sandbox create --describe
|
|
159
|
+
# Returns: { "name": "create", "options": [...], "arguments": [...], "response": {...} }
|
|
160
|
+
\`\`\`
|
|
161
|
+
|
|
162
|
+
No authentication required. Use this to self-serve command schemas instead of reading documentation.
|
|
163
|
+
|
|
164
|
+
### Output Field Filtering: \`--fields <fields>\`
|
|
165
|
+
|
|
166
|
+
Limit JSON output to only the fields you need (protects context window):
|
|
167
|
+
|
|
168
|
+
\`\`\`bash
|
|
169
|
+
agentuity --json --fields "id,name,status" cloud deployment list
|
|
170
|
+
\`\`\`
|
|
171
|
+
|
|
172
|
+
Supports dot notation for nested fields (e.g., \`properties.title\`). Applies to arrays automatically.
|
|
173
|
+
|
|
174
|
+
### Input Validation: \`--validate\`
|
|
175
|
+
|
|
176
|
+
Validate your input without executing the command:
|
|
177
|
+
|
|
178
|
+
\`\`\`bash
|
|
179
|
+
agentuity --validate cloud kv set --input '{"namespace":"ns","key":"k","value":"v"}'
|
|
180
|
+
# Returns: { "valid": true, "command": "cloud kv set" }
|
|
181
|
+
\`\`\`
|
|
182
|
+
|
|
183
|
+
### Recommended Agent Workflow
|
|
184
|
+
|
|
185
|
+
1. **Discover**: \`agentuity <command> --describe\` — learn what the command accepts
|
|
186
|
+
2. **Validate**: \`agentuity --validate <command> --input '{...}'\` — check input before executing
|
|
187
|
+
3. **Execute**: \`agentuity --json <command> --input '{...}' --fields "id,status"\` — run with structured I/O
|
|
188
|
+
4. **Dry-run**: \`agentuity --dry-run <command> --input '{...}'\` — test mutating operations safely`;
|
|
189
|
+
}
|
|
190
|
+
|
|
130
191
|
/**
|
|
131
192
|
* Build Quick Reference with 15-20 most common operations
|
|
132
193
|
*/
|
package/src/cache/agent-intro.ts
CHANGED
|
@@ -59,3 +59,57 @@ export function markAgentIntroSeen(agentId: string): void {
|
|
|
59
59
|
// Non-critical - intro tracking failure shouldn't block CLI
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Ensure the agent_input_hint_seen table exists.
|
|
65
|
+
* Called lazily on first hint check.
|
|
66
|
+
*/
|
|
67
|
+
let hintTableCreated = false;
|
|
68
|
+
function ensureHintTable(): void {
|
|
69
|
+
if (hintTableCreated) return;
|
|
70
|
+
try {
|
|
71
|
+
getDatabase().run(`
|
|
72
|
+
CREATE TABLE IF NOT EXISTS agent_input_hint_seen (
|
|
73
|
+
agent_id TEXT PRIMARY KEY,
|
|
74
|
+
first_seen_at INTEGER NOT NULL
|
|
75
|
+
)
|
|
76
|
+
`);
|
|
77
|
+
hintTableCreated = true;
|
|
78
|
+
} catch {
|
|
79
|
+
// Non-critical
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if an agent has already seen the structured input hint.
|
|
85
|
+
* Returns true on error to avoid blocking CLI (assumes seen).
|
|
86
|
+
*/
|
|
87
|
+
export function hasAgentSeenInputHint(agentId: string): boolean {
|
|
88
|
+
try {
|
|
89
|
+
ensureHintTable();
|
|
90
|
+
const row = getDatabase()
|
|
91
|
+
.query<{ agent_id: string }, [string]>(
|
|
92
|
+
'SELECT agent_id FROM agent_input_hint_seen WHERE agent_id = ?'
|
|
93
|
+
)
|
|
94
|
+
.get(agentId);
|
|
95
|
+
return row !== null;
|
|
96
|
+
} catch {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Mark an agent as having seen the structured input hint.
|
|
103
|
+
* Silently fails on error (non-critical feature).
|
|
104
|
+
*/
|
|
105
|
+
export function markAgentInputHintSeen(agentId: string): void {
|
|
106
|
+
try {
|
|
107
|
+
ensureHintTable();
|
|
108
|
+
getDatabase().run(
|
|
109
|
+
'INSERT OR IGNORE INTO agent_input_hint_seen (agent_id, first_seen_at) VALUES (?, ?)',
|
|
110
|
+
[agentId, Date.now()]
|
|
111
|
+
);
|
|
112
|
+
} catch {
|
|
113
|
+
// Non-critical
|
|
114
|
+
}
|
|
115
|
+
}
|
package/src/cache/index.ts
CHANGED
|
@@ -12,6 +12,11 @@ export {
|
|
|
12
12
|
|
|
13
13
|
export { getCachedProject, setCachedProject, clearProjectCache } from './project-cache';
|
|
14
14
|
|
|
15
|
-
export {
|
|
15
|
+
export {
|
|
16
|
+
hasAgentSeenIntro,
|
|
17
|
+
markAgentIntroSeen,
|
|
18
|
+
hasAgentSeenInputHint,
|
|
19
|
+
markAgentInputHintSeen,
|
|
20
|
+
} from './agent-intro';
|
|
16
21
|
|
|
17
22
|
export { getCachedUserInfo, setCachedUserInfo, clearCachedUserInfo } from './user-cache';
|
package/src/cli.ts
CHANGED
|
@@ -291,12 +291,20 @@ function handleValidationError(
|
|
|
291
291
|
? errorMessages[0]
|
|
292
292
|
: 'Invalid options or arguments';
|
|
293
293
|
|
|
294
|
+
const suggestions = [`Run 'agentuity ${commandName} --help' for usage information`];
|
|
295
|
+
// Add agent-friendly hints when running from an AI agent
|
|
296
|
+
if (getExecutingAgent()) {
|
|
297
|
+
suggestions.push(
|
|
298
|
+
`Run 'agentuity ${commandName} --describe' to see the command schema as JSON`,
|
|
299
|
+
`Use --input '{...}' to pass arguments and options as a JSON object`
|
|
300
|
+
);
|
|
301
|
+
}
|
|
294
302
|
exitWithError(
|
|
295
303
|
{
|
|
296
304
|
code: ErrorCode.VALIDATION_FAILED,
|
|
297
305
|
message: primaryMessage,
|
|
298
306
|
details: errorMessages.length > 1 ? { errors: errorMessages } : undefined,
|
|
299
|
-
suggestions
|
|
307
|
+
suggestions,
|
|
300
308
|
},
|
|
301
309
|
baseCtx.logger,
|
|
302
310
|
baseCtx.options.errorFormat ?? 'text'
|
|
@@ -520,7 +528,13 @@ export async function createCLI(version: string): Promise<Command> {
|
|
|
520
528
|
.option('--explain', 'Show what the command would do without executing', false)
|
|
521
529
|
.option('--dry-run', 'Execute command without making changes', false)
|
|
522
530
|
.option('--validate', 'Validate arguments and options without executing', false)
|
|
523
|
-
.option('--ai-help', 'Show AI-optimized help in dashdash format', false)
|
|
531
|
+
.option('--ai-help', 'Show AI-optimized help in dashdash format', false)
|
|
532
|
+
.option('--input <json>', 'Pass arguments and options as a JSON object (for agents)')
|
|
533
|
+
.option('--describe', 'Output command schema as JSON for agent introspection', false)
|
|
534
|
+
.option(
|
|
535
|
+
'--fields <fields>',
|
|
536
|
+
'Filter JSON output to specified fields (comma-separated, dot notation for nested)'
|
|
537
|
+
);
|
|
524
538
|
|
|
525
539
|
const skipVersionCheckOption = program.createOption(
|
|
526
540
|
'--skip-version-check',
|
|
@@ -1035,6 +1049,18 @@ async function registerSubcommand(
|
|
|
1035
1049
|
cmd.help();
|
|
1036
1050
|
});
|
|
1037
1051
|
|
|
1052
|
+
// Handle --describe for command-group nodes
|
|
1053
|
+
cmd.action(async () => {
|
|
1054
|
+
if (baseCtx.options.describe) {
|
|
1055
|
+
const { extractSubcommandSchema } = await import('./schema-generator');
|
|
1056
|
+
const schema = extractSubcommandSchema(subcommand);
|
|
1057
|
+
const { outputJSON } = await import('./output');
|
|
1058
|
+
outputJSON(schema);
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
cmd.help();
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1038
1064
|
// Don't add options to parent commands - only to leaf commands
|
|
1039
1065
|
return;
|
|
1040
1066
|
}
|
|
@@ -1216,6 +1242,28 @@ async function registerSubcommand(
|
|
|
1216
1242
|
const options = cmdObj.opts();
|
|
1217
1243
|
const args = rawArgs.slice(0, -1);
|
|
1218
1244
|
|
|
1245
|
+
// Handle --describe mode: output command schema and exit
|
|
1246
|
+
if (baseCtx.options.describe) {
|
|
1247
|
+
const { extractSubcommandSchema } = await import('./schema-generator');
|
|
1248
|
+
const schema = extractSubcommandSchema(subcommand);
|
|
1249
|
+
const { outputJSON } = await import('./output');
|
|
1250
|
+
outputJSON(schema);
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// One-time hint for agents about structured input/output features
|
|
1255
|
+
// Emitted on stderr so it doesn't interfere with --json stdout
|
|
1256
|
+
const detectedAgent = getExecutingAgent();
|
|
1257
|
+
if (detectedAgent) {
|
|
1258
|
+
const { hasAgentSeenInputHint, markAgentInputHintSeen } = await import('./cache');
|
|
1259
|
+
if (!hasAgentSeenInputHint(detectedAgent)) {
|
|
1260
|
+
markAgentInputHintSeen(detectedAgent);
|
|
1261
|
+
console.error(
|
|
1262
|
+
`[agent] This CLI supports structured I/O for agents: --input <json> (structured input), --describe (schema introspection), --fields (output filtering). Run --ai-help for details.`
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1219
1267
|
// Merge global --org-id and --project-id into subcommand options when the schema
|
|
1220
1268
|
// defines these fields. Global options (program-level) capture the values first,
|
|
1221
1269
|
// so subcommand-level options may not have them. Only merge when the user
|
|
@@ -1415,9 +1463,13 @@ async function registerSubcommand(
|
|
|
1415
1463
|
try {
|
|
1416
1464
|
// Check if command uses stdin (don't auto-confirm if it does)
|
|
1417
1465
|
const usesStdin = subcommand.tags?.includes('uses-stdin') ?? false;
|
|
1418
|
-
const input = await buildValidationInputAsync(
|
|
1419
|
-
|
|
1420
|
-
|
|
1466
|
+
const input = await buildValidationInputAsync(
|
|
1467
|
+
subcommand.schema,
|
|
1468
|
+
args,
|
|
1469
|
+
options,
|
|
1470
|
+
{ usesStdin },
|
|
1471
|
+
baseCtx.options.input
|
|
1472
|
+
);
|
|
1421
1473
|
const ctx: Record<string, unknown> = {
|
|
1422
1474
|
...baseCtx,
|
|
1423
1475
|
config: {
|
|
@@ -1705,9 +1757,15 @@ async function registerSubcommand(
|
|
|
1705
1757
|
try {
|
|
1706
1758
|
// Check if command uses stdin (don't auto-confirm if it does)
|
|
1707
1759
|
const usesStdin = subcommand.tags?.includes('uses-stdin') ?? false;
|
|
1708
|
-
const input = await buildValidationInputAsync(
|
|
1709
|
-
|
|
1710
|
-
|
|
1760
|
+
const input = await buildValidationInputAsync(
|
|
1761
|
+
subcommand.schema,
|
|
1762
|
+
args,
|
|
1763
|
+
options,
|
|
1764
|
+
{
|
|
1765
|
+
usesStdin,
|
|
1766
|
+
},
|
|
1767
|
+
baseCtx.options.input
|
|
1768
|
+
);
|
|
1711
1769
|
const ctx: Record<string, unknown> = {
|
|
1712
1770
|
...baseCtx,
|
|
1713
1771
|
config: auth
|
|
@@ -1969,9 +2027,15 @@ async function registerSubcommand(
|
|
|
1969
2027
|
try {
|
|
1970
2028
|
// Check if command uses stdin (don't auto-confirm if it does)
|
|
1971
2029
|
const usesStdin = subcommand.tags?.includes('uses-stdin') ?? false;
|
|
1972
|
-
const input = await buildValidationInputAsync(
|
|
1973
|
-
|
|
1974
|
-
|
|
2030
|
+
const input = await buildValidationInputAsync(
|
|
2031
|
+
subcommand.schema,
|
|
2032
|
+
args,
|
|
2033
|
+
options,
|
|
2034
|
+
{
|
|
2035
|
+
usesStdin,
|
|
2036
|
+
},
|
|
2037
|
+
baseCtx.options.input
|
|
2038
|
+
);
|
|
1975
2039
|
const ctx: Record<string, unknown> = {
|
|
1976
2040
|
...baseCtx,
|
|
1977
2041
|
};
|
|
@@ -2157,6 +2221,15 @@ export async function registerCommands(
|
|
|
2157
2221
|
|
|
2158
2222
|
if (cmdDef.handler) {
|
|
2159
2223
|
cmd.action(async () => {
|
|
2224
|
+
// Handle --describe mode: output command schema and exit
|
|
2225
|
+
if (baseCtx.options.describe) {
|
|
2226
|
+
const { extractCommandSchema } = await import('./schema-generator');
|
|
2227
|
+
const schema = extractCommandSchema(cmdDef);
|
|
2228
|
+
const { outputJSON } = await import('./output');
|
|
2229
|
+
outputJSON(schema);
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2160
2233
|
if (cmdDef.banner) {
|
|
2161
2234
|
showBanner();
|
|
2162
2235
|
}
|
package/src/cmd/ai/intro.ts
CHANGED
|
@@ -31,6 +31,7 @@ The Agentuity CLI is designed to be agent-friendly. Here are the key commands:
|
|
|
31
31
|
|
|
32
32
|
### Discovery & Introspection
|
|
33
33
|
\`\`\`bash
|
|
34
|
+
${getCommand('<command> --describe')} # Get command schema as JSON (args, options, response)
|
|
34
35
|
${getCommand('--help=json')} # Get complete CLI schema as JSON
|
|
35
36
|
${getCommand('ai capabilities show')} # List all capabilities and workflows
|
|
36
37
|
${getCommand('ai schema show')} # Detailed command metadata
|
|
@@ -61,22 +62,41 @@ ${getCommand('env set KEY value --secret')} # Set secrets (encrypted)
|
|
|
61
62
|
|
|
62
63
|
## Best Practices for AI Agents
|
|
63
64
|
|
|
64
|
-
1. **
|
|
65
|
+
1. **Use \`--input <json>\` to pass arguments and options as a single JSON object**
|
|
65
66
|
\`\`\`bash
|
|
66
|
-
${getCommand('--
|
|
67
|
+
${getCommand('cloud sandbox create --input \'{"runtime":"bun:1","memory":"1Gi","network":true}\'')}
|
|
68
|
+
${getCommand('cloud kv set --input \'{"namespace":"ns","key":"k","value":"v","ttl":300}\'')}
|
|
69
|
+
\`\`\`
|
|
70
|
+
JSON keys must be the **camelCase schema keys** shown by \`--describe\` output (not kebab-case flag names). For example, the flag \`--dry-run\` becomes \`dryRun\` in JSON. CLI flags take precedence over --input values.
|
|
71
|
+
|
|
72
|
+
2. **Use \`--describe\` to introspect what a command accepts before calling it**
|
|
73
|
+
\`\`\`bash
|
|
74
|
+
${getCommand('cloud sandbox create --describe')}
|
|
67
75
|
\`\`\`
|
|
76
|
+
Returns the full command schema as JSON: arguments, options (with types), response shape, requirements, and examples. No authentication required.
|
|
68
77
|
|
|
69
|
-
|
|
78
|
+
3. **Use \`--fields\` with \`--json\` to limit output and protect your context window**
|
|
70
79
|
\`\`\`bash
|
|
71
|
-
${getCommand('--
|
|
80
|
+
${getCommand('--json --fields "id,name,status" cloud deployment list')}
|
|
72
81
|
\`\`\`
|
|
82
|
+
Comma-separated field names, supports dot notation for nested fields (e.g., \`properties.title\`).
|
|
73
83
|
|
|
74
|
-
|
|
84
|
+
4. **Always use \`--json\` for machine-readable output**
|
|
85
|
+
\`\`\`bash
|
|
86
|
+
${getCommand('--json project list')}
|
|
87
|
+
\`\`\`
|
|
88
|
+
|
|
89
|
+
5. **Use \`--dry-run\` to test commands safely before mutating**
|
|
75
90
|
\`\`\`bash
|
|
76
91
|
${getCommand('--dry-run cloud deploy')}
|
|
77
92
|
\`\`\`
|
|
78
93
|
|
|
79
|
-
|
|
94
|
+
6. **Use \`--validate\` to check inputs without executing**
|
|
95
|
+
\`\`\`bash
|
|
96
|
+
${getCommand('--validate cloud kv set --input \'{"namespace":"ns","key":"k","value":"v"}\'')}
|
|
97
|
+
\`\`\`
|
|
98
|
+
|
|
99
|
+
7. **Check requirements before running commands**
|
|
80
100
|
- Many commands require authentication (\`${getCommand('auth login')}\`)
|
|
81
101
|
- Project commands require an \`agentuity.json\` file in the current directory
|
|
82
102
|
|
package/src/cmd/cloud/deploy.ts
CHANGED
|
@@ -1226,6 +1226,11 @@ export const deploySubcommand = createSubcommand({
|
|
|
1226
1226
|
});
|
|
1227
1227
|
}
|
|
1228
1228
|
|
|
1229
|
+
// Trigger TLS certificate provisioning for custom domains (fire-and-forget)
|
|
1230
|
+
if (project.deployment?.domains?.length) {
|
|
1231
|
+
void domain.triggerTLSProvisioning(project.deployment.domains);
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1229
1234
|
// Write final report on success
|
|
1230
1235
|
if (opts.reportFile) {
|
|
1231
1236
|
await collector.forceWrite();
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCommand, createSubcommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { createQueueAPIClient, getQueueApiOptions } from './util';
|
|
5
|
+
import { getCommand } from '../../../command-prefix';
|
|
6
|
+
import { listConsumers, type Consumer } from '@agentuity/server';
|
|
7
|
+
|
|
8
|
+
const ConsumersListResponseSchema = z.object({
|
|
9
|
+
consumers: z.array(
|
|
10
|
+
z.object({
|
|
11
|
+
id: z.string(),
|
|
12
|
+
client_id: z.string().nullable().optional(),
|
|
13
|
+
durable: z.boolean(),
|
|
14
|
+
connected: z.boolean(),
|
|
15
|
+
ip_address: z.string().nullable().optional(),
|
|
16
|
+
last_offset: z.number().nullable().optional(),
|
|
17
|
+
})
|
|
18
|
+
),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const listConsumersSubcommand = createSubcommand({
|
|
22
|
+
name: 'list',
|
|
23
|
+
aliases: ['ls'],
|
|
24
|
+
description: 'List consumers for a queue',
|
|
25
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
26
|
+
requires: { auth: true },
|
|
27
|
+
examples: [
|
|
28
|
+
{
|
|
29
|
+
command: getCommand('cloud queue consumers list my-queue'),
|
|
30
|
+
description: 'List queue consumers',
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
schema: {
|
|
34
|
+
args: z.object({
|
|
35
|
+
queue_name: z.string().min(1).describe('Queue name'),
|
|
36
|
+
}),
|
|
37
|
+
response: ConsumersListResponseSchema,
|
|
38
|
+
},
|
|
39
|
+
idempotent: true,
|
|
40
|
+
|
|
41
|
+
async handler(ctx) {
|
|
42
|
+
const { args, options } = ctx;
|
|
43
|
+
const client = await createQueueAPIClient(ctx);
|
|
44
|
+
const consumers = await listConsumers(client, args.queue_name, getQueueApiOptions(ctx));
|
|
45
|
+
|
|
46
|
+
if (!options.json) {
|
|
47
|
+
if (consumers.length === 0) {
|
|
48
|
+
tui.info('No consumers connected');
|
|
49
|
+
} else {
|
|
50
|
+
const tableData = consumers.map((c: Consumer) => ({
|
|
51
|
+
ID: c.id,
|
|
52
|
+
'Client ID': c.client_id || '-',
|
|
53
|
+
Durable: c.durable ? 'Yes' : 'No',
|
|
54
|
+
Connected: c.disconnected_at ? 'No' : 'Yes',
|
|
55
|
+
'IP Address': c.ip_address || '-',
|
|
56
|
+
'Last Offset': c.last_offset != null ? String(c.last_offset) : '-',
|
|
57
|
+
}));
|
|
58
|
+
tui.table(tableData, [
|
|
59
|
+
'ID',
|
|
60
|
+
'Client ID',
|
|
61
|
+
'Durable',
|
|
62
|
+
'Connected',
|
|
63
|
+
'IP Address',
|
|
64
|
+
'Last Offset',
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
consumers: consumers.map((c: Consumer) => ({
|
|
71
|
+
id: c.id,
|
|
72
|
+
client_id: c.client_id || null,
|
|
73
|
+
durable: c.durable,
|
|
74
|
+
connected: !c.disconnected_at,
|
|
75
|
+
ip_address: c.ip_address || null,
|
|
76
|
+
last_offset: c.last_offset ?? null,
|
|
77
|
+
})),
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
export const consumersSubcommand = createCommand({
|
|
83
|
+
name: 'consumers',
|
|
84
|
+
aliases: ['consumer'],
|
|
85
|
+
description: 'Manage queue consumers (WebSocket subscriptions)',
|
|
86
|
+
tags: ['requires-auth'],
|
|
87
|
+
requires: { auth: true },
|
|
88
|
+
examples: [
|
|
89
|
+
{
|
|
90
|
+
command: getCommand('cloud queue consumers list my-queue'),
|
|
91
|
+
description: 'List consumers',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
subcommands: [listConsumersSubcommand],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
export default consumersSubcommand;
|
|
@@ -18,6 +18,8 @@ const DestinationsListResponseSchema = z.object({
|
|
|
18
18
|
destinations: z.array(
|
|
19
19
|
z.object({
|
|
20
20
|
id: z.string(),
|
|
21
|
+
name: z.string(),
|
|
22
|
+
description: z.string().nullable().optional(),
|
|
21
23
|
destination_type: z.string(),
|
|
22
24
|
url: z.string(),
|
|
23
25
|
enabled: z.boolean(),
|
|
@@ -57,18 +59,21 @@ const listDestinationsSubcommand = createSubcommand({
|
|
|
57
59
|
} else {
|
|
58
60
|
const tableData = destinations.map((d: Destination) => ({
|
|
59
61
|
ID: d.id,
|
|
62
|
+
Name: d.name,
|
|
60
63
|
Type: d.destination_type,
|
|
61
64
|
URL: d.config.url,
|
|
62
65
|
Enabled: d.enabled ? 'Yes' : 'No',
|
|
63
66
|
Created: new Date(d.created_at).toLocaleString(),
|
|
64
67
|
}));
|
|
65
|
-
tui.table(tableData, ['ID', 'Type', 'URL', 'Enabled', 'Created']);
|
|
68
|
+
tui.table(tableData, ['ID', 'Name', 'Type', 'URL', 'Enabled', 'Created']);
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
return {
|
|
70
73
|
destinations: destinations.map((d: Destination) => ({
|
|
71
74
|
id: d.id,
|
|
75
|
+
name: d.name,
|
|
76
|
+
description: d.description ?? null,
|
|
72
77
|
destination_type: d.destination_type,
|
|
73
78
|
url: d.config.url,
|
|
74
79
|
enabled: d.enabled,
|
|
@@ -86,7 +91,7 @@ const createDestinationSubcommand = createSubcommand({
|
|
|
86
91
|
examples: [
|
|
87
92
|
{
|
|
88
93
|
command: getCommand(
|
|
89
|
-
'cloud queue destinations create my-queue --url https://example.com/webhook'
|
|
94
|
+
'cloud queue destinations create my-queue --name order-webhooks --url https://example.com/webhook'
|
|
90
95
|
),
|
|
91
96
|
description: 'Create a webhook destination',
|
|
92
97
|
},
|
|
@@ -96,6 +101,8 @@ const createDestinationSubcommand = createSubcommand({
|
|
|
96
101
|
queue_name: z.string().min(1).describe('Queue name'),
|
|
97
102
|
}),
|
|
98
103
|
options: z.object({
|
|
104
|
+
name: z.string().min(1).describe('Destination name'),
|
|
105
|
+
description: z.string().optional().describe('Destination description'),
|
|
99
106
|
url: z.string().url().describe('Webhook URL'),
|
|
100
107
|
method: z.string().default('POST').optional().describe('HTTP method (default: POST)'),
|
|
101
108
|
timeout: z.coerce.number().optional().describe('Request timeout in milliseconds'),
|
|
@@ -112,6 +119,8 @@ const createDestinationSubcommand = createSubcommand({
|
|
|
112
119
|
client,
|
|
113
120
|
args.queue_name,
|
|
114
121
|
{
|
|
122
|
+
name: opts.name,
|
|
123
|
+
description: opts.description,
|
|
115
124
|
destination_type: 'http',
|
|
116
125
|
config: {
|
|
117
126
|
url: opts.url,
|
|
@@ -125,6 +134,7 @@ const createDestinationSubcommand = createSubcommand({
|
|
|
125
134
|
|
|
126
135
|
if (!options.json) {
|
|
127
136
|
tui.success(`Created destination: ${destination.id}`);
|
|
137
|
+
console.log(` Name: ${destination.name}`);
|
|
128
138
|
console.log(` URL: ${destination.config.url}`);
|
|
129
139
|
console.log(` Method: ${destination.config.method}`);
|
|
130
140
|
}
|
|
@@ -149,7 +159,7 @@ const updateDestinationSubcommand = createSubcommand({
|
|
|
149
159
|
requires: { auth: true },
|
|
150
160
|
examples: [
|
|
151
161
|
{
|
|
152
|
-
command: getCommand('cloud queue destinations update my-queue
|
|
162
|
+
command: getCommand('cloud queue destinations update my-queue qdest_abc123 --disabled'),
|
|
153
163
|
description: 'Disable a destination',
|
|
154
164
|
},
|
|
155
165
|
],
|
|
@@ -159,6 +169,8 @@ const updateDestinationSubcommand = createSubcommand({
|
|
|
159
169
|
destination_id: z.string().min(1).describe('Destination ID'),
|
|
160
170
|
}),
|
|
161
171
|
options: z.object({
|
|
172
|
+
name: z.string().min(1).optional().describe('Destination name'),
|
|
173
|
+
description: z.string().optional().describe('Destination description'),
|
|
162
174
|
url: z.string().url().optional().describe('Webhook URL'),
|
|
163
175
|
method: z.string().optional().describe('HTTP method'),
|
|
164
176
|
timeout: z.coerce.number().optional().describe('Request timeout in milliseconds'),
|
|
@@ -173,10 +185,15 @@ const updateDestinationSubcommand = createSubcommand({
|
|
|
173
185
|
const client = await createQueueAPIClient(ctx);
|
|
174
186
|
|
|
175
187
|
const updateParams: {
|
|
188
|
+
name?: string;
|
|
189
|
+
description?: string | null;
|
|
176
190
|
config?: { url?: string; method?: string; timeout_ms?: number };
|
|
177
191
|
enabled?: boolean;
|
|
178
192
|
} = {};
|
|
179
193
|
|
|
194
|
+
if (opts.name !== undefined) updateParams.name = opts.name;
|
|
195
|
+
if (opts.description !== undefined) updateParams.description = opts.description || null;
|
|
196
|
+
|
|
180
197
|
if (opts.url || opts.method || opts.timeout !== undefined) {
|
|
181
198
|
updateParams.config = {};
|
|
182
199
|
if (opts.url) updateParams.config.url = opts.url;
|
|
@@ -202,6 +219,7 @@ const updateDestinationSubcommand = createSubcommand({
|
|
|
202
219
|
|
|
203
220
|
if (!options.json) {
|
|
204
221
|
tui.success(`Updated destination: ${destination.id}`);
|
|
222
|
+
console.log(` Name: ${destination.name}`);
|
|
205
223
|
console.log(` URL: ${destination.config.url}`);
|
|
206
224
|
console.log(` Enabled: ${destination.enabled ? 'Yes' : 'No'}`);
|
|
207
225
|
}
|
|
@@ -11,6 +11,7 @@ import { nackSubcommand } from './nack';
|
|
|
11
11
|
import { dlqSubcommand } from './dlq';
|
|
12
12
|
import { destinationsSubcommand } from './destinations';
|
|
13
13
|
import { sourcesSubcommand } from './sources';
|
|
14
|
+
import { consumersSubcommand } from './consumers';
|
|
14
15
|
import { pauseSubcommand } from './pause';
|
|
15
16
|
import { resumeSubcommand } from './resume';
|
|
16
17
|
import { statsSubcommand } from './stats';
|
|
@@ -56,6 +57,7 @@ export const command = createCommand({
|
|
|
56
57
|
dlqSubcommand,
|
|
57
58
|
destinationsSubcommand,
|
|
58
59
|
sourcesSubcommand,
|
|
60
|
+
consumersSubcommand,
|
|
59
61
|
pauseSubcommand,
|
|
60
62
|
resumeSubcommand,
|
|
61
63
|
statsSubcommand,
|
|
@@ -7,7 +7,6 @@ import { isJSONMode } from '../../../output';
|
|
|
7
7
|
import {
|
|
8
8
|
checkCustomDomainForDNS,
|
|
9
9
|
isSuccess,
|
|
10
|
-
isPending,
|
|
11
10
|
isMissing,
|
|
12
11
|
isMisconfigured,
|
|
13
12
|
isError,
|
|
@@ -92,9 +91,6 @@ export const checkSubcommand = createSubcommand({
|
|
|
92
91
|
status = tui.colorSuccess(`${tui.ICONS.success} Configured`);
|
|
93
92
|
statusRaw = 'configured';
|
|
94
93
|
success = true;
|
|
95
|
-
} else if (isPending(r)) {
|
|
96
|
-
status = tui.colorWarning('⏳ Pending');
|
|
97
|
-
statusRaw = 'pending';
|
|
98
94
|
} else if (isMisconfigured(r)) {
|
|
99
95
|
status = tui.colorWarning(`${tui.ICONS.warning} ${r.misconfigured}`);
|
|
100
96
|
statusRaw = 'misconfigured';
|