@postplus/cli 0.1.45 → 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.'
@@ -169,7 +169,8 @@ export const HOSTED_EXECUTION_MANIFESTS = {
169
169
  "image-seedream-v5-lite-text",
170
170
  "image-seedream-v5-lite-sequential",
171
171
  "image-seedream-v5-lite-edit",
172
- "image-seedream-v5-lite-edit-sequential"
172
+ "image-seedream-v5-lite-edit-sequential",
173
+ "image-higgsfield-soul-text"
173
174
  ],
174
175
  "endpoints": [
175
176
  {
@@ -1123,6 +1124,85 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1123
1124
  "billingDimensions": [
1124
1125
  "billableUnitCount"
1125
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
+ ]
1126
1206
  }
1127
1207
  ]
1128
1208
  }
@@ -1323,6 +1403,30 @@ export const HOSTED_EXECUTION_MANIFESTS = {
1323
1403
  "repeatable": true,
1324
1404
  "required": false
1325
1405
  },
1406
+ {
1407
+ "name": "reference_audios",
1408
+ "class": "intent",
1409
+ "flag": null,
1410
+ "type": "media-url",
1411
+ "repeatable": true,
1412
+ "required": false
1413
+ },
1414
+ {
1415
+ "name": "enable_web_search",
1416
+ "class": "default",
1417
+ "flag": null,
1418
+ "type": "boolean",
1419
+ "default": false,
1420
+ "required": false
1421
+ },
1422
+ {
1423
+ "name": "generate_audio",
1424
+ "class": "default",
1425
+ "flag": null,
1426
+ "type": "boolean",
1427
+ "default": true,
1428
+ "required": false
1429
+ },
1326
1430
  {
1327
1431
  "name": "operationId",
1328
1432
  "class": "runner-managed",
@@ -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
+ }
@@ -7,7 +7,7 @@ import { sendAuthedCloudRequest } from './authed-cloud-request.js';
7
7
  import { formatPostPlusCompatibilityError } from './client-compatibility.js';
8
8
  import { assertModelledFieldValuesInRange } from './hosted-field-validation.js';
9
9
  import { buildVerbTargetIndex, } from './hosted-manifest-index.js';
10
- import { buildHostedRequestSchemaReport, buildMediaGenerationRequestDimensions, } from './hosted-request-schemas.js';
10
+ import { buildHostedRequestSchemaReport } from './hosted-request-schemas.js';
11
11
  import { readLargeCreditQuoteConfirmationChallenge, } from './quote-confirmation.js';
12
12
  // Manifest-driven verb grammar indexes (SSOT projected from apps/web +
13
13
  // public-skill-metadata via the generated manifest). The verb/flag grammar,
@@ -492,6 +492,9 @@ Usage:
492
492
  // Shared submit path for both surfaces: wrap the media input, derive billing
493
493
  // dimensions from endpointKey + input, and POST to the Web boundary.
494
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).
495
498
  const body = {
496
499
  capability: params.capability,
497
500
  endpointKey: params.endpointKey,
@@ -499,7 +502,6 @@ function submitMediaGenerationRequest(params) {
499
502
  operation: 'request',
500
503
  operationId: params.operationId,
501
504
  quoteConfirmationToken: params.quoteConfirmationToken ?? undefined,
502
- requestDimensions: buildMediaGenerationRequestDimensions(params.endpointKey, params.input),
503
505
  };
504
506
  return runHostedCommand({
505
507
  request: () => postHostedJson({
@@ -1,93 +1,13 @@
1
- // Schema-driven early field validation (issue #475). Mirrors the Web boundary's
2
- // assertModelledFieldValuesInRange: every enum / numeric-range field an endpoint
3
- // advertises in the generated execution manifest — the same EnvelopeFieldSpec the
4
- // Web validator reads is checked here BEFORE the request is posted, so the agent
5
- // gets an immediate field-level error (e.g. seedance resolution "999p") instead of
6
- // waiting for the round-trip. The Web boundary stays the AUTHORITATIVE gate; this is
7
- // only pre-submit feedback.
8
- //
9
- // Casing-faithfulness is the reason this cannot be a CLI-side island: the per-field
10
- // canonicalization rule is read from the manifest `canonicalize` hint, the SAME
11
- // single source the Web validator reads, so "720P" / "4K" pass and "english" /
12
- // "999p" fail exactly as they do on the boundary. The two canonicalize functions
13
- // below are stable 3-line algorithms; WHICH field uses WHICH is decided by the
14
- // schema hint, never re-guessed here.
15
- // k-tier normalization for image resolution ("4K" -> "4k"). Mirrors the Web
16
- // canonicalizeImageResolution exactly.
17
- function canonicalizeImageResolution(value) {
18
- const trimmed = value.trim();
19
- const tier = trimmed.match(/^(\d+(?:\.\d+)?)\s*k$/iu);
20
- return tier ? `${tier[1]}k` : trimmed;
21
- }
22
- function canonicalizeLowercaseToken(value) {
23
- return value.trim().toLowerCase();
24
- }
25
- function canonicalizeModelledFieldValue(field, value) {
26
- switch (field.canonicalize) {
27
- case 'image-resolution-tier':
28
- return canonicalizeImageResolution(value);
29
- case 'lowercase':
30
- return canonicalizeLowercaseToken(value);
31
- default:
32
- return value;
33
- }
34
- }
35
- function isIntegerInRange(min, max, value) {
36
- return Number.isInteger(value) && value >= min && value <= max;
37
- }
38
- function formatReceivedValue(raw) {
39
- return typeof raw === 'string' ? `"${raw}"` : String(raw);
40
- }
41
- function assertModelledNumberFieldValue(endpointKey, field, raw) {
42
- const enumValues = field.enumValues && field.enumValues.length > 0 ? field.enumValues : null;
43
- const constraint = enumValues
44
- ? `must be one of ${enumValues.join(', ')}`
45
- : `must be an integer from ${field.min} to ${field.max}`;
46
- if (typeof raw !== 'number' || !Number.isFinite(raw)) {
47
- throw new Error(`${endpointKey} ${field.name} ${constraint}; received ${formatReceivedValue(raw)}.`);
48
- }
49
- if (enumValues) {
50
- if (!enumValues.includes(String(raw))) {
51
- throw new Error(`${endpointKey} ${field.name} ${constraint}; received ${raw}.`);
52
- }
53
- return;
54
- }
55
- if (field.min === undefined || field.max === undefined) {
56
- return;
57
- }
58
- if (!isIntegerInRange(field.min, field.max, raw)) {
59
- throw new Error(`${endpointKey} ${field.name} ${constraint}; received ${raw}.`);
60
- }
61
- }
62
- // Validates every advertised enum / numeric-range field present in the input against
63
- // the manifest contract. Skips runner-managed fields (no caller input), fields with
64
- // neither an enum nor a range, and fields the input omits — exactly mirroring the Web
65
- // boundary so a value the CLI accepts the boundary also accepts, and vice versa.
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';
66
11
  export function assertModelledFieldValuesInRange(endpointKey, fields, input) {
67
- for (const field of fields) {
68
- if (field.class === 'runner-managed') {
69
- continue;
70
- }
71
- const enumValues = field.enumValues && field.enumValues.length > 0 ? field.enumValues : null;
72
- const hasRange = field.min !== undefined && field.max !== undefined;
73
- if (!enumValues && !hasRange) {
74
- continue;
75
- }
76
- if (!Object.hasOwn(input, field.name)) {
77
- continue;
78
- }
79
- if (field.type === 'number') {
80
- assertModelledNumberFieldValue(endpointKey, field, input[field.name]);
81
- continue;
82
- }
83
- const raw = input[field.name];
84
- if (typeof raw !== 'string' || !raw.trim()) {
85
- continue;
86
- }
87
- const value = raw.trim();
88
- if (enumValues &&
89
- !enumValues.includes(canonicalizeModelledFieldValue(field, value))) {
90
- throw new Error(`${endpointKey} ${field.name} must be one of ${enumValues.join(', ')}; received "${value}".`);
91
- }
92
- }
12
+ assertModelledFieldValuesInRangeCore(endpointKey, fields, input, (message) => new Error(message));
93
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,
@@ -211,113 +210,6 @@ function requireMediaEndpoint(endpointKey) {
211
210
  }
212
211
  return endpoint;
213
212
  }
214
- const MANIFEST_FIELD_DEFAULTS = buildManifestFieldDefaults();
215
- const MANIFEST_DERIVED_DIMENSIONS = buildManifestDerivedDimensions();
216
- function buildManifestFieldDefaults() {
217
- const index = new Map();
218
- for (const key of manifestTargetKeys('media', 'media-generation')) {
219
- const endpoint = findMediaEndpoint(key);
220
- if (!endpoint) {
221
- continue;
222
- }
223
- const byField = new Map();
224
- for (const field of endpoint.fields) {
225
- if (field.default !== undefined) {
226
- byField.set(field.name, field.default);
227
- }
228
- }
229
- index.set(key, byField);
230
- }
231
- return index;
232
- }
233
- function manifestFieldDefault(endpointKey, fieldName) {
234
- return MANIFEST_FIELD_DEFAULTS.get(endpointKey)?.get(fieldName);
235
- }
236
- function buildManifestDerivedDimensions() {
237
- const index = new Map();
238
- for (const key of manifestTargetKeys('media', 'media-generation')) {
239
- const endpoint = findMediaEndpoint(key);
240
- if (!endpoint) {
241
- continue;
242
- }
243
- const derived = endpoint.fields.flatMap((field) => field.class === 'runner-managed' && field.derivedFrom
244
- ? [{ fieldName: field.name, sourceName: field.derivedFrom }]
245
- : []);
246
- if (derived.length > 0) {
247
- index.set(key, derived);
248
- }
249
- }
250
- return index;
251
- }
252
- export function buildMediaGenerationRequestDimensions(endpointKey, input) {
253
- const dimensions = {
254
- billableUnitCount: 1,
255
- operationKey: endpointKey,
256
- };
257
- for (const derived of MANIFEST_DERIVED_DIMENSIONS.get(endpointKey) ?? []) {
258
- const value = input[derived.sourceName] ??
259
- manifestFieldDefault(endpointKey, derived.sourceName);
260
- if (value !== undefined) {
261
- dimensions[derived.fieldName] = value;
262
- }
263
- }
264
- if (endpointKey.startsWith('image-')) {
265
- const resolution = typeof input.resolution === 'string' && input.resolution.trim()
266
- ? input.resolution.trim()
267
- : manifestFieldDefault(endpointKey, 'resolution');
268
- const quality = typeof input.quality === 'string' && input.quality.trim()
269
- ? input.quality.trim()
270
- : manifestFieldDefault(endpointKey, 'quality');
271
- if (typeof resolution === 'string') {
272
- dimensions.imageSize = resolution;
273
- }
274
- if (typeof quality === 'string') {
275
- dimensions.quality = quality;
276
- }
277
- }
278
- if (endpointKey.startsWith('video-')) {
279
- const manifestResolution = manifestFieldDefault(endpointKey, 'resolution');
280
- const duration = readPositiveNumber(input.duration) ??
281
- readPositiveNumber(manifestFieldDefault(endpointKey, 'duration')) ??
282
- 5;
283
- const resolution = typeof input.resolution === 'string' && input.resolution.trim()
284
- ? input.resolution.trim()
285
- : typeof manifestResolution === 'string'
286
- ? manifestResolution
287
- : '720p';
288
- dimensions.audioMode =
289
- endpointKey.startsWith('video-kling-v3-0-') && input.sound !== true
290
- ? 'off'
291
- : 'on';
292
- dimensions.duration = Math.ceil(duration);
293
- dimensions.requestBytes = Buffer.byteLength(JSON.stringify(input));
294
- dimensions.resolution = resolution;
295
- if (endpointKey.startsWith('video-seedance-2-')) {
296
- const referenceVideoCount = Array.isArray(input.reference_videos)
297
- ? input.reference_videos.length
298
- : 0;
299
- dimensions.referenceVideoCount = referenceVideoCount;
300
- dimensions.referenceVideoMode =
301
- referenceVideoCount > 0
302
- ? 'with_reference_videos'
303
- : 'without_reference_videos';
304
- }
305
- if (endpointKey === 'video-kling-v2-6-pro-motion-control') {
306
- dimensions.characterOrientation =
307
- typeof input.character_orientation === 'string'
308
- ? input.character_orientation
309
- : 'image';
310
- dimensions.motionControlMode = 'reference_motion_transfer';
311
- }
312
- }
313
- return dimensions;
314
- }
315
- function readPositiveNumber(value) {
316
- if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
317
- return null;
318
- }
319
- return value;
320
- }
321
213
  function buildPublishSchemaReport() {
322
214
  const operations = manifestTargetKeys('publish', 'social-publishing');
323
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.45",
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,7 @@
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",
21
22
  "build/hosted-field-validation.js",
22
23
  "build/hosted-manifest-index.js",
23
24
  "build/hosted-release.js",