@loomweaver/mcp 0.14.2 → 0.14.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 +3 -1
- package/dist/main.mjs +131 -131
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,9 @@ is not inside this repo (a chat assistant, a remote client) can scaffold and val
|
|
|
9
9
|
- `list_generators` — the available generators.
|
|
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
|
-
(`path -> content`); the client writes the files into its project.
|
|
12
|
+
(`path -> content`); the client writes the files into its project. The server cannot read that
|
|
13
|
+
project, so pass `scaffold_weaver` the selector prefix your application declares as `prefix`;
|
|
14
|
+
without it the components are named `app-…`.
|
|
13
15
|
- `validate_manifest` · `validate_i18n` · `validate_catalog` · `validate_commands` — return structured `Finding[]`.
|
|
14
16
|
|
|
15
17
|
## Consume from npm (product repos)
|
package/dist/main.mjs
CHANGED
|
@@ -31154,9 +31154,9 @@ function renderRegions(indent) {
|
|
|
31154
31154
|
// ../devkit/src/recipes/angular-weaver/agent-panel.ts
|
|
31155
31155
|
function panelFile(weaver) {
|
|
31156
31156
|
return `import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
|
|
31157
|
-
import { EventType, type
|
|
31158
|
-
import {
|
|
31159
|
-
import {
|
|
31157
|
+
import { EventType, type AGUIEvent, type Tool, type ToolMessage } from '@ag-ui/core';
|
|
31158
|
+
import { askAgent } from './${weaver.id}-agent';
|
|
31159
|
+
import { ${weaver.propertyName}Tools } from './${weaver.id}-connection';
|
|
31160
31160
|
|
|
31161
31161
|
interface Line {
|
|
31162
31162
|
readonly kind: 'you' | 'agent' | 'call' | 'result' | 'note';
|
|
@@ -31186,11 +31186,11 @@ export class ${weaver.className}AgentPanel {
|
|
|
31186
31186
|
// The list is read again whenever the panel gains focus, because the weaver's own translations
|
|
31187
31187
|
// and other plugins' commands may arrive after this component was built.
|
|
31188
31188
|
protected refreshOffered(): void {
|
|
31189
|
-
this.offered.set(${weaver.propertyName}
|
|
31189
|
+
this.offered.set(${weaver.propertyName}Tools()?.list() ?? []);
|
|
31190
31190
|
}
|
|
31191
31191
|
|
|
31192
31192
|
protected async ask(name: string): Promise<void> {
|
|
31193
|
-
const tools = ${weaver.propertyName}
|
|
31193
|
+
const tools = ${weaver.propertyName}Tools();
|
|
31194
31194
|
if (!tools || this.busy()) {
|
|
31195
31195
|
return;
|
|
31196
31196
|
}
|
|
@@ -31233,24 +31233,19 @@ export class ${weaver.className}AgentPanel {
|
|
|
31233
31233
|
}
|
|
31234
31234
|
}
|
|
31235
31235
|
|
|
31236
|
-
private draw(event:
|
|
31237
|
-
const raw = event as unknown as Record<string, unknown>;
|
|
31236
|
+
private draw(event: AGUIEvent): void {
|
|
31238
31237
|
switch (event.type) {
|
|
31239
31238
|
case EventType.TEXT_MESSAGE_START:
|
|
31240
31239
|
this.push({ kind: 'agent', text: '' });
|
|
31241
31240
|
break;
|
|
31242
31241
|
case EventType.TEXT_MESSAGE_CONTENT:
|
|
31243
|
-
this.grow('text',
|
|
31242
|
+
this.grow('text', event.delta);
|
|
31244
31243
|
break;
|
|
31245
31244
|
case EventType.TOOL_CALL_START:
|
|
31246
|
-
this.push({
|
|
31247
|
-
kind: 'call',
|
|
31248
|
-
text: String(raw['toolCallName'] ?? ''),
|
|
31249
|
-
args: '',
|
|
31250
|
-
});
|
|
31245
|
+
this.push({ kind: 'call', text: event.toolCallName, args: '' });
|
|
31251
31246
|
break;
|
|
31252
31247
|
case EventType.TOOL_CALL_ARGS:
|
|
31253
|
-
this.grow('args',
|
|
31248
|
+
this.grow('args', event.delta);
|
|
31254
31249
|
break;
|
|
31255
31250
|
default:
|
|
31256
31251
|
break;
|
|
@@ -31279,7 +31274,7 @@ function panelTemplateFile(weaver) {
|
|
|
31279
31274
|
class="shrink-0 rounded-md border border-border bg-surface-raised px-3 py-2 text-xs text-content-muted"
|
|
31280
31275
|
>
|
|
31281
31276
|
This is a stand-in, not an assistant. It speaks the protocol so you can watch the whole path;
|
|
31282
|
-
replace <code class="text-content">${weaver.id}-agent
|
|
31277
|
+
replace <code class="text-content">${weaver.id}-agent.ts</code> with your own transport.
|
|
31283
31278
|
</p>
|
|
31284
31279
|
|
|
31285
31280
|
<div class="min-h-0 flex-1 overflow-auto">
|
|
@@ -31347,7 +31342,7 @@ function panelTemplateFile(weaver) {
|
|
|
31347
31342
|
|
|
31348
31343
|
// ../devkit/src/recipes/angular-weaver/agent-stand-in.ts
|
|
31349
31344
|
function standInFile(weaver) {
|
|
31350
|
-
return `import { EventType, type
|
|
31345
|
+
return `import { EventType, type AGUIEvent, type Tool } from '@ag-ui/core';
|
|
31351
31346
|
|
|
31352
31347
|
// WHAT THIS IS: a stand-in for an agent, and not an agent. It speaks the AG-UI protocol and nothing
|
|
31353
31348
|
// else \u2014 no model, no network, no judgement \u2014 so that the whole path from the offered tools through
|
|
@@ -31367,15 +31362,16 @@ export interface AgentRequest {
|
|
|
31367
31362
|
|
|
31368
31363
|
export async function* askAgent(
|
|
31369
31364
|
request: AgentRequest,
|
|
31370
|
-
): AsyncGenerator<
|
|
31365
|
+
): AsyncGenerator<AGUIEvent> {
|
|
31371
31366
|
const picked = request.tools.find((tool) =>
|
|
31372
31367
|
request.prompt.includes(tool.name),
|
|
31373
31368
|
);
|
|
31374
31369
|
|
|
31375
|
-
yield
|
|
31370
|
+
yield {
|
|
31371
|
+
type: EventType.RUN_STARTED,
|
|
31376
31372
|
threadId: '${weaver.id}-stand-in',
|
|
31377
31373
|
runId: request.runId,
|
|
31378
|
-
}
|
|
31374
|
+
};
|
|
31379
31375
|
yield* speak(
|
|
31380
31376
|
\`\${request.runId}.says\`,
|
|
31381
31377
|
picked
|
|
@@ -31385,37 +31381,35 @@ export async function* askAgent(
|
|
|
31385
31381
|
|
|
31386
31382
|
if (picked) {
|
|
31387
31383
|
const toolCallId = \`\${request.runId}.call\`;
|
|
31388
|
-
yield
|
|
31389
|
-
toolCallId,
|
|
31390
|
-
toolCallName: picked.name,
|
|
31391
|
-
});
|
|
31384
|
+
yield { type: EventType.TOOL_CALL_START, toolCallId, toolCallName: picked.name };
|
|
31392
31385
|
// Arguments arrive in pieces, exactly as they do from a real model. The adapter assembles them;
|
|
31393
31386
|
// nothing downstream ever sees a half-written call. The values come from the JSON Schema the
|
|
31394
31387
|
// workbench described in picked.parameters: the first declared choice of the first argument that
|
|
31395
31388
|
// has choices, and nothing for the rest, so the command applies its own defaults there.
|
|
31396
31389
|
for (const piece of chunks(JSON.stringify(sampleArguments(picked)), 4)) {
|
|
31397
|
-
yield
|
|
31390
|
+
yield { type: EventType.TOOL_CALL_ARGS, toolCallId, delta: piece };
|
|
31398
31391
|
await pause();
|
|
31399
31392
|
}
|
|
31400
|
-
yield
|
|
31393
|
+
yield { type: EventType.TOOL_CALL_END, toolCallId };
|
|
31401
31394
|
}
|
|
31402
31395
|
|
|
31403
|
-
yield
|
|
31396
|
+
yield {
|
|
31397
|
+
type: EventType.RUN_FINISHED,
|
|
31404
31398
|
threadId: '${weaver.id}-stand-in',
|
|
31405
31399
|
runId: request.runId,
|
|
31406
|
-
}
|
|
31400
|
+
};
|
|
31407
31401
|
}
|
|
31408
31402
|
|
|
31409
31403
|
async function* speak(
|
|
31410
31404
|
messageId: string,
|
|
31411
31405
|
text: string,
|
|
31412
|
-
): AsyncGenerator<
|
|
31413
|
-
yield
|
|
31406
|
+
): AsyncGenerator<AGUIEvent> {
|
|
31407
|
+
yield { type: EventType.TEXT_MESSAGE_START, messageId, role: 'assistant' };
|
|
31414
31408
|
for (const piece of chunks(text, 10)) {
|
|
31415
|
-
yield
|
|
31409
|
+
yield { type: EventType.TEXT_MESSAGE_CONTENT, messageId, delta: piece };
|
|
31416
31410
|
await pause();
|
|
31417
31411
|
}
|
|
31418
|
-
yield
|
|
31412
|
+
yield { type: EventType.TEXT_MESSAGE_END, messageId };
|
|
31419
31413
|
}
|
|
31420
31414
|
|
|
31421
31415
|
function sampleArguments(tool: Tool): Record<string, unknown> {
|
|
@@ -31438,10 +31432,6 @@ function chunks(text: string, size: number): readonly string[] {
|
|
|
31438
31432
|
return pieces;
|
|
31439
31433
|
}
|
|
31440
31434
|
|
|
31441
|
-
function event(type: EventType, fields: Record<string, unknown>): BaseEvent {
|
|
31442
|
-
return { type, ...fields } as unknown as BaseEvent;
|
|
31443
|
-
}
|
|
31444
|
-
|
|
31445
31435
|
function pause(): Promise<void> {
|
|
31446
31436
|
return new Promise((done) => setTimeout(done, PAUSE_MS));
|
|
31447
31437
|
}
|
|
@@ -31460,15 +31450,18 @@ import {
|
|
|
31460
31450
|
} from '@loomweaver/ag-ui';
|
|
31461
31451
|
import type { PluginContext } from '@loomweaver/plugin-sdk';
|
|
31462
31452
|
|
|
31453
|
+
// The connection is the workbench's half: the commands offered as tools, and each call put to the
|
|
31454
|
+
// workbench and answered. The agent is yours and lives beside it, in ${weaver.id}-agent.ts.
|
|
31455
|
+
//
|
|
31463
31456
|
// A factory, not a module-level connection: everything a run needs lives in the closure, so a second
|
|
31464
31457
|
// one never shares state with the first.
|
|
31465
|
-
export function ${weaver.
|
|
31458
|
+
export function connect${weaver.className}(ctx: PluginContext): CommandTools {
|
|
31466
31459
|
return commandTools(ctx, { before: (call) => decide(ctx, call) });
|
|
31467
31460
|
}
|
|
31468
31461
|
|
|
31469
31462
|
// The one connection this plugin activates, published for its panel. Set in activate(), cleared in
|
|
31470
31463
|
// deactivate(), so the panel renders an honest empty state either side of that.
|
|
31471
|
-
export const ${weaver.propertyName}
|
|
31464
|
+
export const ${weaver.propertyName}Tools = signal<CommandTools | null>(null);
|
|
31472
31465
|
|
|
31473
31466
|
// What an agent's word is enough for is the command's own statement, declared where the command is
|
|
31474
31467
|
// registered and read off the call here. No list of ids lives beside the commands: a list drifts from
|
|
@@ -31503,9 +31496,10 @@ async function decide(
|
|
|
31503
31496
|
`;
|
|
31504
31497
|
}
|
|
31505
31498
|
function specFile(weaver) {
|
|
31506
|
-
return `import { EventType, type
|
|
31499
|
+
return `import { EventType, type AGUIEvent, type ToolMessage } from '@ag-ui/core';
|
|
31500
|
+
import type { CommandTools } from '@loomweaver/ag-ui';
|
|
31507
31501
|
import type { CommandArguments, PluginContext } from '@loomweaver/plugin-sdk';
|
|
31508
|
-
import { ${weaver.
|
|
31502
|
+
import { connect${weaver.className} } from './${weaver.id}-connection';
|
|
31509
31503
|
|
|
31510
31504
|
interface Asked {
|
|
31511
31505
|
readonly id: string;
|
|
@@ -31526,37 +31520,36 @@ function contextThat(confirms: boolean, ran: Asked[]): PluginContext {
|
|
|
31526
31520
|
} as unknown as PluginContext;
|
|
31527
31521
|
}
|
|
31528
31522
|
|
|
31529
|
-
function
|
|
31530
|
-
return
|
|
31523
|
+
function streamedCall(toolCallId: string, ...deltas: string[]): AGUIEvent[] {
|
|
31524
|
+
return [
|
|
31525
|
+
{ type: EventType.TOOL_CALL_START, toolCallId, toolCallName: '${weaver.id}.hello' },
|
|
31526
|
+
...deltas.map((delta): AGUIEvent => ({ type: EventType.TOOL_CALL_ARGS, toolCallId, delta })),
|
|
31527
|
+
{ type: EventType.TOOL_CALL_END, toolCallId },
|
|
31528
|
+
];
|
|
31529
|
+
}
|
|
31530
|
+
|
|
31531
|
+
async function answersTo(tools: CommandTools, events: AGUIEvent[]): Promise<ToolMessage[]> {
|
|
31532
|
+
const answers: ToolMessage[] = [];
|
|
31533
|
+
for (const event of events) {
|
|
31534
|
+
const answer = await tools.receive(event);
|
|
31535
|
+
if (answer) {
|
|
31536
|
+
answers.push(answer);
|
|
31537
|
+
}
|
|
31538
|
+
}
|
|
31539
|
+
return answers;
|
|
31531
31540
|
}
|
|
31532
31541
|
|
|
31533
|
-
describe('${weaver.
|
|
31542
|
+
describe('connect${weaver.className}', () => {
|
|
31534
31543
|
it('offers what the workbench offers', () => {
|
|
31535
|
-
const tools = ${weaver.
|
|
31544
|
+
const tools = connect${weaver.className}(contextThat(true, []));
|
|
31536
31545
|
expect(tools.list().map((tool) => tool.name)).toEqual(['${weaver.id}.hello']);
|
|
31537
31546
|
});
|
|
31538
31547
|
|
|
31539
31548
|
it('assembles a call from its events and answers with the outcome', async () => {
|
|
31540
31549
|
const ran: Asked[] = [];
|
|
31541
|
-
const tools = ${weaver.
|
|
31550
|
+
const tools = connect${weaver.className}(contextThat(true, ran));
|
|
31542
31551
|
|
|
31543
|
-
|
|
31544
|
-
await tools.receive(
|
|
31545
|
-
event(EventType.TOOL_CALL_START, {
|
|
31546
|
-
toolCallId: 'c1',
|
|
31547
|
-
toolCallName: '${weaver.id}.hello',
|
|
31548
|
-
}),
|
|
31549
|
-
),
|
|
31550
|
-
).toBeNull();
|
|
31551
|
-
await tools.receive(
|
|
31552
|
-
event(EventType.TOOL_CALL_ARGS, { toolCallId: 'c1', delta: '{"tone"' }),
|
|
31553
|
-
);
|
|
31554
|
-
await tools.receive(
|
|
31555
|
-
event(EventType.TOOL_CALL_ARGS, { toolCallId: 'c1', delta: ':"success"}' }),
|
|
31556
|
-
);
|
|
31557
|
-
const answer = await tools.receive(
|
|
31558
|
-
event(EventType.TOOL_CALL_END, { toolCallId: 'c1' }),
|
|
31559
|
-
);
|
|
31552
|
+
const [answer] = await answersTo(tools, streamedCall('c1', '{"tone"', ':"success"}'));
|
|
31560
31553
|
|
|
31561
31554
|
expect(ran).toEqual([{ id: '${weaver.id}.hello', args: { tone: 'success' } }]);
|
|
31562
31555
|
expect(JSON.parse(answer?.content ?? '{}').tone).toBe('success');
|
|
@@ -31565,20 +31558,9 @@ describe('${weaver.propertyName}Connection', () => {
|
|
|
31565
31558
|
|
|
31566
31559
|
it('never reaches the workbench when a consequential call is declined', async () => {
|
|
31567
31560
|
const ran: Asked[] = [];
|
|
31568
|
-
const tools = ${weaver.
|
|
31561
|
+
const tools = connect${weaver.className}(contextThat(false, ran));
|
|
31569
31562
|
|
|
31570
|
-
await tools
|
|
31571
|
-
event(EventType.TOOL_CALL_START, {
|
|
31572
|
-
toolCallId: 'c2',
|
|
31573
|
-
toolCallName: '${weaver.id}.hello',
|
|
31574
|
-
}),
|
|
31575
|
-
);
|
|
31576
|
-
await tools.receive(
|
|
31577
|
-
event(EventType.TOOL_CALL_ARGS, { toolCallId: 'c2', delta: '{}' }),
|
|
31578
|
-
);
|
|
31579
|
-
const answer = await tools.receive(
|
|
31580
|
-
event(EventType.TOOL_CALL_END, { toolCallId: 'c2' }),
|
|
31581
|
-
);
|
|
31563
|
+
const [answer] = await answersTo(tools, streamedCall('c2', '{}'));
|
|
31582
31564
|
|
|
31583
31565
|
expect(ran).toEqual([]);
|
|
31584
31566
|
expect(answer?.error).toContain('did not run');
|
|
@@ -31600,13 +31582,13 @@ function agentSurfaceBlock(weaver) {
|
|
|
31600
31582
|
}
|
|
31601
31583
|
function agentFiles(weaver) {
|
|
31602
31584
|
const files = {
|
|
31603
|
-
[`src/lib/agent/${weaver.id}-
|
|
31604
|
-
[`src/lib/agent/${weaver.id}-agent
|
|
31585
|
+
[`src/lib/agent/${weaver.id}-connection.ts`]: connectionFile(weaver),
|
|
31586
|
+
[`src/lib/agent/${weaver.id}-agent.ts`]: standInFile(weaver),
|
|
31605
31587
|
[`src/lib/agent/${weaver.id}-agent-panel.ts`]: panelFile(weaver),
|
|
31606
31588
|
[`src/lib/agent/${weaver.id}-agent-panel.html`]: panelTemplateFile(weaver)
|
|
31607
31589
|
};
|
|
31608
31590
|
if (weaver.features.spec) {
|
|
31609
|
-
files[`src/lib/agent/${weaver.id}-
|
|
31591
|
+
files[`src/lib/agent/${weaver.id}-connection.spec.ts`] = specFile(weaver);
|
|
31610
31592
|
}
|
|
31611
31593
|
return files;
|
|
31612
31594
|
}
|
|
@@ -31645,6 +31627,45 @@ function i18nFile(weaver) {
|
|
|
31645
31627
|
return JSON.stringify(i18nBundle(weaver), null, 2) + "\n";
|
|
31646
31628
|
}
|
|
31647
31629
|
|
|
31630
|
+
// ../devkit/src/lib/scaffolds/scaffold-values.ts
|
|
31631
|
+
var NEUTRAL_PREFIX = "app";
|
|
31632
|
+
function stringValue(values, name) {
|
|
31633
|
+
const value = values[name];
|
|
31634
|
+
return typeof value === "string" ? value : void 0;
|
|
31635
|
+
}
|
|
31636
|
+
function booleanValue(values, name) {
|
|
31637
|
+
const value = values[name];
|
|
31638
|
+
return typeof value === "boolean" ? value : void 0;
|
|
31639
|
+
}
|
|
31640
|
+
var PLACEMENT_OPTIONS = [
|
|
31641
|
+
{
|
|
31642
|
+
name: "directory",
|
|
31643
|
+
type: "string",
|
|
31644
|
+
description: "Project root, relative to the workspace root.",
|
|
31645
|
+
workspaceOnly: true
|
|
31646
|
+
},
|
|
31647
|
+
{
|
|
31648
|
+
name: "tags",
|
|
31649
|
+
type: "string",
|
|
31650
|
+
description: "Comma-separated Nx tags for the project.",
|
|
31651
|
+
workspaceOnly: true
|
|
31652
|
+
},
|
|
31653
|
+
{
|
|
31654
|
+
name: "unitTestRunner",
|
|
31655
|
+
type: "string",
|
|
31656
|
+
description: "Test wiring to emit. 'vitest' uses @nx/angular:unit-test; 'none' emits no test target.",
|
|
31657
|
+
choices: ["vitest", "none"],
|
|
31658
|
+
default: "vitest",
|
|
31659
|
+
workspaceOnly: true
|
|
31660
|
+
}
|
|
31661
|
+
];
|
|
31662
|
+
var APP_OPTION = {
|
|
31663
|
+
name: "app",
|
|
31664
|
+
type: "string",
|
|
31665
|
+
description: "Application to drop into. Inferred when the workspace has exactly one.",
|
|
31666
|
+
workspaceOnly: true
|
|
31667
|
+
};
|
|
31668
|
+
|
|
31648
31669
|
// ../devkit/src/lib/validate/manifest.ts
|
|
31649
31670
|
var KNOWN_CAPABILITIES = [
|
|
31650
31671
|
"contributions",
|
|
@@ -31804,6 +31825,18 @@ function deriveCapabilities(features) {
|
|
|
31804
31825
|
}
|
|
31805
31826
|
return KNOWN_CAPABILITIES.filter((capability) => set2.has(capability));
|
|
31806
31827
|
}
|
|
31828
|
+
function resolvePrefix(prefix) {
|
|
31829
|
+
const trimmed = prefix?.trim();
|
|
31830
|
+
if (!trimmed) {
|
|
31831
|
+
return NEUTRAL_PREFIX;
|
|
31832
|
+
}
|
|
31833
|
+
if (!isKebabId(trimmed)) {
|
|
31834
|
+
throw new Error(
|
|
31835
|
+
`Selector prefix must be kebab-case (e.g. "acme"); got "${trimmed}".`
|
|
31836
|
+
);
|
|
31837
|
+
}
|
|
31838
|
+
return trimmed;
|
|
31839
|
+
}
|
|
31807
31840
|
function resolveWeaverInput(input) {
|
|
31808
31841
|
if (!isKebabId(input.id)) {
|
|
31809
31842
|
throw new Error(
|
|
@@ -31819,7 +31852,7 @@ function resolveWeaverInput(input) {
|
|
|
31819
31852
|
propertyName: toCamelCase(input.id),
|
|
31820
31853
|
capabilities,
|
|
31821
31854
|
features,
|
|
31822
|
-
prefix: input.prefix
|
|
31855
|
+
prefix: resolvePrefix(input.prefix),
|
|
31823
31856
|
importPath: input.importPath?.trim() || `@loomweaver/${input.id}-weaver`
|
|
31824
31857
|
};
|
|
31825
31858
|
}
|
|
@@ -32016,7 +32049,7 @@ function pluginImports(weaver) {
|
|
|
32016
32049
|
}
|
|
32017
32050
|
if (weaver.features.agent) {
|
|
32018
32051
|
imports.push(
|
|
32019
|
-
`import { ${weaver.
|
|
32052
|
+
`import { connect${weaver.className}, ${weaver.propertyName}Tools } from '../agent/${weaver.id}-connection';`,
|
|
32020
32053
|
`import { ${weaver.className}AgentPanel } from '../agent/${weaver.id}-agent-panel';`
|
|
32021
32054
|
);
|
|
32022
32055
|
}
|
|
@@ -32041,7 +32074,7 @@ function pluginBody(weaver) {
|
|
|
32041
32074
|
const body = [` ctx.contributeIcons({ '${weaver.id}': icon });`];
|
|
32042
32075
|
if (weaver.features.agent) {
|
|
32043
32076
|
body.push(
|
|
32044
|
-
` ${weaver.propertyName}
|
|
32077
|
+
` ${weaver.propertyName}Tools.set(connect${weaver.className}(ctx));`
|
|
32045
32078
|
);
|
|
32046
32079
|
}
|
|
32047
32080
|
if (weaver.features.command) body.push(commandBlock(weaver));
|
|
@@ -32058,7 +32091,7 @@ function pluginFile(weaver) {
|
|
|
32058
32091
|
const body = pluginBody(weaver);
|
|
32059
32092
|
const deactivate = weaver.features.agent ? `
|
|
32060
32093
|
deactivate() {
|
|
32061
|
-
${weaver.propertyName}
|
|
32094
|
+
${weaver.propertyName}Tools.set(null);
|
|
32062
32095
|
},` : "";
|
|
32063
32096
|
return `${pluginImports(weaver).join("\n")}
|
|
32064
32097
|
|
|
@@ -32081,7 +32114,7 @@ function accessLine(weaver) {
|
|
|
32081
32114
|
}
|
|
32082
32115
|
|
|
32083
32116
|
// ../devkit/src/recipes/platform-version.ts
|
|
32084
|
-
var PLATFORM_VERSION = "0.14.
|
|
32117
|
+
var PLATFORM_VERSION = "0.14.4";
|
|
32085
32118
|
|
|
32086
32119
|
// ../devkit/src/recipes/readme-notes.ts
|
|
32087
32120
|
var UNTAGGED_NOTE = [
|
|
@@ -32155,11 +32188,11 @@ function agentNotes(weaver) {
|
|
|
32155
32188
|
"",
|
|
32156
32189
|
`\`src/lib/agent/\` holds three files and one of them is meant to be thrown away.`,
|
|
32157
32190
|
"",
|
|
32158
|
-
`- \`${weaver.id}-
|
|
32191
|
+
`- \`${weaver.id}-connection.ts\` is the connection: the workbench's own commands offered as tools, and a`,
|
|
32159
32192
|
" seam where this weaver decides about a call before it runs. Nothing is registered twice \u2014 the",
|
|
32160
32193
|
" list comes from the workbench, already narrowed by everything that would refuse the call.",
|
|
32161
32194
|
`- \`${weaver.id}-agent-panel.ts\` shows what is offered, the call as it streams, and the outcome.`,
|
|
32162
|
-
`- \`${weaver.id}-agent
|
|
32195
|
+
`- \`${weaver.id}-agent.ts\` is a **stand-in** for the agent, not an assistant: it produces the protocol's own`,
|
|
32163
32196
|
" events so the whole path runs before you have connected anything. Replace that one file with",
|
|
32164
32197
|
" your transport and nothing else changes. No transport, credential or model is generated for",
|
|
32165
32198
|
" you, because none of them can be guessed.",
|
|
@@ -33524,52 +33557,6 @@ var layout = {
|
|
|
33524
33557
|
}
|
|
33525
33558
|
};
|
|
33526
33559
|
|
|
33527
|
-
// ../devkit/src/lib/scaffolds/scaffold-values.ts
|
|
33528
|
-
function stringValue(values, name) {
|
|
33529
|
-
const value = values[name];
|
|
33530
|
-
return typeof value === "string" ? value : void 0;
|
|
33531
|
-
}
|
|
33532
|
-
function booleanValue(values, name) {
|
|
33533
|
-
const value = values[name];
|
|
33534
|
-
return typeof value === "boolean" ? value : void 0;
|
|
33535
|
-
}
|
|
33536
|
-
var PLACEMENT_OPTIONS = [
|
|
33537
|
-
{
|
|
33538
|
-
name: "directory",
|
|
33539
|
-
type: "string",
|
|
33540
|
-
description: "Project root, relative to the workspace root.",
|
|
33541
|
-
workspaceOnly: true
|
|
33542
|
-
},
|
|
33543
|
-
{
|
|
33544
|
-
name: "tags",
|
|
33545
|
-
type: "string",
|
|
33546
|
-
description: "Comma-separated Nx tags for the project.",
|
|
33547
|
-
workspaceOnly: true
|
|
33548
|
-
},
|
|
33549
|
-
{
|
|
33550
|
-
name: "prefix",
|
|
33551
|
-
type: "string",
|
|
33552
|
-
description: "Selector prefix for generated components and directives.",
|
|
33553
|
-
default: "lw",
|
|
33554
|
-
pattern: KEBAB_ID_PATTERN,
|
|
33555
|
-
workspaceOnly: true
|
|
33556
|
-
},
|
|
33557
|
-
{
|
|
33558
|
-
name: "unitTestRunner",
|
|
33559
|
-
type: "string",
|
|
33560
|
-
description: "Test wiring to emit. 'vitest' uses @nx/angular:unit-test; 'none' emits no test target.",
|
|
33561
|
-
choices: ["vitest", "none"],
|
|
33562
|
-
default: "vitest",
|
|
33563
|
-
workspaceOnly: true
|
|
33564
|
-
}
|
|
33565
|
-
];
|
|
33566
|
-
var APP_OPTION = {
|
|
33567
|
-
name: "app",
|
|
33568
|
-
type: "string",
|
|
33569
|
-
description: "Application to drop into. Inferred when the workspace has exactly one.",
|
|
33570
|
-
workspaceOnly: true
|
|
33571
|
-
};
|
|
33572
|
-
|
|
33573
33560
|
// ../devkit/src/recipes/angular-distribution/scaffold.ts
|
|
33574
33561
|
function distributionInput(values) {
|
|
33575
33562
|
return {
|
|
@@ -33608,6 +33595,13 @@ var distributionScaffold = {
|
|
|
33608
33595
|
description: "Compose into the application already at that path, replacing the bootstrap files this scaffold owns and merging its build targets. Without it an existing project is an error.",
|
|
33609
33596
|
workspaceOnly: true
|
|
33610
33597
|
},
|
|
33598
|
+
{
|
|
33599
|
+
name: "prefix",
|
|
33600
|
+
type: "string",
|
|
33601
|
+
description: "Selector prefix the application declares for its components, which a weaver generated into it takes. Defaults to 'app'.",
|
|
33602
|
+
pattern: KEBAB_ID_PATTERN,
|
|
33603
|
+
workspaceOnly: true
|
|
33604
|
+
},
|
|
33611
33605
|
...PLACEMENT_OPTIONS
|
|
33612
33606
|
],
|
|
33613
33607
|
build: (values) => generate(angularDistribution, distributionInput(values)),
|
|
@@ -33771,6 +33765,12 @@ var weaverScaffold = {
|
|
|
33771
33765
|
description: "Import path for the workspace alias. Defaults to the workspace scope plus the project name.",
|
|
33772
33766
|
workspaceOnly: true
|
|
33773
33767
|
},
|
|
33768
|
+
{
|
|
33769
|
+
name: "prefix",
|
|
33770
|
+
type: "string",
|
|
33771
|
+
description: "Selector prefix for the generated components: the one the application declares, as the prefix of its project in angular.json or project.json. Read from the workspace where it can be, else 'app'.",
|
|
33772
|
+
pattern: KEBAB_ID_PATTERN
|
|
33773
|
+
},
|
|
33774
33774
|
APP_OPTION,
|
|
33775
33775
|
...PLACEMENT_OPTIONS
|
|
33776
33776
|
],
|
|
@@ -34570,7 +34570,7 @@ function inputSchema(descriptor) {
|
|
|
34570
34570
|
function createMcpServer() {
|
|
34571
34571
|
const server = new McpServer({
|
|
34572
34572
|
name: "loomweaver-devkit",
|
|
34573
|
-
version: "0.14.
|
|
34573
|
+
version: "0.14.4"
|
|
34574
34574
|
});
|
|
34575
34575
|
server.registerTool(
|
|
34576
34576
|
"list_generators",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomweaver/mcp",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.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",
|