@statechange/council 0.6.0 → 0.8.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 +27 -27
- package/dist/cli.js +15 -15
- package/dist/cli.js.map +1 -1
- package/dist/commands/councilor.d.ts +7 -0
- package/dist/commands/councilor.js +98 -0
- package/dist/commands/councilor.js.map +1 -0
- package/dist/commands/discuss.d.ts +2 -2
- package/dist/commands/discuss.js +14 -14
- package/dist/commands/discuss.js.map +1 -1
- package/dist/commands/history.js +2 -2
- package/dist/commands/history.js.map +1 -1
- package/dist/commands/list.js +7 -7
- package/dist/commands/list.js.map +1 -1
- package/dist/core/conversation-engine.d.ts +3 -3
- package/dist/core/conversation-engine.js +35 -35
- package/dist/core/conversation-engine.js.map +1 -1
- package/dist/core/councilor-loader.d.ts +4 -0
- package/dist/core/councilor-loader.js +98 -0
- package/dist/core/councilor-loader.js.map +1 -0
- package/dist/core/councilor-registry.d.ts +12 -0
- package/dist/core/councilor-registry.js +131 -0
- package/dist/core/councilor-registry.js.map +1 -0
- package/dist/core/excalidraw-cheatsheet.js +2 -2
- package/dist/core/history.d.ts +1 -1
- package/dist/core/history.js +1 -1
- package/dist/core/history.js.map +1 -1
- package/dist/core/infographic.js +4 -4
- package/dist/core/infographic.js.map +1 -1
- package/dist/core/output-formatter.js +2 -2
- package/dist/core/output-formatter.js.map +1 -1
- package/dist/core/secretary.js +7 -7
- package/dist/core/secretary.js.map +1 -1
- package/dist/core/skill-loader.d.ts +2 -2
- package/dist/core/skill-loader.js +6 -6
- package/dist/core/skill-loader.js.map +1 -1
- package/dist/electron/ipc-handlers.js +29 -29
- package/dist/electron/ipc-handlers.js.map +1 -1
- package/dist/electron/preload.js +5 -5
- package/dist/electron/preload.js.map +1 -1
- package/dist/types.d.ts +16 -13
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist-electron/main.js +299 -296
- package/dist-electron/preload.mjs +1 -1
- package/dist-renderer/assets/{ar-SA-G6X2FPQ2-DXBh7WuV.js → ar-SA-G6X2FPQ2-DJTj94ZY.js} +1 -1
- package/dist-renderer/assets/{arc-D_n8J5SI.js → arc-3qXpUeCd.js} +1 -1
- package/dist-renderer/assets/{az-AZ-76LH7QW2-em6ZG9h0.js → az-AZ-76LH7QW2-1qnzBARG.js} +1 -1
- package/dist-renderer/assets/{bg-BG-XCXSNQG7-agu_XNxA.js → bg-BG-XCXSNQG7-BIZ5IFAv.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-38ab4fdb-D1jpM-pu.js → blockDiagram-38ab4fdb-JwSYiuLB.js} +1 -1
- package/dist-renderer/assets/{bn-BD-2XOGV67Q-Y2AVxREy.js → bn-BD-2XOGV67Q-DiYpgYAg.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-3d4e48cf-K75joZkc.js → c4Diagram-3d4e48cf-DUCtOTzV.js} +1 -1
- package/dist-renderer/assets/{ca-ES-6MX7JW3Y-DSUAGL6k.js → ca-ES-6MX7JW3Y-CV2JFVcm.js} +1 -1
- package/dist-renderer/assets/channel-BFQOS5-A.js +1 -0
- package/dist-renderer/assets/{classDiagram-70f12bd4-Dn1c2ZKw.js → classDiagram-70f12bd4-DY_je9I9.js} +1 -1
- package/dist-renderer/assets/{classDiagram-v2-f2320105-DwlW6q7H.js → classDiagram-v2-f2320105-Dm2xf0kS.js} +1 -1
- package/dist-renderer/assets/clone-BdgQjyvt.js +1 -0
- package/dist-renderer/assets/{createText-2e5e7dd3-BdGe-pcn.js → createText-2e5e7dd3-BU4YlynJ.js} +1 -1
- package/dist-renderer/assets/{cs-CZ-2BRQDIVT-DhhKBwfp.js → cs-CZ-2BRQDIVT-DgefxJv2.js} +1 -1
- package/dist-renderer/assets/{da-DK-5WZEPLOC-BXBIUFpK.js → da-DK-5WZEPLOC-CQeMoU_Y.js} +1 -1
- package/dist-renderer/assets/{de-DE-XR44H4JA-DdNoTfJ3.js → de-DE-XR44H4JA-Cm7XiExL.js} +1 -1
- package/dist-renderer/assets/{edges-e0da2a9e-B71iAGdZ.js → edges-e0da2a9e-DU4SF3SK.js} +1 -1
- package/dist-renderer/assets/{el-GR-BZB4AONW-CHvoll3l.js → el-GR-BZB4AONW-BKDtOlnf.js} +1 -1
- package/dist-renderer/assets/{erDiagram-9861fffd-CYB5wwYg.js → erDiagram-9861fffd-D_cCijmv.js} +1 -1
- package/dist-renderer/assets/{es-ES-U4NZUMDT-ndnyt5b3.js → es-ES-U4NZUMDT-Blb_L7K-.js} +1 -1
- package/dist-renderer/assets/{eu-ES-A7QVB2H4-4d18XNGh.js → eu-ES-A7QVB2H4-BZJBLMeO.js} +1 -1
- package/dist-renderer/assets/{fa-IR-HGAKTJCU-DslQwLpv.js → fa-IR-HGAKTJCU-C8gu07sI.js} +1 -1
- package/dist-renderer/assets/{fi-FI-Z5N7JZ37-DiHPxROG.js → fi-FI-Z5N7JZ37-0j8c6s09.js} +1 -1
- package/dist-renderer/assets/{flowDb-956e92f1-B9ZZIH6j.js → flowDb-956e92f1-BYeD7SW0.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-66a62f08-Dp2DmvQc.js → flowDiagram-66a62f08-D_7wXttk.js} +1 -1
- package/dist-renderer/assets/flowDiagram-v2-96b9c2cf-ue4yLZei.js +1 -0
- package/dist-renderer/assets/{flowchart-elk-definition-4a651766-CVmjBy5D.js → flowchart-elk-definition-4a651766-G1tSg-iY.js} +1 -1
- package/dist-renderer/assets/{fr-FR-RHASNOE6-DroH4cCM.js → fr-FR-RHASNOE6-_cfaQNNq.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-c361ad54-SGHeXdlJ.js → ganttDiagram-c361ad54-Dk5lBh7P.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-72cf32ee-fBlPRtHx.js → gitGraphDiagram-72cf32ee-BzJAQtIC.js} +1 -1
- package/dist-renderer/assets/{gl-ES-HMX3MZ6V-B5sN7Uzl.js → gl-ES-HMX3MZ6V-GM5nrSrW.js} +1 -1
- package/dist-renderer/assets/{graph-BUgnMBv6.js → graph-C_xi4PaI.js} +1 -1
- package/dist-renderer/assets/{he-IL-6SHJWFNN-BK97a2ym.js → he-IL-6SHJWFNN-DvBtF7-G.js} +1 -1
- package/dist-renderer/assets/{hi-IN-IWLTKZ5I-DCZlvEWO.js → hi-IN-IWLTKZ5I-CNEB0-5K.js} +1 -1
- package/dist-renderer/assets/{hu-HU-A5ZG7DT2-I8vGLYrC.js → hu-HU-A5ZG7DT2-BmzYfJwp.js} +1 -1
- package/dist-renderer/assets/{id-ID-SAP4L64H-D7Zj-WBO.js → id-ID-SAP4L64H-CGCjaOLU.js} +1 -1
- package/dist-renderer/assets/{index-3862675e-CqgKkg4w.js → index-3862675e-C8a4355J.js} +1 -1
- package/dist-renderer/assets/index-CYsh274_.css +1 -0
- package/dist-renderer/assets/index-Cc7m7vZn.js +51 -0
- package/dist-renderer/assets/{index-9YedcJtH.js → index-x_yLI1Xq.js} +4 -4
- package/dist-renderer/assets/{infoDiagram-f8f76790-DojFopZJ.js → infoDiagram-f8f76790-BsJdteru.js} +1 -1
- package/dist-renderer/assets/{it-IT-JPQ66NNP-BBWhTSgs.js → it-IT-JPQ66NNP-vK6cBs4I.js} +1 -1
- package/dist-renderer/assets/{ja-JP-DBVTYXUO-z4i_Gp8C.js → ja-JP-DBVTYXUO-oUvELdsq.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-49397b02-CJ36K1NH.js → journeyDiagram-49397b02-BZcn-joQ.js} +1 -1
- package/dist-renderer/assets/{kaa-6HZHGXH3-B_WtQlVr.js → kaa-6HZHGXH3-39-zh5xR.js} +1 -1
- package/dist-renderer/assets/{kab-KAB-ZGHBKWFO-DTtORPAb.js → kab-KAB-ZGHBKWFO-DIwwJSlv.js} +1 -1
- package/dist-renderer/assets/{kk-KZ-P5N5QNE5-CPVxS5Do.js → kk-KZ-P5N5QNE5-jEG0G6v4.js} +1 -1
- package/dist-renderer/assets/{km-KH-HSX4SM5Z-Cwm0mGEA.js → km-KH-HSX4SM5Z-f0MtADYu.js} +1 -1
- package/dist-renderer/assets/{ko-KR-MTYHY66A-B7XhlbiR.js → ko-KR-MTYHY66A-D0sjNbcb.js} +1 -1
- package/dist-renderer/assets/{ku-TR-6OUDTVRD-CPCWoAyz.js → ku-TR-6OUDTVRD-D_uqAOZU.js} +1 -1
- package/dist-renderer/assets/{layout--e2IpTlO.js → layout-Bho0HnCB.js} +1 -1
- package/dist-renderer/assets/{line-oAyHL3iY.js → line-BvfrpBJA.js} +1 -1
- package/dist-renderer/assets/{linear-BoN-rD3R.js → linear-CzjqC3F_.js} +1 -1
- package/dist-renderer/assets/{lt-LT-XHIRWOB4-CyI4_Tq3.js → lt-LT-XHIRWOB4-Ct0yC4CT.js} +1 -1
- package/dist-renderer/assets/{lv-LV-5QDEKY6T-DLljN33x.js → lv-LV-5QDEKY6T-nkNbPHg0.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-fc14e90a-CnLgRQ_O.js → mindmap-definition-fc14e90a-BHot8rEp.js} +1 -1
- package/dist-renderer/assets/{mr-IN-CRQNXWMA-CLAaPXvA.js → mr-IN-CRQNXWMA-B861rik7.js} +1 -1
- package/dist-renderer/assets/{my-MM-5M5IBNSE-EGw1M9CW.js → my-MM-5M5IBNSE-SOXg7PeE.js} +1 -1
- package/dist-renderer/assets/{nb-NO-T6EIAALU-CrpHBY71.js → nb-NO-T6EIAALU-D22gGzt7.js} +1 -1
- package/dist-renderer/assets/{nl-NL-IS3SIHDZ-BGiRPMkX.js → nl-NL-IS3SIHDZ-CJxOBLb1.js} +1 -1
- package/dist-renderer/assets/{nn-NO-6E72VCQL-Bg9--0vP.js → nn-NO-6E72VCQL-FGcbdlO3.js} +1 -1
- package/dist-renderer/assets/{oc-FR-POXYY2M6-3aNzRUH5.js → oc-FR-POXYY2M6-s7Swo1Cu.js} +1 -1
- package/dist-renderer/assets/{pa-IN-N4M65BXN-CQ1Qt20e.js → pa-IN-N4M65BXN-DFJMREPh.js} +1 -1
- package/dist-renderer/assets/{percentages-BXMCSKIN-BdcO8JE0.js → percentages-BXMCSKIN-BhceqxTM.js} +7 -7
- package/dist-renderer/assets/{pica-DAe8i4qi.js → pica-ej4Z4fjh.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-8a3498a8-C2C4gnpI.js → pieDiagram-8a3498a8-CnDnQfd0.js} +1 -1
- package/dist-renderer/assets/{pl-PL-T2D74RX3-DgbjC8Ll.js → pl-PL-T2D74RX3-uXVmB6im.js} +1 -1
- package/dist-renderer/assets/{pt-BR-5N22H2LF-DuWVGxtI.js → pt-BR-5N22H2LF-8kdgECeZ.js} +1 -1
- package/dist-renderer/assets/{pt-PT-UZXXM6DQ-CbndO7_y.js → pt-PT-UZXXM6DQ-D4vr9vo6.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-120e2f19-BlmT42uD.js → quadrantDiagram-120e2f19-DlUESmO2.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-deff3bca-DZp4Qu-J.js → requirementDiagram-deff3bca-CfOs9jR8.js} +1 -1
- package/dist-renderer/assets/{ro-RO-JPDTUUEW-YgTIqyaS.js → ro-RO-JPDTUUEW-CztO0tWv.js} +1 -1
- package/dist-renderer/assets/{ru-RU-B4JR7IUQ-B4-xC-bY.js → ru-RU-B4JR7IUQ-aVURliDr.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-04a897e0-DQU3Sh4e.js → sankeyDiagram-04a897e0-DRRc8FSN.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-704730f1-BMDPHAvO.js → sequenceDiagram-704730f1-BaswaqQO.js} +1 -1
- package/dist-renderer/assets/{si-LK-N5RQ5JYF-xJBJNkkH.js → si-LK-N5RQ5JYF-B2KWtx6N.js} +1 -1
- package/dist-renderer/assets/{sk-SK-C5VTKIMK-D3oM9sTx.js → sk-SK-C5VTKIMK-DlRzLxRJ.js} +1 -1
- package/dist-renderer/assets/{sl-SI-NN7IZMDC-Dr3hNCQI.js → sl-SI-NN7IZMDC-Ox8yiRTS.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-587899a1-kJVlt2mB.js → stateDiagram-587899a1-DSEEonbL.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-v2-d93cdb3a-Oo192ox1.js → stateDiagram-v2-d93cdb3a-C135NgbB.js} +1 -1
- package/dist-renderer/assets/{styles-6aaf32cf-Cw1X4bWF.js → styles-6aaf32cf-X5nh1pD3.js} +1 -1
- package/dist-renderer/assets/{styles-9a916d00-BIBcInOQ.js → styles-9a916d00-BCZu272E.js} +1 -1
- package/dist-renderer/assets/{styles-c10674c1-DboG8Lt4.js → styles-c10674c1-C5JGHSaS.js} +1 -1
- package/dist-renderer/assets/{subset-shared.chunk-ZAiO-eLl.js → subset-shared.chunk-CzgdV5hf.js} +1 -1
- package/dist-renderer/assets/{subset-worker.chunk-B6PRRmQb.js → subset-worker.chunk-DfLYxc1O.js} +1 -1
- package/dist-renderer/assets/{sv-SE-XGPEYMSR-CegwfGx6.js → sv-SE-XGPEYMSR-CizFbLCT.js} +1 -1
- package/dist-renderer/assets/{svgDrawCommon-08f97a94-Dn29OsMT.js → svgDrawCommon-08f97a94-Cv5ZIzzk.js} +1 -1
- package/dist-renderer/assets/{ta-IN-2NMHFXQM-tSe3kTsK.js → ta-IN-2NMHFXQM-B66K2LEN.js} +1 -1
- package/dist-renderer/assets/{th-TH-HPSO5L25-DiuZcD9o.js → th-TH-HPSO5L25-DvHt1SBY.js} +1 -1
- package/dist-renderer/assets/{timeline-definition-85554ec2-DAY01_uJ.js → timeline-definition-85554ec2-C955-u4m.js} +1 -1
- package/dist-renderer/assets/{tr-TR-DEFEU3FU-f-T831Ou.js → tr-TR-DEFEU3FU-u0AuqRoD.js} +1 -1
- package/dist-renderer/assets/{uk-UA-QMV73CPH-oa90pxqd.js → uk-UA-QMV73CPH-IwAiPvJL.js} +1 -1
- package/dist-renderer/assets/{vi-VN-M7AON7JQ-CFBU2l5s.js → vi-VN-M7AON7JQ-Dh6Aj3f5.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-e933f94c-B6py5YKf.js → xychartDiagram-e933f94c-Bst4jMma.js} +1 -1
- package/dist-renderer/assets/{zh-CN-LNUGB5OW-R4K3nYOI.js → zh-CN-LNUGB5OW-BVXMa9T3.js} +1 -1
- package/dist-renderer/assets/{zh-HK-E62DVLB3-BjLHW6lU.js → zh-HK-E62DVLB3-DYEIu92z.js} +1 -1
- package/dist-renderer/assets/{zh-TW-RAJ6MFWO-e20gphGm.js → zh-TW-RAJ6MFWO-Dm9oSthu.js} +1 -1
- package/dist-renderer/index.html +2 -2
- package/package.json +2 -2
- package/skills/council-manage/SKILL.md +45 -45
- package/skills/council-setup-keys/SKILL.md +2 -2
- package/dist-renderer/assets/channel-B90-0NuK.js +0 -1
- package/dist-renderer/assets/clone-DEtBvu0Z.js +0 -1
- package/dist-renderer/assets/flowDiagram-v2-96b9c2cf-BsIp2X-N.js +0 -1
- package/dist-renderer/assets/index-DJ14s8KN.js +0 -51
- package/dist-renderer/assets/index-HXjW9ZG3.css +0 -1
package/dist-electron/main.js
CHANGED
|
@@ -23,94 +23,94 @@ const Ke = k.object({
|
|
|
23
23
|
skills: k.array(k.string()).default([]),
|
|
24
24
|
temperature: k.number().min(0).max(2).optional(),
|
|
25
25
|
avatar: k.string().optional()
|
|
26
|
-
}), je = (o,
|
|
27
|
-
d(o, "skills",
|
|
28
|
-
d(process.cwd(), ".claude", "skills",
|
|
29
|
-
d(v(), ".agents", "skills",
|
|
30
|
-
d(v(), ".claude", "skills",
|
|
26
|
+
}), je = (o, s) => [
|
|
27
|
+
d(o, "skills", s, "SKILL.md"),
|
|
28
|
+
d(process.cwd(), ".claude", "skills", s, "SKILL.md"),
|
|
29
|
+
d(v(), ".agents", "skills", s, "SKILL.md"),
|
|
30
|
+
d(v(), ".claude", "skills", s, "SKILL.md")
|
|
31
31
|
];
|
|
32
|
-
async function Be(o,
|
|
33
|
-
for (const t of je(
|
|
32
|
+
async function Be(o, s) {
|
|
33
|
+
for (const t of je(s, o))
|
|
34
34
|
if (E(t)) {
|
|
35
|
-
const e = await w(t, "utf-8"), { content:
|
|
36
|
-
return
|
|
35
|
+
const e = await w(t, "utf-8"), { content: r } = X(e);
|
|
36
|
+
return r.trim();
|
|
37
37
|
}
|
|
38
38
|
return null;
|
|
39
39
|
}
|
|
40
|
-
async function Ge(o,
|
|
40
|
+
async function Ge(o, s) {
|
|
41
41
|
const t = [];
|
|
42
42
|
for (const e of o) {
|
|
43
|
-
const
|
|
44
|
-
|
|
43
|
+
const r = await Be(e, s);
|
|
44
|
+
r && t.push(`## Skill: ${e}
|
|
45
45
|
|
|
46
|
-
${
|
|
46
|
+
${r}`);
|
|
47
47
|
}
|
|
48
48
|
return t.join(`
|
|
49
49
|
|
|
50
50
|
`);
|
|
51
51
|
}
|
|
52
|
-
function Fe(o,
|
|
53
|
-
return o ? o.startsWith("http://") || o.startsWith("https://") ? o : `council-file://${o.startsWith("/") ? o : d(
|
|
52
|
+
function Fe(o, s) {
|
|
53
|
+
return o ? o.startsWith("http://") || o.startsWith("https://") ? o : `council-file://${o.startsWith("/") ? o : d(s, o)}` : void 0;
|
|
54
54
|
}
|
|
55
|
-
async function We(o,
|
|
55
|
+
async function We(o, s) {
|
|
56
56
|
const t = /\{\{(.+?)\}\}/g;
|
|
57
57
|
let e = o;
|
|
58
|
-
for (const
|
|
59
|
-
const n =
|
|
58
|
+
for (const r of o.matchAll(t)) {
|
|
59
|
+
const n = r[1].trim(), a = d(s, n);
|
|
60
60
|
if (E(a)) {
|
|
61
61
|
const i = await w(a, "utf-8");
|
|
62
|
-
e = e.replace(
|
|
62
|
+
e = e.replace(r[0], i.trim());
|
|
63
63
|
} else
|
|
64
|
-
e = e.replace(
|
|
64
|
+
e = e.replace(r[0], `[Reference not found: ${n}]`);
|
|
65
65
|
}
|
|
66
66
|
return e;
|
|
67
67
|
}
|
|
68
68
|
async function oe(o) {
|
|
69
|
-
const
|
|
69
|
+
const s = G(o), t = d(s, "ABOUT.md");
|
|
70
70
|
if (!E(t))
|
|
71
|
-
throw new Error(`No ABOUT.md found in ${
|
|
72
|
-
const e = await w(t, "utf-8"), { data:
|
|
73
|
-
let i = await We(n.trim(),
|
|
71
|
+
throw new Error(`No ABOUT.md found in ${s}`);
|
|
72
|
+
const e = await w(t, "utf-8"), { data: r, content: n } = X(e), a = Ke.parse(r);
|
|
73
|
+
let i = await We(n.trim(), s);
|
|
74
74
|
if (a.skills.length > 0) {
|
|
75
|
-
const u = await Ge(a.skills,
|
|
75
|
+
const u = await Ge(a.skills, s);
|
|
76
76
|
u && (i += `
|
|
77
77
|
|
|
78
78
|
` + u);
|
|
79
79
|
}
|
|
80
80
|
return {
|
|
81
|
-
id: C(
|
|
81
|
+
id: C(s),
|
|
82
82
|
frontmatter: a,
|
|
83
83
|
systemPrompt: i,
|
|
84
|
-
dirPath:
|
|
85
|
-
avatarUrl: Fe(a.avatar,
|
|
84
|
+
dirPath: s,
|
|
85
|
+
avatarUrl: Fe(a.avatar, s)
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
|
-
async function
|
|
88
|
+
async function re(o, s) {
|
|
89
89
|
const t = [], e = /* @__PURE__ */ new Set();
|
|
90
|
-
if (
|
|
91
|
-
for (const
|
|
92
|
-
if (E(d(
|
|
90
|
+
if (s?.length) {
|
|
91
|
+
for (const r of s)
|
|
92
|
+
if (E(d(r, "ABOUT.md")))
|
|
93
93
|
try {
|
|
94
|
-
const n = await oe(
|
|
94
|
+
const n = await oe(r);
|
|
95
95
|
e.has(n.id) || (t.push(n), e.add(n.id));
|
|
96
96
|
} catch {
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
if (E(o)) {
|
|
100
|
-
const
|
|
101
|
-
for (const n of
|
|
100
|
+
const r = await V(o);
|
|
101
|
+
for (const n of r) {
|
|
102
102
|
const a = d(o, n);
|
|
103
103
|
(await he(a)).isDirectory() && E(d(a, "ABOUT.md")) && (e.has(C(a)) || (t.push(await oe(a)), e.add(C(a))));
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
if (t.length === 0)
|
|
107
107
|
throw new Error(
|
|
108
|
-
`No
|
|
109
|
-
Create one with: mkdir -p ~/.ai-council/
|
|
108
|
+
`No councilors found. Searched ${o}${s?.length ? ` and ${s.length} registered path(s)` : ""}.
|
|
109
|
+
Create one with: mkdir -p ~/.ai-council/councilors/my-councilor && council councilor add ~/.ai-council/councilors/my-councilor`
|
|
110
110
|
);
|
|
111
111
|
return t;
|
|
112
112
|
}
|
|
113
|
-
const Me = U(R), ge = d(v(), ".ai-council", "config.json"),
|
|
113
|
+
const Me = U(R), ge = d(v(), ".ai-council", "config.json"), se = d(v(), ".ai-council", "councilors");
|
|
114
114
|
async function Q() {
|
|
115
115
|
try {
|
|
116
116
|
return JSON.parse(await w(ge, "utf-8"));
|
|
@@ -119,37 +119,40 @@ async function Q() {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
async function Z(o) {
|
|
122
|
-
const
|
|
123
|
-
await N(
|
|
122
|
+
const s = d(v(), ".ai-council");
|
|
123
|
+
await N(s, { recursive: !0 }), await P(ge, JSON.stringify(o, null, 2), "utf-8");
|
|
124
|
+
}
|
|
125
|
+
function Ye(o) {
|
|
126
|
+
return o.councilors ?? o.counsellors ?? {};
|
|
124
127
|
}
|
|
125
128
|
function ae(o) {
|
|
126
|
-
return Object.values(o
|
|
129
|
+
return Object.values(Ye(o)).map((s) => s.path);
|
|
127
130
|
}
|
|
128
|
-
async function
|
|
129
|
-
const
|
|
131
|
+
async function He(o) {
|
|
132
|
+
const s = G(o), t = d(s, "ABOUT.md");
|
|
130
133
|
if (!E(t))
|
|
131
|
-
throw new Error(`No ABOUT.md found in ${
|
|
132
|
-
const e = C(
|
|
134
|
+
throw new Error(`No ABOUT.md found in ${s}`);
|
|
135
|
+
const e = C(s), r = await Q(), n = r.councilors ?? {};
|
|
133
136
|
if (n[e])
|
|
134
|
-
throw new Error(`
|
|
137
|
+
throw new Error(`Councilor "${e}" is already registered (path: ${n[e].path})`);
|
|
135
138
|
const u = (await w(t, "utf-8")).match(/^name:\s*["']?(.+?)["']?\s*$/m)?.[1] ?? e;
|
|
136
139
|
return n[e] = {
|
|
137
|
-
path:
|
|
140
|
+
path: s,
|
|
138
141
|
source: "local",
|
|
139
142
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
140
|
-
},
|
|
143
|
+
}, r.councilors = n, await Z(r), { id: e, name: u };
|
|
141
144
|
}
|
|
142
|
-
async function
|
|
143
|
-
await N(
|
|
144
|
-
const
|
|
145
|
+
async function Je(o) {
|
|
146
|
+
await N(se, { recursive: !0 });
|
|
147
|
+
const s = C(o, ".git").replace(/\.git$/, ""), t = d(se, s);
|
|
145
148
|
if (E(t))
|
|
146
149
|
throw new Error(`Directory already exists: ${t}. Remove it first or use a different URL.`);
|
|
147
150
|
await Me("git", ["clone", "--depth", "1", o, t]);
|
|
148
|
-
const e = [],
|
|
151
|
+
const e = [], r = await Q(), n = r.councilors ?? {};
|
|
149
152
|
if (E(d(t, "ABOUT.md"))) {
|
|
150
|
-
const a =
|
|
153
|
+
const a = s;
|
|
151
154
|
if (n[a])
|
|
152
|
-
throw new Error(`
|
|
155
|
+
throw new Error(`Councilor "${a}" is already registered`);
|
|
153
156
|
const c = (await w(d(t, "ABOUT.md"), "utf-8")).match(/^name:\s*["']?(.+?)["']?\s*$/m)?.[1] ?? a;
|
|
154
157
|
n[a] = {
|
|
155
158
|
path: t,
|
|
@@ -175,18 +178,18 @@ async function He(o) {
|
|
|
175
178
|
}
|
|
176
179
|
}
|
|
177
180
|
if (e.length === 0)
|
|
178
|
-
throw await F(t, { recursive: !0, force: !0 }), new Error("No
|
|
181
|
+
throw await F(t, { recursive: !0, force: !0 }), new Error("No councilors found in cloned repository (no ABOUT.md files)");
|
|
179
182
|
}
|
|
180
|
-
return
|
|
183
|
+
return r.councilors = n, await Z(r), e;
|
|
181
184
|
}
|
|
182
|
-
async function
|
|
183
|
-
const t = await Q(), e = t.
|
|
184
|
-
if (!
|
|
185
|
-
throw new Error(`
|
|
186
|
-
|
|
185
|
+
async function ze(o, s = !1) {
|
|
186
|
+
const t = await Q(), e = t.councilors ?? {}, r = e[o];
|
|
187
|
+
if (!r)
|
|
188
|
+
throw new Error(`Councilor "${o}" is not registered`);
|
|
189
|
+
s && r.source === "git" && E(r.path) && await F(r.path, { recursive: !0, force: !0 }), delete e[o], t.councilors = e, await Z(t);
|
|
187
190
|
}
|
|
188
|
-
function
|
|
189
|
-
const
|
|
191
|
+
function Ve(o) {
|
|
192
|
+
const s = new Re({
|
|
190
193
|
apiKey: o.apiKey ?? process.env.ANTHROPIC_API_KEY,
|
|
191
194
|
...o.baseUrl ? { baseURL: o.baseUrl } : {}
|
|
192
195
|
});
|
|
@@ -194,7 +197,7 @@ function ze(o) {
|
|
|
194
197
|
name: "anthropic",
|
|
195
198
|
defaultModel: "claude-sonnet-4-5-20250929",
|
|
196
199
|
async chat(t) {
|
|
197
|
-
const e = await
|
|
200
|
+
const e = await s.messages.create({
|
|
198
201
|
model: t.model,
|
|
199
202
|
max_tokens: 4096,
|
|
200
203
|
system: t.systemPrompt,
|
|
@@ -213,7 +216,7 @@ function ze(o) {
|
|
|
213
216
|
};
|
|
214
217
|
},
|
|
215
218
|
async *chatStream(t) {
|
|
216
|
-
const e =
|
|
219
|
+
const e = s.messages.stream({
|
|
217
220
|
model: t.model,
|
|
218
221
|
max_tokens: 4096,
|
|
219
222
|
system: t.systemPrompt,
|
|
@@ -225,19 +228,19 @@ function ze(o) {
|
|
|
225
228
|
});
|
|
226
229
|
for await (const n of e)
|
|
227
230
|
n.type === "content_block_delta" && n.delta.type === "text_delta" && (yield { delta: n.delta.text });
|
|
228
|
-
const
|
|
231
|
+
const r = await e.finalMessage();
|
|
229
232
|
yield {
|
|
230
233
|
delta: "",
|
|
231
234
|
tokenUsage: {
|
|
232
|
-
input:
|
|
233
|
-
output:
|
|
235
|
+
input: r.usage.input_tokens,
|
|
236
|
+
output: r.usage.output_tokens
|
|
234
237
|
}
|
|
235
238
|
};
|
|
236
239
|
}
|
|
237
240
|
};
|
|
238
241
|
}
|
|
239
|
-
function
|
|
240
|
-
const
|
|
242
|
+
function Xe(o) {
|
|
243
|
+
const s = new Ue({
|
|
241
244
|
apiKey: o.apiKey ?? process.env.OPENAI_API_KEY,
|
|
242
245
|
...o.baseUrl ? { baseURL: o.baseUrl } : {}
|
|
243
246
|
});
|
|
@@ -245,7 +248,7 @@ function Ve(o) {
|
|
|
245
248
|
name: "openai",
|
|
246
249
|
defaultModel: "gpt-4o",
|
|
247
250
|
async chat(t) {
|
|
248
|
-
const e = await
|
|
251
|
+
const e = await s.chat.completions.create({
|
|
249
252
|
model: t.model,
|
|
250
253
|
messages: [
|
|
251
254
|
{ role: "system", content: t.systemPrompt },
|
|
@@ -262,39 +265,39 @@ function Ve(o) {
|
|
|
262
265
|
};
|
|
263
266
|
},
|
|
264
267
|
async *chatStream(t) {
|
|
265
|
-
const e = await
|
|
268
|
+
const e = await s.chat.completions.create({
|
|
266
269
|
model: t.model,
|
|
267
270
|
messages: [
|
|
268
271
|
{ role: "system", content: t.systemPrompt },
|
|
269
|
-
...t.messages.map((
|
|
270
|
-
role:
|
|
271
|
-
content:
|
|
272
|
+
...t.messages.map((r) => ({
|
|
273
|
+
role: r.role,
|
|
274
|
+
content: r.content
|
|
272
275
|
}))
|
|
273
276
|
],
|
|
274
277
|
...t.temperature !== void 0 ? { temperature: t.temperature } : {},
|
|
275
278
|
stream: !0,
|
|
276
279
|
stream_options: { include_usage: !0 }
|
|
277
280
|
});
|
|
278
|
-
for await (const
|
|
279
|
-
const n =
|
|
280
|
-
n && (yield { delta: n }),
|
|
281
|
+
for await (const r of e) {
|
|
282
|
+
const n = r.choices[0]?.delta?.content;
|
|
283
|
+
n && (yield { delta: n }), r.usage && (yield {
|
|
281
284
|
delta: "",
|
|
282
285
|
tokenUsage: {
|
|
283
|
-
input:
|
|
284
|
-
output:
|
|
286
|
+
input: r.usage.prompt_tokens,
|
|
287
|
+
output: r.usage.completion_tokens
|
|
285
288
|
}
|
|
286
289
|
});
|
|
287
290
|
}
|
|
288
291
|
}
|
|
289
292
|
};
|
|
290
293
|
}
|
|
291
|
-
function
|
|
292
|
-
const
|
|
294
|
+
function Qe(o) {
|
|
295
|
+
const s = o.apiKey ?? process.env.GOOGLE_API_KEY ?? "", t = new Te(s);
|
|
293
296
|
return {
|
|
294
297
|
name: "google",
|
|
295
298
|
defaultModel: "gemini-2.0-flash",
|
|
296
299
|
async chat(e) {
|
|
297
|
-
const
|
|
300
|
+
const r = t.getGenerativeModel({
|
|
298
301
|
model: e.model,
|
|
299
302
|
systemInstruction: e.systemPrompt,
|
|
300
303
|
generationConfig: {
|
|
@@ -303,7 +306,7 @@ function Xe(o) {
|
|
|
303
306
|
}), n = e.messages.slice(0, -1).map((m) => ({
|
|
304
307
|
role: m.role === "assistant" ? "model" : "user",
|
|
305
308
|
parts: [{ text: m.content }]
|
|
306
|
-
})), a =
|
|
309
|
+
})), a = r.startChat({ history: n }), i = e.messages[e.messages.length - 1], c = (await a.sendMessage(i?.content ?? "")).response;
|
|
307
310
|
return {
|
|
308
311
|
content: c.text(),
|
|
309
312
|
tokenUsage: c.usageMetadata ? {
|
|
@@ -313,7 +316,7 @@ function Xe(o) {
|
|
|
313
316
|
};
|
|
314
317
|
},
|
|
315
318
|
async *chatStream(e) {
|
|
316
|
-
const
|
|
319
|
+
const r = t.getGenerativeModel({
|
|
317
320
|
model: e.model,
|
|
318
321
|
systemInstruction: e.systemPrompt,
|
|
319
322
|
generationConfig: {
|
|
@@ -322,7 +325,7 @@ function Xe(o) {
|
|
|
322
325
|
}), n = e.messages.slice(0, -1).map((m) => ({
|
|
323
326
|
role: m.role === "assistant" ? "model" : "user",
|
|
324
327
|
parts: [{ text: m.content }]
|
|
325
|
-
})), a =
|
|
328
|
+
})), a = r.startChat({ history: n }), i = e.messages[e.messages.length - 1], u = await a.sendMessageStream(i?.content ?? "");
|
|
326
329
|
for await (const m of u.stream) {
|
|
327
330
|
const y = m.text();
|
|
328
331
|
y && (yield { delta: y });
|
|
@@ -338,21 +341,21 @@ function Xe(o) {
|
|
|
338
341
|
}
|
|
339
342
|
};
|
|
340
343
|
}
|
|
341
|
-
function
|
|
342
|
-
const
|
|
344
|
+
function Ze(o) {
|
|
345
|
+
const s = new Le({
|
|
343
346
|
host: o.baseUrl ?? "http://localhost:11434"
|
|
344
347
|
});
|
|
345
348
|
return {
|
|
346
349
|
name: "ollama",
|
|
347
350
|
defaultModel: "llama3.2",
|
|
348
351
|
async chat(t) {
|
|
349
|
-
const e = await
|
|
352
|
+
const e = await s.chat({
|
|
350
353
|
model: t.model,
|
|
351
354
|
messages: [
|
|
352
355
|
{ role: "system", content: t.systemPrompt },
|
|
353
|
-
...t.messages.map((
|
|
354
|
-
role:
|
|
355
|
-
content:
|
|
356
|
+
...t.messages.map((r) => ({
|
|
357
|
+
role: r.role,
|
|
358
|
+
content: r.content
|
|
356
359
|
}))
|
|
357
360
|
],
|
|
358
361
|
options: {
|
|
@@ -368,7 +371,7 @@ function Qe(o) {
|
|
|
368
371
|
};
|
|
369
372
|
},
|
|
370
373
|
async *chatStream(t) {
|
|
371
|
-
const e = await
|
|
374
|
+
const e = await s.chat({
|
|
372
375
|
model: t.model,
|
|
373
376
|
messages: [
|
|
374
377
|
{ role: "system", content: t.systemPrompt },
|
|
@@ -382,59 +385,59 @@ function Qe(o) {
|
|
|
382
385
|
},
|
|
383
386
|
stream: !0
|
|
384
387
|
});
|
|
385
|
-
let
|
|
388
|
+
let r, n;
|
|
386
389
|
for await (const a of e)
|
|
387
|
-
a.message.content && (yield { delta: a.message.content }), a.done && (
|
|
390
|
+
a.message.content && (yield { delta: a.message.content }), a.done && (r = a.prompt_eval_count, n = a.eval_count);
|
|
388
391
|
yield {
|
|
389
392
|
delta: "",
|
|
390
|
-
tokenUsage:
|
|
393
|
+
tokenUsage: r !== void 0 ? { input: r ?? 0, output: n ?? 0 } : void 0
|
|
391
394
|
};
|
|
392
395
|
}
|
|
393
396
|
};
|
|
394
397
|
}
|
|
395
398
|
const ie = {
|
|
396
|
-
anthropic:
|
|
397
|
-
openai:
|
|
398
|
-
google:
|
|
399
|
-
ollama:
|
|
399
|
+
anthropic: Ve,
|
|
400
|
+
openai: Xe,
|
|
401
|
+
google: Qe,
|
|
402
|
+
ollama: Ze
|
|
400
403
|
};
|
|
401
404
|
let T = null;
|
|
402
|
-
async function
|
|
405
|
+
async function qe() {
|
|
403
406
|
if (T) return T;
|
|
404
407
|
const o = d(v(), ".ai-council", "config.json");
|
|
405
408
|
try {
|
|
406
|
-
const
|
|
407
|
-
T = JSON.parse(
|
|
409
|
+
const s = await w(o, "utf-8");
|
|
410
|
+
T = JSON.parse(s);
|
|
408
411
|
} catch {
|
|
409
412
|
T = { backends: {} };
|
|
410
413
|
}
|
|
411
414
|
return T;
|
|
412
415
|
}
|
|
413
416
|
const z = /* @__PURE__ */ new Map();
|
|
414
|
-
function
|
|
417
|
+
function et() {
|
|
415
418
|
T = null, z.clear();
|
|
416
419
|
}
|
|
417
420
|
async function W(o) {
|
|
418
|
-
const
|
|
419
|
-
if (
|
|
421
|
+
const s = z.get(o);
|
|
422
|
+
if (s) return s;
|
|
420
423
|
const t = ie[o];
|
|
421
424
|
if (!t)
|
|
422
425
|
throw new Error(`Unknown backend: "${o}". Available: ${Object.keys(ie).join(", ")}`);
|
|
423
|
-
const
|
|
426
|
+
const r = (await qe()).backends[o] ?? {}, n = t(r);
|
|
424
427
|
return z.set(o, n), n;
|
|
425
428
|
}
|
|
426
|
-
function
|
|
427
|
-
return '\n## Excalidraw Element Reference\n\nOutput a JSON array of Excalidraw elements. Each element needs these fields:\n\n### Common Fields (all elements)\n- `type`: "rectangle" | "ellipse" | "diamond" | "text" | "arrow" | "line"\n- `id`: unique string (e.g. "rect1", "text1", "arrow1")\n- `x`, `y`: number (top-left origin, x increases right, y increases down)\n- `width`, `height`: number\n- `strokeColor`: hex string (e.g. "#1e1e1e")\n- `backgroundColor`: hex string or "transparent"\n- `fillStyle`: "solid" | "hachure" | "cross-hatch"\n- `strokeWidth`: 1 | 2 | 4\n- `roughness`: 0 (sharp) | 1 (sketchy)\n- `opacity`: 100\n- `angle`: 0\n- `seed`: any integer (e.g. 1)\n- `version`: 1\n- `isDeleted`: false\n- `groupIds`: []\n- `boundElements`: null or array of { id: string, type: "text" | "arrow" }\n- `link`: null\n- `locked`: false\n\n### Text Elements\nAdditional fields: `text`, `fontSize` (16-24), `fontFamily` (1=hand, 2=normal, 3=mono), `textAlign` ("left"|"center"|"right"), `verticalAlign` ("top"|"middle"), `baseline`: 0, `containerId`: null or parent shape id\n\n### Arrow/Line Elements\nAdditional fields: `points` (array of [x,y] relative to element x,y — first point always [0,0]), `startBinding` and `endBinding`: null or { elementId: string, focus: 0, gap: 5 }, `lastCommittedPoint`: null, `startArrowhead`: null, `endArrowhead`: "arrow" | null\n\n### Color Palette\n- Blue: "#1971c2", Light blue bg: "#a5d8ff"\n- Green: "#2f9e44", Light green bg: "#b2f2bb"\n- Red: "#e03131", Light red bg: "#ffc9c9"\n- Orange: "#e8590c", Light orange bg: "#ffd8a8"\n- Purple: "#7048e8", Light purple bg: "#d0bfff"\n- Yellow: "#f08c00", Light yellow bg: "#ffec99"\n- Gray: "#868e96", Light gray bg: "#dee2e6"\n- Dark: "#1e1e1e"\n\n### Layout Tips\n- Space shapes ~200px apart horizontally, ~150px vertically\n- Typical shape size: 160×80 for rectangles, 120×60 for ellipses\n- Center text inside shapes using containerId\n- Use arrows to show relationships (agreement, disagreement, influence)\n\n### Compact Example\n```json\n[\n {"type":"rectangle","id":"r1","x":50,"y":50,"width":160,"height":80,"strokeColor":"#1971c2","backgroundColor":"#a5d8ff","fillStyle":"solid","strokeWidth":2,"roughness":1,"opacity":100,"angle":0,"seed":1,"version":1,"isDeleted":false,"groupIds":[],"boundElements":[{"id":"t1","type":"text"},{"id":"a1","type":"arrow"}],"link":null,"locked":false},\n {"type":"text","id":"t1","x":60,"y":70,"width":140,"height":40,"text":"
|
|
429
|
+
function tt() {
|
|
430
|
+
return '\n## Excalidraw Element Reference\n\nOutput a JSON array of Excalidraw elements. Each element needs these fields:\n\n### Common Fields (all elements)\n- `type`: "rectangle" | "ellipse" | "diamond" | "text" | "arrow" | "line"\n- `id`: unique string (e.g. "rect1", "text1", "arrow1")\n- `x`, `y`: number (top-left origin, x increases right, y increases down)\n- `width`, `height`: number\n- `strokeColor`: hex string (e.g. "#1e1e1e")\n- `backgroundColor`: hex string or "transparent"\n- `fillStyle`: "solid" | "hachure" | "cross-hatch"\n- `strokeWidth`: 1 | 2 | 4\n- `roughness`: 0 (sharp) | 1 (sketchy)\n- `opacity`: 100\n- `angle`: 0\n- `seed`: any integer (e.g. 1)\n- `version`: 1\n- `isDeleted`: false\n- `groupIds`: []\n- `boundElements`: null or array of { id: string, type: "text" | "arrow" }\n- `link`: null\n- `locked`: false\n\n### Text Elements\nAdditional fields: `text`, `fontSize` (16-24), `fontFamily` (1=hand, 2=normal, 3=mono), `textAlign` ("left"|"center"|"right"), `verticalAlign` ("top"|"middle"), `baseline`: 0, `containerId`: null or parent shape id\n\n### Arrow/Line Elements\nAdditional fields: `points` (array of [x,y] relative to element x,y — first point always [0,0]), `startBinding` and `endBinding`: null or { elementId: string, focus: 0, gap: 5 }, `lastCommittedPoint`: null, `startArrowhead`: null, `endArrowhead`: "arrow" | null\n\n### Color Palette\n- Blue: "#1971c2", Light blue bg: "#a5d8ff"\n- Green: "#2f9e44", Light green bg: "#b2f2bb"\n- Red: "#e03131", Light red bg: "#ffc9c9"\n- Orange: "#e8590c", Light orange bg: "#ffd8a8"\n- Purple: "#7048e8", Light purple bg: "#d0bfff"\n- Yellow: "#f08c00", Light yellow bg: "#ffec99"\n- Gray: "#868e96", Light gray bg: "#dee2e6"\n- Dark: "#1e1e1e"\n\n### Layout Tips\n- Space shapes ~200px apart horizontally, ~150px vertically\n- Typical shape size: 160×80 for rectangles, 120×60 for ellipses\n- Center text inside shapes using containerId\n- Use arrows to show relationships (agreement, disagreement, influence)\n\n### Compact Example\n```json\n[\n {"type":"rectangle","id":"r1","x":50,"y":50,"width":160,"height":80,"strokeColor":"#1971c2","backgroundColor":"#a5d8ff","fillStyle":"solid","strokeWidth":2,"roughness":1,"opacity":100,"angle":0,"seed":1,"version":1,"isDeleted":false,"groupIds":[],"boundElements":[{"id":"t1","type":"text"},{"id":"a1","type":"arrow"}],"link":null,"locked":false},\n {"type":"text","id":"t1","x":60,"y":70,"width":140,"height":40,"text":"Councilor A","fontSize":16,"fontFamily":2,"textAlign":"center","verticalAlign":"middle","baseline":0,"containerId":"r1","strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1,"roughness":0,"opacity":100,"angle":0,"seed":2,"version":1,"isDeleted":false,"groupIds":[],"boundElements":null,"link":null,"locked":false},\n {"type":"rectangle","id":"r2","x":350,"y":50,"width":160,"height":80,"strokeColor":"#2f9e44","backgroundColor":"#b2f2bb","fillStyle":"solid","strokeWidth":2,"roughness":1,"opacity":100,"angle":0,"seed":3,"version":1,"isDeleted":false,"groupIds":[],"boundElements":[{"id":"t2","type":"text"},{"id":"a1","type":"arrow"}],"link":null,"locked":false},\n {"type":"text","id":"t2","x":360,"y":70,"width":140,"height":40,"text":"Councilor B","fontSize":16,"fontFamily":2,"textAlign":"center","verticalAlign":"middle","baseline":0,"containerId":"r2","strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1,"roughness":0,"opacity":100,"angle":0,"seed":4,"version":1,"isDeleted":false,"groupIds":[],"boundElements":null,"link":null,"locked":false},\n {"type":"arrow","id":"a1","x":210,"y":90,"width":140,"height":0,"points":[[0,0],[140,0]],"startBinding":{"elementId":"r1","focus":0,"gap":5},"endBinding":{"elementId":"r2","focus":0,"gap":5},"startArrowhead":null,"endArrowhead":"arrow","strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":2,"roughness":1,"opacity":100,"angle":0,"seed":5,"version":1,"isDeleted":false,"groupIds":[],"boundElements":null,"link":null,"locked":false,"lastCommittedPoint":null}\n]\n```\n'.trim();
|
|
428
431
|
}
|
|
429
|
-
const M = "---EXCALIDRAW---",
|
|
432
|
+
const M = "---EXCALIDRAW---", nt = `You are the Secretary of a council discussion. Your job is to synthesize a clear, structured summary of the conversation that just took place.
|
|
430
433
|
|
|
431
434
|
Structure your summary with these sections:
|
|
432
435
|
|
|
433
436
|
## Individual Positions
|
|
434
|
-
Briefly summarize each
|
|
437
|
+
Briefly summarize each councilor's key arguments and stance.
|
|
435
438
|
|
|
436
439
|
## Points of Convergence
|
|
437
|
-
Where did the
|
|
440
|
+
Where did the councilors agree? What common ground emerged?
|
|
438
441
|
|
|
439
442
|
## Points of Divergence
|
|
440
443
|
Where did they disagree? What are the key tensions?
|
|
@@ -443,29 +446,29 @@ Where did they disagree? What are the key tensions?
|
|
|
443
446
|
What are the most important takeaways? What would you recommend based on the full discussion?
|
|
444
447
|
|
|
445
448
|
Be concise but thorough. Use markdown formatting.`;
|
|
446
|
-
function
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
+
function ot(o) {
|
|
450
|
+
const s = [];
|
|
451
|
+
s.push(`Topic: ${o.topic}`), s.push(`Councilors: ${o.councilors.map((e) => e.name).join(", ")}`), s.push(`Rounds: ${o.rounds}`), s.push("");
|
|
449
452
|
let t = 0;
|
|
450
453
|
for (const e of o.turns)
|
|
451
|
-
e.round !== t && (t = e.round,
|
|
452
|
-
return
|
|
454
|
+
e.round !== t && (t = e.round, s.push(`--- Round ${t} ---`), s.push("")), s.push(`[${e.councilorName}]:`), s.push(e.content), s.push("");
|
|
455
|
+
return s.join(`
|
|
453
456
|
`);
|
|
454
457
|
}
|
|
455
|
-
async function
|
|
458
|
+
async function rt({
|
|
456
459
|
result: o,
|
|
457
|
-
config:
|
|
460
|
+
config: s,
|
|
458
461
|
onChunk: t,
|
|
459
462
|
signal: e
|
|
460
463
|
}) {
|
|
461
|
-
const
|
|
462
|
-
if (!
|
|
464
|
+
const r = s.secretary;
|
|
465
|
+
if (!r?.backend)
|
|
463
466
|
throw new Error("No secretary backend configured");
|
|
464
|
-
const n = await W(
|
|
467
|
+
const n = await W(r.backend), a = r.model ?? n.defaultModel, i = r.systemPrompt || nt, u = tt(), c = `${i}
|
|
465
468
|
|
|
466
469
|
${u}
|
|
467
470
|
|
|
468
|
-
After your text summary, output \`${M}\` on its own line, then a JSON array of Excalidraw elements showing a visual map of where each
|
|
471
|
+
After your text summary, output \`${M}\` on its own line, then a JSON array of Excalidraw elements showing a visual map of where each councilor stands on the topic. Use shapes for each councilor with their name, arrows to show relationships (agreement/disagreement), and position them to visually represent the discussion dynamics.`, m = ot(o), y = {
|
|
469
472
|
model: a,
|
|
470
473
|
systemPrompt: c,
|
|
471
474
|
messages: [{ role: "user", content: `Please summarize this council discussion and create a position diagram:
|
|
@@ -494,20 +497,20 @@ ${m}` }],
|
|
|
494
497
|
return { text: b, diagram: g };
|
|
495
498
|
}
|
|
496
499
|
const st = "You are the Secretary of a council debate. Briefly summarize this round of discussion. Note emerging agreements, disagreements, and shifts in position. 2-3 paragraphs max. Use markdown formatting.";
|
|
497
|
-
async function
|
|
500
|
+
async function at({
|
|
498
501
|
result: o,
|
|
499
|
-
roundNumber:
|
|
502
|
+
roundNumber: s,
|
|
500
503
|
config: t,
|
|
501
504
|
onChunk: e,
|
|
502
|
-
signal:
|
|
505
|
+
signal: r
|
|
503
506
|
}) {
|
|
504
507
|
const n = t.secretary;
|
|
505
508
|
if (!n?.backend)
|
|
506
509
|
throw new Error("No secretary backend configured");
|
|
507
|
-
const a = await W(n.backend), i = n.model ?? a.defaultModel, u = o.turns.filter((h) => h.round ===
|
|
508
|
-
c.push(`Topic: ${o.topic}`), c.push(`Round ${
|
|
510
|
+
const a = await W(n.backend), i = n.model ?? a.defaultModel, u = o.turns.filter((h) => h.round === s), c = [];
|
|
511
|
+
c.push(`Topic: ${o.topic}`), c.push(`Round ${s}${s === 1 ? " (Constructive)" : " (Rebuttal)"}`), c.push("");
|
|
509
512
|
for (const h of u)
|
|
510
|
-
c.push(`[${h.
|
|
513
|
+
c.push(`[${h.councilorName}]:`), c.push(h.content), c.push("");
|
|
511
514
|
const m = {
|
|
512
515
|
model: i,
|
|
513
516
|
systemPrompt: st,
|
|
@@ -520,25 +523,25 @@ ${c.join(`
|
|
|
520
523
|
let y = "";
|
|
521
524
|
if (a.chatStream)
|
|
522
525
|
for await (const h of a.chatStream(m)) {
|
|
523
|
-
if (
|
|
526
|
+
if (r?.aborted) break;
|
|
524
527
|
y += h.delta, h.delta && e && e(h.delta);
|
|
525
528
|
}
|
|
526
529
|
else
|
|
527
530
|
y = (await a.chat(m)).content, e && e(y);
|
|
528
531
|
return y.trim();
|
|
529
532
|
}
|
|
530
|
-
async function
|
|
533
|
+
async function it({
|
|
531
534
|
topic: o,
|
|
532
|
-
firstRoundTurns:
|
|
535
|
+
firstRoundTurns: s,
|
|
533
536
|
config: t
|
|
534
537
|
}) {
|
|
535
538
|
const e = t.secretary;
|
|
536
539
|
if (!e?.backend)
|
|
537
540
|
throw new Error("No secretary backend configured");
|
|
538
|
-
const
|
|
541
|
+
const r = await W(e.backend), n = e.model ?? r.defaultModel, a = s.map((u) => `[${u.councilorName}]: ${u.content.slice(0, 300)}`).join(`
|
|
539
542
|
|
|
540
543
|
`);
|
|
541
|
-
return (await
|
|
544
|
+
return (await r.chat({
|
|
542
545
|
model: n,
|
|
543
546
|
systemPrompt: "Generate a concise title (max 8 words) for this council discussion. Return only the title, no quotes or punctuation at the end.",
|
|
544
547
|
messages: [
|
|
@@ -553,13 +556,13 @@ ${a}`
|
|
|
553
556
|
temperature: 0.3
|
|
554
557
|
})).content.trim().replace(/^["']+|["']+$/g, "").replace(/[.!?]+$/, "").trim();
|
|
555
558
|
}
|
|
556
|
-
const ye = d(v(), ".ai-council"),
|
|
559
|
+
const ye = d(v(), ".ai-council"), ct = d(ye, "council.log");
|
|
557
560
|
let ce = !1;
|
|
558
|
-
async function
|
|
561
|
+
async function lt() {
|
|
559
562
|
ce || (await N(ye, { recursive: !0 }), ce = !0);
|
|
560
563
|
}
|
|
561
|
-
function
|
|
562
|
-
let n = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${o} [${
|
|
564
|
+
function ut(o, s, t, e) {
|
|
565
|
+
let n = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${o} [${s}] ${t}`;
|
|
563
566
|
if (e !== void 0) {
|
|
564
567
|
const a = e instanceof Error ? `${e.message}
|
|
565
568
|
${e.stack ?? ""}` : typeof e == "string" ? e : JSON.stringify(e, null, 2);
|
|
@@ -570,79 +573,79 @@ ${e.stack ?? ""}` : typeof e == "string" ? e : JSON.stringify(e, null, 2);
|
|
|
570
573
|
return n + `
|
|
571
574
|
`;
|
|
572
575
|
}
|
|
573
|
-
async function Y(o,
|
|
576
|
+
async function Y(o, s, t, e) {
|
|
574
577
|
try {
|
|
575
|
-
await
|
|
578
|
+
await lt(), await xe(ct, ut(o, s, t, e));
|
|
576
579
|
} catch {
|
|
577
580
|
}
|
|
578
581
|
}
|
|
579
582
|
const _ = {
|
|
580
|
-
info: (o,
|
|
581
|
-
warn: (o,
|
|
582
|
-
error: (o,
|
|
583
|
+
info: (o, s, t) => Y("INFO", o, s, t),
|
|
584
|
+
warn: (o, s, t) => Y("WARN", o, s, t),
|
|
585
|
+
error: (o, s, t) => Y("ERROR", o, s, t)
|
|
583
586
|
};
|
|
584
|
-
function
|
|
587
|
+
function dt(o, s, t, e, r) {
|
|
585
588
|
const n = [{ role: "user", content: o }];
|
|
586
589
|
if (e?.length) {
|
|
587
590
|
for (const a of e)
|
|
588
|
-
a.
|
|
591
|
+
a.councilorId === t ? n.push({ role: "assistant", content: a.content }) : n.push({
|
|
589
592
|
role: "user",
|
|
590
|
-
content: `[${a.
|
|
593
|
+
content: `[${a.councilorName}, Round ${a.round}]: ${a.content}`
|
|
591
594
|
});
|
|
592
|
-
|
|
595
|
+
r && n.push({
|
|
593
596
|
role: "user",
|
|
594
|
-
content: `[Secretary Summary]: ${
|
|
597
|
+
content: `[Secretary Summary]: ${r}`
|
|
595
598
|
});
|
|
596
599
|
}
|
|
597
|
-
for (const a of
|
|
598
|
-
a.
|
|
600
|
+
for (const a of s)
|
|
601
|
+
a.councilorId === t ? n.push({ role: "assistant", content: a.content }) : n.push({
|
|
599
602
|
role: "user",
|
|
600
|
-
content: `[${a.
|
|
603
|
+
content: `[${a.councilorName}, Round ${a.round}]: ${a.content}`
|
|
601
604
|
});
|
|
602
605
|
return n;
|
|
603
606
|
}
|
|
604
|
-
function
|
|
605
|
-
const
|
|
607
|
+
function mt(o, s, t, e) {
|
|
608
|
+
const r = [{ role: "user", content: o }];
|
|
606
609
|
if (e === 1)
|
|
607
|
-
return
|
|
608
|
-
const n =
|
|
610
|
+
return r;
|
|
611
|
+
const n = s.filter((i) => i.round === 1);
|
|
609
612
|
for (const i of n)
|
|
610
|
-
i.
|
|
613
|
+
i.councilorId === t ? r.push({ role: "assistant", content: i.content }) : r.push({
|
|
611
614
|
role: "user",
|
|
612
|
-
content: `[${i.
|
|
615
|
+
content: `[${i.councilorName}, Constructive]: ${i.content}`
|
|
613
616
|
});
|
|
614
617
|
const a = e - 1;
|
|
615
618
|
if (a > 1) {
|
|
616
|
-
const i =
|
|
619
|
+
const i = s.filter((u) => u.round === a);
|
|
617
620
|
for (const u of i)
|
|
618
|
-
u.
|
|
621
|
+
u.councilorId === t ? r.push({ role: "assistant", content: u.content }) : r.push({
|
|
619
622
|
role: "user",
|
|
620
|
-
content: `[${u.
|
|
623
|
+
content: `[${u.councilorName}, Round ${a}]: ${u.content}`
|
|
621
624
|
});
|
|
622
625
|
}
|
|
623
|
-
for (const i of
|
|
624
|
-
i.
|
|
625
|
-
return
|
|
626
|
+
for (const i of s)
|
|
627
|
+
i.councilorId === t && i.round !== 1 && i.round !== a && i.round < e && r.push({ role: "assistant", content: i.content });
|
|
628
|
+
return r;
|
|
626
629
|
}
|
|
627
|
-
function
|
|
630
|
+
function pt(o, s) {
|
|
628
631
|
const t = [...o];
|
|
629
|
-
let e =
|
|
630
|
-
const
|
|
632
|
+
let e = s | 0;
|
|
633
|
+
const r = () => {
|
|
631
634
|
e = e + 1831565813 | 0;
|
|
632
635
|
let n = Math.imul(e ^ e >>> 15, 1 | e);
|
|
633
636
|
return n = n + Math.imul(n ^ n >>> 7, 61 | n) ^ n, ((n ^ n >>> 14) >>> 0) / 4294967296;
|
|
634
637
|
};
|
|
635
638
|
for (let n = t.length - 1; n > 0; n--) {
|
|
636
|
-
const a = Math.floor(
|
|
639
|
+
const a = Math.floor(r() * (n + 1));
|
|
637
640
|
[t[n], t[a]] = [t[a], t[n]];
|
|
638
641
|
}
|
|
639
642
|
return t;
|
|
640
643
|
}
|
|
641
|
-
function H(o,
|
|
644
|
+
function H(o, s, t, e, r, n) {
|
|
642
645
|
return {
|
|
643
646
|
topic: o.topic,
|
|
644
647
|
topicSource: o.topicSource,
|
|
645
|
-
|
|
648
|
+
councilors: o.councilors.map((a) => ({
|
|
646
649
|
id: a.id,
|
|
647
650
|
name: a.frontmatter.name,
|
|
648
651
|
description: a.frontmatter.description,
|
|
@@ -651,32 +654,32 @@ function H(o, r, t, e, s, n) {
|
|
|
651
654
|
avatarUrl: a.avatarUrl
|
|
652
655
|
})),
|
|
653
656
|
rounds: o.rounds,
|
|
654
|
-
turns:
|
|
657
|
+
turns: s,
|
|
655
658
|
startedAt: t,
|
|
656
659
|
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
657
|
-
totalTokenUsage: { input: e, output:
|
|
660
|
+
totalTokenUsage: { input: e, output: r },
|
|
658
661
|
...n && Object.keys(n).length > 0 ? { roundSummaries: n } : {},
|
|
659
662
|
...o.mode === "debate" ? { mode: "debate" } : {}
|
|
660
663
|
};
|
|
661
664
|
}
|
|
662
|
-
async function
|
|
665
|
+
async function ft(o, s, t, e, r) {
|
|
663
666
|
let n;
|
|
664
667
|
typeof o == "string" ? n = {
|
|
665
668
|
topic: o,
|
|
666
|
-
topicSource:
|
|
667
|
-
|
|
669
|
+
topicSource: s,
|
|
670
|
+
councilors: t,
|
|
668
671
|
rounds: e,
|
|
669
|
-
onEvent:
|
|
672
|
+
onEvent: r
|
|
670
673
|
} : n = o;
|
|
671
674
|
const a = (/* @__PURE__ */ new Date()).toISOString(), i = [];
|
|
672
675
|
let u = 0, c = 0;
|
|
673
676
|
const m = n.mode === "debate", y = {}, h = n.previousTurns?.length ? Math.max(...n.previousTurns.map((p) => p.round)) : 0;
|
|
674
|
-
_.info("conversation", `Starting ${m ? "debate" : "freeform"} — ${n.
|
|
675
|
-
|
|
677
|
+
_.info("conversation", `Starting ${m ? "debate" : "freeform"} — ${n.councilors.length} councilors, ${n.rounds} rounds`, {
|
|
678
|
+
councilors: n.councilors.map((p) => `${p.frontmatter.name} (${p.frontmatter.backend}/${p.frontmatter.model ?? "default"})`),
|
|
676
679
|
topic: n.topic.slice(0, 200)
|
|
677
680
|
});
|
|
678
681
|
for (let p = 1; p <= n.rounds; p++) {
|
|
679
|
-
const b = m && p > 1 ?
|
|
682
|
+
const b = m && p > 1 ? pt(n.councilors, p) : n.councilors;
|
|
680
683
|
for (const l of b) {
|
|
681
684
|
if (n.signal?.aborted)
|
|
682
685
|
return H(n, i, a, u, c, y);
|
|
@@ -685,9 +688,9 @@ async function pt(o, r, t, e, s) {
|
|
|
685
688
|
f && (i.push(f), n.onEvent({ type: "turn_complete", turn: f }));
|
|
686
689
|
}
|
|
687
690
|
const g = p + h;
|
|
688
|
-
n.onEvent({ type: "turn_start", round: g,
|
|
691
|
+
n.onEvent({ type: "turn_start", round: g, councilorName: l.frontmatter.name });
|
|
689
692
|
try {
|
|
690
|
-
const f = await W(l.frontmatter.backend), D = l.frontmatter.model ?? f.defaultModel, _e = m ?
|
|
693
|
+
const f = await W(l.frontmatter.backend), D = l.frontmatter.model ?? f.defaultModel, _e = m ? mt(n.topic, i, l.id, p) : dt(n.topic, i, l.id, n.previousTurns, n.previousSummary), q = {
|
|
691
694
|
model: D,
|
|
692
695
|
systemPrompt: l.systemPrompt,
|
|
693
696
|
messages: _e,
|
|
@@ -698,7 +701,7 @@ async function pt(o, r, t, e, s) {
|
|
|
698
701
|
K = "";
|
|
699
702
|
for await (const O of f.chatStream(q)) {
|
|
700
703
|
if (n.signal?.aborted) break;
|
|
701
|
-
K += O.delta, O.delta && n.onEvent({ type: "turn_chunk",
|
|
704
|
+
K += O.delta, O.delta && n.onEvent({ type: "turn_chunk", councilorName: l.frontmatter.name, delta: O.delta }), O.tokenUsage && (x = O.tokenUsage);
|
|
702
705
|
}
|
|
703
706
|
} else {
|
|
704
707
|
const O = await f.chat(q);
|
|
@@ -706,8 +709,8 @@ async function pt(o, r, t, e, s) {
|
|
|
706
709
|
}
|
|
707
710
|
const ee = {
|
|
708
711
|
round: g,
|
|
709
|
-
|
|
710
|
-
|
|
712
|
+
councilorId: l.id,
|
|
713
|
+
councilorName: l.frontmatter.name,
|
|
711
714
|
content: K,
|
|
712
715
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
713
716
|
model: D,
|
|
@@ -718,14 +721,14 @@ async function pt(o, r, t, e, s) {
|
|
|
718
721
|
x && (u += x.input, c += x.output), i.push(ee), n.onEvent({ type: "turn_complete", turn: ee });
|
|
719
722
|
} catch (f) {
|
|
720
723
|
const D = f instanceof Error ? f.message : String(f);
|
|
721
|
-
_.error("conversation", `Turn failed for ${l.frontmatter.name} (round ${p}, model ${l.frontmatter.model ?? "default"}, backend ${l.frontmatter.backend})`, f), n.onEvent({ type: "error",
|
|
724
|
+
_.error("conversation", `Turn failed for ${l.frontmatter.name} (round ${p}, model ${l.frontmatter.model ?? "default"}, backend ${l.frontmatter.backend})`, f), n.onEvent({ type: "error", councilorName: l.frontmatter.name, error: D });
|
|
722
725
|
}
|
|
723
726
|
}
|
|
724
727
|
if (n.onEvent({ type: "round_complete", round: p }), m && n.config?.secretary?.backend && !n.signal?.aborted)
|
|
725
728
|
try {
|
|
726
729
|
const l = H(n, i, a, u, c, y);
|
|
727
730
|
n.onEvent({ type: "round_summary_start", round: p });
|
|
728
|
-
const g = await
|
|
731
|
+
const g = await at({
|
|
729
732
|
result: l,
|
|
730
733
|
roundNumber: p,
|
|
731
734
|
config: n.config,
|
|
@@ -742,74 +745,74 @@ async function pt(o, r, t, e, s) {
|
|
|
742
745
|
return H(n, i, a, u, c, y);
|
|
743
746
|
}
|
|
744
747
|
const I = d(v(), ".ai-council", "history");
|
|
745
|
-
function
|
|
748
|
+
function ht(o) {
|
|
746
749
|
return o.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
747
750
|
}
|
|
748
|
-
async function
|
|
751
|
+
async function gt(o) {
|
|
749
752
|
await N(I, { recursive: !0 });
|
|
750
|
-
const
|
|
751
|
-
return await P(
|
|
753
|
+
const s = new Date(o.startedAt).toISOString().replace(/[:.]/g, "-").slice(0, 19), t = ht(o.topic), e = `${s}-${t}`, r = d(I, `${e}.json`);
|
|
754
|
+
return await P(r, JSON.stringify(o, null, 2), "utf-8"), e;
|
|
752
755
|
}
|
|
753
|
-
async function
|
|
756
|
+
async function yt() {
|
|
754
757
|
await N(I, { recursive: !0 });
|
|
755
|
-
const o = await V(I),
|
|
758
|
+
const o = await V(I), s = [];
|
|
756
759
|
for (const t of o)
|
|
757
760
|
if (t.endsWith(".json"))
|
|
758
761
|
try {
|
|
759
|
-
const e = await w(d(I, t), "utf-8"),
|
|
760
|
-
|
|
762
|
+
const e = await w(d(I, t), "utf-8"), r = JSON.parse(e);
|
|
763
|
+
s.push({
|
|
761
764
|
id: C(t, ".json"),
|
|
762
|
-
topic:
|
|
763
|
-
title:
|
|
764
|
-
|
|
765
|
-
rounds:
|
|
766
|
-
startedAt:
|
|
767
|
-
completedAt:
|
|
765
|
+
topic: r.topic,
|
|
766
|
+
title: r.title,
|
|
767
|
+
councilors: r.councilors.map((n) => n.name),
|
|
768
|
+
rounds: r.rounds,
|
|
769
|
+
startedAt: r.startedAt,
|
|
770
|
+
completedAt: r.completedAt
|
|
768
771
|
});
|
|
769
772
|
} catch {
|
|
770
773
|
}
|
|
771
|
-
return
|
|
774
|
+
return s.sort((t, e) => e.startedAt.localeCompare(t.startedAt));
|
|
772
775
|
}
|
|
773
776
|
async function le(o) {
|
|
774
|
-
const
|
|
777
|
+
const s = d(I, `${o}.json`), t = await w(s, "utf-8"), e = JSON.parse(t);
|
|
775
778
|
return e.infographic && !e.infographics && (e.infographics = [e.infographic], delete e.infographic), e;
|
|
776
779
|
}
|
|
777
|
-
async function
|
|
778
|
-
const
|
|
779
|
-
await F(
|
|
780
|
+
async function wt(o) {
|
|
781
|
+
const s = d(I, `${o}.json`);
|
|
782
|
+
await F(s);
|
|
780
783
|
}
|
|
781
|
-
async function
|
|
782
|
-
const t = d(I, `${o}.json`), e = await w(t, "utf-8"),
|
|
783
|
-
|
|
784
|
+
async function bt(o, s) {
|
|
785
|
+
const t = d(I, `${o}.json`), e = await w(t, "utf-8"), r = JSON.parse(e);
|
|
786
|
+
r.infographics || (r.infographics = []), r.infographics.push(s), await P(t, JSON.stringify(r, null, 2), "utf-8");
|
|
784
787
|
}
|
|
785
|
-
async function
|
|
786
|
-
const t = d(I, `${o}.json`), e = await w(t, "utf-8"),
|
|
787
|
-
|
|
788
|
+
async function vt(o, s) {
|
|
789
|
+
const t = d(I, `${o}.json`), e = await w(t, "utf-8"), r = JSON.parse(e);
|
|
790
|
+
r.infographics && s >= 0 && s < r.infographics.length && r.infographics.splice(s, 1), await P(t, JSON.stringify(r, null, 2), "utf-8");
|
|
788
791
|
}
|
|
789
792
|
const we = De(import.meta.url);
|
|
790
|
-
function
|
|
791
|
-
const
|
|
793
|
+
function kt(o) {
|
|
794
|
+
const s = o.councilors.map((e) => e.name).join(", "), t = o.summary ?? o.turns.map((e) => `${e.councilorName}: ${e.content.slice(0, 200)}`).join(`
|
|
792
795
|
`);
|
|
793
796
|
return [
|
|
794
797
|
"Create a professional infographic summarizing a panel discussion.",
|
|
795
798
|
`Topic: ${o.topic.slice(0, 300)}`,
|
|
796
799
|
`Key points: ${t.slice(0, 1500)}`,
|
|
797
|
-
`Panelists: ${
|
|
800
|
+
`Panelists: ${s}`,
|
|
798
801
|
"Use a clean, modern design with sections for convergence points, divergence points, and key takeaways.",
|
|
799
802
|
"Include relevant icons and visual hierarchy. Use a horizontal landscape layout."
|
|
800
803
|
].join(" ");
|
|
801
804
|
}
|
|
802
|
-
function
|
|
805
|
+
function _t(o) {
|
|
803
806
|
if (o.infographic?.backend) return o.infographic.backend;
|
|
804
|
-
const
|
|
805
|
-
return
|
|
807
|
+
const s = !!(o.backends.google?.apiKey || process.env.GOOGLE_API_KEY), t = !!(o.backends.openai?.apiKey || process.env.OPENAI_API_KEY);
|
|
808
|
+
return s ? "google" : t ? "openai" : null;
|
|
806
809
|
}
|
|
807
|
-
async function
|
|
810
|
+
async function Et(o, s) {
|
|
808
811
|
const t = we("openai").default, n = (await new t({
|
|
809
|
-
apiKey:
|
|
810
|
-
...
|
|
812
|
+
apiKey: s.backends.openai?.apiKey || process.env.OPENAI_API_KEY,
|
|
813
|
+
...s.backends.openai?.baseUrl ? { baseURL: s.backends.openai.baseUrl } : {}
|
|
811
814
|
}).images.generate({
|
|
812
|
-
model: "gpt-image-1",
|
|
815
|
+
model: "gpt-image-1.5",
|
|
813
816
|
prompt: o,
|
|
814
817
|
quality: "high",
|
|
815
818
|
size: "1536x1024"
|
|
@@ -817,11 +820,11 @@ async function _t(o, r) {
|
|
|
817
820
|
if (!n) throw new Error("No image data returned from OpenAI");
|
|
818
821
|
return n;
|
|
819
822
|
}
|
|
820
|
-
async function
|
|
821
|
-
const { GoogleGenAI: t } = we("@google/genai"), e =
|
|
823
|
+
async function St(o, s) {
|
|
824
|
+
const { GoogleGenAI: t } = we("@google/genai"), e = s.backends.google?.apiKey || process.env.GOOGLE_API_KEY;
|
|
822
825
|
if (!e) throw new Error("No Google API key configured");
|
|
823
826
|
const a = (await new t({ apiKey: e }).models.generateContent({
|
|
824
|
-
model: "gemini-3-
|
|
827
|
+
model: "gemini-3.1-flash-image-preview",
|
|
825
828
|
contents: o,
|
|
826
829
|
config: {
|
|
827
830
|
responseModalities: ["IMAGE", "TEXT"]
|
|
@@ -833,11 +836,11 @@ async function Et(o, r) {
|
|
|
833
836
|
return i.inlineData.data;
|
|
834
837
|
throw new Error("No image data in Gemini response");
|
|
835
838
|
}
|
|
836
|
-
async function ue(o,
|
|
837
|
-
const e = t ??
|
|
839
|
+
async function ue(o, s, t) {
|
|
840
|
+
const e = t ?? _t(s);
|
|
838
841
|
if (!e) throw new Error("No image-capable backend configured (need OpenAI or Google API key)");
|
|
839
|
-
const
|
|
840
|
-
return e === "openai" ?
|
|
842
|
+
const r = kt(o);
|
|
843
|
+
return e === "openai" ? Et(r, s) : St(r, s);
|
|
841
844
|
}
|
|
842
845
|
const be = {
|
|
843
846
|
anthropic: "https://api.anthropic.com",
|
|
@@ -858,24 +861,24 @@ const be = {
|
|
|
858
861
|
"gemini-1.5-pro",
|
|
859
862
|
"gemini-1.5-flash"
|
|
860
863
|
];
|
|
861
|
-
async function
|
|
864
|
+
async function At(o, s) {
|
|
862
865
|
try {
|
|
863
866
|
switch (o) {
|
|
864
867
|
case "ollama": {
|
|
865
868
|
const { Ollama: t } = await import("ollama");
|
|
866
|
-
return { connected: !0, models: (await new t({ host:
|
|
869
|
+
return { connected: !0, models: (await new t({ host: s.baseUrl || be.ollama }).list()).models.map((a) => a.name).sort() };
|
|
867
870
|
}
|
|
868
871
|
case "openai": {
|
|
869
872
|
const { default: t } = await import("openai");
|
|
870
873
|
return { connected: !0, models: (await new t({
|
|
871
|
-
apiKey:
|
|
872
|
-
...
|
|
874
|
+
apiKey: s.apiKey || process.env.OPENAI_API_KEY,
|
|
875
|
+
...s.baseUrl ? { baseURL: s.baseUrl } : {}
|
|
873
876
|
}).models.list()).data.map((a) => a.id).filter((a) => a.startsWith("gpt-") || a.startsWith("o") || a.startsWith("chatgpt-")).sort() };
|
|
874
877
|
}
|
|
875
878
|
case "anthropic": {
|
|
876
879
|
const { default: t } = await import("@anthropic-ai/sdk"), e = new t({
|
|
877
|
-
apiKey:
|
|
878
|
-
...
|
|
880
|
+
apiKey: s.apiKey || process.env.ANTHROPIC_API_KEY,
|
|
881
|
+
...s.baseUrl ? { baseURL: s.baseUrl } : {}
|
|
879
882
|
});
|
|
880
883
|
try {
|
|
881
884
|
return { connected: !0, models: (await e.models.list({ limit: 100 })).data.map((a) => a.id).sort() };
|
|
@@ -884,7 +887,7 @@ async function St(o, r) {
|
|
|
884
887
|
}
|
|
885
888
|
}
|
|
886
889
|
case "google": {
|
|
887
|
-
const t =
|
|
890
|
+
const t = s.apiKey || process.env.GOOGLE_API_KEY || "";
|
|
888
891
|
if (!t) return { connected: !1, models: j, error: "No API key" };
|
|
889
892
|
const e = await fetch(
|
|
890
893
|
`https://generativelanguage.googleapis.com/v1beta/models?key=${t}`
|
|
@@ -905,20 +908,20 @@ async function St(o, r) {
|
|
|
905
908
|
}
|
|
906
909
|
}
|
|
907
910
|
let A = null, B = [];
|
|
908
|
-
function
|
|
911
|
+
function It(o, s) {
|
|
909
912
|
o.handle("app:getCouncilDir", async () => {
|
|
910
913
|
const t = process.env.COUNCIL_CWD || process.cwd();
|
|
911
914
|
return G(t, "council");
|
|
912
|
-
}), o.handle("
|
|
913
|
-
const
|
|
915
|
+
}), o.handle("councilors:list", async (t, e) => {
|
|
916
|
+
const r = d(v(), ".ai-council", "config.json");
|
|
914
917
|
let n = { backends: {} };
|
|
915
918
|
try {
|
|
916
|
-
const c = await w(
|
|
919
|
+
const c = await w(r, "utf-8");
|
|
917
920
|
n = JSON.parse(c);
|
|
918
921
|
} catch {
|
|
919
922
|
}
|
|
920
|
-
const a = ae(n), i = n.
|
|
921
|
-
return (await
|
|
923
|
+
const a = ae(n), i = n.councilors ?? {};
|
|
924
|
+
return (await re(e, a)).map((c) => {
|
|
922
925
|
const m = i[c.id];
|
|
923
926
|
return {
|
|
924
927
|
id: c.id,
|
|
@@ -934,16 +937,16 @@ function At(o, r) {
|
|
|
934
937
|
registryUrl: m?.url
|
|
935
938
|
};
|
|
936
939
|
});
|
|
937
|
-
}), o.handle("
|
|
938
|
-
const
|
|
940
|
+
}), o.handle("councilors:get", async (t, e) => {
|
|
941
|
+
const r = d(e, "ABOUT.md"), n = await w(r, "utf-8"), { data: a, content: i } = X(n);
|
|
939
942
|
return { frontmatter: a, body: i.trim(), raw: n };
|
|
940
|
-
}), o.handle("
|
|
943
|
+
}), o.handle("councilors:save", async (t, e, r) => {
|
|
941
944
|
const n = d(e, "ABOUT.md");
|
|
942
|
-
return await P(n,
|
|
943
|
-
}), o.handle("
|
|
944
|
-
const a = d(e,
|
|
945
|
+
return await P(n, r, "utf-8"), { success: !0 };
|
|
946
|
+
}), o.handle("councilors:create", async (t, e, r, n) => {
|
|
947
|
+
const a = d(e, r);
|
|
945
948
|
return await N(a, { recursive: !0 }), await P(d(a, "ABOUT.md"), n, "utf-8"), { success: !0, dirPath: a };
|
|
946
|
-
}), o.handle("
|
|
949
|
+
}), o.handle("councilors:delete", async (t, e) => (await F(e, { recursive: !0, force: !0 }), { success: !0 })), o.handle("config:get", async () => {
|
|
947
950
|
const t = d(v(), ".ai-council", "config.json");
|
|
948
951
|
let e = { backends: {} };
|
|
949
952
|
try {
|
|
@@ -951,7 +954,7 @@ function At(o, r) {
|
|
|
951
954
|
e = JSON.parse(i);
|
|
952
955
|
} catch {
|
|
953
956
|
}
|
|
954
|
-
const
|
|
957
|
+
const r = {
|
|
955
958
|
ANTHROPIC_API_KEY: !!process.env.ANTHROPIC_API_KEY,
|
|
956
959
|
OPENAI_API_KEY: !!process.env.OPENAI_API_KEY,
|
|
957
960
|
GOOGLE_API_KEY: !!process.env.GOOGLE_API_KEY
|
|
@@ -960,18 +963,18 @@ function At(o, r) {
|
|
|
960
963
|
OPENAI_API_KEY: n(process.env.OPENAI_API_KEY),
|
|
961
964
|
GOOGLE_API_KEY: n(process.env.GOOGLE_API_KEY)
|
|
962
965
|
};
|
|
963
|
-
return { config: e, envStatus:
|
|
964
|
-
}), o.handle("backend:probe", async (t, e,
|
|
965
|
-
const
|
|
966
|
-
return await N(
|
|
966
|
+
return { config: e, envStatus: r, envKeySuffix: a, defaultUrls: be };
|
|
967
|
+
}), o.handle("backend:probe", async (t, e, r) => At(e, r)), o.handle("config:save", async (t, e) => {
|
|
968
|
+
const r = d(v(), ".ai-council");
|
|
969
|
+
return await N(r, { recursive: !0 }), await P(d(r, "config.json"), JSON.stringify(e, null, 2), "utf-8"), et(), { success: !0 };
|
|
967
970
|
}), o.handle("discussion:start", async (t, e) => {
|
|
968
|
-
const
|
|
969
|
-
if (!
|
|
971
|
+
const r = s();
|
|
972
|
+
if (!r) return { error: "No window" };
|
|
970
973
|
const n = (a) => {
|
|
971
|
-
|
|
974
|
+
r.isDestroyed() || r.webContents.send("discussion:event", a);
|
|
972
975
|
};
|
|
973
976
|
try {
|
|
974
|
-
A && A.abort(), A = new AbortController(), B = [], _.info("ipc:discussion", "Starting discussion", { councilDir: e.councilDir,
|
|
977
|
+
A && A.abort(), A = new AbortController(), B = [], _.info("ipc:discussion", "Starting discussion", { councilDir: e.councilDir, councilorIds: e.councilorIds, rounds: e.rounds, mode: e.mode });
|
|
975
978
|
const a = d(v(), ".ai-council", "config.json");
|
|
976
979
|
let i = { backends: {} };
|
|
977
980
|
try {
|
|
@@ -980,16 +983,16 @@ function At(o, r) {
|
|
|
980
983
|
} catch {
|
|
981
984
|
}
|
|
982
985
|
const u = ae(i);
|
|
983
|
-
_.info("ipc:discussion", `Loading
|
|
984
|
-
const c = await
|
|
985
|
-
if (_.info("ipc:discussion", `Resolved ${m.length}
|
|
986
|
-
n({ type: "error",
|
|
986
|
+
_.info("ipc:discussion", `Loading councilors from ${e.councilDir} + ${u.length} registered paths`);
|
|
987
|
+
const c = await re(e.councilDir, u), m = e.councilorIds?.length ? c.filter((l) => e.councilorIds.includes(l.id)) : c;
|
|
988
|
+
if (_.info("ipc:discussion", `Resolved ${m.length} councilors: ${m.map((l) => l.id).join(", ")}`), m.length === 0) {
|
|
989
|
+
n({ type: "error", councilorName: "", error: "No councilors found" });
|
|
987
990
|
return;
|
|
988
991
|
}
|
|
989
992
|
const y = async () => B.length === 0 ? null : {
|
|
990
993
|
round: 0,
|
|
991
|
-
|
|
992
|
-
|
|
994
|
+
councilorId: "__user__",
|
|
995
|
+
councilorName: "You",
|
|
993
996
|
content: B.shift(),
|
|
994
997
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
995
998
|
model: "human",
|
|
@@ -997,7 +1000,7 @@ function At(o, r) {
|
|
|
997
1000
|
}, h = !!e.previousTurns?.length, p = {
|
|
998
1001
|
topic: e.topic,
|
|
999
1002
|
topicSource: e.topicSource,
|
|
1000
|
-
|
|
1003
|
+
councilors: m,
|
|
1001
1004
|
rounds: e.rounds,
|
|
1002
1005
|
onEvent: n,
|
|
1003
1006
|
beforeTurn: y,
|
|
@@ -1006,11 +1009,11 @@ function At(o, r) {
|
|
|
1006
1009
|
config: i,
|
|
1007
1010
|
previousTurns: e.previousTurns,
|
|
1008
1011
|
previousSummary: e.previousSummary
|
|
1009
|
-
}, b = await
|
|
1012
|
+
}, b = await ft(p);
|
|
1010
1013
|
if (i.secretary?.backend)
|
|
1011
1014
|
try {
|
|
1012
1015
|
n({ type: "summary_start" });
|
|
1013
|
-
const l = await
|
|
1016
|
+
const l = await rt({
|
|
1014
1017
|
result: b,
|
|
1015
1018
|
config: i,
|
|
1016
1019
|
onChunk: (g) => {
|
|
@@ -1020,11 +1023,11 @@ function At(o, r) {
|
|
|
1020
1023
|
});
|
|
1021
1024
|
b.summary = l.text, l.diagram && (b.diagram = l.diagram), n({ type: "summary_complete", summary: l.text, diagram: l.diagram });
|
|
1022
1025
|
} catch (l) {
|
|
1023
|
-
_.error("ipc:discussion", "Secretary summary failed", l), n({ type: "error",
|
|
1026
|
+
_.error("ipc:discussion", "Secretary summary failed", l), n({ type: "error", councilorName: "Secretary", error: l instanceof Error ? l.message : String(l) });
|
|
1024
1027
|
}
|
|
1025
1028
|
if (i.secretary?.backend)
|
|
1026
1029
|
try {
|
|
1027
|
-
const l = b.turns.filter((f) => f.round === 1), g = await
|
|
1030
|
+
const l = b.turns.filter((f) => f.round === 1), g = await it({
|
|
1028
1031
|
topic: b.topic,
|
|
1029
1032
|
firstRoundTurns: l,
|
|
1030
1033
|
config: i
|
|
@@ -1044,27 +1047,27 @@ function At(o, r) {
|
|
|
1044
1047
|
}
|
|
1045
1048
|
e.continuedFrom && (b.continuedFrom = e.continuedFrom), n({ type: "complete", result: b });
|
|
1046
1049
|
try {
|
|
1047
|
-
await
|
|
1050
|
+
await gt(b);
|
|
1048
1051
|
} catch (l) {
|
|
1049
1052
|
_.error("ipc:discussion", "Failed to save to history", l);
|
|
1050
1053
|
}
|
|
1051
1054
|
} catch (a) {
|
|
1052
|
-
_.error("ipc:discussion", "Discussion failed", a), n({ type: "error",
|
|
1055
|
+
_.error("ipc:discussion", "Discussion failed", a), n({ type: "error", councilorName: "", error: a instanceof Error ? a.message : String(a) });
|
|
1053
1056
|
} finally {
|
|
1054
1057
|
A = null;
|
|
1055
1058
|
}
|
|
1056
|
-
}), o.handle("discussion:stop", async () => (A && (A.abort(), A = null), { success: !0 })), o.handle("discussion:inject", async (t, e) => (B.push(e), { success: !0 })), o.handle("registry:add-local", async (t, e) =>
|
|
1059
|
+
}), o.handle("discussion:stop", async () => (A && (A.abort(), A = null), { success: !0 })), o.handle("discussion:inject", async (t, e) => (B.push(e), { success: !0 })), o.handle("registry:add-local", async (t, e) => He(e)), o.handle("registry:add-remote", async (t, e) => Je(e)), o.handle("registry:remove", async (t, e, r) => (await ze(e, r), { success: !0 })), o.handle("shell:open-in-finder", async (t, e) => {
|
|
1057
1060
|
te.showItemInFolder(d(e, "ABOUT.md"));
|
|
1058
1061
|
}), o.handle("shell:open-in-terminal", async (t, e) => {
|
|
1059
1062
|
await U(R)("open", ["-a", "Terminal", e]);
|
|
1060
1063
|
}), o.handle("shell:open-in-editor", async (t, e) => {
|
|
1061
|
-
const
|
|
1064
|
+
const r = U(R);
|
|
1062
1065
|
try {
|
|
1063
|
-
await
|
|
1066
|
+
await r("code", [e]);
|
|
1064
1067
|
} catch {
|
|
1065
1068
|
te.openPath(e);
|
|
1066
1069
|
}
|
|
1067
|
-
}), o.handle("history:list", async () =>
|
|
1070
|
+
}), o.handle("history:list", async () => yt()), o.handle("history:get", async (t, e) => le(e)), o.handle("history:delete", async (t, e) => (await wt(e), { success: !0 })), o.handle("infographic:generate", async (t, e, r) => {
|
|
1068
1071
|
const n = d(v(), ".ai-council", "config.json");
|
|
1069
1072
|
let a = { backends: {} };
|
|
1070
1073
|
try {
|
|
@@ -1072,10 +1075,10 @@ function At(o, r) {
|
|
|
1072
1075
|
a = JSON.parse(c);
|
|
1073
1076
|
} catch {
|
|
1074
1077
|
}
|
|
1075
|
-
const i = await le(e), u = await ue(i, a,
|
|
1076
|
-
return await
|
|
1077
|
-
}), o.handle("infographic:delete", async (t, e,
|
|
1078
|
-
const
|
|
1078
|
+
const i = await le(e), u = await ue(i, a, r);
|
|
1079
|
+
return await bt(e, u), { infographic: u };
|
|
1080
|
+
}), o.handle("infographic:delete", async (t, e, r) => (await vt(e, r), { success: !0 })), o.handle("file:read-as-text", async (t, e) => {
|
|
1081
|
+
const r = C(e), n = r.includes(".") ? "." + r.split(".").pop().toLowerCase() : "", a = /* @__PURE__ */ new Set([
|
|
1079
1082
|
".txt",
|
|
1080
1083
|
".md",
|
|
1081
1084
|
".csv",
|
|
@@ -1126,9 +1129,9 @@ function At(o, r) {
|
|
|
1126
1129
|
if (a.has(n))
|
|
1127
1130
|
try {
|
|
1128
1131
|
const u = await w(e, "utf-8");
|
|
1129
|
-
return { name:
|
|
1132
|
+
return { name: r, content: u };
|
|
1130
1133
|
} catch (u) {
|
|
1131
|
-
return { name:
|
|
1134
|
+
return { name: r, content: `[Error reading file: ${u instanceof Error ? u.message : String(u)}]` };
|
|
1132
1135
|
}
|
|
1133
1136
|
if (i.has(n)) {
|
|
1134
1137
|
const u = U(R);
|
|
@@ -1138,16 +1141,16 @@ function At(o, r) {
|
|
|
1138
1141
|
maxBuffer: 10485760
|
|
1139
1142
|
// 10 MB
|
|
1140
1143
|
});
|
|
1141
|
-
return { name:
|
|
1144
|
+
return { name: r, content: c };
|
|
1142
1145
|
} catch (c) {
|
|
1143
1146
|
const m = c instanceof Error ? c.message : String(c);
|
|
1144
1147
|
return m.includes("ENOENT") ? {
|
|
1145
|
-
name:
|
|
1148
|
+
name: r,
|
|
1146
1149
|
content: `[Cannot convert ${n} file: markitdown is not installed. Run: pip install 'markitdown[all]']`
|
|
1147
|
-
} : { name:
|
|
1150
|
+
} : { name: r, content: `[Error converting file: ${m}]` };
|
|
1148
1151
|
}
|
|
1149
1152
|
}
|
|
1150
|
-
return { name:
|
|
1153
|
+
return { name: r, content: `[Unsupported file type: ${r}]` };
|
|
1151
1154
|
}), o.handle("markitdown:check", async () => {
|
|
1152
1155
|
const t = U(R);
|
|
1153
1156
|
try {
|
|
@@ -1167,7 +1170,7 @@ function At(o, r) {
|
|
|
1167
1170
|
return { success: !1, error: e instanceof Error ? e.message : String(e) };
|
|
1168
1171
|
}
|
|
1169
1172
|
}), o.handle("dialog:selectDirectory", async () => {
|
|
1170
|
-
const t =
|
|
1173
|
+
const t = s();
|
|
1171
1174
|
if (!t) return null;
|
|
1172
1175
|
const e = await Ee.showOpenDialog(t, {
|
|
1173
1176
|
properties: ["openDirectory"]
|
|
@@ -1175,11 +1178,11 @@ function At(o, r) {
|
|
|
1175
1178
|
return e.canceled ? null : e.filePaths[0];
|
|
1176
1179
|
});
|
|
1177
1180
|
}
|
|
1178
|
-
const
|
|
1181
|
+
const Ot = Oe(import.meta.url), J = Ie(Ot), ve = d(v(), ".ai-council");
|
|
1179
1182
|
Pe(ve, { recursive: !0 });
|
|
1180
1183
|
const ke = d(ve, "electron-debug.log");
|
|
1181
|
-
function $(o, ...
|
|
1182
|
-
const t = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${o}] ${
|
|
1184
|
+
function $(o, ...s) {
|
|
1185
|
+
const t = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${o}] ${s.map((e) => typeof e == "string" ? e : JSON.stringify(e)).join(" ")}
|
|
1183
1186
|
`;
|
|
1184
1187
|
Ne(ke, t);
|
|
1185
1188
|
}
|
|
@@ -1200,20 +1203,20 @@ function me() {
|
|
|
1200
1203
|
nodeIntegration: !1,
|
|
1201
1204
|
preload: d(J, "preload.mjs")
|
|
1202
1205
|
}
|
|
1203
|
-
}), S.webContents.on("console-message", (
|
|
1206
|
+
}), S.webContents.on("console-message", (s, t, e, r, n) => {
|
|
1204
1207
|
const a = ["DEBUG", "INFO", "WARN", "ERROR"][t] || "LOG";
|
|
1205
|
-
$(`renderer:${a}`, `${e} (${n}:${
|
|
1206
|
-
}), S.webContents.on("render-process-gone", (
|
|
1208
|
+
$(`renderer:${a}`, `${e} (${n}:${r})`);
|
|
1209
|
+
}), S.webContents.on("render-process-gone", (s, t) => {
|
|
1207
1210
|
$("main:CRASH", "Renderer process gone:", t);
|
|
1208
|
-
}), S.webContents.on("did-fail-load", (
|
|
1211
|
+
}), S.webContents.on("did-fail-load", (s, t, e) => {
|
|
1209
1212
|
$("main:LOAD_ERROR", `Failed to load: ${t} ${e}`);
|
|
1210
1213
|
});
|
|
1211
1214
|
const o = process.env.VITE_DEV_SERVER_URL;
|
|
1212
1215
|
if (o)
|
|
1213
1216
|
$("main", `Loading dev server URL: ${o}`), S.loadURL(o);
|
|
1214
1217
|
else {
|
|
1215
|
-
const
|
|
1216
|
-
$("main", `Loading file: ${
|
|
1218
|
+
const s = d(J, "../dist-renderer/index.html");
|
|
1219
|
+
$("main", `Loading file: ${s}`), S.loadFile(s);
|
|
1217
1220
|
}
|
|
1218
1221
|
process.env.VITE_DEV_SERVER_URL && S.webContents.openDevTools(), S.on("closed", () => {
|
|
1219
1222
|
S = null;
|
|
@@ -1224,7 +1227,7 @@ pe.registerSchemesAsPrivileged([
|
|
|
1224
1227
|
]);
|
|
1225
1228
|
L.whenReady().then(() => {
|
|
1226
1229
|
$("main", "App ready, registering IPC handlers");
|
|
1227
|
-
const o = "State Change Council",
|
|
1230
|
+
const o = "State Change Council", s = [
|
|
1228
1231
|
{
|
|
1229
1232
|
label: o,
|
|
1230
1233
|
submenu: [
|
|
@@ -1244,10 +1247,10 @@ L.whenReady().then(() => {
|
|
|
1244
1247
|
{ role: "viewMenu" },
|
|
1245
1248
|
{ role: "windowMenu" }
|
|
1246
1249
|
];
|
|
1247
|
-
ne.setApplicationMenu(ne.buildFromTemplate(
|
|
1250
|
+
ne.setApplicationMenu(ne.buildFromTemplate(s)), pe.handle("council-file", (t) => {
|
|
1248
1251
|
const e = decodeURIComponent(t.url.replace("council-file://", ""));
|
|
1249
1252
|
return Se.fetch($e(e).href);
|
|
1250
|
-
}),
|
|
1253
|
+
}), It(Ae, () => S), me(), L.on("activate", () => {
|
|
1251
1254
|
fe.getAllWindows().length === 0 && me();
|
|
1252
1255
|
});
|
|
1253
1256
|
});
|