@postplus/cli 0.1.44 → 0.1.46

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.
@@ -2,6 +2,10 @@ import { readFile } from 'node:fs/promises';
2
2
  import { readLocalConfig, updateLocalConfig } from './local-state.js';
3
3
  export const POSTPLUS_CLIENT_CONTRACT_VERSION = 2;
4
4
  export const POSTPLUS_CLIENT_RUNTIME = 'postplus-cli';
5
+ // Single source for the CLI self-update command. Lives here (the upgrade-error
6
+ // formatter's home) so update-check.ts can import it without a cycle —
7
+ // update-check already depends on this module for readCurrentCliVersion.
8
+ export const POSTPLUS_CLI_UPDATE_COMMAND = 'npm install -g @postplus/cli@latest';
5
9
  export const POSTPLUS_CLIENT_COMPATIBILITY_HEADERS = {
6
10
  cliVersion: 'x-postplus-cli-version',
7
11
  contractVersion: 'x-postplus-client-contract-version',
@@ -50,8 +54,7 @@ export function formatPostPlusClientUpgradeError(payload) {
50
54
  const record = payload && typeof payload === 'object' && !Array.isArray(payload)
51
55
  ? payload
52
56
  : {};
53
- const cliCommand = record.compatibility?.upgrade?.cli?.command ??
54
- 'npm install -g @postplus/cli@latest';
57
+ const cliCommand = record.compatibility?.upgrade?.cli?.command ?? POSTPLUS_CLI_UPDATE_COMMAND;
55
58
  const skillsCommand = record.compatibility?.upgrade?.skills?.command ?? 'postplus update';
56
59
  const restart = record.compatibility?.upgrade?.restartAgentSession
57
60
  ? ' Then restart your agent session.'
@@ -12,8 +12,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
12
12
  "domain": "media",
13
13
  "capability": "media-generation",
14
14
  "endpointKeys": [
15
- "transcription",
16
- "transcription-turbo"
15
+ "transcription"
17
16
  ],
18
17
  "endpoints": [
19
18
  {
@@ -96,87 +95,6 @@ export const HOSTED_EXECUTION_MANIFESTS = {
96
95
  "billingDimensions": [
97
96
  "mediaSeconds"
98
97
  ]
99
- },
100
- {
101
- "endpointKey": "transcription-turbo",
102
- "provider": "wavespeed",
103
- "providerModelPath": "wavespeed-ai/openai-whisper-turbo",
104
- "fields": [
105
- {
106
- "name": "audio",
107
- "class": "intent",
108
- "flag": "--audio",
109
- "type": "media-url",
110
- "required": true
111
- },
112
- {
113
- "name": "duration_seconds",
114
- "class": "intent",
115
- "flag": "--duration-seconds",
116
- "type": "number",
117
- "required": true
118
- },
119
- {
120
- "name": "task",
121
- "class": "default",
122
- "flag": "--task",
123
- "type": "string",
124
- "enumValues": [
125
- "transcribe",
126
- "translate"
127
- ],
128
- "default": "transcribe",
129
- "required": false
130
- },
131
- {
132
- "name": "language",
133
- "class": "default",
134
- "flag": "--language",
135
- "type": "string",
136
- "default": "auto",
137
- "required": false
138
- },
139
- {
140
- "name": "enable_timestamps",
141
- "class": "default",
142
- "flag": "--enable-timestamps",
143
- "type": "boolean",
144
- "default": false,
145
- "required": false
146
- },
147
- {
148
- "name": "prompt",
149
- "class": "intent",
150
- "flag": "--prompt",
151
- "type": "string",
152
- "required": false
153
- },
154
- {
155
- "name": "mediaSeconds",
156
- "class": "runner-managed",
157
- "flag": null,
158
- "type": "number",
159
- "required": false,
160
- "derivedFrom": "duration_seconds"
161
- },
162
- {
163
- "name": "operationId",
164
- "class": "runner-managed",
165
- "flag": null,
166
- "type": "string",
167
- "required": false
168
- },
169
- {
170
- "name": "quoteConfirmationToken",
171
- "class": "runner-managed",
172
- "flag": null,
173
- "type": "string",
174
- "required": false
175
- }
176
- ],
177
- "billingDimensions": [
178
- "mediaSeconds"
179
- ]
180
98
  }
181
99
  ]
182
100
  }
@@ -251,7 +169,8 @@ export const HOSTED_EXECUTION_MANIFESTS = {
251
169
  "image-seedream-v5-lite-text",
252
170
  "image-seedream-v5-lite-sequential",
253
171
  "image-seedream-v5-lite-edit",
254
- "image-seedream-v5-lite-edit-sequential"
172
+ "image-seedream-v5-lite-edit-sequential",
173
+ "image-higgsfield-soul-text"
255
174
  ],
256
175
  "endpoints": [
257
176
  {
@@ -284,6 +203,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
284
203
  "2k",
285
204
  "4k"
286
205
  ],
206
+ "canonicalize": "image-resolution-tier",
287
207
  "default": "1k",
288
208
  "required": false
289
209
  },
@@ -297,6 +217,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
297
217
  "medium",
298
218
  "high"
299
219
  ],
220
+ "canonicalize": "lowercase",
300
221
  "default": "medium",
301
222
  "required": false
302
223
  },
@@ -358,6 +279,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
358
279
  "2k",
359
280
  "4k"
360
281
  ],
282
+ "canonicalize": "image-resolution-tier",
361
283
  "default": "1k",
362
284
  "required": false
363
285
  },
@@ -371,6 +293,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
371
293
  "medium",
372
294
  "high"
373
295
  ],
296
+ "canonicalize": "lowercase",
374
297
  "default": "medium",
375
298
  "required": false
376
299
  },
@@ -425,6 +348,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
425
348
  "2k",
426
349
  "4k"
427
350
  ],
351
+ "canonicalize": "image-resolution-tier",
428
352
  "default": "1k",
429
353
  "required": false
430
354
  },
@@ -445,6 +369,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
445
369
  "png",
446
370
  "jpeg"
447
371
  ],
372
+ "canonicalize": "lowercase",
448
373
  "default": "png",
449
374
  "required": false
450
375
  },
@@ -506,6 +431,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
506
431
  "2k",
507
432
  "4k"
508
433
  ],
434
+ "canonicalize": "image-resolution-tier",
509
435
  "default": "1k",
510
436
  "required": false
511
437
  },
@@ -526,6 +452,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
526
452
  "png",
527
453
  "jpeg"
528
454
  ],
455
+ "canonicalize": "lowercase",
529
456
  "default": "png",
530
457
  "required": false
531
458
  },
@@ -576,6 +503,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
576
503
  "enumValues": [
577
504
  "1k"
578
505
  ],
506
+ "canonicalize": "image-resolution-tier",
579
507
  "default": "1k",
580
508
  "required": false
581
509
  },
@@ -588,6 +516,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
588
516
  "png",
589
517
  "jpeg"
590
518
  ],
519
+ "canonicalize": "lowercase",
591
520
  "default": "png",
592
521
  "required": false
593
522
  },
@@ -638,6 +567,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
638
567
  "enumValues": [
639
568
  "2k"
640
569
  ],
570
+ "canonicalize": "image-resolution-tier",
641
571
  "default": "2k",
642
572
  "required": false
643
573
  },
@@ -650,6 +580,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
650
580
  "png",
651
581
  "jpeg"
652
582
  ],
583
+ "canonicalize": "lowercase",
653
584
  "default": "png",
654
585
  "required": false
655
586
  },
@@ -700,6 +631,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
700
631
  "enumValues": [
701
632
  "4k"
702
633
  ],
634
+ "canonicalize": "image-resolution-tier",
703
635
  "default": "4k",
704
636
  "required": false
705
637
  },
@@ -712,6 +644,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
712
644
  "png",
713
645
  "jpeg"
714
646
  ],
647
+ "canonicalize": "lowercase",
715
648
  "default": "png",
716
649
  "required": false
717
650
  },
@@ -770,6 +703,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
770
703
  "enumValues": [
771
704
  "1k"
772
705
  ],
706
+ "canonicalize": "image-resolution-tier",
773
707
  "default": "1k",
774
708
  "required": false
775
709
  },
@@ -782,6 +716,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
782
716
  "png",
783
717
  "jpeg"
784
718
  ],
719
+ "canonicalize": "lowercase",
785
720
  "default": "png",
786
721
  "required": false
787
722
  },
@@ -840,6 +775,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
840
775
  "enumValues": [
841
776
  "2k"
842
777
  ],
778
+ "canonicalize": "image-resolution-tier",
843
779
  "default": "2k",
844
780
  "required": false
845
781
  },
@@ -852,6 +788,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
852
788
  "png",
853
789
  "jpeg"
854
790
  ],
791
+ "canonicalize": "lowercase",
855
792
  "default": "png",
856
793
  "required": false
857
794
  },
@@ -910,6 +847,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
910
847
  "enumValues": [
911
848
  "4k"
912
849
  ],
850
+ "canonicalize": "image-resolution-tier",
913
851
  "default": "4k",
914
852
  "required": false
915
853
  },
@@ -922,6 +860,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
922
860
  "png",
923
861
  "jpeg"
924
862
  ],
863
+ "canonicalize": "lowercase",
925
864
  "default": "png",
926
865
  "required": false
927
866
  },
@@ -973,6 +912,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
973
912
  "jpeg",
974
913
  "png"
975
914
  ],
915
+ "canonicalize": "lowercase",
976
916
  "default": "png",
977
917
  "required": false
978
918
  },
@@ -1024,6 +964,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1024
964
  "jpeg",
1025
965
  "png"
1026
966
  ],
967
+ "canonicalize": "lowercase",
1027
968
  "default": "png",
1028
969
  "required": false
1029
970
  },
@@ -1092,6 +1033,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1092
1033
  "jpeg",
1093
1034
  "png"
1094
1035
  ],
1036
+ "canonicalize": "lowercase",
1095
1037
  "default": "png",
1096
1038
  "required": false
1097
1039
  },
@@ -1151,6 +1093,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1151
1093
  "jpeg",
1152
1094
  "png"
1153
1095
  ],
1096
+ "canonicalize": "lowercase",
1154
1097
  "default": "png",
1155
1098
  "required": false
1156
1099
  },
@@ -1181,6 +1124,85 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1181
1124
  "billingDimensions": [
1182
1125
  "billableUnitCount"
1183
1126
  ]
1127
+ },
1128
+ {
1129
+ "endpointKey": "image-higgsfield-soul-text",
1130
+ "provider": "higgsfield",
1131
+ "providerModelPath": "higgsfield-ai/soul/standard",
1132
+ "fields": [
1133
+ {
1134
+ "name": "prompt",
1135
+ "class": "intent",
1136
+ "flag": "--prompt",
1137
+ "type": "string",
1138
+ "required": true
1139
+ },
1140
+ {
1141
+ "name": "width_and_height",
1142
+ "class": "intent",
1143
+ "flag": "--width-and-height",
1144
+ "type": "string",
1145
+ "required": true
1146
+ },
1147
+ {
1148
+ "name": "quality",
1149
+ "class": "default",
1150
+ "flag": "--quality",
1151
+ "type": "string",
1152
+ "enumValues": [
1153
+ "720p",
1154
+ "1080p"
1155
+ ],
1156
+ "canonicalize": "lowercase",
1157
+ "default": "720p",
1158
+ "required": false
1159
+ },
1160
+ {
1161
+ "name": "style_id",
1162
+ "class": "intent",
1163
+ "flag": "--style-id",
1164
+ "type": "string",
1165
+ "required": false
1166
+ },
1167
+ {
1168
+ "name": "style_strength",
1169
+ "class": "intent",
1170
+ "flag": "--style-strength",
1171
+ "type": "number",
1172
+ "required": false
1173
+ },
1174
+ {
1175
+ "name": "seed",
1176
+ "class": "intent",
1177
+ "flag": "--seed",
1178
+ "type": "number",
1179
+ "required": false
1180
+ },
1181
+ {
1182
+ "name": "enhance_prompt",
1183
+ "class": "intent",
1184
+ "flag": "--enhance-prompt",
1185
+ "type": "boolean",
1186
+ "required": false
1187
+ },
1188
+ {
1189
+ "name": "operationId",
1190
+ "class": "runner-managed",
1191
+ "flag": null,
1192
+ "type": "string",
1193
+ "required": false
1194
+ },
1195
+ {
1196
+ "name": "quoteConfirmationToken",
1197
+ "class": "runner-managed",
1198
+ "flag": null,
1199
+ "type": "string",
1200
+ "required": false
1201
+ }
1202
+ ],
1203
+ "billingDimensions": [
1204
+ "quality"
1205
+ ]
1184
1206
  }
1185
1207
  ]
1186
1208
  }
@@ -1239,9 +1261,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1239
1261
  "capability": "media-generation",
1240
1262
  "endpointKeys": [
1241
1263
  "video-seedance-2-image",
1242
- "video-seedance-2-image-turbo",
1243
- "video-seedance-2-text",
1244
- "video-seedance-2-text-turbo"
1264
+ "video-seedance-2-text"
1245
1265
  ],
1246
1266
  "endpoints": [
1247
1267
  {
@@ -1273,76 +1293,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1273
1293
  "720p",
1274
1294
  "1080p"
1275
1295
  ],
1276
- "default": "720p",
1277
- "required": false
1278
- },
1279
- {
1280
- "name": "duration",
1281
- "class": "default",
1282
- "flag": null,
1283
- "type": "number",
1284
- "default": 5,
1285
- "required": false,
1286
- "min": 4,
1287
- "max": 15
1288
- },
1289
- {
1290
- "name": "operationId",
1291
- "class": "runner-managed",
1292
- "flag": null,
1293
- "type": "string",
1294
- "required": false
1295
- },
1296
- {
1297
- "name": "quoteConfirmationToken",
1298
- "class": "runner-managed",
1299
- "flag": null,
1300
- "type": "string",
1301
- "required": false
1302
- },
1303
- {
1304
- "name": "requestDimensions",
1305
- "class": "runner-managed",
1306
- "flag": null,
1307
- "type": "string",
1308
- "required": false
1309
- }
1310
- ],
1311
- "billingDimensions": [
1312
- "duration",
1313
- "resolution",
1314
- "referenceVideoCount",
1315
- "referenceVideoMode"
1316
- ]
1317
- },
1318
- {
1319
- "endpointKey": "video-seedance-2-image-turbo",
1320
- "provider": "wavespeed",
1321
- "providerModelPath": "bytedance/seedance-2.0/image-to-video-turbo",
1322
- "fields": [
1323
- {
1324
- "name": "prompt",
1325
- "class": "intent",
1326
- "flag": null,
1327
- "type": "string",
1328
- "required": true
1329
- },
1330
- {
1331
- "name": "image",
1332
- "class": "intent",
1333
- "flag": null,
1334
- "type": "media-url",
1335
- "required": true
1336
- },
1337
- {
1338
- "name": "resolution",
1339
- "class": "default",
1340
- "flag": null,
1341
- "type": "string",
1342
- "enumValues": [
1343
- "720p",
1344
- "1080p"
1345
- ],
1296
+ "canonicalize": "lowercase",
1346
1297
  "default": "720p",
1347
1298
  "required": false
1348
1299
  },
@@ -1407,6 +1358,7 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1407
1358
  "720p",
1408
1359
  "1080p"
1409
1360
  ],
1361
+ "canonicalize": "lowercase",
1410
1362
  "default": "720p",
1411
1363
  "required": false
1412
1364
  },
@@ -1452,97 +1404,27 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1452
1404
  "required": false
1453
1405
  },
1454
1406
  {
1455
- "name": "operationId",
1456
- "class": "runner-managed",
1457
- "flag": null,
1458
- "type": "string",
1459
- "required": false
1460
- },
1461
- {
1462
- "name": "quoteConfirmationToken",
1463
- "class": "runner-managed",
1464
- "flag": null,
1465
- "type": "string",
1466
- "required": false
1467
- },
1468
- {
1469
- "name": "requestDimensions",
1470
- "class": "runner-managed",
1471
- "flag": null,
1472
- "type": "string",
1473
- "required": false
1474
- }
1475
- ],
1476
- "billingDimensions": [
1477
- "duration",
1478
- "resolution",
1479
- "referenceVideoCount",
1480
- "referenceVideoMode"
1481
- ]
1482
- },
1483
- {
1484
- "endpointKey": "video-seedance-2-text-turbo",
1485
- "provider": "wavespeed",
1486
- "providerModelPath": "bytedance/seedance-2.0/text-to-video-turbo",
1487
- "fields": [
1488
- {
1489
- "name": "prompt",
1407
+ "name": "reference_audios",
1490
1408
  "class": "intent",
1491
1409
  "flag": null,
1492
- "type": "string",
1493
- "required": true
1494
- },
1495
- {
1496
- "name": "resolution",
1497
- "class": "default",
1498
- "flag": null,
1499
- "type": "string",
1500
- "enumValues": [
1501
- "720p",
1502
- "1080p"
1503
- ],
1504
- "default": "720p",
1505
- "required": false
1506
- },
1507
- {
1508
- "name": "aspect_ratio",
1509
- "class": "intent",
1510
- "flag": null,
1511
- "type": "string",
1512
- "enumValues": [
1513
- "21:9",
1514
- "16:9",
1515
- "4:3",
1516
- "1:1",
1517
- "3:4",
1518
- "9:16"
1519
- ],
1410
+ "type": "media-url",
1411
+ "repeatable": true,
1520
1412
  "required": false
1521
1413
  },
1522
1414
  {
1523
- "name": "duration",
1415
+ "name": "enable_web_search",
1524
1416
  "class": "default",
1525
1417
  "flag": null,
1526
- "type": "number",
1527
- "default": 5,
1528
- "required": false,
1529
- "min": 4,
1530
- "max": 15
1531
- },
1532
- {
1533
- "name": "reference_images",
1534
- "class": "intent",
1535
- "flag": null,
1536
- "type": "media-url",
1537
- "repeatable": true,
1418
+ "type": "boolean",
1419
+ "default": false,
1538
1420
  "required": false
1539
1421
  },
1540
1422
  {
1541
- "name": "reference_videos",
1542
- "class": "intent",
1423
+ "name": "generate_audio",
1424
+ "class": "default",
1543
1425
  "flag": null,
1544
- "type": "media-url",
1545
- "repeatable": true,
1426
+ "type": "boolean",
1427
+ "default": true,
1546
1428
  "required": false
1547
1429
  },
1548
1430
  {
@@ -1721,8 +1603,6 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1721
1603
  "video-kling-v3-0-pro-image",
1722
1604
  "video-kling-v3-0-std-text",
1723
1605
  "video-kling-v3-0-std-image",
1724
- "video-wanx2-1-t2v-turbo",
1725
- "video-wanx2-1-i2v-turbo",
1726
1606
  "video-infinitetalk",
1727
1607
  "video-kling-v2-6-pro-motion-control"
1728
1608
  ],
@@ -1993,148 +1873,6 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1993
1873
  "audioMode"
1994
1874
  ]
1995
1875
  },
1996
- {
1997
- "endpointKey": "video-wanx2-1-t2v-turbo",
1998
- "provider": "dashscope",
1999
- "providerModelPath": "wanx2.1-t2v-turbo",
2000
- "fields": [
2001
- {
2002
- "name": "prompt",
2003
- "class": "intent",
2004
- "flag": null,
2005
- "type": "string",
2006
- "required": true
2007
- },
2008
- {
2009
- "name": "aspect_ratio",
2010
- "class": "intent",
2011
- "flag": null,
2012
- "type": "string",
2013
- "enumValues": [
2014
- "9:16",
2015
- "16:9"
2016
- ],
2017
- "required": false
2018
- },
2019
- {
2020
- "name": "resolution",
2021
- "class": "default",
2022
- "flag": null,
2023
- "type": "string",
2024
- "enumValues": [
2025
- "480p",
2026
- "720p"
2027
- ],
2028
- "default": "720p",
2029
- "required": false
2030
- },
2031
- {
2032
- "name": "duration",
2033
- "class": "default",
2034
- "flag": null,
2035
- "type": "number",
2036
- "enumValues": [
2037
- "5"
2038
- ],
2039
- "default": 5,
2040
- "required": false
2041
- },
2042
- {
2043
- "name": "operationId",
2044
- "class": "runner-managed",
2045
- "flag": null,
2046
- "type": "string",
2047
- "required": false
2048
- },
2049
- {
2050
- "name": "quoteConfirmationToken",
2051
- "class": "runner-managed",
2052
- "flag": null,
2053
- "type": "string",
2054
- "required": false
2055
- },
2056
- {
2057
- "name": "requestDimensions",
2058
- "class": "runner-managed",
2059
- "flag": null,
2060
- "type": "string",
2061
- "required": false
2062
- }
2063
- ],
2064
- "billingDimensions": [
2065
- "resolution",
2066
- "duration"
2067
- ]
2068
- },
2069
- {
2070
- "endpointKey": "video-wanx2-1-i2v-turbo",
2071
- "provider": "dashscope",
2072
- "providerModelPath": "wanx2.1-i2v-turbo",
2073
- "fields": [
2074
- {
2075
- "name": "prompt",
2076
- "class": "intent",
2077
- "flag": null,
2078
- "type": "string",
2079
- "required": true
2080
- },
2081
- {
2082
- "name": "image",
2083
- "class": "intent",
2084
- "flag": null,
2085
- "type": "media-url",
2086
- "required": true
2087
- },
2088
- {
2089
- "name": "resolution",
2090
- "class": "default",
2091
- "flag": null,
2092
- "type": "string",
2093
- "enumValues": [
2094
- "480p",
2095
- "720p"
2096
- ],
2097
- "default": "720p",
2098
- "required": false
2099
- },
2100
- {
2101
- "name": "duration",
2102
- "class": "default",
2103
- "flag": null,
2104
- "type": "number",
2105
- "enumValues": [
2106
- "5"
2107
- ],
2108
- "default": 5,
2109
- "required": false
2110
- },
2111
- {
2112
- "name": "operationId",
2113
- "class": "runner-managed",
2114
- "flag": null,
2115
- "type": "string",
2116
- "required": false
2117
- },
2118
- {
2119
- "name": "quoteConfirmationToken",
2120
- "class": "runner-managed",
2121
- "flag": null,
2122
- "type": "string",
2123
- "required": false
2124
- },
2125
- {
2126
- "name": "requestDimensions",
2127
- "class": "runner-managed",
2128
- "flag": null,
2129
- "type": "string",
2130
- "required": false
2131
- }
2132
- ],
2133
- "billingDimensions": [
2134
- "resolution",
2135
- "duration"
2136
- ]
2137
- },
2138
1876
  {
2139
1877
  "endpointKey": "video-infinitetalk",
2140
1878
  "provider": "wavespeed",
@@ -0,0 +1,84 @@
1
+ // GENERATED from apps/web/lib/server/postplus-cli/hosted-field-validation-core.ts.
2
+ // Do not edit by hand. Run `pnpm hosted-execution-manifest:sync` to regenerate.
3
+ // Verbatim projection so the canonicalize + enum/range field-validation algorithm stays
4
+ // byte-identical to the Web boundary (the CLI submodule cannot import apps/web TS).
5
+ // k-tier normalization for image resolution ("4K" -> "4k").
6
+ export function canonicalizeImageResolution(value) {
7
+ const trimmed = value.trim();
8
+ const tier = trimmed.match(/^(\d+(?:\.\d+)?)\s*k$/iu);
9
+ return tier ? `${tier[1]}k` : trimmed;
10
+ }
11
+ export function canonicalizeLowercaseToken(value) {
12
+ return value.trim().toLowerCase();
13
+ }
14
+ // Which canonicalization a field uses is decided by the schema `canonicalize` hint —
15
+ // the single source both surfaces read — never re-guessed from the field name.
16
+ export function canonicalizeModelledFieldValue(field, value) {
17
+ switch (field.canonicalize) {
18
+ case 'image-resolution-tier':
19
+ return canonicalizeImageResolution(value);
20
+ case 'lowercase':
21
+ return canonicalizeLowercaseToken(value);
22
+ default:
23
+ return value;
24
+ }
25
+ }
26
+ function formatReceivedValue(raw) {
27
+ return typeof raw === 'string' ? `"${raw}"` : String(raw);
28
+ }
29
+ function assertModelledNumberFieldValue(endpointKey, field, raw, createError) {
30
+ const enumValues = field.enumValues && field.enumValues.length > 0 ? field.enumValues : null;
31
+ const constraint = enumValues
32
+ ? `must be one of ${enumValues.join(', ')}`
33
+ : `must be an integer from ${field.min} to ${field.max}`;
34
+ if (typeof raw !== 'number' || !Number.isFinite(raw)) {
35
+ throw createError(`${endpointKey} ${field.name} ${constraint}; received ${formatReceivedValue(raw)}.`);
36
+ }
37
+ if (enumValues) {
38
+ if (!enumValues.includes(String(raw))) {
39
+ throw createError(`${endpointKey} ${field.name} ${constraint}; received ${raw}.`);
40
+ }
41
+ return;
42
+ }
43
+ if (field.min === undefined || field.max === undefined) {
44
+ return;
45
+ }
46
+ if (!(Number.isInteger(raw) && raw >= field.min && raw <= field.max)) {
47
+ throw createError(`${endpointKey} ${field.name} ${constraint}; received ${raw}.`);
48
+ }
49
+ }
50
+ // Validates every advertised enum / numeric-range field present in the input against
51
+ // the field contract. Skips runner-managed fields (no caller input), fields with
52
+ // neither an enum nor a range, and fields the input omits. The string value is
53
+ // canonicalized with the schema hint before the enum membership check, so a mixed-case
54
+ // "720P"/"4K" still matches the lowercase registry enum while "english" still fails the
55
+ // Title-cased language enum. The error factory is injected: the Web boundary passes its
56
+ // typed invalid_request error, the CLI early validator passes a plain Error.
57
+ export function assertModelledFieldValuesInRange(endpointKey, fields, input, createError) {
58
+ for (const field of fields) {
59
+ if (field.class === 'runner-managed') {
60
+ continue;
61
+ }
62
+ const enumValues = field.enumValues && field.enumValues.length > 0 ? field.enumValues : null;
63
+ const hasRange = field.min !== undefined && field.max !== undefined;
64
+ if (!enumValues && !hasRange) {
65
+ continue;
66
+ }
67
+ if (!Object.hasOwn(input, field.name)) {
68
+ continue;
69
+ }
70
+ if (field.type === 'number') {
71
+ assertModelledNumberFieldValue(endpointKey, field, input[field.name], createError);
72
+ continue;
73
+ }
74
+ const raw = input[field.name];
75
+ if (typeof raw !== 'string' || !raw.trim()) {
76
+ continue;
77
+ }
78
+ const value = raw.trim();
79
+ if (enumValues &&
80
+ !enumValues.includes(canonicalizeModelledFieldValue(field, value))) {
81
+ throw createError(`${endpointKey} ${field.name} must be one of ${enumValues.join(', ')}; received "${value}".`);
82
+ }
83
+ }
84
+ }
@@ -5,8 +5,9 @@ import path from 'node:path';
5
5
  import { resolveFreshRemoteAuth } from './auth-session.js';
6
6
  import { sendAuthedCloudRequest } from './authed-cloud-request.js';
7
7
  import { formatPostPlusCompatibilityError } from './client-compatibility.js';
8
+ import { assertModelledFieldValuesInRange } from './hosted-field-validation.js';
8
9
  import { buildVerbTargetIndex, } from './hosted-manifest-index.js';
9
- import { buildHostedRequestSchemaReport, buildMediaGenerationRequestDimensions, } from './hosted-request-schemas.js';
10
+ import { buildHostedRequestSchemaReport } from './hosted-request-schemas.js';
10
11
  import { readLargeCreditQuoteConfirmationChallenge, } from './quote-confirmation.js';
11
12
  // Manifest-driven verb grammar indexes (SSOT projected from apps/web +
12
13
  // public-skill-metadata via the generated manifest). The verb/flag grammar,
@@ -176,6 +177,11 @@ async function runMediaVerbFlags(args) {
176
177
  flags,
177
178
  verb,
178
179
  });
180
+ // Schema-driven early validation reads the manifest enum/range + canonicalize hint
181
+ // for every modelled field (a single source shared with the Web boundary, which
182
+ // stays authoritative). It runs on the built input so a mixed-case "4K"/"High"
183
+ // passes while an out-of-enum value fast-fails locally before the hosted call.
184
+ assertModelledFieldValuesInRange(endpointKey, fields, input);
179
185
  return submitMediaGenerationRequest({
180
186
  capability: resolved.capability,
181
187
  endpointKey,
@@ -224,6 +230,12 @@ async function runMediaVerbRequestJson(args) {
224
230
  throw new Error(`media ${verb} ${endpointKey} input must not include runner-managed field "${field.name}"; the CLI mints or derives it.`);
225
231
  }
226
232
  }
233
+ // Schema-driven early validation reads the manifest enum/range + canonicalize hint
234
+ // for every modelled field (a single source shared with the Web boundary, which
235
+ // stays authoritative). It runs on the agent-authored body so an out-of-enum
236
+ // resolution ("999p") fast-fails locally before the hosted call while a mixed-case
237
+ // "720P" passes.
238
+ assertModelledFieldValuesInRange(endpointKey, endpoint.fields, input);
227
239
  return submitMediaGenerationRequest({
228
240
  capability: resolved.capability,
229
241
  endpointKey,
@@ -480,6 +492,9 @@ Usage:
480
492
  // Shared submit path for both surfaces: wrap the media input, derive billing
481
493
  // dimensions from endpointKey + input, and POST to the Web boundary.
482
494
  function submitMediaGenerationRequest(params) {
495
+ // Billing dimensions are derived solely at the Web boundary from
496
+ // (endpointKey, input); the CLI sends only the payload. The Web request schema
497
+ // rejects any caller-supplied `requestDimensions` (single source of truth).
483
498
  const body = {
484
499
  capability: params.capability,
485
500
  endpointKey: params.endpointKey,
@@ -487,7 +502,6 @@ function submitMediaGenerationRequest(params) {
487
502
  operation: 'request',
488
503
  operationId: params.operationId,
489
504
  quoteConfirmationToken: params.quoteConfirmationToken ?? undefined,
490
- requestDimensions: buildMediaGenerationRequestDimensions(params.endpointKey, params.input),
491
505
  };
492
506
  return runHostedCommand({
493
507
  request: () => postHostedJson({
@@ -567,9 +581,11 @@ function buildMediaVerbInput(input) {
567
581
  }
568
582
  continue;
569
583
  }
570
- if (field.enumValues && !field.enumValues.includes(raw)) {
571
- throw new Error(`--${key} must be one of ${field.enumValues.join(', ')}.`);
572
- }
584
+ // Enum / numeric-range membership (with canonicalize-faithful casing) is gated
585
+ // once by assertModelledFieldValuesInRange after the input is built — not here —
586
+ // so a mixed-case "4K" is not wrongly rejected by a raw includes() check. This
587
+ // path only parses the flag string into its typed value; the number floor below
588
+ // keeps a non-range number field (e.g. transcription duration_seconds) positive.
573
589
  if (field.type === 'number') {
574
590
  const parsed = Number(raw);
575
591
  if (!Number.isFinite(parsed) || parsed <= 0) {
@@ -0,0 +1,13 @@
1
+ // Schema-driven early field validation (issue #475). The canonicalize + enum/range
2
+ // algorithm is the SSOT `hosted-field-validation-core`, authored in apps/web and
3
+ // projected VERBATIM into ./generated by the hosted-execution-manifest codegen — the CLI
4
+ // submodule cannot import apps/web TS, and a hand-copy here would let the casing / range
5
+ // rules drift from the Web boundary. This module only injects the CLI's plain-Error
6
+ // factory and keeps the established (endpointKey, fields, input) signature its callers
7
+ // use. The Web boundary stays the AUTHORITATIVE gate; this is pre-submit feedback so the
8
+ // agent gets an immediate field-level error (e.g. seedance resolution "999p") instead of
9
+ // waiting for the round-trip.
10
+ import { assertModelledFieldValuesInRange as assertModelledFieldValuesInRangeCore } from './generated/hosted-field-validation-core.generated.js';
11
+ export function assertModelledFieldValuesInRange(endpointKey, fields, input) {
12
+ assertModelledFieldValuesInRangeCore(endpointKey, fields, input, (message) => new Error(message));
13
+ }
@@ -1,4 +1,3 @@
1
- import { Buffer } from 'node:buffer';
2
1
  import { findMediaEndpoint, manifestTargetKeys, } from './hosted-manifest-index.js';
3
2
  const JSON_OBJECT_SCHEMA = {
4
3
  additionalProperties: true,
@@ -29,6 +28,9 @@ function toFieldContract(field) {
29
28
  if (field.max !== undefined) {
30
29
  contract.max = field.max;
31
30
  }
31
+ if (field.canonicalize) {
32
+ contract.canonicalize = field.canonicalize;
33
+ }
32
34
  if (field.default !== undefined) {
33
35
  contract.default = field.default;
34
36
  }
@@ -208,113 +210,6 @@ function requireMediaEndpoint(endpointKey) {
208
210
  }
209
211
  return endpoint;
210
212
  }
211
- const MANIFEST_FIELD_DEFAULTS = buildManifestFieldDefaults();
212
- const MANIFEST_DERIVED_DIMENSIONS = buildManifestDerivedDimensions();
213
- function buildManifestFieldDefaults() {
214
- const index = new Map();
215
- for (const key of manifestTargetKeys('media', 'media-generation')) {
216
- const endpoint = findMediaEndpoint(key);
217
- if (!endpoint) {
218
- continue;
219
- }
220
- const byField = new Map();
221
- for (const field of endpoint.fields) {
222
- if (field.default !== undefined) {
223
- byField.set(field.name, field.default);
224
- }
225
- }
226
- index.set(key, byField);
227
- }
228
- return index;
229
- }
230
- function manifestFieldDefault(endpointKey, fieldName) {
231
- return MANIFEST_FIELD_DEFAULTS.get(endpointKey)?.get(fieldName);
232
- }
233
- function buildManifestDerivedDimensions() {
234
- const index = new Map();
235
- for (const key of manifestTargetKeys('media', 'media-generation')) {
236
- const endpoint = findMediaEndpoint(key);
237
- if (!endpoint) {
238
- continue;
239
- }
240
- const derived = endpoint.fields.flatMap((field) => field.class === 'runner-managed' && field.derivedFrom
241
- ? [{ fieldName: field.name, sourceName: field.derivedFrom }]
242
- : []);
243
- if (derived.length > 0) {
244
- index.set(key, derived);
245
- }
246
- }
247
- return index;
248
- }
249
- export function buildMediaGenerationRequestDimensions(endpointKey, input) {
250
- const dimensions = {
251
- billableUnitCount: 1,
252
- operationKey: endpointKey,
253
- };
254
- for (const derived of MANIFEST_DERIVED_DIMENSIONS.get(endpointKey) ?? []) {
255
- const value = input[derived.sourceName] ??
256
- manifestFieldDefault(endpointKey, derived.sourceName);
257
- if (value !== undefined) {
258
- dimensions[derived.fieldName] = value;
259
- }
260
- }
261
- if (endpointKey.startsWith('image-')) {
262
- const resolution = typeof input.resolution === 'string' && input.resolution.trim()
263
- ? input.resolution.trim()
264
- : manifestFieldDefault(endpointKey, 'resolution');
265
- const quality = typeof input.quality === 'string' && input.quality.trim()
266
- ? input.quality.trim()
267
- : manifestFieldDefault(endpointKey, 'quality');
268
- if (typeof resolution === 'string') {
269
- dimensions.imageSize = resolution;
270
- }
271
- if (typeof quality === 'string') {
272
- dimensions.quality = quality;
273
- }
274
- }
275
- if (endpointKey.startsWith('video-')) {
276
- const manifestResolution = manifestFieldDefault(endpointKey, 'resolution');
277
- const duration = readPositiveNumber(input.duration) ??
278
- readPositiveNumber(manifestFieldDefault(endpointKey, 'duration')) ??
279
- 5;
280
- const resolution = typeof input.resolution === 'string' && input.resolution.trim()
281
- ? input.resolution.trim()
282
- : typeof manifestResolution === 'string'
283
- ? manifestResolution
284
- : '720p';
285
- dimensions.audioMode =
286
- endpointKey.startsWith('video-kling-v3-0-') && input.sound !== true
287
- ? 'off'
288
- : 'on';
289
- dimensions.duration = Math.ceil(duration);
290
- dimensions.requestBytes = Buffer.byteLength(JSON.stringify(input));
291
- dimensions.resolution = resolution;
292
- if (endpointKey.startsWith('video-seedance-2-')) {
293
- const referenceVideoCount = Array.isArray(input.reference_videos)
294
- ? input.reference_videos.length
295
- : 0;
296
- dimensions.referenceVideoCount = referenceVideoCount;
297
- dimensions.referenceVideoMode =
298
- referenceVideoCount > 0
299
- ? 'with_reference_videos'
300
- : 'without_reference_videos';
301
- }
302
- if (endpointKey === 'video-kling-v2-6-pro-motion-control') {
303
- dimensions.characterOrientation =
304
- typeof input.character_orientation === 'string'
305
- ? input.character_orientation
306
- : 'image';
307
- dimensions.motionControlMode = 'reference_motion_transfer';
308
- }
309
- }
310
- return dimensions;
311
- }
312
- function readPositiveNumber(value) {
313
- if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
314
- return null;
315
- }
316
- return value;
317
- }
318
213
  function buildPublishSchemaReport() {
319
214
  const operations = manifestTargetKeys('publish', 'social-publishing');
320
215
  return {
@@ -1,6 +1,6 @@
1
1
  import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
2
2
  import { dirname, join } from 'node:path';
3
- import { readCurrentCliVersion } from './client-compatibility.js';
3
+ import { POSTPLUS_CLI_UPDATE_COMMAND, readCurrentCliVersion, } from './client-compatibility.js';
4
4
  import { runInteractiveCommand as runDefaultInteractiveCommand, } from './command-runner.js';
5
5
  import { getPostPlusConfigDir, readManagedSkillBaseline, } from './local-state.js';
6
6
  import { POSTPLUS_SKILLS_REPO, loadPublicSkillCatalog, } from './skill-catalog.js';
@@ -8,7 +8,6 @@ const UPDATE_CHECK_TTL_MS = 24 * 60 * 60 * 1000;
8
8
  const UPDATE_CHECK_CACHE_FILE = 'update-check.json';
9
9
  const NPM_PACKAGE_NAME = '@postplus/cli';
10
10
  const NPM_LATEST_URL = `https://registry.npmjs.org/${encodeURIComponent(NPM_PACKAGE_NAME)}/latest`;
11
- export const POSTPLUS_CLI_UPDATE_COMMAND = 'npm install -g @postplus/cli@latest';
12
11
  const POSTPLUS_CLI_UPDATE_ARGS = ['install', '-g', '@postplus/cli@latest'];
13
12
  export async function generateUpdateStatusReport(input = {}, dependencies = {
14
13
  fetchFn: fetch,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postplus/cli",
3
- "version": "0.1.44",
3
+ "version": "0.1.46",
4
4
  "packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017",
5
5
  "type": "module",
6
6
  "description": "PostPlus CLI for PostPlus Cloud auth, status, and diagnostics.",
@@ -18,6 +18,8 @@
18
18
  "build/doctor.js",
19
19
  "build/hosted-domain-commands.js",
20
20
  "build/generated/hosted-execution-manifest.generated.js",
21
+ "build/generated/hosted-field-validation-core.generated.js",
22
+ "build/hosted-field-validation.js",
21
23
  "build/hosted-manifest-index.js",
22
24
  "build/hosted-release.js",
23
25
  "build/hosted-request-schemas.js",