@loomweaver/mcp 0.9.2 → 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 +146 -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.3";
|
|
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.3";
|
|
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),
|
|
@@ -33445,10 +33465,10 @@ function weaverAmendments(input, where) {
|
|
|
33445
33465
|
version: AG_UI_PROTOCOL_VERSION
|
|
33446
33466
|
}
|
|
33447
33467
|
] : [];
|
|
33448
|
-
|
|
33449
|
-
if (!directory) {
|
|
33468
|
+
if (where === void 0 || where === "") {
|
|
33450
33469
|
return packages;
|
|
33451
33470
|
}
|
|
33471
|
+
const directory = normalizeProjectRoot(where);
|
|
33452
33472
|
return [
|
|
33453
33473
|
...packages,
|
|
33454
33474
|
{
|
|
@@ -33457,19 +33477,19 @@ function weaverAmendments(input, where) {
|
|
|
33457
33477
|
assets: [
|
|
33458
33478
|
{
|
|
33459
33479
|
glob: "**/*.json",
|
|
33460
|
-
input:
|
|
33480
|
+
input: joinProjectPath(directory, "src/lib/i18n"),
|
|
33461
33481
|
from: "workspace",
|
|
33462
33482
|
output: `i18n/${w.id}`
|
|
33463
33483
|
}
|
|
33464
33484
|
]
|
|
33465
33485
|
},
|
|
33466
|
-
{ kind: "stylesheet-source", sourceRoot:
|
|
33486
|
+
{ kind: "stylesheet-source", sourceRoot: joinProjectPath(directory, "src") },
|
|
33467
33487
|
{
|
|
33468
33488
|
kind: "compose-plugin",
|
|
33469
33489
|
id: w.id,
|
|
33470
33490
|
symbol: `${w.propertyName}Plugin`,
|
|
33471
33491
|
capabilities: w.capabilities,
|
|
33472
|
-
sourceRoot:
|
|
33492
|
+
sourceRoot: joinProjectPath(directory, "src")
|
|
33473
33493
|
}
|
|
33474
33494
|
];
|
|
33475
33495
|
}
|
|
@@ -33477,10 +33497,10 @@ function weaverAmendments(input, where) {
|
|
|
33477
33497
|
// ../devkit/src/recipes/auth-source/recipe-amendments.ts
|
|
33478
33498
|
function authSourceAmendments(input, where) {
|
|
33479
33499
|
const a = resolveAuthSourceInput(input);
|
|
33480
|
-
|
|
33481
|
-
if (a.bare || !directory) {
|
|
33500
|
+
if (a.bare || where === void 0 || where === "") {
|
|
33482
33501
|
return [];
|
|
33483
33502
|
}
|
|
33503
|
+
const directory = normalizeProjectRoot(where);
|
|
33484
33504
|
return [
|
|
33485
33505
|
{
|
|
33486
33506
|
kind: "build-target",
|
|
@@ -33488,7 +33508,7 @@ function authSourceAmendments(input, where) {
|
|
|
33488
33508
|
assets: [
|
|
33489
33509
|
{
|
|
33490
33510
|
glob: "**/*.json",
|
|
33491
|
-
input:
|
|
33511
|
+
input: joinProjectPath(directory, "i18n"),
|
|
33492
33512
|
from: "workspace",
|
|
33493
33513
|
output: `i18n/${SESSION_PLUGIN_ID}`
|
|
33494
33514
|
}
|
|
@@ -34175,7 +34195,7 @@ function read(ts, file2, call) {
|
|
|
34175
34195
|
return {
|
|
34176
34196
|
at: at2,
|
|
34177
34197
|
id: id.text,
|
|
34178
|
-
callable: callable
|
|
34198
|
+
callable: callable?.kind === ts.SyntaxKind.TrueKeyword,
|
|
34179
34199
|
described: properties.has("description"),
|
|
34180
34200
|
answers: properties.has("answers"),
|
|
34181
34201
|
returnsValue: returnsValue(ts, properties.get("run")),
|
|
@@ -34333,9 +34353,10 @@ function valuesFor(scaffold2, args) {
|
|
|
34333
34353
|
}
|
|
34334
34354
|
return values;
|
|
34335
34355
|
}
|
|
34356
|
+
var WHERE_THE_FILES_LAND = "<the directory you wrote these files into>";
|
|
34336
34357
|
function scaffold(scaffold2, args) {
|
|
34337
34358
|
const values = valuesFor(scaffold2, args);
|
|
34338
|
-
const remaining = (scaffold2.amend?.(values) ?? []).map((amendment) => describeAmendment(amendment));
|
|
34359
|
+
const remaining = (scaffold2.amend?.({ ...values, directory: WHERE_THE_FILES_LAND }) ?? []).map((amendment) => describeAmendment(amendment));
|
|
34339
34360
|
return ok({
|
|
34340
34361
|
files: scaffold2.build(values),
|
|
34341
34362
|
...remaining.length > 0 && { remaining }
|
|
@@ -34395,7 +34416,7 @@ function inputSchema(descriptor) {
|
|
|
34395
34416
|
function createMcpServer() {
|
|
34396
34417
|
const server = new McpServer({
|
|
34397
34418
|
name: "loomweaver-devkit",
|
|
34398
|
-
version: "0.9.
|
|
34419
|
+
version: "0.9.3"
|
|
34399
34420
|
});
|
|
34400
34421
|
server.registerTool(
|
|
34401
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",
|