wp-typia 0.22.1 → 0.22.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.
- package/bin/wp-typia.js +15 -1
- package/dist-bunli/.bunli/commands.gen.js +1379 -790
- package/dist-bunli/{cli-add-5z3wpzkh.js → cli-add-p3re8act.js} +506 -124
- package/dist-bunli/{cli-doctor-jd7qyr5s.js → cli-doctor-cjm4rzbk.js} +463 -412
- package/dist-bunli/{cli-init-10nktmme.js → cli-init-7gcthyn1.js} +1 -1
- package/dist-bunli/{cli-0p8wz4a4.js → cli-mpgt29xc.js} +3 -3
- package/dist-bunli/{cli-yzmkz95r.js → cli-prc42zqd.js} +1 -1
- package/dist-bunli/{cli-scaffold-837x3xsv.js → cli-scaffold-x1dp8sz1.js} +3 -3
- package/dist-bunli/{cli-886tjd8m.js → cli-tbd9x8b6.js} +10 -6
- package/dist-bunli/{cli-5md428hf.js → cli-x0h03qqe.js} +197 -73
- package/dist-bunli/cli.js +2 -2
- package/dist-bunli/{command-list-tgyxdhb0.js → command-list-wzej5c7v.js} +84 -92
- package/dist-bunli/{migrations-x3a9t9yf.js → migrations-xfb2h7nf.js} +2 -2
- package/dist-bunli/node-cli.js +120 -119
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY,
|
|
5
5
|
assertExternalLayerCompositionOptions,
|
|
6
6
|
copyInterpolatedDirectory,
|
|
7
|
+
createScaffoldCompatibilityConfig,
|
|
7
8
|
getDefaultAnswers,
|
|
8
9
|
listInterpolatedDirectoryOutputs,
|
|
9
10
|
normalizeOptionalCliString,
|
|
@@ -20,7 +21,7 @@ import {
|
|
|
20
21
|
scaffoldProject,
|
|
21
22
|
syncPersistenceRestArtifacts,
|
|
22
23
|
updatePluginHeaderCompatibility
|
|
23
|
-
} from "./cli-
|
|
24
|
+
} from "./cli-tbd9x8b6.js";
|
|
24
25
|
import {
|
|
25
26
|
DEFAULT_WORDPRESS_ABILITIES_VERSION,
|
|
26
27
|
DEFAULT_WORDPRESS_CORE_ABILITIES_VERSION,
|
|
@@ -33,7 +34,7 @@ import {
|
|
|
33
34
|
} from "./cli-1sm60g1z.js";
|
|
34
35
|
import {
|
|
35
36
|
snapshotProjectVersion
|
|
36
|
-
} from "./cli-
|
|
37
|
+
} from "./cli-prc42zqd.js";
|
|
37
38
|
import {
|
|
38
39
|
ensureMigrationDirectories,
|
|
39
40
|
parseMigrationConfig,
|
|
@@ -57,6 +58,8 @@ import {
|
|
|
57
58
|
assertAdminViewDoesNotExist,
|
|
58
59
|
assertAiFeatureDoesNotExist,
|
|
59
60
|
assertBindingSourceDoesNotExist,
|
|
61
|
+
assertBlockStyleDoesNotExist,
|
|
62
|
+
assertBlockTransformDoesNotExist,
|
|
60
63
|
assertEditorPluginDoesNotExist,
|
|
61
64
|
assertPatternDoesNotExist,
|
|
62
65
|
assertRestResourceDoesNotExist,
|
|
@@ -94,7 +97,7 @@ import {
|
|
|
94
97
|
toPascalCase,
|
|
95
98
|
toSnakeCase,
|
|
96
99
|
toTitleCase
|
|
97
|
-
} from "./cli-
|
|
100
|
+
} from "./cli-x0h03qqe.js";
|
|
98
101
|
import {
|
|
99
102
|
createManagedTempRoot
|
|
100
103
|
} from "./cli-t73q5aqz.js";
|
|
@@ -2376,8 +2379,10 @@ registerBlockBindingsSource( {
|
|
|
2376
2379
|
`;
|
|
2377
2380
|
}
|
|
2378
2381
|
function resolveBindingTarget(options, namespace) {
|
|
2379
|
-
const
|
|
2380
|
-
const
|
|
2382
|
+
const blockName = normalizeOptionalCliString(options.blockName);
|
|
2383
|
+
const attributeName = normalizeOptionalCliString(options.attributeName);
|
|
2384
|
+
const hasBlock = blockName !== undefined;
|
|
2385
|
+
const hasAttribute = attributeName !== undefined;
|
|
2381
2386
|
if (!hasBlock && !hasAttribute) {
|
|
2382
2387
|
return;
|
|
2383
2388
|
}
|
|
@@ -2385,8 +2390,8 @@ function resolveBindingTarget(options, namespace) {
|
|
|
2385
2390
|
throw new Error("`wp-typia add binding-source` requires --block and --attribute to be provided together.");
|
|
2386
2391
|
}
|
|
2387
2392
|
return {
|
|
2388
|
-
attributeName: assertValidBindingAttributeName(
|
|
2389
|
-
blockSlug: resolveBindingTargetBlockSlug(
|
|
2393
|
+
attributeName: assertValidBindingAttributeName(attributeName ?? ""),
|
|
2394
|
+
blockSlug: resolveBindingTargetBlockSlug(blockName ?? "", namespace)
|
|
2390
2395
|
};
|
|
2391
2396
|
}
|
|
2392
2397
|
function formatBindingAttributeTypeMember(attributeName) {
|
|
@@ -4366,12 +4371,14 @@ async function runAddRestResourceCommand({
|
|
|
4366
4371
|
throw error;
|
|
4367
4372
|
}
|
|
4368
4373
|
}
|
|
4369
|
-
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ability.ts
|
|
4374
|
+
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ability-scaffold.ts
|
|
4370
4375
|
var import_semver = __toESM(require_semver(), 1);
|
|
4371
4376
|
import fs5 from "fs";
|
|
4372
4377
|
import { promises as fsp6 } from "fs";
|
|
4373
4378
|
import path10 from "path";
|
|
4374
4379
|
import { syncTypeSchemas as syncTypeSchemas2 } from "@wp-typia/block-runtime/metadata-core";
|
|
4380
|
+
|
|
4381
|
+
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ability-types.ts
|
|
4375
4382
|
var ABILITY_SERVER_GLOB = "/inc/abilities/*.php";
|
|
4376
4383
|
var ABILITY_EDITOR_SCRIPT = "build/abilities/index.js";
|
|
4377
4384
|
var ABILITY_EDITOR_ASSET = "build/abilities/index.asset.php";
|
|
@@ -4379,17 +4386,8 @@ var ABILITY_REGISTRY_END_MARKER = "// wp-typia add ability entries end";
|
|
|
4379
4386
|
var ABILITY_REGISTRY_START_MARKER = "// wp-typia add ability entries start";
|
|
4380
4387
|
var WP_ABILITIES_SCRIPT_MODULE_ID = "@wordpress/abilities";
|
|
4381
4388
|
var WP_CORE_ABILITIES_SCRIPT_MODULE_ID = "@wordpress/core-abilities";
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
return requiredVersion;
|
|
4385
|
-
}
|
|
4386
|
-
const existingMinimum = import_semver.default.minVersion(existingVersion);
|
|
4387
|
-
const requiredMinimum = import_semver.default.minVersion(requiredVersion);
|
|
4388
|
-
if (!existingMinimum || !requiredMinimum) {
|
|
4389
|
-
return requiredVersion;
|
|
4390
|
-
}
|
|
4391
|
-
return import_semver.default.gte(existingMinimum, requiredMinimum) ? existingVersion : requiredVersion;
|
|
4392
|
-
}
|
|
4389
|
+
|
|
4390
|
+
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ability-templates.ts
|
|
4393
4391
|
function toAbilityCategorySlug(workspaceNamespace) {
|
|
4394
4392
|
const normalizedNamespace = workspaceNamespace.replace(/[^a-z0-9-]+/gu, "-").replace(/-{2,}/gu, "-").replace(/^-|-$/gu, "");
|
|
4395
4393
|
return `${normalizedNamespace || "workspace"}-workflows`;
|
|
@@ -4854,6 +4852,19 @@ function buildAbilityRegistrySource(abilitySlugs) {
|
|
|
4854
4852
|
`).concat(`
|
|
4855
4853
|
`);
|
|
4856
4854
|
}
|
|
4855
|
+
|
|
4856
|
+
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ability-scaffold.ts
|
|
4857
|
+
function resolveManagedDependencyVersion(existingVersion, requiredVersion) {
|
|
4858
|
+
if (!existingVersion) {
|
|
4859
|
+
return requiredVersion;
|
|
4860
|
+
}
|
|
4861
|
+
const existingMinimum = import_semver.default.minVersion(existingVersion);
|
|
4862
|
+
const requiredMinimum = import_semver.default.minVersion(requiredVersion);
|
|
4863
|
+
if (!existingMinimum || !requiredMinimum) {
|
|
4864
|
+
return requiredVersion;
|
|
4865
|
+
}
|
|
4866
|
+
return import_semver.default.gte(existingMinimum, requiredMinimum) ? existingVersion : requiredVersion;
|
|
4867
|
+
}
|
|
4857
4868
|
function resolveAbilityRegistryPath(projectDir) {
|
|
4858
4869
|
const abilitiesDir = path10.join(projectDir, "src", "abilities");
|
|
4859
4870
|
return [path10.join(abilitiesDir, "index.ts"), path10.join(abilitiesDir, "index.js")].find((candidatePath) => fs5.existsSync(candidatePath)) ?? path10.join(abilitiesDir, "index.ts");
|
|
@@ -5065,21 +5076,29 @@ async function ensureAbilityBuildScriptAnchors(workspace) {
|
|
|
5065
5076
|
}
|
|
5066
5077
|
const sharedEntriesPattern = /(for\s*\(\s*const\s+relativePath\s+of\s+\[)([\s\S]*?)(\]\s*\)\s*\{)/u;
|
|
5067
5078
|
const match = nextSource.match(sharedEntriesPattern);
|
|
5068
|
-
if (!match ||
|
|
5079
|
+
if (!match || !/['"]src\/bindings\/index\.(?:ts|js)['"]/u.test(match[2]) || !/['"]src\/editor-plugins\/index\.(?:tsx|ts|js)['"]/u.test(match[2])) {
|
|
5069
5080
|
throw new Error([
|
|
5070
5081
|
`ensureAbilityBuildScriptAnchors could not patch ${path10.basename(buildScriptPath)}.`,
|
|
5071
5082
|
"Missing the expected shared editor entries array in scripts/build-workspace.mjs.",
|
|
5072
5083
|
"Restore the generated template or wire abilities/index manually before retrying."
|
|
5073
5084
|
].join(" "));
|
|
5074
5085
|
}
|
|
5075
|
-
nextSource = nextSource.replace(sharedEntriesPattern,
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5086
|
+
nextSource = nextSource.replace(sharedEntriesPattern, (fullMatch, sharedEntries) => {
|
|
5087
|
+
const missingAbilityEntries = [
|
|
5088
|
+
"'src/abilities/index.ts'",
|
|
5089
|
+
"'src/abilities/index.js'"
|
|
5090
|
+
].filter((entry) => !sharedEntries.includes(entry));
|
|
5091
|
+
if (missingAbilityEntries.length === 0) {
|
|
5092
|
+
return fullMatch;
|
|
5093
|
+
}
|
|
5094
|
+
const itemIndent = sharedEntries.match(/\n([ \t]*)['"]/u)?.[1] ?? "\t\t";
|
|
5095
|
+
const trimmedEntries = sharedEntries.replace(/\s*$/u, "");
|
|
5096
|
+
const trailingWhitespace = sharedEntries.slice(trimmedEntries.length);
|
|
5097
|
+
const separator = trimmedEntries.trimEnd().endsWith(",") ? "" : ",";
|
|
5098
|
+
const nextEntries = `${trimmedEntries}${separator}` + missingAbilityEntries.map((entry) => `
|
|
5099
|
+
${itemIndent}${entry},`).join("") + trailingWhitespace;
|
|
5100
|
+
return fullMatch.replace(sharedEntries, nextEntries);
|
|
5101
|
+
});
|
|
5083
5102
|
return nextSource;
|
|
5084
5103
|
});
|
|
5085
5104
|
}
|
|
@@ -5108,8 +5127,7 @@ async function ensureAbilityWebpackAnchors(workspace) {
|
|
|
5108
5127
|
entries.push( [ entryName, entryPath ] );
|
|
5109
5128
|
break;
|
|
5110
5129
|
}
|
|
5111
|
-
}
|
|
5112
|
-
$2`);
|
|
5130
|
+
}$2`);
|
|
5113
5131
|
}
|
|
5114
5132
|
const sharedEntriesPattern = /for\s*\(\s*const\s+\[\s*entryName\s*,\s*candidates\s*\]\s+of\s+\[([\s\S]*?)\]\s*\)\s*\{/u;
|
|
5115
5133
|
const match = source.match(sharedEntriesPattern);
|
|
@@ -5120,31 +5138,33 @@ $2`);
|
|
|
5120
5138
|
"Restore the generated template or wire abilities/index manually before retrying."
|
|
5121
5139
|
].join(" "));
|
|
5122
5140
|
}
|
|
5123
|
-
return source.replace(sharedEntriesPattern,
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5141
|
+
return source.replace(sharedEntriesPattern, (fullMatch, sharedEntries) => {
|
|
5142
|
+
if (/['"]abilities\/index['"]/u.test(sharedEntries)) {
|
|
5143
|
+
return fullMatch;
|
|
5144
|
+
}
|
|
5145
|
+
const tupleIndent = sharedEntries.match(/\n([ \t]*)\[/u)?.[1] ?? "\t\t";
|
|
5146
|
+
const nestedIndent = `${tupleIndent} `;
|
|
5147
|
+
const trimmedEntries = sharedEntries.replace(/\s*$/u, "");
|
|
5148
|
+
const trailingWhitespace = sharedEntries.slice(trimmedEntries.length);
|
|
5149
|
+
const separator = trimmedEntries.trimEnd().endsWith(",") ? "" : ",";
|
|
5150
|
+
const abilityTuple = [
|
|
5151
|
+
`${tupleIndent}[`,
|
|
5152
|
+
`${nestedIndent}'abilities/index',`,
|
|
5153
|
+
`${nestedIndent}[ 'src/abilities/index.ts', 'src/abilities/index.js' ],`,
|
|
5154
|
+
`${tupleIndent}],`
|
|
5155
|
+
].join(`
|
|
5156
|
+
`);
|
|
5157
|
+
const nextEntries = `${trimmedEntries}${separator}
|
|
5158
|
+
${abilityTuple}` + trailingWhitespace;
|
|
5159
|
+
return fullMatch.replace(sharedEntries, nextEntries);
|
|
5160
|
+
});
|
|
5137
5161
|
});
|
|
5138
5162
|
}
|
|
5139
|
-
async function
|
|
5140
|
-
|
|
5141
|
-
|
|
5163
|
+
async function scaffoldAbilityWorkspace({
|
|
5164
|
+
abilitySlug,
|
|
5165
|
+
compatibilityPolicy,
|
|
5166
|
+
workspace
|
|
5142
5167
|
}) {
|
|
5143
|
-
const workspace = resolveWorkspaceProject(cwd);
|
|
5144
|
-
const abilitySlug = assertValidGeneratedSlug("Ability name", normalizeBlockSlug(abilityName), "wp-typia add ability <name>");
|
|
5145
|
-
const inventory = readWorkspaceInventory(workspace.projectDir);
|
|
5146
|
-
assertAbilityDoesNotExist(workspace.projectDir, abilitySlug, inventory);
|
|
5147
|
-
const compatibilityPolicy = resolveScaffoldCompatibilityPolicy(REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY);
|
|
5148
5168
|
const blockConfigPath = path10.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
5149
5169
|
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
5150
5170
|
const buildScriptPath = path10.join(workspace.projectDir, "scripts", "build-workspace.mjs");
|
|
@@ -5203,18 +5223,37 @@ async function runAddAbilityCommand({
|
|
|
5203
5223
|
});
|
|
5204
5224
|
await writeAbilityRegistry(workspace.projectDir, abilitySlug);
|
|
5205
5225
|
await appendWorkspaceInventoryEntries(workspace.projectDir, {
|
|
5206
|
-
abilityEntries: [
|
|
5226
|
+
abilityEntries: [
|
|
5227
|
+
buildAbilityConfigEntry(abilitySlug, compatibilityPolicy)
|
|
5228
|
+
]
|
|
5207
5229
|
});
|
|
5208
|
-
return {
|
|
5209
|
-
abilitySlug,
|
|
5210
|
-
projectDir: workspace.projectDir
|
|
5211
|
-
};
|
|
5212
5230
|
} catch (error) {
|
|
5213
5231
|
await rollbackWorkspaceMutation(mutationSnapshot);
|
|
5214
5232
|
throw error;
|
|
5215
5233
|
}
|
|
5216
5234
|
}
|
|
5217
|
-
|
|
5235
|
+
|
|
5236
|
+
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ability.ts
|
|
5237
|
+
async function runAddAbilityCommand({
|
|
5238
|
+
abilityName,
|
|
5239
|
+
cwd = process.cwd()
|
|
5240
|
+
}) {
|
|
5241
|
+
const workspace = resolveWorkspaceProject(cwd);
|
|
5242
|
+
const abilitySlug = assertValidGeneratedSlug("Ability name", normalizeBlockSlug(abilityName), "wp-typia add ability <name>");
|
|
5243
|
+
const inventory = readWorkspaceInventory(workspace.projectDir);
|
|
5244
|
+
assertAbilityDoesNotExist(workspace.projectDir, abilitySlug, inventory);
|
|
5245
|
+
const compatibilityPolicy = resolveScaffoldCompatibilityPolicy(REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY);
|
|
5246
|
+
await scaffoldAbilityWorkspace({
|
|
5247
|
+
abilitySlug,
|
|
5248
|
+
compatibilityPolicy,
|
|
5249
|
+
workspace
|
|
5250
|
+
});
|
|
5251
|
+
return {
|
|
5252
|
+
abilitySlug,
|
|
5253
|
+
projectDir: workspace.projectDir
|
|
5254
|
+
};
|
|
5255
|
+
}
|
|
5256
|
+
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ai-scaffold.ts
|
|
5218
5257
|
import { promises as fsp8 } from "fs";
|
|
5219
5258
|
import path13 from "path";
|
|
5220
5259
|
|
|
@@ -5435,6 +5474,45 @@ export interface ${pascalCase}AiFeatureResponse {
|
|
|
5435
5474
|
result: ${pascalCase}AiFeatureResult;
|
|
5436
5475
|
telemetry: ${pascalCase}AiFeatureTelemetry;
|
|
5437
5476
|
}
|
|
5477
|
+
|
|
5478
|
+
export type ${pascalCase}AiFeatureSupportProbeMode = 'request-time';
|
|
5479
|
+
|
|
5480
|
+
export type ${pascalCase}AiFeatureUnavailableErrorCode =
|
|
5481
|
+
'ai_client_unavailable';
|
|
5482
|
+
|
|
5483
|
+
export type ${pascalCase}AiFeatureUnavailableReasonCode =
|
|
5484
|
+
| 'missing-wordpress-ai-client'
|
|
5485
|
+
| 'request-time-support-probe';
|
|
5486
|
+
|
|
5487
|
+
export interface ${pascalCase}AiFeatureSupportReason {
|
|
5488
|
+
code: ${pascalCase}AiFeatureUnavailableReasonCode;
|
|
5489
|
+
label: string & tags.MinLength< 1 > & tags.MaxLength< 160 >;
|
|
5490
|
+
message: string & tags.MinLength< 1 > & tags.MaxLength< 4000 >;
|
|
5491
|
+
}
|
|
5492
|
+
|
|
5493
|
+
export interface ${pascalCase}AiFeatureSupportMetadata {
|
|
5494
|
+
featureLabel: string & tags.MinLength< 1 > & tags.MaxLength< 160 >;
|
|
5495
|
+
featureSlug: string & tags.MinLength< 1 > & tags.MaxLength< 160 >;
|
|
5496
|
+
compatibility: {
|
|
5497
|
+
hardMinimums: {
|
|
5498
|
+
php?: string;
|
|
5499
|
+
wordpress?: string;
|
|
5500
|
+
};
|
|
5501
|
+
mode: 'baseline' | 'optional' | 'required';
|
|
5502
|
+
optionalFeatureIds: string[];
|
|
5503
|
+
optionalFeatures: string[];
|
|
5504
|
+
requiredFeatureIds: string[];
|
|
5505
|
+
requiredFeatures: string[];
|
|
5506
|
+
runtimeGates: string[];
|
|
5507
|
+
};
|
|
5508
|
+
supportProbe: {
|
|
5509
|
+
endpointMethod: 'POST';
|
|
5510
|
+
endpointPath: string & tags.MinLength< 1 > & tags.MaxLength< 200 >;
|
|
5511
|
+
mode: ${pascalCase}AiFeatureSupportProbeMode;
|
|
5512
|
+
unavailableErrorCode: ${pascalCase}AiFeatureUnavailableErrorCode;
|
|
5513
|
+
};
|
|
5514
|
+
unavailableReasons: ${pascalCase}AiFeatureSupportReason[];
|
|
5515
|
+
}
|
|
5438
5516
|
`;
|
|
5439
5517
|
}
|
|
5440
5518
|
function buildAiFeatureValidatorsSource(aiFeatureSlug) {
|
|
@@ -5470,6 +5548,8 @@ export const apiValidators = {
|
|
|
5470
5548
|
}
|
|
5471
5549
|
function buildAiFeatureApiSource(aiFeatureSlug) {
|
|
5472
5550
|
const pascalCase = toPascalCase(aiFeatureSlug);
|
|
5551
|
+
const compatibility = createScaffoldCompatibilityConfig(resolveScaffoldCompatibilityPolicy(OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY));
|
|
5552
|
+
const title = toTitleCase(aiFeatureSlug);
|
|
5473
5553
|
return `import {
|
|
5474
5554
|
callEndpoint,
|
|
5475
5555
|
resolveRestRouteUrl,
|
|
@@ -5477,6 +5557,7 @@ function buildAiFeatureApiSource(aiFeatureSlug) {
|
|
|
5477
5557
|
|
|
5478
5558
|
import type {
|
|
5479
5559
|
${pascalCase}AiFeatureRequest,
|
|
5560
|
+
${pascalCase}AiFeatureSupportMetadata,
|
|
5480
5561
|
} from './api-types';
|
|
5481
5562
|
import {
|
|
5482
5563
|
run${pascalCase}AiFeatureEndpoint,
|
|
@@ -5503,6 +5584,14 @@ function resolveRestNonce( fallback?: string ): string | undefined {
|
|
|
5503
5584
|
: undefined;
|
|
5504
5585
|
}
|
|
5505
5586
|
|
|
5587
|
+
function isPlainObject( value: unknown ): value is Record< string, unknown > {
|
|
5588
|
+
return (
|
|
5589
|
+
!! value &&
|
|
5590
|
+
typeof value === 'object' &&
|
|
5591
|
+
! Array.isArray( value )
|
|
5592
|
+
);
|
|
5593
|
+
}
|
|
5594
|
+
|
|
5506
5595
|
export const aiFeatureRunEndpoint = {
|
|
5507
5596
|
...run${pascalCase}AiFeatureEndpoint,
|
|
5508
5597
|
buildRequestOptions: () => {
|
|
@@ -5518,6 +5607,63 @@ export const aiFeatureRunEndpoint = {
|
|
|
5518
5607
|
},
|
|
5519
5608
|
};
|
|
5520
5609
|
|
|
5610
|
+
export const aiFeatureSupportMetadata = {
|
|
5611
|
+
compatibility: ${JSON.stringify(compatibility, null, "\t")},
|
|
5612
|
+
featureLabel: ${quoteTsString(title)},
|
|
5613
|
+
featureSlug: ${quoteTsString(aiFeatureSlug)},
|
|
5614
|
+
supportProbe: {
|
|
5615
|
+
endpointMethod: 'POST',
|
|
5616
|
+
endpointPath: aiFeatureRunEndpoint.path,
|
|
5617
|
+
mode: 'request-time',
|
|
5618
|
+
unavailableErrorCode: 'ai_client_unavailable',
|
|
5619
|
+
},
|
|
5620
|
+
unavailableReasons: [
|
|
5621
|
+
{
|
|
5622
|
+
code: 'missing-wordpress-ai-client',
|
|
5623
|
+
label: 'WordPress AI Client unavailable',
|
|
5624
|
+
message:
|
|
5625
|
+
'This AI feature stays disabled until the WordPress AI Client is available on the site.',
|
|
5626
|
+
},
|
|
5627
|
+
{
|
|
5628
|
+
code: 'request-time-support-probe',
|
|
5629
|
+
label: 'Support is checked at request time',
|
|
5630
|
+
message:
|
|
5631
|
+
'Support is verified when the feature runs, so editor and admin UIs should degrade gracefully when the site rejects the request.',
|
|
5632
|
+
},
|
|
5633
|
+
],
|
|
5634
|
+
} satisfies ${pascalCase}AiFeatureSupportMetadata;
|
|
5635
|
+
|
|
5636
|
+
export function getAiFeatureSupportHintLines() {
|
|
5637
|
+
return aiFeatureSupportMetadata.unavailableReasons.map(
|
|
5638
|
+
( reason ) => reason.message
|
|
5639
|
+
);
|
|
5640
|
+
}
|
|
5641
|
+
|
|
5642
|
+
export function isAiFeatureSupportUnavailableError( error: unknown ) {
|
|
5643
|
+
if ( ! isPlainObject( error ) ) {
|
|
5644
|
+
return false;
|
|
5645
|
+
}
|
|
5646
|
+
|
|
5647
|
+
const data = isPlainObject( error.data ) ? error.data : undefined;
|
|
5648
|
+
return (
|
|
5649
|
+
error.code === aiFeatureSupportMetadata.supportProbe.unavailableErrorCode ||
|
|
5650
|
+
data?.status === 501
|
|
5651
|
+
);
|
|
5652
|
+
}
|
|
5653
|
+
|
|
5654
|
+
export function resolveAiFeatureUnavailableMessage( error: unknown ) {
|
|
5655
|
+
if (
|
|
5656
|
+
isPlainObject( error ) &&
|
|
5657
|
+
typeof error.message === 'string' &&
|
|
5658
|
+
error.message.length > 0
|
|
5659
|
+
) {
|
|
5660
|
+
return error.message;
|
|
5661
|
+
}
|
|
5662
|
+
|
|
5663
|
+
return aiFeatureSupportMetadata.unavailableReasons[ 0 ]?.message ??
|
|
5664
|
+
'This AI feature is currently unavailable.';
|
|
5665
|
+
}
|
|
5666
|
+
|
|
5521
5667
|
export function runAiFeature( request: ${pascalCase}AiFeatureRequest ) {
|
|
5522
5668
|
return callEndpoint( aiFeatureRunEndpoint, request );
|
|
5523
5669
|
}
|
|
@@ -5536,6 +5682,10 @@ import type {
|
|
|
5536
5682
|
} from './api-types';
|
|
5537
5683
|
import {
|
|
5538
5684
|
aiFeatureRunEndpoint,
|
|
5685
|
+
aiFeatureSupportMetadata,
|
|
5686
|
+
getAiFeatureSupportHintLines,
|
|
5687
|
+
isAiFeatureSupportUnavailableError,
|
|
5688
|
+
resolveAiFeatureUnavailableMessage,
|
|
5539
5689
|
} from './api';
|
|
5540
5690
|
|
|
5541
5691
|
export type UseRun${pascalCase}AiFeatureMutationOptions =
|
|
@@ -5550,6 +5700,13 @@ export function useRun${pascalCase}AiFeatureMutation(
|
|
|
5550
5700
|
) {
|
|
5551
5701
|
return useEndpointMutation( aiFeatureRunEndpoint, options );
|
|
5552
5702
|
}
|
|
5703
|
+
|
|
5704
|
+
export {
|
|
5705
|
+
aiFeatureSupportMetadata,
|
|
5706
|
+
getAiFeatureSupportHintLines,
|
|
5707
|
+
isAiFeatureSupportUnavailableError,
|
|
5708
|
+
resolveAiFeatureUnavailableMessage,
|
|
5709
|
+
};
|
|
5553
5710
|
`;
|
|
5554
5711
|
}
|
|
5555
5712
|
function buildAiFeatureSyncScriptSource() {
|
|
@@ -5953,7 +6110,7 @@ async function ensureAiFeatureSyncRestAnchors(workspace) {
|
|
|
5953
6110
|
});
|
|
5954
6111
|
}
|
|
5955
6112
|
|
|
5956
|
-
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ai.ts
|
|
6113
|
+
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ai-templates.ts
|
|
5957
6114
|
function buildAiFeaturePhpSource(aiFeatureSlug, namespace, phpPrefix, textDomain) {
|
|
5958
6115
|
const aiFeatureTitle = toTitleCase(aiFeatureSlug);
|
|
5959
6116
|
const aiFeaturePhpId = aiFeatureSlug.replace(/-/g, "_");
|
|
@@ -5962,18 +6119,40 @@ function buildAiFeaturePhpSource(aiFeatureSlug, namespace, phpPrefix, textDomain
|
|
|
5962
6119
|
const normalizeSchemaFunctionName = `${phpPrefix}_${aiFeaturePhpId}_sanitize_ai_feature_schema`;
|
|
5963
6120
|
const validatePayloadFunctionName = `${phpPrefix}_${aiFeaturePhpId}_validate_ai_feature_payload`;
|
|
5964
6121
|
const canManageFunctionName = `${phpPrefix}_${aiFeaturePhpId}_can_manage_ai_feature`;
|
|
6122
|
+
const normalizePromptPayloadFunctionName = `${phpPrefix}_${aiFeaturePhpId}_normalize_ai_feature_prompt_payload`;
|
|
5965
6123
|
const buildPromptFunctionName = `${phpPrefix}_${aiFeaturePhpId}_build_ai_feature_prompt`;
|
|
6124
|
+
const resolvePromptOptionsFunctionName = `${phpPrefix}_${aiFeaturePhpId}_resolve_ai_feature_prompt_options`;
|
|
5966
6125
|
const normalizeProviderTypeFunctionName = `${phpPrefix}_${aiFeaturePhpId}_normalize_provider_type`;
|
|
5967
6126
|
const buildTelemetryFunctionName = `${phpPrefix}_${aiFeaturePhpId}_build_ai_feature_telemetry`;
|
|
6127
|
+
const resolveUnavailableMessageFunctionName = `${phpPrefix}_${aiFeaturePhpId}_resolve_ai_feature_unavailable_message`;
|
|
5968
6128
|
const isSupportedFunctionName = `${phpPrefix}_${aiFeaturePhpId}_is_ai_feature_supported`;
|
|
5969
6129
|
const adminNoticeFunctionName = `${phpPrefix}_${aiFeaturePhpId}_ai_feature_admin_notice`;
|
|
5970
6130
|
const handlerFunctionName = `${phpPrefix}_${aiFeaturePhpId}_handle_run_ai_feature`;
|
|
5971
6131
|
const registerRoutesFunctionName = `${phpPrefix}_${aiFeaturePhpId}_register_ai_feature_routes`;
|
|
6132
|
+
const permissionFilterHook = `${phpPrefix}_${aiFeaturePhpId}_ai_feature_permission`;
|
|
6133
|
+
const promptPayloadFilterHook = `${phpPrefix}_${aiFeaturePhpId}_ai_feature_prompt_payload`;
|
|
6134
|
+
const promptFilterHook = `${phpPrefix}_${aiFeaturePhpId}_ai_feature_prompt`;
|
|
6135
|
+
const promptOptionsFilterHook = `${phpPrefix}_${aiFeaturePhpId}_ai_feature_prompt_options`;
|
|
6136
|
+
const adminNoticeMessageFilterHook = `${phpPrefix}_${aiFeaturePhpId}_ai_feature_admin_notice_message`;
|
|
6137
|
+
const unavailableMessageFilterHook = `${phpPrefix}_${aiFeaturePhpId}_ai_feature_unavailable_message`;
|
|
6138
|
+
const telemetryFilterHook = `${phpPrefix}_${aiFeaturePhpId}_ai_feature_telemetry`;
|
|
5972
6139
|
return `<?php
|
|
5973
6140
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
5974
6141
|
return;
|
|
5975
6142
|
}
|
|
5976
6143
|
|
|
6144
|
+
/*
|
|
6145
|
+
* Customization hooks for the ${aiFeatureTitle} AI feature:
|
|
6146
|
+
*
|
|
6147
|
+
* - ${quotePhpString(permissionFilterHook)} filters the default current_user_can( 'edit_posts' ) capability check.
|
|
6148
|
+
* - ${quotePhpString(promptPayloadFilterHook)} filters the validated request payload array before prompt serialization.
|
|
6149
|
+
* - ${quotePhpString(promptFilterHook)} filters the final prompt string after payload normalization.
|
|
6150
|
+
* - ${quotePhpString(promptOptionsFilterHook)} filters prompt options with \`temperature\` and \`modelPreference\` keys.
|
|
6151
|
+
* - ${quotePhpString(adminNoticeMessageFilterHook)} filters the wp-admin notice shown when AI support is unavailable.
|
|
6152
|
+
* - ${quotePhpString(unavailableMessageFilterHook)} filters REST-facing unavailable messages by reason code.
|
|
6153
|
+
* - ${quotePhpString(telemetryFilterHook)} filters the response telemetry array before schema validation. Return a schema-compatible array.
|
|
6154
|
+
*/
|
|
6155
|
+
|
|
5977
6156
|
if ( ! function_exists( '${loadSchemaFunctionName}' ) ) {
|
|
5978
6157
|
function ${loadSchemaFunctionName}( $schema_name ) {
|
|
5979
6158
|
$project_root = dirname( __DIR__, 2 );
|
|
@@ -6040,17 +6219,111 @@ if ( ! function_exists( '${validatePayloadFunctionName}' ) ) {
|
|
|
6040
6219
|
}
|
|
6041
6220
|
|
|
6042
6221
|
if ( ! function_exists( '${canManageFunctionName}' ) ) {
|
|
6043
|
-
function ${canManageFunctionName}() {
|
|
6044
|
-
|
|
6222
|
+
function ${canManageFunctionName}( WP_REST_Request $request = null ) {
|
|
6223
|
+
$permission = apply_filters(
|
|
6224
|
+
${quotePhpString(permissionFilterHook)},
|
|
6225
|
+
current_user_can( 'edit_posts' ),
|
|
6226
|
+
$request
|
|
6227
|
+
);
|
|
6228
|
+
if ( is_wp_error( $permission ) ) {
|
|
6229
|
+
return $permission;
|
|
6230
|
+
}
|
|
6231
|
+
return (bool) $permission;
|
|
6232
|
+
}
|
|
6233
|
+
}
|
|
6234
|
+
|
|
6235
|
+
if ( ! function_exists( '${normalizePromptPayloadFunctionName}' ) ) {
|
|
6236
|
+
function ${normalizePromptPayloadFunctionName}( array $payload ) {
|
|
6237
|
+
$normalized_payload = apply_filters(
|
|
6238
|
+
${quotePhpString(promptPayloadFilterHook)},
|
|
6239
|
+
$payload
|
|
6240
|
+
);
|
|
6241
|
+
return is_array( $normalized_payload ) ? $normalized_payload : $payload;
|
|
6045
6242
|
}
|
|
6046
6243
|
}
|
|
6047
6244
|
|
|
6048
6245
|
if ( ! function_exists( '${buildPromptFunctionName}' ) ) {
|
|
6049
6246
|
function ${buildPromptFunctionName}( array $payload ) {
|
|
6050
|
-
|
|
6247
|
+
$normalized_payload = ${normalizePromptPayloadFunctionName}( $payload );
|
|
6248
|
+
$prompt = sprintf(
|
|
6051
6249
|
'You are helping with the %1$s AI workflow. Read the JSON request payload and return JSON that matches the provided schema. Request payload: %2$s',
|
|
6052
6250
|
${quotePhpString(aiFeatureTitle)},
|
|
6053
|
-
wp_json_encode( $
|
|
6251
|
+
wp_json_encode( $normalized_payload )
|
|
6252
|
+
);
|
|
6253
|
+
$filtered_prompt = apply_filters(
|
|
6254
|
+
${quotePhpString(promptFilterHook)},
|
|
6255
|
+
$prompt,
|
|
6256
|
+
$normalized_payload,
|
|
6257
|
+
$payload
|
|
6258
|
+
);
|
|
6259
|
+
return is_string( $filtered_prompt ) && '' !== $filtered_prompt ? $filtered_prompt : $prompt;
|
|
6260
|
+
}
|
|
6261
|
+
}
|
|
6262
|
+
|
|
6263
|
+
if ( ! function_exists( '${resolvePromptOptionsFunctionName}' ) ) {
|
|
6264
|
+
function ${resolvePromptOptionsFunctionName}( array $payload = array() ) {
|
|
6265
|
+
$options = apply_filters(
|
|
6266
|
+
${quotePhpString(promptOptionsFilterHook)},
|
|
6267
|
+
array(
|
|
6268
|
+
'modelPreference' => array(),
|
|
6269
|
+
'temperature' => 0.2,
|
|
6270
|
+
),
|
|
6271
|
+
$payload
|
|
6272
|
+
);
|
|
6273
|
+
if ( ! is_array( $options ) ) {
|
|
6274
|
+
$options = array();
|
|
6275
|
+
}
|
|
6276
|
+
|
|
6277
|
+
$temperature = 0.2;
|
|
6278
|
+
if ( array_key_exists( 'temperature', $options ) ) {
|
|
6279
|
+
if ( null === $options['temperature'] ) {
|
|
6280
|
+
$temperature = null;
|
|
6281
|
+
} elseif ( is_numeric( $options['temperature'] ) ) {
|
|
6282
|
+
$temperature = (float) $options['temperature'];
|
|
6283
|
+
}
|
|
6284
|
+
}
|
|
6285
|
+
|
|
6286
|
+
$model_preferences = array();
|
|
6287
|
+
if ( isset( $options['modelPreference'] ) ) {
|
|
6288
|
+
$raw_model_preferences = $options['modelPreference'];
|
|
6289
|
+
if ( is_string( $raw_model_preferences ) && '' !== $raw_model_preferences ) {
|
|
6290
|
+
$model_preferences = array( $raw_model_preferences );
|
|
6291
|
+
} elseif ( is_array( $raw_model_preferences ) ) {
|
|
6292
|
+
$model_preferences = array_values(
|
|
6293
|
+
array_filter(
|
|
6294
|
+
array_map(
|
|
6295
|
+
static function ( $candidate ) {
|
|
6296
|
+
if ( is_string( $candidate ) && '' !== $candidate ) {
|
|
6297
|
+
return $candidate;
|
|
6298
|
+
}
|
|
6299
|
+
if ( ! is_array( $candidate ) ) {
|
|
6300
|
+
return null;
|
|
6301
|
+
}
|
|
6302
|
+
|
|
6303
|
+
$normalized = array_values(
|
|
6304
|
+
array_filter(
|
|
6305
|
+
$candidate,
|
|
6306
|
+
static function ( $value ) {
|
|
6307
|
+
return is_string( $value ) && '' !== $value;
|
|
6308
|
+
}
|
|
6309
|
+
)
|
|
6310
|
+
);
|
|
6311
|
+
|
|
6312
|
+
return count( $normalized ) > 0 ? $normalized : null;
|
|
6313
|
+
},
|
|
6314
|
+
$raw_model_preferences
|
|
6315
|
+
),
|
|
6316
|
+
static function ( $candidate ) {
|
|
6317
|
+
return null !== $candidate;
|
|
6318
|
+
}
|
|
6319
|
+
)
|
|
6320
|
+
);
|
|
6321
|
+
}
|
|
6322
|
+
}
|
|
6323
|
+
|
|
6324
|
+
return array(
|
|
6325
|
+
'modelPreference' => $model_preferences,
|
|
6326
|
+
'temperature' => $temperature,
|
|
6054
6327
|
);
|
|
6055
6328
|
}
|
|
6056
6329
|
}
|
|
@@ -6066,7 +6339,7 @@ if ( ! function_exists( '${normalizeProviderTypeFunctionName}' ) ) {
|
|
|
6066
6339
|
}
|
|
6067
6340
|
|
|
6068
6341
|
if ( ! function_exists( '${buildTelemetryFunctionName}' ) ) {
|
|
6069
|
-
function ${buildTelemetryFunctionName}( $result ) {
|
|
6342
|
+
function ${buildTelemetryFunctionName}( $result, array $payload = array(), array $normalized_result = array() ) {
|
|
6070
6343
|
if (
|
|
6071
6344
|
! is_object( $result ) ||
|
|
6072
6345
|
! method_exists( $result, 'getId' ) ||
|
|
@@ -6126,47 +6399,95 @@ if ( ! function_exists( '${buildTelemetryFunctionName}' ) ) {
|
|
|
6126
6399
|
}
|
|
6127
6400
|
}
|
|
6128
6401
|
|
|
6129
|
-
|
|
6402
|
+
$filtered_telemetry = apply_filters(
|
|
6403
|
+
${quotePhpString(telemetryFilterHook)},
|
|
6404
|
+
$telemetry,
|
|
6405
|
+
$result,
|
|
6406
|
+
$payload,
|
|
6407
|
+
$normalized_result
|
|
6408
|
+
);
|
|
6409
|
+
return is_array( $filtered_telemetry ) ? $filtered_telemetry : $telemetry;
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6412
|
+
|
|
6413
|
+
if ( ! function_exists( '${resolveUnavailableMessageFunctionName}' ) ) {
|
|
6414
|
+
function ${resolveUnavailableMessageFunctionName}( $message, $reason, array $context = array() ) {
|
|
6415
|
+
$filtered_message = apply_filters(
|
|
6416
|
+
${quotePhpString(unavailableMessageFilterHook)},
|
|
6417
|
+
$message,
|
|
6418
|
+
$reason,
|
|
6419
|
+
$context
|
|
6420
|
+
);
|
|
6421
|
+
return is_string( $filtered_message ) && '' !== $filtered_message ? $filtered_message : $message;
|
|
6130
6422
|
}
|
|
6131
6423
|
}
|
|
6132
6424
|
|
|
6133
6425
|
if ( ! function_exists( '${isSupportedFunctionName}' ) ) {
|
|
6134
|
-
function ${isSupportedFunctionName}() {
|
|
6426
|
+
function ${isSupportedFunctionName}( array $payload = array(), $cache_result = true ) {
|
|
6135
6427
|
static $is_supported = null;
|
|
6136
|
-
|
|
6428
|
+
$use_cache = $cache_result && count( $payload ) === 0;
|
|
6429
|
+
if ( $use_cache && null !== $is_supported ) {
|
|
6137
6430
|
return $is_supported;
|
|
6138
6431
|
}
|
|
6139
6432
|
|
|
6140
6433
|
if ( ! function_exists( 'wp_ai_client_prompt' ) ) {
|
|
6141
|
-
$
|
|
6142
|
-
|
|
6434
|
+
if ( $use_cache ) {
|
|
6435
|
+
$is_supported = false;
|
|
6436
|
+
}
|
|
6437
|
+
return false;
|
|
6143
6438
|
}
|
|
6144
6439
|
|
|
6145
6440
|
$schema = ${loadAiSchemaFunctionName}();
|
|
6146
6441
|
if ( ! is_array( $schema ) ) {
|
|
6147
|
-
$
|
|
6148
|
-
|
|
6442
|
+
if ( $use_cache ) {
|
|
6443
|
+
$is_supported = false;
|
|
6444
|
+
}
|
|
6445
|
+
return false;
|
|
6149
6446
|
}
|
|
6150
6447
|
|
|
6151
6448
|
$prompt = wp_ai_client_prompt( 'AI feature support probe.' );
|
|
6152
6449
|
if ( ! is_object( $prompt ) || ! method_exists( $prompt, 'as_json_response' ) ) {
|
|
6153
|
-
$
|
|
6154
|
-
|
|
6450
|
+
if ( $use_cache ) {
|
|
6451
|
+
$is_supported = false;
|
|
6452
|
+
}
|
|
6453
|
+
return false;
|
|
6454
|
+
}
|
|
6455
|
+
$prompt_options = ${resolvePromptOptionsFunctionName}( $payload );
|
|
6456
|
+
if (
|
|
6457
|
+
array_key_exists( 'temperature', $prompt_options ) &&
|
|
6458
|
+
null !== $prompt_options['temperature'] &&
|
|
6459
|
+
method_exists( $prompt, 'using_temperature' )
|
|
6460
|
+
) {
|
|
6461
|
+
$prompt = $prompt->using_temperature( $prompt_options['temperature'] );
|
|
6462
|
+
}
|
|
6463
|
+
if (
|
|
6464
|
+
! empty( $prompt_options['modelPreference'] ) &&
|
|
6465
|
+
method_exists( $prompt, 'using_model_preference' )
|
|
6466
|
+
) {
|
|
6467
|
+
$prompt = $prompt->using_model_preference( ...$prompt_options['modelPreference'] );
|
|
6155
6468
|
}
|
|
6156
6469
|
|
|
6157
6470
|
$structured_prompt = $prompt->as_json_response( $schema );
|
|
6158
6471
|
if ( ! is_object( $structured_prompt ) ) {
|
|
6159
|
-
$
|
|
6160
|
-
|
|
6472
|
+
if ( $use_cache ) {
|
|
6473
|
+
$is_supported = false;
|
|
6474
|
+
}
|
|
6475
|
+
return false;
|
|
6161
6476
|
}
|
|
6162
6477
|
|
|
6163
6478
|
if ( method_exists( $structured_prompt, 'is_supported_for_text_generation' ) ) {
|
|
6164
|
-
$
|
|
6165
|
-
|
|
6479
|
+
$supported = (bool) $structured_prompt->is_supported_for_text_generation();
|
|
6480
|
+
if ( $use_cache ) {
|
|
6481
|
+
$is_supported = $supported;
|
|
6482
|
+
}
|
|
6483
|
+
return $supported;
|
|
6166
6484
|
}
|
|
6167
6485
|
|
|
6168
|
-
$
|
|
6169
|
-
|
|
6486
|
+
$supported = method_exists( $structured_prompt, 'generate_text_result' );
|
|
6487
|
+
if ( $use_cache ) {
|
|
6488
|
+
$is_supported = $supported;
|
|
6489
|
+
}
|
|
6490
|
+
return $supported;
|
|
6170
6491
|
}
|
|
6171
6492
|
}
|
|
6172
6493
|
|
|
@@ -6181,6 +6502,18 @@ if ( ! function_exists( '${adminNoticeFunctionName}' ) ) {
|
|
|
6181
6502
|
__( 'The %s AI feature is optional and remains disabled until the WordPress AI Client is available with structured text generation support for the generated schema.', ${quotePhpString(textDomain)} ),
|
|
6182
6503
|
${quotePhpString(aiFeatureTitle)}
|
|
6183
6504
|
);
|
|
6505
|
+
$filtered_message = apply_filters(
|
|
6506
|
+
${quotePhpString(adminNoticeMessageFilterHook)},
|
|
6507
|
+
$message,
|
|
6508
|
+
array(
|
|
6509
|
+
'featureSlug' => ${quotePhpString(aiFeatureSlug)},
|
|
6510
|
+
'featureTitle' => ${quotePhpString(aiFeatureTitle)},
|
|
6511
|
+
'namespace' => ${quotePhpString(namespace)},
|
|
6512
|
+
)
|
|
6513
|
+
);
|
|
6514
|
+
if ( is_string( $filtered_message ) && '' !== $filtered_message ) {
|
|
6515
|
+
$message = $filtered_message;
|
|
6516
|
+
}
|
|
6184
6517
|
printf( '<div class="notice notice-warning"><p>%s</p></div>', esc_html( $message ) );
|
|
6185
6518
|
}
|
|
6186
6519
|
}
|
|
@@ -6192,10 +6525,16 @@ if ( ! function_exists( '${handlerFunctionName}' ) ) {
|
|
|
6192
6525
|
return $payload;
|
|
6193
6526
|
}
|
|
6194
6527
|
|
|
6195
|
-
if ( ! ${isSupportedFunctionName}() ) {
|
|
6528
|
+
if ( ! ${isSupportedFunctionName}( $payload, false ) ) {
|
|
6196
6529
|
return new WP_Error(
|
|
6197
6530
|
'ai_client_unavailable',
|
|
6198
|
-
|
|
6531
|
+
${resolveUnavailableMessageFunctionName}(
|
|
6532
|
+
'The WordPress AI Client is unavailable or does not support this feature endpoint.',
|
|
6533
|
+
'support_probe_failed',
|
|
6534
|
+
array(
|
|
6535
|
+
'featureSlug' => ${quotePhpString(aiFeatureSlug)},
|
|
6536
|
+
)
|
|
6537
|
+
),
|
|
6199
6538
|
array( 'status' => 501 )
|
|
6200
6539
|
);
|
|
6201
6540
|
}
|
|
@@ -6209,22 +6548,45 @@ if ( ! function_exists( '${handlerFunctionName}' ) ) {
|
|
|
6209
6548
|
);
|
|
6210
6549
|
}
|
|
6211
6550
|
|
|
6551
|
+
$prompt_options = ${resolvePromptOptionsFunctionName}( $payload );
|
|
6212
6552
|
$prompt = wp_ai_client_prompt( ${buildPromptFunctionName}( $payload ) );
|
|
6213
6553
|
if ( ! is_object( $prompt ) ) {
|
|
6214
6554
|
return new WP_Error(
|
|
6215
6555
|
'ai_client_unavailable',
|
|
6216
|
-
|
|
6556
|
+
${resolveUnavailableMessageFunctionName}(
|
|
6557
|
+
'The WordPress AI Client prompt builder is unavailable on this site.',
|
|
6558
|
+
'prompt_builder_missing',
|
|
6559
|
+
array(
|
|
6560
|
+
'featureSlug' => ${quotePhpString(aiFeatureSlug)},
|
|
6561
|
+
)
|
|
6562
|
+
),
|
|
6217
6563
|
array( 'status' => 501 )
|
|
6218
6564
|
);
|
|
6219
6565
|
}
|
|
6220
6566
|
|
|
6221
|
-
if (
|
|
6222
|
-
|
|
6567
|
+
if (
|
|
6568
|
+
array_key_exists( 'temperature', $prompt_options ) &&
|
|
6569
|
+
null !== $prompt_options['temperature'] &&
|
|
6570
|
+
method_exists( $prompt, 'using_temperature' )
|
|
6571
|
+
) {
|
|
6572
|
+
$prompt = $prompt->using_temperature( $prompt_options['temperature'] );
|
|
6573
|
+
}
|
|
6574
|
+
if (
|
|
6575
|
+
! empty( $prompt_options['modelPreference'] ) &&
|
|
6576
|
+
method_exists( $prompt, 'using_model_preference' )
|
|
6577
|
+
) {
|
|
6578
|
+
$prompt = $prompt->using_model_preference( ...$prompt_options['modelPreference'] );
|
|
6223
6579
|
}
|
|
6224
6580
|
if ( ! method_exists( $prompt, 'as_json_response' ) ) {
|
|
6225
6581
|
return new WP_Error(
|
|
6226
6582
|
'ai_client_unavailable',
|
|
6227
|
-
|
|
6583
|
+
${resolveUnavailableMessageFunctionName}(
|
|
6584
|
+
'The current WordPress AI Client does not expose as_json_response().',
|
|
6585
|
+
'as_json_response_missing',
|
|
6586
|
+
array(
|
|
6587
|
+
'featureSlug' => ${quotePhpString(aiFeatureSlug)},
|
|
6588
|
+
)
|
|
6589
|
+
),
|
|
6228
6590
|
array( 'status' => 501 )
|
|
6229
6591
|
);
|
|
6230
6592
|
}
|
|
@@ -6233,7 +6595,13 @@ if ( ! function_exists( '${handlerFunctionName}' ) ) {
|
|
|
6233
6595
|
if ( ! is_object( $structured_prompt ) ) {
|
|
6234
6596
|
return new WP_Error(
|
|
6235
6597
|
'ai_client_unavailable',
|
|
6236
|
-
|
|
6598
|
+
${resolveUnavailableMessageFunctionName}(
|
|
6599
|
+
'The current WordPress AI Client could not prepare a structured-output prompt.',
|
|
6600
|
+
'structured_prompt_missing',
|
|
6601
|
+
array(
|
|
6602
|
+
'featureSlug' => ${quotePhpString(aiFeatureSlug)},
|
|
6603
|
+
)
|
|
6604
|
+
),
|
|
6237
6605
|
array( 'status' => 501 )
|
|
6238
6606
|
);
|
|
6239
6607
|
}
|
|
@@ -6244,14 +6612,26 @@ if ( ! function_exists( '${handlerFunctionName}' ) ) {
|
|
|
6244
6612
|
) {
|
|
6245
6613
|
return new WP_Error(
|
|
6246
6614
|
'ai_client_unavailable',
|
|
6247
|
-
|
|
6615
|
+
${resolveUnavailableMessageFunctionName}(
|
|
6616
|
+
'The current WordPress AI Client provider or model does not support this structured-output feature.',
|
|
6617
|
+
'text_generation_unsupported',
|
|
6618
|
+
array(
|
|
6619
|
+
'featureSlug' => ${quotePhpString(aiFeatureSlug)},
|
|
6620
|
+
)
|
|
6621
|
+
),
|
|
6248
6622
|
array( 'status' => 501 )
|
|
6249
6623
|
);
|
|
6250
6624
|
}
|
|
6251
6625
|
if ( ! method_exists( $structured_prompt, 'generate_text_result' ) ) {
|
|
6252
6626
|
return new WP_Error(
|
|
6253
6627
|
'ai_client_unavailable',
|
|
6254
|
-
|
|
6628
|
+
${resolveUnavailableMessageFunctionName}(
|
|
6629
|
+
'The current WordPress AI Client does not expose generate_text_result() after as_json_response().',
|
|
6630
|
+
'generate_text_result_missing',
|
|
6631
|
+
array(
|
|
6632
|
+
'featureSlug' => ${quotePhpString(aiFeatureSlug)},
|
|
6633
|
+
)
|
|
6634
|
+
),
|
|
6255
6635
|
array( 'status' => 501 )
|
|
6256
6636
|
);
|
|
6257
6637
|
}
|
|
@@ -6286,7 +6666,7 @@ if ( ! function_exists( '${handlerFunctionName}' ) ) {
|
|
|
6286
6666
|
);
|
|
6287
6667
|
}
|
|
6288
6668
|
|
|
6289
|
-
$telemetry = ${buildTelemetryFunctionName}( $result );
|
|
6669
|
+
$telemetry = ${buildTelemetryFunctionName}( $result, $payload, $normalized_result );
|
|
6290
6670
|
if ( is_wp_error( $telemetry ) ) {
|
|
6291
6671
|
return $telemetry;
|
|
6292
6672
|
}
|
|
@@ -6331,17 +6711,14 @@ add_action( 'admin_notices', '${adminNoticeFunctionName}' );
|
|
|
6331
6711
|
add_action( 'rest_api_init', '${registerRoutesFunctionName}' );
|
|
6332
6712
|
`;
|
|
6333
6713
|
}
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6714
|
+
|
|
6715
|
+
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ai-scaffold.ts
|
|
6716
|
+
async function scaffoldAiFeatureWorkspace({
|
|
6717
|
+
aiFeatureSlug,
|
|
6718
|
+
compatibilityPolicy,
|
|
6719
|
+
namespace,
|
|
6720
|
+
workspace
|
|
6338
6721
|
}) {
|
|
6339
|
-
const workspace = resolveWorkspaceProject(cwd);
|
|
6340
|
-
const aiFeatureSlug = assertValidGeneratedSlug("AI feature name", normalizeBlockSlug(aiFeatureName), "wp-typia add ai-feature <name> [--namespace <vendor/v1>]");
|
|
6341
|
-
const resolvedNamespace = resolveRestResourceNamespace(workspace.workspace.namespace, namespace);
|
|
6342
|
-
const compatibilityPolicy = resolveScaffoldCompatibilityPolicy(OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY);
|
|
6343
|
-
const inventory = readWorkspaceInventory(workspace.projectDir);
|
|
6344
|
-
assertAiFeatureDoesNotExist(workspace.projectDir, aiFeatureSlug, inventory);
|
|
6345
6722
|
const blockConfigPath = path13.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
6346
6723
|
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
6347
6724
|
const packageJsonPath = path13.join(workspace.projectDir, "package.json");
|
|
@@ -6379,7 +6756,7 @@ async function runAddAiFeatureCommand({
|
|
|
6379
6756
|
await fsp8.writeFile(validatorsFilePath, buildAiFeatureValidatorsSource(aiFeatureSlug), "utf8");
|
|
6380
6757
|
await fsp8.writeFile(apiFilePath, buildAiFeatureApiSource(aiFeatureSlug), "utf8");
|
|
6381
6758
|
await fsp8.writeFile(dataFilePath, buildAiFeatureDataSource(aiFeatureSlug), "utf8");
|
|
6382
|
-
await fsp8.writeFile(phpFilePath, buildAiFeaturePhpSource(aiFeatureSlug,
|
|
6759
|
+
await fsp8.writeFile(phpFilePath, buildAiFeaturePhpSource(aiFeatureSlug, namespace, workspace.workspace.phpPrefix, workspace.workspace.textDomain), "utf8");
|
|
6383
6760
|
const pascalCase = toPascalCase(aiFeatureSlug);
|
|
6384
6761
|
await syncAiFeatureRestArtifacts({
|
|
6385
6762
|
clientFile: `src/ai-features/${aiFeatureSlug}/api-client.ts`,
|
|
@@ -6388,7 +6765,7 @@ async function runAddAiFeatureCommand({
|
|
|
6388
6765
|
typesFile: `src/ai-features/${aiFeatureSlug}/api-types.ts`,
|
|
6389
6766
|
validatorsFile: `src/ai-features/${aiFeatureSlug}/api-validators.ts`,
|
|
6390
6767
|
variables: {
|
|
6391
|
-
namespace
|
|
6768
|
+
namespace,
|
|
6392
6769
|
pascalCase,
|
|
6393
6770
|
slugKebabCase: aiFeatureSlug,
|
|
6394
6771
|
title: toTitleCase(aiFeatureSlug)
|
|
@@ -6401,14 +6778,11 @@ async function runAddAiFeatureCommand({
|
|
|
6401
6778
|
});
|
|
6402
6779
|
await appendWorkspaceInventoryEntries(workspace.projectDir, {
|
|
6403
6780
|
aiFeatureEntries: [
|
|
6404
|
-
buildAiFeatureConfigEntry(aiFeatureSlug,
|
|
6781
|
+
buildAiFeatureConfigEntry(aiFeatureSlug, namespace)
|
|
6405
6782
|
],
|
|
6406
6783
|
transformSource: ensureBlockConfigCanAddRestManifests
|
|
6407
6784
|
});
|
|
6408
6785
|
return {
|
|
6409
|
-
aiFeatureSlug,
|
|
6410
|
-
namespace: resolvedNamespace,
|
|
6411
|
-
projectDir: workspace.projectDir,
|
|
6412
6786
|
warnings: packageScriptChanges.addedProjectToolsDependency ? [
|
|
6413
6787
|
"Added `@wp-typia/project-tools` to devDependencies for `sync-ai`. If this workspace was already installed, rerun your package manager install command before the first `wp-typia sync ai`."
|
|
6414
6788
|
] : []
|
|
@@ -6419,6 +6793,32 @@ async function runAddAiFeatureCommand({
|
|
|
6419
6793
|
}
|
|
6420
6794
|
}
|
|
6421
6795
|
|
|
6796
|
+
// ../wp-typia-project-tools/src/runtime/cli-add-workspace-ai.ts
|
|
6797
|
+
async function runAddAiFeatureCommand({
|
|
6798
|
+
aiFeatureName,
|
|
6799
|
+
cwd = process.cwd(),
|
|
6800
|
+
namespace
|
|
6801
|
+
}) {
|
|
6802
|
+
const workspace = resolveWorkspaceProject(cwd);
|
|
6803
|
+
const aiFeatureSlug = assertValidGeneratedSlug("AI feature name", normalizeBlockSlug(aiFeatureName), "wp-typia add ai-feature <name> [--namespace <vendor/v1>]");
|
|
6804
|
+
const resolvedNamespace = resolveRestResourceNamespace(workspace.workspace.namespace, namespace);
|
|
6805
|
+
const compatibilityPolicy = resolveScaffoldCompatibilityPolicy(OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY);
|
|
6806
|
+
const inventory = readWorkspaceInventory(workspace.projectDir);
|
|
6807
|
+
assertAiFeatureDoesNotExist(workspace.projectDir, aiFeatureSlug, inventory);
|
|
6808
|
+
const scaffoldResult = await scaffoldAiFeatureWorkspace({
|
|
6809
|
+
aiFeatureSlug,
|
|
6810
|
+
compatibilityPolicy,
|
|
6811
|
+
namespace: resolvedNamespace,
|
|
6812
|
+
workspace
|
|
6813
|
+
});
|
|
6814
|
+
return {
|
|
6815
|
+
aiFeatureSlug,
|
|
6816
|
+
namespace: resolvedNamespace,
|
|
6817
|
+
projectDir: workspace.projectDir,
|
|
6818
|
+
warnings: scaffoldResult.warnings
|
|
6819
|
+
};
|
|
6820
|
+
}
|
|
6821
|
+
|
|
6422
6822
|
// ../wp-typia-project-tools/src/runtime/cli-add-workspace.ts
|
|
6423
6823
|
var VARIATIONS_IMPORT_LINE = "import { registerWorkspaceVariations } from './variations';";
|
|
6424
6824
|
var VARIATIONS_IMPORT_PATTERN = /^\s*import\s*\{\s*registerWorkspaceVariations\s*\}\s*from\s*["']\.\/variations["']\s*;?\s*$/mu;
|
|
@@ -6900,24 +7300,6 @@ async function writeBlockTransformRegistry(projectDir, blockSlug, transformSlug)
|
|
|
6900
7300
|
const nextTransformSlugs = Array.from(new Set([...existingTransformSlugs, transformSlug])).sort();
|
|
6901
7301
|
await fsp9.writeFile(transformsIndexPath, buildBlockTransformIndexSource(nextTransformSlugs), "utf8");
|
|
6902
7302
|
}
|
|
6903
|
-
function assertBlockStyleDoesNotExist(projectDir, blockSlug, styleSlug, inventory) {
|
|
6904
|
-
const stylePath = path14.join(projectDir, "src", "blocks", blockSlug, "styles", `${styleSlug}.ts`);
|
|
6905
|
-
if (fs6.existsSync(stylePath)) {
|
|
6906
|
-
throw new Error(`A block style already exists at ${path14.relative(projectDir, stylePath)}. Choose a different name.`);
|
|
6907
|
-
}
|
|
6908
|
-
if (inventory.blockStyles.some((entry) => entry.block === blockSlug && entry.slug === styleSlug)) {
|
|
6909
|
-
throw new Error(`A block style inventory entry already exists for ${blockSlug}/${styleSlug}. Choose a different name.`);
|
|
6910
|
-
}
|
|
6911
|
-
}
|
|
6912
|
-
function assertBlockTransformDoesNotExist(projectDir, blockSlug, transformSlug, inventory) {
|
|
6913
|
-
const transformPath = path14.join(projectDir, "src", "blocks", blockSlug, "transforms", `${transformSlug}.ts`);
|
|
6914
|
-
if (fs6.existsSync(transformPath)) {
|
|
6915
|
-
throw new Error(`A block transform already exists at ${path14.relative(projectDir, transformPath)}. Choose a different name.`);
|
|
6916
|
-
}
|
|
6917
|
-
if (inventory.blockTransforms.some((entry) => entry.block === blockSlug && entry.slug === transformSlug)) {
|
|
6918
|
-
throw new Error(`A block transform inventory entry already exists for ${blockSlug}/${transformSlug}. Choose a different name.`);
|
|
6919
|
-
}
|
|
6920
|
-
}
|
|
6921
7303
|
function assertFullBlockName(blockName, flagName) {
|
|
6922
7304
|
const trimmed = blockName.trim();
|
|
6923
7305
|
if (!trimmed) {
|
|
@@ -7165,4 +7547,4 @@ export {
|
|
|
7165
7547
|
ADD_BLOCK_TEMPLATE_IDS
|
|
7166
7548
|
};
|
|
7167
7549
|
|
|
7168
|
-
//# debugId=
|
|
7550
|
+
//# debugId=272EBA8B7C96349F64756E2164756E21
|