dsh-plugin-agentflow 0.3.0 → 0.4.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/README.md +97 -22
- package/cordis.patch.yml +0 -187
- package/index.js +43 -0
- package/lib/client.js +3 -3
- package/lib/commands.js +1058 -0
- package/lib/flow.js +611 -0
- package/lib/observe.js +286 -0
- package/package.json +5 -3
- package/runtime/boards.mjs +42 -1
- package/runtime/commands.mjs +195 -0
- package/runtime/orchestrator.mjs +57 -0
- package/runtime/server.mjs +67 -96
- package/runtime/web/dist/assets/index-BRBK2BoT.css +1 -0
- package/runtime/web/dist/assets/{index-DhM_avMx.js → index-BxE5pyuf.js} +5 -5
- package/runtime/web/dist/index.html +2 -2
- package/scripts/observe-report.mjs +131 -0
- package/runtime/preset-gen.mjs +0 -1117
- package/runtime/web/dist/assets/index-DEZcpxgr.css +0 -1
package/runtime/server.mjs
CHANGED
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
// GET/PUT/DELETE /api/boards/:id/draft → 草稿(手动保存前的未落定修改)
|
|
12
12
|
// GET/PUT /api/board → 旧接口过渡:读写 flow-agentflow
|
|
13
13
|
//
|
|
14
|
+
// 斜杠命令(落盘 <DATA_DIR>/commands/<name>.json,生成即生效):
|
|
15
|
+
// POST /api/export/command?board=<id> → 把画布挂成命令(body {name?})
|
|
16
|
+
// GET /api/commands → 命令列表(带画布名 / 画布是否还在)
|
|
17
|
+
// DELETE /api/commands/:name → 删命令
|
|
18
|
+
//
|
|
14
19
|
// 其余路由:
|
|
15
20
|
// GET / → index.html
|
|
16
21
|
// POST /api/nodes → 新建节点(带 from 时自动建边)
|
|
@@ -40,7 +45,6 @@ import {
|
|
|
40
45
|
renameBoard,
|
|
41
46
|
deleteBoard,
|
|
42
47
|
resolveBoard,
|
|
43
|
-
markPresetSynced,
|
|
44
48
|
getBoard,
|
|
45
49
|
mutateBoardById,
|
|
46
50
|
ensureDefaultBoard,
|
|
@@ -48,7 +52,11 @@ import {
|
|
|
48
52
|
getDraft,
|
|
49
53
|
deleteDraft,
|
|
50
54
|
httpError,
|
|
55
|
+
readIndex,
|
|
56
|
+
boardFile,
|
|
51
57
|
} from './boards.mjs';
|
|
58
|
+
import { assertRootHasNoUpstream } from './orchestrator.mjs';
|
|
59
|
+
import { deleteCommand, isValidCommandName, listCommands, writeCommand } from './commands.mjs';
|
|
52
60
|
import { normalizeConfig, makeCaller } from './llm.mjs';
|
|
53
61
|
import { listSkills, defaultSkillDirs } from './skills.mjs';
|
|
54
62
|
import { askJev, selfVerify } from './verify.mjs';
|
|
@@ -227,28 +235,6 @@ async function ensureMcpPool() {
|
|
|
227
235
|
}
|
|
228
236
|
|
|
229
237
|
/** 给 /api/mcp 用的快照:配置了哪些 server、连没连上、有哪些工具 */
|
|
230
|
-
/** 当前可用的全部技能名与全部 MCP 工具名(根节点默认全选) */
|
|
231
|
-
async function allSkillsAndTools() {
|
|
232
|
-
let skills = [];
|
|
233
|
-
try {
|
|
234
|
-
const dirs = (await buildCfg()).skillDirs?.length ? (await buildCfg()).skillDirs : defaultSkillDirs();
|
|
235
|
-
const listed = await listSkills(dirs);
|
|
236
|
-
skills = (Array.isArray(listed) ? listed : []).map((x) => x.name);
|
|
237
|
-
} catch {
|
|
238
|
-
skills = [];
|
|
239
|
-
}
|
|
240
|
-
let tools = [];
|
|
241
|
-
try {
|
|
242
|
-
const snap = await mcpSnapshot();
|
|
243
|
-
for (const server of snap.servers || []) {
|
|
244
|
-
for (const tool of server.tools || []) tools.push(`${server.name}.${tool.name}`);
|
|
245
|
-
}
|
|
246
|
-
} catch {
|
|
247
|
-
tools = [];
|
|
248
|
-
}
|
|
249
|
-
return { skills, tools };
|
|
250
|
-
}
|
|
251
|
-
|
|
252
238
|
async function mcpSnapshot() {
|
|
253
239
|
const cfg = await buildCfg();
|
|
254
240
|
const specs = cfg.mcpServers || {};
|
|
@@ -300,18 +286,10 @@ const nowId = () => 'n' + Math.random().toString(36).slice(2, 8);
|
|
|
300
286
|
// PUT /api/board 只允许改这些字段:拖动不该把物料冲掉
|
|
301
287
|
const LAYOUT_FIELDS = ['x', 'y', 'label', 'task', 'criteria', 'model', 'provider', 'reasoningEffort', 'fallback', 'fallbackEfforts', 'type', 'skills', 'tools', 'verify', 'tool', 'args'];
|
|
302
288
|
|
|
303
|
-
// ----------
|
|
304
|
-
|
|
305
|
-
//
|
|
306
|
-
|
|
307
|
-
async function getPresetGen() {
|
|
308
|
-
if (presetGen) return presetGen;
|
|
309
|
-
presetGen = await import('./preset-gen.mjs');
|
|
310
|
-
return presetGen;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/** 给用户照着敲的安装命令。不自动改 profile —— 改 profile 的风险太大,踩过坑。 */
|
|
314
|
-
// ---------- 把生成的预设装进 profile ----------
|
|
289
|
+
// ---------- 遗留预设:自定义预设装在哪个 profile ----------
|
|
290
|
+
//
|
|
291
|
+
// 预设生成已下线(画布现在导出的是斜杠命令),这里只剩历史兼容:
|
|
292
|
+
// /api/presets(列出/复制/删除旧预设)与 /api/boards/import-preset 还在用。
|
|
315
293
|
|
|
316
294
|
// 预设写到哪个 profile:默认 DSH 桌面版的 desktop,允许用 AGENTFLOW_PROFILE 覆盖
|
|
317
295
|
const PRESET_PROFILE = () =>
|
|
@@ -530,7 +508,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
530
508
|
const method = req.method;
|
|
531
509
|
|
|
532
510
|
// DSH 的客户端插件在 dsh-app:// 里跑,来调本机 API 属于跨源调用。
|
|
533
|
-
// 只放行本机壳与本机页面,不放
|
|
511
|
+
// 只放行本机壳与本机页面,不放 *:生成命令会写 DATA_DIR,不能让任意网页触发。
|
|
534
512
|
const origin = String(req.headers.origin || '');
|
|
535
513
|
const originOk = !origin
|
|
536
514
|
|| origin.startsWith('dsh-app://')
|
|
@@ -759,8 +737,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
759
737
|
}
|
|
760
738
|
}
|
|
761
739
|
try {
|
|
762
|
-
|
|
763
|
-
gen.assertRootHasNoUpstream(incoming);
|
|
740
|
+
assertRootHasNoUpstream(incoming);
|
|
764
741
|
} catch (err) {
|
|
765
742
|
if (err && err.status) return json(res, 400, { error: String(err.message) });
|
|
766
743
|
}
|
|
@@ -933,73 +910,67 @@ const server = http.createServer(async (req, res) => {
|
|
|
933
910
|
}
|
|
934
911
|
}
|
|
935
912
|
|
|
936
|
-
// ---
|
|
937
|
-
if (p === '/api/export/
|
|
913
|
+
// --- 生成斜杠命令:把画布挂成 DSH 的命令,落盘 <DATA_DIR>/commands/<name>.json ---
|
|
914
|
+
if (p === '/api/export/command' && method === 'POST') {
|
|
938
915
|
const ctx = await resolveBoardCtx(url.searchParams.get('board'));
|
|
939
|
-
const
|
|
940
|
-
const
|
|
941
|
-
|
|
942
|
-
.then((st) => st.isDirectory())
|
|
943
|
-
.catch(() => false);
|
|
944
|
-
if (!profileOk) {
|
|
916
|
+
const body = await readBody(req).catch(() => ({}));
|
|
917
|
+
const wantedName = body && typeof body.name === 'string' ? body.name.trim() : '';
|
|
918
|
+
if (wantedName && !isValidCommandName(wantedName)) {
|
|
945
919
|
return json(res, 400, {
|
|
946
|
-
error:
|
|
920
|
+
error: `命令名不合法:${wantedName}(只允许 ^[a-z][a-z0-9_-]*$,不超过 48 个字符)`,
|
|
947
921
|
});
|
|
948
922
|
}
|
|
949
|
-
|
|
950
|
-
const body = await readBody(req).catch(() => ({}));
|
|
951
|
-
// 自定义预设显示名(可选):只影响预设名,presetId 仍由画布决定
|
|
952
|
-
const presetName = body && typeof body.name === 'string' ? body.name.trim() : '';
|
|
953
|
-
if (!board.nodes || board.nodes.length === 0) {
|
|
923
|
+
if (!Array.isArray(ctx.board.nodes) || ctx.board.nodes.length === 0) {
|
|
954
924
|
return json(res, 400, { error: '画布是空的,先摆几个节点' });
|
|
955
925
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
926
|
+
// name 缺省时按画布 id 生成(agentflow-<slug>,重名自动加 -2/-3)
|
|
927
|
+
const out = await writeCommand({ board: ctx.id, name: wantedName || undefined });
|
|
928
|
+
return json(res, 200, {
|
|
929
|
+
ok: true,
|
|
930
|
+
name: out.name,
|
|
931
|
+
board: ctx.id,
|
|
932
|
+
boardName: ctx.board.name || ctx.id,
|
|
933
|
+
file: out.file,
|
|
934
|
+
replaced: out.replaced,
|
|
935
|
+
});
|
|
936
|
+
}
|
|
962
937
|
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
938
|
+
// --- 命令列表:带上画布名与画布是否还在(画布删了命令不会自动消失)---
|
|
939
|
+
if (p === '/api/commands' && method === 'GET') {
|
|
940
|
+
const index = await readIndex();
|
|
941
|
+
const commands = [];
|
|
942
|
+
for (const rec of await listCommands()) {
|
|
943
|
+
const meta = index.boards[rec.board];
|
|
944
|
+
const boardExists =
|
|
945
|
+
Boolean(meta)
|
|
946
|
+
|| (await fs
|
|
947
|
+
.stat(boardFile(rec.board))
|
|
948
|
+
.then((st) => st.isFile())
|
|
949
|
+
.catch(() => false));
|
|
950
|
+
let boardName = meta?.name || null;
|
|
951
|
+
if (!boardName && boardExists) {
|
|
952
|
+
boardName = (await getBoard(rec.board).catch(() => null))?.name || rec.board;
|
|
953
|
+
}
|
|
954
|
+
commands.push({
|
|
955
|
+
name: rec.name,
|
|
956
|
+
board: rec.board,
|
|
957
|
+
boardName,
|
|
958
|
+
boardExists,
|
|
959
|
+
createdAt: rec.createdAt,
|
|
960
|
+
file: rec.file,
|
|
961
|
+
});
|
|
981
962
|
}
|
|
963
|
+
return json(res, 200, { commands });
|
|
964
|
+
}
|
|
982
965
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
await
|
|
989
|
-
return json(res,
|
|
990
|
-
|
|
991
|
-
profileDir: PRESET_PROFILE(),
|
|
992
|
-
file: out.file,
|
|
993
|
-
presetId: out.presetId,
|
|
994
|
-
presetName: out.name,
|
|
995
|
-
replaced: out.replaced,
|
|
996
|
-
personaPreview: gen.renderPersona(exportBoard),
|
|
997
|
-
addedOrchestrator,
|
|
998
|
-
personaSource,
|
|
999
|
-
needRestart: true,
|
|
1000
|
-
});
|
|
1001
|
-
} catch (err) {
|
|
1002
|
-
return json(res, 400, { error: String((err && err.message) || err) });
|
|
966
|
+
// --- 删命令:DSH 侧下次扫描就没了 ---
|
|
967
|
+
{
|
|
968
|
+
const commandMatch = /^\/api\/commands\/([a-z][a-z0-9_-]{0,47})$/.exec(p);
|
|
969
|
+
if (commandMatch && method === 'DELETE') {
|
|
970
|
+
const name = commandMatch[1];
|
|
971
|
+
const removed = await deleteCommand(name);
|
|
972
|
+
if (!removed) return json(res, 404, { error: `命令不存在:${name}` });
|
|
973
|
+
return json(res, 200, { ok: true, name });
|
|
1003
974
|
}
|
|
1004
975
|
}
|
|
1005
976
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.react-flow{--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:#ffffff80;--xy-minimap-background-color-default:#fff;--xy-minimap-mask-background-color-default:#f0f0f099;--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:#f0f0f040;--xy-node-boxshadow-hover-default:0 1px 4px 1px #00000014;--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:#0059dc14;--xy-selection-border-default:1px dotted #0059dccc;--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 #00000014;--xy-edge-label-background-color-default:#fff;--xy-edge-label-color-default:inherit;--xy-resize-background-color-default:#3367d9;direction:ltr}.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:#96969640;--xy-minimap-background-color-default:#141414;--xy-minimap-mask-background-color-default:#3c3c3c99;--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:#555;--xy-background-pattern-lines-color-default:#333;--xy-background-pattern-cross-color-default:#333;--xy-node-color-default:#f8f8f8;--xy-node-border-default:1px solid #3c3c3c;--xy-node-background-color-default:#1e1e1e;--xy-node-group-background-color-default:#f0f0f040;--xy-node-boxshadow-hover-default:0 1px 4px 1px #ffffff14;--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:#c8c8dc14;--xy-selection-border-default:1px dotted #c8c8dccc;--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 #00000014;--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{width:100%;height:100%;position:absolute;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.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{pointer-events:none;position:absolute;overflow:visible}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:.5s linear infinite dashdraw}.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;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:.5s linear infinite dashdraw}svg.react-flow__connectionline{z-index:1001;position:absolute;overflow:visible}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{-webkit-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default;position:absolute}.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:0 0;pointer-events:none}.react-flow__nodesselection-rect{pointer-events:all;cursor:grab;position:absolute}.react-flow__handle{pointer-events:none;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%;width:6px;min-width:5px;height:6px;min-height:5px;position:absolute}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;bottom:0;left:50%;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{z-index:5;margin:15px;position:absolute}.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{background:var(--xy-attribution-background-color,var(--xy-attribution-background-color-default));margin:0;padding:2px 3px;font-size:10px}.react-flow__attribution a{color:#999;text-decoration:none}@keyframes dashdraw{0%{stroke-dashoffset:10px}}.react-flow__edgelabel-renderer{pointer-events:none;-webkit-user-select:none;user-select:none;width:100%;height:100%;position:absolute;top:0;left:0}.react-flow__viewport-portal{-webkit-user-select:none;user-select:none;width:100%;height:100%;position:absolute;top:0;left:0}.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{box-shadow:var(--xy-controls-box-shadow,var(--xy-controls-box-shadow-default));flex-direction:column;display:flex}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{background:var(--xy-controls-button-background-color,var(--xy-controls-button-background-color-default));border:none;border-bottom:1px solid var(--xy-controls-button-border-color-props,var(--xy-controls-button-border-color,var(--xy-controls-button-border-color-default)));width:26px;height:26px;color:var(--xy-controls-button-color-props,var(--xy-controls-button-color,var(--xy-controls-button-color-default)));cursor:pointer;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;padding:4px;display:flex}.react-flow__controls-button svg{fill:currentColor;width:100%;max-width:12px;max-height:12px}.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{border-radius:var(--xy-node-border-radius,var(--xy-node-border-radius-default));width:150px;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));padding:10px;font-size:12px}.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{background-color:var(--xy-resize-background-color,var(--xy-resize-background-color-default));border:1px solid #fff;border-radius:1px;width:5px;height:5px;translate:-50% -50%}.react-flow__resize-control.handle.left{top:50%;left:0}.react-flow__resize-control.handle.right{top:50%;left:100%}.react-flow__resize-control.handle.top{top:0;left:50%}.react-flow__resize-control.handle.bottom{top:100%;left:50%}.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-style:solid;border-width:0}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;height:100%;top:0;transform:translate(-50%)}.react-flow__resize-control.line.left{border-left-width:1px;left:0}.react-flow__resize-control.line.right{border-right-width:1px;left:100%}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{width:100%;height:1px;left:0;transform:translateY(-50%)}.react-flow__resize-control.line.top{border-top-width:1px;top:0}.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))}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial}}}@layer theme{:root,:host{--color-white:#fff;--spacing:.25rem;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer base{.af-canvas,.af-canvas *,.af-canvas :before,.af-canvas :after{box-sizing:border-box;border:0 solid;margin:0;padding:0}.af-canvas :where(h1,h2,h3,h4,h5,h6){font-size:inherit;font-weight:inherit}.af-canvas :where(ol,ul,menu){list-style:none}.af-canvas :where(a){color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}.af-canvas :where(b,strong){font-weight:bolder}.af-canvas :where(code,kbd,samp,pre){font-family:var(--mono);font-size:1em}.af-canvas :where(img,svg,video,canvas,audio,iframe,embed,object){vertical-align:middle;display:block}.af-canvas :where(img,video){max-width:100%;height:auto}.af-canvas :where(button,input,select,optgroup,textarea){font:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}.af-canvas :where(textarea){resize:vertical}.af-canvas ::placeholder{opacity:1}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{inset-block:0}.top-0{top:0}.top-14{top:calc(var(--spacing) * 14)}.top-\[12px\]{top:12px}.right-0{right:0}.bottom-0{bottom:0}.bottom-6{bottom:calc(var(--spacing) * 6)}.left-0{left:0}.left-1\/2{left:50%}.left-4{left:calc(var(--spacing) * 4)}.z-10{z-index:10}.z-30{z-index:30}.z-50{z-index:50}.\!m-4{margin:calc(var(--spacing) * 4)!important}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-\[5px\]{margin-top:5px}.mt-auto{margin-top:auto}.-mr-1{margin-right:calc(var(--spacing) * -1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-2\.5{margin-bottom:calc(var(--spacing) * 2.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-\[2px\]{height:2px}.h-\[3px\]{height:3px}.h-\[5px\]{height:5px}.h-\[6px\]{height:6px}.h-full{height:100%}.max-h-\[180px\]{max-height:180px}.max-h-\[200px\]{max-height:200px}.max-h-\[240px\]{max-height:240px}.min-h-0{min-height:0}.min-h-\[32px\]{min-height:32px}.min-h-\[150px\]{min-height:150px}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-1\/2{width:50%}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-12{width:calc(var(--spacing) * 12)}.w-\[3px\]{width:3px}.w-\[5px\]{width:5px}.w-\[6px\]{width:6px}.w-\[340px\]{width:340px}.w-\[420px\]{width:420px}.w-full{width:100%}.w-px{width:1px}.max-w-\[280px\]{max-width:280px}.max-w-\[340px\]{max-width:340px}.max-w-\[1080px\]{max-width:1080px}.max-w-full{max-width:100%}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-6{--tw-translate-y:calc(var(--spacing) * -6);translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-grab{cursor:grab}.resize-none{resize:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-\[2px\]{gap:2px}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-\[3px\]{border-radius:3px}.rounded-\[4px\]{border-radius:4px}.rounded-\[6px\]{border-radius:6px}.rounded-\[7px\]{border-radius:7px}.rounded-\[8px\]{border-radius:8px}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-\[4px\]{border-top-left-radius:4px;border-top-right-radius:4px}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-\[\#E1E2DD\]{border-color:#e1e2dd}.border-\[\#E2E4E0\]{border-color:#e2e4e0}.border-\[\#E3E4DF\]{border-color:#e3e4df}.border-\[\#E6E7E2\]{border-color:#e6e7e2}.border-\[\#E9D9B8\]{border-color:#e9d9b8}.border-\[\#EDEEE9\]{border-color:#edeee9}.border-\[\#eef0ec\]{border-color:#eef0ec}.bg-\[\#1C1C1A\]{background-color:#1c1c1a}.bg-\[\#3fa76b\]{background-color:#3fa76b}.bg-\[\#8b8b85\]{background-color:#8b8b85}.bg-\[\#24543F\]{background-color:#24543f}.bg-\[\#B4451F\]{background-color:#b4451f}.bg-\[\#E3E4DF\]{background-color:#e3e4df}.bg-\[\#EEF3EF\]{background-color:#eef3ef}.bg-\[\#EFEFEA\]{background-color:#efefea}.bg-\[\#F4F5F2\]{background-color:#f4f5f2}.bg-\[\#F9F9F6\]{background-color:#f9f9f6}.bg-\[\#FAEFE6\]{background-color:#faefe6}.bg-\[\#FAFAF7\]{background-color:#fafaf7}.bg-\[\#FBEFEA\]{background-color:#fbefea}.bg-\[\#FBF4E6\]{background-color:#fbf4e6}.bg-\[\#FCFCFA\]{background-color:#fcfcfa}.bg-\[\#FCFCFA\]\/90{background-color:oklab(99.0514% -.000745505 .00252551/.9)}.bg-\[\#a8a8a0\]{background-color:#a8a8a0}.bg-\[\#b0b7c3\]{background-color:#b0b7c3}.bg-\[\#b6becb\]{background-color:#b6becb}.bg-\[\#c2410c\]{background-color:#c2410c}.bg-\[\#e05252\]{background-color:#e05252}.bg-\[\#eef3fe\]{background-color:#eef3fe}.bg-\[\#f0a020\]{background-color:#f0a020}.bg-\[\#f1eefe\]{background-color:#f1eefe}.bg-\[\#f2f4f7\]{background-color:#f2f4f7}.bg-\[\#fbeee8\]{background-color:#fbeee8}.bg-\[\#fcfcfd\]{background-color:#fcfcfd}.bg-\[\#ffebee\]{background-color:#ffebee}.bg-current{background-color:currentColor}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.p-0{padding:0}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-\[3px\]{padding:3px}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-7{padding-block:calc(var(--spacing) * 7)}.py-14{padding-block:calc(var(--spacing) * 14)}.py-16{padding-block:calc(var(--spacing) * 16)}.py-\[5px\]{padding-block:5px}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[17px\]{font-size:17px}.text-\[20px\]{font-size:20px}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-\[1\.3\]{--tw-leading:1.3;line-height:1.3}.leading-\[1\.5\]{--tw-leading:1.5;line-height:1.5}.leading-\[1\.6\]{--tw-leading:1.6;line-height:1.6}.leading-\[1\.65\]{--tw-leading:1.65;line-height:1.65}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.01em\]{--tw-tracking:.01em;letter-spacing:.01em}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.text-\[\#1B1B18\]{color:#1b1b18}.text-\[\#1C1C1A\]{color:#1c1c1a}.text-\[\#5F5F59\]{color:#5f5f59}.text-\[\#5b6472\]{color:#5b6472}.text-\[\#6b6b66\]{color:#6b6b66}.text-\[\#7C7C75\]{color:#7c7c75}.text-\[\#7c6cf0\]{color:#7c6cf0}.text-\[\#8a93a3\]{color:#8a93a3}.text-\[\#8a6220\]{color:#8a6220}.text-\[\#8b8b85\]{color:#8b8b85}.text-\[\#98a1b0\]{color:#98a1b0}.text-\[\#24543F\]{color:#24543f}.text-\[\#333330\]{color:#333330}.text-\[\#B4451F\]{color:#b4451f}.text-\[\#a8542f\]{color:#a8542f}.text-\[\#aeb6c3\]{color:#aeb6c3}.text-\[\#c62828\]{color:#c62828}.text-white{color:var(--color-white)}.italic{font-style:italic}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.shadow-\[0_1px_2px_rgba\(0\,0\,0\,0\.06\)\]{--tw-shadow:0 1px 2px var(--tw-shadow-color,#0000000f);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_1px_3px_rgba\(20\,24\,20\,0\.06\)\,0_10px_28px_-18px_rgba\(20\,24\,20\,0\.22\)\]{--tw-shadow:0 1px 3px var(--tw-shadow-color,#1418140f), 0 10px 28px -18px var(--tw-shadow-color,#14181438);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_4px_16px_rgba\(16\,24\,40\,0\.06\)\]{--tw-shadow:0 4px 16px var(--tw-shadow-color,#1018280f);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_6px_20px_rgba\(16\,24\,40\,0\.07\)\]{--tw-shadow:0 6px 20px var(--tw-shadow-color,#10182812);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_6px_20px_rgba\(16\,24\,40\,0\.08\)\]{--tw-shadow:0 6px 20px var(--tw-shadow-color,#10182814);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_10px_30px_-12px_rgba\(36\,84\,63\,0\.35\)\]{--tw-shadow:0 10px 30px -12px var(--tw-shadow-color,#24543f59);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-\[\#24543F\]{--tw-ring-color:#24543f}.ring-offset-2{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.ring-offset-\[\#F4F5F2\]{--tw-ring-offset-color:#f4f5f2}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.outline-none{--tw-outline-style:none;outline-style:none}.placeholder\:text-\[\#9a9a92\]::placeholder{color:#9a9a92}.placeholder\:text-\[\#a8a8a0\]::placeholder{color:#a8a8a0}.first\:mt-1:first-child{margin-top:var(--spacing)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-\[\#1D4634\]:hover{background-color:#1d4634}.hover\:bg-\[\#EFEFEA\]:hover{background-color:#efefea}.hover\:bg-\[\#FBEFEA\]:hover{background-color:#fbefea}.hover\:bg-\[\#eafaef\]:hover{background-color:#eafaef}.hover\:bg-\[\#eef3fe\]:hover{background-color:#eef3fe}.hover\:bg-white\/60:hover{background-color:#fff9}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/60:hover{background-color:color-mix(in oklab, var(--color-white) 60%, transparent)}}.hover\:text-\[\#1B1B18\]:hover{color:#1b1b18}.hover\:text-\[\#2e7d32\]:hover{color:#2e7d32}.hover\:text-\[\#24543F\]:hover{color:#24543f}.hover\:text-\[\#B4451F\]:hover{color:#b4451f}.hover\:opacity-70:hover{opacity:.7}.hover\:shadow-\[0_2px_6px_rgba\(20\,24\,20\,0\.08\)\,0_16px_36px_-20px_rgba\(20\,24\,20\,0\.3\)\]:hover{--tw-shadow:0 2px 6px var(--tw-shadow-color,#14181414), 0 16px 36px -20px var(--tw-shadow-color,#1418144d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.focus\:border-\[\#24543F\]:focus{border-color:#24543f}.focus\:bg-white:focus{background-color:var(--color-white)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-\[\#24543F\]\/30:focus-visible{--tw-ring-color:oklab(40.5771% -.0609612 .0189529/.3)}.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-transparent:disabled{background-color:#0000}.disabled\:opacity-35:disabled{opacity:.35}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media (hover:hover){.disabled\:hover\:bg-transparent:disabled:hover{background-color:#0000}}@media (width>=48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width>=80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}.dark\:border-\[\#2A2C31\]:where(.dark,.dark *){border-color:#2a2c31}.dark\:border-\[\#2E3037\]:where(.dark,.dark *){border-color:#2e3037}.dark\:border-\[\#4a3a1c\]:where(.dark,.dark *){border-color:#4a3a1c}.dark\:border-\[\#262b36\]:where(.dark,.dark *){border-color:#262b36}.dark\:border-\[\#33353B\]:where(.dark,.dark *){border-color:#33353b}.dark\:border-\[\#232421\]:where(.dark,.dark *){border-color:#232421}.dark\:border-\[\#262724\]:where(.dark,.dark *){border-color:#262724}.dark\:bg-\[\#0f1116\]:where(.dark,.dark *){background-color:#0f1116}.dark\:bg-\[\#1B1C20\]:where(.dark,.dark *){background-color:#1b1c20}.dark\:bg-\[\#1B2A22\]:where(.dark,.dark *){background-color:#1b2a22}.dark\:bg-\[\#1E1F24\]:where(.dark,.dark *){background-color:#1e1f24}.dark\:bg-\[\#1a1d25\]:where(.dark,.dark *){background-color:#1a1d25}.dark\:bg-\[\#1b2a44\]:where(.dark,.dark *){background-color:#1b2a44}.dark\:bg-\[\#2A1C17\]:where(.dark,.dark *){background-color:#2a1c17}.dark\:bg-\[\#2a2314\]:where(.dark,.dark *){background-color:#2a2314}.dark\:bg-\[\#2a2440\]:where(.dark,.dark *){background-color:#2a2440}.dark\:bg-\[\#2c2d29\]:where(.dark,.dark *){background-color:#2c2d29}.dark\:bg-\[\#3A3B35\]:where(.dark,.dark *){background-color:#3a3b35}.dark\:bg-\[\#3F7A5F\]:where(.dark,.dark *){background-color:#3f7a5f}.dark\:bg-\[\#3a1b1f\]:where(.dark,.dark *){background-color:#3a1b1f}.dark\:bg-\[\#6aa583\]:where(.dark,.dark *){background-color:#6aa583}.dark\:bg-\[\#6b7385\]:where(.dark,.dark *){background-color:#6b7385}.dark\:bg-\[\#6ee7a0\]:where(.dark,.dark *){background-color:#6ee7a0}.dark\:bg-\[\#6f6f68\]:where(.dark,.dark *){background-color:#6f6f68}.dark\:bg-\[\#8b8b85\]:where(.dark,.dark *){background-color:#8b8b85}.dark\:bg-\[\#181b23\]:where(.dark,.dark *){background-color:#181b23}.dark\:bg-\[\#17181B\]:where(.dark,.dark *),.dark\:bg-\[\#17181b\]:where(.dark,.dark *){background-color:#17181b}.dark\:bg-\[\#17181b\]\/90:where(.dark,.dark *){background-color:oklab(20.9238% .000118949 -.00610654/.9)}.dark\:bg-\[\#39231a\]:where(.dark,.dark *){background-color:#39231a}.dark\:bg-\[\#111214\]:where(.dark,.dark *){background-color:#111214}.dark\:bg-\[\#121312\]\/90:where(.dark,.dark *){background-color:oklab(18.5187% -.0021049 .00144818/.9)}.dark\:bg-\[\#151617\]:where(.dark,.dark *){background-color:#151617}.dark\:bg-\[\#232421\]:where(.dark,.dark *){background-color:#232421}.dark\:bg-\[\#232733\]:where(.dark,.dark *){background-color:#232733}.dark\:bg-\[\#e7e9ee\]:where(.dark,.dark *){background-color:#e7e9ee}.dark\:bg-\[\#e08a6a\]:where(.dark,.dark *){background-color:#e08a6a}.dark\:bg-\[\#f4b95f\]:where(.dark,.dark *){background-color:#f4b95f}.dark\:bg-\[\#f28b8b\]:where(.dark,.dark *){background-color:#f28b8b}.dark\:bg-\[\#fb923c\]:where(.dark,.dark *){background-color:#fb923c}.dark\:text-\[\#0f1116\]:where(.dark,.dark *){color:#0f1116}.dark\:text-\[\#6d7586\]:where(.dark,.dark *){color:#6d7586}.dark\:text-\[\#8E8E86\]:where(.dark,.dark *){color:#8e8e86}.dark\:text-\[\#8FC3A7\]:where(.dark,.dark *){color:#8fc3a7}.dark\:text-\[\#8b8b85\]:where(.dark,.dark *){color:#8b8b85}.dark\:text-\[\#8b93a5\]:where(.dark,.dark *){color:#8b93a5}.dark\:text-\[\#8fb3f2\]:where(.dark,.dark *){color:#8fb3f2}.dark\:text-\[\#A8A8A0\]:where(.dark,.dark *){color:#a8a8a0}.dark\:text-\[\#E08A6A\]:where(.dark,.dark *){color:#e08a6a}.dark\:text-\[\#EDEDE8\]:where(.dark,.dark *){color:#edede8}.dark\:text-\[\#a3a39b\]:where(.dark,.dark *){color:#a3a39b}.dark\:text-\[\#a7aebb\]:where(.dark,.dark *){color:#a7aebb}.dark\:text-\[\#b3a6fa\]:where(.dark,.dark *){color:#b3a6fa}.dark\:text-\[\#c9cdc7\]:where(.dark,.dark *){color:#c9cdc7}.dark\:text-\[\#e0b866\]:where(.dark,.dark *){color:#e0b866}.dark\:text-\[\#e7e9ee\]:where(.dark,.dark *){color:#e7e9ee}.dark\:text-\[\#e08a6a\]:where(.dark,.dark *){color:#e08a6a}.dark\:text-\[\#e8e8e4\]:where(.dark,.dark *){color:#e8e8e4}.dark\:text-\[\#e9a484\]:where(.dark,.dark *){color:#e9a484}.dark\:text-\[\#ff9a9a\]:where(.dark,.dark *){color:#ff9a9a}.dark\:shadow-\[0_1px_3px_rgba\(0\,0\,0\,0\.5\)\,0_10px_28px_-18px_rgba\(0\,0\,0\,0\.7\)\]:where(.dark,.dark *){--tw-shadow:0 1px 3px var(--tw-shadow-color,#00000080), 0 10px 28px -18px var(--tw-shadow-color,#000000b3);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.dark\:shadow-\[0_4px_16px_rgba\(0\,0\,0\,0\.4\)\]:where(.dark,.dark *){--tw-shadow:0 4px 16px var(--tw-shadow-color,#0006);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.dark\:shadow-\[0_6px_20px_rgba\(0\,0\,0\,0\.5\)\]:where(.dark,.dark *){--tw-shadow:0 6px 20px var(--tw-shadow-color,#00000080);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.dark\:shadow-\[0_10px_30px_-12px_rgba\(0\,0\,0\,0\.65\)\]:where(.dark,.dark *){--tw-shadow:0 10px 30px -12px var(--tw-shadow-color,#000000a6);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.dark\:ring-\[\#6aa583\]:where(.dark,.dark *){--tw-ring-color:#6aa583}.dark\:ring-offset-\[\#121312\]:where(.dark,.dark *){--tw-ring-offset-color:#121312}.dark\:placeholder\:text-\[\#6f6f68\]:where(.dark,.dark *)::placeholder{color:#6f6f68}@media (hover:hover){.dark\:hover\:bg-\[\#1b2a44\]:where(.dark,.dark *):hover{background-color:#1b2a44}.dark\:hover\:bg-\[\#1b3327\]:where(.dark,.dark *):hover{background-color:#1b3327}.dark\:hover\:bg-\[\#2A1C17\]:where(.dark,.dark *):hover{background-color:#2a1c17}.dark\:hover\:bg-\[\#4B8B6D\]:where(.dark,.dark *):hover{background-color:#4b8b6d}.dark\:hover\:bg-\[\#232421\]:where(.dark,.dark *):hover{background-color:#232421}.dark\:hover\:text-\[\#6ee7a0\]:where(.dark,.dark *):hover{color:#6ee7a0}.dark\:hover\:text-\[\#8fb3f2\]:where(.dark,.dark *):hover{color:#8fb3f2}.dark\:hover\:text-\[\#e08a6a\]:where(.dark,.dark *):hover{color:#e08a6a}.dark\:hover\:text-\[\#e8e8e4\]:where(.dark,.dark *):hover{color:#e8e8e4}.dark\:hover\:shadow-\[0_2px_6px_rgba\(0\,0\,0\,0\.55\)\,0_16px_36px_-20px_rgba\(0\,0\,0\,0\.8\)\]:where(.dark,.dark *):hover{--tw-shadow:0 2px 6px var(--tw-shadow-color,#0000008c), 0 16px 36px -20px var(--tw-shadow-color,#000c);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.dark\:focus\:border-\[\#6aa583\]:where(.dark,.dark *):focus{border-color:#6aa583}.dark\:focus\:bg-\[\#1B1C20\]:where(.dark,.dark *):focus{background-color:#1b1c20}.dark\:focus-visible\:ring-\[\#6aa583\]\/40:where(.dark,.dark *):focus-visible{--tw-ring-color:oklab(67.1614% -.0742714 .0298978/.4)}.\[\&_button\]\:h-7 button{height:calc(var(--spacing) * 7)}.\[\&_button\]\:w-7 button{width:calc(var(--spacing) * 7)}.\[\&_button\]\:border-b button{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_button\]\:border-\[\#eef1f5\] button{border-color:#eef1f5}.\[\&_button\]\:bg-white button{background-color:var(--color-white)}.\[\&_button\]\:text-\[\#5b6472\] button{color:#5b6472}.\[\&_button\:hover\]\:bg-\[\#f5f7fa\] button:hover{background-color:#f5f7fa}}.af-canvas{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--bg:#f4f5f2;--fg:#1c1c1a;--line:#e2e4e0;--accent:#c2410c;--ink:#24543f;--muted:#6b6b66;--mono:ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;height:100%;color:var(--fg);background:var(--bg);-webkit-font-smoothing:antialiased;margin:0;font-family:-apple-system,BlinkMacSystemFont,PingFang SC,Hiragino Sans GB,Microsoft YaHei,ui-sans-serif,sans-serif;font-size:15px;line-height:1.65;transition:background .2s,color .2s;position:relative}.af-canvas.dark{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--bg:#121312;--fg:#e8e8e4;--line:#262724;--accent:#f97316;--ink:#6aa583;--muted:#8b8b85}.af-canvas .mono{font-family:var(--mono);font-variant-numeric:tabular-nums;letter-spacing:-.01em}.af-canvas .react-flow__node{font-family:inherit}.af-canvas .react-flow__handle{background:#b9bcb4;border:2px solid #fff;width:9px;height:9px;transition:background .15s,transform .15s}.af-canvas.dark .react-flow__handle{background:#4a4d47;border-color:#1a1b19}.af-canvas .react-flow__handle:hover{background:var(--ink);transform:scale(1.25)}.af-canvas .react-flow__controls{border:1px solid var(--line);border-radius:8px;overflow:hidden;box-shadow:0 1px 3px #0000000f}.af-canvas .react-flow__controls-button{border-color:var(--line);color:#3f3f3a;fill:#3f3f3a;background:#fff}.af-canvas .react-flow__controls-button:hover{background:#f0f1ed}.af-canvas.dark .react-flow__controls{border-color:var(--line);background:#1a1b19}.af-canvas.dark .react-flow__controls-button{border-color:var(--line);color:#c9cec7;fill:#c9cec7;background:#1a1b19}.af-canvas.dark .react-flow__controls-button:hover{background:#232421}.af-canvas .react-flow__minimap{border:1px solid var(--line);border-radius:8px;overflow:hidden}.af-canvas.dark .react-flow__minimap{border-color:var(--line);background:#151614}.af-canvas .react-flow__node:focus-visible{outline:2px solid var(--ink);outline-offset:3px}@keyframes af-bar-scan{0%{transform:translate(-120%)}to{transform:translate(240%)}}.af-canvas .af-bar-scan{background:linear-gradient(90deg,#fff0 0%,#fffffff2 50%,#fff0 100%);animation:1.2s linear infinite af-bar-scan}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}
|