@statechange/council 0.1.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 +207 -0
- package/council/creative/ABOUT.md +23 -0
- package/council/critic/ABOUT.md +23 -0
- package/council/strategist/ABOUT.md +21 -0
- package/dist/backends/anthropic.d.ts +2 -0
- package/dist/backends/anthropic.js +57 -0
- package/dist/backends/anthropic.js.map +1 -0
- package/dist/backends/google.d.ts +2 -0
- package/dist/backends/google.js +68 -0
- package/dist/backends/google.js.map +1 -0
- package/dist/backends/index.d.ts +3 -0
- package/dist/backends/index.js +47 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/ollama.d.ts +2 -0
- package/dist/backends/ollama.js +68 -0
- package/dist/backends/ollama.js.map +1 -0
- package/dist/backends/openai.d.ts +2 -0
- package/dist/backends/openai.js +62 -0
- package/dist/backends/openai.js.map +1 -0
- package/dist/backends/types.d.ts +1 -0
- package/dist/backends/types.js +2 -0
- package/dist/backends/types.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +152 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +7 -0
- package/dist/commands/config.js +118 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/counsellor.d.ts +7 -0
- package/dist/commands/counsellor.js +98 -0
- package/dist/commands/counsellor.js.map +1 -0
- package/dist/commands/discuss.d.ts +12 -0
- package/dist/commands/discuss.js +154 -0
- package/dist/commands/discuss.js.map +1 -0
- package/dist/commands/history.d.ts +5 -0
- package/dist/commands/history.js +46 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/list.d.ts +5 -0
- package/dist/commands/list.js +40 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/core/conversation-engine.d.ts +13 -0
- package/dist/core/conversation-engine.js +226 -0
- package/dist/core/conversation-engine.js.map +1 -0
- package/dist/core/counsellor-loader.d.ts +4 -0
- package/dist/core/counsellor-loader.js +97 -0
- package/dist/core/counsellor-loader.js.map +1 -0
- package/dist/core/counsellor-registry.d.ts +12 -0
- package/dist/core/counsellor-registry.js +131 -0
- package/dist/core/counsellor-registry.js.map +1 -0
- package/dist/core/excalidraw-cheatsheet.d.ts +5 -0
- package/dist/core/excalidraw-cheatsheet.js +65 -0
- package/dist/core/excalidraw-cheatsheet.js.map +1 -0
- package/dist/core/history.d.ts +16 -0
- package/dist/core/history.js +74 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/infographic.d.ts +4 -0
- package/dist/core/infographic.js +81 -0
- package/dist/core/infographic.js.map +1 -0
- package/dist/core/key-scanner.d.ts +8 -0
- package/dist/core/key-scanner.js +79 -0
- package/dist/core/key-scanner.js.map +1 -0
- package/dist/core/logger.d.ts +5 -0
- package/dist/core/logger.js +38 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/output-formatter.d.ts +2 -0
- package/dist/core/output-formatter.js +47 -0
- package/dist/core/output-formatter.js.map +1 -0
- package/dist/core/secretary.d.ts +23 -0
- package/dist/core/secretary.js +171 -0
- package/dist/core/secretary.js.map +1 -0
- package/dist/core/skill-loader.d.ts +2 -0
- package/dist/core/skill-loader.js +32 -0
- package/dist/core/skill-loader.js.map +1 -0
- package/dist/electron/ipc-handlers.d.ts +3 -0
- package/dist/electron/ipc-handlers.js +477 -0
- package/dist/electron/ipc-handlers.js.map +1 -0
- package/dist/electron/main.d.ts +1 -0
- package/dist/electron/main.js +85 -0
- package/dist/electron/main.js.map +1 -0
- package/dist/electron/preload.d.ts +1 -0
- package/dist/electron/preload.js +38 -0
- package/dist/electron/preload.js.map +1 -0
- package/dist/types.d.ts +184 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/dist-electron/main.js +1635 -0
- package/package.json +87 -0
- package/skills/council-manage/SKILL.md +214 -0
- package/skills/council-setup-keys/SKILL.md +127 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact Excalidraw element reference for LLM diagram generation.
|
|
3
|
+
* Appended to the secretary system prompt so it can output valid Excalidraw JSON.
|
|
4
|
+
*/
|
|
5
|
+
export function getExcalidrawCheatsheet() {
|
|
6
|
+
return `
|
|
7
|
+
## Excalidraw Element Reference
|
|
8
|
+
|
|
9
|
+
Output a JSON array of Excalidraw elements. Each element needs these fields:
|
|
10
|
+
|
|
11
|
+
### Common Fields (all elements)
|
|
12
|
+
- \`type\`: "rectangle" | "ellipse" | "diamond" | "text" | "arrow" | "line"
|
|
13
|
+
- \`id\`: unique string (e.g. "rect1", "text1", "arrow1")
|
|
14
|
+
- \`x\`, \`y\`: number (top-left origin, x increases right, y increases down)
|
|
15
|
+
- \`width\`, \`height\`: number
|
|
16
|
+
- \`strokeColor\`: hex string (e.g. "#1e1e1e")
|
|
17
|
+
- \`backgroundColor\`: hex string or "transparent"
|
|
18
|
+
- \`fillStyle\`: "solid" | "hachure" | "cross-hatch"
|
|
19
|
+
- \`strokeWidth\`: 1 | 2 | 4
|
|
20
|
+
- \`roughness\`: 0 (sharp) | 1 (sketchy)
|
|
21
|
+
- \`opacity\`: 100
|
|
22
|
+
- \`angle\`: 0
|
|
23
|
+
- \`seed\`: any integer (e.g. 1)
|
|
24
|
+
- \`version\`: 1
|
|
25
|
+
- \`isDeleted\`: false
|
|
26
|
+
- \`groupIds\`: []
|
|
27
|
+
- \`boundElements\`: null or array of { id: string, type: "text" | "arrow" }
|
|
28
|
+
- \`link\`: null
|
|
29
|
+
- \`locked\`: false
|
|
30
|
+
|
|
31
|
+
### Text Elements
|
|
32
|
+
Additional 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
|
|
33
|
+
|
|
34
|
+
### Arrow/Line Elements
|
|
35
|
+
Additional 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
|
|
36
|
+
|
|
37
|
+
### Color Palette
|
|
38
|
+
- Blue: "#1971c2", Light blue bg: "#a5d8ff"
|
|
39
|
+
- Green: "#2f9e44", Light green bg: "#b2f2bb"
|
|
40
|
+
- Red: "#e03131", Light red bg: "#ffc9c9"
|
|
41
|
+
- Orange: "#e8590c", Light orange bg: "#ffd8a8"
|
|
42
|
+
- Purple: "#7048e8", Light purple bg: "#d0bfff"
|
|
43
|
+
- Yellow: "#f08c00", Light yellow bg: "#ffec99"
|
|
44
|
+
- Gray: "#868e96", Light gray bg: "#dee2e6"
|
|
45
|
+
- Dark: "#1e1e1e"
|
|
46
|
+
|
|
47
|
+
### Layout Tips
|
|
48
|
+
- Space shapes ~200px apart horizontally, ~150px vertically
|
|
49
|
+
- Typical shape size: 160×80 for rectangles, 120×60 for ellipses
|
|
50
|
+
- Center text inside shapes using containerId
|
|
51
|
+
- Use arrows to show relationships (agreement, disagreement, influence)
|
|
52
|
+
|
|
53
|
+
### Compact Example
|
|
54
|
+
\`\`\`json
|
|
55
|
+
[
|
|
56
|
+
{"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},
|
|
57
|
+
{"type":"text","id":"t1","x":60,"y":70,"width":140,"height":40,"text":"Counsellor 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},
|
|
58
|
+
{"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},
|
|
59
|
+
{"type":"text","id":"t2","x":360,"y":70,"width":140,"height":40,"text":"Counsellor 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},
|
|
60
|
+
{"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}
|
|
61
|
+
]
|
|
62
|
+
\`\`\`
|
|
63
|
+
`.trim();
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=excalidraw-cheatsheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"excalidraw-cheatsheet.js","sourceRoot":"","sources":["../../src/core/excalidraw-cheatsheet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDR,CAAC,IAAI,EAAE,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ConversationResult } from "../types.js";
|
|
2
|
+
export interface HistoryEntry {
|
|
3
|
+
id: string;
|
|
4
|
+
topic: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
counsellors: string[];
|
|
7
|
+
rounds: number;
|
|
8
|
+
startedAt: string;
|
|
9
|
+
completedAt: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function saveToHistory(result: ConversationResult): Promise<string>;
|
|
12
|
+
export declare function listHistory(): Promise<HistoryEntry[]>;
|
|
13
|
+
export declare function getHistoryEntry(id: string): Promise<ConversationResult>;
|
|
14
|
+
export declare function deleteHistoryEntry(id: string): Promise<void>;
|
|
15
|
+
export declare function addInfographicToHistory(id: string, infographic: string): Promise<void>;
|
|
16
|
+
export declare function deleteInfographicFromHistory(id: string, index: number): Promise<void>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { readFile, writeFile, readdir, rm, mkdir } from "node:fs/promises";
|
|
2
|
+
import { join, basename } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
const HISTORY_DIR = join(homedir(), ".ai-council", "history");
|
|
5
|
+
function slugify(text) {
|
|
6
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
7
|
+
}
|
|
8
|
+
export async function saveToHistory(result) {
|
|
9
|
+
await mkdir(HISTORY_DIR, { recursive: true });
|
|
10
|
+
const timestamp = new Date(result.startedAt).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
11
|
+
const slug = slugify(result.topic);
|
|
12
|
+
const id = `${timestamp}-${slug}`;
|
|
13
|
+
const filePath = join(HISTORY_DIR, `${id}.json`);
|
|
14
|
+
await writeFile(filePath, JSON.stringify(result, null, 2), "utf-8");
|
|
15
|
+
return id;
|
|
16
|
+
}
|
|
17
|
+
export async function listHistory() {
|
|
18
|
+
await mkdir(HISTORY_DIR, { recursive: true });
|
|
19
|
+
const files = await readdir(HISTORY_DIR);
|
|
20
|
+
const entries = [];
|
|
21
|
+
for (const file of files) {
|
|
22
|
+
if (!file.endsWith(".json"))
|
|
23
|
+
continue;
|
|
24
|
+
try {
|
|
25
|
+
const raw = await readFile(join(HISTORY_DIR, file), "utf-8");
|
|
26
|
+
const result = JSON.parse(raw);
|
|
27
|
+
entries.push({
|
|
28
|
+
id: basename(file, ".json"),
|
|
29
|
+
topic: result.topic,
|
|
30
|
+
title: result.title,
|
|
31
|
+
counsellors: result.counsellors.map(c => c.name),
|
|
32
|
+
rounds: result.rounds,
|
|
33
|
+
startedAt: result.startedAt,
|
|
34
|
+
completedAt: result.completedAt,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch { /* skip invalid files */ }
|
|
38
|
+
}
|
|
39
|
+
return entries.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
|
|
40
|
+
}
|
|
41
|
+
export async function getHistoryEntry(id) {
|
|
42
|
+
const filePath = join(HISTORY_DIR, `${id}.json`);
|
|
43
|
+
const raw = await readFile(filePath, "utf-8");
|
|
44
|
+
const result = JSON.parse(raw);
|
|
45
|
+
// Migrate old singular infographic field to array
|
|
46
|
+
if (result.infographic && !result.infographics) {
|
|
47
|
+
result.infographics = [result.infographic];
|
|
48
|
+
delete result.infographic;
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
export async function deleteHistoryEntry(id) {
|
|
53
|
+
const filePath = join(HISTORY_DIR, `${id}.json`);
|
|
54
|
+
await rm(filePath);
|
|
55
|
+
}
|
|
56
|
+
export async function addInfographicToHistory(id, infographic) {
|
|
57
|
+
const filePath = join(HISTORY_DIR, `${id}.json`);
|
|
58
|
+
const raw = await readFile(filePath, "utf-8");
|
|
59
|
+
const result = JSON.parse(raw);
|
|
60
|
+
if (!result.infographics)
|
|
61
|
+
result.infographics = [];
|
|
62
|
+
result.infographics.push(infographic);
|
|
63
|
+
await writeFile(filePath, JSON.stringify(result, null, 2), "utf-8");
|
|
64
|
+
}
|
|
65
|
+
export async function deleteInfographicFromHistory(id, index) {
|
|
66
|
+
const filePath = join(HISTORY_DIR, `${id}.json`);
|
|
67
|
+
const raw = await readFile(filePath, "utf-8");
|
|
68
|
+
const result = JSON.parse(raw);
|
|
69
|
+
if (result.infographics && index >= 0 && index < result.infographics.length) {
|
|
70
|
+
result.infographics.splice(index, 1);
|
|
71
|
+
}
|
|
72
|
+
await writeFile(filePath, JSON.stringify(result, null, 2), "utf-8");
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/core/history.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ConversationResult, CouncilConfig } from "../types.js";
|
|
2
|
+
export type ImageBackend = "openai" | "google";
|
|
3
|
+
export declare function generateInfographic(result: ConversationResult, config: CouncilConfig, backendOverride?: ImageBackend): Promise<string>;
|
|
4
|
+
export declare function hasImageBackend(config: CouncilConfig): boolean;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
function buildPrompt(result) {
|
|
4
|
+
const names = result.counsellors.map((c) => c.name).join(", ");
|
|
5
|
+
const summary = result.summary ?? result.turns.map((t) => `${t.counsellorName}: ${t.content.slice(0, 200)}`).join("\n");
|
|
6
|
+
return [
|
|
7
|
+
"Create a professional infographic summarizing a panel discussion.",
|
|
8
|
+
`Topic: ${result.topic.slice(0, 300)}`,
|
|
9
|
+
`Key points: ${summary.slice(0, 1500)}`,
|
|
10
|
+
`Panelists: ${names}`,
|
|
11
|
+
"Use a clean, modern design with sections for convergence points, divergence points, and key takeaways.",
|
|
12
|
+
"Include relevant icons and visual hierarchy. Use a horizontal landscape layout.",
|
|
13
|
+
].join(" ");
|
|
14
|
+
}
|
|
15
|
+
function detectBackend(config) {
|
|
16
|
+
if (config.infographic?.backend)
|
|
17
|
+
return config.infographic.backend;
|
|
18
|
+
const hasGoogle = !!(config.backends.google?.apiKey || process.env.GOOGLE_API_KEY);
|
|
19
|
+
const hasOpenai = !!(config.backends.openai?.apiKey || process.env.OPENAI_API_KEY);
|
|
20
|
+
if (hasGoogle)
|
|
21
|
+
return "google";
|
|
22
|
+
if (hasOpenai)
|
|
23
|
+
return "openai";
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
async function generateViaOpenAI(prompt, config) {
|
|
27
|
+
const OpenAI = require("openai").default;
|
|
28
|
+
const client = new OpenAI({
|
|
29
|
+
apiKey: config.backends.openai?.apiKey || process.env.OPENAI_API_KEY,
|
|
30
|
+
...(config.backends.openai?.baseUrl ? { baseURL: config.backends.openai.baseUrl } : {}),
|
|
31
|
+
});
|
|
32
|
+
const response = await client.images.generate({
|
|
33
|
+
model: "gpt-image-1",
|
|
34
|
+
prompt,
|
|
35
|
+
quality: "high",
|
|
36
|
+
size: "1536x1024",
|
|
37
|
+
});
|
|
38
|
+
const b64 = response.data?.[0]?.b64_json;
|
|
39
|
+
if (!b64)
|
|
40
|
+
throw new Error("No image data returned from OpenAI");
|
|
41
|
+
return b64;
|
|
42
|
+
}
|
|
43
|
+
async function generateViaGoogle(prompt, config) {
|
|
44
|
+
const { GoogleGenAI } = require("@google/genai");
|
|
45
|
+
const apiKey = config.backends.google?.apiKey || process.env.GOOGLE_API_KEY;
|
|
46
|
+
if (!apiKey)
|
|
47
|
+
throw new Error("No Google API key configured");
|
|
48
|
+
const ai = new GoogleGenAI({ apiKey });
|
|
49
|
+
const response = await ai.models.generateContent({
|
|
50
|
+
model: "gemini-3-pro-image-preview",
|
|
51
|
+
contents: prompt,
|
|
52
|
+
config: {
|
|
53
|
+
responseModalities: ["IMAGE", "TEXT"],
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
const parts = response.candidates?.[0]?.content?.parts;
|
|
57
|
+
if (!parts)
|
|
58
|
+
throw new Error("No response parts from Gemini");
|
|
59
|
+
for (const part of parts) {
|
|
60
|
+
if (part.inlineData?.data) {
|
|
61
|
+
return part.inlineData.data;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
throw new Error("No image data in Gemini response");
|
|
65
|
+
}
|
|
66
|
+
export async function generateInfographic(result, config, backendOverride) {
|
|
67
|
+
const backend = backendOverride ?? detectBackend(config);
|
|
68
|
+
if (!backend)
|
|
69
|
+
throw new Error("No image-capable backend configured (need OpenAI or Google API key)");
|
|
70
|
+
const prompt = buildPrompt(result);
|
|
71
|
+
if (backend === "openai") {
|
|
72
|
+
return generateViaOpenAI(prompt, config);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
return generateViaGoogle(prompt, config);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export function hasImageBackend(config) {
|
|
79
|
+
return detectBackend(config) !== null;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=infographic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"infographic.js","sourceRoot":"","sources":["../../src/core/infographic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
const KEY_PATTERNS = [
|
|
5
|
+
{ backend: "anthropic", envVar: "ANTHROPIC_API_KEY", pattern: /ANTHROPIC_API_KEY\s*=\s*['"]?([^\s'"#]+)/ },
|
|
6
|
+
{ backend: "openai", envVar: "OPENAI_API_KEY", pattern: /OPENAI_API_KEY\s*=\s*['"]?([^\s'"#]+)/ },
|
|
7
|
+
{ backend: "google", envVar: "GOOGLE_API_KEY", pattern: /GOOGLE_API_KEY\s*=\s*['"]?([^\s'"#]+)/ },
|
|
8
|
+
// Also pick up GEMINI_API_KEY and GOOGLE_GEMINI_API_KEY as google
|
|
9
|
+
{ backend: "google", envVar: "GEMINI_API_KEY", pattern: /(?<![A-Z_])GEMINI_API_KEY\s*=\s*['"]?([^\s'"#]+)/ },
|
|
10
|
+
{ backend: "google", envVar: "GOOGLE_GEMINI_API_KEY", pattern: /GOOGLE_GEMINI_API_KEY\s*=\s*['"]?([^\s'"#]+)/ },
|
|
11
|
+
];
|
|
12
|
+
function getSearchPaths() {
|
|
13
|
+
const home = homedir();
|
|
14
|
+
return [
|
|
15
|
+
// Current project
|
|
16
|
+
".env",
|
|
17
|
+
".env.local",
|
|
18
|
+
".env.development",
|
|
19
|
+
".env.production",
|
|
20
|
+
// Home directory dotfiles
|
|
21
|
+
join(home, ".env"),
|
|
22
|
+
join(home, ".bashrc"),
|
|
23
|
+
join(home, ".bash_profile"),
|
|
24
|
+
join(home, ".zshrc"),
|
|
25
|
+
join(home, ".zshenv"),
|
|
26
|
+
join(home, ".zprofile"),
|
|
27
|
+
join(home, ".profile"),
|
|
28
|
+
// Common project locations
|
|
29
|
+
join(home, ".config", "shell", "env"),
|
|
30
|
+
// Fish shell
|
|
31
|
+
join(home, ".config", "fish", "config.fish"),
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
async function scanFile(filePath) {
|
|
35
|
+
let content;
|
|
36
|
+
try {
|
|
37
|
+
content = await readFile(filePath, "utf-8");
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
const found = [];
|
|
43
|
+
for (const { backend, envVar, pattern } of KEY_PATTERNS) {
|
|
44
|
+
const match = content.match(pattern);
|
|
45
|
+
if (match && match[1] && match[1].length > 5) {
|
|
46
|
+
found.push({ backend, envVar, value: match[1], source: filePath });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return found;
|
|
50
|
+
}
|
|
51
|
+
export async function scanForKeys(extraPaths = []) {
|
|
52
|
+
const paths = [...getSearchPaths(), ...extraPaths];
|
|
53
|
+
const results = [];
|
|
54
|
+
// Also check current process env
|
|
55
|
+
for (const { backend, envVar } of KEY_PATTERNS) {
|
|
56
|
+
const val = process.env[envVar];
|
|
57
|
+
if (val && val.length > 5) {
|
|
58
|
+
results.push({ backend, envVar, value: val, source: "process.env" });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const filePath of paths) {
|
|
62
|
+
const found = await scanFile(filePath);
|
|
63
|
+
results.push(...found);
|
|
64
|
+
}
|
|
65
|
+
// Deduplicate — prefer the first occurrence per backend
|
|
66
|
+
const seen = new Map();
|
|
67
|
+
for (const key of results) {
|
|
68
|
+
if (!seen.has(key.backend)) {
|
|
69
|
+
seen.set(key.backend, key);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return Array.from(seen.values());
|
|
73
|
+
}
|
|
74
|
+
export function maskKey(key) {
|
|
75
|
+
if (key.length <= 8)
|
|
76
|
+
return "****";
|
|
77
|
+
return key.slice(0, 4) + "..." + key.slice(-4);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=key-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-scanner.js","sourceRoot":"","sources":["../../src/core/key-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { appendFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
const LOG_DIR = join(homedir(), ".ai-council");
|
|
5
|
+
const LOG_FILE = join(LOG_DIR, "council.log");
|
|
6
|
+
let ensured = false;
|
|
7
|
+
async function ensureDir() {
|
|
8
|
+
if (ensured)
|
|
9
|
+
return;
|
|
10
|
+
await mkdir(LOG_DIR, { recursive: true });
|
|
11
|
+
ensured = true;
|
|
12
|
+
}
|
|
13
|
+
function formatEntry(level, context, message, extra) {
|
|
14
|
+
const ts = new Date().toISOString();
|
|
15
|
+
let line = `[${ts}] ${level} [${context}] ${message}`;
|
|
16
|
+
if (extra !== undefined) {
|
|
17
|
+
const detail = extra instanceof Error
|
|
18
|
+
? `${extra.message}\n${extra.stack ?? ""}`
|
|
19
|
+
: typeof extra === "string" ? extra : JSON.stringify(extra, null, 2);
|
|
20
|
+
line += `\n ${detail.replace(/\n/g, "\n ")}`;
|
|
21
|
+
}
|
|
22
|
+
return line + "\n";
|
|
23
|
+
}
|
|
24
|
+
async function write(level, context, message, extra) {
|
|
25
|
+
try {
|
|
26
|
+
await ensureDir();
|
|
27
|
+
await appendFile(LOG_FILE, formatEntry(level, context, message, extra));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Last-resort: don't let logging itself crash the app
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export const log = {
|
|
34
|
+
info: (context, message, extra) => write("INFO", context, message, extra),
|
|
35
|
+
warn: (context, message, extra) => write("WARN", context, message, extra),
|
|
36
|
+
error: (context, message, extra) => write("ERROR", context, message, extra),
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;AAE9C,IAAI,OAAO,GAAG,KAAK,CAAC;AAEpB,KAAK,UAAU,SAAS;IACtB,IAAI,OAAO;QAAE,OAAO;IACpB,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,OAAO,GAAG,IAAI,CAAC;AACjB,CAAC;AAED,SAAS,WAAW,CAAC,KAAa,EAAE,OAAe,EAAE,OAAe,EAAE,KAAe;IACnF,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,IAAI,GAAG,IAAI,EAAE,KAAK,KAAK,KAAK,OAAO,KAAK,OAAO,EAAE,CAAC;IACtD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK;YACnC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE;YAC1C,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvE,IAAI,IAAI,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,GAAG,IAAI,CAAC;AACrB,CAAC;AAED,KAAK,UAAU,KAAK,CAAC,KAAa,EAAE,OAAe,EAAE,OAAe,EAAE,KAAe;IACnF,IAAI,CAAC;QACH,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,UAAU,CAAC,QAAQ,EAAE,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,sDAAsD;IACxD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,IAAI,EAAE,CAAC,OAAe,EAAE,OAAe,EAAE,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC;IACnG,IAAI,EAAE,CAAC,OAAe,EAAE,OAAe,EAAE,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC;IACnG,KAAK,EAAE,CAAC,OAAe,EAAE,OAAe,EAAE,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC;CACtG,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
function toMarkdown(result) {
|
|
4
|
+
const lines = [];
|
|
5
|
+
const date = new Date(result.startedAt).toISOString().split("T")[0];
|
|
6
|
+
lines.push(`# Council Discussion: ${result.topic.slice(0, 100)}`);
|
|
7
|
+
lines.push("");
|
|
8
|
+
lines.push(`**Counsellors:** ${result.counsellors.map((c) => c.name).join(", ")}`);
|
|
9
|
+
lines.push(`**Rounds:** ${result.rounds} | **Date:** ${date}`);
|
|
10
|
+
lines.push("");
|
|
11
|
+
let currentRound = 0;
|
|
12
|
+
for (const turn of result.turns) {
|
|
13
|
+
if (turn.round !== currentRound) {
|
|
14
|
+
currentRound = turn.round;
|
|
15
|
+
lines.push("---");
|
|
16
|
+
lines.push("");
|
|
17
|
+
lines.push(`## Round ${currentRound}`);
|
|
18
|
+
lines.push("");
|
|
19
|
+
}
|
|
20
|
+
lines.push(`### ${turn.counsellorName}`);
|
|
21
|
+
lines.push(`*${turn.backend}/${turn.model}*`);
|
|
22
|
+
lines.push("");
|
|
23
|
+
lines.push(turn.content);
|
|
24
|
+
lines.push("");
|
|
25
|
+
}
|
|
26
|
+
lines.push("---");
|
|
27
|
+
lines.push("");
|
|
28
|
+
lines.push(`*Total tokens — input: ${result.totalTokenUsage.input}, output: ${result.totalTokenUsage.output}*`);
|
|
29
|
+
return lines.join("\n");
|
|
30
|
+
}
|
|
31
|
+
export async function writeOutput(result, outputDir, format) {
|
|
32
|
+
await mkdir(outputDir, { recursive: true });
|
|
33
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
34
|
+
const written = [];
|
|
35
|
+
if (format === "md" || format === "both") {
|
|
36
|
+
const mdPath = join(outputDir, `council-${timestamp}.md`);
|
|
37
|
+
await writeFile(mdPath, toMarkdown(result), "utf-8");
|
|
38
|
+
written.push(mdPath);
|
|
39
|
+
}
|
|
40
|
+
if (format === "json" || format === "both") {
|
|
41
|
+
const jsonPath = join(outputDir, `council-${timestamp}.json`);
|
|
42
|
+
await writeFile(jsonPath, JSON.stringify(result, null, 2), "utf-8");
|
|
43
|
+
written.push(jsonPath);
|
|
44
|
+
}
|
|
45
|
+
return written;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=output-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-formatter.js","sourceRoot":"","sources":["../../src/core/output-formatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ConversationResult, ConversationTurn, CouncilConfig } from "../types.js";
|
|
2
|
+
export interface SecretaryResult {
|
|
3
|
+
text: string;
|
|
4
|
+
diagram?: unknown[];
|
|
5
|
+
}
|
|
6
|
+
export declare function runSecretary({ result, config, onChunk, signal, }: {
|
|
7
|
+
result: ConversationResult;
|
|
8
|
+
config: CouncilConfig;
|
|
9
|
+
onChunk?: (delta: string) => void;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}): Promise<SecretaryResult>;
|
|
12
|
+
export declare function runInterimSummary({ result, roundNumber, config, onChunk, signal, }: {
|
|
13
|
+
result: ConversationResult;
|
|
14
|
+
roundNumber: number;
|
|
15
|
+
config: CouncilConfig;
|
|
16
|
+
onChunk?: (delta: string) => void;
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
}): Promise<string>;
|
|
19
|
+
export declare function generateTitle({ topic, firstRoundTurns, config, }: {
|
|
20
|
+
topic: string;
|
|
21
|
+
firstRoundTurns: ConversationTurn[];
|
|
22
|
+
config: CouncilConfig;
|
|
23
|
+
}): Promise<string>;
|