cograph 0.1.7 → 0.1.9
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
CHANGED
|
@@ -36,7 +36,7 @@ async function confirm(prompt) {
|
|
|
36
36
|
}
|
|
37
37
|
var program = new Command();
|
|
38
38
|
program.name("cograph").description("Cograph Knowledge Graph CLI").version("0.1.7").action(async () => {
|
|
39
|
-
const { runShell } = await import("./shell-
|
|
39
|
+
const { runShell } = await import("./shell-ZNCZ3O2J.js");
|
|
40
40
|
await runShell({});
|
|
41
41
|
});
|
|
42
42
|
var kg = program.command("kg").description("Manage knowledge graphs");
|
|
@@ -286,7 +286,7 @@ program.command("login").description("Sign in via your browser and save an API k
|
|
|
286
286
|
await runLogin();
|
|
287
287
|
});
|
|
288
288
|
program.command("shell").description("Start an interactive REPL").option("--kg <name>", "Knowledge graph to use").action(async (opts) => {
|
|
289
|
-
const { runShell } = await import("./shell-
|
|
289
|
+
const { runShell } = await import("./shell-ZNCZ3O2J.js");
|
|
290
290
|
await runShell({ kg: opts.kg });
|
|
291
291
|
});
|
|
292
292
|
program.parseAsync(process.argv).catch((err) => {
|
|
@@ -19,17 +19,34 @@ var RESET = "\x1B[0m";
|
|
|
19
19
|
function fmtNum(n) {
|
|
20
20
|
return n.toLocaleString("en-US");
|
|
21
21
|
}
|
|
22
|
+
function canRenderBlockArt() {
|
|
23
|
+
const force = process.env.COGRAPH_BANNER;
|
|
24
|
+
if (force === "on") return true;
|
|
25
|
+
if (force === "off") return false;
|
|
26
|
+
if (!process.stdout.isTTY) return false;
|
|
27
|
+
if (process.env.TERM_PROGRAM === "Apple_Terminal") return false;
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
22
30
|
function showBanner() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
if (canRenderBlockArt()) {
|
|
32
|
+
const lines = [
|
|
33
|
+
"",
|
|
34
|
+
`${CYAN} \u2591\u2588\u2580\u2580\u2591\u2588\u2580\u2588\u2591\u2588\u2580\u2580\u2591\u2588\u2580\u2584\u2591\u2588\u2580\u2588\u2591\u2588\u2580\u2588\u2591\u2588\u2591\u2588${RESET}`,
|
|
35
|
+
`${CYAN} \u2591\u2588\u2591\u2591\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2580\u2584\u2591\u2588\u2580\u2588\u2591\u2588\u2580\u2580\u2591\u2588\u2580\u2588${RESET}`,
|
|
36
|
+
`${CYAN} \u2591\u2580\u2580\u2580\u2591\u2580\u2580\u2580\u2591\u2580\u2580\u2580\u2591\u2580\u2591\u2580\u2591\u2580\u2591\u2580\u2591\u2580\u2591\u2591\u2591\u2580\u2591\u2580${RESET}`,
|
|
37
|
+
"",
|
|
38
|
+
`${DIM} The object graph for AI agents${RESET}`,
|
|
39
|
+
""
|
|
40
|
+
];
|
|
41
|
+
for (const l of lines) stdout.write(l + "\n");
|
|
42
|
+
} else {
|
|
43
|
+
stdout.write(`
|
|
44
|
+
${CYAN_BOLD}cograph${RESET}
|
|
45
|
+
`);
|
|
46
|
+
stdout.write(` ${DIM}The object graph for AI agents${RESET}
|
|
47
|
+
|
|
48
|
+
`);
|
|
49
|
+
}
|
|
33
50
|
showCommands();
|
|
34
51
|
}
|
|
35
52
|
function showCommands() {
|
|
@@ -250,6 +267,20 @@ function splitArgs(s) {
|
|
|
250
267
|
}
|
|
251
268
|
async function runShell(opts) {
|
|
252
269
|
let client = new Client();
|
|
270
|
+
if (!client.apiKey) {
|
|
271
|
+
stdout.write(
|
|
272
|
+
`
|
|
273
|
+
${DIM}Not signed in \u2014 opening your browser to log in...${RESET}
|
|
274
|
+
`
|
|
275
|
+
);
|
|
276
|
+
const { runLogin } = await import("./login-Z3IUOAOB.js");
|
|
277
|
+
await runLogin();
|
|
278
|
+
client = new Client();
|
|
279
|
+
if (!client.apiKey) {
|
|
280
|
+
printError("Login did not produce an API key. Aborting.");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
253
284
|
const rl = readline.createInterface({
|
|
254
285
|
input: stdin,
|
|
255
286
|
output: stdout,
|
|
@@ -345,4 +376,4 @@ async function runShell(opts) {
|
|
|
345
376
|
export {
|
|
346
377
|
runShell
|
|
347
378
|
};
|
|
348
|
-
//# sourceMappingURL=shell-
|
|
379
|
+
//# sourceMappingURL=shell-ZNCZ3O2J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shell.ts"],"sourcesContent":["import * as readline from \"node:readline\";\nimport { stdin, stdout } from \"node:process\";\nimport { Client, CographError } from \"./client.js\";\n\nconst CYAN = \"\\x1b[36m\";\nconst CYAN_BOLD = \"\\x1b[1;36m\";\nconst DIM = \"\\x1b[2m\";\nconst RED = \"\\x1b[31m\";\nconst GREEN = \"\\x1b[32m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\nconst RESET = \"\\x1b[0m\";\n\nfunction fmtNum(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n\nfunction canRenderBlockArt(): boolean {\n // Apple_Terminal (macOS Terminal.app) treats the block-shade chars (▀█░)\n // we use in the banner as East Asian Ambiguous Width = 2 cells, so each\n // 28-char banner row renders as ~56 cells and wraps mid-letter. iTerm,\n // WezTerm, Kitty, VS Code, Cursor, etc. all treat them as 1 cell and\n // render the art correctly. Skip the banner on Apple_Terminal and show\n // a plain header instead. Force on/off via COGRAPH_BANNER=on|off.\n const force = process.env.COGRAPH_BANNER;\n if (force === \"on\") return true;\n if (force === \"off\") return false;\n if (!process.stdout.isTTY) return false;\n if (process.env.TERM_PROGRAM === \"Apple_Terminal\") return false;\n return true;\n}\n\nfunction showBanner(): void {\n if (canRenderBlockArt()) {\n const lines = [\n \"\",\n `${CYAN} ░█▀▀░█▀█░█▀▀░█▀▄░█▀█░█▀█░█░█${RESET}`,\n `${CYAN} ░█░░░█░█░█░█░█▀▄░█▀█░█▀▀░█▀█${RESET}`,\n `${CYAN} ░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀░▀░▀░░░▀░▀${RESET}`,\n \"\",\n `${DIM} The object graph for AI agents${RESET}`,\n \"\",\n ];\n for (const l of lines) stdout.write(l + \"\\n\");\n } else {\n stdout.write(`\\n ${CYAN_BOLD}cograph${RESET}\\n`);\n stdout.write(` ${DIM}The object graph for AI agents${RESET}\\n\\n`);\n }\n showCommands();\n}\n\nfunction showCommands(): void {\n const rows: Array<[string, string]> = [\n [\"/ingest <file> ...\", \"Ingest a CSV/JSON/text file\"],\n [\"/ask <question>\", \"Ask in natural language\"],\n [\"/login\", \"Re-authenticate (browser)\"],\n [\"/status\", \"Show graph stats\"],\n [\"/reset\", \"Clear the current KG\"],\n [\"/help\", \"Show this command list\"],\n [\"/quit\", \"Exit\"],\n ];\n const colWidth = Math.max(...rows.map((r) => r[0].length));\n for (const [cmd, desc] of rows) {\n const pad = \" \".repeat(colWidth - cmd.length);\n stdout.write(` ${CYAN_BOLD}${cmd}${RESET}${pad} ${DIM}${desc}${RESET}\\n`);\n }\n stdout.write(\"\\n\");\n}\n\nfunction printError(msg: string): void {\n stdout.write(` ${RED}✗${RESET} ${msg}\\n`);\n}\n\ninterface KgInfo {\n name: string;\n triple_count: number;\n}\n\nasync function fetchKg(client: Client, name: string): Promise<KgInfo | null> {\n try {\n const kgs = await client.listKgs();\n const found = kgs.find((k) => (k as { name?: string }).name === name);\n if (!found) return null;\n const tc = (found as { triple_count?: number }).triple_count ?? 0;\n return { name, triple_count: typeof tc === \"number\" ? tc : 0 };\n } catch {\n return null;\n }\n}\n\nfunction ask(rl: readline.Interface, prompt: string): Promise<string> {\n return new Promise((resolve) => {\n rl.question(prompt, (answer) => resolve(answer));\n });\n}\n\nasync function selectKg(\n client: Client,\n rl: readline.Interface,\n): Promise<string | null> {\n let kgs: Array<Record<string, unknown>> = [];\n try {\n kgs = await client.listKgs();\n } catch (err) {\n printError(\n `Could not list knowledge graphs: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n\n if (kgs.length === 0) {\n stdout.write(\n ` ${DIM}No knowledge graphs found. Enter a name to create your first KG.${RESET}\\n`,\n );\n const name = (await ask(rl, \" KG name: \")).trim();\n if (!name) return null;\n // Persist immediately. Without this, the name only existed as a local\n // string until the user ran /ingest, so quitting before ingesting lost\n // the KG entirely — and the next shell session showed \"No KGs found\"\n // again.\n try {\n await client.createKg(name);\n stdout.write(` ${GREEN}✓${RESET} Created ${BOLD}${name}${RESET}\\n`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // 409 / \"already exists\" is fine — someone created it between listKgs\n // and now, or the user retried. Anything else is a real failure.\n if (!/already exists|409/i.test(msg)) {\n printError(`Could not create knowledge graph: ${msg}`);\n return null;\n }\n }\n return name;\n }\n\n if (kgs.length === 1) {\n const only = (kgs[0] as { name?: string }).name;\n if (only) {\n stdout.write(` ${DIM}Using only available KG: ${BOLD}${only}${RESET}\\n`);\n return only;\n }\n }\n\n stdout.write(` ${BOLD}Available knowledge graphs:${RESET}\\n`);\n kgs.forEach((kg, i) => {\n const n = (kg as { name?: string }).name ?? \"?\";\n const tc = (kg as { triple_count?: number }).triple_count ?? 0;\n stdout.write(` ${CYAN}${i + 1}${RESET}. ${n} ${DIM}(${fmtNum(tc)} triples)${RESET}\\n`);\n });\n const pick = (await ask(rl, \" Select KG [1]: \")).trim() || \"1\";\n const idx = Number.parseInt(pick, 10);\n if (Number.isFinite(idx) && idx >= 1 && idx <= kgs.length) {\n const name = (kgs[idx - 1] as { name?: string }).name;\n if (name) return name;\n }\n // Allow typing a name directly\n if (pick && !/^\\d+$/.test(pick)) return pick;\n printError(\"Invalid selection.\");\n return null;\n}\n\nasync function cmdIngest(\n client: Client,\n kg: string,\n args: string[],\n): Promise<void> {\n if (args.length === 0) {\n stdout.write(` ${YELLOW}Usage:${RESET} /ingest <file> [<file>...]\\n`);\n return;\n }\n for (const file of args) {\n stdout.write(` ${DIM}${file}${RESET}\\n`);\n try {\n const result = await client.ingest(file, { kg });\n const ents =\n (result as { entities_resolved?: number }).entities_resolved ?? 0;\n const trip =\n (result as { triples_inserted?: number }).triples_inserted ?? 0;\n stdout.write(\n ` ${GREEN}✓${RESET} ${fmtNum(ents)} entities · ${fmtNum(trip)} triples\\n`,\n );\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n }\n }\n}\n\nasync function cmdAsk(\n client: Client,\n kg: string,\n question: string,\n): Promise<void> {\n const q = question.trim();\n if (!q) {\n stdout.write(` ${YELLOW}Usage:${RESET} /ask <your question>\\n`);\n return;\n }\n try {\n const result = await client.ask(q, { kg });\n const answer =\n (result as { narrative_answer?: string }).narrative_answer ||\n (result as { answer?: string }).answer ||\n \"No answer generated.\";\n stdout.write(\"\\n\");\n stdout.write(` ${answer}\\n`);\n stdout.write(\"\\n\");\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n }\n}\n\nasync function cmdStatus(client: Client, kg: string): Promise<void> {\n try {\n const info = await fetchKg(client, kg);\n stdout.write(\"\\n\");\n stdout.write(` ${BOLD}KG${RESET} ${kg}\\n`);\n if (info) {\n stdout.write(` ${BOLD}Triples${RESET} ${fmtNum(info.triple_count)}\\n`);\n } else {\n stdout.write(` ${BOLD}Triples${RESET} ${DIM}(empty)${RESET}\\n`);\n }\n try {\n const types = await client.ontologyTypes();\n const names = types\n .map((t) => (t as { name?: string }).name)\n .filter((n): n is string => Boolean(n));\n if (names.length > 0) {\n stdout.write(` ${BOLD}Types${RESET} ${names.join(\", \")}\\n`);\n } else {\n stdout.write(` ${BOLD}Types${RESET} ${DIM}(none)${RESET}\\n`);\n }\n } catch (err) {\n printError(\n `Could not list ontology types: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n stdout.write(\"\\n\");\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n }\n}\n\nasync function cmdReset(\n client: Client,\n kg: string,\n rl: readline.Interface,\n): Promise<boolean> {\n const confirm = (\n await ask(rl, ` ${YELLOW}Delete KG \"${kg}\"?${RESET} [y/N]: `)\n )\n .trim()\n .toLowerCase();\n if (confirm !== \"y\" && confirm !== \"yes\") {\n stdout.write(` ${DIM}Cancelled.${RESET}\\n`);\n return false;\n }\n try {\n await client.deleteKg(kg);\n stdout.write(` ${GREEN}✓${RESET} Graph cleared.\\n`);\n return true;\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n return false;\n }\n}\n\nfunction makePrompt(triples: number): string {\n if (triples > 0) {\n return ` ${CYAN_BOLD}cograph${RESET} ${DIM}[${fmtNum(triples)}]${RESET} ${CYAN_BOLD}▸${RESET} `;\n }\n return ` ${CYAN_BOLD}cograph ▸${RESET} `;\n}\n\n/**\n * Split a command-line style argument string. Supports double-quoted args.\n */\nfunction splitArgs(s: string): string[] {\n const out: string[] = [];\n let cur = \"\";\n let inQ = false;\n for (let i = 0; i < s.length; i++) {\n const c = s[i];\n if (inQ) {\n if (c === '\"') inQ = false;\n else cur += c;\n } else {\n if (c === '\"') inQ = true;\n else if (c === \" \" || c === \"\\t\") {\n if (cur) {\n out.push(cur);\n cur = \"\";\n }\n } else cur += c;\n }\n }\n if (cur) out.push(cur);\n return out;\n}\n\nexport async function runShell(opts: { kg?: string }): Promise<void> {\n // `let` rather than `const` so /login can swap in a fresh Client after\n // ~/.cograph/config.json is rewritten with the new key.\n let client = new Client();\n\n // First-run ergonomics: if no API key is configured (no env var, no\n // ~/.cograph/config.json), trigger the login flow before opening the\n // shell. Saves the friend from having to know to run `cograph login`\n // first — they just run `npx cograph` and the browser pops.\n if (!client.apiKey) {\n stdout.write(\n `\\n ${DIM}Not signed in — opening your browser to log in...${RESET}\\n`,\n );\n const { runLogin } = await import(\"./login.js\");\n await runLogin();\n client = new Client();\n if (!client.apiKey) {\n // runLogin already exits the process on hard failures, so reaching\n // here means it returned without writing a key (rare). Bail rather\n // than continue into a broken shell.\n printError(\"Login did not produce an API key. Aborting.\");\n return;\n }\n }\n const rl = readline.createInterface({\n input: stdin,\n output: stdout,\n terminal: true,\n });\n\n showBanner();\n\n let kg = opts.kg;\n if (!kg) {\n const picked = await selectKg(client, rl);\n if (!picked) {\n rl.close();\n return;\n }\n kg = picked;\n }\n\n let triples = 0;\n const info = await fetchKg(client, kg);\n if (info && info.triple_count > 0) {\n triples = info.triple_count;\n stdout.write(\n ` ${DIM}Connected to${RESET} ${BOLD}${kg}${RESET}${DIM}: ${fmtNum(triples)} triples${RESET}\\n\\n`,\n );\n } else {\n stdout.write(\n ` ${DIM}Connected — ${kg} is empty (use /ingest to add data)${RESET}\\n\\n`,\n );\n }\n\n const refresh = async (): Promise<void> => {\n const fresh = await fetchKg(client, kg!);\n triples = fresh?.triple_count ?? 0;\n };\n\n let running = true;\n rl.on(\"close\", () => {\n running = false;\n });\n\n while (running) {\n let line: string;\n try {\n line = (await ask(rl, makePrompt(triples))).trim();\n } catch {\n break;\n }\n if (!running) break;\n if (!line) continue;\n\n if (line === \"/quit\" || line === \"/exit\" || line === \"/q\") {\n stdout.write(` ${DIM}Bye.${RESET}\\n`);\n break;\n }\n\n if (line === \"/help\") {\n showCommands();\n continue;\n }\n\n try {\n if (line.startsWith(\"/ingest\")) {\n const args = splitArgs(line.slice(\"/ingest\".length).trim());\n await cmdIngest(client, kg, args);\n await refresh();\n } else if (line.startsWith(\"/ask \")) {\n await cmdAsk(client, kg, line.slice(\"/ask \".length));\n } else if (line === \"/ask\") {\n await cmdAsk(client, kg, \"\");\n } else if (line === \"/status\") {\n await cmdStatus(client, kg);\n await refresh();\n } else if (line === \"/reset\") {\n const did = await cmdReset(client, kg, rl);\n if (did) await refresh();\n } else if (line === \"/login\") {\n const { runLogin } = await import(\"./login.js\");\n await runLogin();\n // Pick up the new key from ~/.cograph/config.json for subsequent calls.\n client = new Client();\n await refresh();\n } else if (line.startsWith(\"/\")) {\n stdout.write(\n ` ${YELLOW}Unknown command.${RESET} Try /ingest, /ask, /login, /status, /reset, /help, /quit\\n`,\n );\n } else {\n // Bare line — auto-route to /ask\n await cmdAsk(client, kg, line);\n }\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n }\n }\n\n rl.close();\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shell.ts"],"sourcesContent":["import * as readline from \"node:readline\";\nimport { stdin, stdout } from \"node:process\";\nimport { Client, CographError } from \"./client.js\";\n\nconst CYAN = \"\\x1b[36m\";\nconst CYAN_BOLD = \"\\x1b[1;36m\";\nconst DIM = \"\\x1b[2m\";\nconst RED = \"\\x1b[31m\";\nconst GREEN = \"\\x1b[32m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\nconst RESET = \"\\x1b[0m\";\n\nfunction fmtNum(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n\nfunction showBanner(): void {\n const lines = [\n \"\",\n `${CYAN} ░█▀▀░█▀█░█▀▀░█▀▄░█▀█░█▀█░█░█${RESET}`,\n `${CYAN} ░█░░░█░█░█░█░█▀▄░█▀█░█▀▀░█▀█${RESET}`,\n `${CYAN} ░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀░▀░▀░░░▀░▀${RESET}`,\n \"\",\n `${DIM} The object graph for AI agents${RESET}`,\n \"\",\n ];\n for (const l of lines) stdout.write(l + \"\\n\");\n showCommands();\n}\n\nfunction showCommands(): void {\n const rows: Array<[string, string]> = [\n [\"/ingest <file> ...\", \"Ingest a CSV/JSON/text file\"],\n [\"/ask <question>\", \"Ask in natural language\"],\n [\"/login\", \"Re-authenticate (browser)\"],\n [\"/status\", \"Show graph stats\"],\n [\"/reset\", \"Clear the current KG\"],\n [\"/help\", \"Show this command list\"],\n [\"/quit\", \"Exit\"],\n ];\n const colWidth = Math.max(...rows.map((r) => r[0].length));\n for (const [cmd, desc] of rows) {\n const pad = \" \".repeat(colWidth - cmd.length);\n stdout.write(` ${CYAN_BOLD}${cmd}${RESET}${pad} ${DIM}${desc}${RESET}\\n`);\n }\n stdout.write(\"\\n\");\n}\n\nfunction printError(msg: string): void {\n stdout.write(` ${RED}✗${RESET} ${msg}\\n`);\n}\n\ninterface KgInfo {\n name: string;\n triple_count: number;\n}\n\nasync function fetchKg(client: Client, name: string): Promise<KgInfo | null> {\n try {\n const kgs = await client.listKgs();\n const found = kgs.find((k) => (k as { name?: string }).name === name);\n if (!found) return null;\n const tc = (found as { triple_count?: number }).triple_count ?? 0;\n return { name, triple_count: typeof tc === \"number\" ? tc : 0 };\n } catch {\n return null;\n }\n}\n\nfunction ask(rl: readline.Interface, prompt: string): Promise<string> {\n return new Promise((resolve) => {\n rl.question(prompt, (answer) => resolve(answer));\n });\n}\n\nasync function selectKg(\n client: Client,\n rl: readline.Interface,\n): Promise<string | null> {\n let kgs: Array<Record<string, unknown>> = [];\n try {\n kgs = await client.listKgs();\n } catch (err) {\n printError(\n `Could not list knowledge graphs: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n\n if (kgs.length === 0) {\n stdout.write(\n ` ${DIM}No knowledge graphs found. Enter a name to create your first KG.${RESET}\\n`,\n );\n const name = (await ask(rl, \" KG name: \")).trim();\n if (!name) return null;\n // Persist immediately. Without this, the name only existed as a local\n // string until the user ran /ingest, so quitting before ingesting lost\n // the KG entirely — and the next shell session showed \"No KGs found\"\n // again.\n try {\n await client.createKg(name);\n stdout.write(` ${GREEN}✓${RESET} Created ${BOLD}${name}${RESET}\\n`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // 409 / \"already exists\" is fine — someone created it between listKgs\n // and now, or the user retried. Anything else is a real failure.\n if (!/already exists|409/i.test(msg)) {\n printError(`Could not create knowledge graph: ${msg}`);\n return null;\n }\n }\n return name;\n }\n\n if (kgs.length === 1) {\n const only = (kgs[0] as { name?: string }).name;\n if (only) {\n stdout.write(` ${DIM}Using only available KG: ${BOLD}${only}${RESET}\\n`);\n return only;\n }\n }\n\n stdout.write(` ${BOLD}Available knowledge graphs:${RESET}\\n`);\n kgs.forEach((kg, i) => {\n const n = (kg as { name?: string }).name ?? \"?\";\n const tc = (kg as { triple_count?: number }).triple_count ?? 0;\n stdout.write(` ${CYAN}${i + 1}${RESET}. ${n} ${DIM}(${fmtNum(tc)} triples)${RESET}\\n`);\n });\n const pick = (await ask(rl, \" Select KG [1]: \")).trim() || \"1\";\n const idx = Number.parseInt(pick, 10);\n if (Number.isFinite(idx) && idx >= 1 && idx <= kgs.length) {\n const name = (kgs[idx - 1] as { name?: string }).name;\n if (name) return name;\n }\n // Allow typing a name directly\n if (pick && !/^\\d+$/.test(pick)) return pick;\n printError(\"Invalid selection.\");\n return null;\n}\n\nasync function cmdIngest(\n client: Client,\n kg: string,\n args: string[],\n): Promise<void> {\n if (args.length === 0) {\n stdout.write(` ${YELLOW}Usage:${RESET} /ingest <file> [<file>...]\\n`);\n return;\n }\n for (const file of args) {\n stdout.write(` ${DIM}${file}${RESET}\\n`);\n try {\n const result = await client.ingest(file, { kg });\n const ents =\n (result as { entities_resolved?: number }).entities_resolved ?? 0;\n const trip =\n (result as { triples_inserted?: number }).triples_inserted ?? 0;\n stdout.write(\n ` ${GREEN}✓${RESET} ${fmtNum(ents)} entities · ${fmtNum(trip)} triples\\n`,\n );\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n }\n }\n}\n\nasync function cmdAsk(\n client: Client,\n kg: string,\n question: string,\n): Promise<void> {\n const q = question.trim();\n if (!q) {\n stdout.write(` ${YELLOW}Usage:${RESET} /ask <your question>\\n`);\n return;\n }\n try {\n const result = await client.ask(q, { kg });\n const answer =\n (result as { narrative_answer?: string }).narrative_answer ||\n (result as { answer?: string }).answer ||\n \"No answer generated.\";\n stdout.write(\"\\n\");\n stdout.write(` ${answer}\\n`);\n stdout.write(\"\\n\");\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n }\n}\n\nasync function cmdStatus(client: Client, kg: string): Promise<void> {\n try {\n const info = await fetchKg(client, kg);\n stdout.write(\"\\n\");\n stdout.write(` ${BOLD}KG${RESET} ${kg}\\n`);\n if (info) {\n stdout.write(` ${BOLD}Triples${RESET} ${fmtNum(info.triple_count)}\\n`);\n } else {\n stdout.write(` ${BOLD}Triples${RESET} ${DIM}(empty)${RESET}\\n`);\n }\n try {\n const types = await client.ontologyTypes();\n const names = types\n .map((t) => (t as { name?: string }).name)\n .filter((n): n is string => Boolean(n));\n if (names.length > 0) {\n stdout.write(` ${BOLD}Types${RESET} ${names.join(\", \")}\\n`);\n } else {\n stdout.write(` ${BOLD}Types${RESET} ${DIM}(none)${RESET}\\n`);\n }\n } catch (err) {\n printError(\n `Could not list ontology types: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n stdout.write(\"\\n\");\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n }\n}\n\nasync function cmdReset(\n client: Client,\n kg: string,\n rl: readline.Interface,\n): Promise<boolean> {\n const confirm = (\n await ask(rl, ` ${YELLOW}Delete KG \"${kg}\"?${RESET} [y/N]: `)\n )\n .trim()\n .toLowerCase();\n if (confirm !== \"y\" && confirm !== \"yes\") {\n stdout.write(` ${DIM}Cancelled.${RESET}\\n`);\n return false;\n }\n try {\n await client.deleteKg(kg);\n stdout.write(` ${GREEN}✓${RESET} Graph cleared.\\n`);\n return true;\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n return false;\n }\n}\n\nfunction makePrompt(triples: number): string {\n if (triples > 0) {\n return ` ${CYAN_BOLD}cograph${RESET} ${DIM}[${fmtNum(triples)}]${RESET} ${CYAN_BOLD}▸${RESET} `;\n }\n return ` ${CYAN_BOLD}cograph ▸${RESET} `;\n}\n\n/**\n * Split a command-line style argument string. Supports double-quoted args.\n */\nfunction splitArgs(s: string): string[] {\n const out: string[] = [];\n let cur = \"\";\n let inQ = false;\n for (let i = 0; i < s.length; i++) {\n const c = s[i];\n if (inQ) {\n if (c === '\"') inQ = false;\n else cur += c;\n } else {\n if (c === '\"') inQ = true;\n else if (c === \" \" || c === \"\\t\") {\n if (cur) {\n out.push(cur);\n cur = \"\";\n }\n } else cur += c;\n }\n }\n if (cur) out.push(cur);\n return out;\n}\n\nexport async function runShell(opts: { kg?: string }): Promise<void> {\n // `let` rather than `const` so /login can swap in a fresh Client after\n // ~/.cograph/config.json is rewritten with the new key.\n let client = new Client();\n const rl = readline.createInterface({\n input: stdin,\n output: stdout,\n terminal: true,\n });\n\n showBanner();\n\n let kg = opts.kg;\n if (!kg) {\n const picked = await selectKg(client, rl);\n if (!picked) {\n rl.close();\n return;\n }\n kg = picked;\n }\n\n let triples = 0;\n const info = await fetchKg(client, kg);\n if (info && info.triple_count > 0) {\n triples = info.triple_count;\n stdout.write(\n ` ${DIM}Connected to${RESET} ${BOLD}${kg}${RESET}${DIM}: ${fmtNum(triples)} triples${RESET}\\n\\n`,\n );\n } else {\n stdout.write(\n ` ${DIM}Connected — ${kg} is empty (use /ingest to add data)${RESET}\\n\\n`,\n );\n }\n\n const refresh = async (): Promise<void> => {\n const fresh = await fetchKg(client, kg!);\n triples = fresh?.triple_count ?? 0;\n };\n\n let running = true;\n rl.on(\"close\", () => {\n running = false;\n });\n\n while (running) {\n let line: string;\n try {\n line = (await ask(rl, makePrompt(triples))).trim();\n } catch {\n break;\n }\n if (!running) break;\n if (!line) continue;\n\n if (line === \"/quit\" || line === \"/exit\" || line === \"/q\") {\n stdout.write(` ${DIM}Bye.${RESET}\\n`);\n break;\n }\n\n if (line === \"/help\") {\n showCommands();\n continue;\n }\n\n try {\n if (line.startsWith(\"/ingest\")) {\n const args = splitArgs(line.slice(\"/ingest\".length).trim());\n await cmdIngest(client, kg, args);\n await refresh();\n } else if (line.startsWith(\"/ask \")) {\n await cmdAsk(client, kg, line.slice(\"/ask \".length));\n } else if (line === \"/ask\") {\n await cmdAsk(client, kg, \"\");\n } else if (line === \"/status\") {\n await cmdStatus(client, kg);\n await refresh();\n } else if (line === \"/reset\") {\n const did = await cmdReset(client, kg, rl);\n if (did) await refresh();\n } else if (line === \"/login\") {\n const { runLogin } = await import(\"./login.js\");\n await runLogin();\n // Pick up the new key from ~/.cograph/config.json for subsequent calls.\n client = new Client();\n await refresh();\n } else if (line.startsWith(\"/\")) {\n stdout.write(\n ` ${YELLOW}Unknown command.${RESET} Try /ingest, /ask, /login, /status, /reset, /help, /quit\\n`,\n );\n } else {\n // Bare line — auto-route to /ask\n await cmdAsk(client, kg, line);\n }\n } catch (err) {\n if (err instanceof CographError) printError(err.message);\n else printError(err instanceof Error ? err.message : String(err));\n }\n }\n\n rl.close();\n}\n"],"mappings":"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","names":[]}
|