@loomweaver/mcp 0.9.2 → 0.9.4
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 +1 -1
- package/dist/main.mjs +147 -125
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ is not inside this repo (a chat assistant, a remote client) can scaffold and val
|
|
|
10
10
|
- `scaffold_weaver` · `scaffold_frame_plugin` · `scaffold_distribution` · `scaffold_auth_source` ·
|
|
11
11
|
`scaffold_settings_store` · `scaffold_theme` · `scaffold_layout` — return a **file map**
|
|
12
12
|
(`path -> content`); the client writes the files into its project.
|
|
13
|
-
- `validate_manifest` · `validate_i18n` · `validate_catalog` — return structured `Finding[]`.
|
|
13
|
+
- `validate_manifest` · `validate_i18n` · `validate_catalog` · `validate_commands` — return structured `Finding[]`.
|
|
14
14
|
|
|
15
15
|
## Consume from npm (product repos)
|
|
16
16
|
|
package/dist/main.mjs
CHANGED
|
@@ -31025,6 +31025,10 @@ function normalizeProjectRoot(value) {
|
|
|
31025
31025
|
}
|
|
31026
31026
|
return rooted.slice(0, end);
|
|
31027
31027
|
}
|
|
31028
|
+
function joinProjectPath(projectRoot, path) {
|
|
31029
|
+
const root = normalizeProjectRoot(projectRoot);
|
|
31030
|
+
return root ? `${root}/${path}` : path;
|
|
31031
|
+
}
|
|
31028
31032
|
|
|
31029
31033
|
// ../devkit/src/lib/amend/describe.ts
|
|
31030
31034
|
function describeAmendment(amendment) {
|
|
@@ -31038,15 +31042,19 @@ function describeAmendment(amendment) {
|
|
|
31038
31042
|
return `Add an @source entry for '${amendment.sourceRoot}' to the application's entry stylesheet, resolved from that stylesheet. Without it none of that code's utilities are emitted.`;
|
|
31039
31043
|
}
|
|
31040
31044
|
if (amendment.kind === "compose-plugin") {
|
|
31041
|
-
const providers = (amendment.providers ?? []).map((provider) => provider.line.replace(/,$/, ""));
|
|
31042
|
-
|
|
31043
|
-
|
|
31044
|
-
|
|
31045
|
+
const providers = (amendment.providers ?? []).map((provider) => `${provider.line.replace(/,$/, "")}, `).join("");
|
|
31046
|
+
const capabilities = amendment.capabilities.map((capability) => `'${capability}'`).join(", ");
|
|
31047
|
+
const imports = (amendment.providers ?? []).flatMap((provider) => provider.from ?? []).map(
|
|
31048
|
+
(imported) => ` import { ${imported.symbols.join(", ")} } from '${imported.path}'.`
|
|
31049
|
+
).join("");
|
|
31050
|
+
return `Register ${amendment.id} in the composition root: import { ${amendment.symbol} }, ${providers}provideTranslationNamespaces('${amendment.id}'), provideCapabilityGrants({ ${amendment.id}: [${capabilities}] }) and ...providePlugins(${amendment.symbol}).${imports} Without it none of its contributions appear.`;
|
|
31045
31051
|
}
|
|
31046
31052
|
return [
|
|
31047
31053
|
...amendment.styles.length > 0 ? [`name ${amendment.styles.join(", ")} in styles`] : [],
|
|
31048
31054
|
...amendment.assets.length > 0 ? [
|
|
31049
|
-
`add assets for ${amendment.assets.map(
|
|
31055
|
+
`add assets for ${amendment.assets.map(
|
|
31056
|
+
(asset) => asset.output ? `${asset.input} served under ${asset.output}` : asset.input
|
|
31057
|
+
).join(
|
|
31050
31058
|
", "
|
|
31051
31059
|
)} (the shell fetches its own strings at runtime, so without that glob every label in the chrome renders as its raw translation key)`
|
|
31052
31060
|
] : [],
|
|
@@ -31450,7 +31458,7 @@ function pause(): Promise<void> {
|
|
|
31450
31458
|
}
|
|
31451
31459
|
|
|
31452
31460
|
// ../devkit/src/recipes/angular-weaver/agent-files.ts
|
|
31453
|
-
var AG_UI_ADAPTER_VERSION = "0.9.
|
|
31461
|
+
var AG_UI_ADAPTER_VERSION = "0.9.4";
|
|
31454
31462
|
var AG_UI_PROTOCOL_VERSION = "0.0.x";
|
|
31455
31463
|
function connectionFile(w) {
|
|
31456
31464
|
return `import { signal } from '@angular/core';
|
|
@@ -31817,109 +31825,8 @@ function toneHelper() {
|
|
|
31817
31825
|
].join("\n");
|
|
31818
31826
|
}
|
|
31819
31827
|
|
|
31820
|
-
// ../devkit/src/recipes/angular-weaver/
|
|
31821
|
-
var DEFAULT_MENU_SLOT = "content/tab/context";
|
|
31828
|
+
// ../devkit/src/recipes/angular-weaver/weaver-plugin.ts
|
|
31822
31829
|
var SURFACE_ICON = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><rect x="4" y="4" width="16" height="16" rx="3"/><path d="M8 9h8M8 13h8M8 17h5"/></svg>';
|
|
31823
|
-
function accessLiteral(spec) {
|
|
31824
|
-
if (spec === "authenticated") return "{ authenticated: true }";
|
|
31825
|
-
if (spec === "anonymous") return "{ authenticated: false }";
|
|
31826
|
-
if (spec.startsWith("role:")) {
|
|
31827
|
-
const role = spec.slice("role:".length);
|
|
31828
|
-
if (!role)
|
|
31829
|
-
throw new Error('Access "role:" needs a role name, e.g. "role:admin".');
|
|
31830
|
-
if (/['\\]/.test(role))
|
|
31831
|
-
throw new Error(
|
|
31832
|
-
`Access role "${role}" must not contain quotes or backslashes.`
|
|
31833
|
-
);
|
|
31834
|
-
return `{ anyRole: ['${role}'] }`;
|
|
31835
|
-
}
|
|
31836
|
-
throw new Error(
|
|
31837
|
-
`Unknown access "${spec}". Use "authenticated", "anonymous" or "role:<name>".`
|
|
31838
|
-
);
|
|
31839
|
-
}
|
|
31840
|
-
function resolveMenuSlot(menu) {
|
|
31841
|
-
if (menu === true) {
|
|
31842
|
-
return DEFAULT_MENU_SLOT;
|
|
31843
|
-
}
|
|
31844
|
-
return typeof menu === "string" && menu.length ? menu : void 0;
|
|
31845
|
-
}
|
|
31846
|
-
var PLATFORM_BOUND_CHORD_TOKENS = /* @__PURE__ */ new Set([
|
|
31847
|
-
"cmd",
|
|
31848
|
-
"command",
|
|
31849
|
-
"ctrl",
|
|
31850
|
-
"control",
|
|
31851
|
-
"meta"
|
|
31852
|
-
]);
|
|
31853
|
-
function assertPlatformNeutralChord(shortcut) {
|
|
31854
|
-
const tokens = shortcut.toLowerCase().split("+").map((token) => token.trim());
|
|
31855
|
-
const bound = tokens.find((token) => PLATFORM_BOUND_CHORD_TOKENS.has(token));
|
|
31856
|
-
if (bound) {
|
|
31857
|
-
throw new Error(
|
|
31858
|
-
`Shortcut "${shortcut}" binds the platform-specific "${bound}" key. Use the neutral 'mod' token (e.g. 'mod+shift+k') \u2014 the host renders it as \u2318 on macOS and Ctrl elsewhere.`
|
|
31859
|
-
);
|
|
31860
|
-
}
|
|
31861
|
-
}
|
|
31862
|
-
function resolveFeatures(id, input) {
|
|
31863
|
-
const menuSlot = resolveMenuSlot(input?.menu);
|
|
31864
|
-
const barItem = Boolean(input?.barItem);
|
|
31865
|
-
const hasShortcut = Boolean(input?.shortcut?.trim());
|
|
31866
|
-
if (hasShortcut) {
|
|
31867
|
-
assertPlatformNeutralChord(input?.shortcut?.trim() ?? "");
|
|
31868
|
-
}
|
|
31869
|
-
const instanceable = Boolean(input?.instanceable);
|
|
31870
|
-
const container = Boolean(input?.container);
|
|
31871
|
-
if (instanceable && container) {
|
|
31872
|
-
throw new Error(
|
|
31873
|
-
'A surface cannot be both a container and instanceable: a container tab holds its own ":id" and is therefore routable, while named instances exist only for a docked, non-routable surface. Pick one.'
|
|
31874
|
-
);
|
|
31875
|
-
}
|
|
31876
|
-
const agent = Boolean(input?.agent);
|
|
31877
|
-
return {
|
|
31878
|
-
command: Boolean(input?.command) || menuSlot !== void 0 || barItem || hasShortcut || agent,
|
|
31879
|
-
menuSlot,
|
|
31880
|
-
settings: Boolean(input?.settings),
|
|
31881
|
-
access: input?.access ? accessLiteral(input.access) : void 0,
|
|
31882
|
-
shortcut: input?.shortcut?.trim() || `mod+shift+${id.charAt(0)}`,
|
|
31883
|
-
barItem,
|
|
31884
|
-
about: Boolean(input?.about),
|
|
31885
|
-
instanceable,
|
|
31886
|
-
container,
|
|
31887
|
-
agent,
|
|
31888
|
-
spec: input?.spec !== false
|
|
31889
|
-
};
|
|
31890
|
-
}
|
|
31891
|
-
function deriveCapabilities(features) {
|
|
31892
|
-
const set2 = /* @__PURE__ */ new Set(["contributions", "navigation"]);
|
|
31893
|
-
if (features.command) set2.add("ui");
|
|
31894
|
-
if (features.about) {
|
|
31895
|
-
set2.add("ui");
|
|
31896
|
-
set2.add("host");
|
|
31897
|
-
}
|
|
31898
|
-
if (features.agent) {
|
|
31899
|
-
set2.add("ui");
|
|
31900
|
-
set2.add("automation");
|
|
31901
|
-
}
|
|
31902
|
-
return KNOWN_CAPABILITIES.filter((capability) => set2.has(capability));
|
|
31903
|
-
}
|
|
31904
|
-
function resolveWeaverInput(input) {
|
|
31905
|
-
if (!isKebabId(input.id)) {
|
|
31906
|
-
throw new Error(
|
|
31907
|
-
`Weaver id must be kebab-case (e.g. "notes"); got "${input.id}".`
|
|
31908
|
-
);
|
|
31909
|
-
}
|
|
31910
|
-
const features = resolveFeatures(input.id, input.features);
|
|
31911
|
-
const capabilities = input.capabilities?.length ? [...input.capabilities] : deriveCapabilities(features);
|
|
31912
|
-
return {
|
|
31913
|
-
id: input.id,
|
|
31914
|
-
name: input.name?.trim() || toTitleCase(input.id),
|
|
31915
|
-
className: toPascalCase(input.id),
|
|
31916
|
-
propertyName: toCamelCase(input.id),
|
|
31917
|
-
capabilities,
|
|
31918
|
-
features,
|
|
31919
|
-
prefix: input.prefix?.trim() || "lw",
|
|
31920
|
-
importPath: input.importPath?.trim() || `@loomweaver/${input.id}-weaver`
|
|
31921
|
-
};
|
|
31922
|
-
}
|
|
31923
31830
|
function containerChildIds(w) {
|
|
31924
31831
|
return [`${w.id}.canvas`, `${w.id}.details`];
|
|
31925
31832
|
}
|
|
@@ -32056,7 +31963,7 @@ function settingsBlock(w) {
|
|
|
32056
31963
|
" });"
|
|
32057
31964
|
].join("\n");
|
|
32058
31965
|
}
|
|
32059
|
-
function
|
|
31966
|
+
function pluginImports(w) {
|
|
32060
31967
|
const imports = ["import { Plugin } from '@loomweaver/plugin-sdk';"];
|
|
32061
31968
|
if (w.features.container) {
|
|
32062
31969
|
imports.push(
|
|
@@ -32080,6 +31987,9 @@ function pluginFile(w) {
|
|
|
32080
31987
|
if (w.features.settings) {
|
|
32081
31988
|
imports.unshift("import { signal } from '@angular/core';");
|
|
32082
31989
|
}
|
|
31990
|
+
return imports;
|
|
31991
|
+
}
|
|
31992
|
+
function pluginConsts(w) {
|
|
32083
31993
|
const consts = [`const icon =
|
|
32084
31994
|
'${SURFACE_ICON}';`];
|
|
32085
31995
|
if (w.features.settings) {
|
|
@@ -32088,6 +31998,10 @@ function pluginFile(w) {
|
|
|
32088
31998
|
`const ${w.propertyName}Note = signal('');`
|
|
32089
31999
|
);
|
|
32090
32000
|
}
|
|
32001
|
+
if (w.features.command) consts.push(toneHelper());
|
|
32002
|
+
return consts;
|
|
32003
|
+
}
|
|
32004
|
+
function pluginBody(w) {
|
|
32091
32005
|
const body = [` ctx.contributeIcons({ '${w.id}': icon });`];
|
|
32092
32006
|
if (w.features.agent) {
|
|
32093
32007
|
body.push(
|
|
@@ -32102,14 +32016,17 @@ function pluginFile(w) {
|
|
|
32102
32016
|
if (w.features.menuSlot) body.push(menuBlock(w));
|
|
32103
32017
|
if (w.features.settings) body.push(settingsBlock(w));
|
|
32104
32018
|
if (w.features.agent) body.push(agentSurfaceBlock(w));
|
|
32019
|
+
return body;
|
|
32020
|
+
}
|
|
32021
|
+
function pluginFile(w) {
|
|
32022
|
+
const body = pluginBody(w);
|
|
32105
32023
|
const deactivate = w.features.agent ? `
|
|
32106
32024
|
deactivate() {
|
|
32107
32025
|
${w.propertyName}Agent.set(null);
|
|
32108
32026
|
},` : "";
|
|
32109
|
-
|
|
32110
|
-
return `${imports.join("\n")}
|
|
32027
|
+
return `${pluginImports(w).join("\n")}
|
|
32111
32028
|
|
|
32112
|
-
${
|
|
32029
|
+
${pluginConsts(w).join("\n\n")}
|
|
32113
32030
|
|
|
32114
32031
|
export const ${w.propertyName}Plugin: Plugin = {
|
|
32115
32032
|
manifest: {
|
|
@@ -32123,6 +32040,109 @@ ${body.join("\n")}
|
|
|
32123
32040
|
};
|
|
32124
32041
|
`;
|
|
32125
32042
|
}
|
|
32043
|
+
|
|
32044
|
+
// ../devkit/src/recipes/angular-weaver/recipe.ts
|
|
32045
|
+
var DEFAULT_MENU_SLOT = "content/tab/context";
|
|
32046
|
+
function accessLiteral(spec) {
|
|
32047
|
+
if (spec === "authenticated") return "{ authenticated: true }";
|
|
32048
|
+
if (spec === "anonymous") return "{ authenticated: false }";
|
|
32049
|
+
if (spec.startsWith("role:")) {
|
|
32050
|
+
const role = spec.slice("role:".length);
|
|
32051
|
+
if (!role)
|
|
32052
|
+
throw new Error('Access "role:" needs a role name, e.g. "role:admin".');
|
|
32053
|
+
if (/['\\]/.test(role))
|
|
32054
|
+
throw new Error(
|
|
32055
|
+
`Access role "${role}" must not contain quotes or backslashes.`
|
|
32056
|
+
);
|
|
32057
|
+
return `{ anyRole: ['${role}'] }`;
|
|
32058
|
+
}
|
|
32059
|
+
throw new Error(
|
|
32060
|
+
`Unknown access "${spec}". Use "authenticated", "anonymous" or "role:<name>".`
|
|
32061
|
+
);
|
|
32062
|
+
}
|
|
32063
|
+
function resolveMenuSlot(menu) {
|
|
32064
|
+
if (menu === true) {
|
|
32065
|
+
return DEFAULT_MENU_SLOT;
|
|
32066
|
+
}
|
|
32067
|
+
return typeof menu === "string" && menu.length ? menu : void 0;
|
|
32068
|
+
}
|
|
32069
|
+
var PLATFORM_BOUND_CHORD_TOKENS = /* @__PURE__ */ new Set([
|
|
32070
|
+
"cmd",
|
|
32071
|
+
"command",
|
|
32072
|
+
"ctrl",
|
|
32073
|
+
"control",
|
|
32074
|
+
"meta"
|
|
32075
|
+
]);
|
|
32076
|
+
function assertPlatformNeutralChord(shortcut) {
|
|
32077
|
+
const tokens = shortcut.toLowerCase().split("+").map((token) => token.trim());
|
|
32078
|
+
const bound = tokens.find((token) => PLATFORM_BOUND_CHORD_TOKENS.has(token));
|
|
32079
|
+
if (bound) {
|
|
32080
|
+
throw new Error(
|
|
32081
|
+
`Shortcut "${shortcut}" binds the platform-specific "${bound}" key. Use the neutral 'mod' token (e.g. 'mod+shift+k') \u2014 the host renders it as \u2318 on macOS and Ctrl elsewhere.`
|
|
32082
|
+
);
|
|
32083
|
+
}
|
|
32084
|
+
}
|
|
32085
|
+
function resolveFeatures(id, input) {
|
|
32086
|
+
const menuSlot = resolveMenuSlot(input?.menu);
|
|
32087
|
+
const barItem = Boolean(input?.barItem);
|
|
32088
|
+
const hasShortcut = Boolean(input?.shortcut?.trim());
|
|
32089
|
+
if (hasShortcut) {
|
|
32090
|
+
assertPlatformNeutralChord(input?.shortcut?.trim() ?? "");
|
|
32091
|
+
}
|
|
32092
|
+
const instanceable = Boolean(input?.instanceable);
|
|
32093
|
+
const container = Boolean(input?.container);
|
|
32094
|
+
if (instanceable && container) {
|
|
32095
|
+
throw new Error(
|
|
32096
|
+
'A surface cannot be both a container and instanceable: a container tab holds its own ":id" and is therefore routable, while named instances exist only for a docked, non-routable surface. Pick one.'
|
|
32097
|
+
);
|
|
32098
|
+
}
|
|
32099
|
+
const agent = Boolean(input?.agent);
|
|
32100
|
+
return {
|
|
32101
|
+
command: Boolean(input?.command) || menuSlot !== void 0 || barItem || hasShortcut || agent,
|
|
32102
|
+
menuSlot,
|
|
32103
|
+
settings: Boolean(input?.settings),
|
|
32104
|
+
access: input?.access ? accessLiteral(input.access) : void 0,
|
|
32105
|
+
shortcut: input?.shortcut?.trim() || `mod+shift+${id.charAt(0)}`,
|
|
32106
|
+
barItem,
|
|
32107
|
+
about: Boolean(input?.about),
|
|
32108
|
+
instanceable,
|
|
32109
|
+
container,
|
|
32110
|
+
agent,
|
|
32111
|
+
spec: input?.spec !== false
|
|
32112
|
+
};
|
|
32113
|
+
}
|
|
32114
|
+
function deriveCapabilities(features) {
|
|
32115
|
+
const set2 = /* @__PURE__ */ new Set(["contributions", "navigation"]);
|
|
32116
|
+
if (features.command) set2.add("ui");
|
|
32117
|
+
if (features.about) {
|
|
32118
|
+
set2.add("ui");
|
|
32119
|
+
set2.add("host");
|
|
32120
|
+
}
|
|
32121
|
+
if (features.agent) {
|
|
32122
|
+
set2.add("ui");
|
|
32123
|
+
set2.add("automation");
|
|
32124
|
+
}
|
|
32125
|
+
return KNOWN_CAPABILITIES.filter((capability) => set2.has(capability));
|
|
32126
|
+
}
|
|
32127
|
+
function resolveWeaverInput(input) {
|
|
32128
|
+
if (!isKebabId(input.id)) {
|
|
32129
|
+
throw new Error(
|
|
32130
|
+
`Weaver id must be kebab-case (e.g. "notes"); got "${input.id}".`
|
|
32131
|
+
);
|
|
32132
|
+
}
|
|
32133
|
+
const features = resolveFeatures(input.id, input.features);
|
|
32134
|
+
const capabilities = input.capabilities?.length ? [...input.capabilities] : deriveCapabilities(features);
|
|
32135
|
+
return {
|
|
32136
|
+
id: input.id,
|
|
32137
|
+
name: input.name?.trim() || toTitleCase(input.id),
|
|
32138
|
+
className: toPascalCase(input.id),
|
|
32139
|
+
propertyName: toCamelCase(input.id),
|
|
32140
|
+
capabilities,
|
|
32141
|
+
features,
|
|
32142
|
+
prefix: input.prefix?.trim() || "lw",
|
|
32143
|
+
importPath: input.importPath?.trim() || `@loomweaver/${input.id}-weaver`
|
|
32144
|
+
};
|
|
32145
|
+
}
|
|
32126
32146
|
function aboutDialogFile(w) {
|
|
32127
32147
|
return `import { Component, inject } from '@angular/core';
|
|
32128
32148
|
import { DialogRef, PluginHost } from '@loomweaver/plugin-sdk';
|
|
@@ -32433,7 +32453,7 @@ var framePlugin = {
|
|
|
32433
32453
|
};
|
|
32434
32454
|
|
|
32435
32455
|
// ../devkit/src/recipes/platform-version.ts
|
|
32436
|
-
var PLATFORM_VERSION = "0.9.
|
|
32456
|
+
var PLATFORM_VERSION = "0.9.4";
|
|
32437
32457
|
|
|
32438
32458
|
// ../devkit/src/recipes/angular-distribution/amendments.ts
|
|
32439
32459
|
var DISTRIBUTION_INITIAL_BUDGET = {
|
|
@@ -32725,7 +32745,7 @@ function resolveDistributionInput(input) {
|
|
|
32725
32745
|
);
|
|
32726
32746
|
}
|
|
32727
32747
|
const directory = input.directory === void 0 ? `apps/${input.name}` : input.directory.trim();
|
|
32728
|
-
const depth = directory.split("/").filter(Boolean).length;
|
|
32748
|
+
const depth = normalizeProjectRoot(directory).split("/").filter(Boolean).length;
|
|
32729
32749
|
return {
|
|
32730
32750
|
name: input.name,
|
|
32731
32751
|
title: input.title?.trim() || toTitleCase(input.name),
|
|
@@ -33368,6 +33388,7 @@ function bootstrapFile(t) {
|
|
|
33368
33388
|
--lw-content: var(--bs-body-color);
|
|
33369
33389
|
--lw-content-muted: var(--bs-secondary-color);
|
|
33370
33390
|
--lw-content-faint: var(--bs-secondary-color);
|
|
33391
|
+
--lw-unsaved: var(--bs-warning-text-emphasis);
|
|
33371
33392
|
|
|
33372
33393
|
--lw-tooltip: var(--bs-emphasis-color);
|
|
33373
33394
|
--lw-tooltip-content: var(--bs-body-bg);
|
|
@@ -33445,10 +33466,10 @@ function weaverAmendments(input, where) {
|
|
|
33445
33466
|
version: AG_UI_PROTOCOL_VERSION
|
|
33446
33467
|
}
|
|
33447
33468
|
] : [];
|
|
33448
|
-
|
|
33449
|
-
if (!directory) {
|
|
33469
|
+
if (where === void 0 || where === "") {
|
|
33450
33470
|
return packages;
|
|
33451
33471
|
}
|
|
33472
|
+
const directory = normalizeProjectRoot(where);
|
|
33452
33473
|
return [
|
|
33453
33474
|
...packages,
|
|
33454
33475
|
{
|
|
@@ -33457,19 +33478,19 @@ function weaverAmendments(input, where) {
|
|
|
33457
33478
|
assets: [
|
|
33458
33479
|
{
|
|
33459
33480
|
glob: "**/*.json",
|
|
33460
|
-
input:
|
|
33481
|
+
input: joinProjectPath(directory, "src/lib/i18n"),
|
|
33461
33482
|
from: "workspace",
|
|
33462
33483
|
output: `i18n/${w.id}`
|
|
33463
33484
|
}
|
|
33464
33485
|
]
|
|
33465
33486
|
},
|
|
33466
|
-
{ kind: "stylesheet-source", sourceRoot:
|
|
33487
|
+
{ kind: "stylesheet-source", sourceRoot: joinProjectPath(directory, "src") },
|
|
33467
33488
|
{
|
|
33468
33489
|
kind: "compose-plugin",
|
|
33469
33490
|
id: w.id,
|
|
33470
33491
|
symbol: `${w.propertyName}Plugin`,
|
|
33471
33492
|
capabilities: w.capabilities,
|
|
33472
|
-
sourceRoot:
|
|
33493
|
+
sourceRoot: joinProjectPath(directory, "src")
|
|
33473
33494
|
}
|
|
33474
33495
|
];
|
|
33475
33496
|
}
|
|
@@ -33477,10 +33498,10 @@ function weaverAmendments(input, where) {
|
|
|
33477
33498
|
// ../devkit/src/recipes/auth-source/recipe-amendments.ts
|
|
33478
33499
|
function authSourceAmendments(input, where) {
|
|
33479
33500
|
const a = resolveAuthSourceInput(input);
|
|
33480
|
-
|
|
33481
|
-
if (a.bare || !directory) {
|
|
33501
|
+
if (a.bare || where === void 0 || where === "") {
|
|
33482
33502
|
return [];
|
|
33483
33503
|
}
|
|
33504
|
+
const directory = normalizeProjectRoot(where);
|
|
33484
33505
|
return [
|
|
33485
33506
|
{
|
|
33486
33507
|
kind: "build-target",
|
|
@@ -33488,7 +33509,7 @@ function authSourceAmendments(input, where) {
|
|
|
33488
33509
|
assets: [
|
|
33489
33510
|
{
|
|
33490
33511
|
glob: "**/*.json",
|
|
33491
|
-
input:
|
|
33512
|
+
input: joinProjectPath(directory, "i18n"),
|
|
33492
33513
|
from: "workspace",
|
|
33493
33514
|
output: `i18n/${SESSION_PLUGIN_ID}`
|
|
33494
33515
|
}
|
|
@@ -34175,7 +34196,7 @@ function read(ts, file2, call) {
|
|
|
34175
34196
|
return {
|
|
34176
34197
|
at: at2,
|
|
34177
34198
|
id: id.text,
|
|
34178
|
-
callable: callable
|
|
34199
|
+
callable: callable?.kind === ts.SyntaxKind.TrueKeyword,
|
|
34179
34200
|
described: properties.has("description"),
|
|
34180
34201
|
answers: properties.has("answers"),
|
|
34181
34202
|
returnsValue: returnsValue(ts, properties.get("run")),
|
|
@@ -34333,9 +34354,10 @@ function valuesFor(scaffold2, args) {
|
|
|
34333
34354
|
}
|
|
34334
34355
|
return values;
|
|
34335
34356
|
}
|
|
34357
|
+
var WHERE_THE_FILES_LAND = "<the directory you wrote these files into>";
|
|
34336
34358
|
function scaffold(scaffold2, args) {
|
|
34337
34359
|
const values = valuesFor(scaffold2, args);
|
|
34338
|
-
const remaining = (scaffold2.amend?.(values) ?? []).map((amendment) => describeAmendment(amendment));
|
|
34360
|
+
const remaining = (scaffold2.amend?.({ ...values, directory: WHERE_THE_FILES_LAND }) ?? []).map((amendment) => describeAmendment(amendment));
|
|
34339
34361
|
return ok({
|
|
34340
34362
|
files: scaffold2.build(values),
|
|
34341
34363
|
...remaining.length > 0 && { remaining }
|
|
@@ -34395,7 +34417,7 @@ function inputSchema(descriptor) {
|
|
|
34395
34417
|
function createMcpServer() {
|
|
34396
34418
|
const server = new McpServer({
|
|
34397
34419
|
name: "loomweaver-devkit",
|
|
34398
|
-
version: "0.9.
|
|
34420
|
+
version: "0.9.4"
|
|
34399
34421
|
});
|
|
34400
34422
|
server.registerTool(
|
|
34401
34423
|
"list_generators",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomweaver/mcp",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "LoomWeaver: open-source plugin platform for Angular workbenches. The MCP server: scaffolding and validation as tools, so an AI assistant in any product repo can build weavers without a checkout.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"loomweaver",
|