wp-typia 0.20.2 → 0.20.3

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.
@@ -54,7 +54,7 @@ import {
54
54
  } from "./cli-sj5mtyzj.js";
55
55
  import {
56
56
  readWorkspaceInventory
57
- } from "./cli-rg481yks.js";
57
+ } from "./cli-3w3qxq9w.js";
58
58
  import {
59
59
  getInvalidWorkspaceProjectReason,
60
60
  tryResolveWorkspaceProject
@@ -171027,6 +171027,8 @@ var ADD_KIND_IDS = [
171027
171027
  "pattern",
171028
171028
  "binding-source",
171029
171029
  "rest-resource",
171030
+ "ability",
171031
+ "ai-feature",
171030
171032
  "hooked-block",
171031
171033
  "editor-plugin"
171032
171034
  ];
@@ -171229,6 +171231,32 @@ function assertRestResourceDoesNotExist(projectDir, restResourceSlug, inventory)
171229
171231
  throw new Error(`A REST resource inventory entry already exists for ${restResourceSlug}. Choose a different name.`);
171230
171232
  }
171231
171233
  }
171234
+ function assertAbilityDoesNotExist(projectDir, abilitySlug, inventory) {
171235
+ const abilityDir = path.join(projectDir, "src", "abilities", abilitySlug);
171236
+ const abilityPhpPath = path.join(projectDir, "inc", "abilities", `${abilitySlug}.php`);
171237
+ if (fs.existsSync(abilityDir)) {
171238
+ throw new Error(`An ability scaffold already exists at ${path.relative(projectDir, abilityDir)}. Choose a different name.`);
171239
+ }
171240
+ if (fs.existsSync(abilityPhpPath)) {
171241
+ throw new Error(`An ability bootstrap already exists at ${path.relative(projectDir, abilityPhpPath)}. Choose a different name.`);
171242
+ }
171243
+ if (inventory.abilities.some((entry) => entry.slug === abilitySlug)) {
171244
+ throw new Error(`An ability inventory entry already exists for ${abilitySlug}. Choose a different name.`);
171245
+ }
171246
+ }
171247
+ function assertAiFeatureDoesNotExist(projectDir, aiFeatureSlug, inventory) {
171248
+ const aiFeatureDir = path.join(projectDir, "src", "ai-features", aiFeatureSlug);
171249
+ const aiFeaturePhpPath = path.join(projectDir, "inc", "ai-features", `${aiFeatureSlug}.php`);
171250
+ if (fs.existsSync(aiFeatureDir)) {
171251
+ throw new Error(`An AI feature already exists at ${path.relative(projectDir, aiFeatureDir)}. Choose a different name.`);
171252
+ }
171253
+ if (fs.existsSync(aiFeaturePhpPath)) {
171254
+ throw new Error(`An AI feature bootstrap already exists at ${path.relative(projectDir, aiFeaturePhpPath)}. Choose a different name.`);
171255
+ }
171256
+ if (inventory.aiFeatures.some((entry) => entry.slug === aiFeatureSlug)) {
171257
+ throw new Error(`An AI feature inventory entry already exists for ${aiFeatureSlug}. Choose a different name.`);
171258
+ }
171259
+ }
171232
171260
  function assertEditorPluginDoesNotExist(projectDir, editorPluginSlug, inventory) {
171233
171261
  const editorPluginDir = path.join(projectDir, "src", "editor-plugins", editorPluginSlug);
171234
171262
  if (fs.existsSync(editorPluginDir)) {
@@ -171245,6 +171273,8 @@ function formatAddHelpText() {
171245
171273
  wp-typia add pattern <name> [--dry-run]
171246
171274
  wp-typia add binding-source <name> [--dry-run]
171247
171275
  wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--dry-run]
171276
+ wp-typia add ability <name> [--dry-run]
171277
+ wp-typia add ai-feature <name> [--namespace <vendor/v1>] [--dry-run]
171248
171278
  wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <${HOOKED_BLOCK_POSITION_IDS.join("|")}> [--dry-run]
171249
171279
  wp-typia add editor-plugin <name> [--slot <${EDITOR_PLUGIN_SLOT_IDS.join("|")}>] [--dry-run]
171250
171280
 
@@ -171256,6 +171286,8 @@ Notes:
171256
171286
  \`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/\`.
171257
171287
  \`add binding-source\` scaffolds shared PHP and editor registration under \`src/bindings/\`.
171258
171288
  \`add rest-resource\` scaffolds plugin-level TypeScript REST contracts under \`src/rest/\` and PHP route glue under \`inc/rest/\`.
171289
+ \`add ability\` scaffolds typed workflow abilities under \`src/abilities/\` and server registration under \`inc/abilities/\`.
171290
+ \`add ai-feature\` scaffolds server-owned AI feature endpoints under \`src/ai-features/\` and PHP route glue under \`inc/ai-features/\`.
171259
171291
  \`add hooked-block\` patches an existing workspace block's \`block.json\` \`blockHooks\` metadata.
171260
171292
  \`add editor-plugin\` scaffolds a document-level editor extension under \`src/editor-plugins/\`.`;
171261
171293
  }
@@ -171270,6 +171302,8 @@ var VARIATION_CONFIG_ENTRY_MARKER = "\t// wp-typia add variation entries";
171270
171302
  var PATTERN_CONFIG_ENTRY_MARKER = "\t// wp-typia add pattern entries";
171271
171303
  var BINDING_SOURCE_CONFIG_ENTRY_MARKER = "\t// wp-typia add binding-source entries";
171272
171304
  var REST_RESOURCE_CONFIG_ENTRY_MARKER = "\t// wp-typia add rest-resource entries";
171305
+ var ABILITY_CONFIG_ENTRY_MARKER = "\t// wp-typia add ability entries";
171306
+ var AI_FEATURE_CONFIG_ENTRY_MARKER = "\t// wp-typia add ai-feature entries";
171273
171307
  var EDITOR_PLUGIN_CONFIG_ENTRY_MARKER = "\t// wp-typia add editor-plugin entries";
171274
171308
  var VARIATIONS_INTERFACE_SECTION = `
171275
171309
 
@@ -171336,6 +171370,62 @@ export const REST_RESOURCES: WorkspaceRestResourceConfig[] = [
171336
171370
  // wp-typia add rest-resource entries
171337
171371
  ];
171338
171372
  `;
171373
+ var WORKSPACE_COMPATIBILITY_CONFIG_FIELD = ` compatibility?: {
171374
+ hardMinimums: {
171375
+ php?: string;
171376
+ wordpress?: string;
171377
+ };
171378
+ mode: 'baseline' | 'optional' | 'required';
171379
+ optionalFeatures: string[];
171380
+ requiredFeatures: string[];
171381
+ runtimeGates: string[];
171382
+ };
171383
+ `;
171384
+ var ABILITIES_INTERFACE_SECTION = `
171385
+
171386
+ export interface WorkspaceAbilityConfig {
171387
+ clientFile: string;
171388
+ ${WORKSPACE_COMPATIBILITY_CONFIG_FIELD} configFile: string;
171389
+ dataFile: string;
171390
+ inputSchemaFile: string;
171391
+ inputTypeName: string;
171392
+ outputSchemaFile: string;
171393
+ outputTypeName: string;
171394
+ phpFile: string;
171395
+ slug: string;
171396
+ typesFile: string;
171397
+ }
171398
+ `;
171399
+ var ABILITIES_CONST_SECTION = `
171400
+
171401
+ export const ABILITIES: WorkspaceAbilityConfig[] = [
171402
+ // wp-typia add ability entries
171403
+ ];
171404
+ `;
171405
+ var AI_FEATURES_INTERFACE_SECTION = `
171406
+
171407
+ export interface WorkspaceAiFeatureConfig {
171408
+ aiSchemaFile: string;
171409
+ apiFile: string;
171410
+ clientFile: string;
171411
+ ${WORKSPACE_COMPATIBILITY_CONFIG_FIELD} dataFile: string;
171412
+ namespace: string;
171413
+ openApiFile: string;
171414
+ phpFile: string;
171415
+ restManifest?: ReturnType<
171416
+ typeof import( '@wp-typia/block-runtime/metadata-core' ).defineEndpointManifest
171417
+ >;
171418
+ slug: string;
171419
+ typesFile: string;
171420
+ validatorsFile: string;
171421
+ }
171422
+ `;
171423
+ var AI_FEATURES_CONST_SECTION = `
171424
+
171425
+ export const AI_FEATURES: WorkspaceAiFeatureConfig[] = [
171426
+ // wp-typia add ai-feature entries
171427
+ ];
171428
+ `;
171339
171429
  var EDITOR_PLUGINS_INTERFACE_SECTION = `
171340
171430
 
171341
171431
  export interface WorkspaceEditorPluginConfig {
@@ -171502,6 +171592,44 @@ function parseRestResourceEntries(arrayLiteral) {
171502
171592
  };
171503
171593
  });
171504
171594
  }
171595
+ function parseAiFeatureEntries(arrayLiteral) {
171596
+ return arrayLiteral.elements.map((element, elementIndex) => {
171597
+ if (!import_typescript.default.isObjectLiteralExpression(element)) {
171598
+ throw new Error(`AI_FEATURES[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
171599
+ }
171600
+ return {
171601
+ aiSchemaFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "aiSchemaFile"),
171602
+ apiFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "apiFile"),
171603
+ clientFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "clientFile"),
171604
+ dataFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "dataFile"),
171605
+ namespace: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "namespace"),
171606
+ openApiFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "openApiFile"),
171607
+ phpFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "phpFile"),
171608
+ slug: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "slug"),
171609
+ typesFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "typesFile"),
171610
+ validatorsFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "validatorsFile")
171611
+ };
171612
+ });
171613
+ }
171614
+ function parseAbilityEntries(arrayLiteral) {
171615
+ return arrayLiteral.elements.map((element, elementIndex) => {
171616
+ if (!import_typescript.default.isObjectLiteralExpression(element)) {
171617
+ throw new Error(`ABILITIES[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
171618
+ }
171619
+ return {
171620
+ clientFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "clientFile"),
171621
+ configFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "configFile"),
171622
+ dataFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "dataFile"),
171623
+ inputSchemaFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "inputSchemaFile"),
171624
+ inputTypeName: getRequiredStringProperty("ABILITIES", elementIndex, element, "inputTypeName"),
171625
+ outputSchemaFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "outputSchemaFile"),
171626
+ outputTypeName: getRequiredStringProperty("ABILITIES", elementIndex, element, "outputTypeName"),
171627
+ phpFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "phpFile"),
171628
+ slug: getRequiredStringProperty("ABILITIES", elementIndex, element, "slug"),
171629
+ typesFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "typesFile")
171630
+ };
171631
+ });
171632
+ }
171505
171633
  function parseEditorPluginEntries(arrayLiteral) {
171506
171634
  return arrayLiteral.elements.map((element, elementIndex) => {
171507
171635
  if (!import_typescript.default.isObjectLiteralExpression(element)) {
@@ -171524,6 +171652,8 @@ function parseWorkspaceInventorySource(source) {
171524
171652
  const patternArray = findExportedArrayLiteral(sourceFile, "PATTERNS");
171525
171653
  const bindingSourceArray = findExportedArrayLiteral(sourceFile, "BINDING_SOURCES");
171526
171654
  const restResourceArray = findExportedArrayLiteral(sourceFile, "REST_RESOURCES");
171655
+ const abilityArray = findExportedArrayLiteral(sourceFile, "ABILITIES");
171656
+ const aiFeatureArray = findExportedArrayLiteral(sourceFile, "AI_FEATURES");
171527
171657
  const editorPluginArray = findExportedArrayLiteral(sourceFile, "EDITOR_PLUGINS");
171528
171658
  if (variationArray.found && !variationArray.array) {
171529
171659
  throw new Error("scripts/block-config.ts must export VARIATIONS as an array literal.");
@@ -171537,12 +171667,22 @@ function parseWorkspaceInventorySource(source) {
171537
171667
  if (restResourceArray.found && !restResourceArray.array) {
171538
171668
  throw new Error("scripts/block-config.ts must export REST_RESOURCES as an array literal.");
171539
171669
  }
171670
+ if (abilityArray.found && !abilityArray.array) {
171671
+ throw new Error("scripts/block-config.ts must export ABILITIES as an array literal.");
171672
+ }
171673
+ if (aiFeatureArray.found && !aiFeatureArray.array) {
171674
+ throw new Error("scripts/block-config.ts must export AI_FEATURES as an array literal.");
171675
+ }
171540
171676
  if (editorPluginArray.found && !editorPluginArray.array) {
171541
171677
  throw new Error("scripts/block-config.ts must export EDITOR_PLUGINS as an array literal.");
171542
171678
  }
171543
171679
  return {
171680
+ abilities: abilityArray.array ? parseAbilityEntries(abilityArray.array) : [],
171681
+ aiFeatures: aiFeatureArray.array ? parseAiFeatureEntries(aiFeatureArray.array) : [],
171544
171682
  bindingSources: bindingSourceArray.array ? parseBindingSourceEntries(bindingSourceArray.array) : [],
171545
171683
  blocks: parseBlockEntries(blockArray.array),
171684
+ hasAbilitiesSection: abilityArray.found,
171685
+ hasAiFeaturesSection: aiFeatureArray.found,
171546
171686
  hasBindingSourcesSection: bindingSourceArray.found,
171547
171687
  hasEditorPluginsSection: editorPluginArray.found,
171548
171688
  hasPatternsSection: patternArray.found,
@@ -171604,6 +171744,18 @@ function ensureWorkspaceInventorySections(source) {
171604
171744
  if (!/export\s+const\s+REST_RESOURCES\b/u.test(nextSource)) {
171605
171745
  nextSource += REST_RESOURCES_CONST_SECTION;
171606
171746
  }
171747
+ if (!/export\s+interface\s+WorkspaceAbilityConfig\b/u.test(nextSource)) {
171748
+ nextSource += ABILITIES_INTERFACE_SECTION;
171749
+ }
171750
+ if (!/export\s+const\s+ABILITIES\b/u.test(nextSource)) {
171751
+ nextSource += ABILITIES_CONST_SECTION;
171752
+ }
171753
+ if (!/export\s+interface\s+WorkspaceAiFeatureConfig\b/u.test(nextSource)) {
171754
+ nextSource += AI_FEATURES_INTERFACE_SECTION;
171755
+ }
171756
+ if (!/export\s+const\s+AI_FEATURES\b/u.test(nextSource)) {
171757
+ nextSource += AI_FEATURES_CONST_SECTION;
171758
+ }
171607
171759
  if (!/export\s+interface\s+WorkspaceEditorPluginConfig\b/u.test(nextSource)) {
171608
171760
  nextSource += EDITOR_PLUGINS_INTERFACE_SECTION;
171609
171761
  }
@@ -171624,9 +171776,40 @@ function appendEntriesAtMarker(source, marker, entries) {
171624
171776
  `)}
171625
171777
  ${marker}`);
171626
171778
  }
171779
+ function escapeRegex(value) {
171780
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
171781
+ }
171782
+ function ensureInterfaceField(source, interfaceName, fieldName, fieldSource) {
171783
+ const interfacePattern = new RegExp(`(export\\s+interface\\s+${escapeRegex(interfaceName)}\\s*\\{\\r?\\n)([\\s\\S]*?)(\\r?\\n\\})`, "u");
171784
+ return source.replace(interfacePattern, (match, start, body, end) => {
171785
+ if (new RegExp(`^[ ]*${escapeRegex(fieldName)}\\??:`, "mu").test(body)) {
171786
+ return match;
171787
+ }
171788
+ const lineEnding = start.endsWith(`\r
171789
+ `) ? `\r
171790
+ ` : `
171791
+ `;
171792
+ const formattedFieldSource = `${fieldSource.replace(/\r?\n$/u, "").split(`
171793
+ `).join(lineEnding)}${lineEnding}`;
171794
+ const memberPattern = /^[ \t]*([A-Za-z_$][\w$]*)\??:/gmu;
171795
+ for (const member of body.matchAll(memberPattern)) {
171796
+ const memberIndex = member.index;
171797
+ const memberName = member[1];
171798
+ if (memberIndex === undefined || !memberName) {
171799
+ continue;
171800
+ }
171801
+ if (memberName.localeCompare(fieldName) > 0) {
171802
+ return `${start}${body.slice(0, memberIndex)}${formattedFieldSource}${body.slice(memberIndex)}${end}`;
171803
+ }
171804
+ }
171805
+ return `${start}${body}${body.length > 0 && !body.endsWith(lineEnding) ? lineEnding : ""}${formattedFieldSource}${end}`;
171806
+ });
171807
+ }
171627
171808
  function updateWorkspaceInventorySource(source, {
171628
171809
  blockEntries = [],
171629
171810
  bindingSourceEntries = [],
171811
+ abilityEntries = [],
171812
+ aiFeatureEntries = [],
171630
171813
  editorPluginEntries = [],
171631
171814
  patternEntries = [],
171632
171815
  restResourceEntries = [],
@@ -171642,6 +171825,10 @@ function updateWorkspaceInventorySource(source, {
171642
171825
  nextSource = appendEntriesAtMarker(nextSource, PATTERN_CONFIG_ENTRY_MARKER, patternEntries);
171643
171826
  nextSource = appendEntriesAtMarker(nextSource, BINDING_SOURCE_CONFIG_ENTRY_MARKER, bindingSourceEntries);
171644
171827
  nextSource = appendEntriesAtMarker(nextSource, REST_RESOURCE_CONFIG_ENTRY_MARKER, restResourceEntries);
171828
+ nextSource = appendEntriesAtMarker(nextSource, ABILITY_CONFIG_ENTRY_MARKER, abilityEntries);
171829
+ nextSource = appendEntriesAtMarker(nextSource, AI_FEATURE_CONFIG_ENTRY_MARKER, aiFeatureEntries);
171830
+ nextSource = ensureInterfaceField(nextSource, "WorkspaceAbilityConfig", "compatibility", WORKSPACE_COMPATIBILITY_CONFIG_FIELD);
171831
+ nextSource = ensureInterfaceField(nextSource, "WorkspaceAiFeatureConfig", "compatibility", WORKSPACE_COMPATIBILITY_CONFIG_FIELD);
171645
171832
  nextSource = appendEntriesAtMarker(nextSource, EDITOR_PLUGIN_CONFIG_ENTRY_MARKER, editorPluginEntries);
171646
171833
  return nextSource;
171647
171834
  }
@@ -171654,6 +171841,6 @@ async function appendWorkspaceInventoryEntries(projectDir, options) {
171654
171841
  }
171655
171842
  }
171656
171843
 
171657
- export { HOOKED_BLOCK_POSITION_SET, HOOKED_BLOCK_ANCHOR_PATTERN, toKebabCase, toSnakeCase, toPascalCase, toSegmentPascalCase, toTitleCase, validateBlockSlug, validateNamespace, normalizeBlockSlug, resolveNonEmptyNormalizedBlockSlug, buildBlockCssClassName, buildFrontendCssClassName, resolveScaffoldIdentifiers, ADD_KIND_IDS, REST_RESOURCE_METHOD_IDS, EDITOR_PLUGIN_SLOT_IDS, ADD_BLOCK_TEMPLATE_IDS, REST_RESOURCE_NAMESPACE_PATTERN, assertValidGeneratedSlug, resolveRestResourceNamespace, assertValidRestResourceMethods, assertValidHookedBlockPosition, getWorkspaceBootstrapPath, buildWorkspacePhpPrefix, isAddBlockTemplateId, quoteTsString, patchFile, readOptionalFile, snapshotWorkspaceFiles, rollbackWorkspaceMutation, resolveWorkspaceBlock, assertValidHookAnchor, assertValidEditorPluginSlot, readWorkspaceBlockJson, getMutableBlockHooks, assertVariationDoesNotExist, assertPatternDoesNotExist, assertBindingSourceDoesNotExist, assertRestResourceDoesNotExist, assertEditorPluginDoesNotExist, formatAddHelpText, readWorkspaceInventory, getWorkspaceBlockSelectOptions, appendWorkspaceInventoryEntries };
171844
+ export { HOOKED_BLOCK_POSITION_SET, HOOKED_BLOCK_ANCHOR_PATTERN, toKebabCase, toSnakeCase, toPascalCase, toSegmentPascalCase, toTitleCase, validateBlockSlug, validateNamespace, normalizeBlockSlug, resolveNonEmptyNormalizedBlockSlug, buildBlockCssClassName, buildFrontendCssClassName, resolveScaffoldIdentifiers, ADD_KIND_IDS, REST_RESOURCE_METHOD_IDS, EDITOR_PLUGIN_SLOT_IDS, ADD_BLOCK_TEMPLATE_IDS, REST_RESOURCE_NAMESPACE_PATTERN, assertValidGeneratedSlug, resolveRestResourceNamespace, assertValidRestResourceMethods, assertValidHookedBlockPosition, getWorkspaceBootstrapPath, buildWorkspacePhpPrefix, isAddBlockTemplateId, quoteTsString, patchFile, readOptionalFile, snapshotWorkspaceFiles, rollbackWorkspaceMutation, resolveWorkspaceBlock, assertValidHookAnchor, assertValidEditorPluginSlot, readWorkspaceBlockJson, getMutableBlockHooks, assertVariationDoesNotExist, assertPatternDoesNotExist, assertBindingSourceDoesNotExist, assertRestResourceDoesNotExist, assertAbilityDoesNotExist, assertAiFeatureDoesNotExist, assertEditorPluginDoesNotExist, formatAddHelpText, readWorkspaceInventory, getWorkspaceBlockSelectOptions, appendWorkspaceInventoryEntries };
171658
171845
 
171659
- //# debugId=E5512AA4DE4BAC6564756E2164756E21
171846
+ //# debugId=42AF31D5CC3A7C2364756E2164756E21
@@ -4,7 +4,7 @@ import {
4
4
  } from "./cli-tesygdnr.js";
5
5
  import {
6
6
  seedProjectMigrations
7
- } from "./cli-qpt5dt0x.js";
7
+ } from "./cli-2rev5hqm.js";
8
8
  import {
9
9
  ensureMigrationDirectories,
10
10
  isPlainObject,
@@ -59,7 +59,7 @@ import {
59
59
  toTitleCase,
60
60
  validateBlockSlug,
61
61
  validateNamespace
62
- } from "./cli-rg481yks.js";
62
+ } from "./cli-3w3qxq9w.js";
63
63
  import {
64
64
  createManagedTempRoot
65
65
  } from "./cli-t73q5aqz.js";
@@ -11427,6 +11427,268 @@ async function resolveTemplateSource(templateId, cwd, variables, variant) {
11427
11427
  }
11428
11428
  }
11429
11429
 
11430
+ // ../wp-typia-project-tools/src/runtime/ai-feature-capability.ts
11431
+ var AI_FEATURE_DEFINITIONS = {
11432
+ wordpressAiClient: {
11433
+ description: "WordPress 7.0 AI Client surface used by AI-capable feature endpoints.",
11434
+ id: "wordpress-ai-client",
11435
+ label: "WordPress AI Client",
11436
+ minimumVersions: {
11437
+ wordpress: "7.0"
11438
+ },
11439
+ runtimeGates: [
11440
+ {
11441
+ kind: "wordpress-core-feature",
11442
+ value: "WordPress AI Client"
11443
+ }
11444
+ ]
11445
+ },
11446
+ wordpressCoreAbilities: {
11447
+ description: "Client-side ability discovery surface for editor and admin flows.",
11448
+ id: "wordpress-core-abilities",
11449
+ label: "@wordpress/core-abilities",
11450
+ minimumVersions: {
11451
+ wordpress: "7.0"
11452
+ },
11453
+ runtimeGates: [
11454
+ {
11455
+ kind: "script-package",
11456
+ value: "@wordpress/core-abilities"
11457
+ }
11458
+ ]
11459
+ },
11460
+ wordpressMcpPublicMetadata: {
11461
+ description: "Optional MCP exposure metadata consumed by a separate adapter path rather than core alone.",
11462
+ id: "wordpress-mcp-public-metadata",
11463
+ label: "MCP public metadata",
11464
+ runtimeGates: [
11465
+ {
11466
+ kind: "adapter",
11467
+ value: "MCP adapter"
11468
+ }
11469
+ ]
11470
+ },
11471
+ wordpressServerAbilities: {
11472
+ description: "Server-side ability registration and execution surface for WordPress-native abilities.",
11473
+ id: "wordpress-server-abilities",
11474
+ label: "WordPress Abilities API",
11475
+ minimumVersions: {
11476
+ wordpress: "6.9"
11477
+ },
11478
+ runtimeGates: [
11479
+ {
11480
+ kind: "php-function",
11481
+ value: "wp_register_ability"
11482
+ },
11483
+ {
11484
+ kind: "php-function",
11485
+ value: "wp_register_ability_category"
11486
+ }
11487
+ ]
11488
+ }
11489
+ };
11490
+ var DEFAULT_AI_FEATURE_REGISTRY = Object.values(AI_FEATURE_DEFINITIONS).reduce((accumulator, definition) => {
11491
+ accumulator[definition.id] = definition;
11492
+ return accumulator;
11493
+ }, {});
11494
+ function parseVersionFloorParts(value) {
11495
+ return value.split(".").map((part, index) => {
11496
+ if (!/^\d+$/.test(part)) {
11497
+ throw new Error(`parseVersionFloorParts received an invalid version floor "${value}" at segment ${index + 1}.`);
11498
+ }
11499
+ return Number.parseInt(part, 10);
11500
+ });
11501
+ }
11502
+ function compareVersionFloors(left, right) {
11503
+ const leftParts = parseVersionFloorParts(left);
11504
+ const rightParts = parseVersionFloorParts(right);
11505
+ const length = Math.max(leftParts.length, rightParts.length);
11506
+ for (let index = 0;index < length; index += 1) {
11507
+ const leftValue = leftParts[index] ?? 0;
11508
+ const rightValue = rightParts[index] ?? 0;
11509
+ if (leftValue > rightValue) {
11510
+ return 1;
11511
+ }
11512
+ if (leftValue < rightValue) {
11513
+ return -1;
11514
+ }
11515
+ }
11516
+ return 0;
11517
+ }
11518
+ function pickHigherVersionFloor(current, candidate) {
11519
+ if (!candidate) {
11520
+ return current;
11521
+ }
11522
+ if (!current) {
11523
+ return candidate;
11524
+ }
11525
+ return compareVersionFloors(current, candidate) >= 0 ? current : candidate;
11526
+ }
11527
+ function normalizeSelections(selections) {
11528
+ const normalized = new Map;
11529
+ for (const selection of selections) {
11530
+ const current = normalized.get(selection.featureId);
11531
+ if (!current || selection.mode === "required") {
11532
+ normalized.set(selection.featureId, selection);
11533
+ }
11534
+ }
11535
+ return [...normalized.values()];
11536
+ }
11537
+ function resolveAiFeatureCapabilityPlan(selections, registry = DEFAULT_AI_FEATURE_REGISTRY) {
11538
+ const requiredFeatures = [];
11539
+ const optionalFeatures = [];
11540
+ let wordpress;
11541
+ let php;
11542
+ for (const selection of normalizeSelections(selections)) {
11543
+ const definition = registry[selection.featureId];
11544
+ if (!definition) {
11545
+ throw new Error(`Unknown AI feature capability "${selection.featureId}".`);
11546
+ }
11547
+ const resolvedDefinition = {
11548
+ ...definition,
11549
+ mode: selection.mode
11550
+ };
11551
+ if (selection.mode === "required") {
11552
+ requiredFeatures.push(resolvedDefinition);
11553
+ wordpress = pickHigherVersionFloor(wordpress, definition.minimumVersions?.wordpress);
11554
+ php = pickHigherVersionFloor(php, definition.minimumVersions?.php);
11555
+ continue;
11556
+ }
11557
+ optionalFeatures.push(resolvedDefinition);
11558
+ }
11559
+ return {
11560
+ hardMinimums: {
11561
+ ...php ? { php } : {},
11562
+ ...wordpress ? { wordpress } : {}
11563
+ },
11564
+ optionalFeatures,
11565
+ requiredFeatures
11566
+ };
11567
+ }
11568
+
11569
+ // ../wp-typia-project-tools/src/runtime/scaffold-compatibility.ts
11570
+ var DEFAULT_SCAFFOLD_COMPATIBILITY = {
11571
+ requiresAtLeast: "6.7",
11572
+ requiresPhp: "8.0",
11573
+ testedUpTo: "6.9"
11574
+ };
11575
+ var OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY = [
11576
+ {
11577
+ featureId: AI_FEATURE_DEFINITIONS.wordpressAiClient.id,
11578
+ mode: "optional"
11579
+ }
11580
+ ];
11581
+ var REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY = [
11582
+ {
11583
+ featureId: AI_FEATURE_DEFINITIONS.wordpressServerAbilities.id,
11584
+ mode: "required"
11585
+ },
11586
+ {
11587
+ featureId: AI_FEATURE_DEFINITIONS.wordpressCoreAbilities.id,
11588
+ mode: "required"
11589
+ }
11590
+ ];
11591
+ function parseVersionFloorParts2(value) {
11592
+ return value.split(".").map((part, index) => {
11593
+ if (!/^\d+$/u.test(part)) {
11594
+ throw new Error(`parseVersionFloorParts received an invalid version floor "${value}" at segment ${index + 1}.`);
11595
+ }
11596
+ return Number.parseInt(part, 10);
11597
+ });
11598
+ }
11599
+ function compareVersionFloors2(left, right) {
11600
+ const leftParts = parseVersionFloorParts2(left);
11601
+ const rightParts = parseVersionFloorParts2(right);
11602
+ const length = Math.max(leftParts.length, rightParts.length);
11603
+ for (let index = 0;index < length; index += 1) {
11604
+ const leftValue = leftParts[index] ?? 0;
11605
+ const rightValue = rightParts[index] ?? 0;
11606
+ if (leftValue > rightValue) {
11607
+ return 1;
11608
+ }
11609
+ if (leftValue < rightValue) {
11610
+ return -1;
11611
+ }
11612
+ }
11613
+ return 0;
11614
+ }
11615
+ function pickHigherVersionFloor2(current, candidate) {
11616
+ if (!candidate) {
11617
+ return current;
11618
+ }
11619
+ return compareVersionFloors2(current, candidate) >= 0 ? current : candidate;
11620
+ }
11621
+ function pickHigherHeaderVersionFloor(policyValue, currentValue) {
11622
+ const normalizedCurrentValue = currentValue.trim();
11623
+ if (!normalizedCurrentValue) {
11624
+ return policyValue;
11625
+ }
11626
+ try {
11627
+ return pickHigherVersionFloor2(policyValue, normalizedCurrentValue);
11628
+ } catch {
11629
+ return policyValue;
11630
+ }
11631
+ }
11632
+ function formatRuntimeGate(feature) {
11633
+ return (feature.runtimeGates ?? []).map((gate) => `${feature.label}: ${gate.kind} ${gate.value}`);
11634
+ }
11635
+ function getPolicyMode(capabilityPlan) {
11636
+ if (capabilityPlan.requiredFeatures.length > 0) {
11637
+ return "required";
11638
+ }
11639
+ if (capabilityPlan.optionalFeatures.length > 0) {
11640
+ return "optional";
11641
+ }
11642
+ return "baseline";
11643
+ }
11644
+ function resolveScaffoldCompatibilityPolicy(selections, {
11645
+ baseline = DEFAULT_SCAFFOLD_COMPATIBILITY
11646
+ } = {}) {
11647
+ const capabilityPlan = resolveAiFeatureCapabilityPlan(selections);
11648
+ const requiresAtLeast = pickHigherVersionFloor2(baseline.requiresAtLeast, capabilityPlan.hardMinimums.wordpress);
11649
+ const requiresPhp = pickHigherVersionFloor2(baseline.requiresPhp, capabilityPlan.hardMinimums.php);
11650
+ const testedUpTo = pickHigherVersionFloor2(baseline.testedUpTo, requiresAtLeast);
11651
+ return {
11652
+ capabilityPlan,
11653
+ pluginHeader: {
11654
+ requiresAtLeast,
11655
+ requiresPhp,
11656
+ testedUpTo
11657
+ }
11658
+ };
11659
+ }
11660
+ function createScaffoldCompatibilityConfig(policy) {
11661
+ const { capabilityPlan } = policy;
11662
+ return {
11663
+ hardMinimums: capabilityPlan.hardMinimums,
11664
+ mode: getPolicyMode(capabilityPlan),
11665
+ optionalFeatures: capabilityPlan.optionalFeatures.map((feature) => feature.label),
11666
+ requiredFeatures: capabilityPlan.requiredFeatures.map((feature) => feature.label),
11667
+ runtimeGates: [
11668
+ ...capabilityPlan.requiredFeatures.flatMap(formatRuntimeGate),
11669
+ ...capabilityPlan.optionalFeatures.flatMap(formatRuntimeGate)
11670
+ ]
11671
+ };
11672
+ }
11673
+ function renderScaffoldCompatibilityConfig(policy, indent = "\t\t") {
11674
+ const config = createScaffoldCompatibilityConfig(policy);
11675
+ return JSON.stringify(config, null, "\t").split(`
11676
+ `).map((line, index) => index === 0 ? line : `${indent}${line}`).join(`
11677
+ `);
11678
+ }
11679
+ function replacePluginHeaderVersionFloor(source, pattern, policyValue) {
11680
+ return source.replace(pattern, (_match, prefix, currentValue, lineEnding) => {
11681
+ const versionPrefix = prefix.endsWith(":") ? `${prefix} ` : prefix;
11682
+ return `${versionPrefix}${pickHigherHeaderVersionFloor(policyValue, currentValue)}${lineEnding}`;
11683
+ });
11684
+ }
11685
+ function updatePluginHeaderCompatibility(source, policy) {
11686
+ const { pluginHeader } = policy;
11687
+ const nextSource = replacePluginHeaderVersionFloor(source, /(\* Requires at least:[^\S\r\n]*)([^\r\n]*)(\r?)/u, pluginHeader.requiresAtLeast);
11688
+ const nextSourceWithTestedUpTo = replacePluginHeaderVersionFloor(nextSource, /(\* Tested up to:[^\S\r\n]*)([^\r\n]*)(\r?)/u, pluginHeader.testedUpTo);
11689
+ return replacePluginHeaderVersionFloor(nextSourceWithTestedUpTo, /(\* Requires PHP:[^\S\r\n]*)([^\r\n]*)(\r?)/u, pluginHeader.requiresPhp);
11690
+ }
11691
+
11430
11692
  // ../wp-typia-project-tools/src/runtime/block-generator-service-spec.ts
11431
11693
  function getBuiltInPersistenceSpec({
11432
11694
  templateId,
@@ -11556,6 +11818,7 @@ function buildTemplateVariablesFromBlockSpec(spec) {
11556
11818
  const dataStorageMode = persistenceEnabled ? spec.persistence.dataStorageMode : "custom-table";
11557
11819
  const persistencePolicy = persistenceEnabled ? spec.persistence.persistencePolicy : "authenticated";
11558
11820
  const queryVariationNamespace = `${namespace}/${slug}`;
11821
+ const compatibility = resolveScaffoldCompatibilityPolicy([]);
11559
11822
  const flatVariables = {
11560
11823
  alternateRenderTargetsCsv: formatAlternateRenderTargets(alternateRenderTargets),
11561
11824
  alternateRenderTargetsJson: JSON.stringify(alternateRenderTargets),
@@ -11583,6 +11846,9 @@ function buildTemplateVariablesFromBlockSpec(spec) {
11583
11846
  hasAlternateMjmlRenderTarget: hasAlternateMjmlRenderTarget ? "true" : "false",
11584
11847
  hasAlternatePlainTextRenderTarget: hasAlternatePlainTextRenderTarget ? "true" : "false",
11585
11848
  hasAlternateRenderTargets: alternateRenderTargets.length > 0 ? "true" : "false",
11849
+ requiresAtLeast: compatibility.pluginHeader.requiresAtLeast,
11850
+ requiresPhp: compatibility.pluginHeader.requiresPhp,
11851
+ testedUpTo: compatibility.pluginHeader.testedUpTo,
11586
11852
  projectToolsPackageVersion,
11587
11853
  cssClassName,
11588
11854
  dashCase: slug,
@@ -11626,6 +11892,7 @@ function buildTemplateVariablesFromBlockSpec(spec) {
11626
11892
  author: spec.project.author,
11627
11893
  blockMetadataVersion: BUILTIN_BLOCK_METADATA_VERSION,
11628
11894
  category: spec.metadata.category,
11895
+ compatibility: compatibility.pluginHeader,
11629
11896
  cssClassName,
11630
11897
  description: spec.metadata.description,
11631
11898
  descriptionJson: flatVariables.descriptionJson,
@@ -15924,6 +16191,7 @@ function getTemplateVariables(templateId, answers) {
15924
16191
  const compoundPersistenceEnabled = templateId === "persistence" ? true : templateId === "compound" ? Boolean(answers.dataStorageMode || answers.persistencePolicy) : false;
15925
16192
  const dataStorageMode = templateId === "persistence" || compoundPersistenceEnabled ? answers.dataStorageMode ?? "custom-table" : "custom-table";
15926
16193
  const persistencePolicy = templateId === "persistence" || compoundPersistenceEnabled ? answers.persistencePolicy ?? "authenticated" : "authenticated";
16194
+ const compatibility = resolveScaffoldCompatibilityPolicy([]);
15927
16195
  const flatVariables = {
15928
16196
  alternateRenderTargetsCsv: "",
15929
16197
  alternateRenderTargetsJson: "[]",
@@ -15952,6 +16220,8 @@ function getTemplateVariables(templateId, answers) {
15952
16220
  hasAlternatePlainTextRenderTarget: "false",
15953
16221
  hasAlternateRenderTargets: "false",
15954
16222
  projectToolsPackageVersion,
16223
+ requiresAtLeast: compatibility.pluginHeader.requiresAtLeast,
16224
+ requiresPhp: compatibility.pluginHeader.requiresPhp,
15955
16225
  cssClassName,
15956
16226
  dataStorageMode,
15957
16227
  dashCase: slug,
@@ -15975,6 +16245,7 @@ function getTemplateVariables(templateId, answers) {
15975
16245
  phpPrefix,
15976
16246
  phpPrefixUpper,
15977
16247
  restPackageVersion,
16248
+ testedUpTo: compatibility.pluginHeader.testedUpTo,
15978
16249
  publicWriteRequestIdDeclaration: persistencePolicy === "public" ? "publicWriteRequestId: string & tags.MinLength< 1 > & tags.MaxLength< 128 >;" : "publicWriteRequestId?: string & tags.MinLength< 1 > & tags.MaxLength< 128 >;",
15979
16250
  restWriteAuthIntent: persistencePolicy === "public" ? "public-write-protected" : "authenticated",
15980
16251
  restWriteAuthMechanism: persistencePolicy === "public" ? "public-signed-token" : "rest-nonce",
@@ -16015,6 +16286,7 @@ function getTemplateVariables(templateId, answers) {
16015
16286
  author: answers.author.trim(),
16016
16287
  blockMetadataVersion: BUILTIN_BLOCK_METADATA_VERSION,
16017
16288
  category: metadataDefaults?.category ?? template?.defaultCategory ?? "widgets",
16289
+ compatibility: compatibility.pluginHeader,
16018
16290
  cssClassName,
16019
16291
  description,
16020
16292
  descriptionJson: JSON.stringify(description),
@@ -16285,6 +16557,6 @@ async function resolveOptionalInteractiveExternalLayerId({
16285
16557
  }
16286
16558
  }
16287
16559
 
16288
- export { syncPersistenceRestArtifacts, copyInterpolatedDirectory, listInterpolatedDirectoryOutputs, getPrimaryDevelopmentScript, getOptionalOnboardingSteps, getOptionalOnboardingNote, getOptionalOnboardingShortNote, formatNonEmptyTargetDirectoryError, parseTemplateLocator, resolveExternalTemplateLayers, resolveTemplateSeed, normalizeOptionalCliString, resolveLocalCliPathOption, assertExternalLayerCompositionOptions, assertBuiltInTemplateVariantAllowed, parseAlternateRenderTargets, parseCompoundInnerBlocksPreset, getDefaultAnswers, resolveTemplateId, resolvePackageManagerId, collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, scaffoldProject, resolveOptionalInteractiveExternalLayerId };
16560
+ export { syncPersistenceRestArtifacts, copyInterpolatedDirectory, listInterpolatedDirectoryOutputs, getPrimaryDevelopmentScript, getOptionalOnboardingSteps, getOptionalOnboardingNote, getOptionalOnboardingShortNote, formatNonEmptyTargetDirectoryError, parseTemplateLocator, resolveExternalTemplateLayers, resolveTemplateSeed, normalizeOptionalCliString, resolveLocalCliPathOption, assertExternalLayerCompositionOptions, assertBuiltInTemplateVariantAllowed, parseAlternateRenderTargets, parseCompoundInnerBlocksPreset, OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY, REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY, resolveScaffoldCompatibilityPolicy, renderScaffoldCompatibilityConfig, updatePluginHeaderCompatibility, getDefaultAnswers, resolveTemplateId, resolvePackageManagerId, collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, scaffoldProject, resolveOptionalInteractiveExternalLayerId };
16289
16561
 
16290
- //# debugId=C62257CB4F3F0AF464756E2164756E21
16562
+ //# debugId=287134A8F6F7F6FD64756E2164756E21