@stjbrown/agent-knowledge 0.1.0-beta.5 → 0.1.0-beta.7

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.
@@ -5,7 +5,7 @@ import {
5
5
  bootJanet,
6
6
  messageText,
7
7
  messageToolNames
8
- } from "./chunk-EBMACGJV.js";
8
+ } from "./chunk-GR2RFQE4.js";
9
9
 
10
10
  // src/headless/run.ts
11
11
  async function runHeadless(opts) {
@@ -124,4 +124,4 @@ Janet hit a snag: ${err.message}
124
124
  export {
125
125
  runHeadless
126
126
  };
127
- //# sourceMappingURL=chunk-GWV4DABI.js.map
127
+ //# sourceMappingURL=chunk-LQOMGCIP.js.map
@@ -6,7 +6,7 @@ import {
6
6
  hasAwsCredentials,
7
7
  hasGoogleCredentials,
8
8
  loadSettings
9
- } from "./chunk-EBMACGJV.js";
9
+ } from "./chunk-GR2RFQE4.js";
10
10
 
11
11
  // src/onboarding/providers.ts
12
12
  var CODEX_MODELS = [
@@ -91,4 +91,4 @@ export {
91
91
  normalizeModelSelection,
92
92
  availableModels
93
93
  };
94
- //# sourceMappingURL=chunk-PUTDZMUI.js.map
94
+ //# sourceMappingURL=chunk-PRZR6RDP.js.map
package/dist/headless.js CHANGED
@@ -3,8 +3,8 @@ import { createRequire as __janetCreateRequire } from "node:module";
3
3
  const require = __janetCreateRequire(import.meta.url);
4
4
  import {
5
5
  runHeadless
6
- } from "./chunk-GWV4DABI.js";
7
- import "./chunk-EBMACGJV.js";
6
+ } from "./chunk-LQOMGCIP.js";
7
+ import "./chunk-GR2RFQE4.js";
8
8
  export {
9
9
  runHeadless
10
10
  };
package/dist/index.js CHANGED
@@ -3,11 +3,11 @@ import { createRequire as __janetCreateRequire } from "node:module";
3
3
  const require = __janetCreateRequire(import.meta.url);
4
4
  import {
5
5
  runHeadless
6
- } from "./chunk-GWV4DABI.js";
6
+ } from "./chunk-LQOMGCIP.js";
7
7
  import {
8
8
  bootJanet,
9
9
  resolveProjectPaths
10
- } from "./chunk-EBMACGJV.js";
10
+ } from "./chunk-GR2RFQE4.js";
11
11
  export {
12
12
  bootJanet,
13
13
  resolveProjectPaths,
package/dist/main.js CHANGED
@@ -3,17 +3,17 @@ import { createRequire as __janetCreateRequire } from "node:module";
3
3
  const require = __janetCreateRequire(import.meta.url);
4
4
  import {
5
5
  runHeadless
6
- } from "./chunk-GWV4DABI.js";
6
+ } from "./chunk-LQOMGCIP.js";
7
7
  import {
8
8
  availableModels,
9
9
  normalizeModelSelection
10
- } from "./chunk-PUTDZMUI.js";
10
+ } from "./chunk-PRZR6RDP.js";
11
11
  import {
12
12
  GREETING,
13
13
  loadSettings,
14
14
  packageVersion,
15
15
  resolveProjectPaths
16
- } from "./chunk-EBMACGJV.js";
16
+ } from "./chunk-GR2RFQE4.js";
17
17
 
18
18
  // src/main.ts
19
19
  import { existsSync as existsSync2 } from "fs";
@@ -299,7 +299,7 @@ async function main(argv) {
299
299
  const sub = parsed.subcommand;
300
300
  if (!sub) {
301
301
  if (!headless) {
302
- const { runTui } = await import("./tui-6F3IBI3J.js");
302
+ const { runTui } = await import("./tui-QMMAC7W7.js");
303
303
  if (modelId && !process.env["JANET_MODEL"]) process.env["JANET_MODEL"] = modelId;
304
304
  return runTui({ dir, bundle: bundleOverride, threadId });
305
305
  }
@@ -4,7 +4,7 @@ const require = __janetCreateRequire(import.meta.url);
4
4
  import {
5
5
  availableModels,
6
6
  normalizeModelSelection
7
- } from "./chunk-PUTDZMUI.js";
7
+ } from "./chunk-PRZR6RDP.js";
8
8
  import {
9
9
  GREETING,
10
10
  bootJanet,
@@ -17,7 +17,7 @@ import {
17
17
  rememberObservability,
18
18
  resolveObservabilityConfig,
19
19
  safeObservabilityEndpoint
20
- } from "./chunk-EBMACGJV.js";
20
+ } from "./chunk-GR2RFQE4.js";
21
21
 
22
22
  // src/tui/index.ts
23
23
  import {
@@ -55,10 +55,14 @@ var WORKSPACE_EXECUTE = /* @__PURE__ */ new Set([
55
55
  "mastra_workspace_get_process_output",
56
56
  "mastra_workspace_kill_process"
57
57
  ]);
58
+ var PDF_READ = /* @__PURE__ */ new Set(["janet_read_pdf", "janet_read_pdf_chunk"]);
59
+ var WEB_READ = /* @__PURE__ */ new Set(["janet_web_fetch", "janet_web_fetch_chunk"]);
58
60
  function toolActivityLabel(toolName) {
59
61
  if (toolName === "skill" || toolName === "skill_read" || toolName === "skill_search") {
60
62
  return "Janet is reading the playbook\u2026";
61
63
  }
64
+ if (PDF_READ.has(toolName)) return "Janet is reading the document\u2026";
65
+ if (WEB_READ.has(toolName)) return "Janet is reading the page\u2026";
62
66
  if (WORKSPACE_READ.has(toolName)) return "Janet is checking the workspace\u2026";
63
67
  if (WORKSPACE_WRITE.has(toolName)) return "Janet is updating the bundle\u2026";
64
68
  if (WORKSPACE_EXECUTE.has(toolName) || toolName.includes("shell")) {
@@ -989,4 +993,4 @@ Ask me anything in the bundle, or say what to ingest. /help for commands.`
989
993
  export {
990
994
  runTui
991
995
  };
992
- //# sourceMappingURL=tui-6F3IBI3J.js.map
996
+ //# sourceMappingURL=tui-QMMAC7W7.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tui/index.ts","../src/tui/activity.ts","../src/tui/interrupt.ts","../src/tui/traces.ts","../src/tui/theme.ts"],"sourcesContent":["/**\n * Janet's interactive TUI — a minimal pi-tui chat.\n *\n * The transcript renders in strict chronological order: each run of assistant\n * text becomes its own markdown block, and a tool line / question / approval\n * \"closes\" the current block so the next text appears BELOW it (rather than the\n * whole answer streaming at the top while tools pile up underneath).\n *\n * Approvals are governed by the controller's tool-category policy: reads,\n * skills, task bookkeeping, ask_user, and bundle edits never prompt. Execution,\n * MCP, and unknown future tools ask — and the prompt offers \"always allow\" for\n * the session. Questions with options render as an arrow-key SelectList.\n */\nimport {\n Container,\n Editor,\n Loader,\n Markdown,\n ProcessTerminal,\n SelectList,\n Spacer,\n TUI,\n Text,\n matchesKey,\n} from \"@earendil-works/pi-tui\";\nimport type { Component, SelectItem } from \"@earendil-works/pi-tui\";\nimport type { AgentControllerEvent } from \"@mastra/core/agent-controller\";\nimport { bootJanet, type BootOptions } from \"../agent/controller.js\";\nimport { messageText } from \"../headless/format.js\";\nimport { GREETING } from \"../agent/persona.js\";\nimport { getAuthStorage } from \"../gateways/oauth/claude-max.js\";\nimport {\n loadSettings,\n completeOnboarding,\n rememberModel,\n rememberObservability,\n} from \"../onboarding/settings.js\";\nimport { availableModels, normalizeModelSelection } from \"../onboarding/providers.js\";\nimport { resolveObservabilityConfig } from \"../observability/config.js\";\nimport {\n formatObservabilityStatus,\n safeObservabilityEndpoint,\n} from \"../observability/runtime.js\";\nimport type {\n ObservabilityCaptureMode,\n ObservabilitySettings,\n} from \"../observability/types.js\";\nimport { toolActivityLabel, toolErrorLabel } from \"./activity.js\";\nimport { createInterruptController, type InterruptResult } from \"./interrupt.js\";\nimport { formatTraceTree, traceStatus } from \"./traces.js\";\nimport { c, editorTheme, markdownTheme } from \"./theme.js\";\n\n/** OAuth providers janet can log in to. */\nconst OAUTH_PROVIDERS = [\"anthropic\", \"openai-codex\"] as const;\n\nconst HELP_TEXT = `Commands:\n /models Pick a model from a list (arrow keys)\n /model [provider/id] Open the picker, or switch directly by id\n /login <provider> [mode]\n Log in; OpenAI mode is browser or device\n /logout <provider> Remove stored credentials for a provider\n /auth Show which providers are authenticated\n /observability Configure opt-in tracing\n /traces Browse recent local traces\n /cancel Cancel the active run\n /help This help\n /quit Exit (double Ctrl+C also works)\n\nWhile Janet is working, Esc or Ctrl+C cancels the active run.\nAnything else is a message to Janet.`;\n\ninterface PendingApproval {\n toolCallId: string;\n toolName: string;\n}\n\ninterface QuestionOption {\n label: string;\n description?: string;\n}\n\ninterface PendingQuestion {\n toolCallId: string;\n options?: QuestionOption[];\n multi: boolean;\n}\n\n/** The assistant text block currently being streamed (one segment between tools). */\ninterface ActiveMessage {\n id: string;\n committedLen: number;\n comp: Markdown | null;\n lastText: string;\n}\n\n/** Map a typed answer to ask_user resume data (free-text or multi-select). */\nfunction resolveAnswer(q: PendingQuestion, text: string): string | string[] | undefined {\n if (!q.options?.length) return text;\n const opts = q.options;\n const pick = (token: string): string | undefined => {\n const t = token.trim();\n if (!t) return undefined;\n const n = Number(t);\n if (Number.isInteger(n) && n >= 1 && n <= opts.length) return opts[n - 1]!.label;\n const exact = opts.find((o) => o.label.toLowerCase() === t.toLowerCase());\n if (exact) return exact.label;\n return opts.find((o) => o.label.toLowerCase().startsWith(t.toLowerCase()))?.label;\n };\n if (q.multi) {\n const picks = text.split(\",\").map(pick);\n return picks.some((p) => p === undefined) ? undefined : (picks as string[]);\n }\n return pick(text);\n}\n\nexport async function runTui(opts: Omit<BootOptions, \"interactive\">): Promise<number> {\n const { controller, session, paths, herdrDetach, observability } = await bootJanet({\n ...opts,\n interactive: true,\n });\n\n // The interactive approval policy is set deterministically in the controller's\n // initialState (reads/edits/meta never prompt; only execute asks, with an\n // \"always allow\" option) — see INTERACTIVE_RULES in controller.ts.\n\n // Model precedence: an already-persisted per-thread selection, else\n // JANET_MODEL, else the global onboarding default. If none, the first-run\n // wizard runs after the UI is up.\n const persistedModel = process.env[\"JANET_MODEL\"] || loadSettings().defaultModelId;\n const presetModel = persistedModel\n ? normalizeModelSelection(persistedModel, availableModels())\n : undefined;\n if (!session.model.hasSelection() && presetModel) {\n await session.model.switch({ modelId: presetModel });\n }\n\n const terminal = new ProcessTerminal();\n const ui = new TUI(terminal);\n const chat = new Container();\n const status = new Text(\"\", 1, 0);\n const editor = new Editor(ui, editorTheme);\n const loader = new Loader(ui, c.accent, c.dim, \"Janet is thinking…\");\n\n ui.addChild(chat);\n ui.addChild(new Spacer(1));\n ui.addChild(editor);\n ui.addChild(status);\n\n let running = false;\n let loaderMounted = false;\n let pendingApproval: PendingApproval | null = null;\n let pendingQuestion: PendingQuestion | null = null;\n let pendingInput: ((text: string) => void) | null = null;\n let activeSelect: SelectList | null = null;\n let active: ActiveMessage | null = null;\n let cancelRequested = false;\n const activeTools = new Map<string, string>();\n\n const updateStatus = (): void => {\n const model = session.model.hasSelection() ? session.model.get() : \"no model — /model <id>\";\n const tracing = observability.status.enabled\n ? c.dim(` · trace:${observability.status.capture}`)\n : \"\";\n const state =\n pendingInput\n ? \"enter the requested value\"\n : pendingQuestion || activeSelect\n ? \"answer Janet's question\"\n : pendingApproval\n ? \"awaiting approval\"\n : cancelRequested\n ? \"cancelling\"\n : running\n ? \"working · Esc/Ctrl+C cancels\"\n : \"idle\";\n status.setText(\n c.dim(`${paths.projectPath} · `) +\n c.accent(model) +\n c.dim(` · ${state}`) +\n tracing,\n );\n ui.requestRender();\n };\n\n // Keep the spinner (and any focused select) visually last by inserting new\n // content before them.\n const appendToChat = (comp: Component): void => {\n if (loaderMounted) chat.removeChild(loader);\n if (activeSelect) chat.removeChild(activeSelect);\n chat.addChild(comp);\n if (activeSelect) chat.addChild(activeSelect);\n if (loaderMounted) chat.addChild(loader);\n ui.requestRender();\n };\n\n const addLine = (text: string): void => appendToChat(new Text(text, 1, 0));\n\n const setLoader = (on: boolean): void => {\n if (on && !loaderMounted) {\n chat.addChild(loader);\n loader.start();\n loaderMounted = true;\n } else if (!on && loaderMounted) {\n loader.stop();\n chat.removeChild(loader);\n loaderMounted = false;\n }\n ui.requestRender();\n };\n\n // Freeze the current text segment so the next assistant text starts a new\n // block below whatever we're about to insert (a tool line, question, etc.).\n const closeSegment = (): void => {\n if (active) {\n active.committedLen = active.lastText.length;\n active.comp = null;\n }\n };\n\n const answerQuestion = (resumeData: string | string[], echo: string): void => {\n if (activeSelect) {\n chat.removeChild(activeSelect);\n activeSelect = null;\n }\n const q = pendingQuestion;\n pendingQuestion = null;\n ui.setFocus(editor);\n addLine(c.user(`❯ ${echo}`));\n setLoader(true);\n updateStatus();\n if (q) void session.respondToToolSuspension({ toolCallId: q.toolCallId, resumeData });\n };\n\n const onEvent = (event: AgentControllerEvent): void => {\n switch (event.type) {\n case \"agent_start\":\n running = true;\n cancelRequested = false;\n active = null;\n activeTools.clear();\n loader.setMessage(\"Janet is thinking…\");\n setLoader(true);\n updateStatus();\n break;\n case \"message_update\":\n case \"message_end\": {\n if (event.message.role !== \"assistant\") break;\n const text = messageText(event.message);\n if (!text) break;\n if (!active || active.id !== event.message.id) {\n active = { id: event.message.id, committedLen: 0, comp: null, lastText: \"\" };\n }\n active.lastText = text;\n const tail = text.slice(active.committedLen);\n if (!tail) break;\n if (!active.comp) {\n active.comp = new Markdown(tail, 1, 0, markdownTheme);\n appendToChat(active.comp);\n } else {\n active.comp.setText(tail);\n ui.requestRender();\n }\n break;\n }\n case \"tool_start\":\n closeSegment();\n if (event.toolName !== \"ask_user\") {\n activeTools.set(event.toolCallId, event.toolName);\n loader.setMessage(toolActivityLabel(event.toolName));\n }\n break;\n case \"tool_end\":\n activeTools.delete(event.toolCallId);\n loader.setMessage(\n activeTools.size\n ? toolActivityLabel(Array.from(activeTools.values()).at(-1)!)\n : \"Janet is thinking…\",\n );\n if (event.isError) {\n closeSegment();\n addLine(c.warn(` ${toolErrorLabel(event.result)}`));\n }\n break;\n case \"tool_suspended\": {\n closeSegment();\n activeTools.delete(event.toolCallId);\n setLoader(false);\n const payload = event.suspendPayload as {\n question?: string;\n options?: QuestionOption[];\n selectionMode?: string;\n };\n const question = payload?.question ?? `Janet needs input for ${event.toolName}.`;\n const options = payload?.options;\n const multi = payload?.selectionMode === \"multi_select\";\n addLine(c.accentBold(` Janet asks: ${question}`));\n\n if (options?.length && !multi) {\n // Arrow-key selection (↑/↓, enter), like a native picker.\n const items: SelectItem[] = options.map((o) => ({\n value: o.label,\n label: o.label,\n ...(o.description ? { description: o.description } : {}),\n }));\n const select = new SelectList(items, Math.min(items.length, 8), editorTheme.selectList);\n select.onSelect = (item: SelectItem) => answerQuestion(item.value, item.label);\n activeSelect = select;\n pendingQuestion = { toolCallId: event.toolCallId, options, multi: false };\n chat.addChild(select);\n addLine(c.dim(\" Use ↑/↓ and Enter.\"));\n ui.setFocus(select);\n } else {\n pendingQuestion = { toolCallId: event.toolCallId, options, multi };\n if (options?.length) {\n options.forEach((o, i) =>\n addLine(c.accent(` ${i + 1}. `) + o.label + (o.description ? c.dim(` — ${o.description}`) : \"\")),\n );\n addLine(c.dim(\" Reply with numbers or labels, then press Enter.\"));\n } else {\n addLine(c.dim(\" Type your answer, then press Enter.\"));\n }\n }\n updateStatus();\n break;\n }\n case \"tool_approval_required\":\n closeSegment();\n activeTools.delete(event.toolCallId);\n pendingApproval = { toolCallId: event.toolCallId, toolName: event.toolName };\n addLine(\n c.warn(` Janet wants to run ${c.bold(event.toolName)}.`) +\n c.dim(\" y = yes · n = no · a = always allow this kind\"),\n );\n updateStatus();\n break;\n case \"error\": {\n closeSegment();\n const err = event.error as Error & { responseBody?: string };\n addLine(\n c.error(` Error: ${err?.message || \"unknown\"}${err?.responseBody ? ` — ${err.responseBody.slice(0, 200)}` : \"\"}`),\n );\n break;\n }\n case \"model_changed\":\n updateStatus();\n break;\n case \"agent_end\":\n running = false;\n cancelRequested = false;\n activeTools.clear();\n loader.setMessage(\"Janet is thinking…\");\n if (event.reason !== \"suspended\") pendingQuestion = null;\n setLoader(false);\n updateStatus();\n break;\n }\n };\n const unsubscribe = session.subscribe(onEvent);\n let removeInputListener = (): void => {};\n let sigintHandler: (() => void) | undefined;\n\n const shutdown = async (code: number): Promise<never> => {\n removeInputListener();\n if (sigintHandler) process.off(\"SIGINT\", sigintHandler);\n unsubscribe();\n herdrDetach();\n ui.stop();\n await observability.flush().catch(() => {});\n await controller.destroy().catch(() => {});\n process.exit(code);\n };\n\n const notifyInterrupt = (result: Exclude<InterruptResult, \"ignored\">): void => {\n switch (result) {\n case \"cancelled\":\n addLine(c.dim(\" Cancelling the active run…\"));\n break;\n case \"cleared\":\n break;\n case \"exit\":\n break;\n case \"exit-hint\":\n addLine(c.dim(\" Press Ctrl+C again to quit.\"));\n break;\n }\n updateStatus();\n };\n\n const abortActiveRun = (): void => {\n if (cancelRequested) return;\n cancelRequested = true;\n pendingApproval = null;\n pendingQuestion = null;\n activeTools.clear();\n if (activeSelect) {\n chat.removeChild(activeSelect);\n activeSelect = null;\n }\n ui.setFocus(editor);\n loader.setMessage(\"Cancelling…\");\n session.abort();\n };\n\n const interrupts = createInterruptController({\n isRunning: () => running,\n hasInput: () => editor.getText().length > 0,\n abortRun: abortActiveRun,\n clearInput: () => {\n editor.setText(\"\");\n ui.requestRender();\n },\n exit: () => {\n void shutdown(0);\n },\n notify: notifyInterrupt,\n });\n\n // Input listeners run before the focused component, so cancellation works\n // during pickers, approvals, questions, and streamed tool activity.\n removeInputListener = ui.addInputListener((data) => {\n if (matchesKey(data, \"ctrl+c\")) {\n interrupts.handleCtrlC();\n return { consume: true };\n }\n if (matchesKey(data, \"escape\") && running) {\n interrupts.handleEscape();\n return { consume: true };\n }\n return undefined;\n });\n\n // Raw terminals normally deliver Ctrl+C as input. Keep a SIGINT fallback for\n // terminals and supervisors that preserve normal signal handling.\n sigintHandler = () => {\n interrupts.handleCtrlC();\n };\n process.on(\"SIGINT\", sigintHandler);\n\n // Ask the user for one value; the next editor submit resolves it. Used by the\n // OAuth login flow (paste-code / prompts).\n const promptInput = (message: string, placeholder?: string): Promise<string> => {\n addLine(c.accentBold(` ${message}`));\n if (placeholder) addLine(c.dim(` (${placeholder})`));\n return new Promise((resolve) => {\n pendingInput = resolve;\n updateStatus();\n });\n };\n\n // Interactive model picker: an arrow-key list of models from the providers\n // reachable right now. Selecting one switches the session and persists it as\n // the default. Shared by /models, /model (no arg), and first-run onboarding.\n const showModelPicker = (intro?: string): void => {\n const choices = availableModels();\n if (intro) addLine(c.accentBold(intro));\n if (!choices.length) {\n addLine(c.dim(\" No providers are configured yet. Set one up, then try again:\"));\n addLine(c.dim(\" • Vertex AI: gcloud auth application-default login (+ GOOGLE_VERTEX_PROJECT)\"));\n addLine(c.dim(\" • Anthropic: set ANTHROPIC_API_KEY, or /login anthropic\"));\n addLine(c.dim(\" • OpenAI: set OPENAI_API_KEY, or /login openai-codex\"));\n addLine(c.dim(\" • Bedrock: configure AWS credentials\"));\n updateStatus();\n return;\n }\n const current = session.model.hasSelection() ? session.model.get() : null;\n addLine(c.dim(\" ↑/↓ to move, enter to choose:\"));\n const select = new SelectList(\n choices.map((ch) => ({\n value: ch.id,\n label: ch.id === current ? `${ch.label} (current)` : ch.label,\n description: ch.via,\n })),\n Math.min(choices.length, 10),\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n chat.removeChild(select);\n activeSelect = null;\n ui.setFocus(editor);\n void session.model.switch({ modelId: item.value });\n completeOnboarding(item.value, new Date().toISOString());\n addLine(c.accentBold(` ✓ Using ${item.value}.`) + c.dim(\" (saved as your default)\"));\n updateStatus();\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const savedObservabilitySummary = (): string => {\n const saved = loadSettings().observability;\n const resolved = resolveObservabilityConfig(saved, {});\n return formatObservabilityStatus({\n enabled: resolved.enabled,\n capture: resolved.capture,\n sampleRate: resolved.sampleRate,\n destinations: [\n ...(resolved.local.enabled ? [\"local\"] : []),\n ...(resolved.remote\n ? [\n resolved.remote.kind === \"phoenix\"\n ? `phoenix (${safeObservabilityEndpoint(resolved.remote.endpoint)})`\n : `otlp (${safeObservabilityEndpoint(resolved.remote.endpoint)})`,\n ]\n : []),\n ],\n warnings: resolved.warnings,\n });\n };\n\n const persistObservability = (settings: ObservabilitySettings): void => {\n rememberObservability(settings);\n addLine(c.accentBold(\" ✓ Observability settings saved.\"));\n addLine(c.dim(` Saved: ${savedObservabilitySummary()}`));\n addLine(c.dim(\" Restart Janet to apply the new setting.\"));\n updateStatus();\n };\n\n const closeActiveSelect = (select: SelectList): void => {\n chat.removeChild(select);\n if (activeSelect === select) activeSelect = null;\n ui.setFocus(editor);\n };\n\n const confirmFullCapture = (\n base: Omit<ObservabilitySettings, \"capture\">,\n ): void => {\n addLine(\n c.warn(\n \" Full capture includes prompts, responses, and tool payloads. Do not use it with sensitive material.\",\n ),\n );\n const select = new SelectList(\n [\n {\n value: \"no\",\n label: \"Keep metadata-only capture\",\n description: \"Recommended. Content stays out of traces.\",\n },\n {\n value: \"yes\",\n label: \"Enable full capture\",\n description: \"I understand trace content may contain sensitive data.\",\n },\n ],\n 2,\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n closeActiveSelect(select);\n persistObservability({\n ...base,\n capture: item.value === \"yes\" ? \"full\" : \"metadata\",\n });\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const chooseCaptureMode = (\n base: Omit<ObservabilitySettings, \"capture\">,\n ): void => {\n addLine(c.accentBold(\" What may Janet include in traces?\"));\n const select = new SelectList(\n [\n {\n value: \"metadata\",\n label: \"Metadata only\",\n description: \"Timing, tool names, model, tokens, status, and errors.\",\n },\n {\n value: \"full\",\n label: \"Full content\",\n description: \"Also includes prompts, responses, and tool payloads.\",\n },\n ],\n 2,\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n closeActiveSelect(select);\n const capture = item.value as ObservabilityCaptureMode;\n if (capture === \"full\") {\n confirmFullCapture(base);\n } else {\n persistObservability({ ...base, capture });\n }\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const showObservabilityPicker = (): void => {\n if (running) {\n addLine(c.dim(\" Cancel the active run before changing observability settings.\"));\n return;\n }\n addLine(c.accentBold(\" Configure observability\"));\n addLine(c.dim(` Active now: ${formatObservabilityStatus(observability.status)}`));\n addLine(c.dim(\" Tracing is opt-in and changes apply after restart.\"));\n const select = new SelectList(\n [\n {\n value: \"off\",\n label: \"Off\",\n description: \"No spans, trace database, or network export.\",\n },\n {\n value: \"local\",\n label: \"Local trace history\",\n description: \"Store traces in ~/.agent-knowledge/observability.db.\",\n },\n {\n value: \"phoenix\",\n label: \"Phoenix\",\n description: \"Send OTLP traces to http://localhost:6006.\",\n },\n {\n value: \"otlp\",\n label: \"Custom OTLP\",\n description: \"Send OTLP/HTTP protobuf traces to your endpoint.\",\n },\n ],\n 4,\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n closeActiveSelect(select);\n if (item.value === \"off\") {\n persistObservability({\n capture: \"off\",\n sampleRate: 1,\n local: { enabled: false, retentionDays: 7 },\n });\n return;\n }\n if (item.value === \"local\") {\n chooseCaptureMode({\n sampleRate: 1,\n local: { enabled: true, retentionDays: 7 },\n });\n return;\n }\n if (item.value === \"phoenix\") {\n chooseCaptureMode({\n sampleRate: 1,\n local: { enabled: false, retentionDays: 7 },\n remote: {\n kind: \"phoenix\",\n endpoint: \"http://localhost:6006\",\n projectName: \"janet\",\n },\n });\n return;\n }\n void promptInput(\n \"OTLP endpoint (for example, http://localhost:4318):\",\n ).then((endpoint) => {\n try {\n const parsed = new URL(endpoint);\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") throw new Error();\n if (parsed.username || parsed.password || parsed.search || parsed.hash) {\n addLine(\n c.error(\n \" Do not put credentials or query parameters in the saved endpoint. Use OTEL_EXPORTER_OTLP_HEADERS.\",\n ),\n );\n return;\n }\n } catch {\n addLine(c.error(\" Endpoint must be a valid HTTP or HTTPS URL.\"));\n return;\n }\n chooseCaptureMode({\n sampleRate: 1,\n local: { enabled: false, retentionDays: 7 },\n remote: {\n kind: \"otlp\",\n endpoint,\n },\n });\n });\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const showLocalTraces = async (): Promise<void> => {\n if (running) {\n addLine(c.dim(\" Cancel the active run before browsing traces.\"));\n return;\n }\n if (!observability.config.local.enabled) {\n addLine(c.dim(\" Local trace history is not active. Use /observability to enable it.\"));\n return;\n }\n await observability.flush().catch(() => {});\n const store = await observability.storage.getStore(\"observability\");\n if (!store) {\n addLine(c.error(\" Local trace storage is unavailable.\"));\n return;\n }\n const recent = await store.listTraces({\n pagination: { page: 0, perPage: 10 },\n orderBy: { field: \"startedAt\", direction: \"DESC\" },\n });\n if (!recent.spans.length) {\n addLine(c.dim(\" No local traces yet.\"));\n return;\n }\n\n addLine(c.accentBold(\" Recent local traces\"));\n const select = new SelectList(\n recent.spans.map((span) => {\n const state = traceStatus(span);\n const marker = state === \"error\" ? \"✗\" : state === \"running\" ? \"…\" : \"✓\";\n return {\n value: span.traceId,\n label: `${marker} ${span.name}`,\n description: `${span.startedAt.toLocaleString()} · ${span.traceId}`,\n };\n }),\n Math.min(recent.spans.length, 10),\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n closeActiveSelect(select);\n void store.getTrace({ traceId: item.value }).then((trace) => {\n if (!trace) {\n addLine(c.error(` Trace not found: ${item.value}`));\n return;\n }\n addLine(c.accentBold(` Trace ${trace.traceId}`));\n for (const line of formatTraceTree(trace.spans)) {\n addLine(c.dim(` ${line}`));\n }\n }).catch((error: Error) => {\n addLine(c.error(` Could not read trace: ${error.message}`));\n });\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const handleCommand = async (text: string): Promise<void> => {\n const [cmd, ...rest] = text.slice(1).split(/\\s+/);\n switch (cmd) {\n case \"quit\":\n case \"exit\":\n await shutdown(0);\n break;\n case \"help\":\n addLine(c.dim(HELP_TEXT));\n break;\n case \"cancel\":\n if (interrupts.handleEscape() === \"ignored\") {\n addLine(c.dim(\" No active run to cancel.\"));\n }\n break;\n case \"observability\": {\n const action = rest[0]?.trim().toLowerCase();\n if (action === \"status\") {\n addLine(c.dim(` Active: ${formatObservabilityStatus(observability.status)}`));\n addLine(c.dim(` Saved: ${savedObservabilitySummary()}`));\n } else if (action === \"off\") {\n persistObservability({\n capture: \"off\",\n sampleRate: 1,\n local: { enabled: false, retentionDays: 7 },\n });\n } else if (!action) {\n showObservabilityPicker();\n } else {\n addLine(c.dim(\"Usage: /observability [status | off]\"));\n }\n break;\n }\n case \"traces\":\n await showLocalTraces();\n break;\n case \"login\": {\n const providerId = (rest[0] || \"anthropic\").trim();\n if (!(OAUTH_PROVIDERS as readonly string[]).includes(providerId)) {\n addLine(c.dim(`Usage: /login <${OAUTH_PROVIDERS.join(\" | \")}>`));\n break;\n }\n const authMode = rest[1]?.trim();\n if (\n authMode &&\n (providerId !== \"openai-codex\" || ![\"browser\", \"device\"].includes(authMode))\n ) {\n addLine(c.dim(\"Usage: /login openai-codex [browser | device]\"));\n break;\n }\n addLine(c.dim(`Starting ${providerId} login…`));\n try {\n await getAuthStorage().login(providerId, {\n onAuth: (info) => {\n addLine(c.accent(\" Open this URL in your browser to authorize:\"));\n addLine(\" \" + info.url);\n if (info.instructions) addLine(c.dim(\" \" + info.instructions));\n },\n onProgress: (m) => addLine(c.dim(\" \" + m)),\n onManualCodeInput: () => promptInput(\"Paste the code shown after you authorize:\"),\n onPrompt: (p) => promptInput(p.message, p.placeholder),\n ...(authMode ? { authMode } : {}),\n });\n addLine(c.accentBold(` ✓ Logged in to ${providerId}.`));\n updateStatus();\n } catch (err) {\n addLine(c.error(` Login failed: ${(err as Error).message}`));\n } finally {\n // A successful browser callback can win the race with the manual-code\n // prompt. Disarm that abandoned prompt so it cannot consume the next\n // chat message after login completes.\n pendingInput = null;\n updateStatus();\n }\n break;\n }\n case \"logout\": {\n const providerId = rest[0]?.trim();\n if (!providerId) {\n addLine(c.dim(`Usage: /logout <${OAUTH_PROVIDERS.join(\" | \")}>`));\n break;\n }\n const storage = getAuthStorage();\n storage.logout(providerId); // OAuth credential\n storage.remove(`apikey:${providerId}`); // stored API key slot, if any\n addLine(c.dim(`Logged out of ${providerId}.`));\n break;\n }\n case \"auth\": {\n const storage = getAuthStorage();\n storage.reload();\n const providers = storage.list();\n if (!providers.length) {\n addLine(c.dim(\"No stored credentials. Use /login <provider>, or set an API key env var\"));\n addLine(c.dim(\"(ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_VERTEX_PROJECT, AWS_*).\"));\n } else {\n for (const p of providers) {\n const cred = storage.get(p);\n addLine(c.dim(` ${p}: `) + (cred?.type === \"oauth\" ? c.accent(\"OAuth (subscription)\") : \"API key\"));\n }\n }\n break;\n }\n case \"model\": {\n const inputId = rest.join(\" \").trim();\n // No id → open the picker; an explicit id still works for power users.\n if (!inputId) {\n showModelPicker();\n break;\n }\n const id = normalizeModelSelection(inputId, availableModels());\n await session.model.switch({ modelId: id });\n completeOnboarding(id, new Date().toISOString());\n rememberModel(id); // so a hand-typed model shows up in the picker next time\n addLine(c.dim(`Model set to ${id}.`));\n updateStatus();\n break;\n }\n case \"models\":\n showModelPicker();\n break;\n default:\n addLine(c.dim(`Unknown command /${cmd}. Try /help.`));\n }\n };\n\n editor.onSubmit = (raw: string) => {\n const text = raw.trim();\n editor.setText(\"\");\n if (!text) return;\n\n // Feed normal prompt input (messages + slash commands) into the editor's\n // built-in up/down history. Skip transient responses — approvals, question\n // answers, and paste-codes shouldn't clutter recall.\n if (!pendingInput && !pendingApproval && !pendingQuestion) {\n editor.addToHistory(text);\n }\n\n // A requested value (e.g. an OAuth paste-code) consumes the next submit.\n // Don't echo it verbatim — it may be a credential.\n if (pendingInput) {\n const resolve = pendingInput;\n pendingInput = null;\n addLine(c.dim(\" ❯ (value entered)\"));\n updateStatus();\n resolve(text);\n return;\n }\n\n // A typed question (free-text or multi-select) consumes the next submit.\n if (pendingQuestion && !activeSelect) {\n const resumeData = resolveAnswer(pendingQuestion, text);\n if (resumeData === undefined) {\n addLine(c.dim(\" Didn't match an option — reply with a number or an exact label.\"));\n return;\n }\n answerQuestion(resumeData, Array.isArray(resumeData) ? resumeData.join(\", \") : resumeData);\n return;\n }\n\n // Pending tool approval: y / n / a (always allow this category).\n if (pendingApproval) {\n const approve = /^y(es)?$/i.test(text);\n const decline = /^n(o)?$/i.test(text);\n const always = /^a(lways)?$/i.test(text);\n if (approve || decline || always) {\n const { toolCallId } = pendingApproval;\n pendingApproval = null;\n addLine(c.dim(always ? \" ✓ always allowed\" : approve ? \" ✓ approved\" : \" ✗ declined\"));\n updateStatus();\n void session.respondToToolApproval({\n decision: always ? \"always_allow_category\" : approve ? \"approve\" : \"decline\",\n toolCallId,\n });\n return;\n }\n addLine(c.dim(\" Answer y (yes), n (no), or a (always allow) first.\"));\n return;\n }\n\n if (text.startsWith(\"/\")) {\n void handleCommand(text);\n return;\n }\n\n addLine(c.user(`❯ ${text}`));\n if (!session.model.hasSelection()) {\n showModelPicker(\" Pick a model first:\");\n return;\n }\n void session.sendMessage({\n content: text,\n tracingOptions: observability.tracingOptionsForTurn({\n interactive: true,\n operation: \"chat\",\n resourceId: paths.resourceId,\n threadId: session.thread.getId() ?? undefined,\n }),\n }).catch((err: Error) => {\n running = false;\n setLoader(false);\n addLine(c.error(` ✗ ${err.message}`));\n updateStatus();\n });\n };\n\n addLine(c.accentBold(GREETING));\n addLine(\n c.dim(\n `Knowledge bundle: ${paths.bundlePath}\\n` +\n `Ask me anything in the bundle, or say what to ingest. /help for commands.`,\n ),\n );\n for (const warning of observability.status.warnings) {\n addLine(c.warn(`Observability: ${warning}`));\n }\n updateStatus();\n ui.start();\n ui.setFocus(editor);\n ui.requestRender();\n\n // First run (no model configured): open the picker to get set up.\n if (!session.model.hasSelection()) showModelPicker(\" Let's pick a model to get you started.\");\n\n // The TUI owns the process from here; exit happens via shutdown().\n return await new Promise<number>(() => {});\n}\n","const WORKSPACE_READ = new Set([\n \"mastra_workspace_file_stat\",\n \"mastra_workspace_grep\",\n \"mastra_workspace_lsp_inspect\",\n \"mastra_workspace_list_files\",\n \"mastra_workspace_read_file\",\n \"mastra_workspace_search\",\n]);\n\nconst WORKSPACE_WRITE = new Set([\n \"mastra_workspace_ast_edit\",\n \"mastra_workspace_delete\",\n \"mastra_workspace_edit_file\",\n \"mastra_workspace_index\",\n \"mastra_workspace_mkdir\",\n \"mastra_workspace_write_file\",\n]);\n\nconst WORKSPACE_EXECUTE = new Set([\n \"mastra_workspace_execute_command\",\n \"mastra_workspace_get_process_output\",\n \"mastra_workspace_kill_process\",\n]);\n\n/** Friendly transient status for routine tool work. */\nexport function toolActivityLabel(toolName: string): string {\n if (toolName === \"skill\" || toolName === \"skill_read\" || toolName === \"skill_search\") {\n return \"Janet is reading the playbook…\";\n }\n if (WORKSPACE_READ.has(toolName)) return \"Janet is checking the workspace…\";\n if (WORKSPACE_WRITE.has(toolName)) return \"Janet is updating the bundle…\";\n if (WORKSPACE_EXECUTE.has(toolName) || toolName.includes(\"shell\")) {\n return \"Janet is running a check…\";\n }\n return \"Janet is working…\";\n}\n\n/** Turn recoverable workspace guard failures into useful user-facing status. */\nexport function toolErrorLabel(result: unknown): string {\n const detail = String(result);\n const readRequired = detail.match(\n /File \"([^\"]+)\" (?:has not been read|was modified since last read)/,\n );\n if (readRequired) {\n return `Update paused: Janet needs to re-read \"${readRequired[1]}\" first.`;\n }\n return `Tool error: ${detail.slice(0, 140)}`;\n}\n","export type InterruptResult =\n | \"cancelled\"\n | \"cleared\"\n | \"exit\"\n | \"exit-hint\"\n | \"ignored\";\n\nexport interface InterruptActions {\n isRunning(): boolean;\n hasInput(): boolean;\n abortRun(): void;\n clearInput(): void;\n exit(): void;\n notify(result: Exclude<InterruptResult, \"ignored\">): void;\n}\n\nexport interface InterruptController {\n handleCtrlC(): InterruptResult;\n handleEscape(): InterruptResult;\n}\n\n/**\n * Centralize Janet's interrupt behavior so it works independently of whichever\n * TUI component currently owns keyboard focus.\n */\nexport function createInterruptController(\n actions: InterruptActions,\n options: {\n doublePressMs?: number;\n now?: () => number;\n } = {},\n): InterruptController {\n const doublePressMs = options.doublePressMs ?? 800;\n const now = options.now ?? Date.now;\n let lastCtrlC: number | undefined;\n\n const cancelRun = (): InterruptResult => {\n if (!actions.isRunning()) return \"ignored\";\n actions.abortRun();\n actions.notify(\"cancelled\");\n return \"cancelled\";\n };\n\n return {\n handleCtrlC(): InterruptResult {\n const pressedAt = now();\n if (lastCtrlC !== undefined && pressedAt - lastCtrlC < doublePressMs) {\n actions.notify(\"exit\");\n actions.exit();\n return \"exit\";\n }\n lastCtrlC = pressedAt;\n\n const cancelled = cancelRun();\n if (cancelled !== \"ignored\") return cancelled;\n\n if (actions.hasInput()) {\n actions.clearInput();\n actions.notify(\"cleared\");\n return \"cleared\";\n }\n\n actions.notify(\"exit-hint\");\n return \"exit-hint\";\n },\n\n handleEscape(): InterruptResult {\n return cancelRun();\n },\n };\n}\n","export interface TraceSpanSummary {\n spanId: string;\n parentSpanId?: string | null;\n name: string;\n spanType: string;\n startedAt: Date;\n endedAt?: Date | null;\n error?: unknown;\n}\n\nfunction duration(span: TraceSpanSummary): string {\n if (!span.endedAt) return \"running\";\n const elapsed = Math.max(0, span.endedAt.getTime() - span.startedAt.getTime());\n return elapsed >= 1_000 ? `${(elapsed / 1_000).toFixed(1)}s` : `${elapsed}ms`;\n}\n\nexport function traceStatus(span: TraceSpanSummary): \"error\" | \"running\" | \"ok\" {\n if (span.error) return \"error\";\n return span.endedAt ? \"ok\" : \"running\";\n}\n\n/** Render Mastra's flat span records as a compact, content-free tree. */\nexport function formatTraceTree(spans: TraceSpanSummary[]): string[] {\n const byParent = new Map<string | null, TraceSpanSummary[]>();\n const ids = new Set(spans.map((span) => span.spanId));\n for (const span of spans) {\n const parent =\n span.parentSpanId && ids.has(span.parentSpanId) ? span.parentSpanId : null;\n const children = byParent.get(parent) ?? [];\n children.push(span);\n byParent.set(parent, children);\n }\n for (const children of byParent.values()) {\n children.sort((a, b) => a.startedAt.getTime() - b.startedAt.getTime());\n }\n\n const lines: string[] = [];\n const visited = new Set<string>();\n const visit = (span: TraceSpanSummary, depth: number): void => {\n if (visited.has(span.spanId)) return;\n visited.add(span.spanId);\n const status = traceStatus(span);\n const marker = status === \"error\" ? \"✗\" : status === \"running\" ? \"…\" : \"✓\";\n lines.push(\n `${\" \".repeat(depth)}${marker} ${span.name} · ${span.spanType} · ${duration(span)}`,\n );\n for (const child of byParent.get(span.spanId) ?? []) visit(child, depth + 1);\n };\n\n for (const root of byParent.get(null) ?? []) visit(root, 0);\n return lines;\n}\n","import chalk from \"chalk\";\nimport type { EditorTheme } from \"@earendil-works/pi-tui\";\n\n/**\n * Janet's minimal terminal theme. Good Place warm: cyan accents, soft dims.\n * Kept tiny on purpose — no gradients, no branding machinery.\n */\nexport const c = {\n accent: chalk.cyan,\n accentBold: chalk.cyan.bold,\n dim: chalk.dim,\n user: chalk.green,\n error: chalk.red,\n warn: chalk.yellow,\n bold: chalk.bold,\n italic: chalk.italic,\n};\n\nexport const editorTheme: EditorTheme = {\n borderColor: (s: string) => chalk.cyan(s),\n selectList: {\n selectedPrefix: (s: string) => chalk.cyan(s),\n selectedText: (s: string) => chalk.cyan.bold(s),\n description: (s: string) => chalk.dim(s),\n scrollInfo: (s: string) => chalk.dim(s),\n noMatch: (s: string) => chalk.dim(s),\n },\n};\n\nexport const markdownTheme = {\n heading: (s: string) => chalk.cyan.bold(s),\n link: (s: string) => chalk.cyan.underline(s),\n linkUrl: (s: string) => chalk.dim(s),\n code: (s: string) => chalk.yellow(s),\n codeBlock: (s: string) => chalk.yellow(s),\n codeBlockBorder: (s: string) => chalk.dim(s),\n quote: (s: string) => chalk.italic(s),\n quoteBorder: (s: string) => chalk.dim(s),\n hr: (s: string) => chalk.dim(s),\n listBullet: (s: string) => chalk.cyan(s),\n bold: (s: string) => chalk.bold(s),\n italic: (s: string) => chalk.italic(s),\n strikethrough: (s: string) => chalk.strikethrough(s),\n underline: (s: string) => chalk.underline(s),\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/tui/index.ts","../src/tui/activity.ts","../src/tui/interrupt.ts","../src/tui/traces.ts","../src/tui/theme.ts"],"sourcesContent":["/**\n * Janet's interactive TUI — a minimal pi-tui chat.\n *\n * The transcript renders in strict chronological order: each run of assistant\n * text becomes its own markdown block, and a tool line / question / approval\n * \"closes\" the current block so the next text appears BELOW it (rather than the\n * whole answer streaming at the top while tools pile up underneath).\n *\n * Approvals are governed by the controller's tool-category policy: reads,\n * skills, task bookkeeping, ask_user, and bundle edits never prompt. Execution,\n * MCP, and unknown future tools ask — and the prompt offers \"always allow\" for\n * the session. Questions with options render as an arrow-key SelectList.\n */\nimport {\n Container,\n Editor,\n Loader,\n Markdown,\n ProcessTerminal,\n SelectList,\n Spacer,\n TUI,\n Text,\n matchesKey,\n} from \"@earendil-works/pi-tui\";\nimport type { Component, SelectItem } from \"@earendil-works/pi-tui\";\nimport type { AgentControllerEvent } from \"@mastra/core/agent-controller\";\nimport { bootJanet, type BootOptions } from \"../agent/controller.js\";\nimport { messageText } from \"../headless/format.js\";\nimport { GREETING } from \"../agent/persona.js\";\nimport { getAuthStorage } from \"../gateways/oauth/claude-max.js\";\nimport {\n loadSettings,\n completeOnboarding,\n rememberModel,\n rememberObservability,\n} from \"../onboarding/settings.js\";\nimport { availableModels, normalizeModelSelection } from \"../onboarding/providers.js\";\nimport { resolveObservabilityConfig } from \"../observability/config.js\";\nimport {\n formatObservabilityStatus,\n safeObservabilityEndpoint,\n} from \"../observability/runtime.js\";\nimport type {\n ObservabilityCaptureMode,\n ObservabilitySettings,\n} from \"../observability/types.js\";\nimport { toolActivityLabel, toolErrorLabel } from \"./activity.js\";\nimport { createInterruptController, type InterruptResult } from \"./interrupt.js\";\nimport { formatTraceTree, traceStatus } from \"./traces.js\";\nimport { c, editorTheme, markdownTheme } from \"./theme.js\";\n\n/** OAuth providers janet can log in to. */\nconst OAUTH_PROVIDERS = [\"anthropic\", \"openai-codex\"] as const;\n\nconst HELP_TEXT = `Commands:\n /models Pick a model from a list (arrow keys)\n /model [provider/id] Open the picker, or switch directly by id\n /login <provider> [mode]\n Log in; OpenAI mode is browser or device\n /logout <provider> Remove stored credentials for a provider\n /auth Show which providers are authenticated\n /observability Configure opt-in tracing\n /traces Browse recent local traces\n /cancel Cancel the active run\n /help This help\n /quit Exit (double Ctrl+C also works)\n\nWhile Janet is working, Esc or Ctrl+C cancels the active run.\nAnything else is a message to Janet.`;\n\ninterface PendingApproval {\n toolCallId: string;\n toolName: string;\n}\n\ninterface QuestionOption {\n label: string;\n description?: string;\n}\n\ninterface PendingQuestion {\n toolCallId: string;\n options?: QuestionOption[];\n multi: boolean;\n}\n\n/** The assistant text block currently being streamed (one segment between tools). */\ninterface ActiveMessage {\n id: string;\n committedLen: number;\n comp: Markdown | null;\n lastText: string;\n}\n\n/** Map a typed answer to ask_user resume data (free-text or multi-select). */\nfunction resolveAnswer(q: PendingQuestion, text: string): string | string[] | undefined {\n if (!q.options?.length) return text;\n const opts = q.options;\n const pick = (token: string): string | undefined => {\n const t = token.trim();\n if (!t) return undefined;\n const n = Number(t);\n if (Number.isInteger(n) && n >= 1 && n <= opts.length) return opts[n - 1]!.label;\n const exact = opts.find((o) => o.label.toLowerCase() === t.toLowerCase());\n if (exact) return exact.label;\n return opts.find((o) => o.label.toLowerCase().startsWith(t.toLowerCase()))?.label;\n };\n if (q.multi) {\n const picks = text.split(\",\").map(pick);\n return picks.some((p) => p === undefined) ? undefined : (picks as string[]);\n }\n return pick(text);\n}\n\nexport async function runTui(opts: Omit<BootOptions, \"interactive\">): Promise<number> {\n const { controller, session, paths, herdrDetach, observability } = await bootJanet({\n ...opts,\n interactive: true,\n });\n\n // The interactive approval policy is set deterministically in the controller's\n // initialState (reads/edits/meta never prompt; only execute asks, with an\n // \"always allow\" option) — see INTERACTIVE_RULES in controller.ts.\n\n // Model precedence: an already-persisted per-thread selection, else\n // JANET_MODEL, else the global onboarding default. If none, the first-run\n // wizard runs after the UI is up.\n const persistedModel = process.env[\"JANET_MODEL\"] || loadSettings().defaultModelId;\n const presetModel = persistedModel\n ? normalizeModelSelection(persistedModel, availableModels())\n : undefined;\n if (!session.model.hasSelection() && presetModel) {\n await session.model.switch({ modelId: presetModel });\n }\n\n const terminal = new ProcessTerminal();\n const ui = new TUI(terminal);\n const chat = new Container();\n const status = new Text(\"\", 1, 0);\n const editor = new Editor(ui, editorTheme);\n const loader = new Loader(ui, c.accent, c.dim, \"Janet is thinking…\");\n\n ui.addChild(chat);\n ui.addChild(new Spacer(1));\n ui.addChild(editor);\n ui.addChild(status);\n\n let running = false;\n let loaderMounted = false;\n let pendingApproval: PendingApproval | null = null;\n let pendingQuestion: PendingQuestion | null = null;\n let pendingInput: ((text: string) => void) | null = null;\n let activeSelect: SelectList | null = null;\n let active: ActiveMessage | null = null;\n let cancelRequested = false;\n const activeTools = new Map<string, string>();\n\n const updateStatus = (): void => {\n const model = session.model.hasSelection() ? session.model.get() : \"no model — /model <id>\";\n const tracing = observability.status.enabled\n ? c.dim(` · trace:${observability.status.capture}`)\n : \"\";\n const state =\n pendingInput\n ? \"enter the requested value\"\n : pendingQuestion || activeSelect\n ? \"answer Janet's question\"\n : pendingApproval\n ? \"awaiting approval\"\n : cancelRequested\n ? \"cancelling\"\n : running\n ? \"working · Esc/Ctrl+C cancels\"\n : \"idle\";\n status.setText(\n c.dim(`${paths.projectPath} · `) +\n c.accent(model) +\n c.dim(` · ${state}`) +\n tracing,\n );\n ui.requestRender();\n };\n\n // Keep the spinner (and any focused select) visually last by inserting new\n // content before them.\n const appendToChat = (comp: Component): void => {\n if (loaderMounted) chat.removeChild(loader);\n if (activeSelect) chat.removeChild(activeSelect);\n chat.addChild(comp);\n if (activeSelect) chat.addChild(activeSelect);\n if (loaderMounted) chat.addChild(loader);\n ui.requestRender();\n };\n\n const addLine = (text: string): void => appendToChat(new Text(text, 1, 0));\n\n const setLoader = (on: boolean): void => {\n if (on && !loaderMounted) {\n chat.addChild(loader);\n loader.start();\n loaderMounted = true;\n } else if (!on && loaderMounted) {\n loader.stop();\n chat.removeChild(loader);\n loaderMounted = false;\n }\n ui.requestRender();\n };\n\n // Freeze the current text segment so the next assistant text starts a new\n // block below whatever we're about to insert (a tool line, question, etc.).\n const closeSegment = (): void => {\n if (active) {\n active.committedLen = active.lastText.length;\n active.comp = null;\n }\n };\n\n const answerQuestion = (resumeData: string | string[], echo: string): void => {\n if (activeSelect) {\n chat.removeChild(activeSelect);\n activeSelect = null;\n }\n const q = pendingQuestion;\n pendingQuestion = null;\n ui.setFocus(editor);\n addLine(c.user(`❯ ${echo}`));\n setLoader(true);\n updateStatus();\n if (q) void session.respondToToolSuspension({ toolCallId: q.toolCallId, resumeData });\n };\n\n const onEvent = (event: AgentControllerEvent): void => {\n switch (event.type) {\n case \"agent_start\":\n running = true;\n cancelRequested = false;\n active = null;\n activeTools.clear();\n loader.setMessage(\"Janet is thinking…\");\n setLoader(true);\n updateStatus();\n break;\n case \"message_update\":\n case \"message_end\": {\n if (event.message.role !== \"assistant\") break;\n const text = messageText(event.message);\n if (!text) break;\n if (!active || active.id !== event.message.id) {\n active = { id: event.message.id, committedLen: 0, comp: null, lastText: \"\" };\n }\n active.lastText = text;\n const tail = text.slice(active.committedLen);\n if (!tail) break;\n if (!active.comp) {\n active.comp = new Markdown(tail, 1, 0, markdownTheme);\n appendToChat(active.comp);\n } else {\n active.comp.setText(tail);\n ui.requestRender();\n }\n break;\n }\n case \"tool_start\":\n closeSegment();\n if (event.toolName !== \"ask_user\") {\n activeTools.set(event.toolCallId, event.toolName);\n loader.setMessage(toolActivityLabel(event.toolName));\n }\n break;\n case \"tool_end\":\n activeTools.delete(event.toolCallId);\n loader.setMessage(\n activeTools.size\n ? toolActivityLabel(Array.from(activeTools.values()).at(-1)!)\n : \"Janet is thinking…\",\n );\n if (event.isError) {\n closeSegment();\n addLine(c.warn(` ${toolErrorLabel(event.result)}`));\n }\n break;\n case \"tool_suspended\": {\n closeSegment();\n activeTools.delete(event.toolCallId);\n setLoader(false);\n const payload = event.suspendPayload as {\n question?: string;\n options?: QuestionOption[];\n selectionMode?: string;\n };\n const question = payload?.question ?? `Janet needs input for ${event.toolName}.`;\n const options = payload?.options;\n const multi = payload?.selectionMode === \"multi_select\";\n addLine(c.accentBold(` Janet asks: ${question}`));\n\n if (options?.length && !multi) {\n // Arrow-key selection (↑/↓, enter), like a native picker.\n const items: SelectItem[] = options.map((o) => ({\n value: o.label,\n label: o.label,\n ...(o.description ? { description: o.description } : {}),\n }));\n const select = new SelectList(items, Math.min(items.length, 8), editorTheme.selectList);\n select.onSelect = (item: SelectItem) => answerQuestion(item.value, item.label);\n activeSelect = select;\n pendingQuestion = { toolCallId: event.toolCallId, options, multi: false };\n chat.addChild(select);\n addLine(c.dim(\" Use ↑/↓ and Enter.\"));\n ui.setFocus(select);\n } else {\n pendingQuestion = { toolCallId: event.toolCallId, options, multi };\n if (options?.length) {\n options.forEach((o, i) =>\n addLine(c.accent(` ${i + 1}. `) + o.label + (o.description ? c.dim(` — ${o.description}`) : \"\")),\n );\n addLine(c.dim(\" Reply with numbers or labels, then press Enter.\"));\n } else {\n addLine(c.dim(\" Type your answer, then press Enter.\"));\n }\n }\n updateStatus();\n break;\n }\n case \"tool_approval_required\":\n closeSegment();\n activeTools.delete(event.toolCallId);\n pendingApproval = { toolCallId: event.toolCallId, toolName: event.toolName };\n addLine(\n c.warn(` Janet wants to run ${c.bold(event.toolName)}.`) +\n c.dim(\" y = yes · n = no · a = always allow this kind\"),\n );\n updateStatus();\n break;\n case \"error\": {\n closeSegment();\n const err = event.error as Error & { responseBody?: string };\n addLine(\n c.error(` Error: ${err?.message || \"unknown\"}${err?.responseBody ? ` — ${err.responseBody.slice(0, 200)}` : \"\"}`),\n );\n break;\n }\n case \"model_changed\":\n updateStatus();\n break;\n case \"agent_end\":\n running = false;\n cancelRequested = false;\n activeTools.clear();\n loader.setMessage(\"Janet is thinking…\");\n if (event.reason !== \"suspended\") pendingQuestion = null;\n setLoader(false);\n updateStatus();\n break;\n }\n };\n const unsubscribe = session.subscribe(onEvent);\n let removeInputListener = (): void => {};\n let sigintHandler: (() => void) | undefined;\n\n const shutdown = async (code: number): Promise<never> => {\n removeInputListener();\n if (sigintHandler) process.off(\"SIGINT\", sigintHandler);\n unsubscribe();\n herdrDetach();\n ui.stop();\n await observability.flush().catch(() => {});\n await controller.destroy().catch(() => {});\n process.exit(code);\n };\n\n const notifyInterrupt = (result: Exclude<InterruptResult, \"ignored\">): void => {\n switch (result) {\n case \"cancelled\":\n addLine(c.dim(\" Cancelling the active run…\"));\n break;\n case \"cleared\":\n break;\n case \"exit\":\n break;\n case \"exit-hint\":\n addLine(c.dim(\" Press Ctrl+C again to quit.\"));\n break;\n }\n updateStatus();\n };\n\n const abortActiveRun = (): void => {\n if (cancelRequested) return;\n cancelRequested = true;\n pendingApproval = null;\n pendingQuestion = null;\n activeTools.clear();\n if (activeSelect) {\n chat.removeChild(activeSelect);\n activeSelect = null;\n }\n ui.setFocus(editor);\n loader.setMessage(\"Cancelling…\");\n session.abort();\n };\n\n const interrupts = createInterruptController({\n isRunning: () => running,\n hasInput: () => editor.getText().length > 0,\n abortRun: abortActiveRun,\n clearInput: () => {\n editor.setText(\"\");\n ui.requestRender();\n },\n exit: () => {\n void shutdown(0);\n },\n notify: notifyInterrupt,\n });\n\n // Input listeners run before the focused component, so cancellation works\n // during pickers, approvals, questions, and streamed tool activity.\n removeInputListener = ui.addInputListener((data) => {\n if (matchesKey(data, \"ctrl+c\")) {\n interrupts.handleCtrlC();\n return { consume: true };\n }\n if (matchesKey(data, \"escape\") && running) {\n interrupts.handleEscape();\n return { consume: true };\n }\n return undefined;\n });\n\n // Raw terminals normally deliver Ctrl+C as input. Keep a SIGINT fallback for\n // terminals and supervisors that preserve normal signal handling.\n sigintHandler = () => {\n interrupts.handleCtrlC();\n };\n process.on(\"SIGINT\", sigintHandler);\n\n // Ask the user for one value; the next editor submit resolves it. Used by the\n // OAuth login flow (paste-code / prompts).\n const promptInput = (message: string, placeholder?: string): Promise<string> => {\n addLine(c.accentBold(` ${message}`));\n if (placeholder) addLine(c.dim(` (${placeholder})`));\n return new Promise((resolve) => {\n pendingInput = resolve;\n updateStatus();\n });\n };\n\n // Interactive model picker: an arrow-key list of models from the providers\n // reachable right now. Selecting one switches the session and persists it as\n // the default. Shared by /models, /model (no arg), and first-run onboarding.\n const showModelPicker = (intro?: string): void => {\n const choices = availableModels();\n if (intro) addLine(c.accentBold(intro));\n if (!choices.length) {\n addLine(c.dim(\" No providers are configured yet. Set one up, then try again:\"));\n addLine(c.dim(\" • Vertex AI: gcloud auth application-default login (+ GOOGLE_VERTEX_PROJECT)\"));\n addLine(c.dim(\" • Anthropic: set ANTHROPIC_API_KEY, or /login anthropic\"));\n addLine(c.dim(\" • OpenAI: set OPENAI_API_KEY, or /login openai-codex\"));\n addLine(c.dim(\" • Bedrock: configure AWS credentials\"));\n updateStatus();\n return;\n }\n const current = session.model.hasSelection() ? session.model.get() : null;\n addLine(c.dim(\" ↑/↓ to move, enter to choose:\"));\n const select = new SelectList(\n choices.map((ch) => ({\n value: ch.id,\n label: ch.id === current ? `${ch.label} (current)` : ch.label,\n description: ch.via,\n })),\n Math.min(choices.length, 10),\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n chat.removeChild(select);\n activeSelect = null;\n ui.setFocus(editor);\n void session.model.switch({ modelId: item.value });\n completeOnboarding(item.value, new Date().toISOString());\n addLine(c.accentBold(` ✓ Using ${item.value}.`) + c.dim(\" (saved as your default)\"));\n updateStatus();\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const savedObservabilitySummary = (): string => {\n const saved = loadSettings().observability;\n const resolved = resolveObservabilityConfig(saved, {});\n return formatObservabilityStatus({\n enabled: resolved.enabled,\n capture: resolved.capture,\n sampleRate: resolved.sampleRate,\n destinations: [\n ...(resolved.local.enabled ? [\"local\"] : []),\n ...(resolved.remote\n ? [\n resolved.remote.kind === \"phoenix\"\n ? `phoenix (${safeObservabilityEndpoint(resolved.remote.endpoint)})`\n : `otlp (${safeObservabilityEndpoint(resolved.remote.endpoint)})`,\n ]\n : []),\n ],\n warnings: resolved.warnings,\n });\n };\n\n const persistObservability = (settings: ObservabilitySettings): void => {\n rememberObservability(settings);\n addLine(c.accentBold(\" ✓ Observability settings saved.\"));\n addLine(c.dim(` Saved: ${savedObservabilitySummary()}`));\n addLine(c.dim(\" Restart Janet to apply the new setting.\"));\n updateStatus();\n };\n\n const closeActiveSelect = (select: SelectList): void => {\n chat.removeChild(select);\n if (activeSelect === select) activeSelect = null;\n ui.setFocus(editor);\n };\n\n const confirmFullCapture = (\n base: Omit<ObservabilitySettings, \"capture\">,\n ): void => {\n addLine(\n c.warn(\n \" Full capture includes prompts, responses, and tool payloads. Do not use it with sensitive material.\",\n ),\n );\n const select = new SelectList(\n [\n {\n value: \"no\",\n label: \"Keep metadata-only capture\",\n description: \"Recommended. Content stays out of traces.\",\n },\n {\n value: \"yes\",\n label: \"Enable full capture\",\n description: \"I understand trace content may contain sensitive data.\",\n },\n ],\n 2,\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n closeActiveSelect(select);\n persistObservability({\n ...base,\n capture: item.value === \"yes\" ? \"full\" : \"metadata\",\n });\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const chooseCaptureMode = (\n base: Omit<ObservabilitySettings, \"capture\">,\n ): void => {\n addLine(c.accentBold(\" What may Janet include in traces?\"));\n const select = new SelectList(\n [\n {\n value: \"metadata\",\n label: \"Metadata only\",\n description: \"Timing, tool names, model, tokens, status, and errors.\",\n },\n {\n value: \"full\",\n label: \"Full content\",\n description: \"Also includes prompts, responses, and tool payloads.\",\n },\n ],\n 2,\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n closeActiveSelect(select);\n const capture = item.value as ObservabilityCaptureMode;\n if (capture === \"full\") {\n confirmFullCapture(base);\n } else {\n persistObservability({ ...base, capture });\n }\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const showObservabilityPicker = (): void => {\n if (running) {\n addLine(c.dim(\" Cancel the active run before changing observability settings.\"));\n return;\n }\n addLine(c.accentBold(\" Configure observability\"));\n addLine(c.dim(` Active now: ${formatObservabilityStatus(observability.status)}`));\n addLine(c.dim(\" Tracing is opt-in and changes apply after restart.\"));\n const select = new SelectList(\n [\n {\n value: \"off\",\n label: \"Off\",\n description: \"No spans, trace database, or network export.\",\n },\n {\n value: \"local\",\n label: \"Local trace history\",\n description: \"Store traces in ~/.agent-knowledge/observability.db.\",\n },\n {\n value: \"phoenix\",\n label: \"Phoenix\",\n description: \"Send OTLP traces to http://localhost:6006.\",\n },\n {\n value: \"otlp\",\n label: \"Custom OTLP\",\n description: \"Send OTLP/HTTP protobuf traces to your endpoint.\",\n },\n ],\n 4,\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n closeActiveSelect(select);\n if (item.value === \"off\") {\n persistObservability({\n capture: \"off\",\n sampleRate: 1,\n local: { enabled: false, retentionDays: 7 },\n });\n return;\n }\n if (item.value === \"local\") {\n chooseCaptureMode({\n sampleRate: 1,\n local: { enabled: true, retentionDays: 7 },\n });\n return;\n }\n if (item.value === \"phoenix\") {\n chooseCaptureMode({\n sampleRate: 1,\n local: { enabled: false, retentionDays: 7 },\n remote: {\n kind: \"phoenix\",\n endpoint: \"http://localhost:6006\",\n projectName: \"janet\",\n },\n });\n return;\n }\n void promptInput(\n \"OTLP endpoint (for example, http://localhost:4318):\",\n ).then((endpoint) => {\n try {\n const parsed = new URL(endpoint);\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") throw new Error();\n if (parsed.username || parsed.password || parsed.search || parsed.hash) {\n addLine(\n c.error(\n \" Do not put credentials or query parameters in the saved endpoint. Use OTEL_EXPORTER_OTLP_HEADERS.\",\n ),\n );\n return;\n }\n } catch {\n addLine(c.error(\" Endpoint must be a valid HTTP or HTTPS URL.\"));\n return;\n }\n chooseCaptureMode({\n sampleRate: 1,\n local: { enabled: false, retentionDays: 7 },\n remote: {\n kind: \"otlp\",\n endpoint,\n },\n });\n });\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const showLocalTraces = async (): Promise<void> => {\n if (running) {\n addLine(c.dim(\" Cancel the active run before browsing traces.\"));\n return;\n }\n if (!observability.config.local.enabled) {\n addLine(c.dim(\" Local trace history is not active. Use /observability to enable it.\"));\n return;\n }\n await observability.flush().catch(() => {});\n const store = await observability.storage.getStore(\"observability\");\n if (!store) {\n addLine(c.error(\" Local trace storage is unavailable.\"));\n return;\n }\n const recent = await store.listTraces({\n pagination: { page: 0, perPage: 10 },\n orderBy: { field: \"startedAt\", direction: \"DESC\" },\n });\n if (!recent.spans.length) {\n addLine(c.dim(\" No local traces yet.\"));\n return;\n }\n\n addLine(c.accentBold(\" Recent local traces\"));\n const select = new SelectList(\n recent.spans.map((span) => {\n const state = traceStatus(span);\n const marker = state === \"error\" ? \"✗\" : state === \"running\" ? \"…\" : \"✓\";\n return {\n value: span.traceId,\n label: `${marker} ${span.name}`,\n description: `${span.startedAt.toLocaleString()} · ${span.traceId}`,\n };\n }),\n Math.min(recent.spans.length, 10),\n editorTheme.selectList,\n );\n select.onSelect = (item: SelectItem) => {\n closeActiveSelect(select);\n void store.getTrace({ traceId: item.value }).then((trace) => {\n if (!trace) {\n addLine(c.error(` Trace not found: ${item.value}`));\n return;\n }\n addLine(c.accentBold(` Trace ${trace.traceId}`));\n for (const line of formatTraceTree(trace.spans)) {\n addLine(c.dim(` ${line}`));\n }\n }).catch((error: Error) => {\n addLine(c.error(` Could not read trace: ${error.message}`));\n });\n };\n activeSelect = select;\n chat.addChild(select);\n ui.setFocus(select);\n updateStatus();\n };\n\n const handleCommand = async (text: string): Promise<void> => {\n const [cmd, ...rest] = text.slice(1).split(/\\s+/);\n switch (cmd) {\n case \"quit\":\n case \"exit\":\n await shutdown(0);\n break;\n case \"help\":\n addLine(c.dim(HELP_TEXT));\n break;\n case \"cancel\":\n if (interrupts.handleEscape() === \"ignored\") {\n addLine(c.dim(\" No active run to cancel.\"));\n }\n break;\n case \"observability\": {\n const action = rest[0]?.trim().toLowerCase();\n if (action === \"status\") {\n addLine(c.dim(` Active: ${formatObservabilityStatus(observability.status)}`));\n addLine(c.dim(` Saved: ${savedObservabilitySummary()}`));\n } else if (action === \"off\") {\n persistObservability({\n capture: \"off\",\n sampleRate: 1,\n local: { enabled: false, retentionDays: 7 },\n });\n } else if (!action) {\n showObservabilityPicker();\n } else {\n addLine(c.dim(\"Usage: /observability [status | off]\"));\n }\n break;\n }\n case \"traces\":\n await showLocalTraces();\n break;\n case \"login\": {\n const providerId = (rest[0] || \"anthropic\").trim();\n if (!(OAUTH_PROVIDERS as readonly string[]).includes(providerId)) {\n addLine(c.dim(`Usage: /login <${OAUTH_PROVIDERS.join(\" | \")}>`));\n break;\n }\n const authMode = rest[1]?.trim();\n if (\n authMode &&\n (providerId !== \"openai-codex\" || ![\"browser\", \"device\"].includes(authMode))\n ) {\n addLine(c.dim(\"Usage: /login openai-codex [browser | device]\"));\n break;\n }\n addLine(c.dim(`Starting ${providerId} login…`));\n try {\n await getAuthStorage().login(providerId, {\n onAuth: (info) => {\n addLine(c.accent(\" Open this URL in your browser to authorize:\"));\n addLine(\" \" + info.url);\n if (info.instructions) addLine(c.dim(\" \" + info.instructions));\n },\n onProgress: (m) => addLine(c.dim(\" \" + m)),\n onManualCodeInput: () => promptInput(\"Paste the code shown after you authorize:\"),\n onPrompt: (p) => promptInput(p.message, p.placeholder),\n ...(authMode ? { authMode } : {}),\n });\n addLine(c.accentBold(` ✓ Logged in to ${providerId}.`));\n updateStatus();\n } catch (err) {\n addLine(c.error(` Login failed: ${(err as Error).message}`));\n } finally {\n // A successful browser callback can win the race with the manual-code\n // prompt. Disarm that abandoned prompt so it cannot consume the next\n // chat message after login completes.\n pendingInput = null;\n updateStatus();\n }\n break;\n }\n case \"logout\": {\n const providerId = rest[0]?.trim();\n if (!providerId) {\n addLine(c.dim(`Usage: /logout <${OAUTH_PROVIDERS.join(\" | \")}>`));\n break;\n }\n const storage = getAuthStorage();\n storage.logout(providerId); // OAuth credential\n storage.remove(`apikey:${providerId}`); // stored API key slot, if any\n addLine(c.dim(`Logged out of ${providerId}.`));\n break;\n }\n case \"auth\": {\n const storage = getAuthStorage();\n storage.reload();\n const providers = storage.list();\n if (!providers.length) {\n addLine(c.dim(\"No stored credentials. Use /login <provider>, or set an API key env var\"));\n addLine(c.dim(\"(ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_VERTEX_PROJECT, AWS_*).\"));\n } else {\n for (const p of providers) {\n const cred = storage.get(p);\n addLine(c.dim(` ${p}: `) + (cred?.type === \"oauth\" ? c.accent(\"OAuth (subscription)\") : \"API key\"));\n }\n }\n break;\n }\n case \"model\": {\n const inputId = rest.join(\" \").trim();\n // No id → open the picker; an explicit id still works for power users.\n if (!inputId) {\n showModelPicker();\n break;\n }\n const id = normalizeModelSelection(inputId, availableModels());\n await session.model.switch({ modelId: id });\n completeOnboarding(id, new Date().toISOString());\n rememberModel(id); // so a hand-typed model shows up in the picker next time\n addLine(c.dim(`Model set to ${id}.`));\n updateStatus();\n break;\n }\n case \"models\":\n showModelPicker();\n break;\n default:\n addLine(c.dim(`Unknown command /${cmd}. Try /help.`));\n }\n };\n\n editor.onSubmit = (raw: string) => {\n const text = raw.trim();\n editor.setText(\"\");\n if (!text) return;\n\n // Feed normal prompt input (messages + slash commands) into the editor's\n // built-in up/down history. Skip transient responses — approvals, question\n // answers, and paste-codes shouldn't clutter recall.\n if (!pendingInput && !pendingApproval && !pendingQuestion) {\n editor.addToHistory(text);\n }\n\n // A requested value (e.g. an OAuth paste-code) consumes the next submit.\n // Don't echo it verbatim — it may be a credential.\n if (pendingInput) {\n const resolve = pendingInput;\n pendingInput = null;\n addLine(c.dim(\" ❯ (value entered)\"));\n updateStatus();\n resolve(text);\n return;\n }\n\n // A typed question (free-text or multi-select) consumes the next submit.\n if (pendingQuestion && !activeSelect) {\n const resumeData = resolveAnswer(pendingQuestion, text);\n if (resumeData === undefined) {\n addLine(c.dim(\" Didn't match an option — reply with a number or an exact label.\"));\n return;\n }\n answerQuestion(resumeData, Array.isArray(resumeData) ? resumeData.join(\", \") : resumeData);\n return;\n }\n\n // Pending tool approval: y / n / a (always allow this category).\n if (pendingApproval) {\n const approve = /^y(es)?$/i.test(text);\n const decline = /^n(o)?$/i.test(text);\n const always = /^a(lways)?$/i.test(text);\n if (approve || decline || always) {\n const { toolCallId } = pendingApproval;\n pendingApproval = null;\n addLine(c.dim(always ? \" ✓ always allowed\" : approve ? \" ✓ approved\" : \" ✗ declined\"));\n updateStatus();\n void session.respondToToolApproval({\n decision: always ? \"always_allow_category\" : approve ? \"approve\" : \"decline\",\n toolCallId,\n });\n return;\n }\n addLine(c.dim(\" Answer y (yes), n (no), or a (always allow) first.\"));\n return;\n }\n\n if (text.startsWith(\"/\")) {\n void handleCommand(text);\n return;\n }\n\n addLine(c.user(`❯ ${text}`));\n if (!session.model.hasSelection()) {\n showModelPicker(\" Pick a model first:\");\n return;\n }\n void session.sendMessage({\n content: text,\n tracingOptions: observability.tracingOptionsForTurn({\n interactive: true,\n operation: \"chat\",\n resourceId: paths.resourceId,\n threadId: session.thread.getId() ?? undefined,\n }),\n }).catch((err: Error) => {\n running = false;\n setLoader(false);\n addLine(c.error(` ✗ ${err.message}`));\n updateStatus();\n });\n };\n\n addLine(c.accentBold(GREETING));\n addLine(\n c.dim(\n `Knowledge bundle: ${paths.bundlePath}\\n` +\n `Ask me anything in the bundle, or say what to ingest. /help for commands.`,\n ),\n );\n for (const warning of observability.status.warnings) {\n addLine(c.warn(`Observability: ${warning}`));\n }\n updateStatus();\n ui.start();\n ui.setFocus(editor);\n ui.requestRender();\n\n // First run (no model configured): open the picker to get set up.\n if (!session.model.hasSelection()) showModelPicker(\" Let's pick a model to get you started.\");\n\n // The TUI owns the process from here; exit happens via shutdown().\n return await new Promise<number>(() => {});\n}\n","const WORKSPACE_READ = new Set([\n \"mastra_workspace_file_stat\",\n \"mastra_workspace_grep\",\n \"mastra_workspace_lsp_inspect\",\n \"mastra_workspace_list_files\",\n \"mastra_workspace_read_file\",\n \"mastra_workspace_search\",\n]);\n\nconst WORKSPACE_WRITE = new Set([\n \"mastra_workspace_ast_edit\",\n \"mastra_workspace_delete\",\n \"mastra_workspace_edit_file\",\n \"mastra_workspace_index\",\n \"mastra_workspace_mkdir\",\n \"mastra_workspace_write_file\",\n]);\n\nconst WORKSPACE_EXECUTE = new Set([\n \"mastra_workspace_execute_command\",\n \"mastra_workspace_get_process_output\",\n \"mastra_workspace_kill_process\",\n]);\n\nconst PDF_READ = new Set([\"janet_read_pdf\", \"janet_read_pdf_chunk\"]);\nconst WEB_READ = new Set([\"janet_web_fetch\", \"janet_web_fetch_chunk\"]);\n\n/** Friendly transient status for routine tool work. */\nexport function toolActivityLabel(toolName: string): string {\n if (toolName === \"skill\" || toolName === \"skill_read\" || toolName === \"skill_search\") {\n return \"Janet is reading the playbook…\";\n }\n if (PDF_READ.has(toolName)) return \"Janet is reading the document…\";\n if (WEB_READ.has(toolName)) return \"Janet is reading the page…\";\n if (WORKSPACE_READ.has(toolName)) return \"Janet is checking the workspace…\";\n if (WORKSPACE_WRITE.has(toolName)) return \"Janet is updating the bundle…\";\n if (WORKSPACE_EXECUTE.has(toolName) || toolName.includes(\"shell\")) {\n return \"Janet is running a check…\";\n }\n return \"Janet is working…\";\n}\n\n/** Turn recoverable workspace guard failures into useful user-facing status. */\nexport function toolErrorLabel(result: unknown): string {\n const detail = String(result);\n const readRequired = detail.match(\n /File \"([^\"]+)\" (?:has not been read|was modified since last read)/,\n );\n if (readRequired) {\n return `Update paused: Janet needs to re-read \"${readRequired[1]}\" first.`;\n }\n return `Tool error: ${detail.slice(0, 140)}`;\n}\n","export type InterruptResult =\n | \"cancelled\"\n | \"cleared\"\n | \"exit\"\n | \"exit-hint\"\n | \"ignored\";\n\nexport interface InterruptActions {\n isRunning(): boolean;\n hasInput(): boolean;\n abortRun(): void;\n clearInput(): void;\n exit(): void;\n notify(result: Exclude<InterruptResult, \"ignored\">): void;\n}\n\nexport interface InterruptController {\n handleCtrlC(): InterruptResult;\n handleEscape(): InterruptResult;\n}\n\n/**\n * Centralize Janet's interrupt behavior so it works independently of whichever\n * TUI component currently owns keyboard focus.\n */\nexport function createInterruptController(\n actions: InterruptActions,\n options: {\n doublePressMs?: number;\n now?: () => number;\n } = {},\n): InterruptController {\n const doublePressMs = options.doublePressMs ?? 800;\n const now = options.now ?? Date.now;\n let lastCtrlC: number | undefined;\n\n const cancelRun = (): InterruptResult => {\n if (!actions.isRunning()) return \"ignored\";\n actions.abortRun();\n actions.notify(\"cancelled\");\n return \"cancelled\";\n };\n\n return {\n handleCtrlC(): InterruptResult {\n const pressedAt = now();\n if (lastCtrlC !== undefined && pressedAt - lastCtrlC < doublePressMs) {\n actions.notify(\"exit\");\n actions.exit();\n return \"exit\";\n }\n lastCtrlC = pressedAt;\n\n const cancelled = cancelRun();\n if (cancelled !== \"ignored\") return cancelled;\n\n if (actions.hasInput()) {\n actions.clearInput();\n actions.notify(\"cleared\");\n return \"cleared\";\n }\n\n actions.notify(\"exit-hint\");\n return \"exit-hint\";\n },\n\n handleEscape(): InterruptResult {\n return cancelRun();\n },\n };\n}\n","export interface TraceSpanSummary {\n spanId: string;\n parentSpanId?: string | null;\n name: string;\n spanType: string;\n startedAt: Date;\n endedAt?: Date | null;\n error?: unknown;\n}\n\nfunction duration(span: TraceSpanSummary): string {\n if (!span.endedAt) return \"running\";\n const elapsed = Math.max(0, span.endedAt.getTime() - span.startedAt.getTime());\n return elapsed >= 1_000 ? `${(elapsed / 1_000).toFixed(1)}s` : `${elapsed}ms`;\n}\n\nexport function traceStatus(span: TraceSpanSummary): \"error\" | \"running\" | \"ok\" {\n if (span.error) return \"error\";\n return span.endedAt ? \"ok\" : \"running\";\n}\n\n/** Render Mastra's flat span records as a compact, content-free tree. */\nexport function formatTraceTree(spans: TraceSpanSummary[]): string[] {\n const byParent = new Map<string | null, TraceSpanSummary[]>();\n const ids = new Set(spans.map((span) => span.spanId));\n for (const span of spans) {\n const parent =\n span.parentSpanId && ids.has(span.parentSpanId) ? span.parentSpanId : null;\n const children = byParent.get(parent) ?? [];\n children.push(span);\n byParent.set(parent, children);\n }\n for (const children of byParent.values()) {\n children.sort((a, b) => a.startedAt.getTime() - b.startedAt.getTime());\n }\n\n const lines: string[] = [];\n const visited = new Set<string>();\n const visit = (span: TraceSpanSummary, depth: number): void => {\n if (visited.has(span.spanId)) return;\n visited.add(span.spanId);\n const status = traceStatus(span);\n const marker = status === \"error\" ? \"✗\" : status === \"running\" ? \"…\" : \"✓\";\n lines.push(\n `${\" \".repeat(depth)}${marker} ${span.name} · ${span.spanType} · ${duration(span)}`,\n );\n for (const child of byParent.get(span.spanId) ?? []) visit(child, depth + 1);\n };\n\n for (const root of byParent.get(null) ?? []) visit(root, 0);\n return lines;\n}\n","import chalk from \"chalk\";\nimport type { EditorTheme } from \"@earendil-works/pi-tui\";\n\n/**\n * Janet's minimal terminal theme. Good Place warm: cyan accents, soft dims.\n * Kept tiny on purpose — no gradients, no branding machinery.\n */\nexport const c = {\n accent: chalk.cyan,\n accentBold: chalk.cyan.bold,\n dim: chalk.dim,\n user: chalk.green,\n error: chalk.red,\n warn: chalk.yellow,\n bold: chalk.bold,\n italic: chalk.italic,\n};\n\nexport const editorTheme: EditorTheme = {\n borderColor: (s: string) => chalk.cyan(s),\n selectList: {\n selectedPrefix: (s: string) => chalk.cyan(s),\n selectedText: (s: string) => chalk.cyan.bold(s),\n description: (s: string) => chalk.dim(s),\n scrollInfo: (s: string) => chalk.dim(s),\n noMatch: (s: string) => chalk.dim(s),\n },\n};\n\nexport const markdownTheme = {\n heading: (s: string) => chalk.cyan.bold(s),\n link: (s: string) => chalk.cyan.underline(s),\n linkUrl: (s: string) => chalk.dim(s),\n code: (s: string) => chalk.yellow(s),\n codeBlock: (s: string) => chalk.yellow(s),\n codeBlockBorder: (s: string) => chalk.dim(s),\n quote: (s: string) => chalk.italic(s),\n quoteBorder: (s: string) => chalk.dim(s),\n hr: (s: string) => chalk.dim(s),\n listBullet: (s: string) => chalk.cyan(s),\n bold: (s: string) => chalk.bold(s),\n italic: (s: string) => chalk.italic(s),\n strikethrough: (s: string) => chalk.strikethrough(s),\n underline: (s: string) => chalk.underline(s),\n};\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stjbrown/agent-knowledge",
3
- "version": "0.1.0-beta.5",
3
+ "version": "0.1.0-beta.7",
4
4
  "description": "Janet builds and maintains portable LLM wikis in plain Markdown using OKF.",
5
5
  "keywords": [
6
6
  "agent",
@@ -58,16 +58,24 @@
58
58
  "@mastra/memory": "1.23.0",
59
59
  "@mastra/observability": "1.16.2",
60
60
  "@mastra/otel-exporter": "1.3.5",
61
+ "@mozilla/readability": "0.6.0",
61
62
  "@opentelemetry/exporter-trace-otlp-proto": "0.218.0",
62
63
  "ai": "6.0.228",
63
64
  "chalk": "5.6.2",
65
+ "ipaddr.js": "2.4.0",
66
+ "jsdom": "29.1.1",
67
+ "pdf-parse": "2.4.5",
64
68
  "strip-ansi": "7.2.0",
69
+ "turndown": "7.2.4",
70
+ "undici": "7.29.0",
65
71
  "yaml": "2.9.0",
66
72
  "zod": "4.4.3"
67
73
  },
68
74
  "devDependencies": {
69
75
  "@agent-knowledge/kb-tools": "workspace:*",
76
+ "@types/jsdom": "28.0.3",
70
77
  "@types/node": "^22.20.1",
78
+ "@types/turndown": "5.0.6",
71
79
  "tsup": "^8.3.0",
72
80
  "tsx": "^4.19.0",
73
81
  "typescript": "^5.6.0",
@@ -40,9 +40,12 @@ thing will be routed.
40
40
  ## 2. Read and classify the source
41
41
 
42
42
  Identify what to ingest (an argument, a path, or content the user dropped). Read it in full —
43
- markdown, text, PDF, image (view it), transcript, web page. Classify it (e.g. transcript, email,
44
- note, document, media) since that shapes extraction. **Ground everything in what the source actually
45
- says** never invent entities, claims, or attribution not present in it (trust model §2).
43
+ markdown, text, image (view it), transcript, web page. In Janet, load and follow the `janet-pdf`
44
+ skill for a PDF; never use Janet's generic workspace file reader on the PDF or its cached
45
+ extraction. In another host, use its supported native PDF-reading workflow. Classify the source
46
+ (e.g. transcript, email, note, document, media) since that shapes extraction. **Ground everything
47
+ in what the source actually says** — never invent entities, claims, or attribution not present in
48
+ it (trust model §2).
46
49
 
47
50
  **Completion criterion:** the source is read in full and classified; you can summarize its key
48
51
  signal.