@loomweaver/mcp 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/main.mjs +160 -130
- 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
|
] : [],
|
|
@@ -31055,7 +31063,10 @@ function describeAmendment(amendment) {
|
|
|
31055
31063
|
] : [],
|
|
31056
31064
|
...amendment.inlineCritical === void 0 ? [] : [
|
|
31057
31065
|
`set optimization.styles.inlineCritical to ${amendment.inlineCritical} in the production configuration (the generated content-security policy blocks the inline handler Angular's critical-CSS pass attaches, so a release build renders unstyled)`
|
|
31058
|
-
]
|
|
31066
|
+
],
|
|
31067
|
+
...amendment.initialBudget ? [
|
|
31068
|
+
`raise the initial bundle budget to ${amendment.initialBudget.warning} warning and ${amendment.initialBudget.error} error in the production configuration (a fresh workspace carries one sized for an empty application, and the workbench alone spends almost all of it, so a release build fails)`
|
|
31069
|
+
] : []
|
|
31059
31070
|
].map((step, index) => `${index + 1}. ${step}`).join(" ");
|
|
31060
31071
|
}
|
|
31061
31072
|
|
|
@@ -31447,7 +31458,7 @@ function pause(): Promise<void> {
|
|
|
31447
31458
|
}
|
|
31448
31459
|
|
|
31449
31460
|
// ../devkit/src/recipes/angular-weaver/agent-files.ts
|
|
31450
|
-
var AG_UI_ADAPTER_VERSION = "0.9.
|
|
31461
|
+
var AG_UI_ADAPTER_VERSION = "0.9.3";
|
|
31451
31462
|
var AG_UI_PROTOCOL_VERSION = "0.0.x";
|
|
31452
31463
|
function connectionFile(w) {
|
|
31453
31464
|
return `import { signal } from '@angular/core';
|
|
@@ -31814,109 +31825,8 @@ function toneHelper() {
|
|
|
31814
31825
|
].join("\n");
|
|
31815
31826
|
}
|
|
31816
31827
|
|
|
31817
|
-
// ../devkit/src/recipes/angular-weaver/
|
|
31818
|
-
var DEFAULT_MENU_SLOT = "content/tab/context";
|
|
31828
|
+
// ../devkit/src/recipes/angular-weaver/weaver-plugin.ts
|
|
31819
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>';
|
|
31820
|
-
function accessLiteral(spec) {
|
|
31821
|
-
if (spec === "authenticated") return "{ authenticated: true }";
|
|
31822
|
-
if (spec === "anonymous") return "{ authenticated: false }";
|
|
31823
|
-
if (spec.startsWith("role:")) {
|
|
31824
|
-
const role = spec.slice("role:".length);
|
|
31825
|
-
if (!role)
|
|
31826
|
-
throw new Error('Access "role:" needs a role name, e.g. "role:admin".');
|
|
31827
|
-
if (/['\\]/.test(role))
|
|
31828
|
-
throw new Error(
|
|
31829
|
-
`Access role "${role}" must not contain quotes or backslashes.`
|
|
31830
|
-
);
|
|
31831
|
-
return `{ anyRole: ['${role}'] }`;
|
|
31832
|
-
}
|
|
31833
|
-
throw new Error(
|
|
31834
|
-
`Unknown access "${spec}". Use "authenticated", "anonymous" or "role:<name>".`
|
|
31835
|
-
);
|
|
31836
|
-
}
|
|
31837
|
-
function resolveMenuSlot(menu) {
|
|
31838
|
-
if (menu === true) {
|
|
31839
|
-
return DEFAULT_MENU_SLOT;
|
|
31840
|
-
}
|
|
31841
|
-
return typeof menu === "string" && menu.length ? menu : void 0;
|
|
31842
|
-
}
|
|
31843
|
-
var PLATFORM_BOUND_CHORD_TOKENS = /* @__PURE__ */ new Set([
|
|
31844
|
-
"cmd",
|
|
31845
|
-
"command",
|
|
31846
|
-
"ctrl",
|
|
31847
|
-
"control",
|
|
31848
|
-
"meta"
|
|
31849
|
-
]);
|
|
31850
|
-
function assertPlatformNeutralChord(shortcut) {
|
|
31851
|
-
const tokens = shortcut.toLowerCase().split("+").map((token) => token.trim());
|
|
31852
|
-
const bound = tokens.find((token) => PLATFORM_BOUND_CHORD_TOKENS.has(token));
|
|
31853
|
-
if (bound) {
|
|
31854
|
-
throw new Error(
|
|
31855
|
-
`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.`
|
|
31856
|
-
);
|
|
31857
|
-
}
|
|
31858
|
-
}
|
|
31859
|
-
function resolveFeatures(id, input) {
|
|
31860
|
-
const menuSlot = resolveMenuSlot(input?.menu);
|
|
31861
|
-
const barItem = Boolean(input?.barItem);
|
|
31862
|
-
const hasShortcut = Boolean(input?.shortcut?.trim());
|
|
31863
|
-
if (hasShortcut) {
|
|
31864
|
-
assertPlatformNeutralChord(input?.shortcut?.trim() ?? "");
|
|
31865
|
-
}
|
|
31866
|
-
const instanceable = Boolean(input?.instanceable);
|
|
31867
|
-
const container = Boolean(input?.container);
|
|
31868
|
-
if (instanceable && container) {
|
|
31869
|
-
throw new Error(
|
|
31870
|
-
'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.'
|
|
31871
|
-
);
|
|
31872
|
-
}
|
|
31873
|
-
const agent = Boolean(input?.agent);
|
|
31874
|
-
return {
|
|
31875
|
-
command: Boolean(input?.command) || menuSlot !== void 0 || barItem || hasShortcut || agent,
|
|
31876
|
-
menuSlot,
|
|
31877
|
-
settings: Boolean(input?.settings),
|
|
31878
|
-
access: input?.access ? accessLiteral(input.access) : void 0,
|
|
31879
|
-
shortcut: input?.shortcut?.trim() || `mod+shift+${id.charAt(0)}`,
|
|
31880
|
-
barItem,
|
|
31881
|
-
about: Boolean(input?.about),
|
|
31882
|
-
instanceable,
|
|
31883
|
-
container,
|
|
31884
|
-
agent,
|
|
31885
|
-
spec: input?.spec !== false
|
|
31886
|
-
};
|
|
31887
|
-
}
|
|
31888
|
-
function deriveCapabilities(features) {
|
|
31889
|
-
const set2 = /* @__PURE__ */ new Set(["contributions", "navigation"]);
|
|
31890
|
-
if (features.command) set2.add("ui");
|
|
31891
|
-
if (features.about) {
|
|
31892
|
-
set2.add("ui");
|
|
31893
|
-
set2.add("host");
|
|
31894
|
-
}
|
|
31895
|
-
if (features.agent) {
|
|
31896
|
-
set2.add("ui");
|
|
31897
|
-
set2.add("automation");
|
|
31898
|
-
}
|
|
31899
|
-
return KNOWN_CAPABILITIES.filter((capability) => set2.has(capability));
|
|
31900
|
-
}
|
|
31901
|
-
function resolveWeaverInput(input) {
|
|
31902
|
-
if (!isKebabId(input.id)) {
|
|
31903
|
-
throw new Error(
|
|
31904
|
-
`Weaver id must be kebab-case (e.g. "notes"); got "${input.id}".`
|
|
31905
|
-
);
|
|
31906
|
-
}
|
|
31907
|
-
const features = resolveFeatures(input.id, input.features);
|
|
31908
|
-
const capabilities = input.capabilities?.length ? [...input.capabilities] : deriveCapabilities(features);
|
|
31909
|
-
return {
|
|
31910
|
-
id: input.id,
|
|
31911
|
-
name: input.name?.trim() || toTitleCase(input.id),
|
|
31912
|
-
className: toPascalCase(input.id),
|
|
31913
|
-
propertyName: toCamelCase(input.id),
|
|
31914
|
-
capabilities,
|
|
31915
|
-
features,
|
|
31916
|
-
prefix: input.prefix?.trim() || "lw",
|
|
31917
|
-
importPath: input.importPath?.trim() || `@loomweaver/${input.id}-weaver`
|
|
31918
|
-
};
|
|
31919
|
-
}
|
|
31920
31830
|
function containerChildIds(w) {
|
|
31921
31831
|
return [`${w.id}.canvas`, `${w.id}.details`];
|
|
31922
31832
|
}
|
|
@@ -32053,7 +31963,7 @@ function settingsBlock(w) {
|
|
|
32053
31963
|
" });"
|
|
32054
31964
|
].join("\n");
|
|
32055
31965
|
}
|
|
32056
|
-
function
|
|
31966
|
+
function pluginImports(w) {
|
|
32057
31967
|
const imports = ["import { Plugin } from '@loomweaver/plugin-sdk';"];
|
|
32058
31968
|
if (w.features.container) {
|
|
32059
31969
|
imports.push(
|
|
@@ -32077,6 +31987,9 @@ function pluginFile(w) {
|
|
|
32077
31987
|
if (w.features.settings) {
|
|
32078
31988
|
imports.unshift("import { signal } from '@angular/core';");
|
|
32079
31989
|
}
|
|
31990
|
+
return imports;
|
|
31991
|
+
}
|
|
31992
|
+
function pluginConsts(w) {
|
|
32080
31993
|
const consts = [`const icon =
|
|
32081
31994
|
'${SURFACE_ICON}';`];
|
|
32082
31995
|
if (w.features.settings) {
|
|
@@ -32085,6 +31998,10 @@ function pluginFile(w) {
|
|
|
32085
31998
|
`const ${w.propertyName}Note = signal('');`
|
|
32086
31999
|
);
|
|
32087
32000
|
}
|
|
32001
|
+
if (w.features.command) consts.push(toneHelper());
|
|
32002
|
+
return consts;
|
|
32003
|
+
}
|
|
32004
|
+
function pluginBody(w) {
|
|
32088
32005
|
const body = [` ctx.contributeIcons({ '${w.id}': icon });`];
|
|
32089
32006
|
if (w.features.agent) {
|
|
32090
32007
|
body.push(
|
|
@@ -32099,14 +32016,17 @@ function pluginFile(w) {
|
|
|
32099
32016
|
if (w.features.menuSlot) body.push(menuBlock(w));
|
|
32100
32017
|
if (w.features.settings) body.push(settingsBlock(w));
|
|
32101
32018
|
if (w.features.agent) body.push(agentSurfaceBlock(w));
|
|
32019
|
+
return body;
|
|
32020
|
+
}
|
|
32021
|
+
function pluginFile(w) {
|
|
32022
|
+
const body = pluginBody(w);
|
|
32102
32023
|
const deactivate = w.features.agent ? `
|
|
32103
32024
|
deactivate() {
|
|
32104
32025
|
${w.propertyName}Agent.set(null);
|
|
32105
32026
|
},` : "";
|
|
32106
|
-
|
|
32107
|
-
return `${imports.join("\n")}
|
|
32027
|
+
return `${pluginImports(w).join("\n")}
|
|
32108
32028
|
|
|
32109
|
-
${
|
|
32029
|
+
${pluginConsts(w).join("\n\n")}
|
|
32110
32030
|
|
|
32111
32031
|
export const ${w.propertyName}Plugin: Plugin = {
|
|
32112
32032
|
manifest: {
|
|
@@ -32120,6 +32040,109 @@ ${body.join("\n")}
|
|
|
32120
32040
|
};
|
|
32121
32041
|
`;
|
|
32122
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
|
+
}
|
|
32123
32146
|
function aboutDialogFile(w) {
|
|
32124
32147
|
return `import { Component, inject } from '@angular/core';
|
|
32125
32148
|
import { DialogRef, PluginHost } from '@loomweaver/plugin-sdk';
|
|
@@ -32430,9 +32453,13 @@ var framePlugin = {
|
|
|
32430
32453
|
};
|
|
32431
32454
|
|
|
32432
32455
|
// ../devkit/src/recipes/platform-version.ts
|
|
32433
|
-
var PLATFORM_VERSION = "0.9.
|
|
32456
|
+
var PLATFORM_VERSION = "0.9.3";
|
|
32434
32457
|
|
|
32435
32458
|
// ../devkit/src/recipes/angular-distribution/amendments.ts
|
|
32459
|
+
var DISTRIBUTION_INITIAL_BUDGET = {
|
|
32460
|
+
warning: "1.5MB",
|
|
32461
|
+
error: "2MB"
|
|
32462
|
+
};
|
|
32436
32463
|
function distributionAmendments(d) {
|
|
32437
32464
|
return [
|
|
32438
32465
|
{
|
|
@@ -32466,7 +32493,8 @@ function distributionAmendments(d) {
|
|
|
32466
32493
|
}
|
|
32467
32494
|
],
|
|
32468
32495
|
serviceWorker: "ngsw-config.json",
|
|
32469
|
-
inlineCritical: false
|
|
32496
|
+
inlineCritical: false,
|
|
32497
|
+
initialBudget: DISTRIBUTION_INITIAL_BUDGET
|
|
32470
32498
|
}
|
|
32471
32499
|
];
|
|
32472
32500
|
}
|
|
@@ -32661,9 +32689,10 @@ function readme2(d) {
|
|
|
32661
32689
|
"the stylesheet with an **inline** `onload` handler that the policy blocks \u2014 the app then renders",
|
|
32662
32690
|
"completely unstyled, and only in production builds.",
|
|
32663
32691
|
"",
|
|
32664
|
-
"
|
|
32665
|
-
"
|
|
32666
|
-
"
|
|
32692
|
+
"The initial-bundle budget in your build target was raised for the same reason: the shell is a",
|
|
32693
|
+
"whole application chrome and spends most of Angular's default before your own code arrives, so",
|
|
32694
|
+
"a production build would have failed on a number meant for an empty app. It is still a budget,",
|
|
32695
|
+
"and it is yours to move.",
|
|
32667
32696
|
"",
|
|
32668
32697
|
"## Ship less than the whole workbench",
|
|
32669
32698
|
"",
|
|
@@ -32716,7 +32745,7 @@ function resolveDistributionInput(input) {
|
|
|
32716
32745
|
);
|
|
32717
32746
|
}
|
|
32718
32747
|
const directory = input.directory === void 0 ? `apps/${input.name}` : input.directory.trim();
|
|
32719
|
-
const depth = directory.split("/").filter(Boolean).length;
|
|
32748
|
+
const depth = normalizeProjectRoot(directory).split("/").filter(Boolean).length;
|
|
32720
32749
|
return {
|
|
32721
32750
|
name: input.name,
|
|
32722
32751
|
title: input.title?.trim() || toTitleCase(input.name),
|
|
@@ -33436,10 +33465,10 @@ function weaverAmendments(input, where) {
|
|
|
33436
33465
|
version: AG_UI_PROTOCOL_VERSION
|
|
33437
33466
|
}
|
|
33438
33467
|
] : [];
|
|
33439
|
-
|
|
33440
|
-
if (!directory) {
|
|
33468
|
+
if (where === void 0 || where === "") {
|
|
33441
33469
|
return packages;
|
|
33442
33470
|
}
|
|
33471
|
+
const directory = normalizeProjectRoot(where);
|
|
33443
33472
|
return [
|
|
33444
33473
|
...packages,
|
|
33445
33474
|
{
|
|
@@ -33448,19 +33477,19 @@ function weaverAmendments(input, where) {
|
|
|
33448
33477
|
assets: [
|
|
33449
33478
|
{
|
|
33450
33479
|
glob: "**/*.json",
|
|
33451
|
-
input:
|
|
33480
|
+
input: joinProjectPath(directory, "src/lib/i18n"),
|
|
33452
33481
|
from: "workspace",
|
|
33453
33482
|
output: `i18n/${w.id}`
|
|
33454
33483
|
}
|
|
33455
33484
|
]
|
|
33456
33485
|
},
|
|
33457
|
-
{ kind: "stylesheet-source", sourceRoot:
|
|
33486
|
+
{ kind: "stylesheet-source", sourceRoot: joinProjectPath(directory, "src") },
|
|
33458
33487
|
{
|
|
33459
33488
|
kind: "compose-plugin",
|
|
33460
33489
|
id: w.id,
|
|
33461
33490
|
symbol: `${w.propertyName}Plugin`,
|
|
33462
33491
|
capabilities: w.capabilities,
|
|
33463
|
-
sourceRoot:
|
|
33492
|
+
sourceRoot: joinProjectPath(directory, "src")
|
|
33464
33493
|
}
|
|
33465
33494
|
];
|
|
33466
33495
|
}
|
|
@@ -33468,10 +33497,10 @@ function weaverAmendments(input, where) {
|
|
|
33468
33497
|
// ../devkit/src/recipes/auth-source/recipe-amendments.ts
|
|
33469
33498
|
function authSourceAmendments(input, where) {
|
|
33470
33499
|
const a = resolveAuthSourceInput(input);
|
|
33471
|
-
|
|
33472
|
-
if (a.bare || !directory) {
|
|
33500
|
+
if (a.bare || where === void 0 || where === "") {
|
|
33473
33501
|
return [];
|
|
33474
33502
|
}
|
|
33503
|
+
const directory = normalizeProjectRoot(where);
|
|
33475
33504
|
return [
|
|
33476
33505
|
{
|
|
33477
33506
|
kind: "build-target",
|
|
@@ -33479,7 +33508,7 @@ function authSourceAmendments(input, where) {
|
|
|
33479
33508
|
assets: [
|
|
33480
33509
|
{
|
|
33481
33510
|
glob: "**/*.json",
|
|
33482
|
-
input:
|
|
33511
|
+
input: joinProjectPath(directory, "i18n"),
|
|
33483
33512
|
from: "workspace",
|
|
33484
33513
|
output: `i18n/${SESSION_PLUGIN_ID}`
|
|
33485
33514
|
}
|
|
@@ -34166,7 +34195,7 @@ function read(ts, file2, call) {
|
|
|
34166
34195
|
return {
|
|
34167
34196
|
at: at2,
|
|
34168
34197
|
id: id.text,
|
|
34169
|
-
callable: callable
|
|
34198
|
+
callable: callable?.kind === ts.SyntaxKind.TrueKeyword,
|
|
34170
34199
|
described: properties.has("description"),
|
|
34171
34200
|
answers: properties.has("answers"),
|
|
34172
34201
|
returnsValue: returnsValue(ts, properties.get("run")),
|
|
@@ -34324,9 +34353,10 @@ function valuesFor(scaffold2, args) {
|
|
|
34324
34353
|
}
|
|
34325
34354
|
return values;
|
|
34326
34355
|
}
|
|
34356
|
+
var WHERE_THE_FILES_LAND = "<the directory you wrote these files into>";
|
|
34327
34357
|
function scaffold(scaffold2, args) {
|
|
34328
34358
|
const values = valuesFor(scaffold2, args);
|
|
34329
|
-
const remaining = (scaffold2.amend?.(values) ?? []).map((amendment) => describeAmendment(amendment));
|
|
34359
|
+
const remaining = (scaffold2.amend?.({ ...values, directory: WHERE_THE_FILES_LAND }) ?? []).map((amendment) => describeAmendment(amendment));
|
|
34330
34360
|
return ok({
|
|
34331
34361
|
files: scaffold2.build(values),
|
|
34332
34362
|
...remaining.length > 0 && { remaining }
|
|
@@ -34386,7 +34416,7 @@ function inputSchema(descriptor) {
|
|
|
34386
34416
|
function createMcpServer() {
|
|
34387
34417
|
const server = new McpServer({
|
|
34388
34418
|
name: "loomweaver-devkit",
|
|
34389
|
-
version: "0.9.
|
|
34419
|
+
version: "0.9.3"
|
|
34390
34420
|
});
|
|
34391
34421
|
server.registerTool(
|
|
34392
34422
|
"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.3",
|
|
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",
|