@wave-ai-os/wave-cli 0.1.78 → 0.1.80
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/index.cjs +482 -40
- package/dist/index.js +482 -40
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -328,6 +328,9 @@ function buildAtlasActionLedgerRequest(params) {
|
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
// src/client/graphqlClient.ts
|
|
331
|
+
var MAX_QUERY_ATTEMPTS = 3;
|
|
332
|
+
var MAX_RETRY_DELAY_MS = 2e3;
|
|
333
|
+
var TRANSIENT_QUERY_STATUSES = /* @__PURE__ */ new Set([429, 502, 503, 504]);
|
|
331
334
|
function buildEnvelope(params) {
|
|
332
335
|
return {
|
|
333
336
|
ok: params.ok,
|
|
@@ -358,6 +361,47 @@ function debugLog(config, message) {
|
|
|
358
361
|
process.stderr.write(`[wave:debug] ${message}
|
|
359
362
|
`);
|
|
360
363
|
}
|
|
364
|
+
function retryAfterDelayMs(value, nowMs = Date.now()) {
|
|
365
|
+
if (value === null) {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
const trimmed = value.trim();
|
|
369
|
+
if (/^\d+$/.test(trimmed)) {
|
|
370
|
+
return Math.min(Number(trimmed) * 1e3, MAX_RETRY_DELAY_MS);
|
|
371
|
+
}
|
|
372
|
+
const retryAtMs = Date.parse(trimmed);
|
|
373
|
+
if (Number.isNaN(retryAtMs)) {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
return Math.min(Math.max(retryAtMs - nowMs, 0), MAX_RETRY_DELAY_MS);
|
|
377
|
+
}
|
|
378
|
+
function retryDelayMs(attempt, retryAfter) {
|
|
379
|
+
const serverDelay = retryAfterDelayMs(retryAfter);
|
|
380
|
+
if (serverDelay !== null) {
|
|
381
|
+
return serverDelay;
|
|
382
|
+
}
|
|
383
|
+
const exponentialCeiling = Math.min(100 * 2 ** (attempt - 1), MAX_RETRY_DELAY_MS);
|
|
384
|
+
return Math.floor(Math.random() * exponentialCeiling);
|
|
385
|
+
}
|
|
386
|
+
function waitForRetry(delayMs, signal) {
|
|
387
|
+
if (signal.aborted) {
|
|
388
|
+
return Promise.reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
389
|
+
}
|
|
390
|
+
if (delayMs <= 0) {
|
|
391
|
+
return Promise.resolve();
|
|
392
|
+
}
|
|
393
|
+
return new Promise((resolve, reject) => {
|
|
394
|
+
const timeoutId = setTimeout(() => {
|
|
395
|
+
signal.removeEventListener("abort", handleAbort);
|
|
396
|
+
resolve();
|
|
397
|
+
}, delayMs);
|
|
398
|
+
const handleAbort = () => {
|
|
399
|
+
clearTimeout(timeoutId);
|
|
400
|
+
reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
401
|
+
};
|
|
402
|
+
signal.addEventListener("abort", handleAbort, { once: true });
|
|
403
|
+
});
|
|
404
|
+
}
|
|
361
405
|
function graphqlOperationName(command) {
|
|
362
406
|
return command.split(/[^a-zA-Z0-9]/).filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1)).join("");
|
|
363
407
|
}
|
|
@@ -675,10 +719,41 @@ async function requestGraphqlHttp(params) {
|
|
|
675
719
|
return {
|
|
676
720
|
status: response.status,
|
|
677
721
|
requestId: responseRequestId,
|
|
722
|
+
retryAfter: response.headers.get("retry-after"),
|
|
678
723
|
body,
|
|
679
724
|
graph
|
|
680
725
|
};
|
|
681
726
|
}
|
|
727
|
+
async function requestGraphqlHttpWithRetry(params) {
|
|
728
|
+
const maxAttempts = params.input.operationType === "query" ? MAX_QUERY_ATTEMPTS : 1;
|
|
729
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
730
|
+
try {
|
|
731
|
+
const response = await requestGraphqlHttp(params);
|
|
732
|
+
const shouldRetry = attempt < maxAttempts && TRANSIENT_QUERY_STATUSES.has(response.status);
|
|
733
|
+
if (!shouldRetry) {
|
|
734
|
+
return response;
|
|
735
|
+
}
|
|
736
|
+
const delayMs = retryDelayMs(attempt, response.retryAfter);
|
|
737
|
+
debugLog(
|
|
738
|
+
params.input.config,
|
|
739
|
+
`graphql retry command=${params.input.command} attempt=${attempt + 1}/${maxAttempts} status=${response.status} delayMs=${delayMs}`
|
|
740
|
+
);
|
|
741
|
+
await waitForRetry(delayMs, params.controller.signal);
|
|
742
|
+
} catch (error) {
|
|
743
|
+
if (attempt >= maxAttempts || params.controller.signal.aborted) {
|
|
744
|
+
throw error;
|
|
745
|
+
}
|
|
746
|
+
const delayMs = retryDelayMs(attempt, null);
|
|
747
|
+
const message = error instanceof Error ? error.message : "Network error.";
|
|
748
|
+
debugLog(
|
|
749
|
+
params.input.config,
|
|
750
|
+
`graphql retry command=${params.input.command} attempt=${attempt + 1}/${maxAttempts} error=${message} delayMs=${delayMs}`
|
|
751
|
+
);
|
|
752
|
+
await waitForRetry(delayMs, params.controller.signal);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
throw new Error("GraphQL query retry attempts exhausted.");
|
|
756
|
+
}
|
|
682
757
|
async function reportAtlasLedgerForResult(input, url, result) {
|
|
683
758
|
const ledgerInput = buildAtlasActionLedgerRequest({
|
|
684
759
|
config: input.config,
|
|
@@ -859,7 +934,7 @@ async function graphqlRequest(input) {
|
|
|
859
934
|
}
|
|
860
935
|
}
|
|
861
936
|
}
|
|
862
|
-
const http = await
|
|
937
|
+
const http = await requestGraphqlHttpWithRetry({
|
|
863
938
|
input,
|
|
864
939
|
url,
|
|
865
940
|
requestId,
|
|
@@ -3037,18 +3112,24 @@ var dtoHelpCatalog = {
|
|
|
3037
3112
|
create: [
|
|
3038
3113
|
["rank", "number"],
|
|
3039
3114
|
["organization_id", "string"],
|
|
3040
|
-
["list_id", "string"],
|
|
3041
|
-
["summary", "string"],
|
|
3115
|
+
["list_id*", "string"],
|
|
3116
|
+
["summary*", "string"],
|
|
3042
3117
|
["member_id", "string"],
|
|
3043
|
-
["status", "
|
|
3118
|
+
["status", "enum(open|completed)"],
|
|
3044
3119
|
["due_date", "string"],
|
|
3045
|
-
["priority", "
|
|
3120
|
+
["priority", "enum(no_priority|urgent|high|medium|low)"],
|
|
3046
3121
|
["description", "string"],
|
|
3047
3122
|
["notes", "string | null"],
|
|
3048
3123
|
["label_ids", "number[]"],
|
|
3049
3124
|
["estimate_ids", "number[]"],
|
|
3050
3125
|
["resources_attributes", "ResourceDTO[]"],
|
|
3051
|
-
["subitems_attributes", "
|
|
3126
|
+
["subitems_attributes", "object[]"],
|
|
3127
|
+
["subitems_attributes[].name", "string"],
|
|
3128
|
+
["subitems_attributes[].member_id", "string"],
|
|
3129
|
+
["subitems_attributes[].status", "enum(active|completed)"],
|
|
3130
|
+
["subitems_attributes[].priority", "enum(no_priority|urgent|high|medium|low)"],
|
|
3131
|
+
["subitems_attributes[].description", "string"],
|
|
3132
|
+
["subitems_attributes[].notes", "string | null"]
|
|
3052
3133
|
],
|
|
3053
3134
|
update: [
|
|
3054
3135
|
["rank", "number"],
|
|
@@ -3056,18 +3137,50 @@ var dtoHelpCatalog = {
|
|
|
3056
3137
|
["list_id", "string"],
|
|
3057
3138
|
["summary", "string"],
|
|
3058
3139
|
["member_id", "string"],
|
|
3059
|
-
["status", "
|
|
3140
|
+
["status", "enum(open|completed)"],
|
|
3060
3141
|
["due_date", "string"],
|
|
3061
|
-
["priority", "
|
|
3142
|
+
["priority", "enum(no_priority|urgent|high|medium|low)"],
|
|
3062
3143
|
["description", "string"],
|
|
3063
3144
|
["notes", "string | null"],
|
|
3064
3145
|
["label_ids", "number[]"],
|
|
3065
3146
|
["estimate_ids", "number[]"],
|
|
3066
3147
|
["resources_attributes", "ResourceDTO[]"],
|
|
3067
|
-
["subitems_attributes", "
|
|
3148
|
+
["subitems_attributes", "object[]"],
|
|
3149
|
+
["subitems_attributes[].name", "string"],
|
|
3150
|
+
["subitems_attributes[].member_id", "string"],
|
|
3151
|
+
["subitems_attributes[].status", "enum(active|completed)"],
|
|
3152
|
+
["subitems_attributes[].priority", "enum(no_priority|urgent|high|medium|low)"],
|
|
3153
|
+
["subitems_attributes[].description", "string"],
|
|
3154
|
+
["subitems_attributes[].notes", "string | null"],
|
|
3068
3155
|
["archived_at", "string | null"]
|
|
3069
3156
|
]
|
|
3070
3157
|
},
|
|
3158
|
+
subitem: {
|
|
3159
|
+
source: "wave-api-rb/config/initializers/constants/subitem.rb + wave-api-rb/app/models/subitem.rb",
|
|
3160
|
+
create: [
|
|
3161
|
+
["list_item_id*", "string"],
|
|
3162
|
+
["name*", "string"],
|
|
3163
|
+
["member_id", "string"],
|
|
3164
|
+
["status", "enum(active|completed)"],
|
|
3165
|
+
["priority", "enum(no_priority|urgent|high|medium|low)"],
|
|
3166
|
+
["description", "string"],
|
|
3167
|
+
["notes", "string | null"],
|
|
3168
|
+
["rank", "number"],
|
|
3169
|
+
["due_date", "string"],
|
|
3170
|
+
["estimate_ids", "number[]"]
|
|
3171
|
+
],
|
|
3172
|
+
update: [
|
|
3173
|
+
["name", "string"],
|
|
3174
|
+
["member_id", "string"],
|
|
3175
|
+
["status", "enum(active|completed)"],
|
|
3176
|
+
["priority", "enum(no_priority|urgent|high|medium|low)"],
|
|
3177
|
+
["description", "string"],
|
|
3178
|
+
["notes", "string | null"],
|
|
3179
|
+
["rank", "number"],
|
|
3180
|
+
["due_date", "string"],
|
|
3181
|
+
["estimate_ids", "number[]"]
|
|
3182
|
+
]
|
|
3183
|
+
},
|
|
3071
3184
|
issue_group: {
|
|
3072
3185
|
source: "wave-ui/src/types/issueGroup.ts + wave-api-rb/config/initializers/constants/issue_group.rb + wave-api-rb/app/models/issue_group.rb",
|
|
3073
3186
|
create: [
|
|
@@ -3442,6 +3555,24 @@ function toRows(fields, mode) {
|
|
|
3442
3555
|
return `${field} | required:${requiredForMode} | type:${type} | ${humanize(field)}`;
|
|
3443
3556
|
});
|
|
3444
3557
|
}
|
|
3558
|
+
function exampleValue(type) {
|
|
3559
|
+
if (type === "number") return 1;
|
|
3560
|
+
if (type === "boolean") return true;
|
|
3561
|
+
if (type.endsWith("[]")) return [];
|
|
3562
|
+
const enumValues = /^enum\(([^)]+)\)$/u.exec(type)?.[1]?.split("|");
|
|
3563
|
+
return enumValues?.[0] ?? "value";
|
|
3564
|
+
}
|
|
3565
|
+
function examplePayload(rootKey, fields, mode) {
|
|
3566
|
+
const requiredFields = mode === "create" ? fields.filter(([field]) => field.endsWith("*")) : [];
|
|
3567
|
+
const exampleFields = requiredFields.length > 0 ? requiredFields : fields.slice(0, 1);
|
|
3568
|
+
const entity = Object.fromEntries(
|
|
3569
|
+
exampleFields.map(([rawField, type]) => [
|
|
3570
|
+
rawField.replace(/\*$/u, ""),
|
|
3571
|
+
exampleValue(type)
|
|
3572
|
+
])
|
|
3573
|
+
);
|
|
3574
|
+
return JSON.stringify({ [rootKey]: entity });
|
|
3575
|
+
}
|
|
3445
3576
|
function buildDataJsonHelp(rootKey, mode) {
|
|
3446
3577
|
const config = dtoHelpCatalog[rootKey];
|
|
3447
3578
|
if (!config) return null;
|
|
@@ -3454,10 +3585,205 @@ function buildDataJsonHelp(rootKey, mode) {
|
|
|
3454
3585
|
`note: fields containing "preference" are intentionally omitted.`,
|
|
3455
3586
|
"field | required | type | description",
|
|
3456
3587
|
...toRows(fields, mode),
|
|
3457
|
-
`example:
|
|
3588
|
+
`example: ${examplePayload(rootKey, fields, mode)}`
|
|
3458
3589
|
].join("\n");
|
|
3459
3590
|
}
|
|
3460
3591
|
|
|
3592
|
+
// src/entityPayloadContracts.ts
|
|
3593
|
+
var PRIORITIES = ["no_priority", "urgent", "high", "medium", "low"];
|
|
3594
|
+
var SUBITEM_STATUSES = ["active", "completed"];
|
|
3595
|
+
var LIST_ITEM_STATUSES = ["open", "completed"];
|
|
3596
|
+
var subitemFields = {
|
|
3597
|
+
list_item_id: { type: "string" },
|
|
3598
|
+
name: { type: "string" },
|
|
3599
|
+
status: { type: "string", enum: SUBITEM_STATUSES },
|
|
3600
|
+
priority: { type: "string", enum: PRIORITIES }
|
|
3601
|
+
};
|
|
3602
|
+
var listItemFields = {
|
|
3603
|
+
list_id: { type: "string" },
|
|
3604
|
+
summary: { type: "string" },
|
|
3605
|
+
status: { type: "string", enum: LIST_ITEM_STATUSES },
|
|
3606
|
+
priority: { type: "string", enum: PRIORITIES },
|
|
3607
|
+
subitems_attributes: {
|
|
3608
|
+
type: "array",
|
|
3609
|
+
items: {
|
|
3610
|
+
type: "object",
|
|
3611
|
+
fields: subitemFields,
|
|
3612
|
+
required: ["name"]
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
};
|
|
3616
|
+
var listItemCreateContract = {
|
|
3617
|
+
rootKey: "list_item",
|
|
3618
|
+
fields: listItemFields,
|
|
3619
|
+
required: ["list_id", "summary"]
|
|
3620
|
+
};
|
|
3621
|
+
var listItemUpdateContract = {
|
|
3622
|
+
rootKey: "list_item",
|
|
3623
|
+
fields: listItemFields
|
|
3624
|
+
};
|
|
3625
|
+
var subitemCreateContract = {
|
|
3626
|
+
rootKey: "subitem",
|
|
3627
|
+
fields: subitemFields,
|
|
3628
|
+
required: ["list_item_id", "name"]
|
|
3629
|
+
};
|
|
3630
|
+
var subitemUpdateContract = {
|
|
3631
|
+
rootKey: "subitem",
|
|
3632
|
+
fields: subitemFields
|
|
3633
|
+
};
|
|
3634
|
+
var CONTRACTS = {
|
|
3635
|
+
"list-items.create": listItemCreateContract,
|
|
3636
|
+
"list-items.update": listItemUpdateContract,
|
|
3637
|
+
"subitems.create": subitemCreateContract,
|
|
3638
|
+
"subitems.update": subitemUpdateContract
|
|
3639
|
+
};
|
|
3640
|
+
function isPlainObject(value) {
|
|
3641
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3642
|
+
}
|
|
3643
|
+
function parsePayload(value) {
|
|
3644
|
+
if (typeof value !== "string") return value;
|
|
3645
|
+
try {
|
|
3646
|
+
return JSON.parse(value);
|
|
3647
|
+
} catch {
|
|
3648
|
+
return /* @__PURE__ */ Symbol.for("invalid-json");
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
function typeMatches(value, type) {
|
|
3652
|
+
if (!type) return true;
|
|
3653
|
+
if (type === "array") return Array.isArray(value);
|
|
3654
|
+
if (type === "object") return isPlainObject(value);
|
|
3655
|
+
return typeof value === type;
|
|
3656
|
+
}
|
|
3657
|
+
function validateField(contract, value, path) {
|
|
3658
|
+
if (!typeMatches(value, contract.type)) {
|
|
3659
|
+
return [`${path.join(".")} must be ${contract.type}.`];
|
|
3660
|
+
}
|
|
3661
|
+
if (contract.enum && !contract.enum.includes(value)) {
|
|
3662
|
+
return [`${path.join(".")} must be one of ${contract.enum.join(", ")}.`];
|
|
3663
|
+
}
|
|
3664
|
+
if (contract.type === "object" && contract.fields && isPlainObject(value)) {
|
|
3665
|
+
const missing = (contract.required ?? []).filter(
|
|
3666
|
+
(field) => value[field] === void 0 || value[field] === null || value[field] === ""
|
|
3667
|
+
);
|
|
3668
|
+
return [
|
|
3669
|
+
...missing.map((field) => `${[...path, field].join(".")} is required.`),
|
|
3670
|
+
...validateFields(contract.fields, value, path)
|
|
3671
|
+
];
|
|
3672
|
+
}
|
|
3673
|
+
if (contract.type === "array" && contract.items && Array.isArray(value)) {
|
|
3674
|
+
return value.flatMap(
|
|
3675
|
+
(item, index) => validateField(contract.items, item, [...path, index])
|
|
3676
|
+
);
|
|
3677
|
+
}
|
|
3678
|
+
return [];
|
|
3679
|
+
}
|
|
3680
|
+
function validateFields(fields, value, path) {
|
|
3681
|
+
return Object.entries(fields).flatMap(([field, contract]) => {
|
|
3682
|
+
const fieldValue = value[field];
|
|
3683
|
+
return fieldValue === void 0 ? [] : validateField(contract, fieldValue, [...path, field]);
|
|
3684
|
+
});
|
|
3685
|
+
}
|
|
3686
|
+
function contractEntity(contract, payload) {
|
|
3687
|
+
if (!isPlainObject(payload)) return null;
|
|
3688
|
+
if (!(contract.rootKey in payload)) return payload;
|
|
3689
|
+
const rooted = payload[contract.rootKey];
|
|
3690
|
+
return isPlainObject(rooted) ? rooted : null;
|
|
3691
|
+
}
|
|
3692
|
+
function validateOperationDataJson(operationId2, value) {
|
|
3693
|
+
const contract = CONTRACTS[operationId2];
|
|
3694
|
+
if (!contract) return [];
|
|
3695
|
+
const payload = parsePayload(value);
|
|
3696
|
+
if (payload === /* @__PURE__ */ Symbol.for("invalid-json")) {
|
|
3697
|
+
return ["Invalid input value for dataJson: must be valid JSON."];
|
|
3698
|
+
}
|
|
3699
|
+
const entity = contractEntity(contract, payload);
|
|
3700
|
+
if (!entity) {
|
|
3701
|
+
return [
|
|
3702
|
+
`Invalid input value for dataJson: ${contract.rootKey} payload must be a JSON object.`
|
|
3703
|
+
];
|
|
3704
|
+
}
|
|
3705
|
+
const missing = (contract.required ?? []).filter(
|
|
3706
|
+
(field) => entity[field] === void 0 || entity[field] === null || entity[field] === ""
|
|
3707
|
+
);
|
|
3708
|
+
return [
|
|
3709
|
+
...missing.map((field) => `${contract.rootKey}.${field} is required.`),
|
|
3710
|
+
...validateFields(contract.fields, entity, [contract.rootKey])
|
|
3711
|
+
].map(
|
|
3712
|
+
(error) => `Invalid input value for dataJson: ${error}`
|
|
3713
|
+
);
|
|
3714
|
+
}
|
|
3715
|
+
function assertOperationPayload(operationId2, body) {
|
|
3716
|
+
const errors = validateOperationDataJson(operationId2, body);
|
|
3717
|
+
if (errors.length === 0) return;
|
|
3718
|
+
throw new CliError({
|
|
3719
|
+
message: errors.join(" "),
|
|
3720
|
+
kind: "invalid_args",
|
|
3721
|
+
status: 400,
|
|
3722
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
3723
|
+
});
|
|
3724
|
+
}
|
|
3725
|
+
function fieldSchema(contract) {
|
|
3726
|
+
const type = contract.type ?? "object";
|
|
3727
|
+
return {
|
|
3728
|
+
type,
|
|
3729
|
+
...contract.enum ? { enum: [...contract.enum] } : {},
|
|
3730
|
+
...contract.fields ? {
|
|
3731
|
+
properties: Object.fromEntries(
|
|
3732
|
+
Object.entries(contract.fields).map(([field, nested]) => [
|
|
3733
|
+
field,
|
|
3734
|
+
fieldSchema(nested)
|
|
3735
|
+
])
|
|
3736
|
+
),
|
|
3737
|
+
...contract.required ? { required: [...contract.required] } : {},
|
|
3738
|
+
additionalProperties: true
|
|
3739
|
+
} : {},
|
|
3740
|
+
...contract.items ? { items: fieldSchema(contract.items) } : {}
|
|
3741
|
+
};
|
|
3742
|
+
}
|
|
3743
|
+
function entitySchema(contract) {
|
|
3744
|
+
return {
|
|
3745
|
+
type: "object",
|
|
3746
|
+
properties: Object.fromEntries(
|
|
3747
|
+
Object.entries(contract.fields).map(([field, nested]) => [
|
|
3748
|
+
field,
|
|
3749
|
+
fieldSchema(nested)
|
|
3750
|
+
])
|
|
3751
|
+
),
|
|
3752
|
+
...contract.required ? { required: [...contract.required] } : {},
|
|
3753
|
+
additionalProperties: true
|
|
3754
|
+
};
|
|
3755
|
+
}
|
|
3756
|
+
function exampleDataJsonForOperation(operationId2) {
|
|
3757
|
+
const contract = CONTRACTS[operationId2];
|
|
3758
|
+
if (!contract) return null;
|
|
3759
|
+
const entity = Object.fromEntries(
|
|
3760
|
+
(contract.required ?? []).map((field) => [field, "example"])
|
|
3761
|
+
);
|
|
3762
|
+
return { [contract.rootKey]: entity };
|
|
3763
|
+
}
|
|
3764
|
+
function dataJsonSchemaPropertyForOperation(operationId2, description) {
|
|
3765
|
+
const contract = CONTRACTS[operationId2];
|
|
3766
|
+
if (!contract) return null;
|
|
3767
|
+
const entity = entitySchema(contract);
|
|
3768
|
+
return {
|
|
3769
|
+
type: ["object", "string"],
|
|
3770
|
+
...description ? { description } : {},
|
|
3771
|
+
anyOf: [
|
|
3772
|
+
{
|
|
3773
|
+
type: "string",
|
|
3774
|
+
description: "A JSON-serialized payload matching one of the object forms."
|
|
3775
|
+
},
|
|
3776
|
+
entity,
|
|
3777
|
+
{
|
|
3778
|
+
type: "object",
|
|
3779
|
+
properties: { [contract.rootKey]: entity },
|
|
3780
|
+
required: [contract.rootKey],
|
|
3781
|
+
additionalProperties: false
|
|
3782
|
+
}
|
|
3783
|
+
]
|
|
3784
|
+
};
|
|
3785
|
+
}
|
|
3786
|
+
|
|
3461
3787
|
// src/commands/entityCrud.ts
|
|
3462
3788
|
var idSchema2 = import_zod4.z.string().min(1);
|
|
3463
3789
|
function toSingularResourceName(resourcePath) {
|
|
@@ -3631,6 +3957,7 @@ function registerEntityCrudCommands(program, config) {
|
|
|
3631
3957
|
if (config.normalizeCreateBody) {
|
|
3632
3958
|
body = config.normalizeCreateBody(body);
|
|
3633
3959
|
}
|
|
3960
|
+
assertOperationPayload(`${config.command}.create`, body);
|
|
3634
3961
|
assertRequiredCreateFields(body, config.rootKey, config.requiredCreateFields);
|
|
3635
3962
|
const defaultCommand = `${config.command}.create`;
|
|
3636
3963
|
const defaultField = `create_${toSingularResourceName(config.resourcePath)}`;
|
|
@@ -3663,6 +3990,7 @@ function registerEntityCrudCommands(program, config) {
|
|
|
3663
3990
|
if (config.normalizeUpdateBody) {
|
|
3664
3991
|
body = config.normalizeUpdateBody(body);
|
|
3665
3992
|
}
|
|
3993
|
+
assertOperationPayload(`${config.command}.update`, body);
|
|
3666
3994
|
const singular = toSingularResourceName(config.resourcePath);
|
|
3667
3995
|
await runGraphqlMutationCommand({
|
|
3668
3996
|
command: `${config.command}.update`,
|
|
@@ -6195,13 +6523,17 @@ function registerChildCommands(program, config) {
|
|
|
6195
6523
|
...config.searchRequiredOptions ? { requiredOptions: config.searchRequiredOptions } : {}
|
|
6196
6524
|
};
|
|
6197
6525
|
registerGraphqlSearchCommand(command, searchConfig);
|
|
6198
|
-
command.command("create").requiredOption(
|
|
6526
|
+
command.command("create").requiredOption(
|
|
6527
|
+
"--data-json <dataJson>",
|
|
6528
|
+
buildDataJsonHelp(config.rootKey, "create") ?? void 0
|
|
6529
|
+
).action(async (opts, cmd) => {
|
|
6199
6530
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
6200
6531
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
6201
6532
|
let body = normalizeBody2(String(opts.dataJson), config.rootKey);
|
|
6202
6533
|
if (config.normalizeCreateBody) {
|
|
6203
6534
|
body = config.normalizeCreateBody(body);
|
|
6204
6535
|
}
|
|
6536
|
+
assertOperationPayload(`${config.command}.create`, body);
|
|
6205
6537
|
assertRequiredParent(body, config.rootKey, config.parentFlag.replace(/-/g, "_"));
|
|
6206
6538
|
await runGraphqlMutationCommand({
|
|
6207
6539
|
command: `${config.command}.create`,
|
|
@@ -6214,11 +6546,15 @@ function registerChildCommands(program, config) {
|
|
|
6214
6546
|
}
|
|
6215
6547
|
});
|
|
6216
6548
|
});
|
|
6217
|
-
command.command("update").requiredOption("--id <id>").requiredOption(
|
|
6549
|
+
command.command("update").requiredOption("--id <id>").requiredOption(
|
|
6550
|
+
"--data-json <dataJson>",
|
|
6551
|
+
buildDataJsonHelp(config.rootKey, "update") ?? void 0
|
|
6552
|
+
).action(async (opts, cmd) => {
|
|
6218
6553
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
6219
6554
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
6220
6555
|
const id = idSchema12.parse(opts.id);
|
|
6221
6556
|
const body = normalizeBody2(String(opts.dataJson), config.rootKey);
|
|
6557
|
+
assertOperationPayload(`${config.command}.update`, body);
|
|
6222
6558
|
await runGraphqlMutationCommand({
|
|
6223
6559
|
command: `${config.command}.update`,
|
|
6224
6560
|
operationName: config.updateOperationName,
|
|
@@ -14863,6 +15199,29 @@ var AUTOMATION_RUN_SELECTION = `{
|
|
|
14863
15199
|
targetId
|
|
14864
15200
|
}
|
|
14865
15201
|
}`;
|
|
15202
|
+
var AUTOMATION_RUN_STATUS_SELECTION = `{
|
|
15203
|
+
status
|
|
15204
|
+
automationTaskId
|
|
15205
|
+
automationTaskSlug
|
|
15206
|
+
agentId
|
|
15207
|
+
agentSlug
|
|
15208
|
+
agentTriggerId
|
|
15209
|
+
chatId
|
|
15210
|
+
chatSlug
|
|
15211
|
+
chatLane
|
|
15212
|
+
messageId
|
|
15213
|
+
runId
|
|
15214
|
+
executionId
|
|
15215
|
+
executionSlug
|
|
15216
|
+
traceId
|
|
15217
|
+
correlationId
|
|
15218
|
+
outputContentId
|
|
15219
|
+
outputContentSlug
|
|
15220
|
+
terminalReason
|
|
15221
|
+
error
|
|
15222
|
+
queuedAt
|
|
15223
|
+
completedAt
|
|
15224
|
+
}`;
|
|
14866
15225
|
function asRecord7(value) {
|
|
14867
15226
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
14868
15227
|
}
|
|
@@ -14993,15 +15352,58 @@ function normalizeAutomationRunPayload(payload) {
|
|
|
14993
15352
|
const automationTaskId = asRequiredString(data?.automation_task_id);
|
|
14994
15353
|
const automationTaskSlug = asRequiredString(data?.automation_task_slug);
|
|
14995
15354
|
const agentId = asRequiredString(data?.agent_id);
|
|
14996
|
-
const agentSlug = asRequiredString(data?.agent_slug);
|
|
14997
|
-
const agentTriggerId = asRequiredString(data?.agent_trigger_id);
|
|
14998
|
-
const executionId = asRequiredString(data?.execution_id);
|
|
14999
|
-
const executionSlug = asRequiredString(data?.execution_slug);
|
|
15000
15355
|
const executionStatus = asRequiredString(data?.execution_status);
|
|
15001
|
-
|
|
15002
|
-
if (!data || !automationTaskId || !automationTaskSlug || !agentId || !agentSlug || !agentTriggerId || !executionId || !executionSlug || !executionStatus || !traceId) {
|
|
15356
|
+
if (!data || !automationTaskId || !automationTaskSlug || !agentId || !executionStatus) {
|
|
15003
15357
|
throw new CliError({
|
|
15004
|
-
message: "Automation run response did not include automation
|
|
15358
|
+
message: "Automation run response did not include automation identity and status.",
|
|
15359
|
+
kind: "malformed_response",
|
|
15360
|
+
status: 502,
|
|
15361
|
+
exitCode: EXIT_CODES.networkOrUpstream
|
|
15362
|
+
});
|
|
15363
|
+
}
|
|
15364
|
+
if (executionStatus === "queued") {
|
|
15365
|
+
const chatId = asRequiredString(data.chat_id);
|
|
15366
|
+
const chatSlug = asRequiredString(data.chat_slug);
|
|
15367
|
+
const chatLane = asRequiredString(data.chat_lane);
|
|
15368
|
+
const messageId = asRequiredString(data.message_id);
|
|
15369
|
+
const runId = asRequiredString(data.run_id);
|
|
15370
|
+
const memberId = asRequiredString(data.member_id);
|
|
15371
|
+
if (!chatId || !chatSlug || !chatLane || !messageId || !runId || !memberId) {
|
|
15372
|
+
throw new CliError({
|
|
15373
|
+
message: "Queued Automation response did not include chat, message, run, and member identity.",
|
|
15374
|
+
kind: "malformed_response",
|
|
15375
|
+
status: 502,
|
|
15376
|
+
exitCode: EXIT_CODES.networkOrUpstream
|
|
15377
|
+
});
|
|
15378
|
+
}
|
|
15379
|
+
return {
|
|
15380
|
+
ok: mutation.ok,
|
|
15381
|
+
status: mutation.status,
|
|
15382
|
+
errorCode: mutation.errorCode ?? null,
|
|
15383
|
+
errors: mutation.errors ?? null,
|
|
15384
|
+
run: {
|
|
15385
|
+
executed: data.executed === true,
|
|
15386
|
+
status: executionStatus,
|
|
15387
|
+
automation: { id: automationTaskId, slug: automationTaskSlug },
|
|
15388
|
+
agent: { id: agentId },
|
|
15389
|
+
trigger: { id: asRequiredString(data.agent_trigger_id) },
|
|
15390
|
+
queue: {
|
|
15391
|
+
chat: { id: chatId, slug: chatSlug, lane: chatLane },
|
|
15392
|
+
message_id: messageId,
|
|
15393
|
+
run_id: runId,
|
|
15394
|
+
member_id: memberId
|
|
15395
|
+
},
|
|
15396
|
+
readback_command: `wave automations run-status --id ${automationTaskSlug} --message-id ${messageId} --run-id ${runId}`
|
|
15397
|
+
}
|
|
15398
|
+
};
|
|
15399
|
+
}
|
|
15400
|
+
const agentSlug = asRequiredString(data.agent_slug);
|
|
15401
|
+
const executionId = asRequiredString(data.execution_id);
|
|
15402
|
+
const executionSlug = asRequiredString(data.execution_slug);
|
|
15403
|
+
const traceId = asRequiredString(data.trace_id);
|
|
15404
|
+
if (!agentSlug || !executionId || !executionSlug || !traceId) {
|
|
15405
|
+
throw new CliError({
|
|
15406
|
+
message: "Terminal Automation response did not include execution and trace evidence.",
|
|
15005
15407
|
kind: "malformed_response",
|
|
15006
15408
|
status: 502,
|
|
15007
15409
|
exitCode: EXIT_CODES.networkOrUpstream
|
|
@@ -15024,7 +15426,7 @@ function normalizeAutomationRunPayload(payload) {
|
|
|
15024
15426
|
slug: agentSlug
|
|
15025
15427
|
},
|
|
15026
15428
|
trigger: {
|
|
15027
|
-
id:
|
|
15429
|
+
id: asRequiredString(data.agent_trigger_id),
|
|
15028
15430
|
type: asRequiredString(data.trigger_type)
|
|
15029
15431
|
},
|
|
15030
15432
|
execution: {
|
|
@@ -15321,7 +15723,7 @@ function registerAtlasAuthoringCommands(program) {
|
|
|
15321
15723
|
isShow: true
|
|
15322
15724
|
});
|
|
15323
15725
|
});
|
|
15324
|
-
automations.command("run").description("
|
|
15726
|
+
automations.command("run").description("Queue one Automation by id or slug and return exact status readback identifiers").requiredOption("--id <idOrSlug>", "Automation id or slug").action(async (opts, cmd) => {
|
|
15325
15727
|
const automationId = idSchema14.parse(opts.id);
|
|
15326
15728
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
15327
15729
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
@@ -15335,6 +15737,33 @@ function registerAtlasAuthoringCommands(program) {
|
|
|
15335
15737
|
transformMutationPayload: normalizeAutomationRunPayload
|
|
15336
15738
|
});
|
|
15337
15739
|
});
|
|
15740
|
+
automations.command("run-status").description("Read one queued or terminal Automation execution by its run identity").requiredOption("--id <idOrSlug>", "Automation id or slug returned by automations run").requiredOption("--message-id <messageId>", "Message id returned by automations run").requiredOption("--run-id <runId>", "Run id returned by automations run").action(async (opts, cmd) => {
|
|
15741
|
+
const automationId = idSchema14.parse(opts.id);
|
|
15742
|
+
const messageId = idSchema14.parse(opts.messageId);
|
|
15743
|
+
const runId = idSchema14.parse(opts.runId);
|
|
15744
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
15745
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
15746
|
+
await runGraphqlQueryCommand({
|
|
15747
|
+
command: "automations.run-status",
|
|
15748
|
+
operationName: "AutomationsRunStatus",
|
|
15749
|
+
runtimeOptions: context.runtimeOptions,
|
|
15750
|
+
field: "automation_run_status",
|
|
15751
|
+
variables: {
|
|
15752
|
+
organization_id: organizationId,
|
|
15753
|
+
automation_id: automationId,
|
|
15754
|
+
message_id: messageId,
|
|
15755
|
+
run_id: runId
|
|
15756
|
+
},
|
|
15757
|
+
variableTypes: {
|
|
15758
|
+
organization_id: "ID!",
|
|
15759
|
+
automation_id: "ID!",
|
|
15760
|
+
message_id: "ID!",
|
|
15761
|
+
run_id: "ID!"
|
|
15762
|
+
},
|
|
15763
|
+
selectionSet: AUTOMATION_RUN_STATUS_SELECTION,
|
|
15764
|
+
isShow: true
|
|
15765
|
+
});
|
|
15766
|
+
});
|
|
15338
15767
|
automations.command("run-show").description("Read one Automation run artifact by Agent id and execution slug").requiredOption("--agent-id <agentIdOrSlug>", "Agent id or slug").requiredOption("--execution-slug <executionSlug>", "Execution slug returned by automations run").action(async (opts, cmd) => {
|
|
15339
15768
|
const agentId = idSchema14.parse(opts.agentId);
|
|
15340
15769
|
const executionSlug = idSchema14.parse(opts.executionSlug);
|
|
@@ -15497,7 +15926,7 @@ var import_node_path4 = require("path");
|
|
|
15497
15926
|
var import_node_crypto3 = require("crypto");
|
|
15498
15927
|
|
|
15499
15928
|
// src/version.ts
|
|
15500
|
-
var CLI_VERSION = "0.1.
|
|
15929
|
+
var CLI_VERSION = "0.1.80";
|
|
15501
15930
|
|
|
15502
15931
|
// src/operationMetadata.ts
|
|
15503
15932
|
var DISCOVERY_OPERATION_IDS = [
|
|
@@ -15620,6 +16049,7 @@ var READ_OPERATION_IDS = [
|
|
|
15620
16049
|
"agents.show",
|
|
15621
16050
|
"auth.status",
|
|
15622
16051
|
"automations.run-show",
|
|
16052
|
+
"automations.run-status",
|
|
15623
16053
|
"automations.show",
|
|
15624
16054
|
"broadcast.community",
|
|
15625
16055
|
"broadcast.list",
|
|
@@ -16034,7 +16464,7 @@ function operationId(path) {
|
|
|
16034
16464
|
function inputKeyForArgument(argument) {
|
|
16035
16465
|
return argument.name().replace(/<|>|\[|\]|\.\.\./g, "");
|
|
16036
16466
|
}
|
|
16037
|
-
function inputSchemaFor(command) {
|
|
16467
|
+
function inputSchemaFor(command, id) {
|
|
16038
16468
|
const properties = {};
|
|
16039
16469
|
const required = [];
|
|
16040
16470
|
for (const argument of command.registeredArguments) {
|
|
@@ -16048,7 +16478,8 @@ function inputSchemaFor(command) {
|
|
|
16048
16478
|
for (const option of command.options) {
|
|
16049
16479
|
const key = option.attributeName();
|
|
16050
16480
|
if (MACHINE_PRESENTATION_OPTIONS.has(key)) continue;
|
|
16051
|
-
|
|
16481
|
+
const payloadSchema = key === "dataJson" ? dataJsonSchemaPropertyForOperation(id, option.description) : null;
|
|
16482
|
+
properties[key] = payloadSchema ?? {
|
|
16052
16483
|
type: option.required ? "string" : option.optional ? ["boolean", "string"] : "boolean",
|
|
16053
16484
|
...option.description ? { description: option.description } : {}
|
|
16054
16485
|
};
|
|
@@ -16061,12 +16492,17 @@ function inputSchemaFor(command) {
|
|
|
16061
16492
|
required: required.sort()
|
|
16062
16493
|
};
|
|
16063
16494
|
}
|
|
16064
|
-
function exampleFor(inputSchema) {
|
|
16495
|
+
function exampleFor(inputSchema, id) {
|
|
16065
16496
|
const input = {};
|
|
16066
16497
|
for (const key of inputSchema.required) {
|
|
16498
|
+
const payloadExample = key === "dataJson" ? exampleDataJsonForOperation(id) : null;
|
|
16499
|
+
if (payloadExample) {
|
|
16500
|
+
input[key] = payloadExample;
|
|
16501
|
+
continue;
|
|
16502
|
+
}
|
|
16067
16503
|
const propertyType = inputSchema.properties[key]?.type;
|
|
16068
16504
|
const types = Array.isArray(propertyType) ? propertyType : [propertyType];
|
|
16069
|
-
input[key] = types.includes("array") ? ["example"] : types.includes("boolean") ? true : "example";
|
|
16505
|
+
input[key] = types.includes("object") ? {} : types.includes("array") ? ["example"] : types.includes("boolean") ? true : "example";
|
|
16070
16506
|
}
|
|
16071
16507
|
return [{ name: "minimal valid input", input }];
|
|
16072
16508
|
}
|
|
@@ -16097,7 +16533,8 @@ function listInvocableCommands(program) {
|
|
|
16097
16533
|
}
|
|
16098
16534
|
function entryFor(command, metadata) {
|
|
16099
16535
|
const path = commandPath(command);
|
|
16100
|
-
const
|
|
16536
|
+
const id = operationId(path);
|
|
16537
|
+
const inputSchema = inputSchemaFor(command, id);
|
|
16101
16538
|
const summary = command.description() || `Run ${path.join(" ")}.`;
|
|
16102
16539
|
return {
|
|
16103
16540
|
id: operationId(path),
|
|
@@ -16110,7 +16547,7 @@ function entryFor(command, metadata) {
|
|
|
16110
16547
|
atlasSafetyClass: metadata.atlasSafetyClass,
|
|
16111
16548
|
inputSchema,
|
|
16112
16549
|
outputSchema: outputSchema(),
|
|
16113
|
-
examples: exampleFor(inputSchema),
|
|
16550
|
+
examples: exampleFor(inputSchema, id),
|
|
16114
16551
|
machine: metadata.machine
|
|
16115
16552
|
};
|
|
16116
16553
|
}
|
|
@@ -16328,6 +16765,7 @@ var NAMESPACE_DOCS = {
|
|
|
16328
16765
|
`wave automations create --summary "Weekly review" --agent-id 123 --ai-task-config '{"cycle":"repeat","repeatSchedule":{"interval":1,"frequency":"week","weekdays":[1,3],"at":"2:30 PM","starting":"2026-07-20T00:00:00.000Z","ending":"never","endingRuns":1,"endingDate":null,"timezone":"America/Phoenix"}}' --idempotency-key automation-create-001`,
|
|
16329
16766
|
"wave automations show --id ATK-01",
|
|
16330
16767
|
"wave automations run --id ATK-01",
|
|
16768
|
+
"wave automations run-status --id ATK-01 --message-id 123 --run-id run_123",
|
|
16331
16769
|
"wave automations run-show --agent-id AGT-01 --execution-slug ART-1234567890",
|
|
16332
16770
|
'wave automations update --id ATK-01 --expected-update-version 2026-07-17T12:00:00.123456Z --summary "Weekly project review"'
|
|
16333
16771
|
],
|
|
@@ -16340,11 +16778,12 @@ var NAMESPACE_DOCS = {
|
|
|
16340
16778
|
"Only the API-defined ai_task_config field accepts validated JSON.",
|
|
16341
16779
|
"Optional executor Agent linkage is sent only through the API-defined top-level agentId input.",
|
|
16342
16780
|
"Update calls only updateTask with an exact opaque updateVersion token; it cannot change status, task type, ownership, or project linkage.",
|
|
16343
|
-
"Run calls only runAutomationNow
|
|
16781
|
+
"Run calls only runAutomationNow and returns the exact queued chat, message, and run identity.",
|
|
16782
|
+
"Run-status reads queued or terminal execution and trace evidence using that exact identity.",
|
|
16344
16783
|
"Run-show reads the persisted Automation run artifact through agentAutomationRun by Agent id and execution slug.",
|
|
16345
16784
|
"Show uses the API-owned automation query by id; no slug fallback is implemented."
|
|
16346
16785
|
],
|
|
16347
|
-
commands: ["create", "show", "run", "run-show", "update"]
|
|
16786
|
+
commands: ["create", "show", "run", "run-status", "run-show", "update"]
|
|
16348
16787
|
}
|
|
16349
16788
|
},
|
|
16350
16789
|
broadcast: {
|
|
@@ -17235,7 +17674,7 @@ function machineEnvelope(params) {
|
|
|
17235
17674
|
meta: { requestId: "machine" }
|
|
17236
17675
|
};
|
|
17237
17676
|
}
|
|
17238
|
-
function
|
|
17677
|
+
function isPlainObject2(value) {
|
|
17239
17678
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
17240
17679
|
}
|
|
17241
17680
|
function hasAction2(command) {
|
|
@@ -17309,7 +17748,7 @@ async function readMachineInput(location) {
|
|
|
17309
17748
|
}
|
|
17310
17749
|
if (!raw.trim()) throw new Error("Machine input JSON is required.");
|
|
17311
17750
|
const parsed = JSON.parse(raw);
|
|
17312
|
-
if (!
|
|
17751
|
+
if (!isPlainObject2(parsed)) throw new Error("Machine input must be a JSON object.");
|
|
17313
17752
|
return parsed;
|
|
17314
17753
|
}
|
|
17315
17754
|
function inputDigest(input) {
|
|
@@ -17317,7 +17756,7 @@ function inputDigest(input) {
|
|
|
17317
17756
|
}
|
|
17318
17757
|
function canonicalJson(value) {
|
|
17319
17758
|
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
17320
|
-
if (
|
|
17759
|
+
if (isPlainObject2(value)) {
|
|
17321
17760
|
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
|
|
17322
17761
|
}
|
|
17323
17762
|
return JSON.stringify(value);
|
|
@@ -17347,18 +17786,18 @@ function parseTrustedJsonFromFd(fd, predicate) {
|
|
|
17347
17786
|
}
|
|
17348
17787
|
}
|
|
17349
17788
|
function isTrustedAuth(value) {
|
|
17350
|
-
return
|
|
17789
|
+
return isPlainObject2(value) && typeof value.token === "string" && value.token.trim() !== "" && typeof value.baseUrl === "string" && value.baseUrl.trim() !== "" && typeof value.organizationId === "string" && value.organizationId.trim() !== "" && typeof value.actorId === "string" && value.actorId.trim() !== "";
|
|
17351
17790
|
}
|
|
17352
17791
|
function isTrustedApproval(value) {
|
|
17353
|
-
return
|
|
17792
|
+
return isPlainObject2(value) && typeof value.operation === "string" && typeof value.inputDigest === "string" && typeof value.cliVersion === "string" && typeof value.registryDigest === "string" && typeof value.organizationId === "string" && value.organizationId.trim() !== "" && typeof value.actorId === "string" && value.actorId.trim() !== "";
|
|
17354
17793
|
}
|
|
17355
17794
|
function operationCommand(program, id) {
|
|
17356
17795
|
return listInvocableCommands(program).find((command) => commandId(command) === id);
|
|
17357
17796
|
}
|
|
17358
|
-
function
|
|
17797
|
+
function typeMatches2(value, type) {
|
|
17359
17798
|
if (type === "array") return Array.isArray(value);
|
|
17360
17799
|
if (type === "null") return value === null;
|
|
17361
|
-
if (type === "object") return
|
|
17800
|
+
if (type === "object") return isPlainObject2(value);
|
|
17362
17801
|
return typeof value === type;
|
|
17363
17802
|
}
|
|
17364
17803
|
function validateInput(operation, input) {
|
|
@@ -17367,16 +17806,19 @@ function validateInput(operation, input) {
|
|
|
17367
17806
|
const missing = operation.inputSchema.required.filter(
|
|
17368
17807
|
(key) => input[key] === void 0 || input[key] === null || input[key] === ""
|
|
17369
17808
|
);
|
|
17370
|
-
const
|
|
17809
|
+
const valueErrors = Object.entries(input).flatMap(([key, value]) => {
|
|
17371
17810
|
const property = operation.inputSchema.properties[key];
|
|
17372
17811
|
if (!property) return [];
|
|
17373
17812
|
const types = Array.isArray(property.type) ? property.type : [property.type];
|
|
17374
|
-
|
|
17813
|
+
if (!types.some((type) => typeMatches2(value, type))) {
|
|
17814
|
+
return [`Invalid input type for ${key}: expected ${types.join(" or ")}.`];
|
|
17815
|
+
}
|
|
17816
|
+
return key === "dataJson" ? validateOperationDataJson(operation.id, value) : [];
|
|
17375
17817
|
});
|
|
17376
17818
|
return [
|
|
17377
17819
|
...unknown.map((key) => `Unknown input property: ${key}`),
|
|
17378
17820
|
...missing.map((key) => `Missing required input property: ${key}`),
|
|
17379
|
-
...
|
|
17821
|
+
...valueErrors
|
|
17380
17822
|
];
|
|
17381
17823
|
}
|
|
17382
17824
|
function optionValue(value) {
|