@agentuity/cli 0.0.104 → 0.0.106
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/bin/cli.ts +6 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +93 -21
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/prompt/version.d.ts +1 -0
- package/dist/cmd/ai/prompt/version.d.ts.map +1 -1
- package/dist/cmd/ai/prompt/version.js +3 -2
- package/dist/cmd/ai/prompt/version.js.map +1 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +179 -37
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/entry-generator.d.ts.map +1 -1
- package/dist/cmd/build/entry-generator.js +24 -14
- package/dist/cmd/build/entry-generator.js.map +1 -1
- package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/registry-generator.js +8 -9
- package/dist/cmd/build/vite/registry-generator.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
- package/dist/cmd/cloud/db/create.d.ts.map +1 -1
- package/dist/cmd/cloud/db/create.js +11 -2
- package/dist/cmd/cloud/db/create.js.map +1 -1
- package/dist/cmd/cloud/db/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/db/delete.js +13 -2
- package/dist/cmd/cloud/db/delete.js.map +1 -1
- package/dist/cmd/cloud/deploy.js +3 -3
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/env/delete.js +1 -1
- package/dist/cmd/cloud/env/delete.js.map +1 -1
- package/dist/cmd/cloud/env/import.js +4 -4
- package/dist/cmd/cloud/env/import.js.map +1 -1
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js +7 -9
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/env/push.js +2 -2
- package/dist/cmd/cloud/env/push.js.map +1 -1
- package/dist/cmd/cloud/env/set.js +3 -3
- package/dist/cmd/cloud/env/set.js.map +1 -1
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/index.js +2 -0
- package/dist/cmd/cloud/index.js.map +1 -1
- package/dist/cmd/cloud/sandbox/cp.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/cp.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/cp.js +334 -0
- package/dist/cmd/cloud/sandbox/cp.js.map +1 -0
- package/dist/cmd/cloud/sandbox/create.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/create.js +105 -0
- package/dist/cmd/cloud/sandbox/create.js.map +1 -0
- package/dist/cmd/cloud/sandbox/delete.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/delete.js +72 -0
- package/dist/cmd/cloud/sandbox/delete.js.map +1 -0
- package/dist/cmd/cloud/sandbox/exec.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/exec.js +211 -0
- package/dist/cmd/cloud/sandbox/exec.js.map +1 -0
- package/dist/cmd/cloud/sandbox/execution/get.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/execution/get.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/execution/get.js +96 -0
- package/dist/cmd/cloud/sandbox/execution/get.js.map +1 -0
- package/dist/cmd/cloud/sandbox/execution/index.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/execution/index.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/execution/index.js +24 -0
- package/dist/cmd/cloud/sandbox/execution/index.js.map +1 -0
- package/dist/cmd/cloud/sandbox/execution/list.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/execution/list.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/execution/list.js +100 -0
- package/dist/cmd/cloud/sandbox/execution/list.js.map +1 -0
- package/dist/cmd/cloud/sandbox/get.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/get.js +95 -0
- package/dist/cmd/cloud/sandbox/get.js.map +1 -0
- package/dist/cmd/cloud/sandbox/index.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/index.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/index.js +45 -0
- package/dist/cmd/cloud/sandbox/index.js.map +1 -0
- package/dist/cmd/cloud/sandbox/list.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/list.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/list.js +120 -0
- package/dist/cmd/cloud/sandbox/list.js.map +1 -0
- package/dist/cmd/cloud/sandbox/run.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/run.js +152 -0
- package/dist/cmd/cloud/sandbox/run.js.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/create.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/snapshot/create.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/create.js +65 -0
- package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/delete.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/snapshot/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/delete.js +66 -0
- package/dist/cmd/cloud/sandbox/snapshot/delete.js.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/get.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/snapshot/get.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/get.js +154 -0
- package/dist/cmd/cloud/sandbox/snapshot/get.js.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/index.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/snapshot/index.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/index.js +27 -0
- package/dist/cmd/cloud/sandbox/snapshot/index.js.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/list.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/snapshot/list.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/list.js +83 -0
- package/dist/cmd/cloud/sandbox/snapshot/list.js.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/tag.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/snapshot/tag.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/tag.js +63 -0
- package/dist/cmd/cloud/sandbox/snapshot/tag.js.map +1 -0
- package/dist/cmd/cloud/sandbox/util.d.ts +15 -0
- package/dist/cmd/cloud/sandbox/util.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/util.js +50 -0
- package/dist/cmd/cloud/sandbox/util.js.map +1 -0
- package/dist/cmd/cloud/secret/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/secret/delete.js +3 -3
- package/dist/cmd/cloud/secret/delete.js.map +1 -1
- package/dist/cmd/cloud/secret/import.js +6 -6
- package/dist/cmd/cloud/secret/import.js.map +1 -1
- package/dist/cmd/cloud/secret/index.d.ts.map +1 -1
- package/dist/cmd/cloud/secret/index.js +1 -0
- package/dist/cmd/cloud/secret/index.js.map +1 -1
- package/dist/cmd/cloud/secret/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/secret/pull.js +7 -9
- package/dist/cmd/cloud/secret/pull.js.map +1 -1
- package/dist/cmd/cloud/secret/push.js +3 -3
- package/dist/cmd/cloud/secret/push.js.map +1 -1
- package/dist/cmd/cloud/secret/set.d.ts.map +1 -1
- package/dist/cmd/cloud/secret/set.js +3 -3
- package/dist/cmd/cloud/secret/set.js.map +1 -1
- package/dist/cmd/cloud/storage/create.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/create.js +13 -2
- package/dist/cmd/cloud/storage/create.js.map +1 -1
- package/dist/cmd/cloud/storage/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/delete.js +13 -2
- package/dist/cmd/cloud/storage/delete.js.map +1 -1
- package/dist/cmd/cloud/stream/list.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/list.js +2 -13
- package/dist/cmd/cloud/stream/list.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +14 -1
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/profile/create.d.ts.map +1 -1
- package/dist/cmd/profile/create.js +1 -0
- package/dist/cmd/profile/create.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +27 -10
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/config.d.ts +0 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/env-util.d.ts +16 -8
- package/dist/env-util.d.ts.map +1 -1
- package/dist/env-util.js +46 -18
- package/dist/env-util.js.map +1 -1
- package/dist/tui.d.ts +20 -3
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +82 -23
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +18 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +4 -4
- package/src/cli.ts +99 -21
- package/src/cmd/ai/prompt/api.md +26 -21
- package/src/cmd/ai/prompt/version.ts +3 -2
- package/src/cmd/build/ast.ts +214 -37
- package/src/cmd/build/entry-generator.ts +24 -14
- package/src/cmd/build/vite/registry-generator.ts +8 -11
- package/src/cmd/build/vite/vite-asset-server.ts +3 -1
- package/src/cmd/cloud/db/create.ts +13 -2
- package/src/cmd/cloud/db/delete.ts +15 -2
- package/src/cmd/cloud/deploy.ts +3 -3
- package/src/cmd/cloud/env/delete.ts +1 -1
- package/src/cmd/cloud/env/import.ts +4 -4
- package/src/cmd/cloud/env/pull.ts +7 -16
- package/src/cmd/cloud/env/push.ts +2 -2
- package/src/cmd/cloud/env/set.ts +3 -3
- package/src/cmd/cloud/index.ts +2 -0
- package/src/cmd/cloud/sandbox/cp.ts +531 -0
- package/src/cmd/cloud/sandbox/create.ts +114 -0
- package/src/cmd/cloud/sandbox/delete.ts +80 -0
- package/src/cmd/cloud/sandbox/exec.ts +254 -0
- package/src/cmd/cloud/sandbox/execution/get.ts +106 -0
- package/src/cmd/cloud/sandbox/execution/index.ts +25 -0
- package/src/cmd/cloud/sandbox/execution/list.ts +111 -0
- package/src/cmd/cloud/sandbox/get.ts +104 -0
- package/src/cmd/cloud/sandbox/index.ts +46 -0
- package/src/cmd/cloud/sandbox/list.ts +129 -0
- package/src/cmd/cloud/sandbox/run.ts +170 -0
- package/src/cmd/cloud/sandbox/snapshot/create.ts +71 -0
- package/src/cmd/cloud/sandbox/snapshot/delete.ts +74 -0
- package/src/cmd/cloud/sandbox/snapshot/get.ts +188 -0
- package/src/cmd/cloud/sandbox/snapshot/index.ts +28 -0
- package/src/cmd/cloud/sandbox/snapshot/list.ts +90 -0
- package/src/cmd/cloud/sandbox/snapshot/tag.ts +70 -0
- package/src/cmd/cloud/sandbox/util.ts +59 -0
- package/src/cmd/cloud/secret/delete.ts +8 -3
- package/src/cmd/cloud/secret/import.ts +6 -6
- package/src/cmd/cloud/secret/index.ts +1 -0
- package/src/cmd/cloud/secret/pull.ts +7 -16
- package/src/cmd/cloud/secret/push.ts +3 -3
- package/src/cmd/cloud/secret/set.ts +8 -3
- package/src/cmd/cloud/storage/create.ts +15 -2
- package/src/cmd/cloud/storage/delete.ts +15 -2
- package/src/cmd/cloud/stream/list.ts +2 -9
- package/src/cmd/dev/index.ts +18 -1
- package/src/cmd/profile/create.ts +1 -0
- package/src/cmd/project/template-flow.ts +29 -13
- package/src/config.ts +3 -0
- package/src/env-util.ts +52 -21
- package/src/tui.ts +131 -39
- package/src/types.ts +18 -16
package/src/cli.ts
CHANGED
|
@@ -141,10 +141,17 @@ async function executeOrValidate(
|
|
|
141
141
|
/**
|
|
142
142
|
* Format a user-friendly message for a validation issue
|
|
143
143
|
*/
|
|
144
|
-
function formatValidationIssueMessage(
|
|
144
|
+
function formatValidationIssueMessage(
|
|
145
|
+
field: string,
|
|
146
|
+
message: string,
|
|
147
|
+
isArg: boolean = false
|
|
148
|
+
): string {
|
|
145
149
|
// Detect "expected X, received undefined" pattern (missing required value)
|
|
146
150
|
if (message.includes('received undefined')) {
|
|
147
151
|
if (field && field !== 'unknown') {
|
|
152
|
+
if (isArg) {
|
|
153
|
+
return `Missing required argument: <${field}>`;
|
|
154
|
+
}
|
|
148
155
|
return `Missing required option: --${field}`;
|
|
149
156
|
}
|
|
150
157
|
return 'Missing required value';
|
|
@@ -155,6 +162,9 @@ function formatValidationIssueMessage(field: string, message: string): string {
|
|
|
155
162
|
if (typeMatch) {
|
|
156
163
|
const [, expected, received] = typeMatch;
|
|
157
164
|
if (field && field !== 'unknown') {
|
|
165
|
+
if (isArg) {
|
|
166
|
+
return `Invalid value for <${field}>: expected ${expected}, got ${received}`;
|
|
167
|
+
}
|
|
158
168
|
return `Invalid value for --${field}: expected ${expected}, got ${received}`;
|
|
159
169
|
}
|
|
160
170
|
return `Invalid value: expected ${expected}, got ${received}`;
|
|
@@ -162,25 +172,69 @@ function formatValidationIssueMessage(field: string, message: string): string {
|
|
|
162
172
|
|
|
163
173
|
// Default: include the field name if we have it
|
|
164
174
|
if (field && field !== 'unknown') {
|
|
175
|
+
if (isArg) {
|
|
176
|
+
return `<${field}>: ${message}`;
|
|
177
|
+
}
|
|
165
178
|
return `--${field}: ${message}`;
|
|
166
179
|
}
|
|
167
180
|
return message;
|
|
168
181
|
}
|
|
169
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Custom error class to wrap ZodErrors with context about whether they are for args or options
|
|
185
|
+
*/
|
|
186
|
+
class SchemaValidationError extends Error {
|
|
187
|
+
constructor(
|
|
188
|
+
public readonly originalError: unknown,
|
|
189
|
+
public readonly isArg: boolean
|
|
190
|
+
) {
|
|
191
|
+
super('Schema validation error');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Parse args schema and wrap any ZodError with context
|
|
197
|
+
*/
|
|
198
|
+
function parseArgs<T>(schema: { parse: (input: unknown) => T }, input: unknown): T {
|
|
199
|
+
try {
|
|
200
|
+
return schema.parse(input);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (error && typeof error === 'object' && 'issues' in error) {
|
|
203
|
+
throw new SchemaValidationError(error, true);
|
|
204
|
+
}
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Parse options schema (no wrapping needed, isArg defaults to false)
|
|
211
|
+
*/
|
|
212
|
+
function parseOptions<T>(schema: { parse: (input: unknown) => T }, input: unknown): T {
|
|
213
|
+
return schema.parse(input);
|
|
214
|
+
}
|
|
215
|
+
|
|
170
216
|
function handleValidationError(
|
|
171
217
|
error: unknown,
|
|
172
218
|
commandName: string,
|
|
173
219
|
baseCtx: { options: GlobalOptions; logger: Logger }
|
|
174
220
|
): never {
|
|
175
|
-
|
|
176
|
-
|
|
221
|
+
// Unwrap SchemaValidationError to get context about whether it's an arg or option
|
|
222
|
+
let actualError = error;
|
|
223
|
+
let isArg = false;
|
|
224
|
+
if (error instanceof SchemaValidationError) {
|
|
225
|
+
actualError = error.originalError;
|
|
226
|
+
isArg = error.isArg;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (actualError && typeof actualError === 'object' && 'issues' in actualError) {
|
|
230
|
+
const issues = (actualError as { issues: Array<{ path: string[]; message: string }> }).issues;
|
|
177
231
|
|
|
178
232
|
const formattedIssues = issues.map((issue) => {
|
|
179
233
|
const field = issue.path?.length ? issue.path.join('.') : 'unknown';
|
|
180
234
|
return {
|
|
181
235
|
field,
|
|
182
236
|
message: issue.message,
|
|
183
|
-
formatted: formatValidationIssueMessage(field, issue.message),
|
|
237
|
+
formatted: formatValidationIssueMessage(field, issue.message, isArg),
|
|
184
238
|
};
|
|
185
239
|
});
|
|
186
240
|
|
|
@@ -227,6 +281,22 @@ type Normalized = {
|
|
|
227
281
|
optionalRegion: boolean;
|
|
228
282
|
};
|
|
229
283
|
|
|
284
|
+
/**
|
|
285
|
+
* Get the full command path for a command (e.g., "cloud sandbox snapshot delete")
|
|
286
|
+
* Uses Commander's _getCommandAndAncestors to traverse the command hierarchy.
|
|
287
|
+
*/
|
|
288
|
+
function getFullCommandPath(cmd: Command): string {
|
|
289
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
290
|
+
const ancestors = (cmd as any)._getCommandAndAncestors() as Command[];
|
|
291
|
+
// ancestors is [current, parent, grandparent, ...root] - reverse and skip root program name
|
|
292
|
+
const names = ancestors.map((c) => c.name()).reverse();
|
|
293
|
+
// Skip the first entry if it's the root program (usually empty or 'agentuity')
|
|
294
|
+
if (names.length > 1 && (names[0] === '' || names[0] === 'agentuity')) {
|
|
295
|
+
return names.slice(1).join(' ');
|
|
296
|
+
}
|
|
297
|
+
return names.join(' ');
|
|
298
|
+
}
|
|
299
|
+
|
|
230
300
|
function normalizeReqs(def: CommandDefinition | SubcommandDefinition): Normalized {
|
|
231
301
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
232
302
|
const d: any = def as any;
|
|
@@ -802,6 +872,7 @@ async function registerSubcommand(
|
|
|
802
872
|
|
|
803
873
|
if (subcommand.schema?.options) {
|
|
804
874
|
const parsed = parseOptionsSchema(subcommand.schema.options);
|
|
875
|
+
const aliases = subcommand.schema.aliases ?? {};
|
|
805
876
|
for (const opt of parsed) {
|
|
806
877
|
const flag = opt.name
|
|
807
878
|
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
@@ -814,8 +885,15 @@ async function registerSubcommand(
|
|
|
814
885
|
}
|
|
815
886
|
|
|
816
887
|
const desc = opt.description || '';
|
|
817
|
-
//
|
|
818
|
-
const
|
|
888
|
+
// Build flag spec with aliases (check both camelCase and kebab-case names)
|
|
889
|
+
const optAliases = aliases[opt.name] ?? aliases[flag] ?? [];
|
|
890
|
+
let flagSpec = `--${flag}`;
|
|
891
|
+
if (flag === 'verbose') {
|
|
892
|
+
flagSpec = `-v, --${flag}`;
|
|
893
|
+
} else if (optAliases.length > 0) {
|
|
894
|
+
const shortFlags = optAliases.map((a) => `-${a}`).join(', ');
|
|
895
|
+
flagSpec = `${shortFlags}, --${flag}`;
|
|
896
|
+
}
|
|
819
897
|
if (opt.type === 'boolean') {
|
|
820
898
|
if (opt.hasDefault) {
|
|
821
899
|
const defaultValue =
|
|
@@ -1019,10 +1097,10 @@ async function registerSubcommand(
|
|
|
1019
1097
|
ctx.projectDir = projectDir;
|
|
1020
1098
|
}
|
|
1021
1099
|
if (subcommand.schema.args) {
|
|
1022
|
-
ctx.args = subcommand.schema.args
|
|
1100
|
+
ctx.args = parseArgs(subcommand.schema.args, input.args);
|
|
1023
1101
|
}
|
|
1024
1102
|
if (subcommand.schema.options) {
|
|
1025
|
-
ctx.opts = subcommand.schema.options
|
|
1103
|
+
ctx.opts = parseOptions(subcommand.schema.options, input.options);
|
|
1026
1104
|
}
|
|
1027
1105
|
if (normalized.requiresAPIClient) {
|
|
1028
1106
|
// Recreate apiClient with auth credentials
|
|
@@ -1059,14 +1137,14 @@ async function registerSubcommand(
|
|
|
1059
1137
|
}
|
|
1060
1138
|
await executeOrValidate(
|
|
1061
1139
|
ctx as CommandContext,
|
|
1062
|
-
|
|
1140
|
+
getFullCommandPath(cmd),
|
|
1063
1141
|
subcommand.handler,
|
|
1064
1142
|
!!subcommand.schema?.response,
|
|
1065
1143
|
subcommand.webUrl
|
|
1066
1144
|
);
|
|
1067
1145
|
} catch (error) {
|
|
1068
1146
|
if (error && typeof error === 'object' && 'issues' in error) {
|
|
1069
|
-
handleValidationError(error,
|
|
1147
|
+
handleValidationError(error, getFullCommandPath(cmd), baseCtx);
|
|
1070
1148
|
}
|
|
1071
1149
|
handleProjectConfigError(
|
|
1072
1150
|
error,
|
|
@@ -1139,7 +1217,7 @@ async function registerSubcommand(
|
|
|
1139
1217
|
exitWithError(
|
|
1140
1218
|
createError(
|
|
1141
1219
|
ErrorCode.INTERNAL_ERROR,
|
|
1142
|
-
`Command '${
|
|
1220
|
+
`Command '${getFullCommandPath(cmd)}' declares a response schema but returned no data. This is a bug in the command implementation.`
|
|
1143
1221
|
),
|
|
1144
1222
|
baseCtx.logger,
|
|
1145
1223
|
baseCtx.options.errorFormat
|
|
@@ -1192,10 +1270,10 @@ async function registerSubcommand(
|
|
|
1192
1270
|
ctx.projectDir = projectDir;
|
|
1193
1271
|
}
|
|
1194
1272
|
if (subcommand.schema.args) {
|
|
1195
|
-
ctx.args = subcommand.schema.args
|
|
1273
|
+
ctx.args = parseArgs(subcommand.schema.args, input.args);
|
|
1196
1274
|
}
|
|
1197
1275
|
if (subcommand.schema.options) {
|
|
1198
|
-
ctx.opts = subcommand.schema.options
|
|
1276
|
+
ctx.opts = parseOptions(subcommand.schema.options, input.options);
|
|
1199
1277
|
}
|
|
1200
1278
|
if (normalized.requiresAPIClient) {
|
|
1201
1279
|
// Recreate apiClient with auth credentials
|
|
@@ -1238,14 +1316,14 @@ async function registerSubcommand(
|
|
|
1238
1316
|
}
|
|
1239
1317
|
await executeOrValidate(
|
|
1240
1318
|
ctx as CommandContext,
|
|
1241
|
-
|
|
1319
|
+
getFullCommandPath(cmd),
|
|
1242
1320
|
subcommand.handler,
|
|
1243
1321
|
!!subcommand.schema?.response,
|
|
1244
1322
|
subcommand.webUrl
|
|
1245
1323
|
);
|
|
1246
1324
|
} catch (error) {
|
|
1247
1325
|
if (error && typeof error === 'object' && 'issues' in error) {
|
|
1248
|
-
handleValidationError(error,
|
|
1326
|
+
handleValidationError(error, getFullCommandPath(cmd), baseCtx);
|
|
1249
1327
|
}
|
|
1250
1328
|
handleProjectConfigError(
|
|
1251
1329
|
error,
|
|
@@ -1314,7 +1392,7 @@ async function registerSubcommand(
|
|
|
1314
1392
|
exitWithError(
|
|
1315
1393
|
createError(
|
|
1316
1394
|
ErrorCode.INTERNAL_ERROR,
|
|
1317
|
-
`Command '${
|
|
1395
|
+
`Command '${getFullCommandPath(cmd)}' declares a response schema but returned no data. This is a bug in the command implementation.`
|
|
1318
1396
|
),
|
|
1319
1397
|
baseCtx.logger,
|
|
1320
1398
|
baseCtx.options.errorFormat
|
|
@@ -1343,10 +1421,10 @@ async function registerSubcommand(
|
|
|
1343
1421
|
ctx.projectDir = projectDir;
|
|
1344
1422
|
}
|
|
1345
1423
|
if (subcommand.schema.args) {
|
|
1346
|
-
ctx.args = subcommand.schema.args
|
|
1424
|
+
ctx.args = parseArgs(subcommand.schema.args, input.args);
|
|
1347
1425
|
}
|
|
1348
1426
|
if (subcommand.schema.options) {
|
|
1349
|
-
ctx.opts = subcommand.schema.options
|
|
1427
|
+
ctx.opts = parseOptions(subcommand.schema.options, input.options);
|
|
1350
1428
|
}
|
|
1351
1429
|
if (normalized.requiresAPIClient && !ctx.apiClient) {
|
|
1352
1430
|
ctx.apiClient = createAPIClient(baseCtx, ctx.config as Config | null);
|
|
@@ -1363,14 +1441,14 @@ async function registerSubcommand(
|
|
|
1363
1441
|
}
|
|
1364
1442
|
await executeOrValidate(
|
|
1365
1443
|
ctx as CommandContext,
|
|
1366
|
-
|
|
1444
|
+
getFullCommandPath(cmd),
|
|
1367
1445
|
subcommand.handler,
|
|
1368
1446
|
!!subcommand.schema?.response,
|
|
1369
1447
|
subcommand.webUrl
|
|
1370
1448
|
);
|
|
1371
1449
|
} catch (error) {
|
|
1372
1450
|
if (error && typeof error === 'object' && 'issues' in error) {
|
|
1373
|
-
handleValidationError(error,
|
|
1451
|
+
handleValidationError(error, getFullCommandPath(cmd), baseCtx);
|
|
1374
1452
|
}
|
|
1375
1453
|
handleProjectConfigError(
|
|
1376
1454
|
error,
|
|
@@ -1426,7 +1504,7 @@ async function registerSubcommand(
|
|
|
1426
1504
|
exitWithError(
|
|
1427
1505
|
createError(
|
|
1428
1506
|
ErrorCode.INTERNAL_ERROR,
|
|
1429
|
-
`Command '${
|
|
1507
|
+
`Command '${getFullCommandPath(cmd)}' declares a response schema but returned no data. This is a bug in the command implementation.`
|
|
1430
1508
|
),
|
|
1431
1509
|
baseCtx.logger,
|
|
1432
1510
|
baseCtx.options.errorFormat
|
package/src/cmd/ai/prompt/api.md
CHANGED
|
@@ -311,40 +311,45 @@ return c.json({ data: 'value' }, 200, {
|
|
|
311
311
|
## Streaming Routes
|
|
312
312
|
|
|
313
313
|
```typescript
|
|
314
|
-
import { createRouter } from '@agentuity/runtime';
|
|
314
|
+
import { createRouter, stream, sse, websocket } from '@agentuity/runtime';
|
|
315
315
|
|
|
316
316
|
const router = createRouter();
|
|
317
317
|
|
|
318
|
-
// Stream response
|
|
319
|
-
router.
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
controller
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
318
|
+
// Stream response (use with POST)
|
|
319
|
+
router.post(
|
|
320
|
+
'/events',
|
|
321
|
+
stream((c) => {
|
|
322
|
+
return new ReadableStream({
|
|
323
|
+
start(controller) {
|
|
324
|
+
controller.enqueue('event 1\n');
|
|
325
|
+
controller.enqueue('event 2\n');
|
|
326
|
+
controller.close();
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
})
|
|
330
|
+
);
|
|
328
331
|
|
|
329
|
-
// Server-Sent Events
|
|
330
|
-
router.
|
|
331
|
-
|
|
332
|
+
// Server-Sent Events (use with GET)
|
|
333
|
+
router.get(
|
|
334
|
+
'/notifications',
|
|
335
|
+
sse((c, stream) => {
|
|
332
336
|
stream.writeSSE({ data: 'Hello', event: 'message' });
|
|
333
337
|
stream.writeSSE({ data: 'World', event: 'message' });
|
|
334
|
-
}
|
|
335
|
-
|
|
338
|
+
})
|
|
339
|
+
);
|
|
336
340
|
|
|
337
|
-
// WebSocket
|
|
338
|
-
router.
|
|
339
|
-
|
|
341
|
+
// WebSocket (use with GET)
|
|
342
|
+
router.get(
|
|
343
|
+
'/ws',
|
|
344
|
+
websocket((c, ws) => {
|
|
340
345
|
ws.onOpen(() => {
|
|
341
346
|
ws.send('Connected!');
|
|
342
347
|
});
|
|
343
348
|
ws.onMessage((event) => {
|
|
344
349
|
ws.send(`Echo: ${event.data}`);
|
|
345
350
|
});
|
|
346
|
-
}
|
|
347
|
-
|
|
351
|
+
})
|
|
352
|
+
);
|
|
348
353
|
|
|
349
354
|
export default router;
|
|
350
355
|
```
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* This allows detecting if the source template has changed.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
const HASH_REGEX = /\n?<!-- prompt_hash: ([a-f0-9]+)
|
|
11
|
+
const HASH_REGEX = /\n?<!-- prompt_hash: ([a-f0-9]+) -->\n?$/;
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Compute SHA256 hash of content using Bun's built-in hasher.
|
|
@@ -37,10 +37,11 @@ export function extractHash(content: string): string | null {
|
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Generate content with hash comment appended.
|
|
40
|
+
* Ensures the output ends with a newline for POSIX compliance and Prettier compatibility.
|
|
40
41
|
*/
|
|
41
42
|
export function appendHashComment(content: string): string {
|
|
42
43
|
const hash = computeHash(content);
|
|
43
|
-
return `${content}\n<!-- prompt_hash: ${hash}
|
|
44
|
+
return `${content}\n<!-- prompt_hash: ${hash} -->\n`;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
/**
|
package/src/cmd/build/ast.ts
CHANGED
|
@@ -1300,12 +1300,168 @@ export async function parseRoute(
|
|
|
1300
1300
|
const action = statement.expression.arguments[0];
|
|
1301
1301
|
let suffix = '';
|
|
1302
1302
|
let config: Record<string, unknown> | undefined;
|
|
1303
|
+
// Supported HTTP methods that can be represented in BuildMetadata
|
|
1304
|
+
const SUPPORTED_HTTP_METHODS = ['get', 'post', 'put', 'delete', 'patch'] as const;
|
|
1305
|
+
type SupportedHttpMethod = (typeof SUPPORTED_HTTP_METHODS)[number];
|
|
1306
|
+
|
|
1307
|
+
const isSupportedHttpMethod = (m: string): m is SupportedHttpMethod =>
|
|
1308
|
+
SUPPORTED_HTTP_METHODS.includes(m.toLowerCase() as SupportedHttpMethod);
|
|
1309
|
+
|
|
1303
1310
|
switch (method) {
|
|
1304
1311
|
case 'use':
|
|
1305
|
-
case 'on':
|
|
1306
|
-
case 'all':
|
|
1307
1312
|
case 'route': {
|
|
1308
|
-
// Skip Hono middleware
|
|
1313
|
+
// Skip Hono middleware and sub-router mounting - they don't represent API routes
|
|
1314
|
+
continue;
|
|
1315
|
+
}
|
|
1316
|
+
case 'on': {
|
|
1317
|
+
// router.on(method | method[], path, handler)
|
|
1318
|
+
// First arg is method(s), second arg is path
|
|
1319
|
+
const methodArg = statement.expression.arguments[0];
|
|
1320
|
+
const pathArg = statement.expression.arguments[1];
|
|
1321
|
+
|
|
1322
|
+
// Extract methods from first argument
|
|
1323
|
+
const methods: SupportedHttpMethod[] = [];
|
|
1324
|
+
|
|
1325
|
+
if (methodArg && (methodArg as ASTLiteral).type === 'Literal') {
|
|
1326
|
+
// Single method: router.on('GET', '/path', handler)
|
|
1327
|
+
const raw = String((methodArg as ASTLiteral).value || '').toLowerCase();
|
|
1328
|
+
if (isSupportedHttpMethod(raw)) {
|
|
1329
|
+
methods.push(raw as SupportedHttpMethod);
|
|
1330
|
+
}
|
|
1331
|
+
} else if (methodArg && (methodArg as ASTNode).type === 'ArrayExpression') {
|
|
1332
|
+
// Array of methods: router.on(['GET', 'POST'], '/path', handler)
|
|
1333
|
+
const arr = methodArg as { elements: ASTNode[] };
|
|
1334
|
+
for (const el of arr.elements) {
|
|
1335
|
+
if (!el || (el as ASTLiteral).type !== 'Literal') continue;
|
|
1336
|
+
const raw = String((el as ASTLiteral).value || '').toLowerCase();
|
|
1337
|
+
if (isSupportedHttpMethod(raw)) {
|
|
1338
|
+
methods.push(raw as SupportedHttpMethod);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
// Skip if no supported methods or path is not a literal
|
|
1344
|
+
if (
|
|
1345
|
+
methods.length === 0 ||
|
|
1346
|
+
!pathArg ||
|
|
1347
|
+
(pathArg as ASTLiteral).type !== 'Literal'
|
|
1348
|
+
) {
|
|
1349
|
+
continue;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
const pathSuffix = String((pathArg as ASTLiteral).value);
|
|
1353
|
+
|
|
1354
|
+
// Create a route entry for each method
|
|
1355
|
+
for (const httpMethod of methods) {
|
|
1356
|
+
const thepath = `${routePrefix}/${routeName}/${pathSuffix}`
|
|
1357
|
+
.replaceAll(/\/{2,}/g, '/')
|
|
1358
|
+
.replaceAll(/\/$/g, '');
|
|
1359
|
+
const id = generateRouteId(
|
|
1360
|
+
projectId,
|
|
1361
|
+
deploymentId,
|
|
1362
|
+
'api',
|
|
1363
|
+
httpMethod,
|
|
1364
|
+
rel,
|
|
1365
|
+
thepath,
|
|
1366
|
+
version
|
|
1367
|
+
);
|
|
1368
|
+
|
|
1369
|
+
// Check if this route uses validator middleware
|
|
1370
|
+
const validatorInfo = hasValidatorCall(statement.expression.arguments);
|
|
1371
|
+
const routeConfig: Record<string, unknown> = {};
|
|
1372
|
+
if (validatorInfo.hasValidator) {
|
|
1373
|
+
routeConfig.hasValidator = true;
|
|
1374
|
+
if (validatorInfo.agentVariable) {
|
|
1375
|
+
routeConfig.agentVariable = validatorInfo.agentVariable;
|
|
1376
|
+
const agentImportPath = importMap.get(validatorInfo.agentVariable);
|
|
1377
|
+
if (agentImportPath) {
|
|
1378
|
+
routeConfig.agentImportPath = agentImportPath;
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
if (validatorInfo.inputSchemaVariable) {
|
|
1382
|
+
routeConfig.inputSchemaVariable =
|
|
1383
|
+
validatorInfo.inputSchemaVariable;
|
|
1384
|
+
}
|
|
1385
|
+
if (validatorInfo.outputSchemaVariable) {
|
|
1386
|
+
routeConfig.outputSchemaVariable =
|
|
1387
|
+
validatorInfo.outputSchemaVariable;
|
|
1388
|
+
}
|
|
1389
|
+
if (validatorInfo.stream !== undefined) {
|
|
1390
|
+
routeConfig.stream = validatorInfo.stream;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
routes.push({
|
|
1395
|
+
id,
|
|
1396
|
+
method: httpMethod,
|
|
1397
|
+
type: 'api',
|
|
1398
|
+
filename: rel,
|
|
1399
|
+
path: thepath,
|
|
1400
|
+
version,
|
|
1401
|
+
config: Object.keys(routeConfig).length > 0 ? routeConfig : undefined,
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
continue;
|
|
1405
|
+
}
|
|
1406
|
+
case 'all': {
|
|
1407
|
+
// router.all(path, handler) - matches all HTTP methods
|
|
1408
|
+
// First arg is path (same as get/post/etc.)
|
|
1409
|
+
if (!action || (action as ASTLiteral).type !== 'Literal') {
|
|
1410
|
+
continue;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
const pathSuffix = String((action as ASTLiteral).value);
|
|
1414
|
+
|
|
1415
|
+
// Create a route entry for each supported method
|
|
1416
|
+
for (const httpMethod of SUPPORTED_HTTP_METHODS) {
|
|
1417
|
+
const thepath = `${routePrefix}/${routeName}/${pathSuffix}`
|
|
1418
|
+
.replaceAll(/\/{2,}/g, '/')
|
|
1419
|
+
.replaceAll(/\/$/g, '');
|
|
1420
|
+
const id = generateRouteId(
|
|
1421
|
+
projectId,
|
|
1422
|
+
deploymentId,
|
|
1423
|
+
'api',
|
|
1424
|
+
httpMethod,
|
|
1425
|
+
rel,
|
|
1426
|
+
thepath,
|
|
1427
|
+
version
|
|
1428
|
+
);
|
|
1429
|
+
|
|
1430
|
+
// Check if this route uses validator middleware
|
|
1431
|
+
const validatorInfo = hasValidatorCall(statement.expression.arguments);
|
|
1432
|
+
const routeConfig: Record<string, unknown> = {};
|
|
1433
|
+
if (validatorInfo.hasValidator) {
|
|
1434
|
+
routeConfig.hasValidator = true;
|
|
1435
|
+
if (validatorInfo.agentVariable) {
|
|
1436
|
+
routeConfig.agentVariable = validatorInfo.agentVariable;
|
|
1437
|
+
const agentImportPath = importMap.get(validatorInfo.agentVariable);
|
|
1438
|
+
if (agentImportPath) {
|
|
1439
|
+
routeConfig.agentImportPath = agentImportPath;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
if (validatorInfo.inputSchemaVariable) {
|
|
1443
|
+
routeConfig.inputSchemaVariable =
|
|
1444
|
+
validatorInfo.inputSchemaVariable;
|
|
1445
|
+
}
|
|
1446
|
+
if (validatorInfo.outputSchemaVariable) {
|
|
1447
|
+
routeConfig.outputSchemaVariable =
|
|
1448
|
+
validatorInfo.outputSchemaVariable;
|
|
1449
|
+
}
|
|
1450
|
+
if (validatorInfo.stream !== undefined) {
|
|
1451
|
+
routeConfig.stream = validatorInfo.stream;
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
routes.push({
|
|
1456
|
+
id,
|
|
1457
|
+
method: httpMethod,
|
|
1458
|
+
type: 'api',
|
|
1459
|
+
filename: rel,
|
|
1460
|
+
path: thepath,
|
|
1461
|
+
version,
|
|
1462
|
+
config: Object.keys(routeConfig).length > 0 ? routeConfig : undefined,
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1309
1465
|
continue;
|
|
1310
1466
|
}
|
|
1311
1467
|
case 'get':
|
|
@@ -1315,6 +1471,52 @@ export async function parseRoute(
|
|
|
1315
1471
|
case 'delete': {
|
|
1316
1472
|
if (action && (action as ASTLiteral).type === 'Literal') {
|
|
1317
1473
|
suffix = String((action as ASTLiteral).value);
|
|
1474
|
+
|
|
1475
|
+
// Check if any argument is a middleware function call (websocket, sse, stream, cron)
|
|
1476
|
+
// New pattern: router.get('/ws', websocket((c, ws) => { ... }))
|
|
1477
|
+
for (const arg of statement.expression.arguments) {
|
|
1478
|
+
if ((arg as ASTCallExpression).type === 'CallExpression') {
|
|
1479
|
+
const callExpr = arg as ASTCallExpression;
|
|
1480
|
+
// Only handle simple Identifier callees (e.g., websocket(), sse())
|
|
1481
|
+
// Skip MemberExpression callees (e.g., obj.method())
|
|
1482
|
+
if (callExpr.callee.type !== 'Identifier') {
|
|
1483
|
+
continue;
|
|
1484
|
+
}
|
|
1485
|
+
const calleeName = (callExpr.callee as ASTNodeIdentifier).name;
|
|
1486
|
+
if (
|
|
1487
|
+
calleeName === 'websocket' ||
|
|
1488
|
+
calleeName === 'sse' ||
|
|
1489
|
+
calleeName === 'stream'
|
|
1490
|
+
) {
|
|
1491
|
+
type = calleeName;
|
|
1492
|
+
break;
|
|
1493
|
+
}
|
|
1494
|
+
if (calleeName === 'cron') {
|
|
1495
|
+
type = 'cron';
|
|
1496
|
+
// First argument to cron() is the schedule expression
|
|
1497
|
+
if (callExpr.arguments && callExpr.arguments.length > 0) {
|
|
1498
|
+
const cronArg = callExpr.arguments[0] as ASTLiteral;
|
|
1499
|
+
if (cronArg.type === 'Literal') {
|
|
1500
|
+
const expression = String(cronArg.value);
|
|
1501
|
+
try {
|
|
1502
|
+
parseCronExpression(expression, {
|
|
1503
|
+
hasSeconds: false,
|
|
1504
|
+
});
|
|
1505
|
+
} catch (ex) {
|
|
1506
|
+
throw new InvalidRouterConfigError({
|
|
1507
|
+
filename,
|
|
1508
|
+
cause: ex,
|
|
1509
|
+
line: body.loc?.start?.line,
|
|
1510
|
+
message: `invalid cron expression "${expression}" in ${filename} at line ${body.loc?.start?.line}`,
|
|
1511
|
+
});
|
|
1512
|
+
}
|
|
1513
|
+
config = { expression };
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
break;
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1318
1520
|
} else {
|
|
1319
1521
|
throw new InvalidRouterConfigError({
|
|
1320
1522
|
filename,
|
|
@@ -1327,6 +1529,8 @@ export async function parseRoute(
|
|
|
1327
1529
|
case 'stream':
|
|
1328
1530
|
case 'sse':
|
|
1329
1531
|
case 'websocket': {
|
|
1532
|
+
// DEPRECATED: router.stream(), router.sse(), router.websocket()
|
|
1533
|
+
// These methods now throw errors at runtime
|
|
1330
1534
|
type = method;
|
|
1331
1535
|
method = 'post';
|
|
1332
1536
|
const theaction = action as ASTLiteral;
|
|
@@ -1336,39 +1540,9 @@ export async function parseRoute(
|
|
|
1336
1540
|
}
|
|
1337
1541
|
break;
|
|
1338
1542
|
}
|
|
1339
|
-
case 'sms': {
|
|
1340
|
-
type = method;
|
|
1341
|
-
method = 'post';
|
|
1342
|
-
const theaction = action as ASTObjectExpression;
|
|
1343
|
-
if (theaction.type === 'ObjectExpression') {
|
|
1344
|
-
config = {};
|
|
1345
|
-
theaction.properties.forEach((p) => {
|
|
1346
|
-
if (p.value.type === 'Literal') {
|
|
1347
|
-
const literal = p.value as ASTLiteral;
|
|
1348
|
-
config![p.key.name] = literal.value;
|
|
1349
|
-
}
|
|
1350
|
-
});
|
|
1351
|
-
const number = theaction.properties.find((p) => p.key.name === 'number');
|
|
1352
|
-
if (number && number.value.type === 'Literal') {
|
|
1353
|
-
const phoneNumber = number.value as ASTLiteral;
|
|
1354
|
-
suffix = hash(String(phoneNumber.value));
|
|
1355
|
-
break;
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
break;
|
|
1359
|
-
}
|
|
1360
|
-
case 'email': {
|
|
1361
|
-
type = method;
|
|
1362
|
-
method = 'post';
|
|
1363
|
-
const theaction = action as ASTLiteral;
|
|
1364
|
-
if (theaction.type === 'Literal') {
|
|
1365
|
-
const email = String(theaction.value);
|
|
1366
|
-
suffix = hash(email);
|
|
1367
|
-
break;
|
|
1368
|
-
}
|
|
1369
|
-
break;
|
|
1370
|
-
}
|
|
1371
1543
|
case 'cron': {
|
|
1544
|
+
// DEPRECATED: router.cron()
|
|
1545
|
+
// This method now throws errors at runtime
|
|
1372
1546
|
type = method;
|
|
1373
1547
|
method = 'post';
|
|
1374
1548
|
const theaction = action as ASTLiteral;
|
|
@@ -1437,8 +1611,11 @@ export async function parseRoute(
|
|
|
1437
1611
|
}
|
|
1438
1612
|
}
|
|
1439
1613
|
|
|
1440
|
-
// For WebSocket/SSE routes that don't use validator(), fall back to exported schemas
|
|
1441
|
-
if (
|
|
1614
|
+
// For WebSocket/SSE/stream routes that don't use validator(), fall back to exported schemas
|
|
1615
|
+
if (
|
|
1616
|
+
!routeConfig.hasValidator &&
|
|
1617
|
+
(type === 'websocket' || type === 'sse' || type === 'stream')
|
|
1618
|
+
) {
|
|
1442
1619
|
if (!routeConfig.inputSchemaVariable && exportedInputSchemaName) {
|
|
1443
1620
|
routeConfig.inputSchemaVariable = exportedInputSchemaName;
|
|
1444
1621
|
}
|