@spira-lab/cli 0.0.5 → 0.0.7
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/README.md +27 -22
- package/dist/index.cjs +724 -142
- package/package.json +2 -25
package/dist/index.cjs
CHANGED
|
@@ -18048,6 +18048,7 @@ var cliResultTypeSchema = external_exports.enum([
|
|
|
18048
18048
|
"aiJobAction",
|
|
18049
18049
|
"aiModelList",
|
|
18050
18050
|
"aiModelDetail",
|
|
18051
|
+
"aiModelProviderList",
|
|
18051
18052
|
"workflowList",
|
|
18052
18053
|
"workflowNodeCatalog",
|
|
18053
18054
|
"workflowDetail",
|
|
@@ -18083,16 +18084,13 @@ var cliResultSchema = external_exports.object({
|
|
|
18083
18084
|
// src/ai/model-docs.ts
|
|
18084
18085
|
var cliAiModelDocs = [
|
|
18085
18086
|
{
|
|
18086
|
-
"id": "
|
|
18087
|
+
"id": "ai-influencer-image",
|
|
18087
18088
|
"name": "AI Influencer",
|
|
18088
18089
|
"mediaType": "image",
|
|
18089
18090
|
"description": "AI Influencer image generation model.",
|
|
18090
18091
|
"capabilities": [
|
|
18091
18092
|
"text-to-image"
|
|
18092
18093
|
],
|
|
18093
|
-
"providers": [
|
|
18094
|
-
"image-higgsfield"
|
|
18095
|
-
],
|
|
18096
18094
|
"variants": [
|
|
18097
18095
|
{
|
|
18098
18096
|
"key": "default",
|
|
@@ -18155,9 +18153,6 @@ var cliAiModelDocs = [
|
|
|
18155
18153
|
"text-to-image",
|
|
18156
18154
|
"image-to-image"
|
|
18157
18155
|
],
|
|
18158
|
-
"providers": [
|
|
18159
|
-
"socheap-media"
|
|
18160
|
-
],
|
|
18161
18156
|
"variants": [
|
|
18162
18157
|
{
|
|
18163
18158
|
"key": "1k",
|
|
@@ -18248,9 +18243,6 @@ var cliAiModelDocs = [
|
|
|
18248
18243
|
"text-to-image",
|
|
18249
18244
|
"image-to-image"
|
|
18250
18245
|
],
|
|
18251
|
-
"providers": [
|
|
18252
|
-
"socheap-media"
|
|
18253
|
-
],
|
|
18254
18246
|
"variants": [
|
|
18255
18247
|
{
|
|
18256
18248
|
"key": "standard",
|
|
@@ -18331,9 +18323,6 @@ var cliAiModelDocs = [
|
|
|
18331
18323
|
"text-to-image",
|
|
18332
18324
|
"image-to-image"
|
|
18333
18325
|
],
|
|
18334
|
-
"providers": [
|
|
18335
|
-
"socheap-media"
|
|
18336
|
-
],
|
|
18337
18326
|
"variants": [
|
|
18338
18327
|
{
|
|
18339
18328
|
"key": "1k",
|
|
@@ -18430,9 +18419,6 @@ var cliAiModelDocs = [
|
|
|
18430
18419
|
"text-to-image",
|
|
18431
18420
|
"image-to-image"
|
|
18432
18421
|
],
|
|
18433
|
-
"providers": [
|
|
18434
|
-
"image-kie"
|
|
18435
|
-
],
|
|
18436
18422
|
"variants": [
|
|
18437
18423
|
{
|
|
18438
18424
|
"key": "default",
|
|
@@ -18505,9 +18491,6 @@ var cliAiModelDocs = [
|
|
|
18505
18491
|
"text-to-image",
|
|
18506
18492
|
"image-to-image"
|
|
18507
18493
|
],
|
|
18508
|
-
"providers": [
|
|
18509
|
-
"socheap-media"
|
|
18510
|
-
],
|
|
18511
18494
|
"variants": [
|
|
18512
18495
|
{
|
|
18513
18496
|
"key": "1k",
|
|
@@ -18598,9 +18581,6 @@ var cliAiModelDocs = [
|
|
|
18598
18581
|
"text-to-video",
|
|
18599
18582
|
"image-to-video"
|
|
18600
18583
|
],
|
|
18601
|
-
"providers": [
|
|
18602
|
-
"socheap-media"
|
|
18603
|
-
],
|
|
18604
18584
|
"variants": [
|
|
18605
18585
|
{
|
|
18606
18586
|
"key": "4s-720p",
|
|
@@ -18860,9 +18840,6 @@ var cliAiModelDocs = [
|
|
|
18860
18840
|
"text-to-video",
|
|
18861
18841
|
"image-to-video"
|
|
18862
18842
|
],
|
|
18863
|
-
"providers": [
|
|
18864
|
-
"socheap-media"
|
|
18865
|
-
],
|
|
18866
18843
|
"variants": [
|
|
18867
18844
|
{
|
|
18868
18845
|
"key": "480p",
|
|
@@ -18974,9 +18951,6 @@ var cliAiModelDocs = [
|
|
|
18974
18951
|
"text-to-video",
|
|
18975
18952
|
"image-to-video"
|
|
18976
18953
|
],
|
|
18977
|
-
"providers": [
|
|
18978
|
-
"hailuo-comfly"
|
|
18979
|
-
],
|
|
18980
18954
|
"variants": [
|
|
18981
18955
|
{
|
|
18982
18956
|
"key": "default",
|
|
@@ -19030,8 +19004,8 @@ var cliAiModelDocs = [
|
|
|
19030
19004
|
}
|
|
19031
19005
|
],
|
|
19032
19006
|
"notes": [
|
|
19033
|
-
"referenceVideo and generationType are not supported
|
|
19034
|
-
"duration=10 with resolution=1080P is
|
|
19007
|
+
"referenceVideo and generationType are not supported for this model.",
|
|
19008
|
+
"duration=10 with resolution=1080P is not supported."
|
|
19035
19009
|
]
|
|
19036
19010
|
},
|
|
19037
19011
|
{
|
|
@@ -19043,9 +19017,6 @@ var cliAiModelDocs = [
|
|
|
19043
19017
|
"text-to-video",
|
|
19044
19018
|
"image-to-video"
|
|
19045
19019
|
],
|
|
19046
|
-
"providers": [
|
|
19047
|
-
"socheap-media"
|
|
19048
|
-
],
|
|
19049
19020
|
"variants": [
|
|
19050
19021
|
{
|
|
19051
19022
|
"key": "720p",
|
|
@@ -19169,9 +19140,6 @@ var cliAiModelDocs = [
|
|
|
19169
19140
|
"capabilities": [
|
|
19170
19141
|
"image-to-video"
|
|
19171
19142
|
],
|
|
19172
|
-
"providers": [
|
|
19173
|
-
"fal-ai"
|
|
19174
|
-
],
|
|
19175
19143
|
"variants": [
|
|
19176
19144
|
{
|
|
19177
19145
|
"key": "default",
|
|
@@ -19286,9 +19254,6 @@ var cliAiModelDocs = [
|
|
|
19286
19254
|
"text-to-video",
|
|
19287
19255
|
"image-to-video"
|
|
19288
19256
|
],
|
|
19289
|
-
"providers": [
|
|
19290
|
-
"socheap-media"
|
|
19291
|
-
],
|
|
19292
19257
|
"variants": [
|
|
19293
19258
|
{
|
|
19294
19259
|
"key": "standard-no-sound",
|
|
@@ -19431,7 +19396,7 @@ var cliAiModelDocs = [
|
|
|
19431
19396
|
],
|
|
19432
19397
|
"notes": [
|
|
19433
19398
|
"generation type is derived from referenceImage count: 0 text, 1 reference, 2 first/last frames.",
|
|
19434
|
-
"referenceVideo, negativePrompt, and elements are not supported
|
|
19399
|
+
"referenceVideo, negativePrompt, and elements are not supported for Kling 3.0.",
|
|
19435
19400
|
"Use mode=4K for 4K generation; do not pass resolution."
|
|
19436
19401
|
]
|
|
19437
19402
|
},
|
|
@@ -19443,9 +19408,6 @@ var cliAiModelDocs = [
|
|
|
19443
19408
|
"capabilities": [
|
|
19444
19409
|
"image-to-video"
|
|
19445
19410
|
],
|
|
19446
|
-
"providers": [
|
|
19447
|
-
"socheap-media"
|
|
19448
|
-
],
|
|
19449
19411
|
"variants": [
|
|
19450
19412
|
{
|
|
19451
19413
|
"key": "standard",
|
|
@@ -19566,9 +19528,6 @@ var cliAiModelDocs = [
|
|
|
19566
19528
|
"text-to-video",
|
|
19567
19529
|
"image-to-video"
|
|
19568
19530
|
],
|
|
19569
|
-
"providers": [
|
|
19570
|
-
"socheap-media"
|
|
19571
|
-
],
|
|
19572
19531
|
"variants": [
|
|
19573
19532
|
{
|
|
19574
19533
|
"key": "standard-480p-no-sound",
|
|
@@ -19730,9 +19689,6 @@ var cliAiModelDocs = [
|
|
|
19730
19689
|
"text-to-video",
|
|
19731
19690
|
"image-to-video"
|
|
19732
19691
|
],
|
|
19733
|
-
"providers": [
|
|
19734
|
-
"socheap-media"
|
|
19735
|
-
],
|
|
19736
19692
|
"variants": [
|
|
19737
19693
|
{
|
|
19738
19694
|
"key": "standard-480p",
|
|
@@ -20016,9 +19972,6 @@ var cliAiModelDocs = [
|
|
|
20016
19972
|
"text-to-video",
|
|
20017
19973
|
"image-to-video"
|
|
20018
19974
|
],
|
|
20019
|
-
"providers": [
|
|
20020
|
-
"socheap-media"
|
|
20021
|
-
],
|
|
20022
19975
|
"variants": [
|
|
20023
19976
|
{
|
|
20024
19977
|
"key": "fast-720p",
|
|
@@ -20133,8 +20086,7 @@ var cliAiModelDocs = [
|
|
|
20133
20086
|
"description": "Output aspect ratio.",
|
|
20134
20087
|
"values": [
|
|
20135
20088
|
"16:9",
|
|
20136
|
-
"9:16"
|
|
20137
|
-
"1:1"
|
|
20089
|
+
"9:16"
|
|
20138
20090
|
],
|
|
20139
20091
|
"defaultValue": "16:9"
|
|
20140
20092
|
},
|
|
@@ -20170,14 +20122,9 @@ var cliAiModelDocs = [
|
|
|
20170
20122
|
"description": "Whether the generated video should be extendable when supported."
|
|
20171
20123
|
},
|
|
20172
20124
|
{
|
|
20173
|
-
"name": "
|
|
20125
|
+
"name": "extendFromJobId",
|
|
20174
20126
|
"type": "string",
|
|
20175
|
-
"description": "
|
|
20176
|
-
},
|
|
20177
|
-
{
|
|
20178
|
-
"name": "extendProviderId",
|
|
20179
|
-
"type": "string",
|
|
20180
|
-
"description": "Original provider id for extension lineage. Must be socheap-media for this CLI path."
|
|
20127
|
+
"description": "Spira job ID of an extendable Veo generation owned by the current user."
|
|
20181
20128
|
}
|
|
20182
20129
|
],
|
|
20183
20130
|
"examples": [
|
|
@@ -20193,11 +20140,261 @@ var cliAiModelDocs = [
|
|
|
20193
20140
|
}
|
|
20194
20141
|
],
|
|
20195
20142
|
"notes": [
|
|
20143
|
+
"Veo 3.1 supports 16:9 and 9:16 output aspect ratios.",
|
|
20196
20144
|
"referenceVideo and referenceAudio are not supported.",
|
|
20197
20145
|
"image_to_video is not a supported generationType; use reference_to_video with one or more referenceImage URLs.",
|
|
20198
20146
|
"first_last_frames_to_video requires exactly 2 referenceImage URLs.",
|
|
20199
|
-
"
|
|
20147
|
+
"extendFromJobId requires resolution=720p."
|
|
20200
20148
|
]
|
|
20149
|
+
},
|
|
20150
|
+
{
|
|
20151
|
+
id: "suno-music",
|
|
20152
|
+
name: "Suno Music",
|
|
20153
|
+
mediaType: "audio",
|
|
20154
|
+
description: "Suno music generation with simple prompt and custom song modes.",
|
|
20155
|
+
capabilities: ["text-to-audio"],
|
|
20156
|
+
variants: [
|
|
20157
|
+
{
|
|
20158
|
+
key: "v5_5",
|
|
20159
|
+
display: "v5_5",
|
|
20160
|
+
conditions: {},
|
|
20161
|
+
billingUnit: "per_generation",
|
|
20162
|
+
creditsPerUnit: 6.6
|
|
20163
|
+
}
|
|
20164
|
+
],
|
|
20165
|
+
fields: [
|
|
20166
|
+
{
|
|
20167
|
+
name: "prompt",
|
|
20168
|
+
type: "string",
|
|
20169
|
+
description: "Song description in simple mode, or lyrics in custom vocal mode."
|
|
20170
|
+
},
|
|
20171
|
+
{
|
|
20172
|
+
name: "mode",
|
|
20173
|
+
type: "string",
|
|
20174
|
+
description: "Suno model version.",
|
|
20175
|
+
values: ["v5_5"],
|
|
20176
|
+
defaultValue: "v5_5"
|
|
20177
|
+
},
|
|
20178
|
+
{
|
|
20179
|
+
name: "customMode",
|
|
20180
|
+
type: "boolean",
|
|
20181
|
+
description: "Enable custom lyrics, style, and title inputs.",
|
|
20182
|
+
defaultValue: false
|
|
20183
|
+
},
|
|
20184
|
+
{
|
|
20185
|
+
name: "instrumental",
|
|
20186
|
+
type: "boolean",
|
|
20187
|
+
description: "Generate an instrumental track. Only used in custom mode.",
|
|
20188
|
+
defaultValue: false
|
|
20189
|
+
},
|
|
20190
|
+
{
|
|
20191
|
+
name: "style",
|
|
20192
|
+
type: "string",
|
|
20193
|
+
description: "Required music style in custom mode."
|
|
20194
|
+
},
|
|
20195
|
+
{
|
|
20196
|
+
name: "title",
|
|
20197
|
+
type: "string",
|
|
20198
|
+
description: "Required song title in custom mode."
|
|
20199
|
+
}
|
|
20200
|
+
],
|
|
20201
|
+
examples: [
|
|
20202
|
+
{
|
|
20203
|
+
label: "Generate music",
|
|
20204
|
+
inputs: {
|
|
20205
|
+
prompt: "A warm upbeat electronic instrumental for a product launch",
|
|
20206
|
+
mode: "v5_5"
|
|
20207
|
+
}
|
|
20208
|
+
}
|
|
20209
|
+
],
|
|
20210
|
+
notes: [
|
|
20211
|
+
"Simple mode requires prompt. Custom mode requires style and title; vocal custom mode also requires prompt as lyrics."
|
|
20212
|
+
]
|
|
20213
|
+
},
|
|
20214
|
+
{
|
|
20215
|
+
id: "elevenlabs-music-generation",
|
|
20216
|
+
name: "Eleven Music V1",
|
|
20217
|
+
mediaType: "audio",
|
|
20218
|
+
description: "ElevenLabs prompt-to-music generation.",
|
|
20219
|
+
capabilities: ["text-to-audio"],
|
|
20220
|
+
variants: [
|
|
20221
|
+
{
|
|
20222
|
+
key: "default",
|
|
20223
|
+
display: "Per second",
|
|
20224
|
+
conditions: {},
|
|
20225
|
+
billingUnit: "per_second",
|
|
20226
|
+
creditsPerUnit: 0.25
|
|
20227
|
+
}
|
|
20228
|
+
],
|
|
20229
|
+
fields: [
|
|
20230
|
+
{
|
|
20231
|
+
name: "prompt",
|
|
20232
|
+
type: "string",
|
|
20233
|
+
description: "Description of the music to generate.",
|
|
20234
|
+
required: true
|
|
20235
|
+
},
|
|
20236
|
+
{
|
|
20237
|
+
name: "duration",
|
|
20238
|
+
type: "string",
|
|
20239
|
+
description: "Whole number of seconds from 1 to 300.",
|
|
20240
|
+
defaultValue: "10"
|
|
20241
|
+
}
|
|
20242
|
+
],
|
|
20243
|
+
examples: [
|
|
20244
|
+
{
|
|
20245
|
+
label: "Generate music",
|
|
20246
|
+
inputs: {
|
|
20247
|
+
prompt: "A calm ambient piano cue with a gentle ending",
|
|
20248
|
+
duration: "10"
|
|
20249
|
+
}
|
|
20250
|
+
}
|
|
20251
|
+
]
|
|
20252
|
+
},
|
|
20253
|
+
{
|
|
20254
|
+
id: "elevenlabs-sound-effects",
|
|
20255
|
+
name: "Eleven Text To Sound V2",
|
|
20256
|
+
mediaType: "audio",
|
|
20257
|
+
description: "ElevenLabs sound-effect generation from an English prompt.",
|
|
20258
|
+
capabilities: ["text-to-audio"],
|
|
20259
|
+
variants: [
|
|
20260
|
+
{
|
|
20261
|
+
key: "default",
|
|
20262
|
+
display: "Per generation",
|
|
20263
|
+
conditions: {},
|
|
20264
|
+
billingUnit: "per_generation",
|
|
20265
|
+
creditsPerUnit: 12
|
|
20266
|
+
}
|
|
20267
|
+
],
|
|
20268
|
+
fields: [
|
|
20269
|
+
{
|
|
20270
|
+
name: "prompt",
|
|
20271
|
+
type: "string",
|
|
20272
|
+
description: "English description of the sound effect.",
|
|
20273
|
+
required: true
|
|
20274
|
+
},
|
|
20275
|
+
{
|
|
20276
|
+
name: "duration",
|
|
20277
|
+
type: "string",
|
|
20278
|
+
description: "Duration in seconds from 0.5 to 30.",
|
|
20279
|
+
defaultValue: "5"
|
|
20280
|
+
}
|
|
20281
|
+
],
|
|
20282
|
+
examples: [
|
|
20283
|
+
{
|
|
20284
|
+
label: "Generate a sound effect",
|
|
20285
|
+
inputs: {
|
|
20286
|
+
prompt: "A soft camera shutter in a quiet studio",
|
|
20287
|
+
duration: "2"
|
|
20288
|
+
}
|
|
20289
|
+
}
|
|
20290
|
+
]
|
|
20291
|
+
},
|
|
20292
|
+
{
|
|
20293
|
+
id: "elevenlabs-text-to-speech",
|
|
20294
|
+
name: "ElevenLabs Text to Speech",
|
|
20295
|
+
mediaType: "audio",
|
|
20296
|
+
description: "ElevenLabs text-to-speech using an existing voice ID.",
|
|
20297
|
+
capabilities: ["text-to-speech"],
|
|
20298
|
+
variants: [
|
|
20299
|
+
{
|
|
20300
|
+
key: "multilingual-v2-v3",
|
|
20301
|
+
display: "Per character",
|
|
20302
|
+
conditions: {},
|
|
20303
|
+
billingUnit: "per_character",
|
|
20304
|
+
creditsPerUnit: 0.01
|
|
20305
|
+
}
|
|
20306
|
+
],
|
|
20307
|
+
fields: [
|
|
20308
|
+
{
|
|
20309
|
+
name: "text",
|
|
20310
|
+
type: "string",
|
|
20311
|
+
description: "Text to speak.",
|
|
20312
|
+
required: true
|
|
20313
|
+
},
|
|
20314
|
+
{
|
|
20315
|
+
name: "voiceId",
|
|
20316
|
+
type: "string",
|
|
20317
|
+
description: "Existing ElevenLabs voice ID.",
|
|
20318
|
+
required: true
|
|
20319
|
+
},
|
|
20320
|
+
{
|
|
20321
|
+
name: "providerModelId",
|
|
20322
|
+
type: "string",
|
|
20323
|
+
description: "ElevenLabs speech model.",
|
|
20324
|
+
values: ["eleven_multilingual_v2", "eleven_v3"],
|
|
20325
|
+
defaultValue: "eleven_multilingual_v2"
|
|
20326
|
+
}
|
|
20327
|
+
],
|
|
20328
|
+
examples: [
|
|
20329
|
+
{
|
|
20330
|
+
label: "Generate speech",
|
|
20331
|
+
inputs: {
|
|
20332
|
+
text: "Welcome to Spira.",
|
|
20333
|
+
voiceId: "<voice-id>",
|
|
20334
|
+
providerModelId: "eleven_multilingual_v2"
|
|
20335
|
+
}
|
|
20336
|
+
}
|
|
20337
|
+
]
|
|
20338
|
+
},
|
|
20339
|
+
{
|
|
20340
|
+
id: "elevenlabs-voice-clone-tts",
|
|
20341
|
+
name: "ElevenLabs Voice TTS",
|
|
20342
|
+
mediaType: "audio",
|
|
20343
|
+
description: "Text-to-speech using either an existing voice ID or one reference audio URL.",
|
|
20344
|
+
capabilities: ["text-to-speech", "audio-to-speech"],
|
|
20345
|
+
variants: [
|
|
20346
|
+
{
|
|
20347
|
+
key: "voice-clone-tts",
|
|
20348
|
+
display: "Per character",
|
|
20349
|
+
conditions: {},
|
|
20350
|
+
billingUnit: "per_character",
|
|
20351
|
+
creditsPerUnit: 0.01
|
|
20352
|
+
}
|
|
20353
|
+
],
|
|
20354
|
+
fields: [
|
|
20355
|
+
{
|
|
20356
|
+
name: "text",
|
|
20357
|
+
type: "string",
|
|
20358
|
+
description: "Text to speak.",
|
|
20359
|
+
required: true
|
|
20360
|
+
},
|
|
20361
|
+
{
|
|
20362
|
+
name: "voiceId",
|
|
20363
|
+
type: "string",
|
|
20364
|
+
description: "Existing ElevenLabs voice ID. Do not combine with referenceAudio."
|
|
20365
|
+
},
|
|
20366
|
+
{
|
|
20367
|
+
name: "referenceAudio",
|
|
20368
|
+
type: "string[]",
|
|
20369
|
+
description: "Exactly one audio URL when cloning a voice. Do not combine with voiceId."
|
|
20370
|
+
},
|
|
20371
|
+
{
|
|
20372
|
+
name: "providerModelId",
|
|
20373
|
+
type: "string",
|
|
20374
|
+
description: "ElevenLabs speech model.",
|
|
20375
|
+
values: ["eleven_multilingual_v2", "eleven_v3"],
|
|
20376
|
+
defaultValue: "eleven_multilingual_v2"
|
|
20377
|
+
},
|
|
20378
|
+
{
|
|
20379
|
+
name: "qualityMode",
|
|
20380
|
+
type: "string",
|
|
20381
|
+
description: "Voice delivery mode.",
|
|
20382
|
+
values: ["stable", "expressive"],
|
|
20383
|
+
defaultValue: "stable"
|
|
20384
|
+
}
|
|
20385
|
+
],
|
|
20386
|
+
examples: [
|
|
20387
|
+
{
|
|
20388
|
+
label: "Generate speech from a reference voice",
|
|
20389
|
+
inputs: {
|
|
20390
|
+
text: "Welcome to Spira.",
|
|
20391
|
+
referenceAudio: ["https://example.com/reference.mp3"],
|
|
20392
|
+
providerModelId: "eleven_multilingual_v2",
|
|
20393
|
+
qualityMode: "stable"
|
|
20394
|
+
}
|
|
20395
|
+
}
|
|
20396
|
+
],
|
|
20397
|
+
notes: ["Provide either voiceId or exactly one referenceAudio URL, never both."]
|
|
20201
20398
|
}
|
|
20202
20399
|
];
|
|
20203
20400
|
function listCliAiModelDocs(mediaType) {
|
|
@@ -20207,6 +20404,120 @@ function getCliAiModelDoc(modelId) {
|
|
|
20207
20404
|
return cliAiModelDocs.find((model) => model.id === modelId);
|
|
20208
20405
|
}
|
|
20209
20406
|
|
|
20407
|
+
// src/ai/wait.ts
|
|
20408
|
+
var DEFAULT_WAIT_COMMAND = "spira ai jobs create";
|
|
20409
|
+
function wait(durationMs) {
|
|
20410
|
+
return new Promise((resolve) => setTimeout(resolve, durationMs));
|
|
20411
|
+
}
|
|
20412
|
+
function jobStatus(result) {
|
|
20413
|
+
if (!result.data || typeof result.data !== "object") return void 0;
|
|
20414
|
+
const status = result.data.status;
|
|
20415
|
+
return typeof status === "string" ? status : void 0;
|
|
20416
|
+
}
|
|
20417
|
+
function providerError(result) {
|
|
20418
|
+
if (!result.data || typeof result.data !== "object") return void 0;
|
|
20419
|
+
const latestExecution = result.data.latestExecution;
|
|
20420
|
+
if (!latestExecution || typeof latestExecution !== "object") return void 0;
|
|
20421
|
+
const error51 = latestExecution.error;
|
|
20422
|
+
if (typeof error51 === "string") return error51;
|
|
20423
|
+
if (error51 && typeof error51 === "object" && typeof error51.message === "string") {
|
|
20424
|
+
return error51.message;
|
|
20425
|
+
}
|
|
20426
|
+
return void 0;
|
|
20427
|
+
}
|
|
20428
|
+
function completedResult(result, command) {
|
|
20429
|
+
return cliResultSchema.parse({
|
|
20430
|
+
...result,
|
|
20431
|
+
resultType: "aiJobStatus",
|
|
20432
|
+
command,
|
|
20433
|
+
nextActions: []
|
|
20434
|
+
});
|
|
20435
|
+
}
|
|
20436
|
+
function pollingError(result, command) {
|
|
20437
|
+
return cliResultSchema.parse({
|
|
20438
|
+
...result,
|
|
20439
|
+
command
|
|
20440
|
+
});
|
|
20441
|
+
}
|
|
20442
|
+
function terminalError(result, jobId, status, command) {
|
|
20443
|
+
const message = providerError(result) ?? `AI job ${jobId} ended with status ${status}.`;
|
|
20444
|
+
return cliResultSchema.parse({
|
|
20445
|
+
...result,
|
|
20446
|
+
status: "error",
|
|
20447
|
+
resultType: "aiJobStatus",
|
|
20448
|
+
command,
|
|
20449
|
+
error: {
|
|
20450
|
+
code: status === "FAILED" ? "PROVIDER_FAILED" : "ASYNC_STATE",
|
|
20451
|
+
message,
|
|
20452
|
+
resource: { type: "aiJob", id: jobId },
|
|
20453
|
+
retryable: false,
|
|
20454
|
+
nextActions: [{ label: "Show job status", command: `spira ai jobs status ${jobId}` }]
|
|
20455
|
+
}
|
|
20456
|
+
});
|
|
20457
|
+
}
|
|
20458
|
+
function timeoutResult(jobId, timeoutMs, command, lastResult) {
|
|
20459
|
+
return cliResultSchema.parse({
|
|
20460
|
+
object: "cli.result",
|
|
20461
|
+
status: "error",
|
|
20462
|
+
resultType: "aiJobStatus",
|
|
20463
|
+
command,
|
|
20464
|
+
data: lastResult?.data,
|
|
20465
|
+
ids: { ...lastResult?.ids, jobId },
|
|
20466
|
+
error: {
|
|
20467
|
+
code: "TIMEOUT",
|
|
20468
|
+
message: `AI job ${jobId} did not finish within ${timeoutMs}ms.`,
|
|
20469
|
+
resource: { type: "aiJob", id: jobId },
|
|
20470
|
+
retryable: true,
|
|
20471
|
+
nextActions: [
|
|
20472
|
+
{ label: "Keep waiting", command: `spira ai jobs wait ${jobId}` },
|
|
20473
|
+
{ label: "Show job status", command: `spira ai jobs status ${jobId}` }
|
|
20474
|
+
]
|
|
20475
|
+
}
|
|
20476
|
+
});
|
|
20477
|
+
}
|
|
20478
|
+
function contractError(result, jobId, command) {
|
|
20479
|
+
return cliResultSchema.parse({
|
|
20480
|
+
...result,
|
|
20481
|
+
status: "error",
|
|
20482
|
+
resultType: "aiJobStatus",
|
|
20483
|
+
command,
|
|
20484
|
+
error: {
|
|
20485
|
+
code: "CONTRACT_MISMATCH",
|
|
20486
|
+
message: `AI job ${jobId} status response did not contain a recognized status.`,
|
|
20487
|
+
resource: { type: "aiJob", id: jobId },
|
|
20488
|
+
retryable: false,
|
|
20489
|
+
nextActions: [{ label: "Show job status", command: `spira ai jobs status ${jobId}` }]
|
|
20490
|
+
}
|
|
20491
|
+
});
|
|
20492
|
+
}
|
|
20493
|
+
async function waitForAiJob(input) {
|
|
20494
|
+
const now = input.now ?? Date.now;
|
|
20495
|
+
const sleep = input.sleep ?? wait;
|
|
20496
|
+
const command = input.command ?? DEFAULT_WAIT_COMMAND;
|
|
20497
|
+
const deadline = now() + input.timeoutMs;
|
|
20498
|
+
let lastResult;
|
|
20499
|
+
let lastStatus;
|
|
20500
|
+
while (true) {
|
|
20501
|
+
const result = await input.poll();
|
|
20502
|
+
lastResult = result;
|
|
20503
|
+
if (result.status === "error") {
|
|
20504
|
+
if (!result.error?.retryable) return pollingError(result, command);
|
|
20505
|
+
} else {
|
|
20506
|
+
const status = jobStatus(result);
|
|
20507
|
+
if (status && status !== lastStatus) {
|
|
20508
|
+
input.onStatus?.(status);
|
|
20509
|
+
lastStatus = status;
|
|
20510
|
+
}
|
|
20511
|
+
if (status === "COMPLETED") return completedResult(result, command);
|
|
20512
|
+
if (status === "FAILED" || status === "CANCELED") return terminalError(result, input.jobId, status, command);
|
|
20513
|
+
if (status !== "QUEUED" && status !== "RUNNING") return contractError(result, input.jobId, command);
|
|
20514
|
+
}
|
|
20515
|
+
const remainingMs = deadline - now();
|
|
20516
|
+
if (remainingMs <= 0) return timeoutResult(input.jobId, input.timeoutMs, command, lastResult);
|
|
20517
|
+
await sleep(Math.min(input.intervalMs, remainingMs));
|
|
20518
|
+
}
|
|
20519
|
+
}
|
|
20520
|
+
|
|
20210
20521
|
// src/commands/definitions.ts
|
|
20211
20522
|
var commonListOptions = [
|
|
20212
20523
|
{
|
|
@@ -20390,7 +20701,10 @@ var commandDefinitions = [
|
|
|
20390
20701
|
},
|
|
20391
20702
|
resultType: "socialSubmissionList",
|
|
20392
20703
|
examples: ["spira social submissions list --platform tiktok --status draft --limit 10"],
|
|
20393
|
-
relatedCommands: [
|
|
20704
|
+
relatedCommands: [
|
|
20705
|
+
"spira social submissions get <submissionId>",
|
|
20706
|
+
"spira social submissions publish <submissionId> --confirm"
|
|
20707
|
+
]
|
|
20394
20708
|
},
|
|
20395
20709
|
{
|
|
20396
20710
|
path: ["social", "submissions", "get"],
|
|
@@ -20436,7 +20750,12 @@ var commandDefinitions = [
|
|
|
20436
20750
|
defaultValue: "oauth_account"
|
|
20437
20751
|
},
|
|
20438
20752
|
{ name: "title", flag: "--title <title>", description: "Draft title.", type: "string" },
|
|
20439
|
-
{
|
|
20753
|
+
{
|
|
20754
|
+
name: "description",
|
|
20755
|
+
flag: "--description <description>",
|
|
20756
|
+
description: "Draft description/text.",
|
|
20757
|
+
type: "string"
|
|
20758
|
+
},
|
|
20440
20759
|
{ name: "mediaUrls", flag: "--media-url <url>", description: "Media URL. Repeatable.", type: "stringArray" },
|
|
20441
20760
|
{ name: "agentId", flag: "--agent-id <agentId>", description: "Associated agent ID.", type: "string" },
|
|
20442
20761
|
{
|
|
@@ -20463,9 +20782,7 @@ var commandDefinitions = [
|
|
|
20463
20782
|
]
|
|
20464
20783
|
},
|
|
20465
20784
|
resultType: "socialSubmissionAction",
|
|
20466
|
-
examples: [
|
|
20467
|
-
'spira social submissions create --platform twitter --content-kind text --description "Launch note"'
|
|
20468
|
-
],
|
|
20785
|
+
examples: ['spira social submissions create --platform twitter --content-kind text --description "Launch note"'],
|
|
20469
20786
|
relatedCommands: [
|
|
20470
20787
|
"spira social submissions get <submissionId>",
|
|
20471
20788
|
"spira social submissions publish <submissionId> --confirm"
|
|
@@ -20476,9 +20793,20 @@ var commandDefinitions = [
|
|
|
20476
20793
|
purpose: "Publish a social submission draft.",
|
|
20477
20794
|
arguments: [{ name: "submissionId", description: "Submission ID.", required: true }],
|
|
20478
20795
|
options: [
|
|
20479
|
-
{
|
|
20796
|
+
{
|
|
20797
|
+
name: "confirm",
|
|
20798
|
+
flag: "--confirm",
|
|
20799
|
+
description: "Required explicit publish confirmation.",
|
|
20800
|
+
type: "boolean",
|
|
20801
|
+
required: true
|
|
20802
|
+
},
|
|
20480
20803
|
{ name: "title", flag: "--title <title>", description: "Platform title override.", type: "string" },
|
|
20481
|
-
{
|
|
20804
|
+
{
|
|
20805
|
+
name: "description",
|
|
20806
|
+
flag: "--description <description>",
|
|
20807
|
+
description: "Platform description override.",
|
|
20808
|
+
type: "string"
|
|
20809
|
+
},
|
|
20482
20810
|
{ name: "text", flag: "--text <text>", description: "Text override for X or LinkedIn.", type: "string" },
|
|
20483
20811
|
{ name: "mediaUrls", flag: "--media-url <url>", description: "Media URL. Repeatable.", type: "stringArray" },
|
|
20484
20812
|
{ name: "privacyLevel", flag: "--privacy-level <value>", description: "TikTok privacy level.", type: "string" },
|
|
@@ -20515,22 +20843,48 @@ var commandDefinitions = [
|
|
|
20515
20843
|
},
|
|
20516
20844
|
resultType: "aiJobStatus",
|
|
20517
20845
|
examples: ["spira ai jobs status job_123"],
|
|
20518
|
-
relatedCommands: []
|
|
20846
|
+
relatedCommands: ["spira ai jobs wait <jobId>"]
|
|
20847
|
+
},
|
|
20848
|
+
{
|
|
20849
|
+
path: ["ai", "jobs", "wait"],
|
|
20850
|
+
purpose: "Block until an AI job finishes, then print the final result.",
|
|
20851
|
+
arguments: [{ name: "jobId", description: "AI job ID.", required: true }],
|
|
20852
|
+
options: [
|
|
20853
|
+
{
|
|
20854
|
+
name: "timeout",
|
|
20855
|
+
flag: "--timeout <duration>",
|
|
20856
|
+
description: "Maximum wait duration.",
|
|
20857
|
+
type: "duration",
|
|
20858
|
+
defaultValue: 6e5,
|
|
20859
|
+
minimum: 1e3
|
|
20860
|
+
},
|
|
20861
|
+
{
|
|
20862
|
+
name: "interval",
|
|
20863
|
+
flag: "--interval <duration>",
|
|
20864
|
+
description: "Polling interval while waiting.",
|
|
20865
|
+
type: "duration",
|
|
20866
|
+
defaultValue: 3e3,
|
|
20867
|
+
minimum: 1e3
|
|
20868
|
+
}
|
|
20869
|
+
],
|
|
20870
|
+
resultType: "aiJobStatus",
|
|
20871
|
+
examples: ["spira ai jobs wait job_123", "spira ai jobs wait job_123 --timeout 20m --interval 5s"],
|
|
20872
|
+
relatedCommands: ["spira ai jobs status <jobId>", "spira ai jobs create"]
|
|
20519
20873
|
},
|
|
20520
20874
|
{
|
|
20521
20875
|
path: ["ai", "models", "list"],
|
|
20522
|
-
purpose: "List AI image and
|
|
20876
|
+
purpose: "List AI image, video, and audio models available from the CLI.",
|
|
20523
20877
|
options: [
|
|
20524
20878
|
{
|
|
20525
20879
|
name: "mediaType",
|
|
20526
20880
|
flag: "--media-type <type>",
|
|
20527
20881
|
description: "Filter by model media type.",
|
|
20528
20882
|
type: "string",
|
|
20529
|
-
enumValues: ["image", "video"]
|
|
20883
|
+
enumValues: ["image", "video", "audio"]
|
|
20530
20884
|
}
|
|
20531
20885
|
],
|
|
20532
20886
|
resultType: "aiModelList",
|
|
20533
|
-
examples: ["spira ai models list", "spira ai models list --media-type
|
|
20887
|
+
examples: ["spira ai models list", "spira ai models list --media-type audio"],
|
|
20534
20888
|
relatedCommands: ["spira ai models get <modelId>", "spira ai jobs create"]
|
|
20535
20889
|
},
|
|
20536
20890
|
{
|
|
@@ -20541,13 +20895,61 @@ var commandDefinitions = [
|
|
|
20541
20895
|
examples: ["spira ai models get nano-banana-2", "spira ai models get seedance-2.0"],
|
|
20542
20896
|
relatedCommands: ["spira ai jobs create"]
|
|
20543
20897
|
},
|
|
20898
|
+
{
|
|
20899
|
+
path: ["ai", "models", "providers"],
|
|
20900
|
+
purpose: "List provider routing IDs for AI models; requires admin.access.",
|
|
20901
|
+
permissions: ["admin.access"],
|
|
20902
|
+
arguments: [{ name: "modelId", description: "Optional AI model ID.", required: false }],
|
|
20903
|
+
http: {
|
|
20904
|
+
method: "GET",
|
|
20905
|
+
path: "/api/cli/v1/ai/models/providers",
|
|
20906
|
+
authRequired: true,
|
|
20907
|
+
query: [{ name: "modelId", source: "argument", from: "modelId" }]
|
|
20908
|
+
},
|
|
20909
|
+
resultType: "aiModelProviderList",
|
|
20910
|
+
examples: ["spira ai models providers", "spira ai models providers veo3.1 --json"],
|
|
20911
|
+
relatedCommands: ["spira ai models list", "spira ai jobs create"]
|
|
20912
|
+
},
|
|
20544
20913
|
{
|
|
20545
20914
|
path: ["ai", "jobs", "create"],
|
|
20546
|
-
purpose: "Create an AI image or
|
|
20915
|
+
purpose: "Create an AI image, video, or audio generation job.",
|
|
20547
20916
|
options: [
|
|
20548
20917
|
{ name: "modelId", flag: "--model-id <modelId>", description: "AI model ID.", type: "string", required: true },
|
|
20549
|
-
{
|
|
20550
|
-
|
|
20918
|
+
{
|
|
20919
|
+
name: "providerId",
|
|
20920
|
+
flag: "--provider-id <providerId>",
|
|
20921
|
+
description: "Explicit provider routing override; requires admin.access.",
|
|
20922
|
+
type: "string"
|
|
20923
|
+
},
|
|
20924
|
+
{
|
|
20925
|
+
name: "inputsJson",
|
|
20926
|
+
flag: "--inputs-json <json>",
|
|
20927
|
+
description: "Model inputs JSON object.",
|
|
20928
|
+
type: "json",
|
|
20929
|
+
required: true
|
|
20930
|
+
},
|
|
20931
|
+
{
|
|
20932
|
+
name: "wait",
|
|
20933
|
+
flag: "--wait",
|
|
20934
|
+
description: "Wait for the job to finish and print the final result.",
|
|
20935
|
+
type: "boolean"
|
|
20936
|
+
},
|
|
20937
|
+
{
|
|
20938
|
+
name: "waitTimeout",
|
|
20939
|
+
flag: "--wait-timeout <duration>",
|
|
20940
|
+
description: "Maximum wait duration.",
|
|
20941
|
+
type: "duration",
|
|
20942
|
+
defaultValue: 6e5,
|
|
20943
|
+
minimum: 1e3
|
|
20944
|
+
},
|
|
20945
|
+
{
|
|
20946
|
+
name: "waitInterval",
|
|
20947
|
+
flag: "--wait-interval <duration>",
|
|
20948
|
+
description: "Polling interval while waiting.",
|
|
20949
|
+
type: "duration",
|
|
20950
|
+
defaultValue: 3e3,
|
|
20951
|
+
minimum: 1e3
|
|
20952
|
+
}
|
|
20551
20953
|
],
|
|
20552
20954
|
http: {
|
|
20553
20955
|
method: "POST",
|
|
@@ -20560,8 +20962,16 @@ var commandDefinitions = [
|
|
|
20560
20962
|
]
|
|
20561
20963
|
},
|
|
20562
20964
|
resultType: "aiJobAction",
|
|
20563
|
-
examples: [
|
|
20564
|
-
|
|
20965
|
+
examples: [
|
|
20966
|
+
`spira ai jobs create --model-id nano-banana-2 --inputs-json '{"prompt":"A product photo"}'`,
|
|
20967
|
+
`spira ai jobs create --model-id nano-banana-2 --inputs-json '{"prompt":"A product photo"}' --wait`
|
|
20968
|
+
],
|
|
20969
|
+
relatedCommands: [
|
|
20970
|
+
"spira ai jobs wait <jobId>",
|
|
20971
|
+
"spira ai jobs status <jobId>",
|
|
20972
|
+
"spira ai models get <modelId>",
|
|
20973
|
+
"spira credits balance"
|
|
20974
|
+
]
|
|
20565
20975
|
},
|
|
20566
20976
|
{
|
|
20567
20977
|
path: ["workflows", "list"],
|
|
@@ -20617,10 +21027,7 @@ var commandDefinitions = [
|
|
|
20617
21027
|
query: [{ name: "surface", source: "option", from: "surface" }]
|
|
20618
21028
|
},
|
|
20619
21029
|
resultType: "workflowNodeCatalog",
|
|
20620
|
-
examples: [
|
|
20621
|
-
"spira workflows node-catalog --json",
|
|
20622
|
-
"spira workflows node-catalog --surface admin --json"
|
|
20623
|
-
],
|
|
21030
|
+
examples: ["spira workflows node-catalog --json", "spira workflows node-catalog --surface admin --json"],
|
|
20624
21031
|
relatedCommands: [
|
|
20625
21032
|
"spira workflows create --name <name>",
|
|
20626
21033
|
"spira workflows update <workflowId>",
|
|
@@ -20670,7 +21077,11 @@ var commandDefinitions = [
|
|
|
20670
21077
|
'spira workflows create --name "Product launch workflow"',
|
|
20671
21078
|
`spira workflows create --name "Product launch workflow" --workflow-definition-json '{"nodes":[],"edges":[]}'`
|
|
20672
21079
|
],
|
|
20673
|
-
relatedCommands: [
|
|
21080
|
+
relatedCommands: [
|
|
21081
|
+
"spira workflows get <workflowId>",
|
|
21082
|
+
"spira workflows update <workflowId>",
|
|
21083
|
+
"spira workflows runs start <workflowId>"
|
|
21084
|
+
]
|
|
20674
21085
|
},
|
|
20675
21086
|
{
|
|
20676
21087
|
path: ["workflows", "get"],
|
|
@@ -20808,7 +21219,12 @@ var commandDefinitions = [
|
|
|
20808
21219
|
purpose: "Start a workflow run and return its run ID.",
|
|
20809
21220
|
arguments: [{ name: "workflowId", description: "Workflow ID.", required: true }],
|
|
20810
21221
|
options: [
|
|
20811
|
-
{
|
|
21222
|
+
{
|
|
21223
|
+
name: "startOptionsJson",
|
|
21224
|
+
flag: "--start-options-json <json>",
|
|
21225
|
+
description: "Workflow start options JSON.",
|
|
21226
|
+
type: "json"
|
|
21227
|
+
},
|
|
20812
21228
|
{
|
|
20813
21229
|
name: "surface",
|
|
20814
21230
|
flag: "--surface <surface>",
|
|
@@ -20867,7 +21283,9 @@ var commandDefinitions = [
|
|
|
20867
21283
|
path: ["schedules", "executions"],
|
|
20868
21284
|
purpose: "List persisted schedule execution attempts.",
|
|
20869
21285
|
arguments: [{ name: "scheduleId", description: "Schedule ID.", required: true }],
|
|
20870
|
-
options: [
|
|
21286
|
+
options: [
|
|
21287
|
+
{ name: "limit", flag: "--limit <number>", description: "Maximum executions to return.", type: "number" }
|
|
21288
|
+
],
|
|
20871
21289
|
http: {
|
|
20872
21290
|
method: "GET",
|
|
20873
21291
|
path: "/api/schedules/:scheduleId/executions",
|
|
@@ -20883,11 +21301,28 @@ var commandDefinitions = [
|
|
|
20883
21301
|
path: ["schedules", "calendar"],
|
|
20884
21302
|
purpose: "List scheduled occurrences between two times.",
|
|
20885
21303
|
options: [
|
|
20886
|
-
{
|
|
20887
|
-
|
|
21304
|
+
{
|
|
21305
|
+
name: "from",
|
|
21306
|
+
flag: "--from <ms>",
|
|
21307
|
+
description: "Start timestamp in epoch milliseconds.",
|
|
21308
|
+
type: "number",
|
|
21309
|
+
required: true
|
|
21310
|
+
},
|
|
21311
|
+
{
|
|
21312
|
+
name: "to",
|
|
21313
|
+
flag: "--to <ms>",
|
|
21314
|
+
description: "End timestamp in epoch milliseconds.",
|
|
21315
|
+
type: "number",
|
|
21316
|
+
required: true
|
|
21317
|
+
},
|
|
20888
21318
|
{ name: "limit", flag: "--limit <number>", description: "Maximum occurrences to return.", type: "number" },
|
|
20889
21319
|
{ name: "offset", flag: "--offset <number>", description: "Zero-based occurrence offset.", type: "number" },
|
|
20890
|
-
{
|
|
21320
|
+
{
|
|
21321
|
+
name: "scheduleId",
|
|
21322
|
+
flag: "--schedule-id <scheduleId>",
|
|
21323
|
+
description: "Optional schedule id filter.",
|
|
21324
|
+
type: "string"
|
|
21325
|
+
}
|
|
20891
21326
|
],
|
|
20892
21327
|
http: {
|
|
20893
21328
|
method: "GET",
|
|
@@ -20928,7 +21363,12 @@ var commandDefinitions = [
|
|
|
20928
21363
|
{ name: "lineEnd", flag: "--line-end <number>", description: "End line (inclusive).", type: "number" },
|
|
20929
21364
|
{ name: "page", flag: "--page <number>", description: "Start page (1-based, PDFs).", type: "number" },
|
|
20930
21365
|
{ name: "pageEnd", flag: "--page-end <number>", description: "End page (inclusive).", type: "number" },
|
|
20931
|
-
{
|
|
21366
|
+
{
|
|
21367
|
+
name: "expand",
|
|
21368
|
+
flag: "--expand <number>",
|
|
21369
|
+
description: "Extra lines of context around the range.",
|
|
21370
|
+
type: "number"
|
|
21371
|
+
}
|
|
20932
21372
|
],
|
|
20933
21373
|
http: {
|
|
20934
21374
|
method: "GET",
|
|
@@ -20958,7 +21398,12 @@ var commandDefinitions = [
|
|
|
20958
21398
|
options: [
|
|
20959
21399
|
{ name: "scope", flag: "--scope <path>", description: "Restrict to a folder path.", type: "string" },
|
|
20960
21400
|
{ name: "limit", flag: "--limit <number>", description: "Max matches (default 20, max 100).", type: "number" },
|
|
20961
|
-
{
|
|
21401
|
+
{
|
|
21402
|
+
name: "debug",
|
|
21403
|
+
flag: "--debug",
|
|
21404
|
+
description: "Include candidate scoring breakdown (JSON mode).",
|
|
21405
|
+
type: "boolean"
|
|
21406
|
+
}
|
|
20962
21407
|
],
|
|
20963
21408
|
http: {
|
|
20964
21409
|
method: "POST",
|
|
@@ -20982,8 +21427,18 @@ var commandDefinitions = [
|
|
|
20982
21427
|
options: [
|
|
20983
21428
|
{ name: "scope", flag: "--scope <path>", description: "Restrict to a folder path.", type: "string" },
|
|
20984
21429
|
{ name: "limit", flag: "--limit <number>", description: "Max matches (default 20, max 100).", type: "number" },
|
|
20985
|
-
{
|
|
20986
|
-
|
|
21430
|
+
{
|
|
21431
|
+
name: "rerank",
|
|
21432
|
+
flag: "--rerank",
|
|
21433
|
+
description: "Enable LLM reranking (slower, higher quality).",
|
|
21434
|
+
type: "boolean"
|
|
21435
|
+
},
|
|
21436
|
+
{
|
|
21437
|
+
name: "debug",
|
|
21438
|
+
flag: "--debug",
|
|
21439
|
+
description: "Include candidate scoring breakdown (JSON mode).",
|
|
21440
|
+
type: "boolean"
|
|
21441
|
+
}
|
|
20987
21442
|
],
|
|
20988
21443
|
http: {
|
|
20989
21444
|
method: "POST",
|
|
@@ -21026,6 +21481,13 @@ function validateCommandInput(command, args, options) {
|
|
|
21026
21481
|
return validationError(command, option.name, `Expected one of: ${option.enumValues.join(", ")}.`);
|
|
21027
21482
|
}
|
|
21028
21483
|
}
|
|
21484
|
+
if (typeof value === "number" && option.minimum !== void 0 && value < option.minimum) {
|
|
21485
|
+
return validationError(
|
|
21486
|
+
command,
|
|
21487
|
+
option.name,
|
|
21488
|
+
`${getOptionDisplayName(option.flag)} must be at least ${option.minimum}.`
|
|
21489
|
+
);
|
|
21490
|
+
}
|
|
21029
21491
|
}
|
|
21030
21492
|
return null;
|
|
21031
21493
|
}
|
|
@@ -21579,6 +22041,43 @@ async function logout() {
|
|
|
21579
22041
|
});
|
|
21580
22042
|
}
|
|
21581
22043
|
|
|
22044
|
+
// src/render/ai-job-wait.ts
|
|
22045
|
+
function objectRecord(value) {
|
|
22046
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
22047
|
+
}
|
|
22048
|
+
function compactResult(result) {
|
|
22049
|
+
const data = objectRecord(result.data);
|
|
22050
|
+
const execution = objectRecord(data.latestExecution);
|
|
22051
|
+
const status = typeof data.status === "string" ? data.status.toLowerCase() : result.status;
|
|
22052
|
+
const resultUrls = Array.isArray(execution.resultUrls) ? execution.resultUrls.filter((url2) => typeof url2 === "string") : [];
|
|
22053
|
+
return {
|
|
22054
|
+
id: typeof data.id === "string" ? data.id : result.ids.jobId,
|
|
22055
|
+
modelId: typeof data.modelId === "string" ? data.modelId : void 0,
|
|
22056
|
+
status,
|
|
22057
|
+
resultType: typeof execution.resultType === "string" ? execution.resultType : void 0,
|
|
22058
|
+
resultUrls,
|
|
22059
|
+
...result.error ? {
|
|
22060
|
+
error: {
|
|
22061
|
+
code: result.error.code,
|
|
22062
|
+
message: result.error.message,
|
|
22063
|
+
retryable: result.error.retryable
|
|
22064
|
+
}
|
|
22065
|
+
} : {}
|
|
22066
|
+
};
|
|
22067
|
+
}
|
|
22068
|
+
function renderAiJobWait(result, options) {
|
|
22069
|
+
const compact = compactResult(result);
|
|
22070
|
+
if (options.json) return `${JSON.stringify(compact, null, 2)}
|
|
22071
|
+
`;
|
|
22072
|
+
const lines = [`id: ${compact.id ?? "-"}`, `status: ${compact.status}`];
|
|
22073
|
+
if (compact.modelId) lines.push(`modelId: ${compact.modelId}`);
|
|
22074
|
+
if (compact.resultType) lines.push(`resultType: ${compact.resultType}`);
|
|
22075
|
+
lines.push(...compact.resultUrls);
|
|
22076
|
+
if (compact.error) lines.push(`error: ${compact.error.message}`);
|
|
22077
|
+
return `${lines.join("\n")}
|
|
22078
|
+
`;
|
|
22079
|
+
}
|
|
22080
|
+
|
|
21582
22081
|
// src/render/human.ts
|
|
21583
22082
|
function valueToText(value) {
|
|
21584
22083
|
if (value === null || value === void 0 || value === "") return "-";
|
|
@@ -21604,20 +22103,18 @@ function dataArray(data) {
|
|
|
21604
22103
|
}
|
|
21605
22104
|
function renderRows(rows, columns) {
|
|
21606
22105
|
if (rows.length === 0) return "No results.\n";
|
|
21607
|
-
const records = rows.map(
|
|
22106
|
+
const records = rows.map(
|
|
22107
|
+
(row) => row && typeof row === "object" ? row : { value: row }
|
|
22108
|
+
);
|
|
21608
22109
|
const widths = columns.map(
|
|
21609
|
-
(column) => Math.min(
|
|
21610
|
-
42,
|
|
21611
|
-
Math.max(
|
|
21612
|
-
column.length,
|
|
21613
|
-
...records.map((record2) => valueToText(record2[column]).slice(0, 42).length)
|
|
21614
|
-
)
|
|
21615
|
-
)
|
|
22110
|
+
(column) => Math.min(42, Math.max(column.length, ...records.map((record2) => valueToText(record2[column]).slice(0, 42).length)))
|
|
21616
22111
|
);
|
|
21617
22112
|
const header = columns.map((column, index) => column.padEnd(widths[index])).join(" ");
|
|
21618
22113
|
const divider = widths.map((width) => "-".repeat(width)).join(" ");
|
|
21619
22114
|
const body = records.map(
|
|
21620
|
-
(record2) => columns.map(
|
|
22115
|
+
(record2) => columns.map(
|
|
22116
|
+
(column, index) => valueToText(record2[column]).replace(/\s+/g, " ").slice(0, widths[index]).padEnd(widths[index])
|
|
22117
|
+
).join(" ")
|
|
21621
22118
|
).join("\n");
|
|
21622
22119
|
return `${header}
|
|
21623
22120
|
${divider}
|
|
@@ -21629,11 +22126,11 @@ function renderKeyValues(data) {
|
|
|
21629
22126
|
`;
|
|
21630
22127
|
return Object.entries(data).filter(([, value]) => typeof value !== "object" || value === null).map(([key, value]) => `${key}: ${valueToText(value)}`).join("\n").concat("\n");
|
|
21631
22128
|
}
|
|
21632
|
-
function
|
|
22129
|
+
function objectRecord2(data) {
|
|
21633
22130
|
return data && typeof data === "object" ? data : {};
|
|
21634
22131
|
}
|
|
21635
22132
|
function formatWhen(value) {
|
|
21636
|
-
const record2 =
|
|
22133
|
+
const record2 = objectRecord2(value);
|
|
21637
22134
|
const entries = Object.entries(record2);
|
|
21638
22135
|
if (!entries.length) return "";
|
|
21639
22136
|
return entries.map(([key, item]) => `${key}=${valueToText(item)}`).join(", ");
|
|
@@ -21649,17 +22146,17 @@ function formatCreditOption(option) {
|
|
|
21649
22146
|
function portSummary(ports) {
|
|
21650
22147
|
if (!Array.isArray(ports) || ports.length === 0) return "-";
|
|
21651
22148
|
return ports.map((port) => {
|
|
21652
|
-
const record2 =
|
|
22149
|
+
const record2 = objectRecord2(port);
|
|
21653
22150
|
const suffix = record2.multiple ? "[]" : "";
|
|
21654
22151
|
return `${valueToText(record2.id)}:${valueToText(record2.valueType)}${suffix}`;
|
|
21655
22152
|
}).join(", ");
|
|
21656
22153
|
}
|
|
21657
22154
|
function renderWorkflowNodeCatalog(data) {
|
|
21658
|
-
const record2 =
|
|
22155
|
+
const record2 = objectRecord2(data);
|
|
21659
22156
|
const nodes = Array.isArray(record2.nodes) ? record2.nodes : [];
|
|
21660
22157
|
const rows = nodes.map((node) => {
|
|
21661
|
-
const nodeRecord =
|
|
21662
|
-
const ports =
|
|
22158
|
+
const nodeRecord = objectRecord2(node);
|
|
22159
|
+
const ports = objectRecord2(nodeRecord.ports);
|
|
21663
22160
|
return {
|
|
21664
22161
|
type: nodeRecord.type,
|
|
21665
22162
|
inputs: portSummary(ports.inputs),
|
|
@@ -21673,7 +22170,7 @@ function renderAccountList(data) {
|
|
|
21673
22170
|
const channels = data && typeof data === "object" ? data.publishChannels : null;
|
|
21674
22171
|
if (Array.isArray(channels)) {
|
|
21675
22172
|
const rows = channels.map((channel) => {
|
|
21676
|
-
const record2 =
|
|
22173
|
+
const record2 = objectRecord2(channel);
|
|
21677
22174
|
return {
|
|
21678
22175
|
platform: record2.platform,
|
|
21679
22176
|
connected: record2.oauthAccountsCount,
|
|
@@ -21686,12 +22183,12 @@ function renderAccountList(data) {
|
|
|
21686
22183
|
return renderKeyValues(data);
|
|
21687
22184
|
}
|
|
21688
22185
|
function renderAccountConnect(data) {
|
|
21689
|
-
const record2 =
|
|
22186
|
+
const record2 = objectRecord2(data);
|
|
21690
22187
|
return `platform: ${valueToText(record2.platform)}
|
|
21691
22188
|
`;
|
|
21692
22189
|
}
|
|
21693
22190
|
function renderCreditBalance(data) {
|
|
21694
|
-
const record2 =
|
|
22191
|
+
const record2 = objectRecord2(data);
|
|
21695
22192
|
const lines = [
|
|
21696
22193
|
`availableCredits: ${formatCredits(record2.availableCredits)}`,
|
|
21697
22194
|
`permanentCredits: ${formatCredits(record2.availablePermanentCredits)}`,
|
|
@@ -21718,7 +22215,7 @@ function renderUser(prefix, value) {
|
|
|
21718
22215
|
function renderAuthWhoami(data) {
|
|
21719
22216
|
if (!data || typeof data !== "object") return renderKeyValues(data);
|
|
21720
22217
|
const record2 = data;
|
|
21721
|
-
const effective =
|
|
22218
|
+
const effective = objectRecord2(record2.effectiveUser);
|
|
21722
22219
|
const name = valueToText(effective.name);
|
|
21723
22220
|
const email3 = valueToText(effective.email);
|
|
21724
22221
|
const lines = [`user: ${name}${email3 === "-" ? "" : ` <${email3}>`}`];
|
|
@@ -21733,8 +22230,8 @@ function renderAuthLogin(data) {
|
|
|
21733
22230
|
`;
|
|
21734
22231
|
}
|
|
21735
22232
|
function renderSocialSubmissionDetail(data) {
|
|
21736
|
-
const raw =
|
|
21737
|
-
const nested =
|
|
22233
|
+
const raw = objectRecord2(data);
|
|
22234
|
+
const nested = objectRecord2(raw.data);
|
|
21738
22235
|
const record2 = nested.submission_id || nested.postUrl || nested.tweetId ? {
|
|
21739
22236
|
id: nested.submission_id,
|
|
21740
22237
|
platform: raw.platform,
|
|
@@ -21768,8 +22265,8 @@ function renderSocialSubmissionDetail(data) {
|
|
|
21768
22265
|
`;
|
|
21769
22266
|
}
|
|
21770
22267
|
function renderAiJobStatus(data) {
|
|
21771
|
-
const record2 =
|
|
21772
|
-
const latestExecution =
|
|
22268
|
+
const record2 = objectRecord2(data);
|
|
22269
|
+
const latestExecution = objectRecord2(record2.latestExecution);
|
|
21773
22270
|
const resultUrls = Array.isArray(latestExecution.resultUrls) ? latestExecution.resultUrls : [];
|
|
21774
22271
|
const lines = [
|
|
21775
22272
|
`id: ${valueToText(record2.id)}`,
|
|
@@ -21787,11 +22284,14 @@ function renderAiJobStatus(data) {
|
|
|
21787
22284
|
function renderAiModelList(data) {
|
|
21788
22285
|
return renderRows(dataArray(data), ["id", "mediaType", "creditOptions", "name", "capabilities"]);
|
|
21789
22286
|
}
|
|
22287
|
+
function renderAiModelProviderList(data) {
|
|
22288
|
+
return renderRows(dataArray(data), ["modelId", "name", "providers", "hidden"]);
|
|
22289
|
+
}
|
|
21790
22290
|
function renderAiModelDetail(data) {
|
|
21791
|
-
const record2 =
|
|
21792
|
-
const fields = Array.isArray(record2.fields) ? record2.fields.map(
|
|
21793
|
-
const creditOptions = Array.isArray(record2.creditOptions) ? record2.creditOptions.map(
|
|
21794
|
-
const examples = Array.isArray(record2.examples) ? record2.examples.map(
|
|
22291
|
+
const record2 = objectRecord2(data);
|
|
22292
|
+
const fields = Array.isArray(record2.fields) ? record2.fields.map(objectRecord2) : [];
|
|
22293
|
+
const creditOptions = Array.isArray(record2.creditOptions) ? record2.creditOptions.map(objectRecord2) : Array.isArray(record2.variants) ? record2.variants.map(objectRecord2) : [];
|
|
22294
|
+
const examples = Array.isArray(record2.examples) ? record2.examples.map(objectRecord2) : [];
|
|
21795
22295
|
const notes = Array.isArray(record2.notes) ? record2.notes : [];
|
|
21796
22296
|
const lines = [
|
|
21797
22297
|
`id: ${valueToText(record2.id)}`,
|
|
@@ -21831,8 +22331,8 @@ function renderAiModelDetail(data) {
|
|
|
21831
22331
|
`;
|
|
21832
22332
|
}
|
|
21833
22333
|
function renderWorkflowDetail(data) {
|
|
21834
|
-
const record2 =
|
|
21835
|
-
const definition =
|
|
22334
|
+
const record2 = objectRecord2(data);
|
|
22335
|
+
const definition = objectRecord2(record2.workflowDefinition);
|
|
21836
22336
|
const nodes = Array.isArray(definition.nodes) ? definition.nodes : [];
|
|
21837
22337
|
const edges = Array.isArray(definition.edges) ? definition.edges : [];
|
|
21838
22338
|
return [
|
|
@@ -21845,9 +22345,9 @@ function renderWorkflowDetail(data) {
|
|
|
21845
22345
|
].join("\n").concat("\n");
|
|
21846
22346
|
}
|
|
21847
22347
|
function renderScheduleDetail(data) {
|
|
21848
|
-
const record2 =
|
|
21849
|
-
const executorConfig =
|
|
21850
|
-
const currentPattern =
|
|
22348
|
+
const record2 = objectRecord2(data);
|
|
22349
|
+
const executorConfig = objectRecord2(record2.executorConfig);
|
|
22350
|
+
const currentPattern = objectRecord2(record2.currentPattern);
|
|
21851
22351
|
return [
|
|
21852
22352
|
`id: ${valueToText(record2.id)}`,
|
|
21853
22353
|
`executorType: ${valueToText(record2.executorType)}`,
|
|
@@ -21888,9 +22388,9 @@ function formatAnchor(anchor) {
|
|
|
21888
22388
|
return parts.join(", ") || "-";
|
|
21889
22389
|
}
|
|
21890
22390
|
function renderDataBaseGlob(data) {
|
|
21891
|
-
const record2 =
|
|
22391
|
+
const record2 = objectRecord2(data);
|
|
21892
22392
|
const pattern = valueToText(record2.pattern);
|
|
21893
|
-
const entries = Array.isArray(record2.entries) ? record2.entries.map(
|
|
22393
|
+
const entries = Array.isArray(record2.entries) ? record2.entries.map(objectRecord2) : [];
|
|
21894
22394
|
if (entries.length === 0) return `pattern: ${pattern}
|
|
21895
22395
|
No entries.
|
|
21896
22396
|
`;
|
|
@@ -21910,11 +22410,11 @@ No entries.
|
|
|
21910
22410
|
${renderRows(rows, ["type", "path", "fileType", "size", "status", "updatedAt"])}`;
|
|
21911
22411
|
}
|
|
21912
22412
|
function renderDataBaseRead(data) {
|
|
21913
|
-
const record2 =
|
|
22413
|
+
const record2 = objectRecord2(data);
|
|
21914
22414
|
const path = valueToText(record2.path);
|
|
21915
22415
|
const fileType = valueToText(record2.fileType);
|
|
21916
22416
|
const mimeType = valueToText(record2.mimeType);
|
|
21917
|
-
const rangeObj =
|
|
22417
|
+
const rangeObj = objectRecord2(record2.range);
|
|
21918
22418
|
let rangeStr = "-";
|
|
21919
22419
|
if (Array.isArray(rangeObj.line) && rangeObj.line.length === 2) {
|
|
21920
22420
|
rangeStr = `lines ${rangeObj.line[0]}-${rangeObj.line[1]}`;
|
|
@@ -21946,14 +22446,14 @@ function renderDataBaseRead(data) {
|
|
|
21946
22446
|
${content}${footer}`;
|
|
21947
22447
|
}
|
|
21948
22448
|
function renderDataBaseMatches(data) {
|
|
21949
|
-
const record2 =
|
|
22449
|
+
const record2 = objectRecord2(data);
|
|
21950
22450
|
const query = valueToText(record2.query);
|
|
21951
|
-
const matches = Array.isArray(record2.matches) ? record2.matches.map(
|
|
22451
|
+
const matches = Array.isArray(record2.matches) ? record2.matches.map(objectRecord2) : [];
|
|
21952
22452
|
if (matches.length === 0) return `query: ${query}
|
|
21953
22453
|
No matches.
|
|
21954
22454
|
`;
|
|
21955
22455
|
const blocks = matches.map((match) => {
|
|
21956
|
-
const anchor = formatAnchor(
|
|
22456
|
+
const anchor = formatAnchor(objectRecord2(match.anchor));
|
|
21957
22457
|
const score = typeof match.score === "number" ? match.score.toFixed(3) : valueToText(match.score);
|
|
21958
22458
|
const fields = Array.isArray(match.matchedFields) ? match.matchedFields.join(",") : "";
|
|
21959
22459
|
const header = `${valueToText(match.path)}(${anchor}) [score=${score}${fields ? ` fields=${fields}` : ""}]`;
|
|
@@ -21983,7 +22483,7 @@ function renderSuccess(result) {
|
|
|
21983
22483
|
case "socialSubmissionList":
|
|
21984
22484
|
return renderRows(
|
|
21985
22485
|
dataArray(result.data).map((item) => {
|
|
21986
|
-
const record2 =
|
|
22486
|
+
const record2 = objectRecord2(item);
|
|
21987
22487
|
return {
|
|
21988
22488
|
id: record2.id,
|
|
21989
22489
|
platform: record2.platform,
|
|
@@ -22006,6 +22506,8 @@ function renderSuccess(result) {
|
|
|
22006
22506
|
return renderAiModelList(result.data);
|
|
22007
22507
|
case "aiModelDetail":
|
|
22008
22508
|
return renderAiModelDetail(result.data);
|
|
22509
|
+
case "aiModelProviderList":
|
|
22510
|
+
return renderAiModelProviderList(result.data);
|
|
22009
22511
|
case "workflowList":
|
|
22010
22512
|
return renderRows(dataArray(result.data), ["id", "name", "creatorName", "nodeTypes", "updatedAt"]);
|
|
22011
22513
|
case "workflowNodeCatalog":
|
|
@@ -22021,7 +22523,14 @@ function renderSuccess(result) {
|
|
|
22021
22523
|
case "scheduleOccurrenceList":
|
|
22022
22524
|
return renderRows(dataArray(result.data), ["id", "scheduleId", "scheduledAt", "status", "executorType"]);
|
|
22023
22525
|
case "scheduleExecutionList":
|
|
22024
|
-
return renderRows(dataArray(result.data), [
|
|
22526
|
+
return renderRows(dataArray(result.data), [
|
|
22527
|
+
"id",
|
|
22528
|
+
"scheduleId",
|
|
22529
|
+
"status",
|
|
22530
|
+
"originalScheduledAt",
|
|
22531
|
+
"startedAt",
|
|
22532
|
+
"finishedAt"
|
|
22533
|
+
]);
|
|
22025
22534
|
case "dataBaseGlob":
|
|
22026
22535
|
return renderDataBaseGlob(result.data);
|
|
22027
22536
|
case "dataBaseRead":
|
|
@@ -22080,6 +22589,7 @@ function renderJson(result) {
|
|
|
22080
22589
|
|
|
22081
22590
|
// src/render/index.ts
|
|
22082
22591
|
function renderResult(result, options) {
|
|
22592
|
+
if (options.compactAiJobWait) return renderAiJobWait(result, options);
|
|
22083
22593
|
return options.json ? renderJson(result) : renderHuman(result);
|
|
22084
22594
|
}
|
|
22085
22595
|
|
|
@@ -22232,6 +22742,24 @@ function parseNumber(value) {
|
|
|
22232
22742
|
if (!Number.isFinite(parsed)) throw new InvalidArgumentError("Expected a number.");
|
|
22233
22743
|
return parsed;
|
|
22234
22744
|
}
|
|
22745
|
+
function parseDuration(value) {
|
|
22746
|
+
const match = /^(\d+(?:\.\d+)?)(ms|s|m|h)$/.exec(value.trim());
|
|
22747
|
+
if (!match) throw new InvalidArgumentError("Expected a duration such as 500ms, 3s, 10m, or 1h.");
|
|
22748
|
+
const amount = Number(match[1]);
|
|
22749
|
+
const unit = match[2];
|
|
22750
|
+
const multiplier = unit === "ms" ? 1 : unit === "s" ? 1e3 : unit === "m" ? 6e4 : 36e5;
|
|
22751
|
+
const durationMs = amount * multiplier;
|
|
22752
|
+
if (!Number.isSafeInteger(durationMs) || durationMs <= 0) {
|
|
22753
|
+
throw new InvalidArgumentError("Expected a positive duration.");
|
|
22754
|
+
}
|
|
22755
|
+
return durationMs;
|
|
22756
|
+
}
|
|
22757
|
+
function formatDuration(durationMs) {
|
|
22758
|
+
if (durationMs % 36e5 === 0) return `${durationMs / 36e5}h`;
|
|
22759
|
+
if (durationMs % 6e4 === 0) return `${durationMs / 6e4}m`;
|
|
22760
|
+
if (durationMs % 1e3 === 0) return `${durationMs / 1e3}s`;
|
|
22761
|
+
return `${durationMs}ms`;
|
|
22762
|
+
}
|
|
22235
22763
|
function parseJson(value) {
|
|
22236
22764
|
try {
|
|
22237
22765
|
return JSON.parse(value);
|
|
@@ -22250,6 +22778,11 @@ function addOption(command, definition) {
|
|
|
22250
22778
|
command.addOption(option.argParser(parseNumber).default(definition.defaultValue));
|
|
22251
22779
|
return;
|
|
22252
22780
|
}
|
|
22781
|
+
if (definition.type === "duration") {
|
|
22782
|
+
const defaultDescription = typeof definition.defaultValue === "number" ? formatDuration(definition.defaultValue) : void 0;
|
|
22783
|
+
command.addOption(option.argParser(parseDuration).default(definition.defaultValue, defaultDescription));
|
|
22784
|
+
return;
|
|
22785
|
+
}
|
|
22253
22786
|
if (definition.type === "json") {
|
|
22254
22787
|
command.addOption(option.argParser(parseJson).default(definition.defaultValue));
|
|
22255
22788
|
return;
|
|
@@ -22306,10 +22839,7 @@ function getOrCreateSubcommand(parent, name) {
|
|
|
22306
22839
|
return next;
|
|
22307
22840
|
}
|
|
22308
22841
|
function renderCommandReference(definition) {
|
|
22309
|
-
const lines = [
|
|
22310
|
-
`Command: spira ${definition.path.join(" ")}`,
|
|
22311
|
-
`Description: ${definition.purpose}`
|
|
22312
|
-
];
|
|
22842
|
+
const lines = [`Command: spira ${definition.path.join(" ")}`, `Description: ${definition.purpose}`];
|
|
22313
22843
|
if (definition.arguments?.length) {
|
|
22314
22844
|
lines.push("Arguments:");
|
|
22315
22845
|
for (const argument of definition.arguments) {
|
|
@@ -22338,8 +22868,8 @@ function renderCommandIndex() {
|
|
|
22338
22868
|
`;
|
|
22339
22869
|
}
|
|
22340
22870
|
async function packageVersion() {
|
|
22341
|
-
if ("0.0.
|
|
22342
|
-
return "0.0.
|
|
22871
|
+
if ("0.0.7".length > 0) {
|
|
22872
|
+
return "0.0.7";
|
|
22343
22873
|
}
|
|
22344
22874
|
try {
|
|
22345
22875
|
const packageUrl = new URL("../package.json", import_meta.url);
|
|
@@ -22512,7 +23042,52 @@ ${url2}
|
|
|
22512
23042
|
resultType: "aiModelDetail",
|
|
22513
23043
|
command: "spira ai models get",
|
|
22514
23044
|
data: publicAiModelDoc(model),
|
|
22515
|
-
nextActions: [
|
|
23045
|
+
nextActions: [
|
|
23046
|
+
{ label: "Create job", command: `spira ai jobs create --model-id ${model.id} --inputs-json '<json>'` }
|
|
23047
|
+
]
|
|
23048
|
+
});
|
|
23049
|
+
}
|
|
23050
|
+
if (commandKey(definition.path) === "ai jobs create") {
|
|
23051
|
+
const created = await executeHttpCommand({ command: definition, args, options });
|
|
23052
|
+
if (options.wait !== true || created.status === "error") return created;
|
|
23053
|
+
const jobId = created.ids.jobId;
|
|
23054
|
+
if (!jobId) {
|
|
23055
|
+
return cliResultSchema.parse({
|
|
23056
|
+
...created,
|
|
23057
|
+
status: "error",
|
|
23058
|
+
error: {
|
|
23059
|
+
code: "CONTRACT_MISMATCH",
|
|
23060
|
+
message: "AI job creation response did not contain a jobId.",
|
|
23061
|
+
retryable: false,
|
|
23062
|
+
nextActions: []
|
|
23063
|
+
}
|
|
23064
|
+
});
|
|
23065
|
+
}
|
|
23066
|
+
const statusCommand = findCommandDefinition(["ai", "jobs", "status"]);
|
|
23067
|
+
if (!statusCommand) throw new Error("AI job status command is not registered.");
|
|
23068
|
+
output.error(`AI job ${jobId}: SUBMITTED
|
|
23069
|
+
`);
|
|
23070
|
+
return waitForAiJob({
|
|
23071
|
+
jobId,
|
|
23072
|
+
timeoutMs: options.waitTimeout,
|
|
23073
|
+
intervalMs: options.waitInterval,
|
|
23074
|
+
onStatus: (status) => output.error(`AI job ${jobId}: ${status}
|
|
23075
|
+
`),
|
|
23076
|
+
poll: () => executeHttpCommand({ command: statusCommand, args: { jobId }, options: {} })
|
|
23077
|
+
});
|
|
23078
|
+
}
|
|
23079
|
+
if (commandKey(definition.path) === "ai jobs wait") {
|
|
23080
|
+
const statusCommand = findCommandDefinition(["ai", "jobs", "status"]);
|
|
23081
|
+
if (!statusCommand) throw new Error("AI job status command is not registered.");
|
|
23082
|
+
const jobId = args.jobId;
|
|
23083
|
+
return waitForAiJob({
|
|
23084
|
+
jobId,
|
|
23085
|
+
command: "spira ai jobs wait",
|
|
23086
|
+
timeoutMs: options.timeout,
|
|
23087
|
+
intervalMs: options.interval,
|
|
23088
|
+
onStatus: (status) => output.error(`AI job ${jobId}: ${status}
|
|
23089
|
+
`),
|
|
23090
|
+
poll: () => executeHttpCommand({ command: statusCommand, args: { jobId }, options: {} })
|
|
22516
23091
|
});
|
|
22517
23092
|
}
|
|
22518
23093
|
return executeHttpCommand({ command: definition, args, options });
|
|
@@ -22531,11 +23106,18 @@ function addLeafCommand(root, definition, output) {
|
|
|
22531
23106
|
leaf.action(async (...values) => {
|
|
22532
23107
|
const command = values[values.length - 1];
|
|
22533
23108
|
const positional = values.slice(0, -1).map((value) => value === void 0 ? "" : String(value));
|
|
22534
|
-
const args = Object.fromEntries(
|
|
23109
|
+
const args = Object.fromEntries(
|
|
23110
|
+
(definition.arguments ?? []).map((argument, index) => [argument.name, positional[index] ?? ""])
|
|
23111
|
+
);
|
|
22535
23112
|
const options = command.optsWithGlobals();
|
|
22536
23113
|
const validationResult2 = validateCommandInput(definition, args, options);
|
|
22537
23114
|
const result = validationResult2 ?? await executeDefinition(definition, args, options, output);
|
|
22538
|
-
output.write(
|
|
23115
|
+
output.write(
|
|
23116
|
+
renderResult(result, {
|
|
23117
|
+
json: Boolean(options.json),
|
|
23118
|
+
compactAiJobWait: commandKey(definition.path) === "ai jobs create" && options.wait === true || commandKey(definition.path) === "ai jobs wait"
|
|
23119
|
+
})
|
|
23120
|
+
);
|
|
22539
23121
|
if (result.status === "error") process.exitCode = 1;
|
|
22540
23122
|
});
|
|
22541
23123
|
parent.addCommand(leaf);
|