@wp-typia/project-tools 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/dist/runtime/built-in-block-code-templates/interactivity.d.ts +1 -1
- package/dist/runtime/built-in-block-code-templates/interactivity.js +4 -2
- package/dist/runtime/cli-add-shared.d.ts +49 -0
- package/dist/runtime/cli-add-shared.js +204 -71
- package/dist/runtime/cli-add-workspace-ability-scaffold.d.ts +5 -0
- package/dist/runtime/cli-add-workspace-ability-scaffold.js +392 -0
- package/dist/runtime/cli-add-workspace-ability-templates.d.ts +34 -0
- package/dist/runtime/cli-add-workspace-ability-templates.js +500 -0
- package/dist/runtime/cli-add-workspace-ability-types.d.ts +27 -0
- package/dist/runtime/cli-add-workspace-ability-types.js +14 -0
- package/dist/runtime/cli-add-workspace-ability.js +12 -852
- package/dist/runtime/cli-add-workspace-ai-scaffold.d.ts +21 -0
- package/dist/runtime/cli-add-workspace-ai-scaffold.js +91 -0
- package/dist/runtime/cli-add-workspace-ai-source-emitters.js +119 -1
- package/dist/runtime/cli-add-workspace-ai-templates.d.ts +4 -0
- package/dist/runtime/cli-add-workspace-ai-templates.js +605 -0
- package/dist/runtime/cli-add-workspace-ai.js +15 -465
- package/dist/runtime/cli-add-workspace-assets.js +7 -4
- package/dist/runtime/cli-add-workspace.js +1 -19
- package/dist/runtime/cli-doctor-workspace-bindings.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-bindings.js +134 -0
- package/dist/runtime/cli-doctor-workspace-blocks.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-blocks.js +504 -0
- package/dist/runtime/cli-doctor-workspace-features.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-features.js +383 -0
- package/dist/runtime/cli-doctor-workspace-package.d.ts +18 -0
- package/dist/runtime/cli-doctor-workspace-package.js +59 -0
- package/dist/runtime/cli-doctor-workspace-shared.d.ts +69 -0
- package/dist/runtime/cli-doctor-workspace-shared.js +87 -0
- package/dist/runtime/cli-doctor-workspace.js +25 -1062
- package/dist/runtime/scaffold-compatibility.d.ts +2 -0
- package/dist/runtime/scaffold-compatibility.js +2 -0
- package/dist/runtime/typia-llm.d.ts +37 -2
- package/dist/runtime/typia-llm.js +240 -3
- package/dist/runtime/workspace-inventory.js +24 -0
- package/package.json +3 -3
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ScaffoldCompatibilityPolicy } from "./scaffold-compatibility.js";
|
|
2
|
+
import type { WorkspaceProject } from "./workspace-project.js";
|
|
3
|
+
/**
|
|
4
|
+
* Inputs required to scaffold a generated AI feature into a workspace.
|
|
5
|
+
*/
|
|
6
|
+
export interface ScaffoldAiFeatureWorkspaceOptions {
|
|
7
|
+
/** Kebab-case feature slug used for file paths and route ids. */
|
|
8
|
+
aiFeatureSlug: string;
|
|
9
|
+
/** Compatibility metadata applied to the generated workspace bootstrap. */
|
|
10
|
+
compatibilityPolicy: ScaffoldCompatibilityPolicy;
|
|
11
|
+
/** WordPress REST namespace used for generated feature routes. */
|
|
12
|
+
namespace: string;
|
|
13
|
+
/** Resolved workspace metadata and filesystem paths for the target project. */
|
|
14
|
+
workspace: WorkspaceProject;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Write generated AI feature sources and patch shared workspace anchors.
|
|
18
|
+
*/
|
|
19
|
+
export declare function scaffoldAiFeatureWorkspace({ aiFeatureSlug, compatibilityPolicy, namespace, workspace, }: ScaffoldAiFeatureWorkspaceOptions): Promise<{
|
|
20
|
+
warnings: string[];
|
|
21
|
+
}>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { promises as fsp } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { ensureBlockConfigCanAddRestManifests } from "./cli-add-block-legacy-validator.js";
|
|
4
|
+
import { buildAiFeatureConfigEntry, buildAiFeatureDataSource, buildAiFeatureSyncScriptSource, buildAiFeatureTypesSource, buildAiFeatureValidatorsSource, buildAiFeatureApiSource, } from "./cli-add-workspace-ai-source-emitters.js";
|
|
5
|
+
import { ensureAiFeatureBootstrapAnchors, ensureAiFeaturePackageScripts, ensureAiFeatureSyncProjectAnchors, ensureAiFeatureSyncRestAnchors, } from "./cli-add-workspace-ai-anchors.js";
|
|
6
|
+
import { buildAiFeaturePhpSource } from "./cli-add-workspace-ai-templates.js";
|
|
7
|
+
import { appendWorkspaceInventoryEntries } from "./workspace-inventory.js";
|
|
8
|
+
import { getWorkspaceBootstrapPath, patchFile, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
|
|
9
|
+
import { updatePluginHeaderCompatibility } from "./scaffold-compatibility.js";
|
|
10
|
+
import { toPascalCase, toTitleCase } from "./string-case.js";
|
|
11
|
+
import { syncAiFeatureRestArtifacts, syncAiFeatureSchemaArtifact, } from "./ai-feature-artifacts.js";
|
|
12
|
+
/**
|
|
13
|
+
* Write generated AI feature sources and patch shared workspace anchors.
|
|
14
|
+
*/
|
|
15
|
+
export async function scaffoldAiFeatureWorkspace({ aiFeatureSlug, compatibilityPolicy, namespace, workspace, }) {
|
|
16
|
+
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
17
|
+
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
18
|
+
const packageJsonPath = path.join(workspace.projectDir, "package.json");
|
|
19
|
+
const syncAiScriptPath = path.join(workspace.projectDir, "scripts", "sync-ai-features.ts");
|
|
20
|
+
const syncProjectScriptPath = path.join(workspace.projectDir, "scripts", "sync-project.ts");
|
|
21
|
+
const syncRestScriptPath = path.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
|
|
22
|
+
const aiFeatureDir = path.join(workspace.projectDir, "src", "ai-features", aiFeatureSlug);
|
|
23
|
+
const typesFilePath = path.join(aiFeatureDir, "api-types.ts");
|
|
24
|
+
const validatorsFilePath = path.join(aiFeatureDir, "api-validators.ts");
|
|
25
|
+
const apiFilePath = path.join(aiFeatureDir, "api.ts");
|
|
26
|
+
const dataFilePath = path.join(aiFeatureDir, "data.ts");
|
|
27
|
+
const phpFilePath = path.join(workspace.projectDir, "inc", "ai-features", `${aiFeatureSlug}.php`);
|
|
28
|
+
const mutationSnapshot = {
|
|
29
|
+
fileSources: await snapshotWorkspaceFiles([
|
|
30
|
+
blockConfigPath,
|
|
31
|
+
bootstrapPath,
|
|
32
|
+
packageJsonPath,
|
|
33
|
+
syncAiScriptPath,
|
|
34
|
+
syncProjectScriptPath,
|
|
35
|
+
syncRestScriptPath,
|
|
36
|
+
]),
|
|
37
|
+
snapshotDirs: [],
|
|
38
|
+
targetPaths: [aiFeatureDir, phpFilePath, syncAiScriptPath],
|
|
39
|
+
};
|
|
40
|
+
try {
|
|
41
|
+
await fsp.mkdir(aiFeatureDir, { recursive: true });
|
|
42
|
+
await fsp.mkdir(path.dirname(phpFilePath), { recursive: true });
|
|
43
|
+
await ensureAiFeatureBootstrapAnchors(workspace);
|
|
44
|
+
await patchFile(bootstrapPath, (source) => updatePluginHeaderCompatibility(source, compatibilityPolicy));
|
|
45
|
+
const packageScriptChanges = await ensureAiFeaturePackageScripts(workspace);
|
|
46
|
+
await ensureAiFeatureSyncProjectAnchors(workspace);
|
|
47
|
+
await ensureAiFeatureSyncRestAnchors(workspace);
|
|
48
|
+
await fsp.writeFile(syncAiScriptPath, buildAiFeatureSyncScriptSource(), "utf8");
|
|
49
|
+
await fsp.writeFile(typesFilePath, buildAiFeatureTypesSource(aiFeatureSlug), "utf8");
|
|
50
|
+
await fsp.writeFile(validatorsFilePath, buildAiFeatureValidatorsSource(aiFeatureSlug), "utf8");
|
|
51
|
+
await fsp.writeFile(apiFilePath, buildAiFeatureApiSource(aiFeatureSlug), "utf8");
|
|
52
|
+
await fsp.writeFile(dataFilePath, buildAiFeatureDataSource(aiFeatureSlug), "utf8");
|
|
53
|
+
await fsp.writeFile(phpFilePath, buildAiFeaturePhpSource(aiFeatureSlug, namespace, workspace.workspace.phpPrefix, workspace.workspace.textDomain), "utf8");
|
|
54
|
+
const pascalCase = toPascalCase(aiFeatureSlug);
|
|
55
|
+
await syncAiFeatureRestArtifacts({
|
|
56
|
+
clientFile: `src/ai-features/${aiFeatureSlug}/api-client.ts`,
|
|
57
|
+
outputDir: path.join("src", "ai-features", aiFeatureSlug),
|
|
58
|
+
projectDir: workspace.projectDir,
|
|
59
|
+
typesFile: `src/ai-features/${aiFeatureSlug}/api-types.ts`,
|
|
60
|
+
validatorsFile: `src/ai-features/${aiFeatureSlug}/api-validators.ts`,
|
|
61
|
+
variables: {
|
|
62
|
+
namespace,
|
|
63
|
+
pascalCase,
|
|
64
|
+
slugKebabCase: aiFeatureSlug,
|
|
65
|
+
title: toTitleCase(aiFeatureSlug),
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
await syncAiFeatureSchemaArtifact({
|
|
69
|
+
aiSchemaFile: `src/ai-features/${aiFeatureSlug}/ai-schemas/feature-result.ai.schema.json`,
|
|
70
|
+
outputDir: path.join("src", "ai-features", aiFeatureSlug),
|
|
71
|
+
projectDir: workspace.projectDir,
|
|
72
|
+
});
|
|
73
|
+
await appendWorkspaceInventoryEntries(workspace.projectDir, {
|
|
74
|
+
aiFeatureEntries: [
|
|
75
|
+
buildAiFeatureConfigEntry(aiFeatureSlug, namespace),
|
|
76
|
+
],
|
|
77
|
+
transformSource: ensureBlockConfigCanAddRestManifests,
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
warnings: packageScriptChanges.addedProjectToolsDependency
|
|
81
|
+
? [
|
|
82
|
+
"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`.",
|
|
83
|
+
]
|
|
84
|
+
: [],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
await rollbackWorkspaceMutation(mutationSnapshot);
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { quoteTsString } from "./cli-add-shared.js";
|
|
2
2
|
import { buildAiFeatureEndpointManifest } from "./ai-feature-artifacts.js";
|
|
3
|
-
import { OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY, renderScaffoldCompatibilityConfig, resolveScaffoldCompatibilityPolicy, } from "./scaffold-compatibility.js";
|
|
3
|
+
import { OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY, createScaffoldCompatibilityConfig, renderScaffoldCompatibilityConfig, resolveScaffoldCompatibilityPolicy, } from "./scaffold-compatibility.js";
|
|
4
4
|
import { toPascalCase, toTitleCase } from "./string-case.js";
|
|
5
5
|
function indentMultiline(source, prefix) {
|
|
6
6
|
return source
|
|
@@ -79,6 +79,45 @@ export interface ${pascalCase}AiFeatureResponse {
|
|
|
79
79
|
\tresult: ${pascalCase}AiFeatureResult;
|
|
80
80
|
\ttelemetry: ${pascalCase}AiFeatureTelemetry;
|
|
81
81
|
}
|
|
82
|
+
|
|
83
|
+
export type ${pascalCase}AiFeatureSupportProbeMode = 'request-time';
|
|
84
|
+
|
|
85
|
+
export type ${pascalCase}AiFeatureUnavailableErrorCode =
|
|
86
|
+
\t'ai_client_unavailable';
|
|
87
|
+
|
|
88
|
+
export type ${pascalCase}AiFeatureUnavailableReasonCode =
|
|
89
|
+
\t| 'missing-wordpress-ai-client'
|
|
90
|
+
\t| 'request-time-support-probe';
|
|
91
|
+
|
|
92
|
+
export interface ${pascalCase}AiFeatureSupportReason {
|
|
93
|
+
\tcode: ${pascalCase}AiFeatureUnavailableReasonCode;
|
|
94
|
+
\tlabel: string & tags.MinLength< 1 > & tags.MaxLength< 160 >;
|
|
95
|
+
\tmessage: string & tags.MinLength< 1 > & tags.MaxLength< 4000 >;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface ${pascalCase}AiFeatureSupportMetadata {
|
|
99
|
+
\tfeatureLabel: string & tags.MinLength< 1 > & tags.MaxLength< 160 >;
|
|
100
|
+
\tfeatureSlug: string & tags.MinLength< 1 > & tags.MaxLength< 160 >;
|
|
101
|
+
\tcompatibility: {
|
|
102
|
+
\t\thardMinimums: {
|
|
103
|
+
\t\t\tphp?: string;
|
|
104
|
+
\t\t\twordpress?: string;
|
|
105
|
+
\t\t};
|
|
106
|
+
\t\tmode: 'baseline' | 'optional' | 'required';
|
|
107
|
+
\t\toptionalFeatureIds: string[];
|
|
108
|
+
\t\toptionalFeatures: string[];
|
|
109
|
+
\t\trequiredFeatureIds: string[];
|
|
110
|
+
\t\trequiredFeatures: string[];
|
|
111
|
+
\t\truntimeGates: string[];
|
|
112
|
+
\t};
|
|
113
|
+
\tsupportProbe: {
|
|
114
|
+
\t\tendpointMethod: 'POST';
|
|
115
|
+
\t\tendpointPath: string & tags.MinLength< 1 > & tags.MaxLength< 200 >;
|
|
116
|
+
\t\tmode: ${pascalCase}AiFeatureSupportProbeMode;
|
|
117
|
+
\t\tunavailableErrorCode: ${pascalCase}AiFeatureUnavailableErrorCode;
|
|
118
|
+
\t};
|
|
119
|
+
\tunavailableReasons: ${pascalCase}AiFeatureSupportReason[];
|
|
120
|
+
}
|
|
82
121
|
`;
|
|
83
122
|
}
|
|
84
123
|
/**
|
|
@@ -120,6 +159,8 @@ export const apiValidators = {
|
|
|
120
159
|
*/
|
|
121
160
|
export function buildAiFeatureApiSource(aiFeatureSlug) {
|
|
122
161
|
const pascalCase = toPascalCase(aiFeatureSlug);
|
|
162
|
+
const compatibility = createScaffoldCompatibilityConfig(resolveScaffoldCompatibilityPolicy(OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY));
|
|
163
|
+
const title = toTitleCase(aiFeatureSlug);
|
|
123
164
|
return `import {
|
|
124
165
|
\tcallEndpoint,
|
|
125
166
|
\tresolveRestRouteUrl,
|
|
@@ -127,6 +168,7 @@ export function buildAiFeatureApiSource(aiFeatureSlug) {
|
|
|
127
168
|
|
|
128
169
|
import type {
|
|
129
170
|
\t${pascalCase}AiFeatureRequest,
|
|
171
|
+
\t${pascalCase}AiFeatureSupportMetadata,
|
|
130
172
|
} from './api-types';
|
|
131
173
|
import {
|
|
132
174
|
\trun${pascalCase}AiFeatureEndpoint,
|
|
@@ -153,6 +195,14 @@ function resolveRestNonce( fallback?: string ): string | undefined {
|
|
|
153
195
|
\t\t: undefined;
|
|
154
196
|
}
|
|
155
197
|
|
|
198
|
+
function isPlainObject( value: unknown ): value is Record< string, unknown > {
|
|
199
|
+
\treturn (
|
|
200
|
+
\t\t!! value &&
|
|
201
|
+
\t\ttypeof value === 'object' &&
|
|
202
|
+
\t\t! Array.isArray( value )
|
|
203
|
+
\t);
|
|
204
|
+
}
|
|
205
|
+
|
|
156
206
|
export const aiFeatureRunEndpoint = {
|
|
157
207
|
\t...run${pascalCase}AiFeatureEndpoint,
|
|
158
208
|
\tbuildRequestOptions: () => {
|
|
@@ -168,6 +218,63 @@ export const aiFeatureRunEndpoint = {
|
|
|
168
218
|
\t},
|
|
169
219
|
};
|
|
170
220
|
|
|
221
|
+
export const aiFeatureSupportMetadata = {
|
|
222
|
+
\tcompatibility: ${JSON.stringify(compatibility, null, "\t")},
|
|
223
|
+
\tfeatureLabel: ${quoteTsString(title)},
|
|
224
|
+
\tfeatureSlug: ${quoteTsString(aiFeatureSlug)},
|
|
225
|
+
\tsupportProbe: {
|
|
226
|
+
\t\tendpointMethod: 'POST',
|
|
227
|
+
\t\tendpointPath: aiFeatureRunEndpoint.path,
|
|
228
|
+
\t\tmode: 'request-time',
|
|
229
|
+
\t\tunavailableErrorCode: 'ai_client_unavailable',
|
|
230
|
+
\t},
|
|
231
|
+
\tunavailableReasons: [
|
|
232
|
+
\t\t{
|
|
233
|
+
\t\t\tcode: 'missing-wordpress-ai-client',
|
|
234
|
+
\t\t\tlabel: 'WordPress AI Client unavailable',
|
|
235
|
+
\t\t\tmessage:
|
|
236
|
+
\t\t\t\t'This AI feature stays disabled until the WordPress AI Client is available on the site.',
|
|
237
|
+
\t\t},
|
|
238
|
+
\t\t{
|
|
239
|
+
\t\t\tcode: 'request-time-support-probe',
|
|
240
|
+
\t\t\tlabel: 'Support is checked at request time',
|
|
241
|
+
\t\t\tmessage:
|
|
242
|
+
\t\t\t\t'Support is verified when the feature runs, so editor and admin UIs should degrade gracefully when the site rejects the request.',
|
|
243
|
+
\t\t},
|
|
244
|
+
\t],
|
|
245
|
+
} satisfies ${pascalCase}AiFeatureSupportMetadata;
|
|
246
|
+
|
|
247
|
+
export function getAiFeatureSupportHintLines() {
|
|
248
|
+
\treturn aiFeatureSupportMetadata.unavailableReasons.map(
|
|
249
|
+
\t\t( reason ) => reason.message
|
|
250
|
+
\t);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function isAiFeatureSupportUnavailableError( error: unknown ) {
|
|
254
|
+
\tif ( ! isPlainObject( error ) ) {
|
|
255
|
+
\t\treturn false;
|
|
256
|
+
\t}
|
|
257
|
+
|
|
258
|
+
\tconst data = isPlainObject( error.data ) ? error.data : undefined;
|
|
259
|
+
\treturn (
|
|
260
|
+
\t\terror.code === aiFeatureSupportMetadata.supportProbe.unavailableErrorCode ||
|
|
261
|
+
\t\tdata?.status === 501
|
|
262
|
+
\t);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export function resolveAiFeatureUnavailableMessage( error: unknown ) {
|
|
266
|
+
\tif (
|
|
267
|
+
\t\tisPlainObject( error ) &&
|
|
268
|
+
\t\ttypeof error.message === 'string' &&
|
|
269
|
+
\t\terror.message.length > 0
|
|
270
|
+
\t) {
|
|
271
|
+
\t\treturn error.message;
|
|
272
|
+
\t}
|
|
273
|
+
|
|
274
|
+
\treturn aiFeatureSupportMetadata.unavailableReasons[ 0 ]?.message ??
|
|
275
|
+
\t\t'This AI feature is currently unavailable.';
|
|
276
|
+
}
|
|
277
|
+
|
|
171
278
|
export function runAiFeature( request: ${pascalCase}AiFeatureRequest ) {
|
|
172
279
|
\treturn callEndpoint( aiFeatureRunEndpoint, request );
|
|
173
280
|
}
|
|
@@ -189,6 +296,10 @@ import type {
|
|
|
189
296
|
} from './api-types';
|
|
190
297
|
import {
|
|
191
298
|
\taiFeatureRunEndpoint,
|
|
299
|
+
\taiFeatureSupportMetadata,
|
|
300
|
+
\tgetAiFeatureSupportHintLines,
|
|
301
|
+
\tisAiFeatureSupportUnavailableError,
|
|
302
|
+
\tresolveAiFeatureUnavailableMessage,
|
|
192
303
|
} from './api';
|
|
193
304
|
|
|
194
305
|
export type UseRun${pascalCase}AiFeatureMutationOptions =
|
|
@@ -203,6 +314,13 @@ export function useRun${pascalCase}AiFeatureMutation(
|
|
|
203
314
|
) {
|
|
204
315
|
\treturn useEndpointMutation( aiFeatureRunEndpoint, options );
|
|
205
316
|
}
|
|
317
|
+
|
|
318
|
+
export {
|
|
319
|
+
\taiFeatureSupportMetadata,
|
|
320
|
+
\tgetAiFeatureSupportHintLines,
|
|
321
|
+
\tisAiFeatureSupportUnavailableError,
|
|
322
|
+
\tresolveAiFeatureUnavailableMessage,
|
|
323
|
+
};
|
|
206
324
|
`;
|
|
207
325
|
}
|
|
208
326
|
/**
|