aub-workspace 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +23 -0
- package/bin/aub-workspace.mjs +246 -0
- package/package.json +32 -0
- package/vendor/aub/apps/editor/dist/assets/_commonjs-dynamic-modules-TDtrdbi3.js +1 -0
- package/vendor/aub/apps/editor/dist/assets/angular-importer.lib-dB_jK4mR.js +32 -0
- package/vendor/aub/apps/editor/dist/assets/canvas-tools-CuYC7cA2.js +364 -0
- package/vendor/aub/apps/editor/dist/assets/design-bridge.lib-DJvaK6AX.js +1 -0
- package/vendor/aub/apps/editor/dist/assets/export-agent-prompt.lib-BsP0KNqo.js +2 -0
- package/vendor/aub/apps/editor/dist/assets/export-md.lib-DdmdeWgO.js +3 -0
- package/vendor/aub/apps/editor/dist/assets/handoff-package.lib-DDYpcEma.js +20 -0
- package/vendor/aub/apps/editor/dist/assets/implementation-report.lib-CmsSB_8s.js +1 -0
- package/vendor/aub/apps/editor/dist/assets/index-BCH-ek3h.js +2 -0
- package/vendor/aub/apps/editor/dist/assets/index-lAnc928Q.css +1 -0
- package/vendor/aub/apps/editor/dist/assets/index-vt1nM1M4.js +507 -0
- package/vendor/aub/apps/editor/dist/assets/jszip.min-CRfXyL92.js +12 -0
- package/vendor/aub/apps/editor/dist/assets/react-vendor-ByX9Pqse.js +40 -0
- package/vendor/aub/apps/editor/dist/brand/android-chrome-192x192.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/android-chrome-512x512.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/app-icon-1024.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/app-icon-192.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/app-icon-512.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/apple-touch-icon.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/aub-logo-mark.svg +28 -0
- package/vendor/aub/apps/editor/dist/brand/favicon-16x16.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/favicon-32x32.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/favicon-48x48.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/favicon.ico +0 -0
- package/vendor/aub/apps/editor/dist/brand/favicon.svg +9 -0
- package/vendor/aub/apps/editor/dist/brand/maskable-icon-512.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/mstile-150x150.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/safari-pinned-tab.svg +8 -0
- package/vendor/aub/apps/editor/dist/browserconfig.xml +9 -0
- package/vendor/aub/apps/editor/dist/index.html +22 -0
- package/vendor/aub/apps/editor/dist/manifest.webmanifest +28 -0
- package/vendor/aub/apps/editor/dist/template-previews/admin-table.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/booking.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/calendar.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/catalog.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/chat.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/checkout.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/crm.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/dashboard.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/feed.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/files.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/kanban.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/landing.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/mail.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/onboarding.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/pricing.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/product-detail.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/settings.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/wiki.png +0 -0
- package/vendor/aub/apps/mcp-server/dist/aub.js +15 -0
- package/vendor/aub/apps/mcp-server/dist/context.js +1 -0
- package/vendor/aub/apps/mcp-server/dist/http.js +123 -0
- package/vendor/aub/apps/mcp-server/dist/index.js +23 -0
- package/vendor/aub/apps/mcp-server/dist/repo.js +17 -0
- package/vendor/aub/apps/mcp-server/dist/schema.js +42 -0
- package/vendor/aub/apps/mcp-server/dist/server.js +80 -0
- package/vendor/aub/apps/mcp-server/dist/tools/approve-component-candidate.js +27 -0
- package/vendor/aub/apps/mcp-server/dist/tools/diff-blueprints.js +27 -0
- package/vendor/aub/apps/mcp-server/dist/tools/export-handoff.js +87 -0
- package/vendor/aub/apps/mcp-server/dist/tools/export-prompt.js +35 -0
- package/vendor/aub/apps/mcp-server/dist/tools/export-template-authoring-prompt.js +13 -0
- package/vendor/aub/apps/mcp-server/dist/tools/generate-template-from-source.js +25 -0
- package/vendor/aub/apps/mcp-server/dist/tools/get-aub-session.js +13 -0
- package/vendor/aub/apps/mcp-server/dist/tools/get-blueprint.js +28 -0
- package/vendor/aub/apps/mcp-server/dist/tools/get-project.js +45 -0
- package/vendor/aub/apps/mcp-server/dist/tools/get-workspace-status.js +10 -0
- package/vendor/aub/apps/mcp-server/dist/tools/import-design-bridge.js +62 -0
- package/vendor/aub/apps/mcp-server/dist/tools/list-blueprints.js +11 -0
- package/vendor/aub/apps/mcp-server/dist/tools/list-projects.js +11 -0
- package/vendor/aub/apps/mcp-server/dist/tools/lock-blueprint.js +33 -0
- package/vendor/aub/apps/mcp-server/dist/tools/migrate-blueprint.js +38 -0
- package/vendor/aub/apps/mcp-server/dist/tools/resolve-component.js +51 -0
- package/vendor/aub/apps/mcp-server/dist/tools/scaffold-blueprint.js +53 -0
- package/vendor/aub/apps/mcp-server/dist/tools/scan-project-ui.js +18 -0
- package/vendor/aub/apps/mcp-server/dist/tools/submit-report.js +48 -0
- package/vendor/aub/apps/mcp-server/dist/tools/update-aub-session.js +14 -0
- package/vendor/aub/apps/mcp-server/dist/tools/validate-blueprint.js +67 -0
- package/vendor/aub/apps/mcp-server/dist/tools/validate-project.js +74 -0
- package/vendor/aub/apps/mcp-server/dist/tools/write-blueprint.js +72 -0
- package/vendor/aub/apps/mcp-server/dist/workspace.js +138 -0
- package/vendor/aub/docs/agent-handoff.md +85 -0
- package/vendor/aub/docs/agent-handoff.zh-Hant.md +85 -0
- package/vendor/aub/docs/template-authoring-agent.md +86 -0
- package/vendor/aub/schema/aub-ci.schema.json +34 -0
- package/vendor/aub/schema/aub.registry.schema.json +118 -0
- package/vendor/aub/schema/design-bridge.schema.json +44 -0
- package/vendor/aub/schema/implementation-report.schema.json +93 -0
- package/vendor/aub/schema/project-types.ts +72 -0
- package/vendor/aub/schema/registry/components.json +118 -0
- package/vendor/aub/schema/types.js +13 -0
- package/vendor/aub/schema/types.ts +348 -0
- package/vendor/aub/schema/ui-blueprint-lock.schema.json +61 -0
- package/vendor/aub/schema/ui-blueprint.schema.json +1339 -0
- package/vendor/aub/schema/ui-project.schema.json +139 -0
- package/vendor/aub/scripts/agent-implementation-benchmark.lib.mjs +125 -0
- package/vendor/aub/scripts/angular-importer.lib.mjs +982 -0
- package/vendor/aub/scripts/check-editor-bundle-budget.mjs +36 -0
- package/vendor/aub/scripts/ci-verify.lib.mjs +256 -0
- package/vendor/aub/scripts/ci-verify.mjs +45 -0
- package/vendor/aub/scripts/create-authoring-kit.mjs +84 -0
- package/vendor/aub/scripts/create-implementation-report.mjs +24 -0
- package/vendor/aub/scripts/design-bridge.lib.d.mts +32 -0
- package/vendor/aub/scripts/design-bridge.lib.mjs +69 -0
- package/vendor/aub/scripts/diff-blueprint.lib.d.mts +18 -0
- package/vendor/aub/scripts/diff-blueprint.lib.mjs +148 -0
- package/vendor/aub/scripts/diff-blueprint.mjs +25 -0
- package/vendor/aub/scripts/export-agent-prompt.lib.d.mts +10 -0
- package/vendor/aub/scripts/export-agent-prompt.lib.mjs +160 -0
- package/vendor/aub/scripts/export-agent-prompt.mjs +79 -0
- package/vendor/aub/scripts/export-md.lib.d.mts +3 -0
- package/vendor/aub/scripts/export-md.lib.mjs +302 -0
- package/vendor/aub/scripts/export-md.mjs +43 -0
- package/vendor/aub/scripts/generate-registry-artifacts.lib.mjs +118 -0
- package/vendor/aub/scripts/generate-registry-artifacts.mjs +65 -0
- package/vendor/aub/scripts/generate-site-locales.mjs +545 -0
- package/vendor/aub/scripts/handoff-package.lib.d.mts +20 -0
- package/vendor/aub/scripts/handoff-package.lib.mjs +111 -0
- package/vendor/aub/scripts/implementation-report.lib.d.mts +21 -0
- package/vendor/aub/scripts/implementation-report.lib.mjs +97 -0
- package/vendor/aub/scripts/import-angular-component.mjs +72 -0
- package/vendor/aub/scripts/import-design-bridge.mjs +59 -0
- package/vendor/aub/scripts/lock-blueprint.lib.d.mts +23 -0
- package/vendor/aub/scripts/lock-blueprint.lib.mjs +58 -0
- package/vendor/aub/scripts/lock-blueprint.mjs +36 -0
- package/vendor/aub/scripts/migrate-blueprint-cli.mjs +28 -0
- package/vendor/aub/scripts/migrate-blueprint.d.mts +5 -0
- package/vendor/aub/scripts/migrate-blueprint.mjs +95 -0
- package/vendor/aub/scripts/package-workspace-cli.mjs +34 -0
- package/vendor/aub/scripts/project.lib.d.mts +44 -0
- package/vendor/aub/scripts/project.lib.mjs +175 -0
- package/vendor/aub/scripts/project.mjs +332 -0
- package/vendor/aub/scripts/registry.lib.d.mts +52 -0
- package/vendor/aub/scripts/registry.lib.mjs +222 -0
- package/vendor/aub/scripts/run-agent-implementation.mjs +423 -0
- package/vendor/aub/scripts/run-agent-readability.mjs +145 -0
- package/vendor/aub/scripts/run-ollama-prompt.mjs +30 -0
- package/vendor/aub/scripts/scaffold-blueprint.lib.d.mts +38 -0
- package/vendor/aub/scripts/scaffold-blueprint.lib.mjs +316 -0
- package/vendor/aub/scripts/scaffold-blueprint.mjs +86 -0
- package/vendor/aub/scripts/score-agent-implementation.mjs +27 -0
- package/vendor/aub/scripts/score-agent-readability.mjs +54 -0
- package/vendor/aub/scripts/sync-brand-assets.mjs +33 -0
- package/vendor/aub/scripts/validate-blueprint.lib.d.mts +14 -0
- package/vendor/aub/scripts/validate-blueprint.lib.mjs +136 -0
- package/vendor/aub/scripts/validate.mjs +128 -0
- package/vendor/aub/scripts/verify-implementation-report.mjs +36 -0
- package/vendor/aub/scripts/workspace-loop.lib.d.mts +17 -0
- package/vendor/aub/scripts/workspace-loop.lib.mjs +674 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Single bridge to the repository's pure-function libraries in `scripts/`.
|
|
2
|
+
// All relative paths to scripts/*.lib.mjs live here so emitted dist depth stays predictable.
|
|
3
|
+
export { exportMarkdown } from '../../../scripts/export-md.lib.mjs';
|
|
4
|
+
export { exportAgentPrompt, supportedAgentAdapters, supportedAgentTasks, } from '../../../scripts/export-agent-prompt.lib.mjs';
|
|
5
|
+
export { validateBlueprintSemantics } from '../../../scripts/validate-blueprint.lib.mjs';
|
|
6
|
+
export { buildKnownTypes } from '../../../scripts/registry.lib.mjs';
|
|
7
|
+
export { diffBlueprints } from '../../../scripts/diff-blueprint.lib.mjs';
|
|
8
|
+
export { migrateBlueprint } from '../../../scripts/migrate-blueprint.mjs';
|
|
9
|
+
export { createBlueprintLock } from '../../../scripts/lock-blueprint.lib.mjs';
|
|
10
|
+
export { createHandoffArchive } from '../../../scripts/handoff-package.lib.mjs';
|
|
11
|
+
export { importDesignBridge, DESIGN_BRIDGE_VERSION } from '../../../scripts/design-bridge.lib.mjs';
|
|
12
|
+
export { scaffoldBlueprint, SCAFFOLD_SECTIONS } from '../../../scripts/scaffold-blueprint.lib.mjs';
|
|
13
|
+
export { createImplementationReportTemplate, verifyImplementationReport, } from '../../../scripts/implementation-report.lib.mjs';
|
|
14
|
+
export { loadProject, validateProjectSemantics, parseProjectText, mergeDesignSystem, PROJECT_VERSION, } from '../../../scripts/project.lib.mjs';
|
|
15
|
+
export { approveComponentCandidate, generateTemplateFromSource, getWorkspaceStatus, readAubSession, scanProjectUi, templateAuthoringPrompt, updateAubSession, } from '../../../scripts/workspace-loop.lib.mjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { createMcpExpressApp } from '@modelcontextprotocol/sdk/server/express.js';
|
|
5
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
6
|
+
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
7
|
+
import express from 'express';
|
|
8
|
+
import { loadValidators } from './schema.js';
|
|
9
|
+
import { createAubServer, registeredToolNames, runAubTool } from './server.js';
|
|
10
|
+
function option(name) {
|
|
11
|
+
const index = process.argv.indexOf(name);
|
|
12
|
+
return index >= 0 ? process.argv[index + 1] : undefined;
|
|
13
|
+
}
|
|
14
|
+
function resolveConfig() {
|
|
15
|
+
const positional = process.argv[2]?.startsWith('--') ? undefined : process.argv[2];
|
|
16
|
+
const root = resolve(option('--workspace') ?? positional ?? process.env.AUB_WORKSPACE ?? process.cwd());
|
|
17
|
+
const host = option('--host') ?? process.env.AUB_HOST ?? '127.0.0.1';
|
|
18
|
+
const port = Number(option('--port') ?? process.env.AUB_PORT ?? 3100);
|
|
19
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
20
|
+
throw new Error(`Invalid port: ${String(port)}`);
|
|
21
|
+
}
|
|
22
|
+
return { root, host, port };
|
|
23
|
+
}
|
|
24
|
+
async function main() {
|
|
25
|
+
const { root, host, port } = resolveConfig();
|
|
26
|
+
const validators = await loadValidators();
|
|
27
|
+
const ctx = { root, validators };
|
|
28
|
+
const app = createMcpExpressApp({ host });
|
|
29
|
+
const transports = new Map();
|
|
30
|
+
app.use(express.json({ limit: '20mb' }));
|
|
31
|
+
app.use((req, res, next) => {
|
|
32
|
+
const origin = req.headers.origin;
|
|
33
|
+
if (origin && /^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/.test(origin)) {
|
|
34
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
35
|
+
}
|
|
36
|
+
else if (origin === 'https://henrylau1103.github.io') {
|
|
37
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
38
|
+
}
|
|
39
|
+
res.setHeader('Vary', 'Origin');
|
|
40
|
+
res.setHeader('Access-Control-Allow-Headers', 'content-type, mcp-session-id');
|
|
41
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
|
|
42
|
+
if (req.method === 'OPTIONS') {
|
|
43
|
+
res.status(204).end();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
next();
|
|
47
|
+
});
|
|
48
|
+
app.get('/health', (_req, res) => {
|
|
49
|
+
res.json({
|
|
50
|
+
status: 'ok',
|
|
51
|
+
service: 'aub-mcp-server',
|
|
52
|
+
version: '0.3.0',
|
|
53
|
+
workspace: root,
|
|
54
|
+
tools: registeredToolNames(),
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
app.post('/rpc', async (req, res) => {
|
|
58
|
+
try {
|
|
59
|
+
const tool = String(req.body?.tool ?? '');
|
|
60
|
+
const args = req.body?.args ?? {};
|
|
61
|
+
const result = await runAubTool(ctx, tool, args);
|
|
62
|
+
res.json({ ok: true, result });
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
res.status(400).json({
|
|
66
|
+
ok: false,
|
|
67
|
+
error: error instanceof Error ? error.message : String(error),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
app.all('/mcp', async (req, res) => {
|
|
72
|
+
try {
|
|
73
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
74
|
+
let transport = typeof sessionId === 'string' ? transports.get(sessionId) : undefined;
|
|
75
|
+
if (!transport && req.method === 'POST' && isInitializeRequest(req.body)) {
|
|
76
|
+
transport = new StreamableHTTPServerTransport({
|
|
77
|
+
sessionIdGenerator: () => randomUUID(),
|
|
78
|
+
onsessioninitialized: (id) => {
|
|
79
|
+
transports.set(id, transport);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
transport.onclose = () => {
|
|
83
|
+
if (transport?.sessionId)
|
|
84
|
+
transports.delete(transport.sessionId);
|
|
85
|
+
};
|
|
86
|
+
await createAubServer(ctx).connect(transport);
|
|
87
|
+
}
|
|
88
|
+
if (!transport) {
|
|
89
|
+
res.status(400).json({
|
|
90
|
+
jsonrpc: '2.0',
|
|
91
|
+
error: { code: -32000, message: 'A valid MCP session is required.' },
|
|
92
|
+
id: null,
|
|
93
|
+
});
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
await transport.handleRequest(req, res, req.body);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
console.error('AUB MCP HTTP request failed:', error);
|
|
100
|
+
if (!res.headersSent) {
|
|
101
|
+
res.status(500).json({
|
|
102
|
+
jsonrpc: '2.0',
|
|
103
|
+
error: { code: -32603, message: 'Internal server error' },
|
|
104
|
+
id: null,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
const listener = app.listen(port, host, () => {
|
|
110
|
+
console.error(`aub-mcp-server HTTP ready at http://${host}:${port}/mcp (workspace: ${root})`);
|
|
111
|
+
});
|
|
112
|
+
const shutdown = async () => {
|
|
113
|
+
for (const transport of transports.values())
|
|
114
|
+
await transport.close();
|
|
115
|
+
listener.close(() => process.exit(0));
|
|
116
|
+
};
|
|
117
|
+
process.on('SIGINT', shutdown);
|
|
118
|
+
process.on('SIGTERM', shutdown);
|
|
119
|
+
}
|
|
120
|
+
main().catch((error) => {
|
|
121
|
+
console.error(error);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { loadValidators } from './schema.js';
|
|
5
|
+
import { createAubServer } from './server.js';
|
|
6
|
+
export function resolveWorkspaceRoot() {
|
|
7
|
+
const fromArg = process.argv[2];
|
|
8
|
+
const fromEnv = process.env.AUB_WORKSPACE;
|
|
9
|
+
return resolve(fromArg ?? fromEnv ?? process.cwd());
|
|
10
|
+
}
|
|
11
|
+
async function main() {
|
|
12
|
+
const root = resolveWorkspaceRoot();
|
|
13
|
+
const validators = await loadValidators();
|
|
14
|
+
const ctx = { root, validators };
|
|
15
|
+
const server = createAubServer(ctx);
|
|
16
|
+
const transport = new StdioServerTransport();
|
|
17
|
+
await server.connect(transport);
|
|
18
|
+
console.error(`aub-mcp-server ready (workspace: ${root})`);
|
|
19
|
+
}
|
|
20
|
+
main().catch((error) => {
|
|
21
|
+
console.error(error);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
// Walk up from this module to find the AUB repository root (the directory that
|
|
5
|
+
// owns schema/ui-blueprint.schema.json). Works from both src/ and dist/ layouts.
|
|
6
|
+
export function findRepoRoot() {
|
|
7
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
for (let i = 0; i < 12; i += 1) {
|
|
9
|
+
if (existsSync(join(dir, 'schema', 'ui-blueprint.schema.json')))
|
|
10
|
+
return dir;
|
|
11
|
+
const parent = dirname(dir);
|
|
12
|
+
if (parent === dir)
|
|
13
|
+
break;
|
|
14
|
+
dir = parent;
|
|
15
|
+
}
|
|
16
|
+
throw new Error('Could not locate AUB repo root (schema/ui-blueprint.schema.json not found).');
|
|
17
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import AjvModule from 'ajv/dist/2020.js';
|
|
4
|
+
import addFormatsModule from 'ajv-formats';
|
|
5
|
+
import { findRepoRoot } from './repo.js';
|
|
6
|
+
// ajv and ajv-formats ship as CJS; normalize the default export across loaders.
|
|
7
|
+
const Ajv2020 = (AjvModule.default ?? AjvModule);
|
|
8
|
+
const addFormats = (addFormatsModule.default ?? addFormatsModule);
|
|
9
|
+
let cached = null;
|
|
10
|
+
export async function loadValidators() {
|
|
11
|
+
if (cached)
|
|
12
|
+
return cached;
|
|
13
|
+
const root = findRepoRoot();
|
|
14
|
+
const [blueprintRaw, reportRaw, projectRaw, designBridgeRaw] = await Promise.all([
|
|
15
|
+
readFile(join(root, 'schema', 'ui-blueprint.schema.json'), 'utf8'),
|
|
16
|
+
readFile(join(root, 'schema', 'implementation-report.schema.json'), 'utf8'),
|
|
17
|
+
readFile(join(root, 'schema', 'ui-project.schema.json'), 'utf8'),
|
|
18
|
+
readFile(join(root, 'schema', 'design-bridge.schema.json'), 'utf8'),
|
|
19
|
+
]);
|
|
20
|
+
const blueprintSchema = JSON.parse(blueprintRaw);
|
|
21
|
+
const reportSchema = JSON.parse(reportRaw);
|
|
22
|
+
const projectSchema = JSON.parse(projectRaw);
|
|
23
|
+
const designBridgeSchema = JSON.parse(designBridgeRaw);
|
|
24
|
+
const ajv = new Ajv2020({ allErrors: true, strict: true });
|
|
25
|
+
addFormats(ajv);
|
|
26
|
+
const validateBlueprint = ajv.compile(blueprintSchema);
|
|
27
|
+
cached = {
|
|
28
|
+
validateBlueprint,
|
|
29
|
+
validateReport: ajv.compile(reportSchema),
|
|
30
|
+
validateProject: ajv.compile(projectSchema),
|
|
31
|
+
validateDesignBridge: ajv.compile(designBridgeSchema),
|
|
32
|
+
reportSchema,
|
|
33
|
+
};
|
|
34
|
+
return cached;
|
|
35
|
+
}
|
|
36
|
+
export function formatAjvErrors(validate) {
|
|
37
|
+
return (validate.errors ?? []).map((err) => {
|
|
38
|
+
const path = err.instancePath || '(root)';
|
|
39
|
+
const params = err.params ? ` ${JSON.stringify(err.params)}` : '';
|
|
40
|
+
return `${path} ${err.message ?? 'invalid'}${params}`.trim();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import * as listBlueprints from './tools/list-blueprints.js';
|
|
3
|
+
import * as getBlueprint from './tools/get-blueprint.js';
|
|
4
|
+
import * as validateBlueprint from './tools/validate-blueprint.js';
|
|
5
|
+
import * as scaffoldBlueprint from './tools/scaffold-blueprint.js';
|
|
6
|
+
import * as importDesignBridge from './tools/import-design-bridge.js';
|
|
7
|
+
import * as writeBlueprint from './tools/write-blueprint.js';
|
|
8
|
+
import * as exportPrompt from './tools/export-prompt.js';
|
|
9
|
+
import * as exportHandoff from './tools/export-handoff.js';
|
|
10
|
+
import * as submitReport from './tools/submit-report.js';
|
|
11
|
+
import * as listProjects from './tools/list-projects.js';
|
|
12
|
+
import * as getProject from './tools/get-project.js';
|
|
13
|
+
import * as validateProject from './tools/validate-project.js';
|
|
14
|
+
import * as resolveComponent from './tools/resolve-component.js';
|
|
15
|
+
import * as diffBlueprints from './tools/diff-blueprints.js';
|
|
16
|
+
import * as migrateBlueprint from './tools/migrate-blueprint.js';
|
|
17
|
+
import * as lockBlueprint from './tools/lock-blueprint.js';
|
|
18
|
+
import * as getAubSession from './tools/get-aub-session.js';
|
|
19
|
+
import * as updateAubSession from './tools/update-aub-session.js';
|
|
20
|
+
import * as getWorkspaceStatus from './tools/get-workspace-status.js';
|
|
21
|
+
import * as scanProjectUi from './tools/scan-project-ui.js';
|
|
22
|
+
import * as generateTemplateFromSource from './tools/generate-template-from-source.js';
|
|
23
|
+
import * as approveComponentCandidate from './tools/approve-component-candidate.js';
|
|
24
|
+
import * as exportTemplateAuthoringPrompt from './tools/export-template-authoring-prompt.js';
|
|
25
|
+
const tools = [
|
|
26
|
+
listBlueprints,
|
|
27
|
+
getBlueprint,
|
|
28
|
+
validateBlueprint,
|
|
29
|
+
scaffoldBlueprint,
|
|
30
|
+
importDesignBridge,
|
|
31
|
+
writeBlueprint,
|
|
32
|
+
exportPrompt,
|
|
33
|
+
exportHandoff,
|
|
34
|
+
submitReport,
|
|
35
|
+
listProjects,
|
|
36
|
+
getProject,
|
|
37
|
+
validateProject,
|
|
38
|
+
resolveComponent,
|
|
39
|
+
diffBlueprints,
|
|
40
|
+
migrateBlueprint,
|
|
41
|
+
lockBlueprint,
|
|
42
|
+
getAubSession,
|
|
43
|
+
updateAubSession,
|
|
44
|
+
getWorkspaceStatus,
|
|
45
|
+
scanProjectUi,
|
|
46
|
+
generateTemplateFromSource,
|
|
47
|
+
approveComponentCandidate,
|
|
48
|
+
exportTemplateAuthoringPrompt,
|
|
49
|
+
];
|
|
50
|
+
function ok(payload) {
|
|
51
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
52
|
+
}
|
|
53
|
+
function fail(error) {
|
|
54
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
55
|
+
return { content: [{ type: 'text', text: JSON.stringify({ error: message }, null, 2) }], isError: true };
|
|
56
|
+
}
|
|
57
|
+
export function createAubServer(ctx) {
|
|
58
|
+
const server = new McpServer({ name: 'aub-mcp-server', version: '0.3.0' });
|
|
59
|
+
for (const tool of tools) {
|
|
60
|
+
server.registerTool(tool.name, tool.config, async (args) => {
|
|
61
|
+
try {
|
|
62
|
+
return ok(await tool.run(ctx, args));
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return fail(error);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return server;
|
|
70
|
+
}
|
|
71
|
+
export function registeredToolNames() {
|
|
72
|
+
return tools.map((tool) => tool.name);
|
|
73
|
+
}
|
|
74
|
+
export async function runAubTool(ctx, name, args = {}) {
|
|
75
|
+
const tool = tools.find((candidate) => candidate.name === name);
|
|
76
|
+
if (!tool) {
|
|
77
|
+
throw new Error(`Unknown AUB tool "${name}". Available: ${registeredToolNames().join(', ')}.`);
|
|
78
|
+
}
|
|
79
|
+
return tool.run(ctx, args);
|
|
80
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { approveComponentCandidate } from '../aub.js';
|
|
3
|
+
export const name = 'approve_component_candidate';
|
|
4
|
+
const inputSchema = {
|
|
5
|
+
id: z.string().describe('Component candidate id from .aub/component-candidates.json.'),
|
|
6
|
+
action: z
|
|
7
|
+
.enum(['create_extension', 'map_core', 'ignore'])
|
|
8
|
+
.describe('Review decision. create_extension writes aub.registry.json; map_core and ignore only update the candidate record.'),
|
|
9
|
+
coreType: z.string().optional().describe('Core AUB component type when action is map_core.'),
|
|
10
|
+
namespacedType: z.string().optional().describe('Approved team:component type when action is create_extension.'),
|
|
11
|
+
isContainer: z.boolean().optional().describe('Container behavior override for create_extension.'),
|
|
12
|
+
description: z.string().optional().describe('Description override for the extension entry.'),
|
|
13
|
+
module: z.string().optional().describe('Production module/source override for the extension implementation.'),
|
|
14
|
+
export: z.string().optional().describe('Production export symbol override for the extension implementation.'),
|
|
15
|
+
importStyle: z
|
|
16
|
+
.enum(['named', 'default', 'namespace', 'side-effect', 'custom-element'])
|
|
17
|
+
.optional()
|
|
18
|
+
.describe('Production import style override for the extension implementation.'),
|
|
19
|
+
};
|
|
20
|
+
export const config = {
|
|
21
|
+
title: 'Approve Component Candidate',
|
|
22
|
+
description: 'Review a scanned custom component candidate. Only create_extension writes aub.registry.json; other decisions stay in .aub/component-candidates.json.',
|
|
23
|
+
inputSchema,
|
|
24
|
+
};
|
|
25
|
+
export async function run(ctx, args) {
|
|
26
|
+
return approveComponentCandidate(ctx.root, args ?? {});
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { resolveBlueprint } from '../workspace.js';
|
|
3
|
+
import { diffBlueprints } from '../aub.js';
|
|
4
|
+
export const name = 'diff_blueprints';
|
|
5
|
+
const inputSchema = {
|
|
6
|
+
before: z.string().describe('Baseline Blueprint file path or screen id.'),
|
|
7
|
+
after: z.string().describe('Updated Blueprint file path or screen id.'),
|
|
8
|
+
};
|
|
9
|
+
export const config = {
|
|
10
|
+
title: 'Diff Blueprints',
|
|
11
|
+
description: 'Compare two Blueprint revisions and return structural changes across nodes, interactions, responsive rules, acceptance, viewports, and design tokens.',
|
|
12
|
+
inputSchema,
|
|
13
|
+
};
|
|
14
|
+
export async function run(ctx, args) {
|
|
15
|
+
if (!args.before || !args.after) {
|
|
16
|
+
throw new Error('Provide both "before" and "after" Blueprint refs.');
|
|
17
|
+
}
|
|
18
|
+
const [before, after] = await Promise.all([
|
|
19
|
+
resolveBlueprint(ctx.root, args.before),
|
|
20
|
+
resolveBlueprint(ctx.root, args.after),
|
|
21
|
+
]);
|
|
22
|
+
return {
|
|
23
|
+
beforePath: before.entry.path,
|
|
24
|
+
afterPath: after.entry.path,
|
|
25
|
+
diff: diffBlueprints(before.blueprint, after.blueprint),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { buildKnownTypes, createHandoffArchive, createImplementationReportTemplate, exportAgentPrompt, exportMarkdown, validateBlueprintSemantics, } from '../aub.js';
|
|
6
|
+
import { findRepoRoot } from '../repo.js';
|
|
7
|
+
import { formatAjvErrors } from '../schema.js';
|
|
8
|
+
import { resolveBlueprint, resolveWorkspacePath } from '../workspace.js';
|
|
9
|
+
export const name = 'export_handoff';
|
|
10
|
+
const inputSchema = {
|
|
11
|
+
ref: z.string().describe('Blueprint file path or screen id.'),
|
|
12
|
+
output: z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe('Destination .aub.zip path inside the workspace. Defaults to .aub/handoffs/<screen-id>.aub.zip.'),
|
|
16
|
+
registry: z.string().optional().describe('Optional aub.registry.json path to include and validate.'),
|
|
17
|
+
overwrite: z.boolean().optional().describe('Replace an existing package. Defaults to false.'),
|
|
18
|
+
viewportImages: z
|
|
19
|
+
.record(z.string())
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Optional map of viewport id to PNG data URL for screenshot evidence.'),
|
|
22
|
+
};
|
|
23
|
+
export const config = {
|
|
24
|
+
title: 'Export Handoff Package',
|
|
25
|
+
description: 'Validate a Blueprint and write a complete .aub.zip agent handoff package inside the workspace, including prompts, report contract, optional component registry, and optional viewport screenshots.',
|
|
26
|
+
inputSchema,
|
|
27
|
+
};
|
|
28
|
+
async function exists(path) {
|
|
29
|
+
try {
|
|
30
|
+
await access(path);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function run(ctx, args) {
|
|
38
|
+
if (!args.ref)
|
|
39
|
+
throw new Error('Provide a Blueprint "ref".');
|
|
40
|
+
const { blueprint, entry } = await resolveBlueprint(ctx.root, args.ref);
|
|
41
|
+
const schemaOk = ctx.validators.validateBlueprint(blueprint);
|
|
42
|
+
const schemaErrors = schemaOk ? [] : formatAjvErrors(ctx.validators.validateBlueprint);
|
|
43
|
+
const knownTypes = await buildKnownTypes({
|
|
44
|
+
extensionPath: args.registry ? resolveWorkspacePath(ctx.root, args.registry) : null,
|
|
45
|
+
startDir: dirname(entry.absPath),
|
|
46
|
+
});
|
|
47
|
+
const semanticErrors = schemaOk
|
|
48
|
+
? validateBlueprintSemantics(blueprint, { knownTypes: knownTypes.knownTypes })
|
|
49
|
+
: [];
|
|
50
|
+
if (!schemaOk || semanticErrors.length > 0) {
|
|
51
|
+
throw new Error(`Blueprint validation failed:\n${[...schemaErrors, ...semanticErrors].map((item) => `- ${item}`).join('\n')}`);
|
|
52
|
+
}
|
|
53
|
+
const outputRef = args.output ?? `.aub/handoffs/${blueprint.screen.id}.aub.zip`;
|
|
54
|
+
if (!outputRef.endsWith('.aub.zip'))
|
|
55
|
+
throw new Error('Handoff output must end in .aub.zip.');
|
|
56
|
+
const outputPath = resolveWorkspacePath(ctx.root, outputRef);
|
|
57
|
+
if (!args.overwrite && (await exists(outputPath))) {
|
|
58
|
+
throw new Error(`Refusing to overwrite existing file: ${outputRef}`);
|
|
59
|
+
}
|
|
60
|
+
const repoRoot = findRepoRoot();
|
|
61
|
+
const [agentGuide, agentGuideZhHant, extensionRegistry] = await Promise.all([
|
|
62
|
+
readFile(resolve(repoRoot, 'docs/agent-handoff.md'), 'utf8'),
|
|
63
|
+
readFile(resolve(repoRoot, 'docs/agent-handoff.zh-Hant.md'), 'utf8'),
|
|
64
|
+
knownTypes.extensionPath ? readFile(knownTypes.extensionPath, 'utf8') : Promise.resolve(undefined),
|
|
65
|
+
]);
|
|
66
|
+
const { bytes, manifest } = await createHandoffArchive({
|
|
67
|
+
blueprint,
|
|
68
|
+
markdown: exportMarkdown(blueprint),
|
|
69
|
+
genericPrompt: exportAgentPrompt(blueprint, { adapter: 'generic', task: 'implement' }),
|
|
70
|
+
codexPrompt: exportAgentPrompt(blueprint, { adapter: 'codex', task: 'implement' }),
|
|
71
|
+
agentGuide,
|
|
72
|
+
agentGuideZhHant,
|
|
73
|
+
reportTemplate: createImplementationReportTemplate(blueprint),
|
|
74
|
+
reportSchema: ctx.validators.reportSchema,
|
|
75
|
+
viewportImages: args.viewportImages ?? {},
|
|
76
|
+
extensionRegistry,
|
|
77
|
+
});
|
|
78
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
79
|
+
await writeFile(outputPath, bytes);
|
|
80
|
+
return {
|
|
81
|
+
savedPath: relative(ctx.root, outputPath).split(sep).join('/'),
|
|
82
|
+
screenId: blueprint.screen.id,
|
|
83
|
+
bytes: bytes.byteLength,
|
|
84
|
+
sha256: createHash('sha256').update(bytes).digest('hex'),
|
|
85
|
+
manifest,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { resolveBlueprint } from '../workspace.js';
|
|
3
|
+
import { exportAgentPrompt, supportedAgentAdapters, supportedAgentTasks } from '../aub.js';
|
|
4
|
+
export const name = 'export_prompt';
|
|
5
|
+
const inputSchema = {
|
|
6
|
+
ref: z.string().describe('Blueprint file path or screen id.'),
|
|
7
|
+
adapter: z
|
|
8
|
+
.string()
|
|
9
|
+
.optional()
|
|
10
|
+
.describe('Agent adapter: generic | codex | claude-code | copilot. Defaults to generic.'),
|
|
11
|
+
task: z
|
|
12
|
+
.string()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe('Prompt task: author | plan | implement | review. Defaults to implement.'),
|
|
15
|
+
};
|
|
16
|
+
export const config = {
|
|
17
|
+
title: 'Export Agent Prompt',
|
|
18
|
+
description: 'Generate an agent-ready prompt (with embedded Blueprint context) for a given adapter and task.',
|
|
19
|
+
inputSchema,
|
|
20
|
+
};
|
|
21
|
+
export async function run(ctx, args) {
|
|
22
|
+
const adapter = args.adapter ?? 'generic';
|
|
23
|
+
const task = args.task ?? 'implement';
|
|
24
|
+
const adapters = supportedAgentAdapters();
|
|
25
|
+
const tasks = supportedAgentTasks();
|
|
26
|
+
if (!adapters.includes(adapter)) {
|
|
27
|
+
throw new Error(`Unknown adapter "${adapter}". Supported: ${adapters.join(', ')}.`);
|
|
28
|
+
}
|
|
29
|
+
if (!tasks.includes(task)) {
|
|
30
|
+
throw new Error(`Unknown task "${task}". Supported: ${tasks.join(', ')}.`);
|
|
31
|
+
}
|
|
32
|
+
const { blueprint, entry } = await resolveBlueprint(ctx.root, args.ref);
|
|
33
|
+
const prompt = exportAgentPrompt(blueprint, { adapter, task });
|
|
34
|
+
return { screenId: entry.screenId, path: entry.path, adapter, task, prompt };
|
|
35
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { templateAuthoringPrompt } from '../aub.js';
|
|
2
|
+
export const name = 'export_template_authoring_prompt';
|
|
3
|
+
export const config = {
|
|
4
|
+
title: 'Export Template Authoring Prompt',
|
|
5
|
+
description: 'Return the agent-facing contract for scanning existing apps into AUB workspace templates and component candidates.',
|
|
6
|
+
inputSchema: {},
|
|
7
|
+
};
|
|
8
|
+
export async function run(_ctx) {
|
|
9
|
+
return {
|
|
10
|
+
format: 'markdown',
|
|
11
|
+
prompt: templateAuthoringPrompt(),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { generateTemplateFromSource } from '../aub.js';
|
|
3
|
+
export const name = 'generate_template_from_source';
|
|
4
|
+
const inputSchema = {
|
|
5
|
+
sourcePath: z.string().describe('Workspace-relative route or component source file path.'),
|
|
6
|
+
name: z.string().optional().describe('Template display name. Defaults to the source filename.'),
|
|
7
|
+
id: z.string().optional().describe('Stable template id. Defaults to a slug derived from framework and name.'),
|
|
8
|
+
category: z.string().optional().describe('Template category. Defaults to workspace.'),
|
|
9
|
+
framework: z.string().optional().describe('Framework label. Defaults to path-based inference.'),
|
|
10
|
+
route: z.string().optional().describe('Application route represented by the source. Defaults to path-based inference.'),
|
|
11
|
+
sourceKind: z.string().optional().describe('Source kind such as route or component. Defaults to source-file.'),
|
|
12
|
+
output: z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe('Destination .aub.template.json path inside the workspace. Defaults to .aub/templates/<id>.aub.template.json.'),
|
|
16
|
+
status: z.enum(['candidate', 'approved']).optional().describe('Initial template status. Defaults to candidate.'),
|
|
17
|
+
};
|
|
18
|
+
export const config = {
|
|
19
|
+
title: 'Generate Template From Source',
|
|
20
|
+
description: 'Generate a candidate AUB workspace template from a static route/component source file and save it under .aub/templates.',
|
|
21
|
+
inputSchema,
|
|
22
|
+
};
|
|
23
|
+
export async function run(ctx, args) {
|
|
24
|
+
return generateTemplateFromSource(ctx.root, args ?? {});
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { readAubSession } from '../aub.js';
|
|
2
|
+
export const name = 'get_aub_session';
|
|
3
|
+
export const config = {
|
|
4
|
+
title: 'Get AUB Session',
|
|
5
|
+
description: 'Read .aub/session.json so an agent can see which Blueprint/project/preview route the user is actively editing.',
|
|
6
|
+
inputSchema: {},
|
|
7
|
+
};
|
|
8
|
+
export async function run(ctx) {
|
|
9
|
+
return {
|
|
10
|
+
path: '.aub/session.json',
|
|
11
|
+
session: await readAubSession(ctx.root),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import yaml from 'js-yaml';
|
|
3
|
+
import { resolveBlueprint } from '../workspace.js';
|
|
4
|
+
import { exportMarkdown } from '../aub.js';
|
|
5
|
+
export const name = 'get_blueprint';
|
|
6
|
+
const inputSchema = {
|
|
7
|
+
ref: z.string().describe('Blueprint file path (relative to the workspace root) or screen id.'),
|
|
8
|
+
format: z
|
|
9
|
+
.enum(['json', 'yaml', 'markdown'])
|
|
10
|
+
.optional()
|
|
11
|
+
.describe('Output format. Defaults to json. markdown returns the derived .ui.md agent context.'),
|
|
12
|
+
};
|
|
13
|
+
export const config = {
|
|
14
|
+
title: 'Get Blueprint',
|
|
15
|
+
description: 'Resolve a Blueprint by file path or screen id and return it as JSON, YAML, or derived Markdown agent context.',
|
|
16
|
+
inputSchema,
|
|
17
|
+
};
|
|
18
|
+
export async function run(ctx, args) {
|
|
19
|
+
const { blueprint, entry } = await resolveBlueprint(ctx.root, args.ref);
|
|
20
|
+
const format = args.format ?? 'json';
|
|
21
|
+
if (format === 'markdown') {
|
|
22
|
+
return { format, path: entry.path, screenId: entry.screenId, content: exportMarkdown(blueprint) };
|
|
23
|
+
}
|
|
24
|
+
if (format === 'yaml') {
|
|
25
|
+
return { format, path: entry.path, screenId: entry.screenId, content: yaml.dump(blueprint) };
|
|
26
|
+
}
|
|
27
|
+
return { format, path: entry.path, screenId: entry.screenId, blueprint };
|
|
28
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { relative, sep } from 'node:path';
|
|
3
|
+
import { resolveProjectRef } from '../workspace.js';
|
|
4
|
+
import { loadProject, mergeDesignSystem } from '../aub.js';
|
|
5
|
+
export const name = 'get_project';
|
|
6
|
+
const inputSchema = {
|
|
7
|
+
ref: z.string().describe('Project file path (relative to the workspace root) or project id.'),
|
|
8
|
+
inlineScreens: z
|
|
9
|
+
.boolean()
|
|
10
|
+
.optional()
|
|
11
|
+
.describe('When true, include each member screen Blueprint inline along with its merged design system. Defaults to false (refs only).'),
|
|
12
|
+
};
|
|
13
|
+
export const config = {
|
|
14
|
+
title: 'Get Project',
|
|
15
|
+
description: 'Resolve a multi-screen project by file path or id and return its metadata plus member screens. Pass inlineScreens to embed each full member Blueprint.',
|
|
16
|
+
inputSchema,
|
|
17
|
+
};
|
|
18
|
+
export async function run(ctx, args) {
|
|
19
|
+
if (!args.ref) {
|
|
20
|
+
throw new Error('Provide a project "ref" (file path or project id).');
|
|
21
|
+
}
|
|
22
|
+
const { projectPath } = await resolveProjectRef(ctx.root, args.ref);
|
|
23
|
+
const loaded = await loadProject(projectPath);
|
|
24
|
+
const inline = args.inlineScreens === true;
|
|
25
|
+
const screens = loaded.screens.map((screen) => {
|
|
26
|
+
const base = {
|
|
27
|
+
id: screen.ref?.id ?? '',
|
|
28
|
+
name: screen.ref?.name ?? '',
|
|
29
|
+
path: screen.path,
|
|
30
|
+
loaded: screen.blueprint != null,
|
|
31
|
+
};
|
|
32
|
+
if (inline && screen.blueprint) {
|
|
33
|
+
base.blueprint = screen.blueprint;
|
|
34
|
+
base.mergedDesignSystem = mergeDesignSystem(loaded.project, screen.blueprint);
|
|
35
|
+
}
|
|
36
|
+
return base;
|
|
37
|
+
});
|
|
38
|
+
const source = relative(ctx.root, loaded.projectPath).split(sep).join('/');
|
|
39
|
+
return {
|
|
40
|
+
source,
|
|
41
|
+
project: loaded.project,
|
|
42
|
+
screens,
|
|
43
|
+
loadErrors: loaded.errors,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getWorkspaceStatus } from '../aub.js';
|
|
2
|
+
export const name = 'get_workspace_status';
|
|
3
|
+
export const config = {
|
|
4
|
+
title: 'Get Workspace Status',
|
|
5
|
+
description: 'Return AUB workspace-loop status: detected frameworks/routes, current session, workspace templates, and component candidates.',
|
|
6
|
+
inputSchema: {},
|
|
7
|
+
};
|
|
8
|
+
export async function run(ctx) {
|
|
9
|
+
return getWorkspaceStatus(ctx.root);
|
|
10
|
+
}
|