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.
@@ -20,7 +20,7 @@ import {
20
20
  REST_RESOURCE_METHOD_IDS,
21
21
  REST_RESOURCE_NAMESPACE_PATTERN,
22
22
  readWorkspaceInventory
23
- } from "./cli-rg481yks.js";
23
+ } from "./cli-3w3qxq9w.js";
24
24
  import"./cli-t73q5aqz.js";
25
25
  import {
26
26
  WORKSPACE_TEMPLATE_PACKAGE,
@@ -136,6 +136,10 @@ var WORKSPACE_BINDING_SERVER_GLOB = "/src/bindings/*/server.php";
136
136
  var WORKSPACE_BINDING_EDITOR_SCRIPT = "build/bindings/index.js";
137
137
  var WORKSPACE_BINDING_EDITOR_ASSET = "build/bindings/index.asset.php";
138
138
  var WORKSPACE_REST_RESOURCE_GLOB = "/inc/rest/*.php";
139
+ var WORKSPACE_ABILITY_GLOB = "/inc/abilities/*.php";
140
+ var WORKSPACE_ABILITY_EDITOR_SCRIPT = "build/abilities/index.js";
141
+ var WORKSPACE_ABILITY_EDITOR_ASSET = "build/abilities/index.asset.php";
142
+ var WORKSPACE_AI_FEATURE_GLOB = "/inc/ai-features/*.php";
139
143
  var WORKSPACE_EDITOR_PLUGIN_EDITOR_SCRIPT = "build/editor-plugins/index.js";
140
144
  var WORKSPACE_EDITOR_PLUGIN_EDITOR_ASSET = "build/editor-plugins/index.asset.php";
141
145
  var WORKSPACE_EDITOR_PLUGIN_EDITOR_STYLE = "build/editor-plugins/style-index.css";
@@ -342,6 +346,101 @@ function checkWorkspaceRestResourceBootstrap(projectDir, packageName, phpPrefix)
342
346
  const hasRegisterHook = source.includes(registerHook);
343
347
  return createDoctorCheck2("REST resource bootstrap", hasServerGlob && hasRegisterHook ? "pass" : "fail", hasServerGlob && hasRegisterHook ? "REST resource PHP loader hook is present" : "Missing REST resource PHP require glob or init hook");
344
348
  }
349
+ function getWorkspaceAbilityRequiredFiles(ability) {
350
+ return Array.from(new Set([
351
+ ability.clientFile,
352
+ ability.configFile,
353
+ ability.dataFile,
354
+ ability.inputSchemaFile,
355
+ ability.outputSchemaFile,
356
+ ability.phpFile,
357
+ ability.typesFile
358
+ ]));
359
+ }
360
+ function checkWorkspaceAbilityConfig(projectDir, ability) {
361
+ const configPath = path2.join(projectDir, ability.configFile);
362
+ if (!fs2.existsSync(configPath)) {
363
+ return createDoctorCheck2(`Ability config ${ability.slug}`, "fail", `Missing ${ability.configFile}`);
364
+ }
365
+ try {
366
+ const config = JSON.parse(fs2.readFileSync(configPath, "utf8"));
367
+ const abilityId = typeof config.abilityId === "string" ? config.abilityId.trim() : "";
368
+ const categorySlug = typeof config.category?.slug === "string" ? config.category.slug.trim() : "";
369
+ const hasValidAbilityId = /^[a-z0-9-]+\/[a-z0-9-]+$/u.test(abilityId);
370
+ const hasValidCategorySlug = /^[a-z0-9-]+$/u.test(categorySlug);
371
+ return createDoctorCheck2(`Ability config ${ability.slug}`, hasValidAbilityId && hasValidCategorySlug ? "pass" : "fail", hasValidAbilityId && hasValidCategorySlug ? `Ability id ${abilityId} in category ${categorySlug} is valid` : "Ability config must define a valid abilityId (`namespace/ability-name`) and category.slug.");
372
+ } catch (error) {
373
+ return createDoctorCheck2(`Ability config ${ability.slug}`, "fail", error instanceof Error ? error.message : String(error));
374
+ }
375
+ }
376
+ function checkWorkspaceAbilityBootstrap(projectDir, packageName, phpPrefix) {
377
+ const packageBaseName = packageName.split("/").pop() ?? packageName;
378
+ const bootstrapPath = path2.join(projectDir, `${packageBaseName}.php`);
379
+ if (!fs2.existsSync(bootstrapPath)) {
380
+ return createDoctorCheck2("Ability bootstrap", "fail", `Missing ${path2.basename(bootstrapPath)}`);
381
+ }
382
+ const source = fs2.readFileSync(bootstrapPath, "utf8");
383
+ const loadFunctionName = `${phpPrefix}_load_workflow_abilities`;
384
+ const enqueueFunctionName = `${phpPrefix}_enqueue_workflow_abilities`;
385
+ const loadHook = `add_action( 'plugins_loaded', '${loadFunctionName}' );`;
386
+ const adminEnqueueHook = `add_action( 'admin_enqueue_scripts', '${enqueueFunctionName}' );`;
387
+ const editorEnqueueHook = `add_action( 'enqueue_block_editor_assets', '${enqueueFunctionName}' );`;
388
+ const hasLoaderHook = source.includes(loadHook);
389
+ const hasAdminEnqueueHook = source.includes(adminEnqueueHook);
390
+ const hasEditorEnqueueHook = source.includes(editorEnqueueHook);
391
+ const hasServerGlob = source.includes(WORKSPACE_ABILITY_GLOB);
392
+ const hasEditorScript = source.includes(WORKSPACE_ABILITY_EDITOR_SCRIPT);
393
+ const hasEditorAsset = source.includes(WORKSPACE_ABILITY_EDITOR_ASSET);
394
+ return createDoctorCheck2("Ability bootstrap", hasLoaderHook && hasAdminEnqueueHook && hasEditorEnqueueHook && hasServerGlob && hasEditorScript && hasEditorAsset ? "pass" : "fail", hasLoaderHook && hasAdminEnqueueHook && hasEditorEnqueueHook && hasServerGlob && hasEditorScript && hasEditorAsset ? "Ability loader and admin/editor client bootstrap hooks are present" : "Missing ability loader hook or build/abilities script asset references");
395
+ }
396
+ function checkWorkspaceAbilityIndex(projectDir, abilities) {
397
+ const indexRelativePath = [
398
+ path2.join("src", "abilities", "index.ts"),
399
+ path2.join("src", "abilities", "index.js")
400
+ ].find((relativePath) => fs2.existsSync(path2.join(projectDir, relativePath)));
401
+ if (!indexRelativePath) {
402
+ return createDoctorCheck2("Abilities index", "fail", "Missing src/abilities/index.ts or src/abilities/index.js");
403
+ }
404
+ const indexPath = path2.join(projectDir, indexRelativePath);
405
+ const source = fs2.readFileSync(indexPath, "utf8");
406
+ const missingExports = abilities.filter((ability) => {
407
+ const exportPattern = new RegExp(`^\\s*export\\s+(?:\\*\\s+from|\\{[^}]+\\}\\s+from)\\s+['"\`]\\./${escapeRegex(ability.slug)}\\/client['"\`]`, "mu");
408
+ return !exportPattern.test(source);
409
+ });
410
+ return createDoctorCheck2("Abilities index", missingExports.length === 0 ? "pass" : "fail", missingExports.length === 0 ? "Ability client helpers are aggregated" : `Missing ability exports for: ${missingExports.map((entry) => entry.slug).join(", ")}`);
411
+ }
412
+ function getWorkspaceAiFeatureRequiredFiles(aiFeature) {
413
+ return Array.from(new Set([
414
+ aiFeature.aiSchemaFile,
415
+ aiFeature.apiFile,
416
+ path2.join(path2.dirname(aiFeature.typesFile), "api-schemas", "feature-request.schema.json"),
417
+ path2.join(path2.dirname(aiFeature.typesFile), "api-schemas", "feature-response.schema.json"),
418
+ path2.join(path2.dirname(aiFeature.typesFile), "api-schemas", "feature-result.schema.json"),
419
+ aiFeature.clientFile,
420
+ aiFeature.dataFile,
421
+ aiFeature.openApiFile,
422
+ aiFeature.phpFile,
423
+ aiFeature.typesFile,
424
+ aiFeature.validatorsFile
425
+ ]));
426
+ }
427
+ function checkWorkspaceAiFeatureConfig(aiFeature) {
428
+ const hasNamespace = REST_RESOURCE_NAMESPACE_PATTERN.test(aiFeature.namespace);
429
+ return createDoctorCheck2(`AI feature config ${aiFeature.slug}`, hasNamespace ? "pass" : "fail", hasNamespace ? `AI feature namespace ${aiFeature.namespace} is valid` : "AI feature namespace is invalid");
430
+ }
431
+ function checkWorkspaceAiFeatureBootstrap(projectDir, packageName, phpPrefix) {
432
+ const packageBaseName = packageName.split("/").pop() ?? packageName;
433
+ const bootstrapPath = path2.join(projectDir, `${packageBaseName}.php`);
434
+ if (!fs2.existsSync(bootstrapPath)) {
435
+ return createDoctorCheck2("AI feature bootstrap", "fail", `Missing ${path2.basename(bootstrapPath)}`);
436
+ }
437
+ const source = fs2.readFileSync(bootstrapPath, "utf8");
438
+ const registerFunctionName = `${phpPrefix}_register_ai_features`;
439
+ const registerHook = `add_action( 'init', '${registerFunctionName}', 20 );`;
440
+ const hasServerGlob = source.includes(WORKSPACE_AI_FEATURE_GLOB);
441
+ const hasRegisterHook = source.includes(registerHook);
442
+ return createDoctorCheck2("AI feature bootstrap", hasServerGlob && hasRegisterHook ? "pass" : "fail", hasServerGlob && hasRegisterHook ? "AI feature PHP loader hook is present" : "Missing AI feature PHP require glob or init hook");
443
+ }
345
444
  function getWorkspaceEditorPluginRequiredFiles(editorPlugin) {
346
445
  const editorPluginDir = path2.join("src", "editor-plugins", editorPlugin.slug);
347
446
  return Array.from(new Set([
@@ -439,7 +538,7 @@ function getWorkspaceDoctorChecks(cwd) {
439
538
  checks.push(checkWorkspacePackageMetadata(workspace, workspacePackageJson));
440
539
  try {
441
540
  const inventory = readWorkspaceInventory(workspace.projectDir);
442
- checks.push(createDoctorCheck2("Workspace inventory", "pass", `${inventory.blocks.length} block(s), ${inventory.variations.length} variation(s), ${inventory.patterns.length} pattern(s), ${inventory.bindingSources.length} binding source(s), ${inventory.restResources.length} REST resource(s), ${inventory.editorPlugins.length} editor plugin(s)`));
541
+ checks.push(createDoctorCheck2("Workspace inventory", "pass", `${inventory.blocks.length} block(s), ${inventory.variations.length} variation(s), ${inventory.patterns.length} pattern(s), ${inventory.bindingSources.length} binding source(s), ${inventory.restResources.length} REST resource(s), ${inventory.abilities.length} ability scaffold(s), ${inventory.aiFeatures.length} AI feature(s), ${inventory.editorPlugins.length} editor plugin(s)`));
443
542
  for (const block of inventory.blocks) {
444
543
  checks.push(checkExistingFiles(workspace.projectDir, `Block ${block.slug}`, getWorkspaceBlockRequiredFiles(block)));
445
544
  checks.push(checkWorkspaceBlockMetadata(workspace.projectDir, workspace, block));
@@ -483,6 +582,21 @@ function getWorkspaceDoctorChecks(cwd) {
483
582
  checks.push(checkWorkspaceRestResourceConfig(restResource));
484
583
  checks.push(checkExistingFiles(workspace.projectDir, `REST resource ${restResource.slug}`, getWorkspaceRestResourceRequiredFiles(restResource)));
485
584
  }
585
+ if (inventory.abilities.length > 0) {
586
+ checks.push(checkWorkspaceAbilityBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
587
+ checks.push(checkWorkspaceAbilityIndex(workspace.projectDir, inventory.abilities));
588
+ }
589
+ for (const ability of inventory.abilities) {
590
+ checks.push(checkWorkspaceAbilityConfig(workspace.projectDir, ability));
591
+ checks.push(checkExistingFiles(workspace.projectDir, `Ability ${ability.slug}`, getWorkspaceAbilityRequiredFiles(ability)));
592
+ }
593
+ if (inventory.aiFeatures.length > 0) {
594
+ checks.push(checkWorkspaceAiFeatureBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
595
+ }
596
+ for (const aiFeature of inventory.aiFeatures) {
597
+ checks.push(checkWorkspaceAiFeatureConfig(aiFeature));
598
+ checks.push(checkExistingFiles(workspace.projectDir, `AI feature ${aiFeature.slug}`, getWorkspaceAiFeatureRequiredFiles(aiFeature)));
599
+ }
486
600
  if (inventory.editorPlugins.length > 0) {
487
601
  checks.push(checkWorkspaceEditorPluginBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
488
602
  checks.push(checkWorkspaceEditorPluginIndex(workspace.projectDir, inventory.editorPlugins));
@@ -533,4 +647,4 @@ export {
533
647
  getDoctorChecks
534
648
  };
535
649
 
536
- //# debugId=BACE4BB4FC84F0EB64756E2164756E21
650
+ //# debugId=1F5A1F43481D5B9164756E2164756E21
@@ -19,9 +19,9 @@ import {
19
19
  resolvePackageManagerId,
20
20
  resolveTemplateId,
21
21
  scaffoldProject
22
- } from "./cli-32rf304y.js";
22
+ } from "./cli-8rnhjvb8.js";
23
23
  import"./cli-tesygdnr.js";
24
- import"./cli-qpt5dt0x.js";
24
+ import"./cli-2rev5hqm.js";
25
25
  import"./cli-gcbre1zs.js";
26
26
  import"./cli-bq2v559b.js";
27
27
  import {
@@ -33,7 +33,7 @@ import {
33
33
  OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE,
34
34
  isBuiltInTemplateId
35
35
  } from "./cli-tke8twkn.js";
36
- import"./cli-rg481yks.js";
36
+ import"./cli-3w3qxq9w.js";
37
37
  import {
38
38
  createManagedTempRoot
39
39
  } from "./cli-t73q5aqz.js";
@@ -9,7 +9,7 @@ import {
9
9
  // package.json
10
10
  var package_default = {
11
11
  name: "wp-typia",
12
- version: "0.20.2",
12
+ version: "0.20.3",
13
13
  description: "Canonical CLI package for wp-typia scaffolding and project workflows",
14
14
  packageManager: "bun@1.3.11",
15
15
  type: "module",
@@ -77,7 +77,7 @@ var package_default = {
77
77
  "@bunli/tui": "0.6.0",
78
78
  "@bunli/utils": "0.6.0",
79
79
  "@wp-typia/api-client": "^0.4.5",
80
- "@wp-typia/project-tools": "0.19.3",
80
+ "@wp-typia/project-tools": "0.20.0",
81
81
  "better-result": "^2.7.0",
82
82
  react: "^19.2.5",
83
83
  "react-dom": "^19.2.5",
@@ -226,7 +226,7 @@ var ADD_OPTION_METADATA = {
226
226
  type: "string"
227
227
  },
228
228
  namespace: {
229
- description: "REST namespace for rest-resource workflows.",
229
+ description: "REST namespace for rest-resource and ai-feature workflows.",
230
230
  type: "string"
231
231
  },
232
232
  "persistence-policy": {
@@ -532,4 +532,4 @@ function createPlugin(input) {
532
532
  }
533
533
  export { createPlugin, package_default, CREATE_OPTION_METADATA, ADD_OPTION_METADATA, MIGRATE_OPTION_METADATA, SYNC_OPTION_METADATA, TEMPLATES_OPTION_METADATA, GLOBAL_OPTION_METADATA, buildCommandOptions, collectOptionNamesByType, buildCommandOptionParser, resolveCommandOptionValues, prefersStructuredCliOutput, emitCliDiagnosticFailure, writeStructuredCliDiagnosticError, WP_TYPIA_CONFIG_SOURCES, mergeWpTypiaUserConfig, loadWpTypiaUserConfigFromSource, loadWpTypiaUserConfig, getCreateDefaults, getAddBlockDefaults, getMcpSchemaSources };
534
534
 
535
- //# debugId=28308AF00841565964756E2164756E21
535
+ //# debugId=E7CE1D8C99B5584064756E2164756E21
package/dist-bunli/cli.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  mergeWpTypiaUserConfig,
15
15
  package_default,
16
16
  writeStructuredCliDiagnosticError
17
- } from "./cli-n4m6yqz1.js";
17
+ } from "./cli-z18m4k4g.js";
18
18
  import"./cli-03j0axbt.js";
19
19
  import {
20
20
  GLOBAL_FLAGS,
@@ -2539,7 +2539,7 @@ async function formatCliError(error) {
2539
2539
  }
2540
2540
  async function createWpTypiaCli(options = {}) {
2541
2541
  applyStandaloneSupportLayoutEnv();
2542
- const { wpTypiaCommands } = await import("./command-list-5xp9pjyy.js");
2542
+ const { wpTypiaCommands } = await import("./command-list-g3z86j3x.js");
2543
2543
  const cli = await createCLI({
2544
2544
  ...bunliConfig,
2545
2545
  description: package_default.description,
@@ -13,7 +13,7 @@ import {
13
13
  package_default,
14
14
  prefersStructuredCliOutput,
15
15
  resolveCommandOptionValues
16
- } from "./cli-n4m6yqz1.js";
16
+ } from "./cli-z18m4k4g.js";
17
17
  import {
18
18
  Result,
19
19
  TaggedError,
@@ -72,6 +72,8 @@ var ADD_KIND_IDS = [
72
72
  "pattern",
73
73
  "binding-source",
74
74
  "rest-resource",
75
+ "ability",
76
+ "ai-feature",
75
77
  "editor-plugin",
76
78
  "hooked-block"
77
79
  ];
@@ -136,6 +138,22 @@ var ADD_KIND_REGISTRY = {
136
138
  return true;
137
139
  })
138
140
  },
141
+ ability: {
142
+ completion: {
143
+ nextSteps: (values) => [
144
+ `Review src/abilities/${values.abilitySlug}/ and inc/abilities/${values.abilitySlug}.php.`,
145
+ "Run `wp-typia sync` or `npm run sync-abilities -- --check` and then your workspace build/dev command to verify the generated workflow ability."
146
+ ],
147
+ summaryLines: (values, projectDir) => [
148
+ `Ability: ${values.abilitySlug}`,
149
+ `Project directory: ${projectDir}`
150
+ ],
151
+ title: "Added workflow ability"
152
+ },
153
+ description: "Add a typed server/client workflow ability scaffold",
154
+ nameLabel: "Ability name",
155
+ visibleFieldNames: () => ["kind", "name"]
156
+ },
139
157
  "editor-plugin": {
140
158
  completion: {
141
159
  nextSteps: (values) => [
@@ -205,6 +223,23 @@ var ADD_KIND_REGISTRY = {
205
223
  nameLabel: "REST resource name",
206
224
  visibleFieldNames: () => ["kind", "name", "namespace", "methods"]
207
225
  },
226
+ "ai-feature": {
227
+ completion: {
228
+ nextSteps: (values) => [
229
+ `Review src/ai-features/${values.aiFeatureSlug}/ and inc/ai-features/${values.aiFeatureSlug}.php.`,
230
+ "Run `wp-typia sync-rest` and `wp-typia sync ai` or your workspace build/dev command to verify the generated REST artifacts and AI schema."
231
+ ],
232
+ summaryLines: (values, projectDir) => [
233
+ `AI feature: ${values.aiFeatureSlug}`,
234
+ `Namespace: ${values.namespace}`,
235
+ `Project directory: ${projectDir}`
236
+ ],
237
+ title: "Added server-only AI feature"
238
+ },
239
+ description: "Add a server-owned WordPress AI feature endpoint",
240
+ nameLabel: "AI feature name",
241
+ visibleFieldNames: () => ["kind", "name", "namespace"]
242
+ },
208
243
  variation: {
209
244
  completion: {
210
245
  nextSteps: (values) => [
@@ -609,16 +644,19 @@ function buildAddDryRunPayload(options, markerOptions) {
609
644
  };
610
645
  }
611
646
  function buildSyncDryRunPayload(options, markerOptions) {
647
+ const targetSuffix = options.target === "ai" ? " ai" : "";
648
+ const targetSummary = options.target === "ai" ? "Sync target: AI artifacts only." : options.target === "default" ? "Sync target: generated project defaults." : undefined;
612
649
  return {
613
650
  optionalLines: options.plannedCommands.map((command) => command.displayCommand),
614
- optionalNote: options.check ? "No sync scripts were executed because --dry-run was enabled. Re-run `wp-typia sync --check` to verify generated artifacts without rewriting them." : "No sync scripts were executed because --dry-run was enabled. Re-run without --dry-run to apply generated-file updates, or add --check to verify without rewriting.",
651
+ optionalNote: options.check ? `No sync scripts were executed because --dry-run was enabled. Re-run \`wp-typia sync${targetSuffix} --check\` to verify generated artifacts without rewriting them.` : `No sync scripts were executed because --dry-run was enabled. Re-run \`wp-typia sync${targetSuffix}\` without --dry-run to apply generated-file updates, or add --check to verify without rewriting.`,
615
652
  optionalTitle: `Planned sync commands (${options.plannedCommands.length}):`,
616
653
  summaryLines: [
617
654
  `Project directory: ${options.projectDir}`,
618
655
  `Package manager: ${options.packageManager}`,
656
+ ...targetSummary ? [targetSummary] : [],
619
657
  options.check ? "Execution mode: would run generated sync scripts in verification mode." : "Execution mode: would run generated sync scripts in apply mode."
620
658
  ],
621
- title: formatOutputMarker("dryRun", "Dry run for wp-typia sync", markerOptions)
659
+ title: formatOutputMarker("dryRun", `Dry run for wp-typia sync${targetSuffix}`, markerOptions)
622
660
  };
623
661
  }
624
662
  function printBlock(lines, printLine) {
@@ -657,9 +695,22 @@ function supportsInteractiveTui(options = {}) {
657
695
  import { spawnSync } from "child_process";
658
696
  import fs4 from "fs";
659
697
  import path3 from "path";
660
- var SYNC_INSTALL_MARKERS = ["node_modules", ".pnp.cjs", ".pnp.loader.mjs"];
698
+ var SYNC_INSTALL_MARKERS = [
699
+ "node_modules",
700
+ ".pnp.cjs",
701
+ ".pnp.loader.mjs"
702
+ ];
661
703
  var LOCAL_SYNC_TOOL_PATTERN = /(^|[\s;&|()])(?:tsx|wp-scripts)(?=($|[\s;&|()]))/u;
662
704
  var CAPTURED_SYNC_OUTPUT_MAX_BUFFER = 16 * 1024 * 1024;
705
+ function resolveSyncExecutionTarget(subcommand) {
706
+ if (!subcommand) {
707
+ return "default";
708
+ }
709
+ if (subcommand === "ai") {
710
+ return "ai";
711
+ }
712
+ throw new Error(`Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
713
+ }
663
714
  function formatRunScript(packageManagerId, scriptName, extraArgs = "") {
664
715
  const args = extraArgs.trim();
665
716
  if (packageManagerId === "bun") {
@@ -720,13 +771,26 @@ function resolveSyncProjectContext(cwd) {
720
771
  const packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf8"));
721
772
  const scripts = packageJson.scripts ?? {};
722
773
  const syncScripts = {
723
- sync: typeof scripts.sync === "string" ? scripts.sync : undefined,
724
- "sync-rest": typeof scripts["sync-rest"] === "string" ? scripts["sync-rest"] : undefined,
725
- "sync-types": typeof scripts["sync-types"] === "string" ? scripts["sync-types"] : undefined
774
+ sync: typeof scripts.sync === "string" ? {
775
+ command: scripts.sync,
776
+ scriptName: "sync"
777
+ } : undefined,
778
+ "sync-ai": typeof scripts["sync-ai"] === "string" ? {
779
+ command: scripts["sync-ai"],
780
+ scriptName: "sync-ai"
781
+ } : typeof scripts["sync-wordpress-ai"] === "string" ? {
782
+ command: scripts["sync-wordpress-ai"],
783
+ scriptName: "sync-wordpress-ai"
784
+ } : undefined,
785
+ "sync-rest": typeof scripts["sync-rest"] === "string" ? {
786
+ command: scripts["sync-rest"],
787
+ scriptName: "sync-rest"
788
+ } : undefined,
789
+ "sync-types": typeof scripts["sync-types"] === "string" ? {
790
+ command: scripts["sync-types"],
791
+ scriptName: "sync-types"
792
+ } : undefined
726
793
  };
727
- if (!syncScripts.sync && !syncScripts["sync-types"]) {
728
- throw new Error(`Expected ${packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
729
- }
730
794
  return {
731
795
  cwd,
732
796
  packageJsonPath,
@@ -747,12 +811,16 @@ function findInstalledDependencyMarkerDir(projectDir) {
747
811
  currentDir = parentDir;
748
812
  }
749
813
  }
750
- function scriptsLikelyNeedInstalledDependencies(project) {
751
- const candidateScripts = project.scripts.sync ? [project.scripts.sync] : [project.scripts["sync-types"], project.scripts["sync-rest"]];
752
- return candidateScripts.some((script) => typeof script === "string" && LOCAL_SYNC_TOOL_PATTERN.test(script));
814
+ function scriptsLikelyNeedInstalledDependencies(project, target) {
815
+ const candidateScripts = target === "ai" ? [project.scripts["sync-ai"]] : project.scripts.sync ? [project.scripts.sync] : [
816
+ project.scripts["sync-types"],
817
+ project.scripts["sync-rest"],
818
+ project.scripts["sync-ai"]
819
+ ];
820
+ return candidateScripts.some((script) => script !== undefined && LOCAL_SYNC_TOOL_PATTERN.test(script.command));
753
821
  }
754
- function assertSyncDependenciesInstalled(project) {
755
- if (!scriptsLikelyNeedInstalledDependencies(project)) {
822
+ function assertSyncDependenciesInstalled(project, target) {
823
+ if (!scriptsLikelyNeedInstalledDependencies(project, target)) {
756
824
  return;
757
825
  }
758
826
  const markerDir = findInstalledDependencyMarkerDir(project.cwd);
@@ -767,7 +835,11 @@ function getPackageManagerRunInvocation(packageManager, scriptName, extraArgs) {
767
835
  return { args: ["run", scriptName, ...extraArgs], command: "bun" };
768
836
  case "npm":
769
837
  return {
770
- args: ["run", scriptName, ...extraArgs.length > 0 ? ["--", ...extraArgs] : []],
838
+ args: [
839
+ "run",
840
+ scriptName,
841
+ ...extraArgs.length > 0 ? ["--", ...extraArgs] : []
842
+ ],
771
843
  command: "npm"
772
844
  };
773
845
  case "pnpm":
@@ -781,23 +853,38 @@ function createSyncPlannedCommand(project, scriptName, extraArgs) {
781
853
  if (!script) {
782
854
  return null;
783
855
  }
784
- const invocation = getPackageManagerRunInvocation(project.packageManager, scriptName, extraArgs);
856
+ const invocation = getPackageManagerRunInvocation(project.packageManager, script.scriptName, extraArgs);
785
857
  return {
786
858
  args: invocation.args,
787
859
  command: invocation.command,
788
- displayCommand: formatRunScript(project.packageManager, scriptName, extraArgs.join(" ")),
789
- scriptName
860
+ displayCommand: formatRunScript(project.packageManager, script.scriptName, extraArgs.join(" ")),
861
+ scriptName: script.scriptName
790
862
  };
791
863
  }
792
- function buildSyncPlannedCommands(project, extraArgs) {
864
+ function buildSyncPlannedCommands(project, extraArgs, target) {
865
+ if (target === "ai") {
866
+ const syncAiCommand2 = createSyncPlannedCommand(project, "sync-ai", extraArgs);
867
+ if (!syncAiCommand2) {
868
+ throw new Error(`Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
869
+ }
870
+ return [syncAiCommand2];
871
+ }
793
872
  if (project.scripts.sync) {
794
873
  return [createSyncPlannedCommand(project, "sync", extraArgs)];
795
874
  }
796
- const plannedCommands = [createSyncPlannedCommand(project, "sync-types", extraArgs)];
875
+ const syncTypesCommand = createSyncPlannedCommand(project, "sync-types", extraArgs);
876
+ if (!syncTypesCommand) {
877
+ throw new Error(`Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
878
+ }
879
+ const plannedCommands = [syncTypesCommand];
797
880
  const syncRestCommand = createSyncPlannedCommand(project, "sync-rest", extraArgs);
798
881
  if (syncRestCommand) {
799
882
  plannedCommands.push(syncRestCommand);
800
883
  }
884
+ const syncAiCommand = createSyncPlannedCommand(project, "sync-ai", extraArgs);
885
+ if (syncAiCommand) {
886
+ plannedCommands.push(syncAiCommand);
887
+ }
801
888
  return plannedCommands;
802
889
  }
803
890
  function runProjectScript(project, plannedCommand, options) {
@@ -826,23 +913,25 @@ async function executeSyncCommand({
826
913
  captureOutput = false,
827
914
  check = false,
828
915
  cwd,
829
- dryRun = false
916
+ dryRun = false,
917
+ target = "default"
830
918
  }) {
831
919
  const project = resolveSyncProjectContext(cwd);
832
920
  const extraArgs = check ? ["--check"] : [];
833
- const plannedCommands = buildSyncPlannedCommands(project, extraArgs);
921
+ const plannedCommands = buildSyncPlannedCommands(project, extraArgs, target);
834
922
  const result = {
835
923
  check,
836
924
  dryRun,
837
925
  packageJsonPath: project.packageJsonPath,
838
926
  packageManager: project.packageManager,
839
927
  plannedCommands,
840
- projectDir: project.cwd
928
+ projectDir: project.cwd,
929
+ target
841
930
  };
842
931
  if (dryRun) {
843
932
  return result;
844
933
  }
845
- assertSyncDependenciesInstalled(project);
934
+ assertSyncDependenciesInstalled(project, target);
846
935
  result.executedCommands = plannedCommands.map((plannedCommand) => runProjectScript(project, plannedCommand, {
847
936
  captureOutput
848
937
  }));
@@ -850,14 +939,14 @@ async function executeSyncCommand({
850
939
  }
851
940
 
852
941
  // src/runtime-bridge.ts
853
- var loadCliAddRuntime = () => import("./cli-add-dcr8ek9z.js");
942
+ var loadCliAddRuntime = () => import("./cli-add-43f9hqev.js");
854
943
  var loadCliDiagnosticsRuntime = () => import("./cli-diagnostics-db6kxv83.js");
855
- var loadCliDoctorRuntime = () => import("./cli-doctor-3myz5bd3.js");
944
+ var loadCliDoctorRuntime = () => import("./cli-doctor-wnx8rv84.js");
856
945
  var loadCliInitRuntime = () => import("./cli-init-gdyp9enw.js");
857
946
  var loadCliPromptRuntime = () => import("./cli-prompt-614tq57c.js");
858
- var loadCliScaffoldRuntime = () => import("./cli-scaffold-w5f4zbz1.js");
947
+ var loadCliScaffoldRuntime = () => import("./cli-scaffold-nt1fx2f0.js");
859
948
  var loadCliTemplatesRuntime = () => import("./cli-templates-9t2a7zqd.js");
860
- var loadMigrationsRuntime = () => import("./migrations-fanyw571.js");
949
+ var loadMigrationsRuntime = () => import("./migrations-1p6mbkyw.js");
861
950
  async function wrapCliCommandError(command, error) {
862
951
  const { createCliCommandError } = await loadCliDiagnosticsRuntime();
863
952
  return createCliCommandError({ command, error });
@@ -920,6 +1009,22 @@ function runRegisteredAddKind(context, plan) {
920
1009
  });
921
1010
  }
922
1011
  var ADD_KIND_EXECUTION_REGISTRY = {
1012
+ ability: async (context) => {
1013
+ const name = requireAddKindName(context, "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.");
1014
+ return runRegisteredAddKind(context, {
1015
+ buildCompletion: (result) => buildAddCompletionPayload({
1016
+ kind: "ability",
1017
+ projectDir: result.projectDir,
1018
+ values: {
1019
+ abilitySlug: result.abilitySlug
1020
+ }
1021
+ }),
1022
+ execute: (targetCwd) => context.addRuntime.runAddAbilityCommand({
1023
+ abilityName: name,
1024
+ cwd: targetCwd
1025
+ })
1026
+ });
1027
+ },
923
1028
  "binding-source": async (context) => {
924
1029
  const name = requireAddKindName(context, "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name>.");
925
1030
  return runRegisteredAddKind(context, {
@@ -994,6 +1099,26 @@ var ADD_KIND_EXECUTION_REGISTRY = {
994
1099
  })
995
1100
  });
996
1101
  },
1102
+ "ai-feature": async (context) => {
1103
+ const name = requireAddKindName(context, "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].");
1104
+ const namespace = readOptionalStringFlag(context.flags, "namespace");
1105
+ return runRegisteredAddKind(context, {
1106
+ buildCompletion: (result) => buildAddCompletionPayload({
1107
+ kind: "ai-feature",
1108
+ projectDir: result.projectDir,
1109
+ values: {
1110
+ aiFeatureSlug: result.aiFeatureSlug,
1111
+ namespace: result.namespace
1112
+ },
1113
+ warnings: result.warnings
1114
+ }),
1115
+ execute: (targetCwd) => context.addRuntime.runAddAiFeatureCommand({
1116
+ aiFeatureName: name,
1117
+ cwd: targetCwd,
1118
+ namespace
1119
+ })
1120
+ });
1121
+ },
997
1122
  "hooked-block": async (context) => {
998
1123
  const name = requireAddKindName(context, "`wp-typia add hooked-block` requires <block-slug>. Usage: wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild>.");
999
1124
  const anchorBlockName = readOptionalStringFlag(context.flags, "anchor");
@@ -1821,7 +1946,7 @@ function loadAddFlow() {
1821
1946
  var addOptions = buildCommandOptions(ADD_OPTION_METADATA);
1822
1947
  var addCommand = defineCommand({
1823
1948
  defaultFormat: "toon",
1824
- description: "Extend an official wp-typia workspace with blocks, variations, patterns, binding sources, plugin-level REST resources, editor plugins, or hooked blocks.",
1949
+ description: "Extend an official wp-typia workspace with blocks, variations, patterns, binding sources, plugin-level REST resources, workflow abilities, server-only AI features, editor plugins, or hooked blocks.",
1825
1950
  handler: async (args) => {
1826
1951
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
1827
1952
  try {
@@ -1958,7 +2083,7 @@ var doctorCommand = defineCommand({
1958
2083
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
1959
2084
  if (prefersStructuredOutput) {
1960
2085
  const [{ getDoctorChecks }, { getDoctorFailureDetailLines }] = await Promise.all([
1961
- import("./cli-doctor-3myz5bd3.js"),
2086
+ import("./cli-doctor-wnx8rv84.js"),
1962
2087
  import("./cli-diagnostics-db6kxv83.js")
1963
2088
  ]);
1964
2089
  const checks = await getDoctorChecks(args.cwd);
@@ -2725,11 +2850,13 @@ var syncCommand = defineCommand({
2725
2850
  const dryRun = Boolean(args.flags["dry-run"]);
2726
2851
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
2727
2852
  try {
2853
+ const target = resolveSyncExecutionTarget(args.positional[0]);
2728
2854
  const sync = await executeSyncCommand({
2729
2855
  captureOutput: prefersStructuredOutput && !dryRun,
2730
2856
  check,
2731
2857
  cwd: args.cwd,
2732
- dryRun
2858
+ dryRun,
2859
+ target
2733
2860
  });
2734
2861
  if (prefersStructuredOutput) {
2735
2862
  args.output({ sync });
@@ -2740,7 +2867,8 @@ var syncCommand = defineCommand({
2740
2867
  check: sync.check,
2741
2868
  packageManager: sync.packageManager,
2742
2869
  plannedCommands: sync.plannedCommands,
2743
- projectDir: sync.projectDir
2870
+ projectDir: sync.projectDir,
2871
+ target: sync.target
2744
2872
  }));
2745
2873
  }
2746
2874
  } catch (error) {
@@ -2820,4 +2948,4 @@ export {
2820
2948
  wpTypiaCommands
2821
2949
  };
2822
2950
 
2823
- //# debugId=BDDF8505CB43292164756E2164756E21
2951
+ //# debugId=F507311661D3283E64756E2164756E21
@@ -15,11 +15,11 @@ import {
15
15
  snapshotProjectVersion,
16
16
  verifyProjectMigrations,
17
17
  wizardProjectMigrations
18
- } from "./cli-qpt5dt0x.js";
18
+ } from "./cli-2rev5hqm.js";
19
19
  import"./cli-gcbre1zs.js";
20
20
  import"./cli-bq2v559b.js";
21
21
  import"./cli-sj5mtyzj.js";
22
- import"./cli-rg481yks.js";
22
+ import"./cli-3w3qxq9w.js";
23
23
  import"./cli-pd5pqgre.js";
24
24
  import"./cli-xnn9xjcy.js";
25
25
  export {