wordpress-agent-kit 0.3.0 → 0.4.0
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/.github/skills/blueprint/SKILL.md +418 -0
- package/.github/skills/wp-abilities-api/SKILL.md +12 -0
- package/.github/skills/wp-abilities-api/references/delegate-helper-pattern.md +241 -0
- package/.github/skills/wp-abilities-api/references/domain-vs-projection.md +113 -0
- package/.github/skills/wp-abilities-api/references/error-code-vocabulary.md +123 -0
- package/.github/skills/wp-abilities-api/references/grouping-heuristic.md +89 -0
- package/.github/skills/wp-abilities-api/references/input-schema-gotchas.md +265 -0
- package/.github/skills/wp-abilities-api/references/php-registration.md +47 -20
- package/.github/skills/wp-abilities-api/references/plugin-family-patterns.md +233 -0
- package/.github/skills/wp-abilities-api/references/shared-core-service.md +184 -0
- package/.github/skills/wp-abilities-audit/SKILL.md +199 -0
- package/.github/skills/wp-abilities-audit/references/audit-schema.md +300 -0
- package/.github/skills/wp-abilities-audit/references/capability-gate-tracing.md +197 -0
- package/.github/skills/wp-abilities-audit/references/controller-enumeration.md +116 -0
- package/.github/skills/wp-abilities-verify/SKILL.md +215 -0
- package/.github/skills/wp-abilities-verify/references/annotation-correctness.md +154 -0
- package/.github/skills/wp-abilities-verify/references/audit-schema-validation.md +131 -0
- package/.github/skills/wp-abilities-verify/references/permission-roundtrip.md +190 -0
- package/.github/skills/wp-abilities-verify/references/runtime-harness.md +462 -0
- package/.github/skills/wp-abilities-verify/references/schema-lints.md +118 -0
- package/.github/skills/wp-abilities-verify/references/static-enumeration.md +126 -0
- package/.github/skills/wp-playground/SKILL.md +132 -1
- package/.github/skills/wp-playground/references/e2e-playwright.md +115 -0
- package/.github/skills/wp-plugin-directory-guidelines/SKILL.md +133 -0
- package/.github/skills/wp-plugin-directory-guidelines/references/gpl-compliance.md +217 -0
- package/.github/skills/wp-plugin-directory-guidelines/references/guideline-review-checklist.md +592 -0
- package/.github/skills/wp-plugin-directory-guidelines/references/naming-rules.md +121 -0
- package/.github/skills/wp-project-triage/scripts/detect_wp_project.mjs +22 -4
- package/.github/skills/wp-wpengine/SKILL.md +127 -0
- package/README.md +14 -8
- package/dist/lib/api.js +43 -19
- package/dist/lib/installer.js +0 -2
- package/extensions/wp-agent-kit/index.ts +146 -324
- package/package.json +1 -1
- package/skills-custom/wp-wpengine/SKILL.md +127 -0
|
@@ -1,51 +1,57 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
1
3
|
/**
|
|
2
|
-
* WordPress Agent Kit Pi Extension
|
|
4
|
+
* WordPress Agent Kit — Pi Extension
|
|
3
5
|
*
|
|
4
|
-
* Provides Pi
|
|
5
|
-
* - WordPress agent skills (
|
|
6
|
+
* Provides Pi Coding Agent with WordPress development tools:
|
|
7
|
+
* - 17 WordPress agent skills (plugin/theme/block dev, REST API, WP-CLI, etc.)
|
|
6
8
|
* - Project triage detection
|
|
7
|
-
* - Skill installation and
|
|
8
|
-
* - Version upgrade management
|
|
9
|
+
* - Skill installation, syncing, and upgrade management
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
+
* Follows Pi Coding Agent SDK conventions (extensions.md, packages.md, skills.md).
|
|
11
12
|
*/
|
|
12
13
|
import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
|
|
13
14
|
import { Type } from 'typebox';
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..', '..');
|
|
18
|
+
|
|
19
|
+
// Resolve the API import dynamically — works in both dev (src/) and npm (dist/)
|
|
20
|
+
let apiModule: typeof import('../../dist/lib/api.js');
|
|
21
|
+
try {
|
|
22
|
+
apiModule = await import('../../dist/lib/api.js');
|
|
23
|
+
} catch {
|
|
24
|
+
// Fallback for dev: import from source via jiti
|
|
25
|
+
apiModule = (await import('../../src/lib/api.js')) as typeof import('../../dist/lib/api.js');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { installKitApi, syncSkillsApi, runTriageApi, isKitInstalled, loadManifest } = apiModule;
|
|
27
29
|
|
|
28
30
|
export default function (pi: ExtensionAPI) {
|
|
29
31
|
// =========================================================================
|
|
30
32
|
// Skills Registration
|
|
31
33
|
// =========================================================================
|
|
32
|
-
// Register WordPress skills via resources_discover so Pi agents can use them.
|
|
33
|
-
// Skills are loaded from .github/skills/ (also declared in package.json pi.skills).
|
|
34
34
|
pi.on('resources_discover', async (_event, _ctx) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return {
|
|
35
|
+
const skillsDir = path.join(PACKAGE_ROOT, '.github', 'skills');
|
|
36
|
+
const promptsDir = path.join(PACKAGE_ROOT, '.github', 'prompts');
|
|
37
|
+
return {
|
|
38
|
+
skillPaths: [skillsDir],
|
|
39
|
+
promptPaths: [promptsDir],
|
|
40
|
+
};
|
|
38
41
|
});
|
|
39
42
|
|
|
40
43
|
// =========================================================================
|
|
41
44
|
// Session notifications
|
|
42
45
|
// =========================================================================
|
|
43
46
|
pi.on('session_start', async (_event, ctx) => {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
const platforms: Array<'pi' | 'github'> = ['pi', 'github'];
|
|
48
|
+
for (const p of platforms) {
|
|
49
|
+
if (isKitInstalled(ctx.cwd, p)) {
|
|
50
|
+
const manifest = loadManifest(ctx.cwd, p);
|
|
51
|
+
if (manifest) {
|
|
52
|
+
ctx.ui.setStatus('wp-agent-kit', `WP Agent Kit v${manifest.version}`);
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
});
|
|
@@ -55,37 +61,29 @@ export default function (pi: ExtensionAPI) {
|
|
|
55
61
|
// =========================================================================
|
|
56
62
|
|
|
57
63
|
// --- wp_triage ---
|
|
58
|
-
// Run WordPress project triage to detect project type, signals, and tooling.
|
|
59
64
|
pi.registerTool({
|
|
60
65
|
name: 'wp_triage',
|
|
61
66
|
label: 'WP Triage',
|
|
62
67
|
description:
|
|
63
|
-
'
|
|
68
|
+
'Detect WordPress project type (plugin, theme, block theme, site, Gutenberg), signals (block.json, Interactivity API, WP-CLI, REST API), and tooling (PHP/Node). Use before making changes to any WordPress project.',
|
|
64
69
|
promptSnippet: 'Detect WordPress project type, signals, and tooling',
|
|
65
70
|
promptGuidelines: [
|
|
66
|
-
'Use wp_triage before making changes to any WordPress project to understand the codebase
|
|
71
|
+
'Use wp_triage before making changes to any WordPress project to understand the codebase.',
|
|
67
72
|
'Use wp_triage output to route to the correct WordPress development skill.',
|
|
68
73
|
],
|
|
69
74
|
parameters: Type.Object({
|
|
70
75
|
targetDir: Type.Optional(
|
|
71
76
|
Type.String({
|
|
72
|
-
description: '
|
|
73
|
-
})
|
|
74
|
-
),
|
|
75
|
-
platform: Type.Optional(
|
|
76
|
-
Type.String({
|
|
77
|
-
description:
|
|
78
|
-
'Platform where skills are installed (github, cursor, claude, agent, pi). Default: github',
|
|
77
|
+
description: 'WordPress project directory (defaults to current working directory)',
|
|
79
78
|
})
|
|
80
79
|
),
|
|
81
80
|
}),
|
|
82
|
-
async execute(
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const result = await runTriageApi(options);
|
|
81
|
+
async execute(_callId, params, _signal, _onUpdate, _ctx) {
|
|
82
|
+
const targetDir = params.targetDir || process.cwd();
|
|
83
|
+
const result = await runTriageApi({
|
|
84
|
+
targetDir,
|
|
85
|
+
platform: 'pi',
|
|
86
|
+
});
|
|
89
87
|
|
|
90
88
|
if (!result.success) {
|
|
91
89
|
return {
|
|
@@ -100,18 +98,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
100
98
|
};
|
|
101
99
|
}
|
|
102
100
|
|
|
103
|
-
const
|
|
101
|
+
const t = result.data;
|
|
104
102
|
return {
|
|
105
103
|
content: [
|
|
106
104
|
{
|
|
107
105
|
type: 'text',
|
|
108
106
|
text: JSON.stringify(
|
|
109
107
|
{
|
|
110
|
-
project:
|
|
111
|
-
signals:
|
|
112
|
-
tooling:
|
|
113
|
-
recommendation:
|
|
114
|
-
?
|
|
108
|
+
project: t.project,
|
|
109
|
+
signals: t.signals,
|
|
110
|
+
tooling: t.tooling,
|
|
111
|
+
recommendation: t.project
|
|
112
|
+
? `${t.project.primary} project (confidence: ${t.project.confidence}). Use the matching wp-* skill.`
|
|
115
113
|
: 'Could not determine project type. Review signals manually.',
|
|
116
114
|
},
|
|
117
115
|
null,
|
|
@@ -119,108 +117,87 @@ export default function (pi: ExtensionAPI) {
|
|
|
119
117
|
),
|
|
120
118
|
},
|
|
121
119
|
],
|
|
122
|
-
details:
|
|
120
|
+
details: t,
|
|
123
121
|
};
|
|
124
122
|
},
|
|
125
123
|
});
|
|
126
124
|
|
|
127
125
|
// --- wp_install_kit ---
|
|
128
|
-
// Install WordPress Agent Kit skills into a target directory.
|
|
129
126
|
pi.registerTool({
|
|
130
127
|
name: 'wp_install_kit',
|
|
131
128
|
label: 'WP Install Kit',
|
|
132
129
|
description:
|
|
133
|
-
'Install
|
|
130
|
+
'Install WordPress Agent Kit into a project directory. Copies 17 WordPress development skills, agent definitions, workflow instructions, and an AGENTS.md template. Safe by default — preserves user modifications on re-run.',
|
|
134
131
|
promptSnippet: 'Install WordPress AI agent skills and configuration into a project',
|
|
135
132
|
promptGuidelines: [
|
|
136
133
|
'Use wp_install_kit when setting up a new WordPress project for AI agent development.',
|
|
137
|
-
'Use wp_install_kit with dryRun:true to preview changes before applying.',
|
|
134
|
+
'Use wp_install_kit with dryRun: true to preview changes before applying.',
|
|
138
135
|
],
|
|
139
136
|
parameters: Type.Object({
|
|
140
137
|
targetDir: Type.String({
|
|
141
|
-
description: '
|
|
138
|
+
description: 'WordPress project root directory to install into',
|
|
142
139
|
}),
|
|
143
|
-
platform: Type.Optional(
|
|
144
|
-
Type.String({
|
|
145
|
-
description: 'Target platform: github, cursor, claude, agent, or pi. Default: github',
|
|
146
|
-
})
|
|
147
|
-
),
|
|
148
140
|
dryRun: Type.Optional(
|
|
149
141
|
Type.Boolean({
|
|
150
|
-
description: '
|
|
142
|
+
description: 'Preview changes without applying (default: false)',
|
|
151
143
|
})
|
|
152
144
|
),
|
|
153
145
|
force: Type.Optional(
|
|
154
146
|
Type.Boolean({
|
|
155
|
-
description: 'Overwrite user modifications on update
|
|
147
|
+
description: 'Overwrite user modifications on update (default: false)',
|
|
156
148
|
})
|
|
157
149
|
),
|
|
158
150
|
}),
|
|
159
|
-
async execute(
|
|
160
|
-
const
|
|
151
|
+
async execute(_callId, params, _signal, onUpdate, _ctx) {
|
|
152
|
+
const opts = {
|
|
161
153
|
targetDir: params.targetDir,
|
|
162
|
-
platform:
|
|
154
|
+
platform: 'pi' as const,
|
|
163
155
|
dryRun: params.dryRun ?? false,
|
|
164
156
|
force: params.force ?? false,
|
|
165
|
-
safe: !params.force
|
|
157
|
+
safe: !(params.force ?? false),
|
|
166
158
|
backup: true,
|
|
167
159
|
};
|
|
168
160
|
|
|
169
|
-
if (
|
|
170
|
-
onUpdate?.({
|
|
171
|
-
content: [
|
|
172
|
-
{
|
|
173
|
-
type: 'text',
|
|
174
|
-
text: 'Computing changes (dry-run)...',
|
|
175
|
-
},
|
|
176
|
-
],
|
|
177
|
-
});
|
|
161
|
+
if (opts.dryRun) {
|
|
162
|
+
onUpdate?.({ content: [{ type: 'text', text: 'Computing changes (dry-run)...' }] });
|
|
178
163
|
}
|
|
179
164
|
|
|
180
|
-
const result = await installKitApi(
|
|
165
|
+
const result = await installKitApi(opts);
|
|
181
166
|
|
|
182
167
|
if (!result.success) {
|
|
183
168
|
return {
|
|
184
169
|
content: [
|
|
185
|
-
{
|
|
186
|
-
type: 'text',
|
|
187
|
-
text: `Install failed: ${result.error?.message || 'Unknown error'}`,
|
|
188
|
-
},
|
|
170
|
+
{ type: 'text', text: `Install failed: ${result.error?.message || 'Unknown error'}` },
|
|
189
171
|
],
|
|
190
|
-
details: { error: result.error },
|
|
191
172
|
isError: true,
|
|
192
173
|
};
|
|
193
174
|
}
|
|
194
175
|
|
|
195
|
-
//
|
|
196
|
-
if (
|
|
197
|
-
const
|
|
176
|
+
// Dry-run: show change preview
|
|
177
|
+
if (opts.dryRun && 'wouldExecute' in (result.data || {})) {
|
|
178
|
+
const dr = result.data as {
|
|
198
179
|
wouldExecute: boolean;
|
|
199
180
|
actions: Array<{ type: string; description: string }>;
|
|
200
|
-
summary: Record<string, unknown>;
|
|
201
181
|
};
|
|
202
182
|
return {
|
|
203
183
|
content: [
|
|
204
184
|
{
|
|
205
185
|
type: 'text',
|
|
206
186
|
text: [
|
|
207
|
-
'# WordPress Agent Kit — Dry Run
|
|
208
|
-
'',
|
|
209
|
-
`Target: ${options.targetDir}`,
|
|
210
|
-
`Platform: ${options.platform}`,
|
|
187
|
+
'# WordPress Agent Kit — Dry Run',
|
|
211
188
|
'',
|
|
212
189
|
'## Changes',
|
|
213
|
-
...
|
|
190
|
+
...dr.actions.map((a) => `- **${a.type}**: ${a.description}`),
|
|
214
191
|
'',
|
|
215
|
-
'Run without dryRun to apply
|
|
192
|
+
'Run without `dryRun` to apply.',
|
|
216
193
|
].join('\n'),
|
|
217
194
|
},
|
|
218
195
|
],
|
|
219
|
-
details:
|
|
196
|
+
details: dr,
|
|
220
197
|
};
|
|
221
198
|
}
|
|
222
199
|
|
|
223
|
-
//
|
|
200
|
+
// Real result
|
|
224
201
|
const data = result.data as {
|
|
225
202
|
filesCreated: string[];
|
|
226
203
|
filesSkipped: string[];
|
|
@@ -230,40 +207,28 @@ export default function (pi: ExtensionAPI) {
|
|
|
230
207
|
};
|
|
231
208
|
|
|
232
209
|
const lines = [
|
|
233
|
-
data.isUpdate ? '#
|
|
210
|
+
data.isUpdate ? '# Updated' : '# Installed',
|
|
234
211
|
'',
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
`Files created/updated: ${data.filesCreated.length}`,
|
|
212
|
+
`**Target**: ${opts.targetDir}`,
|
|
213
|
+
`**Files**: ${data.filesCreated.length} created/updated`,
|
|
238
214
|
];
|
|
239
215
|
|
|
240
216
|
if (data.filesSkipped.length > 0) {
|
|
241
|
-
lines.push(
|
|
242
|
-
for (const skipped of data.filesSkipped.slice(0, 10)) {
|
|
243
|
-
lines.push(` - ${skipped}`);
|
|
244
|
-
}
|
|
217
|
+
lines.push(`**Preserved**: ${data.filesSkipped.length} files (user-modified)`);
|
|
245
218
|
}
|
|
246
219
|
|
|
247
|
-
if (data.conflicts
|
|
248
|
-
lines.push(
|
|
249
|
-
|
|
250
|
-
`⚠ ${data.conflicts.length} conflict(s) — re-run with force:true to overwrite:`
|
|
251
|
-
);
|
|
252
|
-
for (const conflict of data.conflicts.slice(0, 5)) {
|
|
253
|
-
lines.push(` - ${conflict}`);
|
|
254
|
-
}
|
|
220
|
+
if (data.conflicts?.length) {
|
|
221
|
+
lines.push('', '⚠ **Conflicts** (re-run with `force: true` to overwrite):');
|
|
222
|
+
for (const c of data.conflicts.slice(0, 5)) lines.push(`- ${c}`);
|
|
255
223
|
}
|
|
256
224
|
|
|
257
|
-
if (data.backupDir) {
|
|
258
|
-
lines.push('', `Backup created: ${data.backupDir}`);
|
|
259
|
-
}
|
|
225
|
+
if (data.backupDir) lines.push('', `**Backup**: ${data.backupDir}`);
|
|
260
226
|
|
|
261
227
|
lines.push(
|
|
262
228
|
'',
|
|
263
229
|
'## Next Steps',
|
|
264
|
-
'1. Run wp_triage to detect project type',
|
|
265
|
-
'2. Review AGENTS.md for
|
|
266
|
-
'3. Use `/skill:wp-project-triage` to begin development'
|
|
230
|
+
'1. Run `wp_triage` to detect project type',
|
|
231
|
+
'2. Review `AGENTS.md` for guidance'
|
|
267
232
|
);
|
|
268
233
|
|
|
269
234
|
return {
|
|
@@ -274,109 +239,45 @@ export default function (pi: ExtensionAPI) {
|
|
|
274
239
|
});
|
|
275
240
|
|
|
276
241
|
// --- wp_sync_skills ---
|
|
277
|
-
// Sync WordPress skills from upstream WordPress/agent-skills repo.
|
|
278
242
|
pi.registerTool({
|
|
279
243
|
name: 'wp_sync_skills',
|
|
280
244
|
label: 'WP Sync Skills',
|
|
281
245
|
description:
|
|
282
|
-
'Sync WordPress agent skills from the upstream WordPress/agent-skills repository
|
|
246
|
+
'Sync WordPress agent skills from the upstream WordPress/agent-skills repository. Fetches the latest 17 skill definitions and replaces the local skills directory.',
|
|
283
247
|
promptSnippet: 'Sync latest WordPress agent skills from upstream',
|
|
284
248
|
promptGuidelines: [
|
|
285
249
|
'Use wp_sync_skills to pull the latest WordPress development skills from WordPress/agent-skills.',
|
|
286
|
-
'Use wp_sync_skills with dryRun:true to preview before syncing.',
|
|
287
250
|
],
|
|
288
251
|
parameters: Type.Object({
|
|
289
|
-
targetDir: Type.Optional(
|
|
290
|
-
Type.String({
|
|
291
|
-
description: 'Target directory (defaults to the project root running wp-agent-kit)',
|
|
292
|
-
})
|
|
293
|
-
),
|
|
294
252
|
ref: Type.Optional(
|
|
295
253
|
Type.String({
|
|
296
254
|
description: 'Git ref to sync from (default: trunk)',
|
|
297
255
|
})
|
|
298
256
|
),
|
|
299
|
-
dryRun: Type.Optional(
|
|
300
|
-
Type.Boolean({
|
|
301
|
-
description: 'If true, preview without applying. Default: false',
|
|
302
|
-
})
|
|
303
|
-
),
|
|
304
257
|
}),
|
|
305
|
-
async execute(
|
|
306
|
-
|
|
307
|
-
targetDir: params.targetDir || process.cwd(),
|
|
308
|
-
ref: params.ref || 'trunk',
|
|
309
|
-
dryRun: params.dryRun ?? false,
|
|
310
|
-
};
|
|
258
|
+
async execute(_callId, params, _signal, onUpdate, _ctx) {
|
|
259
|
+
onUpdate?.({ content: [{ type: 'text', text: 'Syncing from WordPress/agent-skills...' }] });
|
|
311
260
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
type: 'text',
|
|
316
|
-
text: params.dryRun
|
|
317
|
-
? 'Previewing skill sync (dry-run)...'
|
|
318
|
-
: `Syncing skills from WordPress/agent-skills@${options.ref}...`,
|
|
319
|
-
},
|
|
320
|
-
],
|
|
261
|
+
const result = await syncSkillsApi({
|
|
262
|
+
targetDir: PACKAGE_ROOT,
|
|
263
|
+
ref: params.ref || 'trunk',
|
|
321
264
|
});
|
|
322
265
|
|
|
323
|
-
const result = await syncSkillsApi(options);
|
|
324
|
-
|
|
325
266
|
if (!result.success) {
|
|
326
267
|
return {
|
|
327
268
|
content: [
|
|
328
|
-
{
|
|
329
|
-
type: 'text',
|
|
330
|
-
text: `Sync failed: ${result.error?.message || 'Unknown error'}`,
|
|
331
|
-
},
|
|
269
|
+
{ type: 'text', text: `Sync failed: ${result.error?.message || 'Unknown error'}` },
|
|
332
270
|
],
|
|
333
|
-
details: { error: result.error },
|
|
334
271
|
isError: true,
|
|
335
272
|
};
|
|
336
273
|
}
|
|
337
274
|
|
|
338
|
-
|
|
339
|
-
const dryRun = result.data as {
|
|
340
|
-
wouldExecute: boolean;
|
|
341
|
-
actions: Array<{ type: string; description: string }>;
|
|
342
|
-
};
|
|
343
|
-
return {
|
|
344
|
-
content: [
|
|
345
|
-
{
|
|
346
|
-
type: 'text',
|
|
347
|
-
text: [
|
|
348
|
-
'# Skill Sync — Dry Run',
|
|
349
|
-
'',
|
|
350
|
-
`Source: WordPress/agent-skills@${options.ref}`,
|
|
351
|
-
'',
|
|
352
|
-
'## Actions',
|
|
353
|
-
...dryRun.actions.map((a) => `- ${a.type}: ${a.description}`),
|
|
354
|
-
'',
|
|
355
|
-
'Run without dryRun to apply.',
|
|
356
|
-
].join('\n'),
|
|
357
|
-
},
|
|
358
|
-
],
|
|
359
|
-
details: dryRun,
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const data = result.data as {
|
|
364
|
-
skillsSynced: number;
|
|
365
|
-
method: string;
|
|
366
|
-
sourceUrl: string;
|
|
367
|
-
};
|
|
368
|
-
|
|
275
|
+
const data = result.data as { skillsSynced: number; method: string };
|
|
369
276
|
return {
|
|
370
277
|
content: [
|
|
371
278
|
{
|
|
372
279
|
type: 'text',
|
|
373
|
-
text:
|
|
374
|
-
'# Skills Synced',
|
|
375
|
-
'',
|
|
376
|
-
`Skills synced: ${data.skillsSynced}`,
|
|
377
|
-
`Method: ${data.method}`,
|
|
378
|
-
`Source: ${data.sourceUrl}`,
|
|
379
|
-
].join('\n'),
|
|
280
|
+
text: `# Skills Synced\n\n**Synced**: ${data.skillsSynced} skills\n**Method**: ${data.method}`,
|
|
380
281
|
},
|
|
381
282
|
],
|
|
382
283
|
details: data,
|
|
@@ -385,60 +286,44 @@ export default function (pi: ExtensionAPI) {
|
|
|
385
286
|
});
|
|
386
287
|
|
|
387
288
|
// --- wp_upgrade ---
|
|
388
|
-
// Check and apply WordPress Agent Kit upgrades.
|
|
389
289
|
pi.registerTool({
|
|
390
290
|
name: 'wp_upgrade',
|
|
391
291
|
label: 'WP Upgrade',
|
|
392
292
|
description:
|
|
393
|
-
'Check for WordPress Agent Kit updates
|
|
394
|
-
promptSnippet: 'Check
|
|
293
|
+
'Check for WordPress Agent Kit updates. Shows current vs latest version and can preview or apply upgrades.',
|
|
294
|
+
promptSnippet: 'Check WordPress Agent Kit version',
|
|
395
295
|
promptGuidelines: [
|
|
396
296
|
'Use wp_upgrade to check if the installed WordPress Agent Kit is up to date.',
|
|
397
|
-
'Use wp_upgrade with checkOnly:true to preview without applying.',
|
|
297
|
+
'Use wp_upgrade with checkOnly: true to preview without applying.',
|
|
398
298
|
],
|
|
399
299
|
parameters: Type.Object({
|
|
400
300
|
targetDir: Type.Optional(
|
|
401
301
|
Type.String({
|
|
402
|
-
description: '
|
|
302
|
+
description: 'Project directory to check (defaults to cwd)',
|
|
403
303
|
})
|
|
404
304
|
),
|
|
405
305
|
checkOnly: Type.Optional(
|
|
406
306
|
Type.Boolean({
|
|
407
|
-
description: 'Only check for updates, do not apply
|
|
408
|
-
})
|
|
409
|
-
),
|
|
410
|
-
force: Type.Optional(
|
|
411
|
-
Type.Boolean({
|
|
412
|
-
description: 'Overwrite user modifications on upgrade. Default: false',
|
|
307
|
+
description: 'Only check for updates, do not apply (default: false)',
|
|
413
308
|
})
|
|
414
309
|
),
|
|
415
310
|
}),
|
|
416
|
-
async execute(
|
|
311
|
+
async execute(_callId, params, _signal, _onUpdate, _ctx) {
|
|
417
312
|
const targetDir = params.targetDir || process.cwd();
|
|
418
|
-
const force = params.force ?? false;
|
|
419
313
|
const checkOnly = params.checkOnly ?? false;
|
|
314
|
+
const manifest = loadManifest(targetDir, 'pi') || loadManifest(targetDir, 'github');
|
|
315
|
+
const currentVersion = manifest?.version || 'not installed';
|
|
316
|
+
const latestVersion = (() => {
|
|
317
|
+
try {
|
|
318
|
+
const fs = require('node:fs');
|
|
319
|
+
return JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf-8'))
|
|
320
|
+
.version;
|
|
321
|
+
} catch {
|
|
322
|
+
return 'unknown';
|
|
323
|
+
}
|
|
324
|
+
})();
|
|
420
325
|
|
|
421
|
-
|
|
422
|
-
const fs = await import('node:fs');
|
|
423
|
-
const path = await import('node:path');
|
|
424
|
-
const pkgPath = path.join(
|
|
425
|
-
path.dirname(new URL(import.meta.url).pathname),
|
|
426
|
-
'..',
|
|
427
|
-
'..',
|
|
428
|
-
'..',
|
|
429
|
-
'package.json'
|
|
430
|
-
);
|
|
431
|
-
let latestVersion = 'unknown';
|
|
432
|
-
try {
|
|
433
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
434
|
-
latestVersion = pkg.version;
|
|
435
|
-
} catch {
|
|
436
|
-
// fallback
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
const manifest = loadManifest(targetDir, 'github');
|
|
440
|
-
const currentVersion = manifest?.version || 'unknown';
|
|
441
|
-
const isInstalled = isKitInstalled(targetDir, 'github');
|
|
326
|
+
const installed = isKitInstalled(targetDir, 'pi') || isKitInstalled(targetDir, 'github');
|
|
442
327
|
|
|
443
328
|
if (checkOnly) {
|
|
444
329
|
return {
|
|
@@ -448,57 +333,39 @@ export default function (pi: ExtensionAPI) {
|
|
|
448
333
|
text: [
|
|
449
334
|
'# WordPress Agent Kit — Version Check',
|
|
450
335
|
'',
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
`Latest version: ${latestVersion}`,
|
|
336
|
+
`**Installed**: ${installed ? 'yes' : 'no'}`,
|
|
337
|
+
`**Current**: ${currentVersion}`,
|
|
338
|
+
`**Latest**: ${latestVersion}`,
|
|
455
339
|
'',
|
|
456
|
-
currentVersion !== latestVersion &&
|
|
457
|
-
? '⚠ Update available. Run without checkOnly to apply.'
|
|
458
|
-
:
|
|
459
|
-
? '
|
|
460
|
-
: 'Not installed. Use wp_install_kit to install.',
|
|
340
|
+
currentVersion !== latestVersion && installed
|
|
341
|
+
? '⚠ Update available. Run without `checkOnly` to apply.'
|
|
342
|
+
: installed
|
|
343
|
+
? '✅ Up to date.'
|
|
344
|
+
: 'Not installed. Use `wp_install_kit` to install.',
|
|
461
345
|
].join('\n'),
|
|
462
346
|
},
|
|
463
347
|
],
|
|
464
|
-
details: {
|
|
465
|
-
targetDir,
|
|
466
|
-
currentVersion,
|
|
467
|
-
latestVersion,
|
|
468
|
-
isInstalled,
|
|
469
|
-
},
|
|
348
|
+
details: { currentVersion, latestVersion, installed },
|
|
470
349
|
};
|
|
471
350
|
}
|
|
472
351
|
|
|
473
|
-
|
|
474
|
-
if (!isInstalled) {
|
|
352
|
+
if (!installed) {
|
|
475
353
|
return {
|
|
476
|
-
content: [
|
|
477
|
-
{
|
|
478
|
-
type: 'text',
|
|
479
|
-
text: 'Kit not installed. Use wp_install_kit to install first.',
|
|
480
|
-
},
|
|
481
|
-
],
|
|
354
|
+
content: [{ type: 'text', text: 'Kit not installed. Use `wp_install_kit` first.' }],
|
|
482
355
|
isError: true,
|
|
483
356
|
};
|
|
484
357
|
}
|
|
485
358
|
|
|
486
359
|
const result = await installKitApi({
|
|
487
360
|
targetDir,
|
|
488
|
-
platform: '
|
|
489
|
-
|
|
490
|
-
safe: !force,
|
|
361
|
+
platform: 'pi',
|
|
362
|
+
safe: true,
|
|
491
363
|
backup: true,
|
|
492
364
|
});
|
|
493
365
|
|
|
494
366
|
if (!result.success) {
|
|
495
367
|
return {
|
|
496
|
-
content: [
|
|
497
|
-
{
|
|
498
|
-
type: 'text',
|
|
499
|
-
text: `Upgrade failed: ${result.error?.message || 'Unknown error'}`,
|
|
500
|
-
},
|
|
501
|
-
],
|
|
368
|
+
content: [{ type: 'text', text: `Upgrade failed: ${result.error?.message}` }],
|
|
502
369
|
isError: true,
|
|
503
370
|
};
|
|
504
371
|
}
|
|
@@ -507,28 +374,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
507
374
|
filesCreated: string[];
|
|
508
375
|
filesSkipped: string[];
|
|
509
376
|
conflicts?: string[];
|
|
510
|
-
backupDir: string | null;
|
|
511
377
|
};
|
|
512
|
-
|
|
513
378
|
const lines = [
|
|
514
|
-
'#
|
|
379
|
+
'# Upgraded',
|
|
515
380
|
'',
|
|
516
|
-
|
|
517
|
-
|
|
381
|
+
`**Version**: ${currentVersion} → ${latestVersion}`,
|
|
382
|
+
`**Files updated**: ${data.filesCreated.length}`,
|
|
518
383
|
];
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
if (data.conflicts && data.conflicts.length > 0) {
|
|
524
|
-
lines.push(
|
|
525
|
-
'',
|
|
526
|
-
`⚠ ${data.conflicts.length} conflict(s) — re-run with force:true to overwrite.`
|
|
527
|
-
);
|
|
528
|
-
}
|
|
529
|
-
if (data.backupDir) {
|
|
530
|
-
lines.push(`Backup: ${data.backupDir}`);
|
|
531
|
-
}
|
|
384
|
+
if (data.filesSkipped.length)
|
|
385
|
+
lines.push(`**Preserved**: ${data.filesSkipped.length} (user-modified)`);
|
|
386
|
+
if (data.conflicts?.length)
|
|
387
|
+
lines.push(`⚠ ${data.conflicts.length} conflicts (use force: true)`);
|
|
532
388
|
|
|
533
389
|
return {
|
|
534
390
|
content: [{ type: 'text', text: lines.join('\n') }],
|
|
@@ -546,85 +402,51 @@ export default function (pi: ExtensionAPI) {
|
|
|
546
402
|
handler: async (args, ctx) => {
|
|
547
403
|
const targetDir = args?.trim() || ctx.cwd;
|
|
548
404
|
ctx.ui.setStatus('wp-triage', 'Running triage...');
|
|
549
|
-
const result = await runTriageApi({ targetDir });
|
|
550
|
-
|
|
405
|
+
const result = await runTriageApi({ targetDir, platform: 'pi' });
|
|
551
406
|
if (!result.success) {
|
|
552
407
|
ctx.ui.notify(`Triage failed: ${result.error?.message}`, 'error');
|
|
553
408
|
return;
|
|
554
409
|
}
|
|
555
|
-
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
? `${triage.project.primary} (confidence: ${triage.project.confidence})`
|
|
410
|
+
const t = result.data;
|
|
411
|
+
const summary = t.project
|
|
412
|
+
? `${t.project.primary} (confidence: ${t.project.confidence})`
|
|
559
413
|
: 'unknown';
|
|
560
414
|
ctx.ui.notify(`Project: ${summary}`, 'info');
|
|
561
|
-
ctx.ui.setStatus('wp-triage',
|
|
415
|
+
ctx.ui.setStatus('wp-triage', summary);
|
|
562
416
|
},
|
|
563
417
|
});
|
|
564
418
|
|
|
565
419
|
pi.registerCommand('wp-install', {
|
|
566
|
-
description: 'Install WordPress Agent Kit into
|
|
420
|
+
description: 'Install WordPress Agent Kit into current project',
|
|
567
421
|
handler: async (args, ctx) => {
|
|
568
422
|
const targetDir = args?.trim() || ctx.cwd;
|
|
569
423
|
ctx.ui.setStatus('wp-install', 'Installing...');
|
|
570
|
-
const result = await installKitApi({
|
|
571
|
-
targetDir,
|
|
572
|
-
platform: 'github',
|
|
573
|
-
safe: true,
|
|
574
|
-
backup: true,
|
|
575
|
-
});
|
|
576
|
-
|
|
424
|
+
const result = await installKitApi({ targetDir, platform: 'pi', safe: true, backup: true });
|
|
577
425
|
if (!result.success) {
|
|
578
426
|
ctx.ui.notify(`Install failed: ${result.error?.message}`, 'error');
|
|
579
427
|
return;
|
|
580
428
|
}
|
|
581
|
-
|
|
582
429
|
const data = result.data as { filesCreated: string[]; isUpdate: boolean };
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
430
|
+
ctx.ui.notify(
|
|
431
|
+
`${data.isUpdate ? 'Updated' : 'Installed'} (${data.filesCreated.length} entries)`,
|
|
432
|
+
'info'
|
|
433
|
+
);
|
|
434
|
+
ctx.ui.setStatus('wp-agent-kit', 'v0.3.0 installed');
|
|
586
435
|
},
|
|
587
436
|
});
|
|
588
437
|
|
|
589
438
|
pi.registerCommand('wp-sync-skills', {
|
|
590
439
|
description: 'Sync WordPress skills from upstream',
|
|
591
440
|
handler: async (args, ctx) => {
|
|
592
|
-
ctx.ui.setStatus('wp-sync', 'Syncing
|
|
593
|
-
const result = await syncSkillsApi({
|
|
594
|
-
ref: args?.trim() || 'trunk',
|
|
595
|
-
});
|
|
596
|
-
|
|
441
|
+
ctx.ui.setStatus('wp-sync', 'Syncing...');
|
|
442
|
+
const result = await syncSkillsApi({ targetDir: PACKAGE_ROOT, ref: args?.trim() || 'trunk' });
|
|
597
443
|
if (!result.success) {
|
|
598
444
|
ctx.ui.notify(`Sync failed: ${result.error?.message}`, 'error');
|
|
599
445
|
return;
|
|
600
446
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
ctx.ui.
|
|
604
|
-
ctx.ui.setStatus('wp-sync', `${data.skillsSynced} skills`);
|
|
605
|
-
},
|
|
606
|
-
});
|
|
607
|
-
|
|
608
|
-
pi.registerCommand('wp-upgrade', {
|
|
609
|
-
description: 'Check or apply WordPress Agent Kit upgrades',
|
|
610
|
-
handler: async (_args, ctx) => {
|
|
611
|
-
const targetDir = ctx.cwd;
|
|
612
|
-
const manifest = loadManifest(targetDir, 'github');
|
|
613
|
-
const currentVersion = manifest?.version || 'not installed';
|
|
614
|
-
|
|
615
|
-
const pkgPath = `${ctx.cwd}/node_modules/wordpress-agent-kit/package.json`;
|
|
616
|
-
let latestVersion = 'unknown';
|
|
617
|
-
try {
|
|
618
|
-
const fs = await import('node:fs');
|
|
619
|
-
if (fs.existsSync(pkgPath)) {
|
|
620
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
621
|
-
latestVersion = pkg.version;
|
|
622
|
-
}
|
|
623
|
-
} catch {
|
|
624
|
-
// fallback
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
ctx.ui.notify(`WP Agent Kit: ${currentVersion} → ${latestVersion}`, 'info');
|
|
447
|
+
const data = result.data as { skillsSynced: number };
|
|
448
|
+
ctx.ui.notify(`Synced ${data.skillsSynced} skills`, 'info');
|
|
449
|
+
ctx.ui.setStatus('wp-agent-kit', `${data.skillsSynced} skills`);
|
|
628
450
|
},
|
|
629
451
|
});
|
|
630
452
|
}
|