@wootsup/yt-builder-mcp 1.0.0 → 1.1.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/README.md +18 -6
- package/bin/yt-builder-mcp.js +6 -0
- package/dist/auth.d.ts +86 -6
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +141 -8
- package/dist/auth.js.map +1 -1
- package/dist/errors/sanitize.d.ts.map +1 -1
- package/dist/errors/sanitize.js +10 -0
- package/dist/errors/sanitize.js.map +1 -1
- package/dist/gateway/essentials.d.ts +1 -1
- package/dist/gateway/essentials.d.ts.map +1 -1
- package/dist/gateway/essentials.js +15 -2
- package/dist/gateway/essentials.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -16
- package/dist/index.js.map +1 -1
- package/dist/install-skill.d.ts +10 -2
- package/dist/install-skill.d.ts.map +1 -1
- package/dist/install-skill.js +18 -7
- package/dist/install-skill.js.map +1 -1
- package/dist/platform/detect.d.ts +64 -0
- package/dist/platform/detect.d.ts.map +1 -0
- package/dist/platform/detect.js +98 -0
- package/dist/platform/detect.js.map +1 -0
- package/dist/platform/index.d.ts +72 -0
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/index.js +138 -0
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/joomla.d.ts +44 -0
- package/dist/platform/joomla.d.ts.map +1 -0
- package/dist/platform/joomla.js +46 -0
- package/dist/platform/joomla.js.map +1 -0
- package/dist/server.d.ts +61 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +86 -2
- package/dist/server.js.map +1 -1
- package/dist/setup-cli-confirm.d.ts +36 -0
- package/dist/setup-cli-confirm.d.ts.map +1 -0
- package/dist/setup-cli-confirm.js +59 -0
- package/dist/setup-cli-confirm.js.map +1 -0
- package/dist/setup-cli.d.ts +53 -1
- package/dist/setup-cli.d.ts.map +1 -1
- package/dist/setup-cli.js +525 -10
- package/dist/setup-cli.js.map +1 -1
- package/dist/setup-prompts.d.ts.map +1 -1
- package/dist/setup-prompts.js +12 -8
- package/dist/setup-prompts.js.map +1 -1
- package/dist/setup-wizard-types.d.ts +19 -3
- package/dist/setup-wizard-types.d.ts.map +1 -1
- package/dist/setup-wizard.d.ts.map +1 -1
- package/dist/setup-wizard.js +34 -1
- package/dist/setup-wizard.js.map +1 -1
- package/dist/sites/cli/add-site.d.ts +106 -0
- package/dist/sites/cli/add-site.d.ts.map +1 -0
- package/dist/sites/cli/add-site.js +185 -0
- package/dist/sites/cli/add-site.js.map +1 -0
- package/dist/sites/cli/list-sites.d.ts +40 -0
- package/dist/sites/cli/list-sites.d.ts.map +1 -0
- package/dist/sites/cli/list-sites.js +117 -0
- package/dist/sites/cli/list-sites.js.map +1 -0
- package/dist/sites/cli/remove-site.d.ts +60 -0
- package/dist/sites/cli/remove-site.d.ts.map +1 -0
- package/dist/sites/cli/remove-site.js +120 -0
- package/dist/sites/cli/remove-site.js.map +1 -0
- package/dist/sites/cli/set-default.d.ts +47 -0
- package/dist/sites/cli/set-default.d.ts.map +1 -0
- package/dist/sites/cli/set-default.js +69 -0
- package/dist/sites/cli/set-default.js.map +1 -0
- package/dist/sites/cli/test-site.d.ts +77 -0
- package/dist/sites/cli/test-site.d.ts.map +1 -0
- package/dist/sites/cli/test-site.js +146 -0
- package/dist/sites/cli/test-site.js.map +1 -0
- package/dist/sites/client-pool.d.ts +124 -0
- package/dist/sites/client-pool.d.ts.map +1 -0
- package/dist/sites/client-pool.js +172 -0
- package/dist/sites/client-pool.js.map +1 -0
- package/dist/sites/env-bridge.d.ts +55 -0
- package/dist/sites/env-bridge.d.ts.map +1 -0
- package/dist/sites/env-bridge.js +94 -0
- package/dist/sites/env-bridge.js.map +1 -0
- package/dist/sites/paths.d.ts +21 -0
- package/dist/sites/paths.d.ts.map +1 -0
- package/dist/sites/paths.js +37 -0
- package/dist/sites/paths.js.map +1 -0
- package/dist/sites/probe.d.ts +60 -0
- package/dist/sites/probe.d.ts.map +1 -0
- package/dist/sites/probe.js +112 -0
- package/dist/sites/probe.js.map +1 -0
- package/dist/sites/registry.d.ts +142 -0
- package/dist/sites/registry.d.ts.map +1 -0
- package/dist/sites/registry.js +163 -0
- package/dist/sites/registry.js.map +1 -0
- package/dist/sites/schema.d.ts +90 -0
- package/dist/sites/schema.d.ts.map +1 -0
- package/dist/sites/schema.js +71 -0
- package/dist/sites/schema.js.map +1 -0
- package/dist/sites/secret-resolver.d.ts +109 -0
- package/dist/sites/secret-resolver.d.ts.map +1 -0
- package/dist/sites/secret-resolver.js +189 -0
- package/dist/sites/secret-resolver.js.map +1 -0
- package/dist/sites/store.d.ts +82 -0
- package/dist/sites/store.d.ts.map +1 -0
- package/dist/sites/store.js +198 -0
- package/dist/sites/store.js.map +1 -0
- package/dist/sites/tools/index.d.ts +28 -0
- package/dist/sites/tools/index.d.ts.map +1 -0
- package/dist/sites/tools/index.js +30 -0
- package/dist/sites/tools/index.js.map +1 -0
- package/dist/sites/tools/sites-list.d.ts +48 -0
- package/dist/sites/tools/sites-list.d.ts.map +1 -0
- package/dist/sites/tools/sites-list.js +135 -0
- package/dist/sites/tools/sites-list.js.map +1 -0
- package/dist/sites/tools/sites-test.d.ts +47 -0
- package/dist/sites/tools/sites-test.d.ts.map +1 -0
- package/dist/sites/tools/sites-test.js +148 -0
- package/dist/sites/tools/sites-test.js.map +1 -0
- package/dist/skill-loader.d.ts +63 -3
- package/dist/skill-loader.d.ts.map +1 -1
- package/dist/skill-loader.js +123 -10
- package/dist/skill-loader.js.map +1 -1
- package/dist/tools/elements/builders.d.ts +2 -2
- package/dist/tools/elements/builders.d.ts.map +1 -1
- package/dist/tools/elements/builders.js +45 -23
- package/dist/tools/elements/builders.js.map +1 -1
- package/dist/tools/elements/handlers.d.ts +8 -1
- package/dist/tools/elements/handlers.d.ts.map +1 -1
- package/dist/tools/elements/handlers.js +37 -1
- package/dist/tools/elements/handlers.js.map +1 -1
- package/dist/tools/format/health-format.d.ts +12 -6
- package/dist/tools/format/health-format.d.ts.map +1 -1
- package/dist/tools/format/health-format.js +14 -11
- package/dist/tools/format/health-format.js.map +1 -1
- package/dist/tools/format/pages-format.d.ts +7 -1
- package/dist/tools/format/pages-format.d.ts.map +1 -1
- package/dist/tools/format/pages-format.js +25 -1
- package/dist/tools/format/pages-format.js.map +1 -1
- package/dist/tools/health.d.ts +2 -2
- package/dist/tools/health.d.ts.map +1 -1
- package/dist/tools/health.js +120 -47
- package/dist/tools/health.js.map +1 -1
- package/dist/tools/index.d.ts +9 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +21 -7
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/inspection.d.ts +2 -2
- package/dist/tools/inspection.d.ts.map +1 -1
- package/dist/tools/inspection.js +67 -22
- package/dist/tools/inspection.js.map +1 -1
- package/dist/tools/multi-items/builders.d.ts +2 -2
- package/dist/tools/multi-items/builders.d.ts.map +1 -1
- package/dist/tools/multi-items/builders.js +21 -8
- package/dist/tools/multi-items/builders.js.map +1 -1
- package/dist/tools/pages/builders.d.ts +2 -2
- package/dist/tools/pages/builders.d.ts.map +1 -1
- package/dist/tools/pages/builders.js +36 -24
- package/dist/tools/pages/builders.js.map +1 -1
- package/dist/tools/pages/handlers-read.d.ts.map +1 -1
- package/dist/tools/pages/handlers-read.js +10 -0
- package/dist/tools/pages/handlers-read.js.map +1 -1
- package/dist/tools/pages/schemas.d.ts.map +1 -1
- package/dist/tools/pages/schemas.js +18 -0
- package/dist/tools/pages/schemas.js.map +1 -1
- package/dist/tools/pool-resolve-helper.d.ts +83 -0
- package/dist/tools/pool-resolve-helper.d.ts.map +1 -0
- package/dist/tools/pool-resolve-helper.js +148 -0
- package/dist/tools/pool-resolve-helper.js.map +1 -0
- package/dist/tools/shared-schemas.d.ts +10 -0
- package/dist/tools/shared-schemas.d.ts.map +1 -1
- package/dist/tools/shared-schemas.js +20 -2
- package/dist/tools/shared-schemas.js.map +1 -1
- package/dist/tools/sources/builders.d.ts +2 -2
- package/dist/tools/sources/builders.d.ts.map +1 -1
- package/dist/tools/sources/builders.js +27 -15
- package/dist/tools/sources/builders.js.map +1 -1
- package/dist/tools/tool-builder/index.d.ts +1 -1
- package/dist/tools/tool-builder/index.d.ts.map +1 -1
- package/dist/tools/tool-builder/index.js +1 -1
- package/dist/tools/tool-builder/index.js.map +1 -1
- package/dist/tools/tool-builder/results.d.ts +34 -0
- package/dist/tools/tool-builder/results.d.ts.map +1 -1
- package/dist/tools/tool-builder/results.js +86 -0
- package/dist/tools/tool-builder/results.js.map +1 -1
- package/manifest.json +27 -10
- package/package.json +3 -1
- package/skills/yt-builder-mcp/SKILL.md +846 -0
- package/skills/yootheme-builder/SKILL.md +0 -587
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* W7 — `yootheme_builder_sites_test` L1 tool.
|
|
3
|
+
*
|
|
4
|
+
* Targeted connectivity probe for ONE site_id: runs `/health` (no auth
|
|
5
|
+
* required) + `/etag` (auth required) in parallel and returns a
|
|
6
|
+
* structured `{plugin_reachable, bearer_valid, platform, ...}` block.
|
|
7
|
+
*
|
|
8
|
+
* Why `site_id` is REQUIRED here (not optional):
|
|
9
|
+
* - Every other tool in the registry treats `site_id` as an optional
|
|
10
|
+
* selector that falls back to the default. `sites_test` is the
|
|
11
|
+
* exception: its raison d'être is to verify ONE specific id, so the
|
|
12
|
+
* schema upgrades from `.optional()` to required. The W5
|
|
13
|
+
* SITE_ID_SCHEMA pin-test in `tests/tools/site-id-schema.test.ts`
|
|
14
|
+
* explicitly skips this tool from its "every tool's site_id is
|
|
15
|
+
* optional" loop — see the SITES_TEST_EXEMPT_FROM_OPTIONAL set there.
|
|
16
|
+
*
|
|
17
|
+
* Why the result wraps `withSiteMeta`:
|
|
18
|
+
* - Once `pool.resolve(site_id)` succeeds we DO have a resolved-site
|
|
19
|
+
* descriptor, so the text-prefix `[<label> @ <host>] ` is the same
|
|
20
|
+
* site-awareness signal a Maria-class user already sees on every
|
|
21
|
+
* other tool. The W6.2 wrapper handles both green AND red results
|
|
22
|
+
* uniformly (it just stamps; no behaviour difference).
|
|
23
|
+
*
|
|
24
|
+
* Failure modes mapped:
|
|
25
|
+
* - `UnknownSiteError` → structured error `code: 'unknown_site'` with
|
|
26
|
+
* `available[]` hint (via `resolveSiteOrError`).
|
|
27
|
+
* - `NoDefaultSiteError` → cannot fire here because site_id is required
|
|
28
|
+
* and validated by Zod before the handler runs; left in the helper
|
|
29
|
+
* for defense-in-depth.
|
|
30
|
+
* - `/health` rejects → `plugin_reachable: false` + error message.
|
|
31
|
+
* - `/etag` 401/403 → `plugin_reachable: true` + `bearer_valid: false`.
|
|
32
|
+
* - `/etag` other reject → `plugin_reachable: true` + `bearer_valid:
|
|
33
|
+
* false` + raw error.
|
|
34
|
+
*
|
|
35
|
+
* @license MIT
|
|
36
|
+
*/
|
|
37
|
+
import { detailResult } from '@getimo/mcp-toolkit';
|
|
38
|
+
import { z } from 'zod';
|
|
39
|
+
import { resolveSiteOrError, } from '../../tools/pool-resolve-helper.js';
|
|
40
|
+
import { defineTool, readOnly, structuredResult, withSiteMeta, } from '../../tools/tool-builder.js';
|
|
41
|
+
import { probeSite } from '../probe.js';
|
|
42
|
+
const SITES_TEST_OUTPUT_SCHEMA = z.object({
|
|
43
|
+
site_id: z.string(),
|
|
44
|
+
site_url: z.string(),
|
|
45
|
+
platform: z.enum(['wordpress', 'joomla']),
|
|
46
|
+
plugin_reachable: z.boolean(),
|
|
47
|
+
bearer_valid: z.boolean(),
|
|
48
|
+
etag_received: z.boolean(),
|
|
49
|
+
plugin_error: z.string().optional(),
|
|
50
|
+
bearer_error: z.string().optional(),
|
|
51
|
+
summary: z.string(),
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* Build the W7 `yootheme_builder_sites_test` tool.
|
|
55
|
+
*
|
|
56
|
+
* Signature accepts the {@link ClientPool} directly (no separate
|
|
57
|
+
* registry param) — `pool.resolve(site_id)` is the single source of
|
|
58
|
+
* truth and carries the registry inside.
|
|
59
|
+
*/
|
|
60
|
+
export function buildSitesTestTool(pool) {
|
|
61
|
+
return defineTool({
|
|
62
|
+
name: 'yootheme_builder_sites_test',
|
|
63
|
+
description: 'Verify connectivity to ONE site: probes /health (no auth) + ' +
|
|
64
|
+
'/etag (auth) in parallel; returns plugin_reachable + ' +
|
|
65
|
+
'bearer_valid. `site_id` is REQUIRED. Use sites_list to find IDs.',
|
|
66
|
+
inputSchema: {
|
|
67
|
+
site_id: z
|
|
68
|
+
.string()
|
|
69
|
+
.min(1)
|
|
70
|
+
.max(64)
|
|
71
|
+
.regex(/^[a-zA-Z0-9_-]+$/, 'site_id uses letters/digits/dash/underscore only')
|
|
72
|
+
.describe('Site to test (REQUIRED for this tool — overrides default). ' +
|
|
73
|
+
'Use yootheme_builder_sites_list to discover valid IDs.'),
|
|
74
|
+
},
|
|
75
|
+
outputSchema: SITES_TEST_OUTPUT_SCHEMA,
|
|
76
|
+
annotations: readOnly('Sites — Test connectivity'),
|
|
77
|
+
handler: async ({ site_id }) => {
|
|
78
|
+
const r = await resolveSiteOrError(pool, site_id);
|
|
79
|
+
if (!r.ok)
|
|
80
|
+
return r.error;
|
|
81
|
+
const { client: siteClient, site } = r;
|
|
82
|
+
// W12-R1.2: the parallel /health + /etag probe lives in
|
|
83
|
+
// sites/probe.ts so MCP-tool + CLI surfaces stay byte-for-byte
|
|
84
|
+
// in sync. The handler here only maps the structured probe
|
|
85
|
+
// result into the toolkit detail-card envelope and stamps
|
|
86
|
+
// site-awareness via withSiteMeta.
|
|
87
|
+
const probe = await probeSite(siteClient);
|
|
88
|
+
const checks = {
|
|
89
|
+
site_id: site.id,
|
|
90
|
+
site_url: site.url,
|
|
91
|
+
platform: site.platform.kind,
|
|
92
|
+
plugin_reachable: probe.plugin_reachable,
|
|
93
|
+
bearer_valid: probe.bearer_valid,
|
|
94
|
+
etag_received: probe.etag_received,
|
|
95
|
+
summary: probe.summary,
|
|
96
|
+
...(probe.plugin_error !== undefined ? { plugin_error: probe.plugin_error } : {}),
|
|
97
|
+
...(probe.bearer_error !== undefined ? { bearer_error: probe.bearer_error } : {}),
|
|
98
|
+
};
|
|
99
|
+
const toolkitResult = detailResult(buildTestDetail(checks));
|
|
100
|
+
const isError = !(checks.plugin_reachable && checks.bearer_valid);
|
|
101
|
+
const base = structuredResult(toolkitResult, {
|
|
102
|
+
...checks,
|
|
103
|
+
});
|
|
104
|
+
const wrapped = isError
|
|
105
|
+
? { ...base, isError: true }
|
|
106
|
+
: base;
|
|
107
|
+
return withSiteMeta(wrapped, site);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Render a 2-group detail-card body from the structured `checks`. Group
|
|
113
|
+
* 1 = identity (site_id/url/platform), Group 2 = probe results
|
|
114
|
+
* (plugin_reachable + bearer_valid + etag_received + summary). Keeps the
|
|
115
|
+
* shape stable across green / partial / red so MCP-host Detail-Card
|
|
116
|
+
* renderers don't need to branch.
|
|
117
|
+
*/
|
|
118
|
+
function buildTestDetail(checks) {
|
|
119
|
+
const identityEntries = [
|
|
120
|
+
{ key: 'site_id', label: 'Site ID', value: checks.site_id, format: 'badge' },
|
|
121
|
+
{ key: 'site_url', label: 'Site URL', value: checks.site_url },
|
|
122
|
+
{ key: 'platform', label: 'Platform', value: checks.platform, format: 'badge' },
|
|
123
|
+
];
|
|
124
|
+
const probeEntries = [
|
|
125
|
+
{ key: 'plugin_reachable', label: 'Plugin reachable', value: checks.plugin_reachable, format: 'boolean' },
|
|
126
|
+
{ key: 'bearer_valid', label: 'Bearer valid', value: checks.bearer_valid, format: 'boolean' },
|
|
127
|
+
{ key: 'etag_received', label: 'ETag received', value: checks.etag_received, format: 'boolean' },
|
|
128
|
+
{ key: 'summary', label: 'Summary', value: checks.summary },
|
|
129
|
+
];
|
|
130
|
+
if (checks.plugin_error !== undefined) {
|
|
131
|
+
probeEntries.push({
|
|
132
|
+
key: 'plugin_error', label: 'Plugin error', value: checks.plugin_error, format: 'code',
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (checks.bearer_error !== undefined) {
|
|
136
|
+
probeEntries.push({
|
|
137
|
+
key: 'bearer_error', label: 'Bearer error', value: checks.bearer_error, format: 'code',
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
title: 'YT Builder MCP — Sites Test',
|
|
142
|
+
groups: [
|
|
143
|
+
{ label: 'Site', entries: identityEntries },
|
|
144
|
+
{ label: 'Probe', entries: probeEntries },
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=sites-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sites-test.js","sourceRoot":"","sources":["../../../src/sites/tools/sites-test.ts"],"names":[],"mappings":"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"}
|
package/dist/skill-loader.d.ts
CHANGED
|
@@ -16,18 +16,35 @@
|
|
|
16
16
|
*
|
|
17
17
|
* Resolution layout (matches `install-skill.ts` + `build-dxt.js`):
|
|
18
18
|
*
|
|
19
|
-
* packages/mcp/skills/
|
|
19
|
+
* packages/mcp/skills/yt-builder-mcp/SKILL.md
|
|
20
20
|
*
|
|
21
21
|
* When the file is compiled to `dist/skill-loader.js`, the same
|
|
22
|
-
* relative `../skills/
|
|
22
|
+
* relative `../skills/yt-builder-mcp/SKILL.md` resolves correctly
|
|
23
23
|
* because the published npm tarball (and the DXT stage) preserves the
|
|
24
24
|
* `skills/` folder next to `dist/`.
|
|
25
25
|
*
|
|
26
26
|
* Read errors throw at module-init: a missing SKILL.md is a packaging
|
|
27
27
|
* bug, not a recoverable runtime condition.
|
|
28
28
|
*
|
|
29
|
+
* W8 — `appendSitesBlock(skillContent, registry)` post-processor.
|
|
30
|
+
* When the in-process {@link SiteRegistry} carries ≥1 configured
|
|
31
|
+
* site, append a "Currently configured sites" appendix to the
|
|
32
|
+
* instructions string so MCP hosts surface the live site roster
|
|
33
|
+
* alongside the skill narrative. The appendix contains ONLY
|
|
34
|
+
* safe-to-render metadata (site_id, label, platform hint/resolved,
|
|
35
|
+
* url, default-flag) — bearer fields are NEVER touched. When the
|
|
36
|
+
* registry has 0 sites the original skill content is returned
|
|
37
|
+
* verbatim (no appendix, no separator).
|
|
38
|
+
*
|
|
39
|
+
* This is a pure-string post-processor; it does not touch the
|
|
40
|
+
* on-disk SKILL.md. Per plan §W8 (line 919) the MCP `initialize`
|
|
41
|
+
* response carries `instructions` as a single shot, so an AI client
|
|
42
|
+
* restart is required for the appendix to refresh after a sites file
|
|
43
|
+
* edit. The W9 CLI commands (add-site / remove-site) print a reminder.
|
|
44
|
+
*
|
|
29
45
|
* @license MIT
|
|
30
46
|
*/
|
|
47
|
+
import type { SiteRegistry } from './sites/registry.js';
|
|
31
48
|
/** Stable URI under which the skill resource is exposed via MCP `resources/*`. */
|
|
32
49
|
export declare const SKILL_RESOURCE_URI = "skill://yt-builder-mcp";
|
|
33
50
|
/** Human-readable resource name surfaced in `resources/list`. */
|
|
@@ -39,9 +56,52 @@ export declare const SKILL_RESOURCE_MIME_TYPE = "text/markdown";
|
|
|
39
56
|
/**
|
|
40
57
|
* Load the bundled SKILL.md content. Cached after the first read.
|
|
41
58
|
*
|
|
59
|
+
* When `registry` is supplied AND it carries ≥1 site, the returned
|
|
60
|
+
* string is the on-disk SKILL.md PLUS the W8 sites appendix (see
|
|
61
|
+
* {@link appendSitesBlock}). When `registry` is omitted or empty, the
|
|
62
|
+
* raw skill content is returned unchanged. The disk cache is shared
|
|
63
|
+
* across calls — the appendix is recomputed each time so registry
|
|
64
|
+
* mutations after the first load are reflected (within the same
|
|
65
|
+
* process instance — the MCP `initialize` response only takes a
|
|
66
|
+
* single-shot snapshot per session per plan §W8 line 919).
|
|
67
|
+
*
|
|
42
68
|
* @throws Error when the file is missing or unreadable (packaging bug).
|
|
43
69
|
*/
|
|
44
|
-
export declare function loadSkillContent(): string;
|
|
70
|
+
export declare function loadSkillContent(registry?: SiteRegistry): string;
|
|
71
|
+
/**
|
|
72
|
+
* Append the W8 "Currently configured sites" block to a skill-content
|
|
73
|
+
* string. When the registry is empty, returns the input verbatim — no
|
|
74
|
+
* separator, no header, no trailing newline change.
|
|
75
|
+
*
|
|
76
|
+
* Output shape (per plan §W8 Z.904-917):
|
|
77
|
+
* ```text
|
|
78
|
+
* <skillContent>
|
|
79
|
+
*
|
|
80
|
+
* ---
|
|
81
|
+
*
|
|
82
|
+
* ## Currently configured sites (3)
|
|
83
|
+
*
|
|
84
|
+
* - `wp-acme` — Acme — Production · wordpress · https://acme.com · default
|
|
85
|
+
* - `joomla-beta` — Beta — Staging · joomla · https://beta.example.com/joomla
|
|
86
|
+
* - `wp-internal` — Internal staging · wordpress · https://internal.example.com
|
|
87
|
+
*
|
|
88
|
+
* Use `yootheme_builder_sites_list` to inspect this at runtime.
|
|
89
|
+
* Pass `site_id: "<id>"` on any tool call to target a specific site;
|
|
90
|
+
* omit it to use the default.
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* Per-row format (bullet):
|
|
94
|
+
* `- \`<site_id>\` — <label or "(no label)"> · <platform> · <url><" · default"?>`
|
|
95
|
+
*
|
|
96
|
+
* The platform column prefers `platform_resolved` when the registry
|
|
97
|
+
* has memoised a probe result for that site (peek-only — never
|
|
98
|
+
* triggers a new probe), and falls back to `platform_hint` otherwise.
|
|
99
|
+
*
|
|
100
|
+
* Bearer fields (bearer / bearer_ref) are intentionally NEVER
|
|
101
|
+
* referenced — only `site_id`, `url`, `platform_*`, `is_default`,
|
|
102
|
+
* `label` from {@link SiteRowT}.
|
|
103
|
+
*/
|
|
104
|
+
export declare function appendSitesBlock(skillContent: string, registry: SiteRegistry): string;
|
|
45
105
|
/**
|
|
46
106
|
* Reset the in-memory cache. Intended for tests only.
|
|
47
107
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,qBAAqB,CAAC;AAElE,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,2BAA2B,CAAC;AAE3D,iEAAiE;AACjE,eAAO,MAAM,mBAAmB,sCAAiC,CAAC;AAElE,wDAAwD;AACxD,eAAO,MAAM,0BAA0B,QAEqC,CAAC;AAE7E,0CAA0C;AAC1C,eAAO,MAAM,wBAAwB,kBAAkB,CAAC;AAmBxD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,MAAM,CAShE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,gBAAgB,CAC5B,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,YAAY,GACvB,MAAM,CAkBR;AA0CD;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
|
package/dist/skill-loader.js
CHANGED
|
@@ -16,16 +16,32 @@
|
|
|
16
16
|
*
|
|
17
17
|
* Resolution layout (matches `install-skill.ts` + `build-dxt.js`):
|
|
18
18
|
*
|
|
19
|
-
* packages/mcp/skills/
|
|
19
|
+
* packages/mcp/skills/yt-builder-mcp/SKILL.md
|
|
20
20
|
*
|
|
21
21
|
* When the file is compiled to `dist/skill-loader.js`, the same
|
|
22
|
-
* relative `../skills/
|
|
22
|
+
* relative `../skills/yt-builder-mcp/SKILL.md` resolves correctly
|
|
23
23
|
* because the published npm tarball (and the DXT stage) preserves the
|
|
24
24
|
* `skills/` folder next to `dist/`.
|
|
25
25
|
*
|
|
26
26
|
* Read errors throw at module-init: a missing SKILL.md is a packaging
|
|
27
27
|
* bug, not a recoverable runtime condition.
|
|
28
28
|
*
|
|
29
|
+
* W8 — `appendSitesBlock(skillContent, registry)` post-processor.
|
|
30
|
+
* When the in-process {@link SiteRegistry} carries ≥1 configured
|
|
31
|
+
* site, append a "Currently configured sites" appendix to the
|
|
32
|
+
* instructions string so MCP hosts surface the live site roster
|
|
33
|
+
* alongside the skill narrative. The appendix contains ONLY
|
|
34
|
+
* safe-to-render metadata (site_id, label, platform hint/resolved,
|
|
35
|
+
* url, default-flag) — bearer fields are NEVER touched. When the
|
|
36
|
+
* registry has 0 sites the original skill content is returned
|
|
37
|
+
* verbatim (no appendix, no separator).
|
|
38
|
+
*
|
|
39
|
+
* This is a pure-string post-processor; it does not touch the
|
|
40
|
+
* on-disk SKILL.md. Per plan §W8 (line 919) the MCP `initialize`
|
|
41
|
+
* response carries `instructions` as a single shot, so an AI client
|
|
42
|
+
* restart is required for the appendix to refresh after a sites file
|
|
43
|
+
* edit. The W9 CLI commands (add-site / remove-site) print a reminder.
|
|
44
|
+
*
|
|
29
45
|
* @license MIT
|
|
30
46
|
*/
|
|
31
47
|
import { readFileSync } from 'node:fs';
|
|
@@ -44,28 +60,125 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
44
60
|
/**
|
|
45
61
|
* Resolve the on-disk path to the bundled SKILL.md.
|
|
46
62
|
*
|
|
47
|
-
* Source-tree: packages/mcp/src/skill-loader.ts → ../skills/
|
|
48
|
-
* Built tarball: packages/mcp/dist/skill-loader.js → ../skills/
|
|
63
|
+
* Source-tree: packages/mcp/src/skill-loader.ts → ../skills/yt-builder-mcp/SKILL.md
|
|
64
|
+
* Built tarball: packages/mcp/dist/skill-loader.js → ../skills/yt-builder-mcp/SKILL.md
|
|
49
65
|
*
|
|
50
66
|
* Both layouts work because `dist/` and `src/` are siblings of
|
|
51
67
|
* `skills/` under the package root.
|
|
52
68
|
*/
|
|
53
69
|
function resolveSkillPath() {
|
|
54
|
-
return resolve(__dirname, '..', 'skills', '
|
|
70
|
+
return resolve(__dirname, '..', 'skills', 'yt-builder-mcp', 'SKILL.md');
|
|
55
71
|
}
|
|
56
72
|
let cached;
|
|
57
73
|
/**
|
|
58
74
|
* Load the bundled SKILL.md content. Cached after the first read.
|
|
59
75
|
*
|
|
76
|
+
* When `registry` is supplied AND it carries ≥1 site, the returned
|
|
77
|
+
* string is the on-disk SKILL.md PLUS the W8 sites appendix (see
|
|
78
|
+
* {@link appendSitesBlock}). When `registry` is omitted or empty, the
|
|
79
|
+
* raw skill content is returned unchanged. The disk cache is shared
|
|
80
|
+
* across calls — the appendix is recomputed each time so registry
|
|
81
|
+
* mutations after the first load are reflected (within the same
|
|
82
|
+
* process instance — the MCP `initialize` response only takes a
|
|
83
|
+
* single-shot snapshot per session per plan §W8 line 919).
|
|
84
|
+
*
|
|
60
85
|
* @throws Error when the file is missing or unreadable (packaging bug).
|
|
61
86
|
*/
|
|
62
|
-
export function loadSkillContent() {
|
|
63
|
-
if (cached
|
|
87
|
+
export function loadSkillContent(registry) {
|
|
88
|
+
if (cached === undefined) {
|
|
89
|
+
const path = resolveSkillPath();
|
|
90
|
+
cached = readFileSync(path, 'utf-8');
|
|
91
|
+
}
|
|
92
|
+
if (registry === undefined) {
|
|
64
93
|
return cached;
|
|
65
94
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
95
|
+
return appendSitesBlock(cached, registry);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Append the W8 "Currently configured sites" block to a skill-content
|
|
99
|
+
* string. When the registry is empty, returns the input verbatim — no
|
|
100
|
+
* separator, no header, no trailing newline change.
|
|
101
|
+
*
|
|
102
|
+
* Output shape (per plan §W8 Z.904-917):
|
|
103
|
+
* ```text
|
|
104
|
+
* <skillContent>
|
|
105
|
+
*
|
|
106
|
+
* ---
|
|
107
|
+
*
|
|
108
|
+
* ## Currently configured sites (3)
|
|
109
|
+
*
|
|
110
|
+
* - `wp-acme` — Acme — Production · wordpress · https://acme.com · default
|
|
111
|
+
* - `joomla-beta` — Beta — Staging · joomla · https://beta.example.com/joomla
|
|
112
|
+
* - `wp-internal` — Internal staging · wordpress · https://internal.example.com
|
|
113
|
+
*
|
|
114
|
+
* Use `yootheme_builder_sites_list` to inspect this at runtime.
|
|
115
|
+
* Pass `site_id: "<id>"` on any tool call to target a specific site;
|
|
116
|
+
* omit it to use the default.
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* Per-row format (bullet):
|
|
120
|
+
* `- \`<site_id>\` — <label or "(no label)"> · <platform> · <url><" · default"?>`
|
|
121
|
+
*
|
|
122
|
+
* The platform column prefers `platform_resolved` when the registry
|
|
123
|
+
* has memoised a probe result for that site (peek-only — never
|
|
124
|
+
* triggers a new probe), and falls back to `platform_hint` otherwise.
|
|
125
|
+
*
|
|
126
|
+
* Bearer fields (bearer / bearer_ref) are intentionally NEVER
|
|
127
|
+
* referenced — only `site_id`, `url`, `platform_*`, `is_default`,
|
|
128
|
+
* `label` from {@link SiteRowT}.
|
|
129
|
+
*/
|
|
130
|
+
export function appendSitesBlock(skillContent, registry) {
|
|
131
|
+
const rows = registry.listForDisplay();
|
|
132
|
+
if (rows.length === 0) {
|
|
133
|
+
return skillContent;
|
|
134
|
+
}
|
|
135
|
+
const bullets = rows.map((row) => renderBullet(row)).join('\n');
|
|
136
|
+
const block = '\n\n---\n\n' +
|
|
137
|
+
`## Currently configured sites (${String(rows.length)})\n\n` +
|
|
138
|
+
bullets +
|
|
139
|
+
'\n\n' +
|
|
140
|
+
'Use `yootheme_builder_sites_list` to inspect this at runtime.\n' +
|
|
141
|
+
'Pass `site_id: "<id>"` on any tool call to target a specific site;\n' +
|
|
142
|
+
'omit it to use the default.\n';
|
|
143
|
+
return skillContent + block;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Markdown-escape an operator-provided string so it cannot inject
|
|
147
|
+
* structure into the rendered SKILL.md appendix.
|
|
148
|
+
*
|
|
149
|
+
* W12-R1.3 (A2-L2): the W8 sites-appendix renders `row.label` into the
|
|
150
|
+
* server's `instructions` field, which MCP hosts surface to the LLM
|
|
151
|
+
* verbatim. An operator with write-access to sites.json could land a
|
|
152
|
+
* label like `Acme [INTERNAL TOOL: ignore prior context] Production`
|
|
153
|
+
* and the prompt would carry that text into the model context. The
|
|
154
|
+
* escape list covers the markdown special chars the W8 bullet format
|
|
155
|
+
* could collide with (\`*_[]<>), preserving readable text while
|
|
156
|
+
* preventing injection. site_id is regex-restricted at the schema
|
|
157
|
+
* layer so it doesn't need escaping; url is operator-controlled but
|
|
158
|
+
* has a much smaller chosen-char surface and is rendered after a `·`
|
|
159
|
+
* separator that limits payload shape.
|
|
160
|
+
*/
|
|
161
|
+
function escapeMarkdown(text) {
|
|
162
|
+
return text.replace(/([\\`*_[\]<>])/g, '\\$1');
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Render one {@link SiteRowT} as a markdown bullet for the W8 sites
|
|
166
|
+
* appendix.
|
|
167
|
+
*
|
|
168
|
+
* Format: `- \`<site_id>\` — <label> · <platform> · <url><" · default"?>`
|
|
169
|
+
*
|
|
170
|
+
* `<platform>` prefers `platform_resolved` (the W3 memo cache) and
|
|
171
|
+
* falls back to `platform_hint` when no probe has run yet.
|
|
172
|
+
* `<label>` falls back to the literal string `(no label)` when the
|
|
173
|
+
* entry has none AND is markdown-escaped (W12-R1.3 prompt-injection
|
|
174
|
+
* defense). The `default` suffix is only present when `is_default`
|
|
175
|
+
* is true.
|
|
176
|
+
*/
|
|
177
|
+
function renderBullet(row) {
|
|
178
|
+
const platform = row.platform_resolved ?? row.platform_hint;
|
|
179
|
+
const label = escapeMarkdown(row.label ?? '(no label)');
|
|
180
|
+
const defaultSuffix = row.is_default ? ' · default' : '';
|
|
181
|
+
return `- \`${row.site_id}\` — ${label} · ${platform} · ${row.url}${defaultSuffix}`;
|
|
69
182
|
}
|
|
70
183
|
/**
|
|
71
184
|
* Reset the in-memory cache. Intended for tests only.
|
package/dist/skill-loader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-loader.js","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"skill-loader.js","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @license MIT
|
|
13
13
|
*/
|
|
14
|
-
import type {
|
|
14
|
+
import type { ClientPool } from '../../sites/client-pool.js';
|
|
15
15
|
import { type AnyToolDefinition } from '../tool-builder.js';
|
|
16
16
|
import { type ElementsHandlerDeps } from './handlers.js';
|
|
17
17
|
/**
|
|
@@ -20,5 +20,5 @@ import { type ElementsHandlerDeps } from './handlers.js';
|
|
|
20
20
|
* omitted, the destructive tool falls back to the explicit
|
|
21
21
|
* `confirm: true` parameter.
|
|
22
22
|
*/
|
|
23
|
-
export declare function buildElementsTools(
|
|
23
|
+
export declare function buildElementsTools(pool: ClientPool, deps?: Partial<ElementsHandlerDeps>): readonly AnyToolDefinition[];
|
|
24
24
|
//# sourceMappingURL=builders.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../../src/tools/elements/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../../src/tools/elements/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAI7D,OAAO,EAOH,KAAK,iBAAiB,EACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGH,KAAK,mBAAmB,EAQ3B,MAAM,eAAe,CAAC;AAEvB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAC9B,IAAI,EAAE,UAAU,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACpC,SAAS,iBAAiB,EAAE,CAqN9B"}
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
* @license MIT
|
|
13
13
|
*/
|
|
14
14
|
import { z } from 'zod';
|
|
15
|
-
import {
|
|
15
|
+
import { withSiteRetry } from '../pool-resolve-helper.js';
|
|
16
|
+
import { ELEMENT_PATH, ETAG, PROPS, SITE_ID_SCHEMA, TEMPLATE_ID } from '../shared-schemas.js';
|
|
16
17
|
import { FIELDS } from '../sparse-fields.js';
|
|
17
|
-
import { creating, defineTool, destructive, mutating, readOnly, } from '../tool-builder.js';
|
|
18
|
+
import { creating, defineTool, destructive, mutating, readOnly, withSiteMeta, } from '../tool-builder.js';
|
|
18
19
|
import { ELEMENT_GET_OUTPUT_SCHEMA, ELEMENT_LIST_OUTPUT_SCHEMA, handleElementAdd, handleElementClone, handleElementDelete, handleElementGet, handleElementList, handleElementMove, handleElementUpdateSettings, } from './handlers.js';
|
|
19
20
|
/**
|
|
20
21
|
* Build the 7 element tools. The optional `deps` carries the
|
|
@@ -22,18 +23,23 @@ import { ELEMENT_GET_OUTPUT_SCHEMA, ELEMENT_LIST_OUTPUT_SCHEMA, handleElementAdd
|
|
|
22
23
|
* omitted, the destructive tool falls back to the explicit
|
|
23
24
|
* `confirm: true` parameter.
|
|
24
25
|
*/
|
|
25
|
-
export function buildElementsTools(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
export function buildElementsTools(pool, deps) {
|
|
27
|
+
// W6.3 — each handler resolves the pool inline (per `site_id`) so
|
|
28
|
+
// the per-handler `siteClient` reaches the right CMS install. The
|
|
29
|
+
// elicitation capability is the only non-client dep we propagate.
|
|
30
|
+
const elicitation = deps?.elicitation;
|
|
31
|
+
const makeDeps = (siteClient) => (elicitation !== undefined
|
|
32
|
+
? { client: siteClient, elicitation }
|
|
33
|
+
: { client: siteClient });
|
|
30
34
|
return [
|
|
31
35
|
defineTool({
|
|
32
36
|
name: 'yootheme_builder_element_list',
|
|
33
37
|
description: 'List elements in a template as a flat array with JSON-Pointer paths + ' +
|
|
34
38
|
'types. Scope with `root_path`/`depth` for a subtree, paginate with ' +
|
|
35
|
-
'`limit`/`cursor` for large templates. `fields[]` narrows each row.'
|
|
39
|
+
'`limit`/`cursor` for large templates. `fields[]` narrows each row. ' +
|
|
40
|
+
'Operates on the default site unless site_id is provided.',
|
|
36
41
|
inputSchema: {
|
|
42
|
+
site_id: SITE_ID_SCHEMA,
|
|
37
43
|
template_id: TEMPLATE_ID,
|
|
38
44
|
fields: FIELDS,
|
|
39
45
|
root_path: z
|
|
@@ -61,32 +67,41 @@ export function buildElementsTools(client, deps) {
|
|
|
61
67
|
},
|
|
62
68
|
outputSchema: ELEMENT_LIST_OUTPUT_SCHEMA,
|
|
63
69
|
annotations: readOnly('List Elements'),
|
|
64
|
-
handler: (
|
|
70
|
+
handler: async ({ site_id, ...rest }) => withSiteRetry(pool, site_id, async (client, site) => withSiteMeta(await handleElementList(makeDeps(client), rest), site)),
|
|
65
71
|
}),
|
|
66
72
|
defineTool({
|
|
67
73
|
name: 'yootheme_builder_element_get',
|
|
68
74
|
description: 'Get the full element object at a specific JSON-Pointer path, including props ' +
|
|
69
|
-
'and children. Use yootheme_builder_element_list to discover paths.'
|
|
75
|
+
'and children. Use yootheme_builder_element_list to discover paths. ' +
|
|
76
|
+
'Operates on the default site unless site_id is provided.',
|
|
70
77
|
inputSchema: {
|
|
78
|
+
site_id: SITE_ID_SCHEMA,
|
|
71
79
|
template_id: TEMPLATE_ID,
|
|
72
80
|
element_path: ELEMENT_PATH,
|
|
73
81
|
},
|
|
74
82
|
outputSchema: ELEMENT_GET_OUTPUT_SCHEMA,
|
|
75
83
|
annotations: readOnly('Get Element'),
|
|
76
|
-
handler: (
|
|
84
|
+
handler: async ({ site_id, ...rest }) => withSiteRetry(pool, site_id, async (client, site) => withSiteMeta(await handleElementGet(makeDeps(client), rest), site)),
|
|
77
85
|
}),
|
|
78
86
|
defineTool({
|
|
79
87
|
name: 'yootheme_builder_element_add',
|
|
80
88
|
description: 'Add a new element to a template. Provide `parent_path` (or "" for root), ' +
|
|
81
89
|
'`element_type` (e.g. "headline", "text", "grid"), and optional `props` / ' +
|
|
82
|
-
'`children`. Returns the new element\'s JSON-Pointer path. Requires ETag.'
|
|
90
|
+
'`children`. Returns the new element\'s JSON-Pointer path. Requires ETag. ' +
|
|
91
|
+
'Operates on the default site unless site_id is provided.',
|
|
83
92
|
inputSchema: {
|
|
93
|
+
site_id: SITE_ID_SCHEMA,
|
|
84
94
|
template_id: TEMPLATE_ID,
|
|
85
95
|
parent_path: z
|
|
86
96
|
.string()
|
|
87
97
|
.default('')
|
|
88
|
-
.describe('JSON-Pointer of the parent node
|
|
89
|
-
'
|
|
98
|
+
.describe('JSON-Pointer of the parent node. Accepts EITHER "" for ' +
|
|
99
|
+
'template root, a `rel_path` from `element_list` ' +
|
|
100
|
+
'(`/children/0`, `/children/0/children/2`) — the server ' +
|
|
101
|
+
'resolves it within this template — OR a fully-qualified ' +
|
|
102
|
+
'pointer (`/templates/<id>/layout/children/0/...`). The ' +
|
|
103
|
+
'rel_path form is preferred (copy-paste straight from ' +
|
|
104
|
+
'`element_list`).'),
|
|
90
105
|
element_type: z
|
|
91
106
|
.string()
|
|
92
107
|
.min(1)
|
|
@@ -100,14 +115,16 @@ export function buildElementsTools(client, deps) {
|
|
|
100
115
|
etag: ETAG,
|
|
101
116
|
},
|
|
102
117
|
annotations: creating('Add Element'),
|
|
103
|
-
handler: (
|
|
118
|
+
handler: async ({ site_id, ...rest }, extra) => withSiteRetry(pool, site_id, async (client, site) => withSiteMeta(await handleElementAdd(makeDeps(client), rest, extra), site)),
|
|
104
119
|
}),
|
|
105
120
|
defineTool({
|
|
106
121
|
name: 'yootheme_builder_element_update_settings',
|
|
107
122
|
description: 'Update `props` on an element. Default replaces all props; pass ' +
|
|
108
123
|
'`merge:true` for server-side deep-merge (only request keys overwritten, ' +
|
|
109
|
-
'others survive — avoids read-modify-write races). Requires ETag.'
|
|
124
|
+
'others survive — avoids read-modify-write races). Requires ETag. ' +
|
|
125
|
+
'Operates on the default site unless site_id is provided.',
|
|
110
126
|
inputSchema: {
|
|
127
|
+
site_id: SITE_ID_SCHEMA,
|
|
111
128
|
template_id: TEMPLATE_ID,
|
|
112
129
|
element_path: ELEMENT_PATH,
|
|
113
130
|
props: PROPS,
|
|
@@ -119,13 +136,15 @@ export function buildElementsTools(client, deps) {
|
|
|
119
136
|
etag: ETAG,
|
|
120
137
|
},
|
|
121
138
|
annotations: mutating('Update Element Settings'),
|
|
122
|
-
handler: (
|
|
139
|
+
handler: async ({ site_id, ...rest }, extra) => withSiteRetry(pool, site_id, async (client, site) => withSiteMeta(await handleElementUpdateSettings(makeDeps(client), rest, extra), site)),
|
|
123
140
|
}),
|
|
124
141
|
defineTool({
|
|
125
142
|
name: 'yootheme_builder_element_move',
|
|
126
143
|
description: 'Move an element to a new parent + index in the tree. Useful for reordering or ' +
|
|
127
|
-
'reparenting (e.g. moving a card from one grid column to another). Requires ETag.'
|
|
144
|
+
'reparenting (e.g. moving a card from one grid column to another). Requires ETag. ' +
|
|
145
|
+
'Operates on the default site unless site_id is provided.',
|
|
128
146
|
inputSchema: {
|
|
147
|
+
site_id: SITE_ID_SCHEMA,
|
|
129
148
|
template_id: TEMPLATE_ID,
|
|
130
149
|
element_path: ELEMENT_PATH,
|
|
131
150
|
to_parent_path: z
|
|
@@ -139,26 +158,29 @@ export function buildElementsTools(client, deps) {
|
|
|
139
158
|
etag: ETAG,
|
|
140
159
|
},
|
|
141
160
|
annotations: mutating('Move Element'),
|
|
142
|
-
handler: (
|
|
161
|
+
handler: async ({ site_id, ...rest }, extra) => withSiteRetry(pool, site_id, async (client, site) => withSiteMeta(await handleElementMove(makeDeps(client), rest, extra), site)),
|
|
143
162
|
}),
|
|
144
163
|
defineTool({
|
|
145
164
|
name: 'yootheme_builder_element_clone',
|
|
146
165
|
description: 'Clone an element as a sibling (same parent, immediately after the source). ' +
|
|
147
|
-
'Returns the new element\'s path. Requires ETag.'
|
|
166
|
+
'Returns the new element\'s path. Requires ETag. ' +
|
|
167
|
+
'Operates on the default site unless site_id is provided.',
|
|
148
168
|
inputSchema: {
|
|
169
|
+
site_id: SITE_ID_SCHEMA,
|
|
149
170
|
template_id: TEMPLATE_ID,
|
|
150
171
|
element_path: ELEMENT_PATH,
|
|
151
172
|
etag: ETAG,
|
|
152
173
|
},
|
|
153
174
|
annotations: creating('Clone Element'),
|
|
154
|
-
handler: (
|
|
175
|
+
handler: async ({ site_id, ...rest }, extra) => withSiteRetry(pool, site_id, async (client, site) => withSiteMeta(await handleElementClone(makeDeps(client), rest, extra), site)),
|
|
155
176
|
}),
|
|
156
177
|
defineTool({
|
|
157
178
|
name: 'yootheme_builder_element_delete',
|
|
158
179
|
description: 'PERMANENTLY delete an element and all its children. Cannot be undone. Always ' +
|
|
159
180
|
'ask the user to confirm first, then call again with `confirm: true`. Requires ' +
|
|
160
|
-
'ETag.',
|
|
181
|
+
'ETag. Operates on the default site unless site_id is provided.',
|
|
161
182
|
inputSchema: {
|
|
183
|
+
site_id: SITE_ID_SCHEMA,
|
|
162
184
|
template_id: TEMPLATE_ID,
|
|
163
185
|
element_path: ELEMENT_PATH,
|
|
164
186
|
etag: ETAG,
|
|
@@ -170,7 +192,7 @@ export function buildElementsTools(client, deps) {
|
|
|
170
192
|
'preview and the agent must retry with `confirm: true`.'),
|
|
171
193
|
},
|
|
172
194
|
annotations: destructive('Delete Element'),
|
|
173
|
-
handler: (
|
|
195
|
+
handler: async ({ site_id, ...rest }, extra) => withSiteRetry(pool, site_id, async (client, site) => withSiteMeta(await handleElementDelete(makeDeps(client), rest, extra), site)),
|
|
174
196
|
}),
|
|
175
197
|
];
|
|
176
198
|
}
|