@statechange/council 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/discuss.js +20 -4
- package/dist/commands/discuss.js.map +1 -1
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +100 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/core/conversation-engine.js +15 -0
- package/dist/core/conversation-engine.js.map +1 -1
- package/dist/core/preflight.d.ts +17 -0
- package/dist/core/preflight.js +56 -0
- package/dist/core/preflight.js.map +1 -0
- package/dist/electron/ipc-handlers.js +27 -3
- package/dist/electron/ipc-handlers.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist-electron/main.js +638 -577
- package/dist-renderer/assets/{ar-SA-G6X2FPQ2-DJTj94ZY.js → ar-SA-G6X2FPQ2-DT1ABS9g.js} +1 -1
- package/dist-renderer/assets/{arc-3qXpUeCd.js → arc-B7OfCKe9.js} +1 -1
- package/dist-renderer/assets/{az-AZ-76LH7QW2-1qnzBARG.js → az-AZ-76LH7QW2-D8wBYMaH.js} +1 -1
- package/dist-renderer/assets/{bg-BG-XCXSNQG7-BIZ5IFAv.js → bg-BG-XCXSNQG7-BzDdz5-g.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-38ab4fdb-JwSYiuLB.js → blockDiagram-38ab4fdb-DRwhQ-xk.js} +1 -1
- package/dist-renderer/assets/{bn-BD-2XOGV67Q-DiYpgYAg.js → bn-BD-2XOGV67Q-Bhihwwmv.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-3d4e48cf-DUCtOTzV.js → c4Diagram-3d4e48cf-BKt-lwYH.js} +1 -1
- package/dist-renderer/assets/{ca-ES-6MX7JW3Y-CV2JFVcm.js → ca-ES-6MX7JW3Y-BXRLXOfx.js} +1 -1
- package/dist-renderer/assets/channel-BThr2Pht.js +1 -0
- package/dist-renderer/assets/{classDiagram-70f12bd4-DY_je9I9.js → classDiagram-70f12bd4-DCF0wJjS.js} +1 -1
- package/dist-renderer/assets/{classDiagram-v2-f2320105-Dm2xf0kS.js → classDiagram-v2-f2320105-DUqV3auX.js} +1 -1
- package/dist-renderer/assets/clone-Dzrmu-hX.js +1 -0
- package/dist-renderer/assets/{createText-2e5e7dd3-BU4YlynJ.js → createText-2e5e7dd3-jZiKHT8b.js} +1 -1
- package/dist-renderer/assets/{cs-CZ-2BRQDIVT-DgefxJv2.js → cs-CZ-2BRQDIVT-C2n_W20l.js} +1 -1
- package/dist-renderer/assets/{da-DK-5WZEPLOC-CQeMoU_Y.js → da-DK-5WZEPLOC-BMyGcTrK.js} +1 -1
- package/dist-renderer/assets/{de-DE-XR44H4JA-Cm7XiExL.js → de-DE-XR44H4JA-DSalSqLg.js} +1 -1
- package/dist-renderer/assets/{edges-e0da2a9e-DU4SF3SK.js → edges-e0da2a9e-CxH4eozj.js} +1 -1
- package/dist-renderer/assets/{el-GR-BZB4AONW-BKDtOlnf.js → el-GR-BZB4AONW-6JczKU8m.js} +1 -1
- package/dist-renderer/assets/{erDiagram-9861fffd-D_cCijmv.js → erDiagram-9861fffd-zrWbiPwE.js} +1 -1
- package/dist-renderer/assets/{es-ES-U4NZUMDT-Blb_L7K-.js → es-ES-U4NZUMDT-W3x9nuJM.js} +1 -1
- package/dist-renderer/assets/{eu-ES-A7QVB2H4-BZJBLMeO.js → eu-ES-A7QVB2H4-DWPIl7U2.js} +1 -1
- package/dist-renderer/assets/{fa-IR-HGAKTJCU-C8gu07sI.js → fa-IR-HGAKTJCU-6f-gS7va.js} +1 -1
- package/dist-renderer/assets/{fi-FI-Z5N7JZ37-0j8c6s09.js → fi-FI-Z5N7JZ37-D9INJayl.js} +1 -1
- package/dist-renderer/assets/{flowDb-956e92f1-BYeD7SW0.js → flowDb-956e92f1-BcD3knfQ.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-66a62f08-D_7wXttk.js → flowDiagram-66a62f08-ueJuroOL.js} +1 -1
- package/dist-renderer/assets/flowDiagram-v2-96b9c2cf-Bc_edFJX.js +1 -0
- package/dist-renderer/assets/{flowchart-elk-definition-4a651766-G1tSg-iY.js → flowchart-elk-definition-4a651766-YvyrdIKN.js} +1 -1
- package/dist-renderer/assets/{fr-FR-RHASNOE6-_cfaQNNq.js → fr-FR-RHASNOE6-Cs8X8O3s.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-c361ad54-Dk5lBh7P.js → ganttDiagram-c361ad54-DUs5xgl-.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-72cf32ee-BzJAQtIC.js → gitGraphDiagram-72cf32ee-DerrZoOI.js} +1 -1
- package/dist-renderer/assets/{gl-ES-HMX3MZ6V-GM5nrSrW.js → gl-ES-HMX3MZ6V-id5cZnrR.js} +1 -1
- package/dist-renderer/assets/{graph-C_xi4PaI.js → graph-qZGJ3a_0.js} +1 -1
- package/dist-renderer/assets/{he-IL-6SHJWFNN-DvBtF7-G.js → he-IL-6SHJWFNN-ClkmOrEY.js} +1 -1
- package/dist-renderer/assets/{hi-IN-IWLTKZ5I-CNEB0-5K.js → hi-IN-IWLTKZ5I-XcT0be4B.js} +1 -1
- package/dist-renderer/assets/{hu-HU-A5ZG7DT2-BmzYfJwp.js → hu-HU-A5ZG7DT2-BauiuWYa.js} +1 -1
- package/dist-renderer/assets/{id-ID-SAP4L64H-CGCjaOLU.js → id-ID-SAP4L64H-BjwDtEsw.js} +1 -1
- package/dist-renderer/assets/{index-3862675e-C8a4355J.js → index-3862675e--n2KjoQQ.js} +1 -1
- package/dist-renderer/assets/{index-Cc7m7vZn.js → index-Bff8gOpX.js} +29 -29
- package/dist-renderer/assets/{index-x_yLI1Xq.js → index-DiVVwzho.js} +4 -4
- package/dist-renderer/assets/index-qNRDTlPC.css +1 -0
- package/dist-renderer/assets/{infoDiagram-f8f76790-BsJdteru.js → infoDiagram-f8f76790-D5cAW55N.js} +1 -1
- package/dist-renderer/assets/{it-IT-JPQ66NNP-vK6cBs4I.js → it-IT-JPQ66NNP-GSOK3zyA.js} +1 -1
- package/dist-renderer/assets/{ja-JP-DBVTYXUO-oUvELdsq.js → ja-JP-DBVTYXUO-BqdBOVtd.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-49397b02-BZcn-joQ.js → journeyDiagram-49397b02-D3g-8QZM.js} +1 -1
- package/dist-renderer/assets/{kaa-6HZHGXH3-39-zh5xR.js → kaa-6HZHGXH3-BhCfH7Nw.js} +1 -1
- package/dist-renderer/assets/{kab-KAB-ZGHBKWFO-DIwwJSlv.js → kab-KAB-ZGHBKWFO-BiEpzhMA.js} +1 -1
- package/dist-renderer/assets/{kk-KZ-P5N5QNE5-jEG0G6v4.js → kk-KZ-P5N5QNE5-DQL7tI7B.js} +1 -1
- package/dist-renderer/assets/{km-KH-HSX4SM5Z-f0MtADYu.js → km-KH-HSX4SM5Z-BNzGZwqS.js} +1 -1
- package/dist-renderer/assets/{ko-KR-MTYHY66A-D0sjNbcb.js → ko-KR-MTYHY66A-BrTGfdJs.js} +1 -1
- package/dist-renderer/assets/{ku-TR-6OUDTVRD-D_uqAOZU.js → ku-TR-6OUDTVRD-DV6qxsd3.js} +1 -1
- package/dist-renderer/assets/{layout-Bho0HnCB.js → layout-qt9ncKQO.js} +1 -1
- package/dist-renderer/assets/{line-BvfrpBJA.js → line-LCvRLu_z.js} +1 -1
- package/dist-renderer/assets/{linear-CzjqC3F_.js → linear-B1dFt2Mi.js} +1 -1
- package/dist-renderer/assets/{lt-LT-XHIRWOB4-Ct0yC4CT.js → lt-LT-XHIRWOB4-WVGEZ27s.js} +1 -1
- package/dist-renderer/assets/{lv-LV-5QDEKY6T-nkNbPHg0.js → lv-LV-5QDEKY6T-77cng2TE.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-fc14e90a-BHot8rEp.js → mindmap-definition-fc14e90a-DNtcEEqa.js} +1 -1
- package/dist-renderer/assets/{mr-IN-CRQNXWMA-B861rik7.js → mr-IN-CRQNXWMA-BFexevhO.js} +1 -1
- package/dist-renderer/assets/{my-MM-5M5IBNSE-SOXg7PeE.js → my-MM-5M5IBNSE-C9Vf2u64.js} +1 -1
- package/dist-renderer/assets/{nb-NO-T6EIAALU-D22gGzt7.js → nb-NO-T6EIAALU-B6nE3WpA.js} +1 -1
- package/dist-renderer/assets/{nl-NL-IS3SIHDZ-CJxOBLb1.js → nl-NL-IS3SIHDZ-CaRaqbQC.js} +1 -1
- package/dist-renderer/assets/{nn-NO-6E72VCQL-FGcbdlO3.js → nn-NO-6E72VCQL-DgeqKi0O.js} +1 -1
- package/dist-renderer/assets/{oc-FR-POXYY2M6-s7Swo1Cu.js → oc-FR-POXYY2M6-BE5foCrM.js} +1 -1
- package/dist-renderer/assets/{pa-IN-N4M65BXN-DFJMREPh.js → pa-IN-N4M65BXN-YstXUC1N.js} +1 -1
- package/dist-renderer/assets/{percentages-BXMCSKIN-BhceqxTM.js → percentages-BXMCSKIN-ClEmrH5S.js} +7 -7
- package/dist-renderer/assets/{pica-ej4Z4fjh.js → pica-BzhwS7O9.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-8a3498a8-CnDnQfd0.js → pieDiagram-8a3498a8-Gm6b2Dvv.js} +1 -1
- package/dist-renderer/assets/{pl-PL-T2D74RX3-uXVmB6im.js → pl-PL-T2D74RX3-BYANIPnT.js} +1 -1
- package/dist-renderer/assets/{pt-BR-5N22H2LF-8kdgECeZ.js → pt-BR-5N22H2LF-Crb41rJn.js} +1 -1
- package/dist-renderer/assets/{pt-PT-UZXXM6DQ-D4vr9vo6.js → pt-PT-UZXXM6DQ-BZb84OUI.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-120e2f19-DlUESmO2.js → quadrantDiagram-120e2f19-uZf8ZOq7.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-deff3bca-CfOs9jR8.js → requirementDiagram-deff3bca-CXv-XkpA.js} +1 -1
- package/dist-renderer/assets/{ro-RO-JPDTUUEW-CztO0tWv.js → ro-RO-JPDTUUEW-pVMFDrzX.js} +1 -1
- package/dist-renderer/assets/{ru-RU-B4JR7IUQ-aVURliDr.js → ru-RU-B4JR7IUQ-BqvZXiAC.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-04a897e0-DRRc8FSN.js → sankeyDiagram-04a897e0-BE7SzdTQ.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-704730f1-BaswaqQO.js → sequenceDiagram-704730f1-mDPi1i-N.js} +1 -1
- package/dist-renderer/assets/{si-LK-N5RQ5JYF-B2KWtx6N.js → si-LK-N5RQ5JYF-CJNPpP3j.js} +1 -1
- package/dist-renderer/assets/{sk-SK-C5VTKIMK-DlRzLxRJ.js → sk-SK-C5VTKIMK-BrOHOeIl.js} +1 -1
- package/dist-renderer/assets/{sl-SI-NN7IZMDC-Ox8yiRTS.js → sl-SI-NN7IZMDC-CS9lfsZo.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-587899a1-DSEEonbL.js → stateDiagram-587899a1-X1op9_rl.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-v2-d93cdb3a-C135NgbB.js → stateDiagram-v2-d93cdb3a-DW1QycRH.js} +1 -1
- package/dist-renderer/assets/{styles-6aaf32cf-X5nh1pD3.js → styles-6aaf32cf-DPaq63ON.js} +1 -1
- package/dist-renderer/assets/{styles-9a916d00-BCZu272E.js → styles-9a916d00-BuzHNqFw.js} +1 -1
- package/dist-renderer/assets/{styles-c10674c1-C5JGHSaS.js → styles-c10674c1-DMm_j-y2.js} +1 -1
- package/dist-renderer/assets/{subset-shared.chunk-CzgdV5hf.js → subset-shared.chunk-3Aplsfln.js} +1 -1
- package/dist-renderer/assets/{subset-worker.chunk-DfLYxc1O.js → subset-worker.chunk-4W4tHba_.js} +1 -1
- package/dist-renderer/assets/{sv-SE-XGPEYMSR-CizFbLCT.js → sv-SE-XGPEYMSR-DmtGm_CR.js} +1 -1
- package/dist-renderer/assets/{svgDrawCommon-08f97a94-Cv5ZIzzk.js → svgDrawCommon-08f97a94-Cwi8wjQD.js} +1 -1
- package/dist-renderer/assets/{ta-IN-2NMHFXQM-B66K2LEN.js → ta-IN-2NMHFXQM-6iYbXM4R.js} +1 -1
- package/dist-renderer/assets/{th-TH-HPSO5L25-DvHt1SBY.js → th-TH-HPSO5L25-CeMt3K_X.js} +1 -1
- package/dist-renderer/assets/{timeline-definition-85554ec2-C955-u4m.js → timeline-definition-85554ec2-DDvzM2vU.js} +1 -1
- package/dist-renderer/assets/{tr-TR-DEFEU3FU-u0AuqRoD.js → tr-TR-DEFEU3FU-kKNTgK1x.js} +1 -1
- package/dist-renderer/assets/{uk-UA-QMV73CPH-IwAiPvJL.js → uk-UA-QMV73CPH-DXv_zymS.js} +1 -1
- package/dist-renderer/assets/{vi-VN-M7AON7JQ-Dh6Aj3f5.js → vi-VN-M7AON7JQ-DeRc6V7y.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-e933f94c-Bst4jMma.js → xychartDiagram-e933f94c-Bwdd1C-0.js} +1 -1
- package/dist-renderer/assets/{zh-CN-LNUGB5OW-BVXMa9T3.js → zh-CN-LNUGB5OW-DAkhZJEJ.js} +1 -1
- package/dist-renderer/assets/{zh-HK-E62DVLB3-DYEIu92z.js → zh-HK-E62DVLB3-MU8npHxs.js} +1 -1
- package/dist-renderer/assets/{zh-TW-RAJ6MFWO-Dm9oSthu.js → zh-TW-RAJ6MFWO-BHTDbzbd.js} +1 -1
- package/dist-renderer/index.html +2 -2
- package/package.json +1 -1
- package/dist-renderer/assets/channel-BFQOS5-A.js +0 -1
- package/dist-renderer/assets/clone-BdgQjyvt.js +0 -1
- package/dist-renderer/assets/flowDiagram-v2-96b9c2cf-ue4yLZei.js +0 -1
- package/dist-renderer/assets/index-CYsh274_.css +0 -1
package/dist-electron/main.js
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
import { shell as
|
|
2
|
-
import { join as u, basename as
|
|
1
|
+
import { shell as ne, dialog as $e, app as K, protocol as ge, Menu as oe, net as Ae, BrowserWindow as he, ipcMain as Ie } from "electron";
|
|
2
|
+
import { join as u, basename as N, resolve as W, dirname as Oe } from "node:path";
|
|
3
3
|
import { fileURLToPath as Pe, pathToFileURL as Ce } from "node:url";
|
|
4
|
-
import { existsSync as
|
|
5
|
-
import { homedir as
|
|
6
|
-
import { readFile as w, readdir as
|
|
4
|
+
import { existsSync as E, mkdirSync as Ne, writeFileSync as xe, appendFileSync as Te } from "node:fs";
|
|
5
|
+
import { homedir as k } from "node:os";
|
|
6
|
+
import { readFile as w, readdir as Q, stat as ye, mkdir as x, rm as Y, writeFile as C, appendFile as Re } from "node:fs/promises";
|
|
7
7
|
import { execFile as R } from "node:child_process";
|
|
8
|
-
import { promisify as
|
|
9
|
-
import
|
|
10
|
-
import { z as
|
|
8
|
+
import { promisify as U } from "node:util";
|
|
9
|
+
import Z from "gray-matter";
|
|
10
|
+
import { z as S } from "zod";
|
|
11
11
|
import Ue from "@anthropic-ai/sdk";
|
|
12
12
|
import Le from "openai";
|
|
13
13
|
import { GoogleGenerativeAI as De } from "@google/generative-ai";
|
|
14
14
|
import { Ollama as je } from "ollama";
|
|
15
15
|
import { createRequire as Ke } from "node:module";
|
|
16
16
|
import "dotenv/config";
|
|
17
|
-
const Be =
|
|
18
|
-
name:
|
|
19
|
-
description:
|
|
20
|
-
interests:
|
|
21
|
-
backend:
|
|
22
|
-
model:
|
|
23
|
-
skills:
|
|
24
|
-
temperature:
|
|
25
|
-
avatar:
|
|
26
|
-
}),
|
|
17
|
+
const Be = S.object({
|
|
18
|
+
name: S.string(),
|
|
19
|
+
description: S.string(),
|
|
20
|
+
interests: S.array(S.string()).default([]),
|
|
21
|
+
backend: S.enum(["anthropic", "openai", "google", "ollama"]),
|
|
22
|
+
model: S.string().optional(),
|
|
23
|
+
skills: S.array(S.string()).default([]),
|
|
24
|
+
temperature: S.number().min(0).max(2).optional(),
|
|
25
|
+
avatar: S.string().optional()
|
|
26
|
+
}), Me = (o, s) => [
|
|
27
27
|
u(o, "skills", s, "SKILL.md"),
|
|
28
28
|
u(process.cwd(), ".claude", "skills", s, "SKILL.md"),
|
|
29
|
-
u(
|
|
30
|
-
u(
|
|
29
|
+
u(k(), ".agents", "skills", s, "SKILL.md"),
|
|
30
|
+
u(k(), ".claude", "skills", s, "SKILL.md")
|
|
31
31
|
];
|
|
32
|
-
async function
|
|
33
|
-
for (const
|
|
34
|
-
if (
|
|
35
|
-
const e = await w(
|
|
32
|
+
async function Ge(o, s) {
|
|
33
|
+
for (const n of Me(s, o))
|
|
34
|
+
if (E(n)) {
|
|
35
|
+
const e = await w(n, "utf-8"), { content: r } = Z(e);
|
|
36
36
|
return r.trim();
|
|
37
37
|
}
|
|
38
38
|
return null;
|
|
39
39
|
}
|
|
40
|
-
async function
|
|
41
|
-
const
|
|
40
|
+
async function Fe(o, s) {
|
|
41
|
+
const n = [];
|
|
42
42
|
for (const e of o) {
|
|
43
|
-
const r = await
|
|
44
|
-
r &&
|
|
43
|
+
const r = await Ge(e, s);
|
|
44
|
+
r && n.push(`## Skill: ${e}
|
|
45
45
|
|
|
46
46
|
${r}`);
|
|
47
47
|
}
|
|
48
|
-
return
|
|
48
|
+
return n.join(`
|
|
49
49
|
|
|
50
50
|
`);
|
|
51
51
|
}
|
|
@@ -53,140 +53,140 @@ function We(o, s) {
|
|
|
53
53
|
return o ? o.startsWith("http://") || o.startsWith("https://") ? o : `council-file://${o.startsWith("/") ? o : u(s, o)}` : void 0;
|
|
54
54
|
}
|
|
55
55
|
async function Ye(o, s) {
|
|
56
|
-
const
|
|
56
|
+
const n = /\{\{(.+?)\}\}/g;
|
|
57
57
|
let e = o;
|
|
58
|
-
for (const r of o.matchAll(
|
|
59
|
-
const
|
|
60
|
-
if (
|
|
58
|
+
for (const r of o.matchAll(n)) {
|
|
59
|
+
const t = r[1].trim(), a = u(s, t);
|
|
60
|
+
if (E(a)) {
|
|
61
61
|
const i = await w(a, "utf-8");
|
|
62
62
|
e = e.replace(r[0], i.trim());
|
|
63
63
|
} else
|
|
64
|
-
e = e.replace(r[0], `[Reference not found: ${
|
|
64
|
+
e = e.replace(r[0], `[Reference not found: ${t}]`);
|
|
65
65
|
}
|
|
66
66
|
return e;
|
|
67
67
|
}
|
|
68
|
-
async function
|
|
69
|
-
const s =
|
|
70
|
-
if (!
|
|
68
|
+
async function re(o) {
|
|
69
|
+
const s = W(o), n = u(s, "ABOUT.md");
|
|
70
|
+
if (!E(n))
|
|
71
71
|
throw new Error(`No ABOUT.md found in ${s}`);
|
|
72
|
-
const e = await w(
|
|
73
|
-
let i = await Ye(
|
|
72
|
+
const e = await w(n, "utf-8"), { data: r, content: t } = Z(e), a = Be.parse(r);
|
|
73
|
+
let i = await Ye(t.trim(), s);
|
|
74
74
|
if (a.skills.length > 0) {
|
|
75
|
-
const
|
|
76
|
-
|
|
75
|
+
const c = await Fe(a.skills, s);
|
|
76
|
+
c && (i += `
|
|
77
77
|
|
|
78
|
-
` +
|
|
78
|
+
` + c);
|
|
79
79
|
}
|
|
80
80
|
return {
|
|
81
|
-
id:
|
|
81
|
+
id: N(s),
|
|
82
82
|
frontmatter: a,
|
|
83
83
|
systemPrompt: i,
|
|
84
84
|
dirPath: s,
|
|
85
85
|
avatarUrl: We(a.avatar, s)
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
|
-
async function
|
|
89
|
-
const
|
|
88
|
+
async function se(o, s) {
|
|
89
|
+
const n = [], e = /* @__PURE__ */ new Set();
|
|
90
90
|
if (s?.length) {
|
|
91
91
|
for (const r of s)
|
|
92
|
-
if (
|
|
92
|
+
if (E(u(r, "ABOUT.md")))
|
|
93
93
|
try {
|
|
94
|
-
const
|
|
95
|
-
e.has(
|
|
94
|
+
const t = await re(r);
|
|
95
|
+
e.has(t.id) || (n.push(t), e.add(t.id));
|
|
96
96
|
} catch {
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
if (
|
|
100
|
-
const r = await
|
|
101
|
-
for (const
|
|
102
|
-
const a = u(o,
|
|
103
|
-
(await
|
|
99
|
+
if (E(o)) {
|
|
100
|
+
const r = await Q(o);
|
|
101
|
+
for (const t of r) {
|
|
102
|
+
const a = u(o, t);
|
|
103
|
+
(await ye(a)).isDirectory() && E(u(a, "ABOUT.md")) && (e.has(N(a)) || (n.push(await re(a)), e.add(N(a))));
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
if (
|
|
106
|
+
if (n.length === 0)
|
|
107
107
|
throw new Error(
|
|
108
108
|
`No councilors found. Searched ${o}${s?.length ? ` and ${s.length} registered path(s)` : ""}.
|
|
109
109
|
Create one with: mkdir -p ~/.ai-council/councilors/my-councilor && council councilor add ~/.ai-council/councilors/my-councilor`
|
|
110
110
|
);
|
|
111
|
-
return
|
|
111
|
+
return n;
|
|
112
112
|
}
|
|
113
|
-
const He =
|
|
114
|
-
async function
|
|
113
|
+
const He = U(R), we = u(k(), ".ai-council", "config.json"), ae = u(k(), ".ai-council", "councilors");
|
|
114
|
+
async function q() {
|
|
115
115
|
try {
|
|
116
|
-
return JSON.parse(await w(
|
|
116
|
+
return JSON.parse(await w(we, "utf-8"));
|
|
117
117
|
} catch {
|
|
118
118
|
return { backends: {} };
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
async function
|
|
122
|
-
const s = u(
|
|
123
|
-
await
|
|
121
|
+
async function ee(o) {
|
|
122
|
+
const s = u(k(), ".ai-council");
|
|
123
|
+
await x(s, { recursive: !0 }), await C(we, JSON.stringify(o, null, 2), "utf-8");
|
|
124
124
|
}
|
|
125
125
|
function Je(o) {
|
|
126
126
|
return o.councilors ?? o.counsellors ?? {};
|
|
127
127
|
}
|
|
128
|
-
function
|
|
128
|
+
function ie(o) {
|
|
129
129
|
return Object.values(Je(o)).map((s) => s.path);
|
|
130
130
|
}
|
|
131
131
|
async function ze(o) {
|
|
132
|
-
const s =
|
|
133
|
-
if (!
|
|
132
|
+
const s = W(o), n = u(s, "ABOUT.md");
|
|
133
|
+
if (!E(n))
|
|
134
134
|
throw new Error(`No ABOUT.md found in ${s}`);
|
|
135
|
-
const e =
|
|
136
|
-
if (
|
|
137
|
-
throw new Error(`Councilor "${e}" is already registered (path: ${
|
|
138
|
-
const
|
|
139
|
-
return
|
|
135
|
+
const e = N(s), r = await q(), t = r.councilors ?? {};
|
|
136
|
+
if (t[e])
|
|
137
|
+
throw new Error(`Councilor "${e}" is already registered (path: ${t[e].path})`);
|
|
138
|
+
const c = (await w(n, "utf-8")).match(/^name:\s*["']?(.+?)["']?\s*$/m)?.[1] ?? e;
|
|
139
|
+
return t[e] = {
|
|
140
140
|
path: s,
|
|
141
141
|
source: "local",
|
|
142
142
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
143
|
-
}, r.councilors =
|
|
143
|
+
}, r.councilors = t, await ee(r), { id: e, name: c };
|
|
144
144
|
}
|
|
145
145
|
async function Ve(o) {
|
|
146
|
-
await
|
|
147
|
-
const s =
|
|
148
|
-
if (
|
|
149
|
-
throw new Error(`Directory already exists: ${
|
|
150
|
-
await He("git", ["clone", "--depth", "1", o,
|
|
151
|
-
const e = [], r = await
|
|
152
|
-
if (
|
|
146
|
+
await x(ae, { recursive: !0 });
|
|
147
|
+
const s = N(o, ".git").replace(/\.git$/, ""), n = u(ae, s);
|
|
148
|
+
if (E(n))
|
|
149
|
+
throw new Error(`Directory already exists: ${n}. Remove it first or use a different URL.`);
|
|
150
|
+
await He("git", ["clone", "--depth", "1", o, n]);
|
|
151
|
+
const e = [], r = await q(), t = r.councilors ?? {};
|
|
152
|
+
if (E(u(n, "ABOUT.md"))) {
|
|
153
153
|
const a = s;
|
|
154
|
-
if (
|
|
154
|
+
if (t[a])
|
|
155
155
|
throw new Error(`Councilor "${a}" is already registered`);
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
path:
|
|
156
|
+
const l = (await w(u(n, "ABOUT.md"), "utf-8")).match(/^name:\s*["']?(.+?)["']?\s*$/m)?.[1] ?? a;
|
|
157
|
+
t[a] = {
|
|
158
|
+
path: n,
|
|
159
159
|
source: "git",
|
|
160
160
|
url: o,
|
|
161
161
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
162
|
-
}, e.push({ id: a, name:
|
|
162
|
+
}, e.push({ id: a, name: l });
|
|
163
163
|
} else {
|
|
164
|
-
const a = await
|
|
164
|
+
const a = await Q(n);
|
|
165
165
|
for (const i of a) {
|
|
166
166
|
if (i.startsWith(".")) continue;
|
|
167
|
-
const
|
|
168
|
-
if ((await
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
171
|
-
const g = (await w(u(
|
|
172
|
-
|
|
173
|
-
path:
|
|
167
|
+
const c = u(n, i);
|
|
168
|
+
if ((await ye(c)).isDirectory() && E(u(c, "ABOUT.md"))) {
|
|
169
|
+
const m = i;
|
|
170
|
+
if (t[m]) continue;
|
|
171
|
+
const g = (await w(u(c, "ABOUT.md"), "utf-8")).match(/^name:\s*["']?(.+?)["']?\s*$/m)?.[1] ?? m;
|
|
172
|
+
t[m] = {
|
|
173
|
+
path: c,
|
|
174
174
|
source: "git",
|
|
175
175
|
url: o,
|
|
176
176
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
177
|
-
}, e.push({ id:
|
|
177
|
+
}, e.push({ id: m, name: g });
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
if (e.length === 0)
|
|
181
|
-
throw await
|
|
181
|
+
throw await Y(n, { recursive: !0, force: !0 }), new Error("No councilors found in cloned repository (no ABOUT.md files)");
|
|
182
182
|
}
|
|
183
|
-
return r.councilors =
|
|
183
|
+
return r.councilors = t, await ee(r), e;
|
|
184
184
|
}
|
|
185
185
|
async function Xe(o, s = !1) {
|
|
186
|
-
const
|
|
186
|
+
const n = await q(), e = n.councilors ?? {}, r = e[o];
|
|
187
187
|
if (!r)
|
|
188
188
|
throw new Error(`Councilor "${o}" is not registered`);
|
|
189
|
-
s && r.source === "git" &&
|
|
189
|
+
s && r.source === "git" && E(r.path) && await Y(r.path, { recursive: !0, force: !0 }), delete e[o], n.councilors = e, await ee(n);
|
|
190
190
|
}
|
|
191
191
|
function Qe(o) {
|
|
192
192
|
const s = new Ue({
|
|
@@ -196,38 +196,38 @@ function Qe(o) {
|
|
|
196
196
|
return {
|
|
197
197
|
name: "anthropic",
|
|
198
198
|
defaultModel: "claude-sonnet-4-6",
|
|
199
|
-
async chat(
|
|
199
|
+
async chat(n) {
|
|
200
200
|
const e = await s.messages.create({
|
|
201
|
-
model:
|
|
201
|
+
model: n.model,
|
|
202
202
|
max_tokens: 4096,
|
|
203
|
-
system:
|
|
204
|
-
messages:
|
|
205
|
-
role:
|
|
206
|
-
content:
|
|
203
|
+
system: n.systemPrompt,
|
|
204
|
+
messages: n.messages.map((t) => ({
|
|
205
|
+
role: t.role,
|
|
206
|
+
content: t.content
|
|
207
207
|
})),
|
|
208
|
-
...
|
|
208
|
+
...n.temperature !== void 0 ? { temperature: n.temperature } : {}
|
|
209
209
|
});
|
|
210
210
|
return {
|
|
211
|
-
content: e.content.find((
|
|
211
|
+
content: e.content.find((t) => t.type === "text")?.text ?? "",
|
|
212
212
|
tokenUsage: {
|
|
213
213
|
input: e.usage.input_tokens,
|
|
214
214
|
output: e.usage.output_tokens
|
|
215
215
|
}
|
|
216
216
|
};
|
|
217
217
|
},
|
|
218
|
-
async *chatStream(
|
|
218
|
+
async *chatStream(n) {
|
|
219
219
|
const e = s.messages.stream({
|
|
220
|
-
model:
|
|
220
|
+
model: n.model,
|
|
221
221
|
max_tokens: 4096,
|
|
222
|
-
system:
|
|
223
|
-
messages:
|
|
224
|
-
role:
|
|
225
|
-
content:
|
|
222
|
+
system: n.systemPrompt,
|
|
223
|
+
messages: n.messages.map((t) => ({
|
|
224
|
+
role: t.role,
|
|
225
|
+
content: t.content
|
|
226
226
|
})),
|
|
227
|
-
...
|
|
227
|
+
...n.temperature !== void 0 ? { temperature: n.temperature } : {}
|
|
228
228
|
});
|
|
229
|
-
for await (const
|
|
230
|
-
|
|
229
|
+
for await (const t of e)
|
|
230
|
+
t.type === "content_block_delta" && t.delta.type === "text_delta" && (yield { delta: t.delta.text });
|
|
231
231
|
const r = await e.finalMessage();
|
|
232
232
|
yield {
|
|
233
233
|
delta: "",
|
|
@@ -238,14 +238,14 @@ function Qe(o) {
|
|
|
238
238
|
};
|
|
239
239
|
},
|
|
240
240
|
async listModels() {
|
|
241
|
-
const
|
|
241
|
+
const n = [];
|
|
242
242
|
for await (const e of s.models.list({ limit: 100 }))
|
|
243
|
-
|
|
243
|
+
n.push({
|
|
244
244
|
id: e.id,
|
|
245
245
|
name: e.display_name,
|
|
246
246
|
created: e.created_at
|
|
247
247
|
});
|
|
248
|
-
return
|
|
248
|
+
return n.sort((e, r) => e.id.localeCompare(r.id));
|
|
249
249
|
}
|
|
250
250
|
};
|
|
251
251
|
}
|
|
@@ -257,40 +257,40 @@ function Ze(o) {
|
|
|
257
257
|
return {
|
|
258
258
|
name: "openai",
|
|
259
259
|
defaultModel: "gpt-4o",
|
|
260
|
-
async chat(
|
|
260
|
+
async chat(n) {
|
|
261
261
|
const e = await s.chat.completions.create({
|
|
262
|
-
model:
|
|
262
|
+
model: n.model,
|
|
263
263
|
messages: [
|
|
264
|
-
{ role: "system", content:
|
|
265
|
-
...
|
|
266
|
-
role:
|
|
267
|
-
content:
|
|
264
|
+
{ role: "system", content: n.systemPrompt },
|
|
265
|
+
...n.messages.map((t) => ({
|
|
266
|
+
role: t.role,
|
|
267
|
+
content: t.content
|
|
268
268
|
}))
|
|
269
269
|
],
|
|
270
|
-
...
|
|
270
|
+
...n.temperature !== void 0 ? { temperature: n.temperature } : {}
|
|
271
271
|
});
|
|
272
272
|
return {
|
|
273
273
|
content: e.choices[0]?.message?.content ?? "",
|
|
274
274
|
tokenUsage: e.usage ? { input: e.usage.prompt_tokens, output: e.usage.completion_tokens } : void 0
|
|
275
275
|
};
|
|
276
276
|
},
|
|
277
|
-
async *chatStream(
|
|
277
|
+
async *chatStream(n) {
|
|
278
278
|
const e = await s.chat.completions.create({
|
|
279
|
-
model:
|
|
279
|
+
model: n.model,
|
|
280
280
|
messages: [
|
|
281
|
-
{ role: "system", content:
|
|
282
|
-
...
|
|
281
|
+
{ role: "system", content: n.systemPrompt },
|
|
282
|
+
...n.messages.map((r) => ({
|
|
283
283
|
role: r.role,
|
|
284
284
|
content: r.content
|
|
285
285
|
}))
|
|
286
286
|
],
|
|
287
|
-
...
|
|
287
|
+
...n.temperature !== void 0 ? { temperature: n.temperature } : {},
|
|
288
288
|
stream: !0,
|
|
289
289
|
stream_options: { include_usage: !0 }
|
|
290
290
|
});
|
|
291
291
|
for await (const r of e) {
|
|
292
|
-
const
|
|
293
|
-
|
|
292
|
+
const t = r.choices[0]?.delta?.content;
|
|
293
|
+
t && (yield { delta: t }), r.usage && (yield {
|
|
294
294
|
delta: "",
|
|
295
295
|
tokenUsage: {
|
|
296
296
|
input: r.usage.prompt_tokens,
|
|
@@ -300,61 +300,61 @@ function Ze(o) {
|
|
|
300
300
|
}
|
|
301
301
|
},
|
|
302
302
|
async listModels() {
|
|
303
|
-
const
|
|
304
|
-
for await (const r of
|
|
303
|
+
const n = await s.models.list(), e = [];
|
|
304
|
+
for await (const r of n)
|
|
305
305
|
e.push({
|
|
306
306
|
id: r.id,
|
|
307
307
|
created: new Date(r.created * 1e3).toISOString()
|
|
308
308
|
});
|
|
309
|
-
return e.sort((r,
|
|
309
|
+
return e.sort((r, t) => r.id.localeCompare(t.id));
|
|
310
310
|
}
|
|
311
311
|
};
|
|
312
312
|
}
|
|
313
313
|
function qe(o) {
|
|
314
|
-
const s = o.apiKey ?? process.env.GOOGLE_API_KEY ?? "",
|
|
314
|
+
const s = o.apiKey ?? process.env.GOOGLE_API_KEY ?? "", n = new De(s);
|
|
315
315
|
return {
|
|
316
316
|
name: "google",
|
|
317
317
|
defaultModel: "gemini-2.0-flash",
|
|
318
318
|
async chat(e) {
|
|
319
|
-
const r =
|
|
319
|
+
const r = n.getGenerativeModel({
|
|
320
320
|
model: e.model,
|
|
321
321
|
systemInstruction: e.systemPrompt,
|
|
322
322
|
generationConfig: {
|
|
323
323
|
...e.temperature !== void 0 ? { temperature: e.temperature } : {}
|
|
324
324
|
}
|
|
325
|
-
}),
|
|
326
|
-
role:
|
|
327
|
-
parts: [{ text:
|
|
328
|
-
})), a = r.startChat({ history:
|
|
325
|
+
}), t = e.messages.slice(0, -1).map((m) => ({
|
|
326
|
+
role: m.role === "assistant" ? "model" : "user",
|
|
327
|
+
parts: [{ text: m.content }]
|
|
328
|
+
})), a = r.startChat({ history: t }), i = e.messages[e.messages.length - 1], l = (await a.sendMessage(i?.content ?? "")).response;
|
|
329
329
|
return {
|
|
330
|
-
content:
|
|
331
|
-
tokenUsage:
|
|
332
|
-
input:
|
|
333
|
-
output:
|
|
330
|
+
content: l.text(),
|
|
331
|
+
tokenUsage: l.usageMetadata ? {
|
|
332
|
+
input: l.usageMetadata.promptTokenCount ?? 0,
|
|
333
|
+
output: l.usageMetadata.candidatesTokenCount ?? 0
|
|
334
334
|
} : void 0
|
|
335
335
|
};
|
|
336
336
|
},
|
|
337
337
|
async *chatStream(e) {
|
|
338
|
-
const r =
|
|
338
|
+
const r = n.getGenerativeModel({
|
|
339
339
|
model: e.model,
|
|
340
340
|
systemInstruction: e.systemPrompt,
|
|
341
341
|
generationConfig: {
|
|
342
342
|
...e.temperature !== void 0 ? { temperature: e.temperature } : {}
|
|
343
343
|
}
|
|
344
|
-
}),
|
|
345
|
-
role:
|
|
346
|
-
parts: [{ text:
|
|
347
|
-
})), a = r.startChat({ history:
|
|
348
|
-
for await (const
|
|
349
|
-
const
|
|
350
|
-
|
|
344
|
+
}), t = e.messages.slice(0, -1).map((m) => ({
|
|
345
|
+
role: m.role === "assistant" ? "model" : "user",
|
|
346
|
+
parts: [{ text: m.content }]
|
|
347
|
+
})), a = r.startChat({ history: t }), i = e.messages[e.messages.length - 1], c = await a.sendMessageStream(i?.content ?? "");
|
|
348
|
+
for await (const m of c.stream) {
|
|
349
|
+
const h = m.text();
|
|
350
|
+
h && (yield { delta: h });
|
|
351
351
|
}
|
|
352
|
-
const
|
|
352
|
+
const l = await c.response;
|
|
353
353
|
yield {
|
|
354
354
|
delta: "",
|
|
355
|
-
tokenUsage:
|
|
356
|
-
input:
|
|
357
|
-
output:
|
|
355
|
+
tokenUsage: l.usageMetadata ? {
|
|
356
|
+
input: l.usageMetadata.promptTokenCount ?? 0,
|
|
357
|
+
output: l.usageMetadata.candidatesTokenCount ?? 0
|
|
358
358
|
} : void 0
|
|
359
359
|
};
|
|
360
360
|
},
|
|
@@ -363,11 +363,11 @@ function qe(o) {
|
|
|
363
363
|
`https://generativelanguage.googleapis.com/v1beta/models?key=${s}&pageSize=100`
|
|
364
364
|
);
|
|
365
365
|
if (!e.ok) throw new Error(`Google API error: ${e.status}`);
|
|
366
|
-
return ((await e.json()).models || []).filter((
|
|
367
|
-
id:
|
|
368
|
-
name:
|
|
369
|
-
description:
|
|
370
|
-
})).sort((
|
|
366
|
+
return ((await e.json()).models || []).filter((t) => t.name.startsWith("models/gemini")).map((t) => ({
|
|
367
|
+
id: t.name.replace("models/", ""),
|
|
368
|
+
name: t.displayName,
|
|
369
|
+
description: t.description
|
|
370
|
+
})).sort((t, a) => t.id.localeCompare(a.id));
|
|
371
371
|
}
|
|
372
372
|
};
|
|
373
373
|
}
|
|
@@ -378,18 +378,18 @@ function et(o) {
|
|
|
378
378
|
return {
|
|
379
379
|
name: "ollama",
|
|
380
380
|
defaultModel: "llama3.2",
|
|
381
|
-
async chat(
|
|
381
|
+
async chat(n) {
|
|
382
382
|
const e = await s.chat({
|
|
383
|
-
model:
|
|
383
|
+
model: n.model,
|
|
384
384
|
messages: [
|
|
385
|
-
{ role: "system", content:
|
|
386
|
-
...
|
|
385
|
+
{ role: "system", content: n.systemPrompt },
|
|
386
|
+
...n.messages.map((r) => ({
|
|
387
387
|
role: r.role,
|
|
388
388
|
content: r.content
|
|
389
389
|
}))
|
|
390
390
|
],
|
|
391
391
|
options: {
|
|
392
|
-
...
|
|
392
|
+
...n.temperature !== void 0 ? { temperature: n.temperature } : {}
|
|
393
393
|
}
|
|
394
394
|
});
|
|
395
395
|
return {
|
|
@@ -400,27 +400,27 @@ function et(o) {
|
|
|
400
400
|
} : void 0
|
|
401
401
|
};
|
|
402
402
|
},
|
|
403
|
-
async *chatStream(
|
|
403
|
+
async *chatStream(n) {
|
|
404
404
|
const e = await s.chat({
|
|
405
|
-
model:
|
|
405
|
+
model: n.model,
|
|
406
406
|
messages: [
|
|
407
|
-
{ role: "system", content:
|
|
408
|
-
...
|
|
407
|
+
{ role: "system", content: n.systemPrompt },
|
|
408
|
+
...n.messages.map((a) => ({
|
|
409
409
|
role: a.role,
|
|
410
410
|
content: a.content
|
|
411
411
|
}))
|
|
412
412
|
],
|
|
413
413
|
options: {
|
|
414
|
-
...
|
|
414
|
+
...n.temperature !== void 0 ? { temperature: n.temperature } : {}
|
|
415
415
|
},
|
|
416
416
|
stream: !0
|
|
417
417
|
});
|
|
418
|
-
let r,
|
|
418
|
+
let r, t;
|
|
419
419
|
for await (const a of e)
|
|
420
|
-
a.message.content && (yield { delta: a.message.content }), a.done && (r = a.prompt_eval_count,
|
|
420
|
+
a.message.content && (yield { delta: a.message.content }), a.done && (r = a.prompt_eval_count, t = a.eval_count);
|
|
421
421
|
yield {
|
|
422
422
|
delta: "",
|
|
423
|
-
tokenUsage: r !== void 0 ? { input: r ?? 0, output:
|
|
423
|
+
tokenUsage: r !== void 0 ? { input: r ?? 0, output: t ?? 0 } : void 0
|
|
424
424
|
};
|
|
425
425
|
},
|
|
426
426
|
async listModels() {
|
|
@@ -432,46 +432,46 @@ function et(o) {
|
|
|
432
432
|
}
|
|
433
433
|
};
|
|
434
434
|
}
|
|
435
|
-
const
|
|
435
|
+
const ce = {
|
|
436
436
|
anthropic: Qe,
|
|
437
437
|
openai: Ze,
|
|
438
438
|
google: qe,
|
|
439
439
|
ollama: et
|
|
440
440
|
};
|
|
441
|
-
let
|
|
441
|
+
let L = null;
|
|
442
442
|
async function tt() {
|
|
443
|
-
if (
|
|
444
|
-
const o = u(
|
|
443
|
+
if (L) return L;
|
|
444
|
+
const o = u(k(), ".ai-council", "config.json");
|
|
445
445
|
try {
|
|
446
446
|
const s = await w(o, "utf-8");
|
|
447
|
-
|
|
447
|
+
L = JSON.parse(s);
|
|
448
448
|
} catch {
|
|
449
|
-
|
|
449
|
+
L = { backends: {} };
|
|
450
450
|
}
|
|
451
|
-
return
|
|
451
|
+
return L;
|
|
452
452
|
}
|
|
453
|
-
const
|
|
454
|
-
function
|
|
455
|
-
|
|
453
|
+
const X = /* @__PURE__ */ new Map();
|
|
454
|
+
function be() {
|
|
455
|
+
L = null, X.clear();
|
|
456
456
|
}
|
|
457
|
-
async function
|
|
458
|
-
const s =
|
|
457
|
+
async function D(o) {
|
|
458
|
+
const s = X.get(o);
|
|
459
459
|
if (s) return s;
|
|
460
|
-
const
|
|
461
|
-
if (!
|
|
462
|
-
throw new Error(`Unknown backend: "${o}". Available: ${Object.keys(
|
|
463
|
-
const r = (await tt()).backends[o] ?? {},
|
|
464
|
-
return
|
|
460
|
+
const n = ce[o];
|
|
461
|
+
if (!n)
|
|
462
|
+
throw new Error(`Unknown backend: "${o}". Available: ${Object.keys(ce).join(", ")}`);
|
|
463
|
+
const r = (await tt()).backends[o] ?? {}, t = n(r);
|
|
464
|
+
return X.set(o, t), t;
|
|
465
465
|
}
|
|
466
466
|
const nt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
467
467
|
__proto__: null,
|
|
468
|
-
clearCaches:
|
|
469
|
-
getBackend:
|
|
468
|
+
clearCaches: be,
|
|
469
|
+
getBackend: D
|
|
470
470
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
471
471
|
function ot() {
|
|
472
472
|
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();
|
|
473
473
|
}
|
|
474
|
-
const
|
|
474
|
+
const H = "---EXCALIDRAW---", rt = `You are the Secretary of a council discussion. Your job is to synthesize a clear, structured summary of the conversation that just took place.
|
|
475
475
|
|
|
476
476
|
Structure your summary with these sections:
|
|
477
477
|
|
|
@@ -491,100 +491,100 @@ Be concise but thorough. Use markdown formatting.`;
|
|
|
491
491
|
function st(o) {
|
|
492
492
|
const s = [];
|
|
493
493
|
s.push(`Topic: ${o.topic}`), s.push(`Councilors: ${o.councilors.map((e) => e.name).join(", ")}`), s.push(`Rounds: ${o.rounds}`), s.push("");
|
|
494
|
-
let
|
|
494
|
+
let n = 0;
|
|
495
495
|
for (const e of o.turns)
|
|
496
|
-
e.round !==
|
|
496
|
+
e.round !== n && (n = e.round, s.push(`--- Round ${n} ---`), s.push("")), s.push(`[${e.councilorName}]:`), s.push(e.content), s.push("");
|
|
497
497
|
return s.join(`
|
|
498
498
|
`);
|
|
499
499
|
}
|
|
500
500
|
async function at({
|
|
501
501
|
result: o,
|
|
502
502
|
config: s,
|
|
503
|
-
onChunk:
|
|
503
|
+
onChunk: n,
|
|
504
504
|
signal: e
|
|
505
505
|
}) {
|
|
506
506
|
const r = s.secretary;
|
|
507
507
|
if (!r?.backend)
|
|
508
508
|
throw new Error("No secretary backend configured");
|
|
509
|
-
const
|
|
509
|
+
const t = await D(r.backend), a = r.model ?? t.defaultModel, i = r.systemPrompt || rt, c = ot(), l = `${i}
|
|
510
510
|
|
|
511
|
-
${
|
|
511
|
+
${c}
|
|
512
512
|
|
|
513
|
-
After your text summary, output \`${
|
|
513
|
+
After your text summary, output \`${H}\` 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 = st(o), h = {
|
|
514
514
|
model: a,
|
|
515
|
-
systemPrompt:
|
|
515
|
+
systemPrompt: l,
|
|
516
516
|
messages: [{ role: "user", content: `Please summarize this council discussion and create a position diagram:
|
|
517
517
|
|
|
518
|
-
${
|
|
518
|
+
${m}` }],
|
|
519
519
|
temperature: 0.5
|
|
520
520
|
};
|
|
521
|
-
let
|
|
522
|
-
if (
|
|
523
|
-
for await (const
|
|
521
|
+
let y = "";
|
|
522
|
+
if (t.chatStream)
|
|
523
|
+
for await (const p of t.chatStream(h)) {
|
|
524
524
|
if (e?.aborted) break;
|
|
525
|
-
|
|
525
|
+
y += p.delta, p.delta && n && n(p.delta);
|
|
526
526
|
}
|
|
527
527
|
else
|
|
528
|
-
|
|
529
|
-
const g =
|
|
528
|
+
y = (await t.chat(h)).content, n && n(y);
|
|
529
|
+
const g = y.indexOf(H);
|
|
530
530
|
if (g === -1)
|
|
531
|
-
return { text:
|
|
532
|
-
const
|
|
533
|
-
let
|
|
531
|
+
return { text: y.trim() };
|
|
532
|
+
const j = y.slice(0, g).trim(), f = y.slice(g + H.length).trim();
|
|
533
|
+
let _;
|
|
534
534
|
try {
|
|
535
|
-
const
|
|
536
|
-
|
|
535
|
+
const p = f.match(/\[[\s\S]*\]/);
|
|
536
|
+
p && (_ = JSON.parse(p[0]));
|
|
537
537
|
} catch {
|
|
538
538
|
}
|
|
539
|
-
return { text:
|
|
539
|
+
return { text: j, diagram: _ };
|
|
540
540
|
}
|
|
541
541
|
const it = "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.";
|
|
542
542
|
async function ct({
|
|
543
543
|
result: o,
|
|
544
544
|
roundNumber: s,
|
|
545
|
-
config:
|
|
545
|
+
config: n,
|
|
546
546
|
onChunk: e,
|
|
547
547
|
signal: r
|
|
548
548
|
}) {
|
|
549
|
-
const
|
|
550
|
-
if (!
|
|
549
|
+
const t = n.secretary;
|
|
550
|
+
if (!t?.backend)
|
|
551
551
|
throw new Error("No secretary backend configured");
|
|
552
|
-
const a = await
|
|
553
|
-
|
|
554
|
-
for (const
|
|
555
|
-
|
|
556
|
-
const
|
|
552
|
+
const a = await D(t.backend), i = t.model ?? a.defaultModel, c = o.turns.filter((y) => y.round === s), l = [];
|
|
553
|
+
l.push(`Topic: ${o.topic}`), l.push(`Round ${s}${s === 1 ? " (Constructive)" : " (Rebuttal)"}`), l.push("");
|
|
554
|
+
for (const y of c)
|
|
555
|
+
l.push(`[${y.councilorName}]:`), l.push(y.content), l.push("");
|
|
556
|
+
const m = {
|
|
557
557
|
model: i,
|
|
558
558
|
systemPrompt: it,
|
|
559
559
|
messages: [{ role: "user", content: `Please summarize this round:
|
|
560
560
|
|
|
561
|
-
${
|
|
561
|
+
${l.join(`
|
|
562
562
|
`)}` }],
|
|
563
563
|
temperature: 0.5
|
|
564
564
|
};
|
|
565
|
-
let
|
|
565
|
+
let h = "";
|
|
566
566
|
if (a.chatStream)
|
|
567
|
-
for await (const
|
|
567
|
+
for await (const y of a.chatStream(m)) {
|
|
568
568
|
if (r?.aborted) break;
|
|
569
|
-
|
|
569
|
+
h += y.delta, y.delta && e && e(y.delta);
|
|
570
570
|
}
|
|
571
571
|
else
|
|
572
|
-
|
|
573
|
-
return
|
|
572
|
+
h = (await a.chat(m)).content, e && e(h);
|
|
573
|
+
return h.trim();
|
|
574
574
|
}
|
|
575
575
|
async function lt({
|
|
576
576
|
topic: o,
|
|
577
577
|
firstRoundTurns: s,
|
|
578
|
-
config:
|
|
578
|
+
config: n
|
|
579
579
|
}) {
|
|
580
|
-
const e =
|
|
580
|
+
const e = n.secretary;
|
|
581
581
|
if (!e?.backend)
|
|
582
582
|
throw new Error("No secretary backend configured");
|
|
583
|
-
const r = await
|
|
583
|
+
const r = await D(e.backend), t = e.model ?? r.defaultModel, a = s.map((c) => `[${c.councilorName}]: ${c.content.slice(0, 300)}`).join(`
|
|
584
584
|
|
|
585
585
|
`);
|
|
586
586
|
return (await r.chat({
|
|
587
|
-
model:
|
|
587
|
+
model: t,
|
|
588
588
|
systemPrompt: "Generate a concise title (max 8 words) for this council discussion. Return only the title, no quotes or punctuation at the end.",
|
|
589
589
|
messages: [
|
|
590
590
|
{
|
|
@@ -598,92 +598,92 @@ ${a}`
|
|
|
598
598
|
temperature: 0.3
|
|
599
599
|
})).content.trim().replace(/^["']+|["']+$/g, "").replace(/[.!?]+$/, "").trim();
|
|
600
600
|
}
|
|
601
|
-
const
|
|
602
|
-
let
|
|
601
|
+
const ve = u(k(), ".ai-council"), ut = u(ve, "council.log");
|
|
602
|
+
let le = !1;
|
|
603
603
|
async function dt() {
|
|
604
|
-
|
|
604
|
+
le || (await x(ve, { recursive: !0 }), le = !0);
|
|
605
605
|
}
|
|
606
|
-
function mt(o, s,
|
|
607
|
-
let
|
|
606
|
+
function mt(o, s, n, e) {
|
|
607
|
+
let t = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${o} [${s}] ${n}`;
|
|
608
608
|
if (e !== void 0) {
|
|
609
609
|
const a = e instanceof Error ? `${e.message}
|
|
610
610
|
${e.stack ?? ""}` : typeof e == "string" ? e : JSON.stringify(e, null, 2);
|
|
611
|
-
|
|
611
|
+
t += `
|
|
612
612
|
${a.replace(/\n/g, `
|
|
613
613
|
`)}`;
|
|
614
614
|
}
|
|
615
|
-
return
|
|
615
|
+
return t + `
|
|
616
616
|
`;
|
|
617
617
|
}
|
|
618
|
-
async function
|
|
618
|
+
async function J(o, s, n, e) {
|
|
619
619
|
try {
|
|
620
|
-
await dt(), await
|
|
620
|
+
await dt(), await Re(ut, mt(o, s, n, e));
|
|
621
621
|
} catch {
|
|
622
622
|
}
|
|
623
623
|
}
|
|
624
624
|
const v = {
|
|
625
|
-
info: (o, s,
|
|
626
|
-
warn: (o, s,
|
|
627
|
-
error: (o, s,
|
|
625
|
+
info: (o, s, n) => J("INFO", o, s, n),
|
|
626
|
+
warn: (o, s, n) => J("WARN", o, s, n),
|
|
627
|
+
error: (o, s, n) => J("ERROR", o, s, n)
|
|
628
628
|
};
|
|
629
|
-
function pt(o, s,
|
|
630
|
-
const
|
|
629
|
+
function pt(o, s, n, e, r) {
|
|
630
|
+
const t = [{ role: "user", content: o }];
|
|
631
631
|
if (e?.length) {
|
|
632
632
|
for (const a of e)
|
|
633
|
-
a.councilorId ===
|
|
633
|
+
a.councilorId === n ? t.push({ role: "assistant", content: a.content }) : t.push({
|
|
634
634
|
role: "user",
|
|
635
635
|
content: `[${a.councilorName}, Round ${a.round}]: ${a.content}`
|
|
636
636
|
});
|
|
637
|
-
r &&
|
|
637
|
+
r && t.push({
|
|
638
638
|
role: "user",
|
|
639
639
|
content: `[Secretary Summary]: ${r}`
|
|
640
640
|
});
|
|
641
641
|
}
|
|
642
642
|
for (const a of s)
|
|
643
|
-
a.councilorId ===
|
|
643
|
+
a.councilorId === n ? t.push({ role: "assistant", content: a.content }) : t.push({
|
|
644
644
|
role: "user",
|
|
645
645
|
content: `[${a.councilorName}, Round ${a.round}]: ${a.content}`
|
|
646
646
|
});
|
|
647
|
-
return
|
|
647
|
+
return t;
|
|
648
648
|
}
|
|
649
|
-
function ft(o, s,
|
|
649
|
+
function ft(o, s, n, e) {
|
|
650
650
|
const r = [{ role: "user", content: o }];
|
|
651
651
|
if (e === 1)
|
|
652
652
|
return r;
|
|
653
|
-
const
|
|
654
|
-
for (const i of
|
|
655
|
-
i.councilorId ===
|
|
653
|
+
const t = s.filter((i) => i.round === 1);
|
|
654
|
+
for (const i of t)
|
|
655
|
+
i.councilorId === n ? r.push({ role: "assistant", content: i.content }) : r.push({
|
|
656
656
|
role: "user",
|
|
657
657
|
content: `[${i.councilorName}, Constructive]: ${i.content}`
|
|
658
658
|
});
|
|
659
659
|
const a = e - 1;
|
|
660
660
|
if (a > 1) {
|
|
661
|
-
const i = s.filter((
|
|
662
|
-
for (const
|
|
663
|
-
|
|
661
|
+
const i = s.filter((c) => c.round === a);
|
|
662
|
+
for (const c of i)
|
|
663
|
+
c.councilorId === n ? r.push({ role: "assistant", content: c.content }) : r.push({
|
|
664
664
|
role: "user",
|
|
665
|
-
content: `[${
|
|
665
|
+
content: `[${c.councilorName}, Round ${a}]: ${c.content}`
|
|
666
666
|
});
|
|
667
667
|
}
|
|
668
668
|
for (const i of s)
|
|
669
|
-
i.councilorId ===
|
|
669
|
+
i.councilorId === n && i.round !== 1 && i.round !== a && i.round < e && r.push({ role: "assistant", content: i.content });
|
|
670
670
|
return r;
|
|
671
671
|
}
|
|
672
672
|
function gt(o, s) {
|
|
673
|
-
const
|
|
673
|
+
const n = [...o];
|
|
674
674
|
let e = s | 0;
|
|
675
675
|
const r = () => {
|
|
676
676
|
e = e + 1831565813 | 0;
|
|
677
|
-
let
|
|
678
|
-
return
|
|
677
|
+
let t = Math.imul(e ^ e >>> 15, 1 | e);
|
|
678
|
+
return t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t, ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
679
679
|
};
|
|
680
|
-
for (let
|
|
681
|
-
const a = Math.floor(r() * (
|
|
682
|
-
[t
|
|
680
|
+
for (let t = n.length - 1; t > 0; t--) {
|
|
681
|
+
const a = Math.floor(r() * (t + 1));
|
|
682
|
+
[n[t], n[a]] = [n[a], n[t]];
|
|
683
683
|
}
|
|
684
|
-
return
|
|
684
|
+
return n;
|
|
685
685
|
}
|
|
686
|
-
function
|
|
686
|
+
function z(o, s, n, e, r, t) {
|
|
687
687
|
return {
|
|
688
688
|
topic: o.topic,
|
|
689
689
|
topicSource: o.topicSource,
|
|
@@ -697,160 +697,202 @@ function H(o, s, t, e, r, n) {
|
|
|
697
697
|
})),
|
|
698
698
|
rounds: o.rounds,
|
|
699
699
|
turns: s,
|
|
700
|
-
startedAt:
|
|
700
|
+
startedAt: n,
|
|
701
701
|
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
702
702
|
totalTokenUsage: { input: e, output: r },
|
|
703
|
-
...
|
|
703
|
+
...t && Object.keys(t).length > 0 ? { roundSummaries: t } : {},
|
|
704
704
|
...o.mode === "debate" ? { mode: "debate" } : {}
|
|
705
705
|
};
|
|
706
706
|
}
|
|
707
|
-
async function ht(o, s,
|
|
708
|
-
let
|
|
709
|
-
typeof o == "string" ?
|
|
707
|
+
async function ht(o, s, n, e, r) {
|
|
708
|
+
let t;
|
|
709
|
+
typeof o == "string" ? t = {
|
|
710
710
|
topic: o,
|
|
711
711
|
topicSource: s,
|
|
712
|
-
councilors:
|
|
712
|
+
councilors: n,
|
|
713
713
|
rounds: e,
|
|
714
714
|
onEvent: r
|
|
715
|
-
} :
|
|
715
|
+
} : t = o;
|
|
716
716
|
const a = (/* @__PURE__ */ new Date()).toISOString(), i = [];
|
|
717
|
-
let
|
|
718
|
-
const
|
|
719
|
-
v.info("conversation", `Starting ${
|
|
720
|
-
councilors:
|
|
721
|
-
topic:
|
|
717
|
+
let c = 0, l = 0;
|
|
718
|
+
const m = t.mode === "debate", h = {}, y = t.previousTurns?.length ? Math.max(...t.previousTurns.map((g) => g.round)) : 0;
|
|
719
|
+
v.info("conversation", `Starting ${m ? "debate" : "freeform"} — ${t.councilors.length} councilors, ${t.rounds} rounds`, {
|
|
720
|
+
councilors: t.councilors.map((g) => `${g.frontmatter.name} (${g.frontmatter.backend}/${g.frontmatter.model ?? "default"})`),
|
|
721
|
+
topic: t.topic.slice(0, 200)
|
|
722
722
|
});
|
|
723
|
-
for (let g = 1; g <=
|
|
724
|
-
const
|
|
725
|
-
for (const
|
|
726
|
-
if (
|
|
727
|
-
return
|
|
728
|
-
if (
|
|
729
|
-
const
|
|
730
|
-
|
|
723
|
+
for (let g = 1; g <= t.rounds; g++) {
|
|
724
|
+
const j = m && g > 1 ? gt(t.councilors, g) : t.councilors;
|
|
725
|
+
for (const f of j) {
|
|
726
|
+
if (t.signal?.aborted)
|
|
727
|
+
return z(t, i, a, c, l, h);
|
|
728
|
+
if (t.beforeTurn) {
|
|
729
|
+
const p = await t.beforeTurn();
|
|
730
|
+
p && (i.push(p), t.onEvent({ type: "turn_complete", turn: p }));
|
|
731
731
|
}
|
|
732
|
-
const
|
|
733
|
-
|
|
732
|
+
const _ = g + y;
|
|
733
|
+
t.onEvent({ type: "turn_start", round: _, councilorName: f.frontmatter.name });
|
|
734
734
|
try {
|
|
735
|
-
const
|
|
736
|
-
model:
|
|
737
|
-
systemPrompt:
|
|
738
|
-
messages:
|
|
739
|
-
temperature:
|
|
735
|
+
const p = await D(f.frontmatter.backend), d = f.frontmatter.model ?? p.defaultModel, b = m ? ft(t.topic, i, f.id, g) : pt(t.topic, i, f.id, t.previousTurns, t.previousSummary), B = {
|
|
736
|
+
model: d,
|
|
737
|
+
systemPrompt: f.systemPrompt,
|
|
738
|
+
messages: b,
|
|
739
|
+
temperature: f.frontmatter.temperature
|
|
740
740
|
};
|
|
741
|
-
let
|
|
742
|
-
if (
|
|
743
|
-
|
|
744
|
-
for await (const
|
|
745
|
-
if (
|
|
746
|
-
|
|
741
|
+
let M, T;
|
|
742
|
+
if (p.chatStream) {
|
|
743
|
+
M = "";
|
|
744
|
+
for await (const O of p.chatStream(B)) {
|
|
745
|
+
if (t.signal?.aborted) break;
|
|
746
|
+
M += O.delta, O.delta && t.onEvent({ type: "turn_chunk", councilorName: f.frontmatter.name, delta: O.delta }), O.tokenUsage && (T = O.tokenUsage);
|
|
747
747
|
}
|
|
748
748
|
} else {
|
|
749
|
-
const
|
|
750
|
-
|
|
749
|
+
const O = await p.chat(B);
|
|
750
|
+
M = O.content, T = O.tokenUsage;
|
|
751
751
|
}
|
|
752
|
-
const
|
|
753
|
-
round:
|
|
754
|
-
councilorId:
|
|
755
|
-
councilorName:
|
|
756
|
-
content:
|
|
752
|
+
const te = {
|
|
753
|
+
round: _,
|
|
754
|
+
councilorId: f.id,
|
|
755
|
+
councilorName: f.frontmatter.name,
|
|
756
|
+
content: M,
|
|
757
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
758
|
+
model: d,
|
|
759
|
+
backend: f.frontmatter.backend,
|
|
760
|
+
tokenUsage: T,
|
|
761
|
+
avatarUrl: f.avatarUrl
|
|
762
|
+
};
|
|
763
|
+
T && (c += T.input, l += T.output), i.push(te), t.onEvent({ type: "turn_complete", turn: te });
|
|
764
|
+
} catch (p) {
|
|
765
|
+
const d = p instanceof Error ? p.message : String(p);
|
|
766
|
+
v.error("conversation", `Turn failed for ${f.frontmatter.name} (round ${g}, model ${f.frontmatter.model ?? "default"}, backend ${f.frontmatter.backend})`, p), t.onEvent({ type: "error", councilorName: f.frontmatter.name, error: d });
|
|
767
|
+
const b = {
|
|
768
|
+
round: _,
|
|
769
|
+
councilorId: f.id,
|
|
770
|
+
councilorName: f.frontmatter.name,
|
|
771
|
+
content: "",
|
|
757
772
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
758
|
-
model:
|
|
759
|
-
backend:
|
|
760
|
-
|
|
761
|
-
|
|
773
|
+
model: f.frontmatter.model ?? "default",
|
|
774
|
+
backend: f.frontmatter.backend,
|
|
775
|
+
avatarUrl: f.avatarUrl,
|
|
776
|
+
error: d
|
|
762
777
|
};
|
|
763
|
-
|
|
764
|
-
} catch (m) {
|
|
765
|
-
const x = m instanceof Error ? m.message : String(m);
|
|
766
|
-
v.error("conversation", `Turn failed for ${d.frontmatter.name} (round ${g}, model ${d.frontmatter.model ?? "default"}, backend ${d.frontmatter.backend})`, m), n.onEvent({ type: "error", councilorName: d.frontmatter.name, error: x });
|
|
778
|
+
i.push(b), t.onEvent({ type: "turn_complete", turn: b });
|
|
767
779
|
}
|
|
768
780
|
}
|
|
769
|
-
if (
|
|
781
|
+
if (t.onEvent({ type: "round_complete", round: g }), m && t.config?.secretary?.backend && !t.signal?.aborted)
|
|
770
782
|
try {
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
const
|
|
774
|
-
result:
|
|
783
|
+
const f = z(t, i, a, c, l, h);
|
|
784
|
+
t.onEvent({ type: "round_summary_start", round: g });
|
|
785
|
+
const _ = await ct({
|
|
786
|
+
result: f,
|
|
775
787
|
roundNumber: g,
|
|
776
|
-
config:
|
|
777
|
-
onChunk: (
|
|
778
|
-
|
|
788
|
+
config: t.config,
|
|
789
|
+
onChunk: (p) => {
|
|
790
|
+
t.onEvent({ type: "round_summary_chunk", round: g, delta: p });
|
|
779
791
|
},
|
|
780
|
-
signal:
|
|
792
|
+
signal: t.signal
|
|
781
793
|
});
|
|
782
|
-
|
|
783
|
-
} catch (
|
|
784
|
-
v.error("conversation", `Interim summary failed for round ${g}`,
|
|
794
|
+
h[g] = _, t.onEvent({ type: "round_summary_complete", round: g, summary: _ });
|
|
795
|
+
} catch (f) {
|
|
796
|
+
v.error("conversation", `Interim summary failed for round ${g}`, f);
|
|
785
797
|
}
|
|
786
798
|
}
|
|
787
|
-
return
|
|
799
|
+
return z(t, i, a, c, l, h);
|
|
800
|
+
}
|
|
801
|
+
async function yt(o, s) {
|
|
802
|
+
const n = /* @__PURE__ */ new Map();
|
|
803
|
+
for (const t of o) {
|
|
804
|
+
const a = t.frontmatter.backend;
|
|
805
|
+
n.has(a) || n.set(a, []), n.get(a).push(t);
|
|
806
|
+
}
|
|
807
|
+
const e = /* @__PURE__ */ new Map();
|
|
808
|
+
for (const [t, a] of n) {
|
|
809
|
+
s?.(`Checking ${t} backend (${a.length} councilor${a.length > 1 ? "s" : ""})...`);
|
|
810
|
+
let i = null, c = [], l = null;
|
|
811
|
+
try {
|
|
812
|
+
i = await D(t), i.listModels && (c = (await i.listModels()).map((h) => h.id));
|
|
813
|
+
} catch (m) {
|
|
814
|
+
l = m instanceof Error ? m.message : String(m), v.error("preflight", `Backend "${t}" probe failed`, m);
|
|
815
|
+
}
|
|
816
|
+
e.set(t, { provider: i, models: c, error: l });
|
|
817
|
+
}
|
|
818
|
+
const r = [];
|
|
819
|
+
for (const t of o) {
|
|
820
|
+
const a = e.get(t.frontmatter.backend), i = [], c = t.frontmatter.model ?? a.provider?.defaultModel ?? "(unknown)";
|
|
821
|
+
a.error ? i.push(`Backend "${t.frontmatter.backend}" unavailable: ${a.error}`) : a.models.length > 0 && !a.models.includes(c) && i.push(
|
|
822
|
+
`Model "${c}" not found on ${t.frontmatter.backend}`
|
|
823
|
+
), r.push({ councilor: t, ok: i.length === 0, model: c, issues: i });
|
|
824
|
+
}
|
|
825
|
+
return {
|
|
826
|
+
results: r,
|
|
827
|
+
valid: r.filter((t) => t.ok).map((t) => t.councilor),
|
|
828
|
+
invalid: r.filter((t) => !t.ok)
|
|
829
|
+
};
|
|
788
830
|
}
|
|
789
|
-
const
|
|
790
|
-
function
|
|
831
|
+
const I = u(k(), ".ai-council", "history");
|
|
832
|
+
function wt(o) {
|
|
791
833
|
return o.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
792
834
|
}
|
|
793
|
-
async function
|
|
794
|
-
await
|
|
795
|
-
const s = new Date(o.startedAt).toISOString().replace(/[:.]/g, "-").slice(0, 19),
|
|
796
|
-
return await
|
|
835
|
+
async function bt(o) {
|
|
836
|
+
await x(I, { recursive: !0 });
|
|
837
|
+
const s = new Date(o.startedAt).toISOString().replace(/[:.]/g, "-").slice(0, 19), n = wt(o.topic), e = `${s}-${n}`, r = u(I, `${e}.json`);
|
|
838
|
+
return await C(r, JSON.stringify(o, null, 2), "utf-8"), e;
|
|
797
839
|
}
|
|
798
|
-
async function
|
|
799
|
-
await
|
|
800
|
-
const o = await
|
|
801
|
-
for (const
|
|
802
|
-
if (
|
|
840
|
+
async function vt() {
|
|
841
|
+
await x(I, { recursive: !0 });
|
|
842
|
+
const o = await Q(I), s = [];
|
|
843
|
+
for (const n of o)
|
|
844
|
+
if (n.endsWith(".json"))
|
|
803
845
|
try {
|
|
804
|
-
const e = await w(u(
|
|
846
|
+
const e = await w(u(I, n), "utf-8"), r = JSON.parse(e);
|
|
805
847
|
s.push({
|
|
806
|
-
id:
|
|
848
|
+
id: N(n, ".json"),
|
|
807
849
|
topic: r.topic,
|
|
808
850
|
title: r.title,
|
|
809
|
-
councilors: r.councilors.map((
|
|
851
|
+
councilors: r.councilors.map((t) => t.name),
|
|
810
852
|
rounds: r.rounds,
|
|
811
853
|
startedAt: r.startedAt,
|
|
812
854
|
completedAt: r.completedAt
|
|
813
855
|
});
|
|
814
856
|
} catch {
|
|
815
857
|
}
|
|
816
|
-
return s.sort((
|
|
858
|
+
return s.sort((n, e) => e.startedAt.localeCompare(n.startedAt));
|
|
817
859
|
}
|
|
818
|
-
async function
|
|
819
|
-
const s = u(
|
|
860
|
+
async function ue(o) {
|
|
861
|
+
const s = u(I, `${o}.json`), n = await w(s, "utf-8"), e = JSON.parse(n);
|
|
820
862
|
return e.infographic && !e.infographics && (e.infographics = [e.infographic], delete e.infographic), e;
|
|
821
863
|
}
|
|
822
|
-
async function
|
|
823
|
-
const s = u(
|
|
824
|
-
await
|
|
825
|
-
}
|
|
826
|
-
async function kt(o, s) {
|
|
827
|
-
const t = u(A, `${o}.json`), e = await w(t, "utf-8"), r = JSON.parse(e);
|
|
828
|
-
r.infographics || (r.infographics = []), r.infographics.push(s), await O(t, JSON.stringify(r, null, 2), "utf-8");
|
|
864
|
+
async function kt(o) {
|
|
865
|
+
const s = u(I, `${o}.json`);
|
|
866
|
+
await Y(s);
|
|
829
867
|
}
|
|
830
868
|
async function _t(o, s) {
|
|
831
|
-
const
|
|
832
|
-
r.infographics
|
|
869
|
+
const n = u(I, `${o}.json`), e = await w(n, "utf-8"), r = JSON.parse(e);
|
|
870
|
+
r.infographics || (r.infographics = []), r.infographics.push(s), await C(n, JSON.stringify(r, null, 2), "utf-8");
|
|
833
871
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
872
|
+
async function St(o, s) {
|
|
873
|
+
const n = u(I, `${o}.json`), e = await w(n, "utf-8"), r = JSON.parse(e);
|
|
874
|
+
r.infographics && s >= 0 && s < r.infographics.length && r.infographics.splice(s, 1), await C(n, JSON.stringify(r, null, 2), "utf-8");
|
|
875
|
+
}
|
|
876
|
+
const ke = Ke(import.meta.url);
|
|
877
|
+
function Et(o) {
|
|
878
|
+
const s = o.councilors.map((e) => e.name).join(", "), n = o.summary ?? o.turns.map((e) => `${e.councilorName}: ${e.content.slice(0, 200)}`).join(`
|
|
837
879
|
`);
|
|
838
880
|
return [
|
|
839
881
|
"Create a professional infographic summarizing a panel discussion.",
|
|
840
882
|
`Topic: ${o.topic.slice(0, 300)}`,
|
|
841
|
-
`Key points: ${
|
|
883
|
+
`Key points: ${n.slice(0, 1500)}`,
|
|
842
884
|
`Panelists: ${s}`,
|
|
843
885
|
"Use a clean, modern design with sections for convergence points, divergence points, and key takeaways.",
|
|
844
886
|
"Include relevant icons and visual hierarchy. Use a horizontal landscape layout."
|
|
845
887
|
].join(" ");
|
|
846
888
|
}
|
|
847
|
-
function
|
|
889
|
+
function $t(o) {
|
|
848
890
|
if (o.infographic?.backend) return o.infographic.backend;
|
|
849
|
-
const s = !!(o.backends.google?.apiKey || process.env.GOOGLE_API_KEY),
|
|
850
|
-
return s ? "google" :
|
|
891
|
+
const s = !!(o.backends.google?.apiKey || process.env.GOOGLE_API_KEY), n = !!(o.backends.openai?.apiKey || process.env.OPENAI_API_KEY);
|
|
892
|
+
return s ? "google" : n ? "openai" : null;
|
|
851
893
|
}
|
|
852
894
|
async function At(o, s) {
|
|
853
|
-
const
|
|
895
|
+
const n = ke("openai").default, t = (await new n({
|
|
854
896
|
apiKey: s.backends.openai?.apiKey || process.env.OPENAI_API_KEY,
|
|
855
897
|
...s.backends.openai?.baseUrl ? { baseURL: s.backends.openai.baseUrl } : {}
|
|
856
898
|
}).images.generate({
|
|
@@ -859,13 +901,13 @@ async function At(o, s) {
|
|
|
859
901
|
quality: "high",
|
|
860
902
|
size: "1536x1024"
|
|
861
903
|
})).data?.[0]?.b64_json;
|
|
862
|
-
if (!
|
|
863
|
-
return
|
|
904
|
+
if (!t) throw new Error("No image data returned from OpenAI");
|
|
905
|
+
return t;
|
|
864
906
|
}
|
|
865
907
|
async function It(o, s) {
|
|
866
|
-
const { GoogleGenAI:
|
|
908
|
+
const { GoogleGenAI: n } = ke("@google/genai"), e = s.backends.google?.apiKey || process.env.GOOGLE_API_KEY;
|
|
867
909
|
if (!e) throw new Error("No Google API key configured");
|
|
868
|
-
const a = (await new
|
|
910
|
+
const a = (await new n({ apiKey: e }).models.generateContent({
|
|
869
911
|
model: "gemini-3.1-flash-image-preview",
|
|
870
912
|
contents: o,
|
|
871
913
|
config: {
|
|
@@ -878,23 +920,23 @@ async function It(o, s) {
|
|
|
878
920
|
return i.inlineData.data;
|
|
879
921
|
throw new Error("No image data in Gemini response");
|
|
880
922
|
}
|
|
881
|
-
async function
|
|
882
|
-
const e =
|
|
923
|
+
async function de(o, s, n) {
|
|
924
|
+
const e = n ?? $t(s);
|
|
883
925
|
if (!e) throw new Error("No image-capable backend configured (need OpenAI or Google API key)");
|
|
884
|
-
const r =
|
|
926
|
+
const r = Et(o);
|
|
885
927
|
return e === "openai" ? At(r, s) : It(r, s);
|
|
886
928
|
}
|
|
887
|
-
const
|
|
888
|
-
function
|
|
889
|
-
const s = o.match(
|
|
929
|
+
const Ot = /https?:\/\/[^\s)<>]+/g;
|
|
930
|
+
function Pt(o) {
|
|
931
|
+
const s = o.match(Ot);
|
|
890
932
|
return s ? [...new Set(s)] : [];
|
|
891
933
|
}
|
|
892
|
-
async function
|
|
893
|
-
const
|
|
894
|
-
s && s.addEventListener("abort", () =>
|
|
934
|
+
async function Ct(o, s) {
|
|
935
|
+
const n = new AbortController(), e = setTimeout(() => n.abort(), 15e3);
|
|
936
|
+
s && s.addEventListener("abort", () => n.abort(), { once: !0 });
|
|
895
937
|
try {
|
|
896
938
|
const r = await fetch(o, {
|
|
897
|
-
signal:
|
|
939
|
+
signal: n.signal,
|
|
898
940
|
headers: {
|
|
899
941
|
"User-Agent": "Council/1.0 (AI Discussion Tool)",
|
|
900
942
|
Accept: "text/html, application/json, text/plain, */*"
|
|
@@ -903,66 +945,66 @@ async function Pt(o, s) {
|
|
|
903
945
|
});
|
|
904
946
|
if (clearTimeout(e), !r.ok)
|
|
905
947
|
return { url: o, content: `[Failed to fetch: HTTP ${r.status}]` };
|
|
906
|
-
const
|
|
907
|
-
if (
|
|
948
|
+
const t = r.headers.get("content-type") || "", a = await r.text();
|
|
949
|
+
if (t.includes("application/json"))
|
|
908
950
|
try {
|
|
909
|
-
const
|
|
910
|
-
return { url: o, content:
|
|
951
|
+
const l = JSON.stringify(JSON.parse(a), null, 2);
|
|
952
|
+
return { url: o, content: l.slice(0, 8e3) };
|
|
911
953
|
} catch {
|
|
912
954
|
return { url: o, content: a.slice(0, 8e3) };
|
|
913
955
|
}
|
|
914
|
-
if (
|
|
956
|
+
if (t.includes("text/plain") || t.includes("text/markdown"))
|
|
915
957
|
return { url: o, content: a.slice(0, 8e3) };
|
|
916
|
-
const { title: i, text:
|
|
917
|
-
return { url: o, title: i, content:
|
|
958
|
+
const { title: i, text: c } = Nt(a);
|
|
959
|
+
return { url: o, title: i, content: c.slice(0, 8e3) };
|
|
918
960
|
} catch (r) {
|
|
919
961
|
clearTimeout(e);
|
|
920
|
-
const
|
|
921
|
-
return
|
|
962
|
+
const t = r instanceof Error ? r.message : String(r);
|
|
963
|
+
return t.includes("abort") ? { url: o, content: "[Fetch timed out]" } : { url: o, content: `[Failed to fetch: ${t}]` };
|
|
922
964
|
}
|
|
923
965
|
}
|
|
924
|
-
function
|
|
925
|
-
const s = o.match(/<title[^>]*>([\s\S]*?)<\/title>/i),
|
|
966
|
+
function Nt(o) {
|
|
967
|
+
const s = o.match(/<title[^>]*>([\s\S]*?)<\/title>/i), n = s ? me(s[1].trim()) : "";
|
|
926
968
|
let e = o.replace(/<script[\s\S]*?<\/script>/gi, "").replace(/<style[\s\S]*?<\/style>/gi, "").replace(/<nav[\s\S]*?<\/nav>/gi, "").replace(/<header[\s\S]*?<\/header>/gi, "").replace(/<footer[\s\S]*?<\/footer>/gi, "");
|
|
927
969
|
return e = e.replace(/<\/(p|div|h[1-6]|li|tr|blockquote|section|article)>/gi, `
|
|
928
970
|
`), e = e.replace(/<br\s*\/?>/gi, `
|
|
929
|
-
`), e = e.replace(/<li[^>]*>/gi, "• "), e = e.replace(/<[^>]+>/g, " "), e =
|
|
971
|
+
`), e = e.replace(/<li[^>]*>/gi, "• "), e = e.replace(/<[^>]+>/g, " "), e = me(e), e = e.split(`
|
|
930
972
|
`).map((r) => r.replace(/\s+/g, " ").trim()).filter(Boolean).join(`
|
|
931
|
-
`), { title:
|
|
973
|
+
`), { title: n, text: e };
|
|
932
974
|
}
|
|
933
|
-
function
|
|
934
|
-
return o.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, " ").replace(/&#(\d+);/g, (s,
|
|
975
|
+
function me(o) {
|
|
976
|
+
return o.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, " ").replace(/&#(\d+);/g, (s, n) => String.fromCharCode(Number(n))).replace(/&[a-zA-Z]+;/g, " ");
|
|
935
977
|
}
|
|
936
|
-
async function xt(o, s,
|
|
937
|
-
const e =
|
|
978
|
+
async function xt(o, s, n) {
|
|
979
|
+
const e = Pt(o);
|
|
938
980
|
if (e.length === 0) return o;
|
|
939
981
|
v.info("topic-enricher", `Found ${e.length} URL(s) in topic`, { urls: e });
|
|
940
982
|
const r = await Promise.all(
|
|
941
|
-
e.map((a) =>
|
|
983
|
+
e.map((a) => Ct(a, s))
|
|
942
984
|
);
|
|
943
|
-
let
|
|
985
|
+
let t = o;
|
|
944
986
|
for (const a of r) {
|
|
945
987
|
const i = a.title ? `Resource: ${a.title} (${a.url})` : `Resource: ${a.url}`;
|
|
946
|
-
|
|
988
|
+
t += `
|
|
947
989
|
|
|
948
990
|
---
|
|
949
991
|
${i}
|
|
950
992
|
${a.content}`;
|
|
951
993
|
}
|
|
952
|
-
return v.info("topic-enricher", `Enriched topic with ${r.length} resource(s)`),
|
|
994
|
+
return v.info("topic-enricher", `Enriched topic with ${r.length} resource(s)`), t;
|
|
953
995
|
}
|
|
954
|
-
const
|
|
996
|
+
const _e = {
|
|
955
997
|
anthropic: "https://api.anthropic.com",
|
|
956
998
|
openai: "https://api.openai.com/v1",
|
|
957
999
|
google: "https://generativelanguage.googleapis.com",
|
|
958
1000
|
ollama: "http://localhost:11434"
|
|
959
|
-
},
|
|
1001
|
+
}, pe = [
|
|
960
1002
|
"claude-opus-4-20250514",
|
|
961
1003
|
"claude-sonnet-4-5-20250514",
|
|
962
1004
|
"claude-sonnet-4-20250514",
|
|
963
1005
|
"claude-haiku-4-20250414",
|
|
964
1006
|
"claude-3-5-haiku-20241022"
|
|
965
|
-
],
|
|
1007
|
+
], G = [
|
|
966
1008
|
"gemini-2.5-pro",
|
|
967
1009
|
"gemini-2.5-flash",
|
|
968
1010
|
"gemini-2.0-flash",
|
|
@@ -970,96 +1012,96 @@ const ke = {
|
|
|
970
1012
|
"gemini-1.5-pro",
|
|
971
1013
|
"gemini-1.5-flash"
|
|
972
1014
|
];
|
|
973
|
-
async function
|
|
1015
|
+
async function Tt(o, s) {
|
|
974
1016
|
try {
|
|
975
1017
|
switch (o) {
|
|
976
1018
|
case "ollama": {
|
|
977
|
-
const { Ollama:
|
|
978
|
-
return { connected: !0, models: (await new
|
|
1019
|
+
const { Ollama: n } = await import("ollama");
|
|
1020
|
+
return { connected: !0, models: (await new n({ host: s.baseUrl || _e.ollama }).list()).models.map((a) => a.name).sort() };
|
|
979
1021
|
}
|
|
980
1022
|
case "openai": {
|
|
981
|
-
const { default:
|
|
982
|
-
return { connected: !0, models: (await new
|
|
1023
|
+
const { default: n } = await import("openai");
|
|
1024
|
+
return { connected: !0, models: (await new n({
|
|
983
1025
|
apiKey: s.apiKey || process.env.OPENAI_API_KEY,
|
|
984
1026
|
...s.baseUrl ? { baseURL: s.baseUrl } : {}
|
|
985
1027
|
}).models.list()).data.map((a) => a.id).filter((a) => a.startsWith("gpt-") || a.startsWith("o") || a.startsWith("chatgpt-")).sort() };
|
|
986
1028
|
}
|
|
987
1029
|
case "anthropic": {
|
|
988
|
-
const { default:
|
|
1030
|
+
const { default: n } = await import("@anthropic-ai/sdk"), e = new n({
|
|
989
1031
|
apiKey: s.apiKey || process.env.ANTHROPIC_API_KEY,
|
|
990
1032
|
...s.baseUrl ? { baseURL: s.baseUrl } : {}
|
|
991
1033
|
});
|
|
992
1034
|
try {
|
|
993
1035
|
return { connected: !0, models: (await e.models.list({ limit: 100 })).data.map((a) => a.id).sort() };
|
|
994
1036
|
} catch {
|
|
995
|
-
return { connected: !0, models:
|
|
1037
|
+
return { connected: !0, models: pe };
|
|
996
1038
|
}
|
|
997
1039
|
}
|
|
998
1040
|
case "google": {
|
|
999
|
-
const
|
|
1000
|
-
if (!
|
|
1041
|
+
const n = s.apiKey || process.env.GOOGLE_API_KEY || "";
|
|
1042
|
+
if (!n) return { connected: !1, models: G, error: "No API key" };
|
|
1001
1043
|
const e = await fetch(
|
|
1002
|
-
`https://generativelanguage.googleapis.com/v1beta/models?key=${
|
|
1044
|
+
`https://generativelanguage.googleapis.com/v1beta/models?key=${n}`
|
|
1003
1045
|
);
|
|
1004
1046
|
if (!e.ok) {
|
|
1005
1047
|
const i = (await e.json().catch(() => ({})))?.error?.message || `HTTP ${e.status}`;
|
|
1006
|
-
return { connected: !1, models:
|
|
1048
|
+
return { connected: !1, models: G, error: i };
|
|
1007
1049
|
}
|
|
1008
|
-
const
|
|
1009
|
-
return { connected: !0, models:
|
|
1050
|
+
const t = ((await e.json()).models || []).filter((a) => a.name.includes("gemini") && a.supportedGenerationMethods?.includes("generateContent")).map((a) => a.name.replace("models/", "")).sort();
|
|
1051
|
+
return { connected: !0, models: t.length > 0 ? t : G };
|
|
1010
1052
|
}
|
|
1011
1053
|
default:
|
|
1012
1054
|
return { connected: !1, models: [], error: `Unknown backend: ${o}` };
|
|
1013
1055
|
}
|
|
1014
|
-
} catch (
|
|
1015
|
-
const e =
|
|
1016
|
-
return { connected: !1, models: o === "anthropic" ?
|
|
1056
|
+
} catch (n) {
|
|
1057
|
+
const e = n instanceof Error ? n.message : String(n);
|
|
1058
|
+
return { connected: !1, models: o === "anthropic" ? pe : o === "google" ? G : [], error: e };
|
|
1017
1059
|
}
|
|
1018
1060
|
}
|
|
1019
|
-
let
|
|
1061
|
+
let $ = null, F = [];
|
|
1020
1062
|
function Rt(o, s) {
|
|
1021
1063
|
o.handle("app:getCouncilDir", async () => {
|
|
1022
|
-
const
|
|
1023
|
-
return
|
|
1024
|
-
}), o.handle("councilors:list", async (
|
|
1025
|
-
const r = u(
|
|
1026
|
-
let
|
|
1064
|
+
const n = process.env.COUNCIL_CWD || process.cwd();
|
|
1065
|
+
return W(n, "council");
|
|
1066
|
+
}), o.handle("councilors:list", async (n, e) => {
|
|
1067
|
+
const r = u(k(), ".ai-council", "config.json");
|
|
1068
|
+
let t = { backends: {} };
|
|
1027
1069
|
try {
|
|
1028
|
-
const
|
|
1029
|
-
|
|
1070
|
+
const l = await w(r, "utf-8");
|
|
1071
|
+
t = JSON.parse(l);
|
|
1030
1072
|
} catch {
|
|
1031
1073
|
}
|
|
1032
|
-
const a =
|
|
1033
|
-
return (await
|
|
1034
|
-
const
|
|
1074
|
+
const a = ie(t), i = t.councilors ?? {};
|
|
1075
|
+
return (await se(e, a)).map((l) => {
|
|
1076
|
+
const m = i[l.id];
|
|
1035
1077
|
return {
|
|
1036
|
-
id:
|
|
1037
|
-
dirPath:
|
|
1038
|
-
name:
|
|
1039
|
-
description:
|
|
1040
|
-
backend:
|
|
1041
|
-
model:
|
|
1042
|
-
temperature:
|
|
1043
|
-
interests:
|
|
1044
|
-
avatarUrl:
|
|
1045
|
-
source:
|
|
1046
|
-
registryUrl:
|
|
1078
|
+
id: l.id,
|
|
1079
|
+
dirPath: l.dirPath,
|
|
1080
|
+
name: l.frontmatter.name,
|
|
1081
|
+
description: l.frontmatter.description,
|
|
1082
|
+
backend: l.frontmatter.backend,
|
|
1083
|
+
model: l.frontmatter.model,
|
|
1084
|
+
temperature: l.frontmatter.temperature,
|
|
1085
|
+
interests: l.frontmatter.interests,
|
|
1086
|
+
avatarUrl: l.avatarUrl,
|
|
1087
|
+
source: m?.source,
|
|
1088
|
+
registryUrl: m?.url
|
|
1047
1089
|
};
|
|
1048
1090
|
});
|
|
1049
|
-
}), o.handle("councilors:get", async (
|
|
1050
|
-
const r = u(e, "ABOUT.md"),
|
|
1051
|
-
return { frontmatter: a, body: i.trim(), raw:
|
|
1052
|
-
}), o.handle("councilors:save", async (
|
|
1053
|
-
const
|
|
1054
|
-
return await
|
|
1055
|
-
}), o.handle("councilors:create", async (
|
|
1091
|
+
}), o.handle("councilors:get", async (n, e) => {
|
|
1092
|
+
const r = u(e, "ABOUT.md"), t = await w(r, "utf-8"), { data: a, content: i } = Z(t);
|
|
1093
|
+
return { frontmatter: a, body: i.trim(), raw: t };
|
|
1094
|
+
}), o.handle("councilors:save", async (n, e, r) => {
|
|
1095
|
+
const t = u(e, "ABOUT.md");
|
|
1096
|
+
return await C(t, r, "utf-8"), { success: !0 };
|
|
1097
|
+
}), o.handle("councilors:create", async (n, e, r, t) => {
|
|
1056
1098
|
const a = u(e, r);
|
|
1057
|
-
return await
|
|
1058
|
-
}), o.handle("councilors:delete", async (
|
|
1059
|
-
const
|
|
1099
|
+
return await x(a, { recursive: !0 }), await C(u(a, "ABOUT.md"), t, "utf-8"), { success: !0, dirPath: a };
|
|
1100
|
+
}), o.handle("councilors:delete", async (n, e) => (await Y(e, { recursive: !0, force: !0 }), { success: !0 })), o.handle("config:get", async () => {
|
|
1101
|
+
const n = u(k(), ".ai-council", "config.json");
|
|
1060
1102
|
let e = { backends: {} };
|
|
1061
1103
|
try {
|
|
1062
|
-
const i = await w(
|
|
1104
|
+
const i = await w(n, "utf-8");
|
|
1063
1105
|
e = JSON.parse(i);
|
|
1064
1106
|
} catch {
|
|
1065
1107
|
}
|
|
@@ -1067,134 +1109,153 @@ function Rt(o, s) {
|
|
|
1067
1109
|
ANTHROPIC_API_KEY: !!process.env.ANTHROPIC_API_KEY,
|
|
1068
1110
|
OPENAI_API_KEY: !!process.env.OPENAI_API_KEY,
|
|
1069
1111
|
GOOGLE_API_KEY: !!process.env.GOOGLE_API_KEY
|
|
1070
|
-
},
|
|
1071
|
-
ANTHROPIC_API_KEY:
|
|
1072
|
-
OPENAI_API_KEY:
|
|
1073
|
-
GOOGLE_API_KEY:
|
|
1112
|
+
}, t = (i) => i ? "..." + i.slice(-4) : void 0, a = {
|
|
1113
|
+
ANTHROPIC_API_KEY: t(process.env.ANTHROPIC_API_KEY),
|
|
1114
|
+
OPENAI_API_KEY: t(process.env.OPENAI_API_KEY),
|
|
1115
|
+
GOOGLE_API_KEY: t(process.env.GOOGLE_API_KEY)
|
|
1074
1116
|
};
|
|
1075
|
-
return { config: e, envStatus: r, envKeySuffix: a, defaultUrls:
|
|
1076
|
-
}), o.handle("backend:probe", async (
|
|
1117
|
+
return { config: e, envStatus: r, envKeySuffix: a, defaultUrls: _e };
|
|
1118
|
+
}), o.handle("backend:probe", async (n, e, r) => Tt(e, r)), o.handle("backend:models", async (n, e) => {
|
|
1077
1119
|
try {
|
|
1078
|
-
const { getBackend: r } = await Promise.resolve().then(() => nt),
|
|
1079
|
-
return
|
|
1120
|
+
const { getBackend: r } = await Promise.resolve().then(() => nt), t = await r(e);
|
|
1121
|
+
return t.listModels ? { models: await t.listModels() } : { models: [], error: "Not supported" };
|
|
1080
1122
|
} catch (r) {
|
|
1081
1123
|
return { models: [], error: r instanceof Error ? r.message : String(r) };
|
|
1082
1124
|
}
|
|
1083
|
-
}), o.handle("config:save", async (
|
|
1084
|
-
const r = u(
|
|
1085
|
-
return await
|
|
1086
|
-
}), o.handle("discussion:start", async (
|
|
1125
|
+
}), o.handle("config:save", async (n, e) => {
|
|
1126
|
+
const r = u(k(), ".ai-council");
|
|
1127
|
+
return await x(r, { recursive: !0 }), await C(u(r, "config.json"), JSON.stringify(e, null, 2), "utf-8"), be(), { success: !0 };
|
|
1128
|
+
}), o.handle("discussion:start", async (n, e) => {
|
|
1087
1129
|
const r = s();
|
|
1088
1130
|
if (!r) return { error: "No window" };
|
|
1089
|
-
const
|
|
1131
|
+
const t = (a) => {
|
|
1090
1132
|
r.isDestroyed() || r.webContents.send("discussion:event", a);
|
|
1091
1133
|
};
|
|
1092
1134
|
try {
|
|
1093
|
-
|
|
1094
|
-
const a = u(
|
|
1135
|
+
$ && $.abort(), $ = new AbortController(), F = [], v.info("ipc:discussion", "Starting discussion", { councilDir: e.councilDir, councilorIds: e.councilorIds, rounds: e.rounds, mode: e.mode });
|
|
1136
|
+
const a = u(k(), ".ai-council", "config.json");
|
|
1095
1137
|
let i = { backends: {} };
|
|
1096
1138
|
try {
|
|
1097
|
-
const
|
|
1098
|
-
i = JSON.parse(
|
|
1139
|
+
const d = await w(a, "utf-8");
|
|
1140
|
+
i = JSON.parse(d);
|
|
1099
1141
|
} catch {
|
|
1100
1142
|
}
|
|
1101
|
-
const
|
|
1102
|
-
v.info("ipc:discussion", `Loading councilors from ${e.councilDir} + ${
|
|
1103
|
-
const
|
|
1104
|
-
if (v.info("ipc:discussion", `Resolved ${
|
|
1105
|
-
|
|
1143
|
+
const c = ie(i);
|
|
1144
|
+
v.info("ipc:discussion", `Loading councilors from ${e.councilDir} + ${c.length} registered paths`);
|
|
1145
|
+
const l = await se(e.councilDir, c), m = e.councilorIds?.length ? l.filter((d) => e.councilorIds.includes(d.id)) : l;
|
|
1146
|
+
if (v.info("ipc:discussion", `Resolved ${m.length} councilors: ${m.map((d) => d.id).join(", ")}`), m.length === 0) {
|
|
1147
|
+
t({ type: "error", councilorName: "", error: "No councilors found" });
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
t({ type: "preflight_start" });
|
|
1151
|
+
const h = await yt(m, (d) => {
|
|
1152
|
+
t({ type: "preflight_status", message: d });
|
|
1153
|
+
});
|
|
1154
|
+
if (h.invalid.length > 0)
|
|
1155
|
+
for (const d of h.invalid)
|
|
1156
|
+
v.warn("ipc:discussion", `Preflight failed for ${d.councilor.frontmatter.name}: ${d.issues.join("; ")}`), t({
|
|
1157
|
+
type: "preflight_fail",
|
|
1158
|
+
councilorName: d.councilor.frontmatter.name,
|
|
1159
|
+
councilorId: d.councilor.id,
|
|
1160
|
+
model: d.model,
|
|
1161
|
+
issues: d.issues
|
|
1162
|
+
});
|
|
1163
|
+
t({ type: "preflight_complete", valid: h.valid.length, invalid: h.invalid.length });
|
|
1164
|
+
const y = h.valid;
|
|
1165
|
+
if (y.length === 0) {
|
|
1166
|
+
t({ type: "error", councilorName: "", error: "No councilors passed pre-flight validation. Check backend API keys and model names." });
|
|
1106
1167
|
return;
|
|
1107
1168
|
}
|
|
1108
|
-
const
|
|
1169
|
+
const g = async () => F.length === 0 ? null : {
|
|
1109
1170
|
round: 0,
|
|
1110
1171
|
councilorId: "__user__",
|
|
1111
1172
|
councilorName: "You",
|
|
1112
|
-
content:
|
|
1173
|
+
content: F.shift(),
|
|
1113
1174
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1114
1175
|
model: "human",
|
|
1115
1176
|
backend: "human"
|
|
1116
|
-
},
|
|
1117
|
-
topic:
|
|
1177
|
+
}, j = await xt(e.topic, $.signal), f = !!e.previousTurns?.length, _ = {
|
|
1178
|
+
topic: j,
|
|
1118
1179
|
topicSource: e.topicSource,
|
|
1119
|
-
councilors:
|
|
1180
|
+
councilors: y,
|
|
1120
1181
|
rounds: e.rounds,
|
|
1121
|
-
onEvent:
|
|
1122
|
-
beforeTurn:
|
|
1123
|
-
signal:
|
|
1124
|
-
mode:
|
|
1182
|
+
onEvent: t,
|
|
1183
|
+
beforeTurn: g,
|
|
1184
|
+
signal: $.signal,
|
|
1185
|
+
mode: f ? "freeform" : e.mode,
|
|
1125
1186
|
config: i,
|
|
1126
1187
|
previousTurns: e.previousTurns,
|
|
1127
1188
|
previousSummary: e.previousSummary
|
|
1128
|
-
},
|
|
1189
|
+
}, p = await ht(_);
|
|
1129
1190
|
if (i.secretary?.backend)
|
|
1130
1191
|
try {
|
|
1131
|
-
|
|
1132
|
-
const
|
|
1133
|
-
result:
|
|
1192
|
+
t({ type: "summary_start" });
|
|
1193
|
+
const d = await at({
|
|
1194
|
+
result: p,
|
|
1134
1195
|
config: i,
|
|
1135
|
-
onChunk: (
|
|
1136
|
-
|
|
1196
|
+
onChunk: (b) => {
|
|
1197
|
+
t({ type: "summary_chunk", delta: b });
|
|
1137
1198
|
},
|
|
1138
|
-
signal:
|
|
1199
|
+
signal: $?.signal
|
|
1139
1200
|
});
|
|
1140
|
-
|
|
1141
|
-
} catch (
|
|
1142
|
-
v.error("ipc:discussion", "Secretary summary failed",
|
|
1201
|
+
p.summary = d.text, d.diagram && (p.diagram = d.diagram), t({ type: "summary_complete", summary: d.text, diagram: d.diagram });
|
|
1202
|
+
} catch (d) {
|
|
1203
|
+
v.error("ipc:discussion", "Secretary summary failed", d), t({ type: "error", councilorName: "Secretary", error: d instanceof Error ? d.message : String(d) });
|
|
1143
1204
|
}
|
|
1144
1205
|
if (i.secretary?.backend)
|
|
1145
1206
|
try {
|
|
1146
|
-
const
|
|
1147
|
-
topic:
|
|
1148
|
-
firstRoundTurns:
|
|
1207
|
+
const d = p.turns.filter((B) => B.round === 1), b = await lt({
|
|
1208
|
+
topic: p.topic,
|
|
1209
|
+
firstRoundTurns: d,
|
|
1149
1210
|
config: i
|
|
1150
1211
|
});
|
|
1151
|
-
|
|
1152
|
-
} catch (
|
|
1153
|
-
v.error("ipc:discussion", "Title generation failed",
|
|
1212
|
+
p.title = b, t({ type: "title_generated", title: b });
|
|
1213
|
+
} catch (d) {
|
|
1214
|
+
v.error("ipc:discussion", "Title generation failed", d);
|
|
1154
1215
|
}
|
|
1155
1216
|
if (e.infographicBackends?.length)
|
|
1156
|
-
for (const
|
|
1217
|
+
for (const d of e.infographicBackends)
|
|
1157
1218
|
try {
|
|
1158
|
-
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1161
|
-
} catch (
|
|
1162
|
-
v.error("ipc:discussion", `Infographic generation failed (${
|
|
1219
|
+
t({ type: "infographic_start" });
|
|
1220
|
+
const b = await de(p, i, d);
|
|
1221
|
+
p.infographics || (p.infographics = []), p.infographics.push(b), t({ type: "infographic_complete", infographic: b });
|
|
1222
|
+
} catch (b) {
|
|
1223
|
+
v.error("ipc:discussion", `Infographic generation failed (${d})`, b), t({ type: "infographic_error", error: b instanceof Error ? b.message : String(b) });
|
|
1163
1224
|
}
|
|
1164
|
-
e.continuedFrom && (
|
|
1225
|
+
e.continuedFrom && (p.continuedFrom = e.continuedFrom), t({ type: "complete", result: p });
|
|
1165
1226
|
try {
|
|
1166
|
-
await
|
|
1167
|
-
} catch (
|
|
1168
|
-
v.error("ipc:discussion", "Failed to save to history",
|
|
1227
|
+
await bt(p);
|
|
1228
|
+
} catch (d) {
|
|
1229
|
+
v.error("ipc:discussion", "Failed to save to history", d);
|
|
1169
1230
|
}
|
|
1170
1231
|
} catch (a) {
|
|
1171
|
-
v.error("ipc:discussion", "Discussion failed", a),
|
|
1232
|
+
v.error("ipc:discussion", "Discussion failed", a), t({ type: "error", councilorName: "", error: a instanceof Error ? a.message : String(a) });
|
|
1172
1233
|
} finally {
|
|
1173
|
-
|
|
1234
|
+
$ = null;
|
|
1174
1235
|
}
|
|
1175
|
-
}), o.handle("discussion:stop", async () => (
|
|
1176
|
-
|
|
1177
|
-
}), o.handle("shell:open-in-terminal", async (
|
|
1178
|
-
await
|
|
1179
|
-
}), o.handle("shell:open-in-editor", async (
|
|
1180
|
-
const r =
|
|
1236
|
+
}), o.handle("discussion:stop", async () => ($ && ($.abort(), $ = null), { success: !0 })), o.handle("discussion:inject", async (n, e) => (F.push(e), { success: !0 })), o.handle("registry:add-local", async (n, e) => ze(e)), o.handle("registry:add-remote", async (n, e) => Ve(e)), o.handle("registry:remove", async (n, e, r) => (await Xe(e, r), { success: !0 })), o.handle("shell:open-in-finder", async (n, e) => {
|
|
1237
|
+
ne.showItemInFolder(u(e, "ABOUT.md"));
|
|
1238
|
+
}), o.handle("shell:open-in-terminal", async (n, e) => {
|
|
1239
|
+
await U(R)("open", ["-a", "Terminal", e]);
|
|
1240
|
+
}), o.handle("shell:open-in-editor", async (n, e) => {
|
|
1241
|
+
const r = U(R);
|
|
1181
1242
|
try {
|
|
1182
1243
|
await r("code", [e]);
|
|
1183
1244
|
} catch {
|
|
1184
|
-
|
|
1245
|
+
ne.openPath(e);
|
|
1185
1246
|
}
|
|
1186
|
-
}), o.handle("history:list", async () =>
|
|
1187
|
-
const
|
|
1247
|
+
}), o.handle("history:list", async () => vt()), o.handle("history:get", async (n, e) => ue(e)), o.handle("history:delete", async (n, e) => (await kt(e), { success: !0 })), o.handle("infographic:generate", async (n, e, r) => {
|
|
1248
|
+
const t = u(k(), ".ai-council", "config.json");
|
|
1188
1249
|
let a = { backends: {} };
|
|
1189
1250
|
try {
|
|
1190
|
-
const
|
|
1191
|
-
a = JSON.parse(
|
|
1251
|
+
const l = await w(t, "utf-8");
|
|
1252
|
+
a = JSON.parse(l);
|
|
1192
1253
|
} catch {
|
|
1193
1254
|
}
|
|
1194
|
-
const i = await
|
|
1195
|
-
return await
|
|
1196
|
-
}), o.handle("infographic:delete", async (
|
|
1197
|
-
const r =
|
|
1255
|
+
const i = await ue(e), c = await de(i, a, r);
|
|
1256
|
+
return await _t(e, c), { infographic: c };
|
|
1257
|
+
}), o.handle("infographic:delete", async (n, e, r) => (await St(e, r), { success: !0 })), o.handle("file:read-as-text", async (n, e) => {
|
|
1258
|
+
const r = N(e), t = r.includes(".") ? "." + r.split(".").pop().toLowerCase() : "", a = /* @__PURE__ */ new Set([
|
|
1198
1259
|
".txt",
|
|
1199
1260
|
".md",
|
|
1200
1261
|
".csv",
|
|
@@ -1242,43 +1303,43 @@ function Rt(o, s) {
|
|
|
1242
1303
|
".epub",
|
|
1243
1304
|
".rtf"
|
|
1244
1305
|
]);
|
|
1245
|
-
if (a.has(
|
|
1306
|
+
if (a.has(t))
|
|
1246
1307
|
try {
|
|
1247
|
-
const
|
|
1248
|
-
return { name: r, content:
|
|
1249
|
-
} catch (
|
|
1250
|
-
return { name: r, content: `[Error reading file: ${
|
|
1308
|
+
const c = await w(e, "utf-8");
|
|
1309
|
+
return { name: r, content: c };
|
|
1310
|
+
} catch (c) {
|
|
1311
|
+
return { name: r, content: `[Error reading file: ${c instanceof Error ? c.message : String(c)}]` };
|
|
1251
1312
|
}
|
|
1252
|
-
if (i.has(
|
|
1253
|
-
const
|
|
1313
|
+
if (i.has(t)) {
|
|
1314
|
+
const c = U(R);
|
|
1254
1315
|
try {
|
|
1255
|
-
const { stdout:
|
|
1316
|
+
const { stdout: l } = await c("markitdown", [e], {
|
|
1256
1317
|
timeout: 3e4,
|
|
1257
1318
|
maxBuffer: 10485760
|
|
1258
1319
|
// 10 MB
|
|
1259
1320
|
});
|
|
1260
|
-
return { name: r, content:
|
|
1261
|
-
} catch (
|
|
1262
|
-
const
|
|
1263
|
-
return
|
|
1321
|
+
return { name: r, content: l };
|
|
1322
|
+
} catch (l) {
|
|
1323
|
+
const m = l instanceof Error ? l.message : String(l);
|
|
1324
|
+
return m.includes("ENOENT") ? {
|
|
1264
1325
|
name: r,
|
|
1265
|
-
content: `[Cannot convert ${
|
|
1266
|
-
} : { name: r, content: `[Error converting file: ${
|
|
1326
|
+
content: `[Cannot convert ${t} file: markitdown is not installed. Run: pip install 'markitdown[all]']`
|
|
1327
|
+
} : { name: r, content: `[Error converting file: ${m}]` };
|
|
1267
1328
|
}
|
|
1268
1329
|
}
|
|
1269
1330
|
return { name: r, content: `[Unsupported file type: ${r}]` };
|
|
1270
1331
|
}), o.handle("markitdown:check", async () => {
|
|
1271
|
-
const
|
|
1332
|
+
const n = U(R);
|
|
1272
1333
|
try {
|
|
1273
|
-
const { stdout: e } = await
|
|
1334
|
+
const { stdout: e } = await n("markitdown", ["--version"], { timeout: 5e3 });
|
|
1274
1335
|
return { installed: !0, version: e.trim() };
|
|
1275
1336
|
} catch {
|
|
1276
1337
|
return { installed: !1 };
|
|
1277
1338
|
}
|
|
1278
1339
|
}), o.handle("markitdown:install", async () => {
|
|
1279
|
-
const
|
|
1340
|
+
const n = U(R);
|
|
1280
1341
|
try {
|
|
1281
|
-
return await
|
|
1342
|
+
return await n("pip", ["install", "markitdown[all]"], {
|
|
1282
1343
|
timeout: 12e4,
|
|
1283
1344
|
maxBuffer: 10 * 1024 * 1024
|
|
1284
1345
|
}), { success: !0 };
|
|
@@ -1286,63 +1347,63 @@ function Rt(o, s) {
|
|
|
1286
1347
|
return { success: !1, error: e instanceof Error ? e.message : String(e) };
|
|
1287
1348
|
}
|
|
1288
1349
|
}), o.handle("dialog:selectDirectory", async () => {
|
|
1289
|
-
const
|
|
1290
|
-
if (!
|
|
1291
|
-
const e = await
|
|
1350
|
+
const n = s();
|
|
1351
|
+
if (!n) return null;
|
|
1352
|
+
const e = await $e.showOpenDialog(n, {
|
|
1292
1353
|
properties: ["openDirectory"]
|
|
1293
1354
|
});
|
|
1294
1355
|
return e.canceled ? null : e.filePaths[0];
|
|
1295
1356
|
});
|
|
1296
1357
|
}
|
|
1297
|
-
const
|
|
1298
|
-
|
|
1299
|
-
const
|
|
1300
|
-
function
|
|
1301
|
-
const
|
|
1358
|
+
const Ut = Pe(import.meta.url), V = Oe(Ut), Se = u(k(), ".ai-council");
|
|
1359
|
+
Ne(Se, { recursive: !0 });
|
|
1360
|
+
const Ee = u(Se, "electron-debug.log");
|
|
1361
|
+
function P(o, ...s) {
|
|
1362
|
+
const n = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${o}] ${s.map((e) => typeof e == "string" ? e : JSON.stringify(e)).join(" ")}
|
|
1302
1363
|
`;
|
|
1303
|
-
|
|
1364
|
+
Te(Ee, n);
|
|
1304
1365
|
}
|
|
1305
|
-
|
|
1366
|
+
xe(Ee, `=== State Change Council Electron — started ${(/* @__PURE__ */ new Date()).toISOString()} ===
|
|
1306
1367
|
`);
|
|
1307
|
-
|
|
1308
|
-
let
|
|
1309
|
-
function
|
|
1310
|
-
|
|
1368
|
+
K.name = "State Change Council";
|
|
1369
|
+
let A = null;
|
|
1370
|
+
function fe() {
|
|
1371
|
+
P("main", "Creating BrowserWindow"), A = new he({
|
|
1311
1372
|
width: 1200,
|
|
1312
1373
|
height: 800,
|
|
1313
1374
|
minWidth: 800,
|
|
1314
1375
|
minHeight: 600,
|
|
1315
1376
|
title: "State Change Council",
|
|
1316
|
-
icon:
|
|
1377
|
+
icon: W(V, "..", "assets", "icon.png"),
|
|
1317
1378
|
webPreferences: {
|
|
1318
1379
|
contextIsolation: !0,
|
|
1319
1380
|
nodeIntegration: !1,
|
|
1320
|
-
preload: u(
|
|
1381
|
+
preload: u(V, "preload.mjs")
|
|
1321
1382
|
}
|
|
1322
|
-
}),
|
|
1323
|
-
const a = ["DEBUG", "INFO", "WARN", "ERROR"][
|
|
1324
|
-
|
|
1325
|
-
}),
|
|
1326
|
-
|
|
1327
|
-
}),
|
|
1328
|
-
|
|
1383
|
+
}), A.webContents.on("console-message", (s, n, e, r, t) => {
|
|
1384
|
+
const a = ["DEBUG", "INFO", "WARN", "ERROR"][n] || "LOG";
|
|
1385
|
+
P(`renderer:${a}`, `${e} (${t}:${r})`);
|
|
1386
|
+
}), A.webContents.on("render-process-gone", (s, n) => {
|
|
1387
|
+
P("main:CRASH", "Renderer process gone:", n);
|
|
1388
|
+
}), A.webContents.on("did-fail-load", (s, n, e) => {
|
|
1389
|
+
P("main:LOAD_ERROR", `Failed to load: ${n} ${e}`);
|
|
1329
1390
|
});
|
|
1330
1391
|
const o = process.env.VITE_DEV_SERVER_URL;
|
|
1331
1392
|
if (o)
|
|
1332
|
-
|
|
1393
|
+
P("main", `Loading dev server URL: ${o}`), A.loadURL(o);
|
|
1333
1394
|
else {
|
|
1334
|
-
const s = u(
|
|
1335
|
-
|
|
1395
|
+
const s = u(V, "../dist-renderer/index.html");
|
|
1396
|
+
P("main", `Loading file: ${s}`), A.loadFile(s);
|
|
1336
1397
|
}
|
|
1337
|
-
process.env.VITE_DEV_SERVER_URL &&
|
|
1338
|
-
|
|
1398
|
+
process.env.VITE_DEV_SERVER_URL && A.webContents.openDevTools(), A.on("closed", () => {
|
|
1399
|
+
A = null;
|
|
1339
1400
|
});
|
|
1340
1401
|
}
|
|
1341
|
-
|
|
1402
|
+
ge.registerSchemesAsPrivileged([
|
|
1342
1403
|
{ scheme: "council-file", privileges: { bypassCSP: !0, supportFetchAPI: !0 } }
|
|
1343
1404
|
]);
|
|
1344
|
-
|
|
1345
|
-
|
|
1405
|
+
K.whenReady().then(() => {
|
|
1406
|
+
P("main", "App ready, registering IPC handlers");
|
|
1346
1407
|
const o = "State Change Council", s = [
|
|
1347
1408
|
{
|
|
1348
1409
|
label: o,
|
|
@@ -1363,13 +1424,13 @@ D.whenReady().then(() => {
|
|
|
1363
1424
|
{ role: "viewMenu" },
|
|
1364
1425
|
{ role: "windowMenu" }
|
|
1365
1426
|
];
|
|
1366
|
-
|
|
1367
|
-
const e = decodeURIComponent(
|
|
1368
|
-
return
|
|
1369
|
-
}), Rt(
|
|
1370
|
-
|
|
1427
|
+
oe.setApplicationMenu(oe.buildFromTemplate(s)), ge.handle("council-file", (n) => {
|
|
1428
|
+
const e = decodeURIComponent(n.url.replace("council-file://", ""));
|
|
1429
|
+
return Ae.fetch(Ce(e).href);
|
|
1430
|
+
}), Rt(Ie, () => A), fe(), K.on("activate", () => {
|
|
1431
|
+
he.getAllWindows().length === 0 && fe();
|
|
1371
1432
|
});
|
|
1372
1433
|
});
|
|
1373
|
-
|
|
1374
|
-
process.platform !== "darwin" &&
|
|
1434
|
+
K.on("window-all-closed", () => {
|
|
1435
|
+
process.platform !== "darwin" && K.quit();
|
|
1375
1436
|
});
|