@davidbalzan/groundwork-console 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/answered.js +35 -2
- package/dist/groundwork.js +8 -3
- package/dist/mcp.js +12 -1
- package/dist/provision.js +23 -2
- package/dist/seam.js +4 -0
- package/dist/server.js +39 -7
- package/package.json +1 -1
- package/public/assets/{abnfDiagram-N423BO3Z-B9qt2Lrn.js → abnfDiagram-N423BO3Z-DjcI5EtN.js} +1 -1
- package/public/assets/{arc-Bu5e98OE.js → arc-CLreMRTi.js} +1 -1
- package/public/assets/architecture-TIHT7OUA-BxHBbCM_.js +1 -0
- package/public/assets/{architectureDiagram-T3A2C74G-C9YgdNEk.js → architectureDiagram-T3A2C74G-GVsKASaE.js} +1 -1
- package/public/assets/{blockDiagram-VBNYF7ZC-KV2ZfVrI.js → blockDiagram-VBNYF7ZC-kUIhKmE4.js} +1 -1
- package/public/assets/{c4Diagram-5PPSVZJV-BOIhWD29.js → c4Diagram-5PPSVZJV-BQFI1po0.js} +1 -1
- package/public/assets/channel-DiEdto8Z.js +1 -0
- package/public/assets/{chunk-2GRJ4B5K-BOYqDFv-.js → chunk-2GRJ4B5K-CAC9E6Lc.js} +1 -1
- package/public/assets/{chunk-4I5QYGJK-aPXqNUlF.js → chunk-4I5QYGJK-Do801ucH.js} +1 -1
- package/public/assets/{chunk-5RXB4S5H-BESU8h4l.js → chunk-5RXB4S5H-DgGb8Ei0.js} +1 -1
- package/public/assets/{chunk-6Q2QTUOP-Dy_tviVm.js → chunk-6Q2QTUOP-N3v574-9.js} +1 -1
- package/public/assets/{chunk-7Z6QIM7H-CViytsd0.js → chunk-7Z6QIM7H-BGVpdvGU.js} +1 -1
- package/public/assets/{chunk-GF5L2VYU-Bw_WxctK.js → chunk-GF5L2VYU-CyQ84gnX.js} +1 -1
- package/public/assets/{chunk-I66GZJ75-CyLcz-VG.js → chunk-I66GZJ75-Bazokq-r.js} +1 -1
- package/public/assets/{chunk-JQJVKLGR-BehQOyT2.js → chunk-JQJVKLGR-BXG1sCkI.js} +1 -1
- package/public/assets/{chunk-KBJHAD2P-Cv0WMvkU.js → chunk-KBJHAD2P-Bi0agcVN.js} +1 -1
- package/public/assets/{chunk-NSK5VX7P-Duq5i1Q8.js → chunk-NSK5VX7P-CRNBZms6.js} +1 -1
- package/public/assets/{chunk-QR6OTTB3-Xi-RqgB3.js → chunk-QR6OTTB3-BVNnO0nC.js} +1 -1
- package/public/assets/{chunk-RYQCIY6F-pkCoj5q-.js → chunk-RYQCIY6F-BDA4j6A-.js} +1 -1
- package/public/assets/{chunk-UBXNYLIW-BRvAYX25.js → chunk-UBXNYLIW-DGeBgwe-.js} +1 -1
- package/public/assets/{chunk-W5SLKNZC-Bjt98ztx.js → chunk-W5SLKNZC-xcy3l2eH.js} +1 -1
- package/public/assets/{chunk-WRU74C26-a9B5o7qU.js → chunk-WRU74C26-CIO3U59-.js} +1 -1
- package/public/assets/{chunk-XXDRQBXY-KvoTdu-7.js → chunk-XXDRQBXY-lsNR2odJ.js} +1 -1
- package/public/assets/classDiagram-JCYQIIEL-DQfOF2lx.js +1 -0
- package/public/assets/classDiagram-v2-OCEON4UE-DQfOF2lx.js +1 -0
- package/public/assets/{cose-bilkent-JH36ORCC-N6ziZwxK.js → cose-bilkent-JH36ORCC-Dgq33rVP.js} +1 -1
- package/public/assets/{cynefin-VYW2F7L2-CIULy749.js → cynefin-VYW2F7L2-BHP3DZqn.js} +1 -1
- package/public/assets/{cynefinDiagram-MW4NZA55-Du-pmosA.js → cynefinDiagram-MW4NZA55-BmxpLFSH.js} +1 -1
- package/public/assets/{dagre-VZM6K2ZE-HGby89Zn.js → dagre-VZM6K2ZE-3sD0lAzD.js} +1 -1
- package/public/assets/{diagram-7IWD3JNH-B7q3-bCI.js → diagram-7IWD3JNH-CyaD0_jh.js} +1 -1
- package/public/assets/{diagram-B4RE2ZJO-YWiWiMdK.js → diagram-B4RE2ZJO-td2N4qE1.js} +1 -1
- package/public/assets/{diagram-LBJQPF4R-BPCYGRvd.js → diagram-LBJQPF4R-D_wWDJ4F.js} +1 -1
- package/public/assets/{diagram-Q27KOJAE-B2LXUwVb.js → diagram-Q27KOJAE-DKPs8Pt1.js} +1 -1
- package/public/assets/{diagram-UB23O5K3-BNVtmpPQ.js → diagram-UB23O5K3-DMH09z4H.js} +1 -1
- package/public/assets/{dist-BVRuovsg.js → dist-BFMCu1a5.js} +1 -1
- package/public/assets/{ebnfDiagram-BXEA7PRR-BWXGcOBy.js → ebnfDiagram-BXEA7PRR-Cl2AEyY9.js} +1 -1
- package/public/assets/{erDiagram-JOGREHBK-Bs7Rt9fE.js → erDiagram-JOGREHBK-CyAJ5sjB.js} +1 -1
- package/public/assets/eventmodeling-45OFAUF4-CA3qsYNk.js +1 -0
- package/public/assets/flowDiagram-UKHOOZJN-BmCE-89P.js +1 -0
- package/public/assets/{ganttDiagram-PKOTCBZU-76WOMwTJ.js → ganttDiagram-PKOTCBZU-YM9FA8H8.js} +1 -1
- package/public/assets/{gitGraph-TEB2WS4Q-ChX3jwy9.js → gitGraph-TEB2WS4Q-ws9TESN2.js} +1 -1
- package/public/assets/{gitGraphDiagram-DS77QQ5N-Df90jw60.js → gitGraphDiagram-DS77QQ5N-CZu8bXTF.js} +1 -1
- package/public/assets/{index-Duxs51eO.js → index-C84drWhX.js} +12 -12
- package/public/assets/{info-DKCQHKI2-B4sk1tEu.js → info-DKCQHKI2-RSQw6txJ.js} +1 -1
- package/public/assets/{infoDiagram-6WML65LV-CwHXQy_Y.js → infoDiagram-6WML65LV-Bxmxzous.js} +1 -1
- package/public/assets/{ishikawaDiagram-WSZJBQD7-9Wx7fEa-.js → ishikawaDiagram-WSZJBQD7-C80fxFdg.js} +1 -1
- package/public/assets/{journeyDiagram-NVQOT4AX-YjyFj4j3.js → journeyDiagram-NVQOT4AX-DQTG0OdM.js} +1 -1
- package/public/assets/{kanban-definition-27J2QSJJ-CCSVpJmG.js → kanban-definition-27J2QSJJ-B5WxFLvF.js} +1 -1
- package/public/assets/{line-BNlogVke.js → line-D-jeoEtL.js} +1 -1
- package/public/assets/{linear-DtHynSNJ.js → linear-7oKWtFDc.js} +1 -1
- package/public/assets/{mermaid-parser.core-Tzw7YIHZ.js → mermaid-parser.core-DG-hDTtF.js} +3 -3
- package/public/assets/{mermaid.core-BYlHVIMn.js → mermaid.core-CxtgV-Z8.js} +4 -4
- package/public/assets/{mindmap-definition-FAOFIHXS-D3RdOamQ.js → mindmap-definition-FAOFIHXS-DyT9O-XZ.js} +1 -1
- package/public/assets/{packet-7NZHBO7P-Gg9ynt_Q.js → packet-7NZHBO7P-fYfZRQ_r.js} +1 -1
- package/public/assets/{pegDiagram-VL7TDLO6-CF8QpCrl.js → pegDiagram-VL7TDLO6-BIKwmoZk.js} +1 -1
- package/public/assets/{pie-RZYD4A2V-tZaCjWV1.js → pie-RZYD4A2V-hHye9M3B.js} +1 -1
- package/public/assets/{pieDiagram-7S7Q4E2Y-q9v-b_KS.js → pieDiagram-7S7Q4E2Y-B9IF9fZk.js} +1 -1
- package/public/assets/{quadrantDiagram-CIZ2JOQS-C1jEdjlT.js → quadrantDiagram-CIZ2JOQS-CriT2z0D.js} +1 -1
- package/public/assets/{radar-I7S5WNFK-Dq9mh9W6.js → radar-I7S5WNFK-UHbLAuY0.js} +1 -1
- package/public/assets/{railroad-3IZDKUUU-Di1R2Dd0.js → railroad-3IZDKUUU-3enNyn3l.js} +1 -1
- package/public/assets/railroad-abnf-AHOZXSZD-CxQOPSx1.js +1 -0
- package/public/assets/railroad-ebnf-EBAXGLYW-CQ4P6ont.js +1 -0
- package/public/assets/railroad-peg-LSFZ7HO6-sSkmKuAv.js +1 -0
- package/public/assets/{railroadDiagram-AXF67PYL-LvRdE_s1.js → railroadDiagram-AXF67PYL-Bkr9TUm0.js} +1 -1
- package/public/assets/{requirementDiagram-LRYGKXZP-BnZ07FeK.js → requirementDiagram-LRYGKXZP-CEp-ppYZ.js} +1 -1
- package/public/assets/{sankeyDiagram-W5VNT64P-E8-ON6IS.js → sankeyDiagram-W5VNT64P-CU-4IBMj.js} +1 -1
- package/public/assets/{sequenceDiagram-SI44F4Z6-DlVaUXz0.js → sequenceDiagram-SI44F4Z6-Asi631mZ.js} +1 -1
- package/public/assets/{src-qdf2s-T4.js → src-CJc45UuW.js} +1 -1
- package/public/assets/{stateDiagram-OKZ733FA-B9ThZGE5.js → stateDiagram-OKZ733FA-DkDphzLX.js} +1 -1
- package/public/assets/stateDiagram-v2-UEYNNEHI-DUHdaHkv.js +1 -0
- package/public/assets/{swimlanes-SLNWSIFB-DtPuEFdj.js → swimlanes-SLNWSIFB-BVnRBmZ_.js} +1 -1
- package/public/assets/swimlanesDiagram-ULZ7WXOC-RkUs-XHd.js +8 -0
- package/public/assets/{timeline-definition-Z64GVDOM-BR4Z5jFy.js → timeline-definition-Z64GVDOM-B3jYbkKD.js} +1 -1
- package/public/assets/{treeView-QDETBFTQ-BgvlYe1u.js → treeView-QDETBFTQ-FZndVHM1.js} +1 -1
- package/public/assets/{treemap-6X3UGDF4-BIP2RMFS.js → treemap-6X3UGDF4-CKoOe0fa.js} +1 -1
- package/public/assets/{vennDiagram-T6HMQDX7-DA80iXM-.js → vennDiagram-T6HMQDX7-B7qlSH-y.js} +1 -1
- package/public/assets/{wardley-OPB4EBWU-Dcxb0gTX.js → wardley-OPB4EBWU-DlWXVdBE.js} +1 -1
- package/public/assets/{wardleyDiagram-T6FBY63Y-i2RYxGIr.js → wardleyDiagram-T6FBY63Y-Dk0uBYWd.js} +1 -1
- package/public/assets/{xychartDiagram-ELKLHX3M-BWEBGjsc.js → xychartDiagram-ELKLHX3M-BDrlWQ3J.js} +1 -1
- package/public/index.html +1 -1
- package/public/assets/architecture-TIHT7OUA-Bga-lAng.js +0 -1
- package/public/assets/channel-BdIShFYL.js +0 -1
- package/public/assets/classDiagram-JCYQIIEL-D2R4WmWG.js +0 -1
- package/public/assets/classDiagram-v2-OCEON4UE-D2R4WmWG.js +0 -1
- package/public/assets/eventmodeling-45OFAUF4-DNrXe8VH.js +0 -1
- package/public/assets/flowDiagram-UKHOOZJN-Bx68YkAo.js +0 -1
- package/public/assets/railroad-abnf-AHOZXSZD-CUlgmRQa.js +0 -1
- package/public/assets/railroad-ebnf-EBAXGLYW-sFLjr1iD.js +0 -1
- package/public/assets/railroad-peg-LSFZ7HO6-BjRYu4TF.js +0 -1
- package/public/assets/stateDiagram-v2-UEYNNEHI-Bt0yXMXs.js +0 -1
- package/public/assets/swimlanesDiagram-ULZ7WXOC-MLUjmCjx.js +0 -8
package/dist/answered.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
/* Console-owned "answered" set for DAVID_DECISION packets (room posts + DMs), keyed by message id.
|
|
@@ -31,4 +31,37 @@ export function markAnswered(ids, meta) {
|
|
|
31
31
|
}
|
|
32
32
|
return n;
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
/* Bus-native answered set (kit ≥ 18ffbf4): any message FROM david carrying inReplyTo:<id> answers <id>. Scanned from ~/agent-coord inbox/*.jsonl + rooms/*.jsonl, cached 10 s. Unioned with the console-owned set above. */
|
|
35
|
+
let busCache = null;
|
|
36
|
+
let coordRoot = null;
|
|
37
|
+
export function setCoordDir(dir) { coordRoot = dir; }
|
|
38
|
+
function busAnswered() {
|
|
39
|
+
if (!coordRoot)
|
|
40
|
+
return new Set();
|
|
41
|
+
if (busCache && Date.now() - busCache.at < 10_000)
|
|
42
|
+
return busCache.ids;
|
|
43
|
+
const ids = new Set();
|
|
44
|
+
for (const sub of ["inbox", "rooms"]) {
|
|
45
|
+
const dir = path.join(coordRoot, sub);
|
|
46
|
+
if (!existsSync(dir))
|
|
47
|
+
continue;
|
|
48
|
+
for (const f of readdirSync(dir).filter((n) => n.endsWith(".jsonl"))) {
|
|
49
|
+
try {
|
|
50
|
+
for (const l of readFileSync(path.join(dir, f), "utf8").split("\n")) {
|
|
51
|
+
if (!l.includes("inReplyTo"))
|
|
52
|
+
continue;
|
|
53
|
+
try {
|
|
54
|
+
const m = JSON.parse(l);
|
|
55
|
+
if (m.from === "david" && typeof m.inReplyTo === "string")
|
|
56
|
+
ids.add(m.inReplyTo);
|
|
57
|
+
}
|
|
58
|
+
catch { /* skip */ }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch { /* skip */ }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
busCache = { at: Date.now(), ids };
|
|
65
|
+
return ids;
|
|
66
|
+
}
|
|
67
|
+
export const isAnswered = (id) => typeof id === "string" && (!!answered()[id] || busAnswered().has(id));
|
package/dist/groundwork.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* Groundwork + playbook CLIs, JSON mode (shipped by grok 2026-08-16). Cached briefly; both are read-only commands. */
|
|
2
2
|
import { execFile } from "node:child_process";
|
|
3
|
-
import path from "node:path";
|
|
4
3
|
import { promisify } from "node:util";
|
|
5
4
|
const run = promisify(execFile);
|
|
6
5
|
const cache = new Map();
|
|
@@ -9,6 +8,11 @@ async function json(key, ttl, argv, fallback) {
|
|
|
9
8
|
if (hit && Date.now() - hit.at < ttl)
|
|
10
9
|
return hit.value;
|
|
11
10
|
let value;
|
|
11
|
+
if (argv[0] === MISSING) {
|
|
12
|
+
value = { ...fallback, ranAt: Date.now(), error: `${key.startsWith("pb") ? "agent-coordination" : "groundwork"} CLI not found — npm i -g (or set kitPath to a kit checkout)` };
|
|
13
|
+
cache.set(key, { at: Date.now(), value });
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
12
16
|
try {
|
|
13
17
|
const r = await run("node", argv, { timeout: 20_000, maxBuffer: 4 << 20 });
|
|
14
18
|
value = { ...JSON.parse(r.stdout), ranAt: Date.now() };
|
|
@@ -26,8 +30,9 @@ async function json(key, ttl, argv, fallback) {
|
|
|
26
30
|
return value;
|
|
27
31
|
}
|
|
28
32
|
import { groundworkCli, playbookCli } from "./kitresolve.js";
|
|
29
|
-
const
|
|
30
|
-
const
|
|
33
|
+
const MISSING = "/dev/null/missing-cli"; // resolver found nothing → the run fails fast with a clear message below instead of a fake kit path
|
|
34
|
+
const gw = (kit) => groundworkCli(kit) ?? MISSING;
|
|
35
|
+
const pb = (kit) => playbookCli(kit) ?? MISSING;
|
|
31
36
|
export const doctor = (kit, proj) => json(`doctor:${proj}`, 30_000, [gw(kit), "doctor", proj, "--json"], { ok: false, exit: 1, checks: [], ranAt: 0 });
|
|
32
37
|
export const status = (kit, proj) => json(`status:${proj}`, 15_000, [gw(kit), "status", proj, "--json"], { streams: [], next: null, queueFound: false, phases: [], ranAt: 0 });
|
|
33
38
|
export const list = (kit, proj) => json(`list:${proj}`, 60_000, [gw(kit), "list", proj, "--json"], { version: "", project: proj, skills: [], ranAt: 0 });
|
package/dist/mcp.js
CHANGED
|
@@ -54,7 +54,8 @@ export class BusClient {
|
|
|
54
54
|
this.identity = identity;
|
|
55
55
|
this.mcpPath = mcpPath;
|
|
56
56
|
}
|
|
57
|
-
get serverPath() {
|
|
57
|
+
get serverPath() { const p = this.mcpPath ?? mcpServer(this.kitPath); if (!p)
|
|
58
|
+
throw new Error("agent-coord-mcp not found — npm i -g agent-coord-mcp (or set kitPath to a kit checkout)"); return p; }
|
|
58
59
|
get agentId() { return IDENTITIES[this.identity].agentId; }
|
|
59
60
|
async connect(log) {
|
|
60
61
|
if (this.client)
|
|
@@ -72,6 +73,13 @@ export class BusClient {
|
|
|
72
73
|
await client.connect(transport);
|
|
73
74
|
const reg = await client.callTool({ name: "register", arguments: { agentId: id.agentId, project: id.project, role: id.role, force: true } });
|
|
74
75
|
log?.(`register → ${JSON.stringify(reg.structuredContent ?? textOf(reg)).slice(0, 160)}`);
|
|
76
|
+
// Feature detection: which args each tool accepts (e.g. send_message.inReplyTo landed in kit 18ffbf4; the live bin may predate it).
|
|
77
|
+
try {
|
|
78
|
+
const tools = await client.listTools();
|
|
79
|
+
for (const t of tools.tools)
|
|
80
|
+
this.toolArgs.set(t.name, new Set(Object.keys(t.inputSchema?.properties ?? {})));
|
|
81
|
+
}
|
|
82
|
+
catch { /* older server: no detection, pass nothing extra */ }
|
|
75
83
|
this.client = client;
|
|
76
84
|
return client;
|
|
77
85
|
})();
|
|
@@ -82,6 +90,9 @@ export class BusClient {
|
|
|
82
90
|
this.connecting = null;
|
|
83
91
|
}
|
|
84
92
|
}
|
|
93
|
+
toolArgs = new Map();
|
|
94
|
+
/** True when the connected server's tool schema lists this argument (false when unknown or not connected yet). */
|
|
95
|
+
supports(tool, arg) { return this.toolArgs.get(tool)?.has(arg) ?? false; }
|
|
85
96
|
async call(name, args, log) {
|
|
86
97
|
const isWrite = WRITE_TOOLS_GATED.has(name);
|
|
87
98
|
if (!READ_ONLY_TOOLS.has(name) && !isWrite)
|
package/dist/provision.js
CHANGED
|
@@ -25,7 +25,7 @@ async function fleetWindow(project, startDir, log) {
|
|
|
25
25
|
log(`created window ${win} in session ${session} (first pane ${pane} reused for the first agent — no spare shell)`);
|
|
26
26
|
return { target: `${session}:${win}`, freshPane: pane };
|
|
27
27
|
}
|
|
28
|
-
export async function spawnAgent(req, isRegistered, log, isAttached = () => true) {
|
|
28
|
+
export async function spawnAgent(req, isRegistered, log, isAttached = () => true, roleOf = () => null) {
|
|
29
29
|
if (!/^[a-z0-9][a-z0-9-_]*$/i.test(req.agentId))
|
|
30
30
|
throw new Error("agentId: letters, digits, - _");
|
|
31
31
|
if (isRegistered(req.agentId))
|
|
@@ -91,7 +91,28 @@ export async function spawnAgent(req, isRegistered, log, isAttached = () => true
|
|
|
91
91
|
}
|
|
92
92
|
log(attached ? `✓ ${req.agentId} attached (tmux-push) — DMs will land in ${paneId}` : `✗ ${req.agentId} still not attached — DMs will sit in its inbox until it attaches (Fleets shows "not attached")`);
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
// Role: every spawned agent must carry its role type on the bus (presence bar, fleet graph, Fix→role routing all key on it). If it registered without one, tell it — into its own pane — and re-check.
|
|
95
|
+
const ROLE_RE = { coordinator: /coordinator/i, worker: /worker|repo-owner|consumer-owner|reference|infra|ops|lane/i, qa: /\bqa\b|quality/i, ci: /\bci\b/i, aide: /aide|liaison|curator/i, audit: /audit/i };
|
|
96
|
+
let roleOk = false;
|
|
97
|
+
if (registered) {
|
|
98
|
+
roleOk = ROLE_RE[req.role].test(roleOf(req.agentId) ?? "");
|
|
99
|
+
if (!roleOk) {
|
|
100
|
+
log(`⚠ registered without a ${req.role} role (role="${roleOf(req.agentId) ?? ""}") — asking it to declare one`);
|
|
101
|
+
await inject(`Declare your role on the coord bus now: call register (or join) again with agentId ${req.agentId} and role: { roleId: "coord-${req.role === "coordinator" ? "coordinator" : req.role}", displayName: "${req.role}" } — the console, fleet graph and Fix→role routing rely on it.`);
|
|
102
|
+
const d4 = Date.now() + 45_000;
|
|
103
|
+
while (Date.now() < d4) {
|
|
104
|
+
if (ROLE_RE[req.role].test(roleOf(req.agentId) ?? "")) {
|
|
105
|
+
roleOk = true;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
await sleep(2_000);
|
|
109
|
+
}
|
|
110
|
+
log(roleOk ? `✓ role declared: ${roleOf(req.agentId)}` : `✗ still no ${req.role} role — Fleets will show it as "—"; DM it to fix`);
|
|
111
|
+
}
|
|
112
|
+
else
|
|
113
|
+
log(`✓ role: ${roleOf(req.agentId)}`);
|
|
114
|
+
}
|
|
115
|
+
return { agentId: req.agentId, pane: paneId, window: target, registered, attached, roleOk };
|
|
95
116
|
}
|
|
96
117
|
export function suggestId(project, role, existing) {
|
|
97
118
|
const base = `${project}-${role}`;
|
package/dist/seam.js
CHANGED
|
@@ -18,8 +18,12 @@ export function boardOf(projectPath) {
|
|
|
18
18
|
const dDoc = d ? parseWorkDoc(d) : null;
|
|
19
19
|
const facts = f ? parseFactsDoc(f) : null;
|
|
20
20
|
const now = Date.now();
|
|
21
|
+
// Onboarding state for the Roadmap empty state: is there a PRD, and what does its Status line say?
|
|
22
|
+
const prdSrc = read(path.join(docs, "PRD.md"));
|
|
23
|
+
const prd = prdSrc === null ? null : { status: prdSrc.match(/^\*\*Status\*\*:\s*([^\n]+)/m)?.[1]?.trim() ?? null, roadmap: existsSync(path.join(docs, "PRODUCTION_ROADMAP.md")) };
|
|
21
24
|
return {
|
|
22
25
|
files: { workstreams: !!ws, queue: !!q, done: !!d, facts: !!f },
|
|
26
|
+
prd,
|
|
23
27
|
workstreams: { schema: schema ?? (ws ? "unknown" : null), rows: board, issues: wsDoc ? workDocIssues(wsDoc) : [] },
|
|
24
28
|
queue: qDoc ? queueItemsOf(qDoc) : [],
|
|
25
29
|
done: dDoc ? doneEntriesOf(dDoc) : [],
|
package/dist/server.js
CHANGED
|
@@ -8,6 +8,7 @@ import { serve } from "@hono/node-server";
|
|
|
8
8
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
9
9
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
10
10
|
import path from "node:path";
|
|
11
|
+
import { hostname as osHostname } from "node:os";
|
|
11
12
|
import { loadConfig, saveProjects, validateProjectPath, CONFIG_FILE } from "./config.js";
|
|
12
13
|
import { boardOf, docOf, docsIndex, phaseTasksOf } from "./seam.js";
|
|
13
14
|
import { DocWriteError, sha256, writeDoc } from "./docwrite.js";
|
|
@@ -26,7 +27,7 @@ import { BusClient, AGENT_ID, busWrites, seamWrites, saveSwitches, SWITCHES_FILE
|
|
|
26
27
|
import { addQueueItem, reverifyFact, scopeAllows } from "./seamwrite.js";
|
|
27
28
|
import { fileURLToPath } from "node:url";
|
|
28
29
|
import { saveUpload, uploadPath, UPLOAD_DIR } from "./uploads.js";
|
|
29
|
-
import { answered, markAnswered, isAnswered } from "./answered.js";
|
|
30
|
+
import { answered, markAnswered, isAnswered, setCoordDir } from "./answered.js";
|
|
30
31
|
import { requireAuth, login, logout, isAuthed, authEnabled, tokenFile } from "./auth.js";
|
|
31
32
|
import { knowledgeIndex, knowledgeDoc, knowledgePath } from "./knowledge.js";
|
|
32
33
|
import { requiresReport, groundworkCli, playbookCli, packageRoot, REQUIRES } from "./kitresolve.js";
|
|
@@ -36,6 +37,7 @@ const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
|
36
37
|
const RULES = process.env.GROUNDWORK_CONSOLE_RULES ?? [path.join(process.env.HOME ?? "", ".groundwork-console", "rules.json"), path.resolve(HERE, "../groundwork-console.rules.json"), path.resolve(HERE, "../../../groundwork-console.rules.json")].find((f) => existsSync(f)) ?? path.resolve(HERE, "../../../groundwork-console.rules.json");
|
|
37
38
|
const PKG = JSON.parse(readFileSync(path.resolve(HERE, "../package.json"), "utf8"));
|
|
38
39
|
const runs = new Runs();
|
|
40
|
+
setCoordDir(cfg.coordDir);
|
|
39
41
|
const bus = new BusClient(cfg.kitPath, cfg.coordDir, "groundwork-console", process.env.AGENT_COORD_MCP);
|
|
40
42
|
const events = new EventEngine(cfg, RULES, runs, (args, log) => bus.call("send_message", args, log));
|
|
41
43
|
const notifier = new Notifier(cfg, runs, events);
|
|
@@ -55,7 +57,7 @@ app.post("/auth/logout", (c) => { logout(c); return c.json({ ok: true }); });
|
|
|
55
57
|
app.get("/auth/login", (c) => { const t = c.req.query("token") ?? ""; if (!login(c, t))
|
|
56
58
|
return c.json({ error: "wrong token" }, 401); return c.redirect(c.req.query("next") ?? "/"); });
|
|
57
59
|
const project = (name) => cfg.projects.find((p) => p.name === name);
|
|
58
|
-
app.get("/health", (c) => c.json({ ok: true, readOnly: !busWrites.enabled, busWrites: busWrites.enabled, version: PKG.version, requires: requiresReport(cfg.kitPath), config: CONFIG_FILE }));
|
|
60
|
+
app.get("/health", (c) => c.json({ ok: true, readOnly: !busWrites.enabled, busWrites: busWrites.enabled, version: PKG.version, requires: requiresReport(cfg.kitPath), config: CONFIG_FILE, hostname: osHostname().replace(/\.local$/, "") }));
|
|
59
61
|
app.get("/admin/bus-writes", (c) => c.json(busWrites));
|
|
60
62
|
app.get("/admin/seam-writes", (c) => c.json(seamWrites));
|
|
61
63
|
app.post("/admin/seam-writes", async (c) => {
|
|
@@ -112,7 +114,13 @@ app.post("/actions/send", async (c) => {
|
|
|
112
114
|
return c.json({ error: "room posts need a prefix (FYI / AGENT_ACTION / DAVID_DECISION / BLOCKER / RISK / DONE / GO / SCOPE CHANGE / VERDICT)" }, 400);
|
|
113
115
|
const target = b.to ? `→ ${b.to}` : `#${b.room.replace(/^#/, "")}`;
|
|
114
116
|
const r = await runs.exec({ kind: "bus", label: `send as ${who} ${target}`, sideEffects: true, args: { as: who, room: b.room, to: b.to, kind: b.kind, text: b.text.slice(0, 200) } }, async (log) => {
|
|
115
|
-
const
|
|
117
|
+
const cl = clientFor(who);
|
|
118
|
+
await cl.connect(log);
|
|
119
|
+
const parent = b.inReplyTo ?? b.answers?.[0];
|
|
120
|
+
const withReply = parent && cl.supports("send_message", "inReplyTo") ? { inReplyTo: parent } : {};
|
|
121
|
+
if (parent && !("inReplyTo" in withReply))
|
|
122
|
+
log("bus predates inReplyTo — using the console-side answered set only");
|
|
123
|
+
const out = await cl.call("send_message", { ...(b.to ? { to: b.to } : { room: b.room.replace(/^#/, "") }), text: b.text, ...(b.kind ? { kind: b.kind } : {}), ...withReply }, log);
|
|
116
124
|
// Answered bookkeeping (console-owned, until the bus has inReplyTo): explicit ids from the UI, plus — for a DM as David — every open DAVID_DECISION DM from that agent.
|
|
117
125
|
if (who === "david") {
|
|
118
126
|
const ids = [...(b.answers ?? [])];
|
|
@@ -540,7 +548,9 @@ app.post("/actions/groundwork-update/:name", async (c) => {
|
|
|
540
548
|
const b = (await c.req.json().catch(() => ({})));
|
|
541
549
|
if (b.confirm !== p.name)
|
|
542
550
|
return c.json({ error: "confirm must equal the project name" }, 400);
|
|
543
|
-
const cli = groundworkCli(cfg.kitPath)
|
|
551
|
+
const cli = groundworkCli(cfg.kitPath);
|
|
552
|
+
if (!cli)
|
|
553
|
+
return c.json({ error: "groundwork CLI not found — npm i -g @davidbalzan/groundwork (or set kitPath to a kit checkout)" }, 500);
|
|
544
554
|
const argv = [cli, "update", p.path, ...(b.all ? ["--all"] : []), ...(b.docs ? ["--docs"] : [])];
|
|
545
555
|
const r = await runs.exec({ kind: "shell", label: `groundwork update · ${p.name}${b.all ? " --all" : ""}${b.docs ? " --docs" : ""}`, project: p.name, sideEffects: true, args: { argv: argv.slice(1) } }, async (log) => {
|
|
546
556
|
log(`$ node ${argv.map((a) => a.replace(cfg.kitPath, "<kit>").replace(p.path, "<repo>")).join(" ")}`);
|
|
@@ -559,7 +569,9 @@ app.post("/actions/playbook-update", async (c) => {
|
|
|
559
569
|
const dry = b.dryRun !== false;
|
|
560
570
|
if (!dry && b.confirm !== "UPDATE")
|
|
561
571
|
return c.json({ error: "confirm must be UPDATE to apply" }, 400);
|
|
562
|
-
const cli = playbookCli(cfg.kitPath)
|
|
572
|
+
const cli = playbookCli(cfg.kitPath);
|
|
573
|
+
if (!cli)
|
|
574
|
+
return c.json({ error: "agent-coordination CLI not found — npm i -g agent-coordination (or set kitPath to a kit checkout)" }, 500);
|
|
563
575
|
const argv = [cli, "update", ...(dry ? ["--dry-run"] : [])];
|
|
564
576
|
const r = await runs.exec({ kind: "shell", label: `agent-coordination update${dry ? " (dry-run)" : ""}`, sideEffects: !dry, args: { argv: argv.slice(1) } }, async (log) => {
|
|
565
577
|
log(`$ node ${argv.map((a) => a.replace(cfg.kitPath, "<kit>")).join(" ")}`);
|
|
@@ -579,6 +591,7 @@ app.get("/projects/:name/fleet", async (c) => {
|
|
|
579
591
|
const live = (await agentsAsync(cfg.coordDir)).filter((a) => a.liveness !== "dead" && (a.project === p.room || a.project === p.name));
|
|
580
592
|
return c.json({ ...fleetStatus(live), templates: FLEET_TEMPLATES, window: `fleet-${p.name}` });
|
|
581
593
|
});
|
|
594
|
+
const roleOfAgent = (id) => agents(cfg.coordDir).find((a) => a.agentId === id)?.role ?? null;
|
|
582
595
|
app.post("/actions/spawn-fleet", async (c) => {
|
|
583
596
|
if (!busWrites.enabled)
|
|
584
597
|
return c.json({ error: "bus writes are off (header toggle)" }, 403);
|
|
@@ -600,7 +613,7 @@ app.post("/actions/spawn-fleet", async (c) => {
|
|
|
600
613
|
for (const step of plan) {
|
|
601
614
|
const agentId = suggestId(p.name, step.role, [...ids(), ...out.map((o) => o.agentId)]);
|
|
602
615
|
log(`── ${step.role} → ${agentId} (${step.harness})`);
|
|
603
|
-
const res = await spawnAgent({ project: p.name, repoPath: p.path, room: p.room, role: step.role, harness: step.harness, agentId, lane: step.lane, waitSeconds: b.waitSeconds }, (id) => ids().includes(id), log, attached);
|
|
616
|
+
const res = await spawnAgent({ project: p.name, repoPath: p.path, room: p.room, role: step.role, harness: step.harness, agentId, lane: step.lane, waitSeconds: b.waitSeconds }, (id) => ids().includes(id), log, attached, roleOfAgent);
|
|
604
617
|
out.push({ agentId: res.agentId, pane: res.pane, registered: res.registered, attached: res.attached });
|
|
605
618
|
}
|
|
606
619
|
log(`fleet ${t.id}: ${out.filter((o) => o.registered).length}/${out.length} registered · ${out.filter((o) => o.attached).length}/${out.length} attached`);
|
|
@@ -625,7 +638,7 @@ app.post("/actions/spawn", async (c) => {
|
|
|
625
638
|
const ids = () => agents(cfg.coordDir).map((a) => a.agentId);
|
|
626
639
|
const attached = (id) => existsSync(path.join(cfg.coordDir, "transports", `${id}.json`));
|
|
627
640
|
const agentId = b.agentId?.trim() || suggestId(p.name, b.role, ids());
|
|
628
|
-
const r = runs.execAsync({ kind: "shell", label: `spawn ${agentId} (${b.role} · ${b.harness}) → fleet-${p.name}`, project: p.name, sideEffects: true, args: { role: b.role, harness: b.harness, agentId, lane: b.lane, model: b.model } }, (log) => spawnAgent({ project: p.name, repoPath: p.path, room: p.room, role: b.role, harness: b.harness, agentId, lane: b.lane, model: b.model, note: b.note, waitSeconds: b.waitSeconds }, (id) => ids().includes(id), log, attached));
|
|
641
|
+
const r = runs.execAsync({ kind: "shell", label: `spawn ${agentId} (${b.role} · ${b.harness}) → fleet-${p.name}`, project: p.name, sideEffects: true, args: { role: b.role, harness: b.harness, agentId, lane: b.lane, model: b.model } }, (log) => spawnAgent({ project: p.name, repoPath: p.path, room: p.room, role: b.role, harness: b.harness, agentId, lane: b.lane, model: b.model, note: b.note, waitSeconds: b.waitSeconds }, (id) => ids().includes(id), log, attached, roleOfAgent));
|
|
629
642
|
return c.json(r);
|
|
630
643
|
});
|
|
631
644
|
/* ---- Gated bus admin: prune stale, unregister one (writes; require switch + confirm) ---- */
|
|
@@ -690,6 +703,25 @@ app.post("/actions/phase/:name/:phase/:verb", async (c) => {
|
|
|
690
703
|
const r = await runs.exec({ kind: "bus", label: `${verb} ${phase} → ${target}`, project: p.name, sideEffects: true, args: { to: target, text: text.slice(0, 200) } }, (log) => busDavid.call("send_message", { to: target, text }, log));
|
|
691
704
|
return c.json(r, r.status === "ok" ? 200 : 403);
|
|
692
705
|
});
|
|
706
|
+
/* ---- Project-level onboarding actions (as david → the aide): create-prd conversation starter, /kickstart ---- */
|
|
707
|
+
app.post("/actions/project/:name/:verb", async (c) => {
|
|
708
|
+
const p = project(c.req.param("name"));
|
|
709
|
+
if (!p)
|
|
710
|
+
return c.json({ error: "unknown project" }, 404);
|
|
711
|
+
const verb = c.req.param("verb");
|
|
712
|
+
const b = (await c.req.json().catch(() => ({})));
|
|
713
|
+
const target = roleAgent(p.name, p.room, /aide|liaison|curator/i);
|
|
714
|
+
if (!target)
|
|
715
|
+
return c.json({ error: `no live aide for ${p.name}` }, 409);
|
|
716
|
+
const text = verb === "kickstart"
|
|
717
|
+
? `AGENT_ACTION: run /kickstart in ${p.name} (${p.path}) — PRD is in docs/PRD.md; produce the roadmap + docs scaffold (TECH_STACK, ARCHITECTURE_GUIDE, DECISIONS, PRODUCTION_ROADMAP, WORKSTREAMS.v1, QUEUE, DONE, FACTS) and report when the doctor is clean.${b.note ? " Note: " + b.note : ""}`
|
|
718
|
+
: verb === "create-prd" ? `AGENT_ACTION: let's write the PRD for ${p.name} (${p.path}) — run /create-prd with me; ask what you need to know, keep it to one pass, Status: Draft until I approve.${b.note ? " Note: " + b.note : ""}`
|
|
719
|
+
: null;
|
|
720
|
+
if (!text)
|
|
721
|
+
return c.json({ error: "verb must be kickstart | create-prd" }, 400);
|
|
722
|
+
const r = await runs.exec({ kind: "bus", label: `${verb} → ${target}`, project: p.name, sideEffects: true, args: { to: target, text: text.slice(0, 200) } }, (log) => busDavid.call("send_message", { to: target, text }, log));
|
|
723
|
+
return c.json(r, r.status === "ok" ? 200 : 403);
|
|
724
|
+
});
|
|
693
725
|
/* ---- Doctor → Fix: route a doctor finding to the role that owns it (live agent required); sent as david ---- */
|
|
694
726
|
const DOCTOR_OWNER = {
|
|
695
727
|
"orphan-wikilinks": { role: "aide", re: /aide|liaison|curator/i, how: "fix the orphan wikilinks (create the target doc or correct the link); docs are your lane" },
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{m as e,t}from"./mermaid-parser.core-
|
|
1
|
+
import{m as e,t}from"./mermaid-parser.core-DG-hDTtF.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-CJc45UuW.js";import"./chunk-I66GZJ75-Bazokq-r.js";import{n as i,r as a,t as o}from"./chunk-6Q2QTUOP-N3v574-9.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-CxtgV-Z8.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-
|
|
1
|
+
import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-BFMCu1a5.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./chunk-KEIR6QF5-BICK3FdT.js";import{M as e}from"./mermaid-parser.core-DG-hDTtF.js";export{e as createArchitectureServices};
|