@a-company/paradigm 3.21.0 → 3.23.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/dist/graph-5VSRBRKZ.js +163 -0
- package/dist/graph-server-BZ73HTAT.js +251 -0
- package/dist/index.js +8 -0
- package/dist/mcp.js +277 -16
- package/graph-ui/dist/assets/index-BlgXTl53.css +1 -0
- package/graph-ui/dist/assets/index-Bq5nXK8p.js +63 -0
- package/graph-ui/dist/index.html +13 -0
- package/package.json +4 -2
package/dist/mcp.js
CHANGED
|
@@ -2026,7 +2026,7 @@ function registerResources(server, getContext2) {
|
|
|
2026
2026
|
|
|
2027
2027
|
// ../paradigm-mcp/src/tools/index.ts
|
|
2028
2028
|
import * as os3 from "os";
|
|
2029
|
-
import * as
|
|
2029
|
+
import * as path26 from "path";
|
|
2030
2030
|
import {
|
|
2031
2031
|
ListToolsRequestSchema,
|
|
2032
2032
|
CallToolRequestSchema
|
|
@@ -2790,7 +2790,7 @@ function navigateExplore(config, target, rootDir) {
|
|
|
2790
2790
|
}
|
|
2791
2791
|
if (result.paths.length === 0) {
|
|
2792
2792
|
const areaSymbols = Object.entries(config.symbols).filter(
|
|
2793
|
-
([sym,
|
|
2793
|
+
([sym, path27]) => sym.toLowerCase().includes(targetLower) || path27.toLowerCase().includes(targetLower)
|
|
2794
2794
|
).slice(0, 10);
|
|
2795
2795
|
result.paths = [...new Set(areaSymbols.map(([, p]) => p))];
|
|
2796
2796
|
result.symbols = areaSymbols.map(([s]) => s);
|
|
@@ -11288,8 +11288,8 @@ function generateRunId() {
|
|
|
11288
11288
|
var TEMPLATE_REGEX = /\{\{([^}]+)\}\}/g;
|
|
11289
11289
|
function interpolate(value, scope) {
|
|
11290
11290
|
if (typeof value === "string") {
|
|
11291
|
-
return value.replace(TEMPLATE_REGEX, (_match,
|
|
11292
|
-
const resolved = resolvePath(
|
|
11291
|
+
return value.replace(TEMPLATE_REGEX, (_match, path27) => {
|
|
11292
|
+
const resolved = resolvePath(path27.trim(), scope);
|
|
11293
11293
|
return resolved !== void 0 ? String(resolved) : _match;
|
|
11294
11294
|
});
|
|
11295
11295
|
}
|
|
@@ -11322,8 +11322,8 @@ function resolvePath(dotPath, scope) {
|
|
|
11322
11322
|
return void 0;
|
|
11323
11323
|
}
|
|
11324
11324
|
}
|
|
11325
|
-
function deepGet(obj,
|
|
11326
|
-
const parts =
|
|
11325
|
+
function deepGet(obj, path27) {
|
|
11326
|
+
const parts = path27.split(/[.\[\]]+/).filter(Boolean);
|
|
11327
11327
|
let current = obj;
|
|
11328
11328
|
for (const part of parts) {
|
|
11329
11329
|
if (current == null || typeof current !== "object") return void 0;
|
|
@@ -11559,11 +11559,11 @@ async function runPersonaObject(rootDir, persona, options) {
|
|
|
11559
11559
|
}
|
|
11560
11560
|
async function runChain(rootDir, chainId, options) {
|
|
11561
11561
|
const start = Date.now();
|
|
11562
|
-
const
|
|
11563
|
-
const
|
|
11562
|
+
const fs23 = await import("fs");
|
|
11563
|
+
const path27 = await import("path");
|
|
11564
11564
|
const yaml14 = await import("js-yaml");
|
|
11565
|
-
const chainPath =
|
|
11566
|
-
if (!
|
|
11565
|
+
const chainPath = path27.join(rootDir, ".paradigm", "personas", "chains", `${chainId}.yaml`);
|
|
11566
|
+
if (!fs23.existsSync(chainPath)) {
|
|
11567
11567
|
return {
|
|
11568
11568
|
chain_id: chainId,
|
|
11569
11569
|
status: "error",
|
|
@@ -11572,7 +11572,7 @@ async function runChain(rootDir, chainId, options) {
|
|
|
11572
11572
|
duration_ms: Date.now() - start
|
|
11573
11573
|
};
|
|
11574
11574
|
}
|
|
11575
|
-
const chain = yaml14.load(
|
|
11575
|
+
const chain = yaml14.load(fs23.readFileSync(chainPath, "utf8"));
|
|
11576
11576
|
let permutation;
|
|
11577
11577
|
if (options.permutation && chain.permutations) {
|
|
11578
11578
|
permutation = chain.permutations.find((p) => p.id === options.permutation);
|
|
@@ -11676,8 +11676,8 @@ function validateInterpolation(persona) {
|
|
|
11676
11676
|
const serialized = JSON.stringify(step);
|
|
11677
11677
|
const templates = serialized.match(TEMPLATE_REGEX) || [];
|
|
11678
11678
|
for (const template of templates) {
|
|
11679
|
-
const
|
|
11680
|
-
const [namespace, ...rest] =
|
|
11679
|
+
const path27 = template.replace("{{", "").replace("}}", "").trim();
|
|
11680
|
+
const [namespace, ...rest] = path27.split(".");
|
|
11681
11681
|
const key = rest.join(".");
|
|
11682
11682
|
switch (namespace) {
|
|
11683
11683
|
case "fixtures":
|
|
@@ -12689,8 +12689,258 @@ function summarizeStep(step) {
|
|
|
12689
12689
|
return result;
|
|
12690
12690
|
}
|
|
12691
12691
|
|
|
12692
|
-
// ../paradigm-mcp/src/tools/
|
|
12692
|
+
// ../paradigm-mcp/src/tools/graph.ts
|
|
12693
|
+
import * as fs22 from "fs";
|
|
12693
12694
|
import * as path24 from "path";
|
|
12695
|
+
var GRAPHS_DIR = ".paradigm/graphs";
|
|
12696
|
+
var CATEGORY_PREFIXES = {
|
|
12697
|
+
component: "#",
|
|
12698
|
+
flow: "$",
|
|
12699
|
+
gate: "^",
|
|
12700
|
+
signal: "!",
|
|
12701
|
+
aspect: "~"
|
|
12702
|
+
};
|
|
12703
|
+
var NODE_WIDTH = 200;
|
|
12704
|
+
var NODE_HEIGHT = 60;
|
|
12705
|
+
var NODE_GAP = 20;
|
|
12706
|
+
var GROUP_PADDING = 40;
|
|
12707
|
+
var GROUP_HEADER = 50;
|
|
12708
|
+
var GROUP_GAP = 60;
|
|
12709
|
+
function getGraphToolsList() {
|
|
12710
|
+
return [
|
|
12711
|
+
{
|
|
12712
|
+
name: "paradigm_graph_generate",
|
|
12713
|
+
description: "Generate a named GraphState JSON file for the Paradigm Symbol Graph UI. Writes to .paradigm/graphs/{name}.graph.json. View saved graphs with `paradigm graph` CLI. Returns a summary with node/edge counts and file path. ~100 tokens.",
|
|
12714
|
+
inputSchema: {
|
|
12715
|
+
type: "object",
|
|
12716
|
+
properties: {
|
|
12717
|
+
name: {
|
|
12718
|
+
type: "string",
|
|
12719
|
+
description: 'Graph name (kebab-case). Used as filename: {name}.graph.json. E.g. "auth-flow", "full-project", "checkout-subsystem".'
|
|
12720
|
+
},
|
|
12721
|
+
symbols: {
|
|
12722
|
+
type: "array",
|
|
12723
|
+
items: { type: "string" },
|
|
12724
|
+
description: 'Symbol names to include (e.g. ["#auth-middleware", "^authenticated"]). Omit to include all from scan-index.'
|
|
12725
|
+
},
|
|
12726
|
+
groups: {
|
|
12727
|
+
type: "array",
|
|
12728
|
+
items: {
|
|
12729
|
+
type: "object",
|
|
12730
|
+
properties: {
|
|
12731
|
+
label: { type: "string", description: "Group display label" },
|
|
12732
|
+
symbols: {
|
|
12733
|
+
type: "array",
|
|
12734
|
+
items: { type: "string" },
|
|
12735
|
+
description: "Symbol names belonging to this group"
|
|
12736
|
+
}
|
|
12737
|
+
},
|
|
12738
|
+
required: ["label", "symbols"]
|
|
12739
|
+
},
|
|
12740
|
+
description: "Optional groupings of symbols."
|
|
12741
|
+
},
|
|
12742
|
+
links: {
|
|
12743
|
+
type: "array",
|
|
12744
|
+
items: {
|
|
12745
|
+
type: "object",
|
|
12746
|
+
properties: {
|
|
12747
|
+
source: { type: "string", description: "Source group label" },
|
|
12748
|
+
target: { type: "string", description: "Target group label" },
|
|
12749
|
+
label: { type: "string", description: "Edge label" }
|
|
12750
|
+
},
|
|
12751
|
+
required: ["source", "target"]
|
|
12752
|
+
},
|
|
12753
|
+
description: "Edges between groups (by label name)."
|
|
12754
|
+
}
|
|
12755
|
+
},
|
|
12756
|
+
required: ["name"]
|
|
12757
|
+
},
|
|
12758
|
+
annotations: {
|
|
12759
|
+
readOnlyHint: false,
|
|
12760
|
+
destructiveHint: false
|
|
12761
|
+
}
|
|
12762
|
+
}
|
|
12763
|
+
];
|
|
12764
|
+
}
|
|
12765
|
+
async function handleGraphTool(name, args, ctx) {
|
|
12766
|
+
if (name !== "paradigm_graph_generate") {
|
|
12767
|
+
return { handled: false, text: "" };
|
|
12768
|
+
}
|
|
12769
|
+
try {
|
|
12770
|
+
const graphName = args.name || "untitled";
|
|
12771
|
+
const slug = graphName.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
12772
|
+
const result = buildGraphState(
|
|
12773
|
+
ctx.rootDir,
|
|
12774
|
+
args.symbols,
|
|
12775
|
+
args.groups,
|
|
12776
|
+
args.links,
|
|
12777
|
+
graphName
|
|
12778
|
+
);
|
|
12779
|
+
const json = JSON.stringify(result, null, 2);
|
|
12780
|
+
const graphsDir = path24.join(ctx.rootDir, GRAPHS_DIR);
|
|
12781
|
+
if (!fs22.existsSync(graphsDir)) fs22.mkdirSync(graphsDir, { recursive: true });
|
|
12782
|
+
const outPath = path24.join(graphsDir, `${slug}.graph.json`);
|
|
12783
|
+
fs22.writeFileSync(outPath, json, "utf8");
|
|
12784
|
+
const summary = JSON.stringify({
|
|
12785
|
+
file: outPath,
|
|
12786
|
+
name: graphName,
|
|
12787
|
+
slug,
|
|
12788
|
+
nodes: result.nodes.length,
|
|
12789
|
+
edges: result.edges.length,
|
|
12790
|
+
size: `${(json.length / 1024).toFixed(1)} KB`,
|
|
12791
|
+
hint: `Graph saved. Run \`paradigm graph\` to view in browser.`
|
|
12792
|
+
}, null, 2);
|
|
12793
|
+
trackToolCall(summary.length, name);
|
|
12794
|
+
return { handled: true, text: summary };
|
|
12795
|
+
} catch (err2) {
|
|
12796
|
+
const text = JSON.stringify({ error: err2.message }, null, 2);
|
|
12797
|
+
trackToolCall(text.length, name);
|
|
12798
|
+
return { handled: true, text };
|
|
12799
|
+
}
|
|
12800
|
+
}
|
|
12801
|
+
var SCAN_CATEGORY_MAP = {
|
|
12802
|
+
components: "component",
|
|
12803
|
+
flows: "flow",
|
|
12804
|
+
gates: "gate",
|
|
12805
|
+
signals: "signal",
|
|
12806
|
+
aspects: "aspect"
|
|
12807
|
+
};
|
|
12808
|
+
function loadScanIndex(rootDir) {
|
|
12809
|
+
const indexPath = path24.join(rootDir, ".paradigm", "scan-index.json");
|
|
12810
|
+
if (!fs22.existsSync(indexPath)) return [];
|
|
12811
|
+
const raw = JSON.parse(fs22.readFileSync(indexPath, "utf8"));
|
|
12812
|
+
const symbols = [];
|
|
12813
|
+
for (const [sectionKey, categoryName] of Object.entries(SCAN_CATEGORY_MAP)) {
|
|
12814
|
+
const section = raw[sectionKey];
|
|
12815
|
+
if (!section || typeof section !== "object") continue;
|
|
12816
|
+
for (const [id, sym] of Object.entries(section)) {
|
|
12817
|
+
const s = sym;
|
|
12818
|
+
symbols.push({
|
|
12819
|
+
id,
|
|
12820
|
+
name: id,
|
|
12821
|
+
category: categoryName,
|
|
12822
|
+
prefix: CATEGORY_PREFIXES[categoryName] || "#",
|
|
12823
|
+
description: s.description,
|
|
12824
|
+
path: s.path,
|
|
12825
|
+
tags: s.tags
|
|
12826
|
+
});
|
|
12827
|
+
}
|
|
12828
|
+
}
|
|
12829
|
+
return symbols;
|
|
12830
|
+
}
|
|
12831
|
+
function resolveSymbol(name, allSymbols) {
|
|
12832
|
+
const stripped = name.replace(/^[#$^!~]/, "");
|
|
12833
|
+
return allSymbols.find(
|
|
12834
|
+
(s) => s.id === stripped || s.name === stripped || s.id === name || s.name === name
|
|
12835
|
+
);
|
|
12836
|
+
}
|
|
12837
|
+
function buildGraphState(rootDir, symbolFilter, groups, links, graphName = "Generated Graph") {
|
|
12838
|
+
const allSymbols = loadScanIndex(rootDir);
|
|
12839
|
+
let included;
|
|
12840
|
+
if (symbolFilter && symbolFilter.length > 0) {
|
|
12841
|
+
included = symbolFilter.map((name) => resolveSymbol(name, allSymbols)).filter(Boolean);
|
|
12842
|
+
} else {
|
|
12843
|
+
included = allSymbols;
|
|
12844
|
+
}
|
|
12845
|
+
const nodes = [];
|
|
12846
|
+
const edges = [];
|
|
12847
|
+
const groupIdMap = /* @__PURE__ */ new Map();
|
|
12848
|
+
const assignedSymbols = /* @__PURE__ */ new Set();
|
|
12849
|
+
let nextGroupX = 0;
|
|
12850
|
+
if (groups && groups.length > 0) {
|
|
12851
|
+
for (const group of groups) {
|
|
12852
|
+
const groupId = `group-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
12853
|
+
groupIdMap.set(group.label, groupId);
|
|
12854
|
+
const memberSymbols = group.symbols.map((name) => resolveSymbol(name, included)).filter(Boolean);
|
|
12855
|
+
const cols = Math.ceil(Math.sqrt(memberSymbols.length));
|
|
12856
|
+
const rows = Math.ceil(memberSymbols.length / cols);
|
|
12857
|
+
for (let i = 0; i < memberSymbols.length; i++) {
|
|
12858
|
+
const sym = memberSymbols[i];
|
|
12859
|
+
const col = i % cols;
|
|
12860
|
+
const row = Math.floor(i / cols);
|
|
12861
|
+
const prefix = CATEGORY_PREFIXES[sym.category] || "#";
|
|
12862
|
+
nodes.push({
|
|
12863
|
+
id: `sym-${sym.id}`,
|
|
12864
|
+
type: "symbolNode",
|
|
12865
|
+
position: {
|
|
12866
|
+
x: GROUP_PADDING + col * (NODE_WIDTH + NODE_GAP),
|
|
12867
|
+
y: GROUP_HEADER + GROUP_PADDING + row * (NODE_HEIGHT + NODE_GAP)
|
|
12868
|
+
},
|
|
12869
|
+
parentId: groupId,
|
|
12870
|
+
data: {
|
|
12871
|
+
type: "symbol",
|
|
12872
|
+
symbol: sym,
|
|
12873
|
+
label: `${prefix}${sym.name}`
|
|
12874
|
+
}
|
|
12875
|
+
});
|
|
12876
|
+
assignedSymbols.add(sym.id);
|
|
12877
|
+
}
|
|
12878
|
+
const cols2 = Math.max(cols, 1);
|
|
12879
|
+
const rows2 = Math.max(rows, 1);
|
|
12880
|
+
const groupWidth = GROUP_PADDING * 2 + cols2 * NODE_WIDTH + (cols2 - 1) * NODE_GAP;
|
|
12881
|
+
const groupHeight = GROUP_HEADER + GROUP_PADDING * 2 + rows2 * NODE_HEIGHT + (rows2 - 1) * NODE_GAP;
|
|
12882
|
+
nodes.unshift({
|
|
12883
|
+
id: groupId,
|
|
12884
|
+
type: "groupNode",
|
|
12885
|
+
position: { x: nextGroupX, y: 0 },
|
|
12886
|
+
style: { width: groupWidth, height: groupHeight },
|
|
12887
|
+
data: { type: "group", label: group.label }
|
|
12888
|
+
});
|
|
12889
|
+
nextGroupX += groupWidth + GROUP_GAP;
|
|
12890
|
+
}
|
|
12891
|
+
}
|
|
12892
|
+
const ungrouped = included.filter((s) => !assignedSymbols.has(s.id));
|
|
12893
|
+
if (ungrouped.length > 0) {
|
|
12894
|
+
const startY = groups && groups.length > 0 ? 400 : 0;
|
|
12895
|
+
const cols = Math.ceil(Math.sqrt(ungrouped.length));
|
|
12896
|
+
for (let i = 0; i < ungrouped.length; i++) {
|
|
12897
|
+
const sym = ungrouped[i];
|
|
12898
|
+
const col = i % cols;
|
|
12899
|
+
const row = Math.floor(i / cols);
|
|
12900
|
+
const prefix = CATEGORY_PREFIXES[sym.category] || "#";
|
|
12901
|
+
nodes.push({
|
|
12902
|
+
id: `sym-${sym.id}`,
|
|
12903
|
+
type: "symbolNode",
|
|
12904
|
+
position: {
|
|
12905
|
+
x: col * (NODE_WIDTH + NODE_GAP),
|
|
12906
|
+
y: startY + row * (NODE_HEIGHT + NODE_GAP)
|
|
12907
|
+
},
|
|
12908
|
+
data: {
|
|
12909
|
+
type: "symbol",
|
|
12910
|
+
symbol: sym,
|
|
12911
|
+
label: `${prefix}${sym.name}`
|
|
12912
|
+
}
|
|
12913
|
+
});
|
|
12914
|
+
}
|
|
12915
|
+
}
|
|
12916
|
+
if (links && links.length > 0) {
|
|
12917
|
+
for (const link of links) {
|
|
12918
|
+
const sourceId = groupIdMap.get(link.source);
|
|
12919
|
+
const targetId = groupIdMap.get(link.target);
|
|
12920
|
+
if (sourceId && targetId) {
|
|
12921
|
+
edges.push({
|
|
12922
|
+
id: `e-${sourceId}-${targetId}`,
|
|
12923
|
+
source: sourceId,
|
|
12924
|
+
target: targetId,
|
|
12925
|
+
type: "default",
|
|
12926
|
+
label: link.label,
|
|
12927
|
+
data: { label: link.label }
|
|
12928
|
+
});
|
|
12929
|
+
}
|
|
12930
|
+
}
|
|
12931
|
+
}
|
|
12932
|
+
return {
|
|
12933
|
+
version: "1.0",
|
|
12934
|
+
name: graphName,
|
|
12935
|
+
projectId: path24.basename(rootDir),
|
|
12936
|
+
lastModified: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12937
|
+
nodes,
|
|
12938
|
+
edges
|
|
12939
|
+
};
|
|
12940
|
+
}
|
|
12941
|
+
|
|
12942
|
+
// ../paradigm-mcp/src/tools/fallback-grep.ts
|
|
12943
|
+
import * as path25 from "path";
|
|
12694
12944
|
import { execSync as execSync5 } from "child_process";
|
|
12695
12945
|
function grepForReferences(rootDir, symbol, options = {}) {
|
|
12696
12946
|
const { maxResults = 20 } = options;
|
|
@@ -12719,7 +12969,7 @@ function grepForReferences(rootDir, symbol, options = {}) {
|
|
|
12719
12969
|
const match = line.match(/^(.+?):(\d+):(.*)$/);
|
|
12720
12970
|
if (match) {
|
|
12721
12971
|
const [, filePath, lineNum, content] = match;
|
|
12722
|
-
const relativePath =
|
|
12972
|
+
const relativePath = path25.relative(rootDir, filePath);
|
|
12723
12973
|
let context2 = "unknown";
|
|
12724
12974
|
if (relativePath.includes(".purpose") || relativePath.includes("portal.yaml")) {
|
|
12725
12975
|
context2 = "purpose";
|
|
@@ -12982,6 +13232,8 @@ function registerTools(server, getContext2, reloadContext2) {
|
|
|
12982
13232
|
...getPersonaToolsList(),
|
|
12983
13233
|
// Protocol tools
|
|
12984
13234
|
...getProtocolsToolsList(),
|
|
13235
|
+
// Graph generation tool
|
|
13236
|
+
...getGraphToolsList(),
|
|
12985
13237
|
// Plugin update check
|
|
12986
13238
|
{
|
|
12987
13239
|
name: "paradigm_plugin_check",
|
|
@@ -13615,7 +13867,7 @@ Update command:
|
|
|
13615
13867
|
const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-CMZARW5K.js");
|
|
13616
13868
|
const memberResults = [];
|
|
13617
13869
|
for (const member of ctx.workspace.config.members) {
|
|
13618
|
-
const memberAbsPath =
|
|
13870
|
+
const memberAbsPath = path26.resolve(path26.dirname(ctx.workspace.workspacePath), member.path);
|
|
13619
13871
|
try {
|
|
13620
13872
|
const result = await rebuildStaticFiles2(memberAbsPath);
|
|
13621
13873
|
memberResults.push({
|
|
@@ -13804,6 +14056,15 @@ Update command:
|
|
|
13804
14056
|
};
|
|
13805
14057
|
}
|
|
13806
14058
|
}
|
|
14059
|
+
if (name === "paradigm_graph_generate") {
|
|
14060
|
+
const result = await handleGraphTool(name, args, ctx);
|
|
14061
|
+
if (result.handled) {
|
|
14062
|
+
trackToolCall(result.text.length, name);
|
|
14063
|
+
return {
|
|
14064
|
+
content: [{ type: "text", text: result.text }]
|
|
14065
|
+
};
|
|
14066
|
+
}
|
|
14067
|
+
}
|
|
13807
14068
|
if (name === "paradigm_reindex") {
|
|
13808
14069
|
const reload = reloadContext2 || (async () => {
|
|
13809
14070
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #777;--xy-background-pattern-lines-color-default: #777;--xy-background-pattern-cross-color-default: #777;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}:root{--bg-base: #0a0a0f;--bg-panel: #0f172a;--bg-surface: #1e293b;--bg-hover: #334155;--text-primary: #e2e8f0;--text-secondary: #94a3b8;--text-muted: #64748b;--border: #1e293b;--border-focus: #475569;--color-component: #86efac;--color-flow: #fbbf24;--color-gate: #f87171;--color-signal: #fde047;--color-aspect: #a78bfa}*{margin:0;padding:0;box-sizing:border-box}body{background:var(--bg-base);color:var(--text-primary);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;overflow:hidden}.app{display:flex;height:100vh;width:100vw}.app__main{flex:1;display:flex;flex-direction:column;min-width:0}.symbol-panel{width:280px;min-width:280px;background:var(--bg-panel);border-right:1px solid var(--border);display:flex;flex-direction:column;overflow:hidden}.symbol-panel__header{display:flex;align-items:center;justify-content:space-between;padding:16px;border-bottom:1px solid var(--border)}.symbol-panel__header h2{font-size:14px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--text-secondary)}.symbol-panel__count{font-size:12px;background:var(--bg-surface);color:var(--text-muted);padding:2px 8px;border-radius:10px}.symbol-panel__search{margin:12px 16px;padding:8px 12px;background:var(--bg-surface);border:1px solid var(--border);border-radius:6px;color:var(--text-primary);font-size:13px;outline:none;transition:border-color .15s}.symbol-panel__search:focus{border-color:var(--border-focus)}.symbol-panel__search::placeholder{color:var(--text-muted)}.symbol-panel__list{flex:1;overflow-y:auto;padding:0 8px 16px}.symbol-panel__section{margin-top:4px}.symbol-panel__section-header{display:flex;align-items:center;gap:6px;width:100%;padding:6px 8px;background:none;border:none;font-size:12px;font-weight:600;cursor:pointer;text-transform:uppercase;letter-spacing:.05em}.symbol-panel__section-arrow{font-size:10px;width:12px}.symbol-panel__section-count{margin-left:auto;font-size:11px;opacity:.5;font-weight:400}.symbol-panel__section-items{padding:2px 0}.symbol-panel__item{display:flex;flex-direction:column;gap:2px;padding:6px 8px 6px 12px;margin:1px 0;border-left:2px solid transparent;border-radius:4px;cursor:grab;transition:background .1s}.symbol-panel__item:hover{background:var(--bg-surface)}.symbol-panel__item:active{cursor:grabbing}.symbol-panel__item-name{font-size:13px;font-weight:500;font-family:SF Mono,Fira Code,monospace}.symbol-panel__item-desc{font-size:11px;color:var(--text-muted);line-height:1.3}.toolbar{display:flex;align-items:center;gap:8px;padding:8px 16px;background:var(--bg-panel);border-bottom:1px solid var(--border)}.toolbar__name{background:transparent;border:1px solid transparent;color:var(--text-primary);font-size:14px;font-weight:600;padding:4px 8px;border-radius:4px;width:200px;outline:none;transition:border-color .15s}.toolbar__name:hover,.toolbar__name:focus{border-color:var(--border-focus)}.toolbar__actions{display:flex;align-items:center;gap:6px;margin-left:auto}.toolbar__btn{padding:6px 12px;background:var(--bg-surface);border:1px solid var(--border);color:var(--text-secondary);font-size:12px;font-weight:500;border-radius:6px;cursor:pointer;transition:all .15s}.toolbar__btn:hover{background:var(--bg-hover);color:var(--text-primary)}.toolbar__btn--primary{background:#1d4ed8;border-color:#2563eb;color:#fff}.toolbar__btn--primary:hover{background:#2563eb}.toolbar__divider{width:1px;height:20px;background:var(--border);margin:0 4px}.canvas-wrapper{flex:1;position:relative}.paradigm-flow{background:var(--bg-base)!important}.react-flow__controls{background:var(--bg-panel)!important;border:1px solid var(--border)!important;border-radius:8px!important;overflow:hidden}.react-flow__controls-button{background:var(--bg-panel)!important;border-bottom:1px solid var(--border)!important;fill:var(--text-secondary)!important}.react-flow__controls-button:hover{background:var(--bg-surface)!important}.react-flow__minimap{border:1px solid var(--border)!important;border-radius:8px!important;overflow:hidden}.react-flow__edge-path{stroke:var(--text-muted)!important;stroke-width:2}.react-flow__edge.selected .react-flow__edge-path{stroke:var(--text-primary)!important}.react-flow__edge-text{fill:var(--text-secondary)!important;font-size:11px}.react-flow__edge-textbg{fill:var(--bg-panel)!important}.symbol-node{background:var(--bg-panel);border:1px solid var(--border);border-left:3px solid var(--color-component);border-radius:8px;padding:8px 12px;min-width:160px;max-width:240px;transition:border-color .15s}.symbol-node:hover{border-color:var(--border-focus)}.symbol-node__name{font-size:13px;font-weight:600;font-family:SF Mono,Fira Code,monospace;line-height:1.4}.symbol-node__desc{font-size:11px;color:var(--text-muted);line-height:1.3;margin-top:2px}.group-node{background:#1e293b80;border:2px dashed var(--border-focus);border-radius:12px;width:100%;height:100%;position:relative}.group-node__header{padding:8px 16px;border-bottom:1px solid var(--border);border-radius:12px 12px 0 0;background:#0f172acc;cursor:default}.group-node__label{font-size:13px;font-weight:600;color:var(--text-primary)}.group-node__input{background:var(--bg-surface);border:1px solid var(--border-focus);color:var(--text-primary);font-size:13px;font-weight:600;padding:2px 8px;border-radius:4px;outline:none;width:100%}.group-node__resizer-line{border-color:var(--color-component)!important}.group-node__resizer-handle{background:var(--color-component)!important;width:8px!important;height:8px!important;border-radius:2px!important}.group-handle{width:10px!important;height:10px!important;background:var(--bg-hover)!important;border:2px solid var(--text-muted)!important}.export-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#0009;display:flex;align-items:center;justify-content:center;z-index:100}.export-dialog{background:var(--bg-panel);border:1px solid var(--border);border-radius:12px;width:640px;max-width:90vw;max-height:80vh;display:flex;flex-direction:column}.export-dialog__header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--border)}.export-dialog__header h3{font-size:16px;font-weight:600}.export-dialog__close{background:none;border:none;color:var(--text-muted);font-size:24px;cursor:pointer;line-height:1;padding:0 4px}.export-dialog__close:hover{color:var(--text-primary)}.export-dialog__content{flex:1;margin:16px 20px;padding:12px;background:var(--bg-base);border:1px solid var(--border);border-radius:8px;color:var(--text-primary);font-size:13px;font-family:SF Mono,Fira Code,monospace;resize:none;outline:none;overflow-y:auto}.export-dialog__actions{display:flex;gap:8px;padding:16px 20px;border-top:1px solid var(--border);justify-content:flex-end}.load-dialog{width:520px}.load-dialog__body{padding:16px 20px;display:flex;flex-direction:column;gap:12px}.load-dialog__section{display:flex;flex-direction:column;gap:8px}.load-dialog__label{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--text-secondary)}.load-dialog__divider{display:flex;align-items:center;gap:12px;color:var(--text-muted);font-size:12px}.load-dialog__divider:before,.load-dialog__divider:after{content:"";flex:1;height:1px;background:var(--border)}.load-dialog__status{font-size:12px;padding:8px 12px;border-radius:6px}.load-dialog__status--error{background:#f871711a;color:#f87171;border:1px solid rgba(248,113,113,.2)}.load-dialog__status--success{background:#86efac1a;color:#86efac;border:1px solid rgba(134,239,172,.2)}.load-dialog__loading{color:#94a3b8;font-size:.85rem;padding:8px 0}.load-dialog__graph-list{display:flex;flex-direction:column;gap:4px;max-height:200px;overflow-y:auto}.load-dialog__graph-item{display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:8px 12px;background:#ffffff08;border:1px solid rgba(255,255,255,.06);border-radius:6px;cursor:pointer;text-align:left;color:inherit;font:inherit;transition:background .15s,border-color .15s}.load-dialog__graph-item:hover{background:#ffffff14;border-color:#7dd3fc4d}.load-dialog__graph-name{font-weight:500;font-size:.9rem;color:#e2e8f0}.load-dialog__graph-meta{font-size:.75rem;color:#64748b}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}
|