codebase-onboarder 0.7.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -12
- package/bin/onboarder.js +0 -0
- package/cli/agent/command.d.ts +71 -0
- package/cli/agent/command.js +177 -0
- package/cli/agent/command.js.map +1 -0
- package/cli/agent/config.d.ts +31 -0
- package/cli/agent/config.js +98 -0
- package/cli/agent/config.js.map +1 -0
- package/cli/agent/contracts.d.ts +77 -0
- package/cli/agent/contracts.js +2 -0
- package/cli/agent/contracts.js.map +1 -0
- package/cli/agent/files.d.ts +19 -0
- package/cli/agent/files.js +109 -0
- package/cli/agent/files.js.map +1 -0
- package/cli/agent/gitSource.d.ts +18 -0
- package/cli/agent/gitSource.js +69 -0
- package/cli/agent/gitSource.js.map +1 -0
- package/cli/agent/github.d.ts +21 -0
- package/cli/agent/github.js +94 -0
- package/cli/agent/github.js.map +1 -0
- package/cli/agent/mcp.d.ts +15 -0
- package/cli/agent/mcp.js +78 -0
- package/cli/agent/mcp.js.map +1 -0
- package/cli/agent/process.d.ts +18 -0
- package/cli/agent/process.js +118 -0
- package/cli/agent/process.js.map +1 -0
- package/cli/agent/protocol.d.ts +3 -0
- package/cli/agent/protocol.js +26 -0
- package/cli/agent/protocol.js.map +1 -0
- package/cli/agent/runner.d.ts +34 -0
- package/cli/agent/runner.js +152 -0
- package/cli/agent/runner.js.map +1 -0
- package/cli/agent/stdio.d.ts +1 -0
- package/cli/agent/stdio.js +62 -0
- package/cli/agent/stdio.js.map +1 -0
- package/cli/agent/tools.d.ts +7 -0
- package/cli/agent/tools.js +201 -0
- package/cli/agent/tools.js.map +1 -0
- package/cli/chat/app.d.ts +16 -0
- package/cli/chat/app.js +345 -0
- package/cli/chat/app.js.map +1 -0
- package/cli/chat/commands.d.ts +11 -0
- package/cli/chat/commands.js +120 -0
- package/cli/chat/commands.js.map +1 -0
- package/cli/chat/composer.d.ts +75 -0
- package/cli/chat/composer.js +467 -0
- package/cli/chat/composer.js.map +1 -0
- package/cli/chat/controller.d.ts +60 -0
- package/cli/chat/controller.js +393 -0
- package/cli/chat/controller.js.map +1 -0
- package/cli/chat/logo.d.ts +3 -0
- package/cli/chat/logo.js +14 -0
- package/cli/chat/logo.js.map +1 -0
- package/cli/chat/models.d.ts +18 -0
- package/cli/chat/models.js +88 -0
- package/cli/chat/models.js.map +1 -0
- package/cli/chat/profile.d.ts +5 -0
- package/cli/chat/profile.js +98 -0
- package/cli/chat/profile.js.map +1 -0
- package/cli/chat/render.d.ts +40 -0
- package/cli/chat/render.js +259 -0
- package/cli/chat/render.js.map +1 -0
- package/cli/chat/screen.d.ts +26 -0
- package/cli/chat/screen.js +117 -0
- package/cli/chat/screen.js.map +1 -0
- package/cli/chat/source.d.ts +29 -0
- package/cli/chat/source.js +116 -0
- package/cli/chat/source.js.map +1 -0
- package/cli/chat/store.d.ts +43 -0
- package/cli/chat/store.js +94 -0
- package/cli/chat/store.js.map +1 -0
- package/cli/chat/text.d.ts +4 -0
- package/cli/chat/text.js +27 -0
- package/cli/chat/text.js.map +1 -0
- package/cli/explorer/app.d.ts +1 -0
- package/cli/explorer/app.js +20 -1
- package/cli/explorer/app.js.map +1 -1
- package/cli/explorer/commands.js +5 -0
- package/cli/explorer/commands.js.map +1 -1
- package/cli/main.js +47 -13
- package/cli/main.js.map +1 -1
- package/docs/HERMES_RESEARCH.md +51 -0
- package/package.json +2 -1
- package/public/app.js +98 -24
- package/public/app.js.map +1 -1
- package/public/assets/onboarder-mark.svg +11 -0
- package/public/browser.d.ts +3 -0
- package/public/browser.js.map +1 -1
- package/public/index.html +24 -7
- package/public/js/about.js +2 -2
- package/public/js/about.js.map +1 -1
- package/public/js/aiDraft.d.ts +1 -0
- package/public/js/aiDraft.js +66 -17
- package/public/js/aiDraft.js.map +1 -1
- package/public/js/api.d.ts +8 -5
- package/public/js/api.js +45 -22
- package/public/js/api.js.map +1 -1
- package/public/js/deepAnalysisView.js +2 -2
- package/public/js/deepAnalysisView.js.map +1 -1
- package/public/js/diagramPane.d.ts +1 -0
- package/public/js/diagramPane.js +5 -0
- package/public/js/diagramPane.js.map +1 -1
- package/public/js/docsView.js +6 -6
- package/public/js/docsView.js.map +1 -1
- package/public/js/dom.d.ts +8 -0
- package/public/js/dom.js.map +1 -1
- package/public/js/llm.d.ts +3 -1
- package/public/js/llm.js +15 -8
- package/public/js/llm.js.map +1 -1
- package/public/js/repoFiles.js +1 -1
- package/public/js/repoFiles.js.map +1 -1
- package/public/js/reviewView.js +1 -1
- package/public/js/reviewView.js.map +1 -1
- package/public/styles.css +25 -0
- package/server/gitDiff.d.ts +1 -1
- package/server/hermesChat.d.ts +13 -0
- package/server/hermesChat.js +145 -0
- package/server/hermesChat.js.map +1 -0
- package/server/http.d.ts +5 -4
- package/server/http.js +0 -4
- package/server/http.js.map +1 -1
- package/server/mcp/server.d.ts +1 -1
- package/server/mcp/server.js +2 -2
- package/server/mcp/server.js.map +1 -1
- package/server/router.js +7 -3
- package/server/router.js.map +1 -1
- package/shared/diagram/aiMermaid.js +16 -13
- package/shared/diagram/aiMermaid.js.map +1 -1
package/cli/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/cli/main.ts"],"names":[],"mappings":"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","sourcesContent":["import { scanOptionsFromFlags } from './scanOptions.js';\n// argv → command. `bin/onboarder.js` is a one-line trampoline into `main`; all\n// parsing and dispatch lives here so the tests can call it directly.\n//\n// Flags use node's util.parseArgs — still zero dependencies, still strict about\n// unknown flags, which is what a tool that writes a config file should be.\n\nimport fs from 'node:fs';\nimport { parseArgs } from 'node:util';\n\nimport {\n runSetup, runStart, runStartBackground, runStartup, runLogs, runStatus, runStop, runRestart,\n runConfig, runConfigKey, runConfigReset, runDoctor, runTunnel, runHttps,\n} from './commands.js';\nimport { runExplore } from './explorer/app.js';\nimport { openRepoOrClone, closeRemote } from './explorer/session.js';\nimport { createReport, formatReport } from './explorer/report.js';\nimport { setColorEnabled } from './ui.js';\nimport { runReview } from '../server/review.js';\nimport { reviewMarkdown, reviewProfile, SEVERITY_RANK } from '../shared/review/review.js';\nimport { expandHome } from '../server/paths.js';\n\nconst PACKAGE = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));\n\nconst HELP = `\n 🧭 Onboarder — drop a path, get a map.\n\n Scan options for report and explore\n --max-files <count> Maximum files to walk (default: 4000)\n --max-file-size <bytes> Maximum UTF-8 file size (default: 204800)\n --read-concurrency <n> Concurrent reads, 1–32 (default: 8)\n\n Usage\n onboarder Explore a codebase here, interactively\n onboarder explore [folder|url] Choose a source, or open one directly (alias: tui)\n onboarder report [folder|url] One-shot summary for terminals and scripts (--json)\n onboarder review [folder] Review local changes (--json for scripts)\n --base <ref> --head <ref> Compare branches from their merge base\n --staged Review only staged changes\n --profile focused|balanced|thorough\n --fail-on high|medium|low|critical|info Exit 1 for findings at this level or above\n onboarder start Start the web UI in the foreground (Ctrl-C stops it)\n onboarder start background Start detached — keeps running after you close the terminal\n onboarder start startup Run automatically at login [install|remove|status]\n onboarder web Alias for \\`onboarder start\\`\n onboarder logs Show recent log lines (-n <count>, -f to follow)\n onboarder status Show whether the web UI is running\n onboarder stop Stop the running web UI\n onboarder restart Stop and start again\n onboarder config [<…>] show | get <key> | set <key> <value> | path | reset | key <rotate|show|set>\n onboarder tunnel <name> cloudflare | tailscale\n onboarder https <action> check | setup | start | stop | status\n onboarder doctor Check the machine and the config\n\n In the explorer\n map tour explain what this is, where to start, and why\n tree find show inspect deps browse it, search it, read it, trace it\n graph blast symbols the dependency tree, the blast radius, the outline\n health hubs layers patterns the analysis, in the same words the site uses\n coupling clusters risks the heat grid, the module groups, what is wrong\n log hotspots blame git history, hot files, who wrote a line\n diagram atlas docs Mermaid source, diagram index, and prose\n workflows sbom CI jobs and dependency/license inventory\n diff engines deep Changed files, analyzer status, optional deep scan\n ask <question> Optional AI answer grounded in the loaded repo\n pick cd rescan web choose a source, switch repo, reload, open the web UI\n github what GitHub says about this repo — stars, issues, license\n !<command> run a shell command without leaving\n help exit everything, and the way out\n Tab completes commands, then file paths\n\n Setup flags (interactive wizard skips what they answer)\n --mode local|self-hosted --host <addr> --port <n> --domain <name>\n --https Set up automatic HTTPS through Caddy\n --access-key generate|<k> --name <n> --email <e>\n --provider none|openai-compatible|ollama|openrouter|custom\n --base-url <url> --model <m> --cloudflare --tailscale\n\n General flags\n --config <file> Use this config file (or ONBOARDER_CONFIG)\n --server With bare \\`onboarder\\`, start the web UI instead of exploring\n --non-interactive Never prompt; flags + defaults are the answers\n -y, --yes Answer yes to confirmations\n --json Machine-readable output\n --reveal config show prints the full access key\n --no-color Plain output (NO_COLOR works too)\n -h, --help This text -v, --version Print the version\n\n Also accepted\n help | --help onboarder help | onboarder --help\n config | config show\n bg | detached alias for start background\n fg | foreground alias for start\n\n Examples\n onboarder # explore the repo you are standing in\n onboarder explore ~/code/my-app # explore somewhere else\n onboarder explore # choose a local folder or paste a Git URL\n onboarder explore https://github.com/expressjs/express # clone one and read it\n onboarder report . --json # analyze once and print machine-readable JSON\n onboarder start background # leave the web UI running, close the terminal\n onboarder logs -f # watch what it is doing\n onboarder start startup install # also start it every time you log in\n onboarder setup --non-interactive --mode local --port 4310\n onboarder setup --non-interactive --mode self-hosted --domain map.example.com --https --start\n onboarder config set tunnel.cloudflare true && onboarder tunnel cloudflare\n`;\n\nconst OPTIONS: NonNullable<import('node:util').ParseArgsConfig['options']> = {\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n json: { type: 'boolean' },\n yes: { type: 'boolean', short: 'y' },\n 'non-interactive': { type: 'boolean' },\n reveal: { type: 'boolean' },\n verbose: { type: 'boolean' },\n start: { type: 'boolean' },\n color: { type: 'boolean' }, // `--no-color` is lifted out by extractNegatedFlags; --color forces it on\n config: { type: 'string' },\n mode: { type: 'string' },\n host: { type: 'string' },\n port: { type: 'string' },\n domain: { type: 'string' },\n https: { type: 'boolean' },\n 'access-key': { type: 'string' },\n name: { type: 'string' },\n email: { type: 'string' },\n provider: { type: 'string' },\n 'base-url': { type: 'string' },\n model: { type: 'string' },\n cloudflare: { type: 'boolean' },\n tailscale: { type: 'boolean' },\n 'auto-open': { type: 'boolean' },\n lines: { type: 'string', short: 'n' },\n follow: { type: 'boolean', short: 'f' },\n timeout: { type: 'string' },\n server: { type: 'boolean' },\n 'max-files': { type: 'string' },\n 'max-file-size': { type: 'string' },\n 'read-concurrency': { type: 'string' },\n base: { type: 'string' },\n head: { type: 'string' },\n staged: { type: 'boolean' },\n profile: { type: 'string' },\n 'fail-on': { type: 'string' },\n};\n\n// parseArgs speaks kebab-case; the wizard's flags speak camelCase.\nfunction normalizeFlags(values) {\n const out: Record<string, any> = {};\n for (const [k, v] of Object.entries(values)) {\n const key = k.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n out[key] = v;\n }\n return out;\n}\n\n// `parseArgs` cannot express a negated boolean. `--color=false` is rejected\n// outright, `--color false` sets `color: true` and leaves `false` behind as a\n// positional, and `--no-color` is an unknown option — so the documented flag\n// had never worked, for any command, and `--no-color status` would try to run a\n// command called `no-color`.\n//\n// There is no parser-level spelling for \"this boolean is false\", so the flag is\n// lifted out of argv before parsing and applied to the parsed flags after. That\n// keeps `parseArgs` strict about genuinely unknown options (which is the point\n// of a tool that writes a config file) while making the one negation the CLI\n// documents actually work.\nfunction extractNegatedFlags(argv) {\n const rest = [];\n let noColor = false;\n for (const arg of argv) {\n if (arg === '--no-color') noColor = true;\n else rest.push(arg);\n }\n return { argv: rest, noColor };\n}\n\nexport async function main(argv = process.argv.slice(2)) {\n const { argv: argsIn, noColor } = extractNegatedFlags(argv);\n let parsed;\n try {\n parsed = parseArgs({ args: argsIn, options: OPTIONS, allowPositionals: true });\n } catch (e) {\n console.error(' ' + e.message + '\\n' + HELP);\n return 2;\n }\n const { values, positionals } = parsed;\n const flags = normalizeFlags(values);\n\n // Color is decided here, after the flags exist and before anything is\n // painted. An explicit `--no-color` wins over `FORCE_COLOR`: a person who\n // typed the flag meant it, and a stray `FORCE_COLOR` inherited from a CI\n // profile should not override the thing they just asked for.\n if (noColor) {\n flags.color = false;\n setColorEnabled(false);\n } else if (flags.color === true) {\n // `--color` was accepted by the parser and then ignored, which is the same\n // lie in the other direction. It is the documented way to keep ANSI in a\n // captured log, so it has to actually turn color on.\n setColorEnabled(true);\n }\n\n if (flags.help) { console.log(HELP); return 0; }\n if (flags.version) { console.log(PACKAGE.version); return 0; }\n\n const [cmd, sub, ...rest] = positionals;\n try {\n switch (cmd) {\n case 'help':\n console.log(HELP);\n return 0;\n case undefined:\n // The entry point. On a terminal, bare `onboarder` explores the repo you\n // are standing in — the thing people actually want from this tool, and\n // what the name promises. Everywhere else (a pipe, CI, a script) it\n // still starts the server, because an interactive session with no input\n // source is a hang, and nothing about a background job wants a prompt.\n // `--server` forces the old behavior even on a terminal.\n if (!flags.server && process.stdin.isTTY && process.stdout.isTTY) {\n return codeOf(await runExplore({ flags }));\n }\n return codeOf(await runStart({ flags }));\n case 'explore':\n case 'tui':\n case 'shell':\n return codeOf(await runExplore({ flags, target: sub }));\n case 'report': {\n const repo = await openRepoOrClone(sub || '.', scanOptionsFromFlags(flags));\n try {\n const report = createReport(repo);\n console.log(flags.json ? JSON.stringify(report, null, 2) : formatReport(report));\n return 0;\n } finally {\n await closeRemote(repo);\n }\n }\n case 'review': {\n if (flags.staged && flags.head) throw new Error('Choose either --staged or --head.');\n if (flags.failOn && !Object.hasOwn(SEVERITY_RANK, flags.failOn)) throw new Error('Choose a valid --fail-on severity: critical, high, medium, low, or info.');\n const report = await runReview(expandHome(sub || '.'), { base: flags.base || 'HEAD', head: flags.head || '', mode: flags.staged ? 'staged' : flags.head ? 'range' : 'working', profile: flags.profile ? reviewProfile(flags.profile) : undefined });\n console.log(flags.json ? JSON.stringify(report, null, 2) : reviewMarkdown(report));\n return flags.failOn && report.findings.some(f => SEVERITY_RANK[f.severity] >= SEVERITY_RANK[flags.failOn]) || report.checks.some(c => c.id === 'conflicts' && c.status === 'fail') ? 1 : 0;\n }\n case 'web':\n case 'site':\n return codeOf(await runStart({ flags }));\n case 'start':\n // `onboarder start [background|fg|startup [action]]`. The sub-verb is a\n // positional, not a flag, because `onboarder start` has to keep working\n // exactly as it did and `startup install` is a different verb from\n // `start`.\n if (sub === 'background' || sub === 'bg' || sub === 'daemon' || sub === 'detached') {\n return codeOf(await runStartBackground({ flags }));\n }\n if (sub === 'startup' || sub === 'login' || sub === 'autostart') {\n return codeOf(await runStartup(rest[0] || 'status', { flags }));\n }\n if (sub === 'fg' || sub === 'foreground') return codeOf(await runStart({ flags }));\n if (sub === 'status') return codeOf(await runStatus({ flags }));\n if (sub === 'stop') return codeOf(await runStop({ flags }));\n if (sub === 'logs') return codeOf(await runLogs({ flags }));\n if (sub) {\n console.error(' Unknown start mode: ' + sub + '\\n' + HELP);\n return 2;\n }\n return codeOf(await runStart({ flags }));\n case 'logs':\n case 'log':\n return codeOf(await runLogs({ flags }));\n case 'startup':\n case 'autostart':\n return codeOf(await runStartup(sub || 'status', { flags }));\n case 'status':\n return codeOf(await runStatus({ flags }));\n case 'stop':\n return codeOf(await runStop({ flags }));\n case 'restart':\n return codeOf(await runRestart({ flags }));\n case 'setup':\n case 'onboard':\n case 'init':\n return codeOf(await runSetup({ flags, version: PACKAGE.version }));\n case 'config':\n if (sub === 'key') return codeOf(await runConfigKey(rest[0], rest.slice(1), { flags }));\n if (sub === 'reset') return codeOf(await runConfigReset({ flags }));\n return codeOf(await runConfig(sub || 'show', rest, { flags }));\n case 'tunnel':\n return codeOf(await runTunnel(sub, { flags }));\n case 'https':\n return codeOf(await runHttps(sub || 'status', { flags }));\n case 'doctor':\n return codeOf(await runDoctor({ flags }));\n default:\n console.error(' Unknown command: ' + cmd + '\\n' + HELP);\n return 2;\n }\n } catch (e) {\n console.error(' ' + (e.message || e));\n return 1;\n }\n}\n\n// Commands return an exit code or, for `start`, an object carrying the live\n// server. Both collapse to \"what code should the process eventually use\".\nfunction codeOf(result) {\n return typeof result === 'number' ? result : result?.code ?? 0;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/cli/main.ts"],"names":[],"mappings":"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","sourcesContent":["import { scanOptionsFromFlags } from './scanOptions.js';\n// argv → command. `bin/onboarder.js` is a one-line trampoline into `main`; all\n// parsing and dispatch lives here so the tests can call it directly.\n//\n// Flags use node's util.parseArgs — still zero dependencies, still strict about\n// unknown flags, which is what a tool that writes a config file should be.\n\nimport fs from 'node:fs';\nimport { parseArgs } from 'node:util';\n\nimport {\n runSetup, runStart, runStartBackground, runStartup, runLogs, runStatus, runStop, runRestart,\n runConfig, runConfigKey, runConfigReset, runDoctor, runTunnel, runHttps,\n} from './commands.js';\nimport { runExplore } from './explorer/app.js';\nimport { runChat, CHAT_HELP } from './chat/app.js';\nimport { isRemoteSource } from './chat/source.js';\nimport { openRepoOrClone, closeRemote } from './explorer/session.js';\nimport { createReport, formatReport } from './explorer/report.js';\nimport { setColorEnabled } from './ui.js';\nimport { runReview } from '../server/review.js';\nimport { reviewMarkdown, reviewProfile, SEVERITY_RANK } from '../shared/review/review.js';\nimport { expandHome } from '../server/paths.js';\nimport { agentCommand, AGENT_OPTIONS } from './agent/command.js';\n\nconst PACKAGE = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));\n\nconst HELP = `\n 🧭 Onboarder — drop a path, get a map.\n\n Scan options for report and explore\n --max-files <count> Maximum files to walk (default: 4000)\n --max-file-size <bytes> Maximum UTF-8 file size (default: 204800)\n --read-concurrency <n> Concurrent reads, 1–32 (default: 8)\n\n Usage\n onboarder Open the Hermes chat harness here\n onboarder chat [folder|url] Clone/open a repo and chat (alias: tui)\n onboarder explore [folder|url] Open the offline repository explorer\n onboarder report [folder|url] One-shot summary for terminals and scripts (--json)\n onboarder review [folder] Review local changes (--json for scripts)\n --base <ref> --head <ref> Compare branches from their merge base\n --staged Review only staged changes\n --profile focused|balanced|thorough\n --fail-on high|medium|low|critical|info Exit 1 for findings at this level or above\n onboarder agent <workflow> Hermes: ask, review, triage, implement, pr, github\n onboarder agent --help Agent setup, permissions, and examples\n onboarder start Start the web UI in the foreground (Ctrl-C stops it)\n onboarder start background Start detached — keeps running after you close the terminal\n onboarder start startup Run automatically at login [install|remove|status]\n onboarder web Alias for \\`onboarder start\\`\n onboarder logs Show recent log lines (-n <count>, -f to follow)\n onboarder status Show whether the web UI is running\n onboarder stop Stop the running web UI\n onboarder restart Stop and start again\n onboarder config [<…>] show | get <key> | set <key> <value> | path | reset | key <rotate|show|set>\n onboarder tunnel <name> cloudflare | tailscale\n onboarder https <action> check | setup | start | stop | status\n onboarder doctor Check the machine and the config\n\n In the explorer\n map tour explain what this is, where to start, and why\n tree find show inspect deps browse it, search it, read it, trace it\n graph blast symbols the dependency tree, the blast radius, the outline\n health hubs layers patterns the analysis, in the same words the site uses\n coupling clusters risks the heat grid, the module groups, what is wrong\n log hotspots blame git history, hot files, who wrote a line\n diagram atlas docs Mermaid source, diagram index, and prose\n workflows sbom CI jobs and dependency/license inventory\n diff engines deep Changed files, analyzer status, optional deep scan\n ask <question> Optional AI answer grounded in the loaded repo\n pick cd rescan web choose a source, switch repo, reload, open the web UI\n github what GitHub says about this repo — stars, issues, license\n !<command> run a shell command without leaving\n help exit everything, and the way out\n Tab completes commands, then file paths\n\n Setup flags (interactive wizard skips what they answer)\n --mode local|self-hosted --host <addr> --port <n> --domain <name>\n --https Set up automatic HTTPS through Caddy\n --access-key generate|<k> --name <n> --email <e>\n --provider none|openai-compatible|ollama|openrouter|custom\n --base-url <url> --model <m> --cloudflare --tailscale\n\n General flags\n --config <file> Use this config file (or ONBOARDER_CONFIG)\n --server With bare \\`onboarder\\`, start the web UI instead of chatting\n --non-interactive Never prompt; flags + defaults are the answers\n -y, --yes Answer yes to confirmations\n --json Machine-readable output\n --reveal config show prints the full access key\n --no-color Plain output (NO_COLOR works too)\n -h, --help This text -v, --version Print the version\n\n Also accepted\n help | --help onboarder help | onboarder --help\n config | config show\n bg | detached alias for start background\n fg | foreground alias for start\n\n Examples\n onboarder # chat about the repo you are standing in\n onboarder chat --mode review # begin in review mode\n onboarder explore ~/code/my-app # explore somewhere else\n onboarder explore # choose a local folder or paste a Git URL\n onboarder explore https://github.com/expressjs/express # clone one and read it\n onboarder report . --json # analyze once and print machine-readable JSON\n onboarder start background # leave the web UI running, close the terminal\n onboarder logs -f # watch what it is doing\n onboarder start startup install # also start it every time you log in\n onboarder setup --non-interactive --mode local --port 4310\n onboarder setup --non-interactive --mode self-hosted --domain map.example.com --https --start\n onboarder config set tunnel.cloudflare true && onboarder tunnel cloudflare\n`;\n\nconst OPTIONS: NonNullable<import('node:util').ParseArgsConfig['options']> = {\n ...AGENT_OPTIONS,\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n json: { type: 'boolean' },\n yes: { type: 'boolean', short: 'y' },\n 'non-interactive': { type: 'boolean' },\n reveal: { type: 'boolean' },\n verbose: { type: 'boolean' },\n start: { type: 'boolean' },\n color: { type: 'boolean' }, // `--no-color` is lifted out by extractNegatedFlags; --color forces it on\n config: { type: 'string' },\n mode: { type: 'string' },\n host: { type: 'string' },\n port: { type: 'string' },\n domain: { type: 'string' },\n https: { type: 'boolean' },\n 'access-key': { type: 'string' },\n name: { type: 'string' },\n email: { type: 'string' },\n provider: { type: 'string' },\n 'base-url': { type: 'string' },\n model: { type: 'string' },\n cloudflare: { type: 'boolean' },\n tailscale: { type: 'boolean' },\n 'auto-open': { type: 'boolean' },\n lines: { type: 'string', short: 'n' },\n follow: { type: 'boolean', short: 'f' },\n timeout: { type: 'string' },\n server: { type: 'boolean' },\n 'max-files': { type: 'string' },\n 'max-file-size': { type: 'string' },\n 'read-concurrency': { type: 'string' },\n base: { type: 'string' },\n head: { type: 'string' },\n staged: { type: 'boolean' },\n profile: { type: 'string' },\n 'fail-on': { type: 'string' },\n};\n\n// parseArgs speaks kebab-case; the wizard's flags speak camelCase.\nfunction normalizeFlags(values) {\n const out: Record<string, any> = {};\n for (const [k, v] of Object.entries(values)) {\n const key = k.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n out[key] = v;\n }\n return out;\n}\n\n// `parseArgs` cannot express a negated boolean. `--color=false` is rejected\n// outright, `--color false` sets `color: true` and leaves `false` behind as a\n// positional, and `--no-color` is an unknown option — so the documented flag\n// had never worked, for any command, and `--no-color status` would try to run a\n// command called `no-color`.\n//\n// There is no parser-level spelling for \"this boolean is false\", so the flag is\n// lifted out of argv before parsing and applied to the parsed flags after. That\n// keeps `parseArgs` strict about genuinely unknown options (which is the point\n// of a tool that writes a config file) while making the one negation the CLI\n// documents actually work.\nfunction extractNegatedFlags(argv) {\n const rest = [];\n let noColor = false;\n for (const arg of argv) {\n if (arg === '--no-color') noColor = true;\n else rest.push(arg);\n }\n return { argv: rest, noColor };\n}\n\nexport async function main(argv = process.argv.slice(2)) {\n const { argv: argsIn, noColor } = extractNegatedFlags(argv);\n let parsed;\n try {\n parsed = parseArgs({ args: argsIn, options: OPTIONS, allowPositionals: true });\n } catch (e) {\n console.error(' ' + e.message + '\\n' + HELP);\n return 2;\n }\n const { values, positionals } = parsed;\n const flags = normalizeFlags(values);\n\n // Color is decided here, after the flags exist and before anything is\n // painted. An explicit `--no-color` wins over `FORCE_COLOR`: a person who\n // typed the flag meant it, and a stray `FORCE_COLOR` inherited from a CI\n // profile should not override the thing they just asked for.\n if (noColor) {\n flags.color = false;\n setColorEnabled(false);\n } else if (flags.color === true) {\n // `--color` was accepted by the parser and then ignored, which is the same\n // lie in the other direction. It is the documented way to keep ANSI in a\n // captured log, so it has to actually turn color on.\n setColorEnabled(true);\n }\n\n if (flags.help && ['chat', 'tui'].includes(positionals[0])) { console.log(CHAT_HELP); return 0; }\n if (flags.help && positionals[0] !== 'agent') { console.log(HELP); return 0; }\n if (flags.version) { console.log(PACKAGE.version); return 0; }\n\n const [cmd, sub, ...rest] = positionals;\n try {\n switch (cmd) {\n case 'agent': {\n if (sub === 'chat') {\n if (rest.length > 1) throw new Error('Use one repository folder: onboarder agent chat [folder].');\n return runChat({ target: rest[0], flags, version: PACKAGE.version });\n }\n const abort = new AbortController();\n const cancel = () => abort.abort(); process.once('SIGINT', cancel); process.once('SIGTERM', cancel);\n try { return await agentCommand(sub, rest, flags, { signal: abort.signal }); }\n finally { process.off('SIGINT', cancel); process.off('SIGTERM', cancel); }\n }\n case 'help':\n console.log(HELP);\n return 0;\n case undefined:\n // Chat on a terminal; retain server behavior for existing scripts.\n if (!flags.server && process.stdin.isTTY && process.stdout.isTTY) {\n return codeOf(await runChat({ flags, version: PACKAGE.version }));\n }\n return codeOf(await runStart({ flags }));\n case 'explore':\n case 'shell':\n return codeOf(await runExplore({ flags, target: sub }));\n case 'chat':\n case 'tui':\n if (rest.length) throw new Error('Use one repository folder: onboarder chat [folder].');\n return codeOf(await runChat({ flags, target: sub, version: PACKAGE.version }));\n case 'report': {\n const repo = await openRepoOrClone(sub || '.', scanOptionsFromFlags(flags));\n try {\n const report = createReport(repo);\n console.log(flags.json ? JSON.stringify(report, null, 2) : formatReport(report));\n return 0;\n } finally {\n await closeRemote(repo);\n }\n }\n case 'review': {\n if (flags.staged && flags.head) throw new Error('Choose either --staged or --head.');\n if (flags.failOn && !Object.hasOwn(SEVERITY_RANK, flags.failOn)) throw new Error('Choose a valid --fail-on severity: critical, high, medium, low, or info.');\n const report = await runReview(expandHome(sub || '.'), { base: flags.base || 'HEAD', head: flags.head || '', mode: flags.staged ? 'staged' : flags.head ? 'range' : 'working', profile: flags.profile ? reviewProfile(flags.profile) : undefined });\n console.log(flags.json ? JSON.stringify(report, null, 2) : reviewMarkdown(report));\n return flags.failOn && report.findings.some(f => SEVERITY_RANK[f.severity] >= SEVERITY_RANK[flags.failOn]) || report.checks.some(c => c.id === 'conflicts' && c.status === 'fail') ? 1 : 0;\n }\n case 'web':\n case 'site':\n return codeOf(await runStart({ flags }));\n case 'start':\n // `onboarder start [background|fg|startup [action]]`. The sub-verb is a\n // positional, not a flag, because `onboarder start` has to keep working\n // exactly as it did and `startup install` is a different verb from\n // `start`.\n if (sub === 'background' || sub === 'bg' || sub === 'daemon' || sub === 'detached') {\n return codeOf(await runStartBackground({ flags }));\n }\n if (sub === 'startup' || sub === 'login' || sub === 'autostart') {\n return codeOf(await runStartup(rest[0] || 'status', { flags }));\n }\n if (sub === 'fg' || sub === 'foreground') return codeOf(await runStart({ flags }));\n if (sub === 'status') return codeOf(await runStatus({ flags }));\n if (sub === 'stop') return codeOf(await runStop({ flags }));\n if (sub === 'logs') return codeOf(await runLogs({ flags }));\n if (sub) {\n console.error(' Unknown start mode: ' + sub + '\\n' + HELP);\n return 2;\n }\n return codeOf(await runStart({ flags }));\n case 'logs':\n case 'log':\n return codeOf(await runLogs({ flags }));\n case 'startup':\n case 'autostart':\n return codeOf(await runStartup(sub || 'status', { flags }));\n case 'status':\n return codeOf(await runStatus({ flags }));\n case 'stop':\n return codeOf(await runStop({ flags }));\n case 'restart':\n return codeOf(await runRestart({ flags }));\n case 'setup':\n case 'onboard':\n case 'init':\n return codeOf(await runSetup({ flags, version: PACKAGE.version }));\n case 'config':\n if (sub === 'key') return codeOf(await runConfigKey(rest[0], rest.slice(1), { flags }));\n if (sub === 'reset') return codeOf(await runConfigReset({ flags }));\n return codeOf(await runConfig(sub || 'show', rest, { flags }));\n case 'tunnel':\n return codeOf(await runTunnel(sub, { flags }));\n case 'https':\n return codeOf(await runHttps(sub || 'status', { flags }));\n case 'doctor':\n return codeOf(await runDoctor({ flags }));\n default:\n if (isRemoteSource(cmd)) {\n if (sub) throw new Error('Use onboarder chat <GitHub URL>, then type your question.');\n return codeOf(await runChat({ target: cmd, flags, version: PACKAGE.version }));\n }\n console.error(' Unknown command: ' + cmd + '\\n' + HELP);\n return 2;\n }\n } catch (e) {\n console.error(' ' + (e.message || e));\n return 1;\n }\n}\n\n// Commands return an exit code or, for `start`, an object carrying the live\n// server. Both collapse to \"what code should the process eventually use\".\nfunction codeOf(result) {\n return typeof result === 'number' ? result : result?.code ?? 0;\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Hermes integration research
|
|
2
|
+
|
|
3
|
+
Research date: 2026-10-03. Official source: [NousResearch/hermes-agent](https://github.com/NousResearch/hermes-agent), revision [`eb7e8620324b32424c06218f6a28094df2e921f8`](https://github.com/NousResearch/hermes-agent/tree/eb7e8620324b32424c06218f6a28094df2e921f8). Upstream is MIT licensed, copyright Nous Research. The installed runtime used for integration testing reports `0.21.5+2584.g1c535d9`; the harness tests its required CLI interfaces rather than assuming that version string alone proves compatibility.
|
|
4
|
+
|
|
5
|
+
## Findings and implementation choice
|
|
6
|
+
|
|
7
|
+
Hermes supplies the model/provider routing, iterative agent loop, sessions, streaming, tool selection, skills, memory and integrations. Its core runtime is Python. Onboarder is a TypeScript/Node application with no npm runtime dependencies. A separate Hermes subprocess plus a scoped MCP server lets both projects retain their existing runtime contracts. No Hermes source files or Python package tree are copied into Onboarder. See the official [architecture guide](https://hermes-agent.nousresearch.com/docs/developer-guide/architecture/) and [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp/).
|
|
8
|
+
|
|
9
|
+
The source was pulled and inspected before implementation. The following upstream files establish the actual contract used by this harness:
|
|
10
|
+
|
|
11
|
+
| Upstream source | Verified behavior | Harness use |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| `hermes_cli/main.py`, `hermes_cli/_parser.py` | One-shot chat, stdin query files, structured format, turn and wall-clock limits, model overrides and session resume | Argument arrays with `--query-file -`; bounded subprocess lifecycle |
|
|
14
|
+
| `hermes_cli/stream_json.py` | JSONL `system`, `text`, `tool_use`, `tool_result`, `result` events; terminal text, exit code, session ID, usage | Typed event validation; successful completion requires both terminal result and successful process exit |
|
|
15
|
+
| `hermes_cli/mcp_startup.py` | `--toolsets` filters which configured MCP servers start | Only the dedicated `onboarder` server is selected |
|
|
16
|
+
| `hermes_cli/_launchers.py`, `model_switch_providers.py`, `model_switch.py` | Installation-bound runtime command, native model catalog, credential resolution, model selection and persistence | Searchable inline provider/model picker; only display fields cross the Python/Node boundary; full `hermes model` setup remains available |
|
|
17
|
+
| `tools/mcp_tool_config.py` | Stdio children receive a filtered environment; `${VAR}` values in explicit server config are interpolated | Explicit run-manifest and GitHub token placeholders; no assumption that ambient secrets reach MCP |
|
|
18
|
+
| `tools/mcp_tool_registration.py` | Server-name aliases resolve to dynamically registered MCP toolsets | `--toolsets onboarder` selects the scoped tools |
|
|
19
|
+
| `tools/mcp_tool_schema.py` | Tool names follow `mcp__<server>__<tool>` with bounded names | Real-runtime fixture verifies discovered tools belong to Onboarder |
|
|
20
|
+
| `tools/tool_search.py`, `hermes_cli/config_defaults.py` | MCP tools may be collapsed behind progressive-discovery bridge tools by default | The dedicated profile uses `tools.tool_search.enabled: off` so this small fixed catalog is explicit |
|
|
21
|
+
| `hermes_constants.py`, `pm/environments.py` | Named profiles share installation dependency state while having separate config/data | A stable named Onboarder profile supports current source installs without duplicating Python packages |
|
|
22
|
+
|
|
23
|
+
Changing `HERMES_HOME` to an arbitrary directory initially exposed a current-source-install issue: its Python dependency selection is also rooted there. The integration uses an installation-root named profile instead. A live local fixture also caught progressive tool disclosure: the initial model surface contained three bridge tools. Making the scoped catalog explicit resolved this and allowed verification of all 37 exposed tool names.
|
|
24
|
+
|
|
25
|
+
## Workflow coverage
|
|
26
|
+
|
|
27
|
+
The CLI supports repository Q&A, local/PR review, issue triage, isolated implementation, draft PR preparation/publishing, and general GitHub tasks. It reuses Onboarder's scan, architecture, dependencies, health, security, history, tour and search engines. Additional tools cover bounded text reads/edits, working diffs, deterministic local review, npm checks, repository facts, issue/PR lists and details, source at exact commit SHAs, review discussions, labels, exact-head check runs, CI workflows/jobs, issue creation/updates, comments, PR review submission and draft PR creation.
|
|
28
|
+
|
|
29
|
+
GitHub routes are pinned to the checkout's github.com origin. PR files are capped at 300, ordinary paginated lists at 200, and CI collections at 100; truncation and missing patches are reported. Local source is explicitly distinguished from a remote PR's head. PR review submission includes the expected commit SHA and checks that the head has not changed.
|
|
30
|
+
|
|
31
|
+
Exact-commit source reads traverse immutable Git trees and check file modes before reading a blob. They reject symlinks/submodules and incomplete trees. This uses the documented [Git tree modes](https://docs.github.com/en/rest/git/trees#get-a-tree) and [Git blob API](https://docs.github.com/en/rest/git/blobs#get-a-blob). Review writes bind their evidence to `commit_id` as documented in [GitHub's review API](https://docs.github.com/en/rest/pulls/reviews#create-a-review-for-a-pull-request).
|
|
32
|
+
|
|
33
|
+
Implementation starts in a Git worktree at committed HEAD on its own `codex/agent-…` branch. Fresh file hashes prevent stale overwrites. `--allow-checks` and `--allow-github-writes` are separate, enforced capabilities; neither is enabled by default. Fixed check commands use argument arrays. Draft publishing verifies origin and branch, disables Git commit/push hooks for those commands, pushes only the task branch without force, checks for an existing PR and creates a draft. This integration does not include automatic merging, GitHub Enterprise origins, webhook hosting, sandboxed script execution, or a background review bot.
|
|
34
|
+
|
|
35
|
+
## Lifecycle and data handling
|
|
36
|
+
|
|
37
|
+
Onboarder stores manifests, final results, event metadata and operation audits with private file permissions. Hermes keeps its own session transcripts inside the dedicated profile. Audit entries omit tool arguments, source and comment bodies; transcripts/final answers can contain source. Known environment credentials are redacted from Onboarder output. A configured model receives selected repository and GitHub content when a task runs.
|
|
38
|
+
|
|
39
|
+
The Node supervisor imposes output, turn and time limits and cancels its process group on POSIX. The stdio server watches its parent because some Hermes releases start MCP children in separate process groups. Windows uses process-tree termination. Worktrees remain inspectable on failure. Resume pins the original repository/workspace and cannot expand permissions. A recorded completion describes the agent run; a model's claims still need the associated tool evidence, and check results remain visible in its transcript.
|
|
40
|
+
|
|
41
|
+
## Validation and practical limits
|
|
42
|
+
|
|
43
|
+
Automated fixtures cover path containment, symlinks, stale edits, subprocess Unicode/framing, cancellation/timeouts/output limits, GitHub identity/authentication/pagination/errors, capability enforcement, write deduplication, PR coverage/exact-head checks, structured completion, isolated worktrees, saved failures, dry runs and bounded resume permissions. The existing MCP transport and explorer command table continue to be exercised by their regression tests.
|
|
44
|
+
|
|
45
|
+
`node scripts/hermes-smoke.mjs` runs the actual installed Hermes runtime against a loopback OpenAI-compatible model fixture. It verifies the native model catalog, model selection and profile persistence, tool selection, MCP discovery, a real context-tool invocation, structured streaming and saved audit/result files. It makes no paid model call or GitHub mutation. Live provider authentication and actual GitHub issue/review/PR publishing require the user's model and GitHub credentials and are not claimed as exercised by this fixture.
|
|
46
|
+
|
|
47
|
+
The chat welcome, composer and inline `/model` menu were compared with the installed interactive Hermes CLI on October 3, 2026. An unconfigured Onboarder profile offers model/provider setup or offline browsing. The full official model wizard owns the terminal exclusively: the parent input stream is paused during the handoff and resumed afterward. Native terminal tests cover keystroke delivery, startup setup, cancellation, model-menu search and keeping the existing conversation when no selection succeeds. The quick picker uses the published launcher command and verifies its bootstrap shape; installations without that boundary fall back to the full wizard.
|
|
48
|
+
|
|
49
|
+
The full-screen chat uses the terminal's alternate buffer, a bottom-pinned composer, and a bounded, scrollable transcript. Resizing reflows both the welcome and conversation; only changed rows are painted. Model setup temporarily restores the original terminal buffer, and chat restores its viewport and draft afterward. Native terminal tests resize a running chat and verify that exit returns to the shell. Onboarder's original code-compass mark replaces the Hermes-inspired mascot, with full/compact terminal representations and a reusable SVG.
|
|
50
|
+
|
|
51
|
+
The harness requires a compatible Hermes installation. `agent doctor` checks the CLI flags, compiled MCP entry point and profile presence; it does not verify provider credentials or GitHub token scopes. Upstream interfaces can evolve; update the source revision and rerun both fixtures and the live-runtime smoke before expanding compatibility claims.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codebase-onboarder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Drop a path. Get a map. A zero-dependency codebase visualizer with a CLI onboarding wizard, a web UI, and an optional key-gated self-hosted mode.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"server",
|
|
14
14
|
"shared",
|
|
15
15
|
"public",
|
|
16
|
+
"docs/HERMES_RESEARCH.md",
|
|
16
17
|
"README.md",
|
|
17
18
|
"LICENSE"
|
|
18
19
|
],
|
package/public/app.js
CHANGED
|
@@ -26,9 +26,9 @@ import { overviewDiagram, folderDiagram, fileDetailDiagram, servicesDiagram, emp
|
|
|
26
26
|
import { analyzeHealth } from '/shared/analyzer/health.js';
|
|
27
27
|
import { summarizeSecurity } from '/shared/analyzer/security.js';
|
|
28
28
|
import { escapeHtml } from '/js/html.js';
|
|
29
|
-
import { scanOnServer, cleanupClone, streamExplain, fetchMcpStatus, startMcpServer, stopMcpServer, fetchMcpCommand, } from '/js/api.js';
|
|
29
|
+
import { scanOnServer, cleanupClone, streamExplain, fetchMcpStatus, startMcpServer, stopMcpServer, fetchMcpCommand, fetchHermesStatus, } from '/js/api.js';
|
|
30
30
|
import { canPickFolder, pickDirectory, browserFileSource } from '/js/fileSourceBrowser.js';
|
|
31
|
-
import { renderInto, wireNodeClicks, makePanzoom, downloadSvg } from '/js/diagramPane.js';
|
|
31
|
+
import { renderInto, validateDiagram, wireNodeClicks, makePanzoom, downloadSvg } from '/js/diagramPane.js';
|
|
32
32
|
import { setViewerTheme } from '/js/codeViewer.js';
|
|
33
33
|
import * as llm from '/js/llm.js';
|
|
34
34
|
import { buildTree, renderTree, resetOpenState, expandedToDepth } from '/js/tree.js';
|
|
@@ -41,7 +41,7 @@ import { initDocs, renderDocs } from '/js/docsView.js';
|
|
|
41
41
|
import { initCodeTab, renderCode, revealLineInCode } from '/js/codeTab.js';
|
|
42
42
|
import { initAnalysisPanel, renderAnalysisPanel, subscribeAnalysis } from '/js/analysisPanel.js';
|
|
43
43
|
import { initDeepAnalysis, renderDeepAnalysis } from '/js/deepAnalysisView.js';
|
|
44
|
-
import { initAiDraft, updateAiBtn, wireAIClicks } from '/js/aiDraft.js';
|
|
44
|
+
import { initAiDraft, updateAiBtn, wireAIClicks, stopAiDraft } from '/js/aiDraft.js';
|
|
45
45
|
import { initAtlas, renderAtlasList, openCardDiagram } from '/js/atlas.js';
|
|
46
46
|
import { initForceGraph } from '/js/forceGraph.js';
|
|
47
47
|
import { initHeatmap } from '/js/heatmap.js';
|
|
@@ -67,6 +67,7 @@ const dom = {};
|
|
|
67
67
|
'tourbar', 'tourTitle', 'tourCount', 'tourPrev', 'tourNext', 'tourExit',
|
|
68
68
|
'drawerScrim', 'settingsDrawer', 'drawerClose', 'setBaseUrl', 'setApiKey', 'setModel',
|
|
69
69
|
'saveSettings', 'testSettings', 'settingsStatus', 'toast', 'brandNote', 'askBtn', 'askInput',
|
|
70
|
+
'setConnection', 'apiConnection', 'hermesConnection', 'hermesConnectionStatus', 'hermesModel', 'hermesProvider', 'refreshHermes', 'aiConnectionNote',
|
|
70
71
|
'graphView', 'graphCanvas', 'graphControls', 'graphReset', 'graphZoomIn', 'graphZoomOut', 'graphFit', 'graphSearchInput', 'graphTooltip',
|
|
71
72
|
'heatmapView', 'heatmapCanvas', 'heatmapTooltip', 'blameGutter', 'codeTabContainer',
|
|
72
73
|
'insightsView', 'diffView', 'reviewView', 'workflowsView', 'sbomView', 'searchTriggerBtn', 'inspSecurityTools', 'analysisView',
|
|
@@ -237,6 +238,7 @@ if (!canPickFolder()) {
|
|
|
237
238
|
}
|
|
238
239
|
// -------------------------------------------------------------- explorer --
|
|
239
240
|
function enterExplorer(payload, opts) {
|
|
241
|
+
stopAiDraft();
|
|
240
242
|
loadRepo(payload, {
|
|
241
243
|
browserSource: opts.browserSource || null,
|
|
242
244
|
history: payload.history || null, // computed server-side; null for browser picks
|
|
@@ -291,6 +293,7 @@ function buildPatterns(scan, facts, manifest) {
|
|
|
291
293
|
};
|
|
292
294
|
}
|
|
293
295
|
dom.newRepoBtn.addEventListener('click', () => {
|
|
296
|
+
stopAiDraft();
|
|
294
297
|
stopReview();
|
|
295
298
|
stopDiff();
|
|
296
299
|
mobilePanels.close();
|
|
@@ -478,6 +481,7 @@ document.addEventListener('heatmap-node-click', (event) => {
|
|
|
478
481
|
openFile(event.detail.path);
|
|
479
482
|
});
|
|
480
483
|
async function renderCanvas() {
|
|
484
|
+
updateAiBtn();
|
|
481
485
|
const isDocs = state.view === 'docs';
|
|
482
486
|
const isAbout = state.view === 'about';
|
|
483
487
|
const isCode = state.view === 'code';
|
|
@@ -587,12 +591,14 @@ async function renderCanvas() {
|
|
|
587
591
|
const key = aiViewKey();
|
|
588
592
|
updateAiBtn(key);
|
|
589
593
|
// Tree-map furniture only belongs to the Map; SVG export can't take cells.
|
|
590
|
-
|
|
594
|
+
const showingSketch = state.aiActiveKey === key && Boolean(state.aiDiagrams[key]);
|
|
595
|
+
dom.svgBtn.hidden = isPage || isAtlasList || (state.view === 'map' && !showingSketch);
|
|
596
|
+
dom.mmToggleBtn.hidden = state.view !== 'map' || showingSketch;
|
|
591
597
|
const filterable = ['map', 'files', 'patterns'].includes(state.view);
|
|
592
|
-
dom.nodeFilter.hidden = !filterable && state.view !== 'atlas';
|
|
593
|
-
dom.testsToggle.hidden = !filterable && state.view !== 'atlas';
|
|
594
|
-
dom.depthSelect.hidden = state.view !== 'map';
|
|
595
|
-
if (state.view === 'map') {
|
|
598
|
+
dom.nodeFilter.hidden = showingSketch || (!filterable && state.view !== 'atlas');
|
|
599
|
+
dom.testsToggle.hidden = showingSketch || (!filterable && state.view !== 'atlas');
|
|
600
|
+
dom.depthSelect.hidden = showingSketch || state.view !== 'map';
|
|
601
|
+
if (state.view === 'map' && !showingSketch) {
|
|
596
602
|
// Copy Mermaid still hands over the classic folder overview.
|
|
597
603
|
state.currentDiagram = { source: overviewDiagram(scan, facts).source, nodes: {} };
|
|
598
604
|
renderMap(true);
|
|
@@ -733,7 +739,7 @@ function nothingToShow() {
|
|
|
733
739
|
// not. The Map redraws in place, everything else goes through the canvas router.
|
|
734
740
|
let filterTimer = null;
|
|
735
741
|
function applyFilters() {
|
|
736
|
-
if (state.view === 'map')
|
|
742
|
+
if (state.view === 'map' && state.aiActiveKey !== aiViewKey())
|
|
737
743
|
renderMap(false);
|
|
738
744
|
else
|
|
739
745
|
renderCanvas();
|
|
@@ -951,6 +957,7 @@ initAiDraft({
|
|
|
951
957
|
statusEl: dom.canvasEmpty, // the placeholder doubles as the progress line
|
|
952
958
|
nodeHost: dom.canvasContent,
|
|
953
959
|
onRender: renderCanvas,
|
|
960
|
+
onValidate: source => validateDiagram(diagramThemeBlock() + '\n' + source),
|
|
954
961
|
onOpenFile: openFile,
|
|
955
962
|
onOpenSettings: openSettings,
|
|
956
963
|
onToast: toast,
|
|
@@ -982,7 +989,7 @@ function repoOverview() {
|
|
|
982
989
|
async function askAI() {
|
|
983
990
|
if (!llm.isConfigured()) {
|
|
984
991
|
openSettings();
|
|
985
|
-
toast('
|
|
992
|
+
toast('Choose Hermes or an endpoint in AI connection first.');
|
|
986
993
|
return;
|
|
987
994
|
}
|
|
988
995
|
if (!state.selected)
|
|
@@ -1004,7 +1011,7 @@ async function askAI() {
|
|
|
1004
1011
|
writer.finish(`Written by ${settings.model}, from the real source and the import graph.`);
|
|
1005
1012
|
}
|
|
1006
1013
|
catch (err) {
|
|
1007
|
-
writer.fail(err.message + ' Check the
|
|
1014
|
+
writer.fail(err.message + ' Check the AI connection drawer, top right.');
|
|
1008
1015
|
}
|
|
1009
1016
|
}
|
|
1010
1017
|
// Free-form questions. The selected file's context rides along when there is
|
|
@@ -1017,7 +1024,7 @@ async function askCustom() {
|
|
|
1017
1024
|
return;
|
|
1018
1025
|
if (!llm.isConfigured()) {
|
|
1019
1026
|
openSettings();
|
|
1020
|
-
toast('
|
|
1027
|
+
toast('Choose Hermes or an endpoint in AI connection first.');
|
|
1021
1028
|
return;
|
|
1022
1029
|
}
|
|
1023
1030
|
const settings = llm.getSettings();
|
|
@@ -1038,7 +1045,7 @@ async function askCustom() {
|
|
|
1038
1045
|
writer.finish(`Answered by ${settings.model}.`);
|
|
1039
1046
|
}
|
|
1040
1047
|
catch (err) {
|
|
1041
|
-
writer.fail(err.message + ' Check the
|
|
1048
|
+
writer.fail(err.message + ' Check the AI connection drawer, top right.');
|
|
1042
1049
|
}
|
|
1043
1050
|
finally {
|
|
1044
1051
|
dom.askBtn.disabled = false;
|
|
@@ -1051,20 +1058,74 @@ dom.askInput.addEventListener('keydown', (event) => {
|
|
|
1051
1058
|
askCustom();
|
|
1052
1059
|
});
|
|
1053
1060
|
// ---------------------------------------------------------- settings bits --
|
|
1061
|
+
let hermesInfo = null;
|
|
1062
|
+
let connectionCheck = null;
|
|
1063
|
+
let connectionTest = null;
|
|
1064
|
+
async function refreshHermes() {
|
|
1065
|
+
connectionCheck?.abort();
|
|
1066
|
+
const controller = connectionCheck = new AbortController();
|
|
1067
|
+
hermesInfo = null;
|
|
1068
|
+
dom.hermesConnectionStatus.textContent = 'Checking your Hermes configuration…';
|
|
1069
|
+
dom.hermesModel.textContent = dom.hermesProvider.textContent = '—';
|
|
1070
|
+
dom.saveSettings.disabled = dom.testSettings.disabled = true;
|
|
1071
|
+
dom.refreshHermes.disabled = true;
|
|
1072
|
+
try {
|
|
1073
|
+
const info = await fetchHermesStatus(controller.signal);
|
|
1074
|
+
if (controller.signal.aborted)
|
|
1075
|
+
return;
|
|
1076
|
+
hermesInfo = info;
|
|
1077
|
+
dom.hermesConnectionStatus.textContent = info.message;
|
|
1078
|
+
dom.hermesModel.textContent = info.model || 'Choose in your terminal';
|
|
1079
|
+
dom.hermesProvider.textContent = info.provider || 'Not configured';
|
|
1080
|
+
dom.saveSettings.disabled = dom.testSettings.disabled = !info.available || !info.configured;
|
|
1081
|
+
}
|
|
1082
|
+
catch (err) {
|
|
1083
|
+
if (!controller.signal.aborted)
|
|
1084
|
+
dom.hermesConnectionStatus.textContent = err.message;
|
|
1085
|
+
}
|
|
1086
|
+
finally {
|
|
1087
|
+
if (connectionCheck === controller)
|
|
1088
|
+
dom.refreshHermes.disabled = false;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
function syncAIConnection() {
|
|
1092
|
+
connectionCheck?.abort();
|
|
1093
|
+
connectionTest?.abort();
|
|
1094
|
+
const hermes = dom.setConnection.value === 'hermes';
|
|
1095
|
+
dom.apiConnection.hidden = hermes;
|
|
1096
|
+
dom.hermesConnection.hidden = !hermes;
|
|
1097
|
+
dom.saveSettings.disabled = dom.testSettings.disabled = false;
|
|
1098
|
+
dom.settingsStatus.textContent = '';
|
|
1099
|
+
dom.aiConnectionNote.textContent = hermes
|
|
1100
|
+
? 'Hermes keeps your login on the server. Only the connection choice is saved in this browser. AI features send the displayed repository context to your Hermes provider.'
|
|
1101
|
+
: 'Endpoint settings are saved in this browser. The key is forwarded through your server and never written to its disk or logs.';
|
|
1102
|
+
if (hermes)
|
|
1103
|
+
void refreshHermes();
|
|
1104
|
+
}
|
|
1105
|
+
function readAISettings() {
|
|
1106
|
+
return { connection: dom.setConnection.value, hermesModel: hermesInfo?.model || '',
|
|
1107
|
+
baseUrl: dom.setBaseUrl.value.trim().replace(/\/+$/, ''), apiKey: dom.setApiKey.value, model: dom.setModel.value.trim() };
|
|
1108
|
+
}
|
|
1109
|
+
dom.setConnection.addEventListener('change', syncAIConnection);
|
|
1110
|
+
dom.refreshHermes.addEventListener('click', () => { void refreshHermes(); });
|
|
1054
1111
|
function openSettings() {
|
|
1055
1112
|
// Same reason the MCP drawer closes settings: one scrim at a time.
|
|
1056
1113
|
if (!dom.mcpDrawer.hidden)
|
|
1057
1114
|
closeMcp();
|
|
1058
1115
|
serverDrawer.close();
|
|
1059
|
-
const s = llm.getSettings();
|
|
1116
|
+
const s = llm.getSettings(false);
|
|
1117
|
+
dom.setConnection.value = s.connection;
|
|
1060
1118
|
dom.setBaseUrl.value = s.baseUrl;
|
|
1061
1119
|
dom.setApiKey.value = s.apiKey;
|
|
1062
1120
|
dom.setModel.value = s.model;
|
|
1063
1121
|
dom.settingsStatus.textContent = '';
|
|
1064
1122
|
dom.settingsDrawer.hidden = false;
|
|
1065
1123
|
dom.drawerScrim.hidden = false;
|
|
1124
|
+
syncAIConnection();
|
|
1066
1125
|
}
|
|
1067
1126
|
function closeSettings() {
|
|
1127
|
+
connectionCheck?.abort();
|
|
1128
|
+
connectionTest?.abort();
|
|
1068
1129
|
dom.settingsDrawer.hidden = true;
|
|
1069
1130
|
dom.drawerScrim.hidden = true;
|
|
1070
1131
|
}
|
|
@@ -1283,41 +1344,54 @@ dom.mcpStop.addEventListener('click', () => setMcpState('stop'));
|
|
|
1283
1344
|
scheduleMcpPoll(0);
|
|
1284
1345
|
dom.drawerScrim.addEventListener('click', closeSettings);
|
|
1285
1346
|
dom.saveSettings.addEventListener('click', () => {
|
|
1286
|
-
|
|
1347
|
+
stopAiDraft();
|
|
1348
|
+
llm.saveSettings(readAISettings());
|
|
1287
1349
|
dom.settingsStatus.className = 'drawer-status ok';
|
|
1288
|
-
dom.settingsStatus.textContent = 'Saved in this browser.';
|
|
1350
|
+
dom.settingsStatus.textContent = dom.setConnection.value === 'hermes' ? 'Hermes connected. Your AI features now use its configured login.' : 'Saved in this browser.';
|
|
1351
|
+
updateAiBtn();
|
|
1352
|
+
if (state.scan) {
|
|
1353
|
+
syncInspector();
|
|
1354
|
+
void renderCanvas();
|
|
1355
|
+
}
|
|
1289
1356
|
});
|
|
1290
1357
|
dom.testSettings.addEventListener('click', async () => {
|
|
1291
|
-
const settings =
|
|
1292
|
-
|
|
1293
|
-
apiKey: dom.setApiKey.value,
|
|
1294
|
-
model: dom.setModel.value.trim(),
|
|
1295
|
-
};
|
|
1296
|
-
if (!settings.baseUrl || !settings.model) {
|
|
1358
|
+
const settings = readAISettings();
|
|
1359
|
+
if (settings.connection !== 'hermes' && (!settings.baseUrl || !settings.model)) {
|
|
1297
1360
|
dom.settingsStatus.className = 'drawer-status err';
|
|
1298
1361
|
dom.settingsStatus.textContent = 'Base URL and model are both needed.';
|
|
1299
1362
|
return;
|
|
1300
1363
|
}
|
|
1301
1364
|
dom.settingsStatus.className = 'drawer-status';
|
|
1302
|
-
dom.settingsStatus.textContent = 'Asking the endpoint…';
|
|
1365
|
+
dom.settingsStatus.textContent = settings.connection === 'hermes' ? 'Asking Hermes… first response may take a moment.' : 'Asking the endpoint…';
|
|
1366
|
+
const controller = connectionTest = new AbortController();
|
|
1367
|
+
dom.testSettings.disabled = true;
|
|
1303
1368
|
try {
|
|
1304
1369
|
let heard = '';
|
|
1305
1370
|
for await (const delta of streamExplain({
|
|
1306
1371
|
...settings,
|
|
1372
|
+
signal: controller.signal,
|
|
1307
1373
|
maxTokens: 64,
|
|
1308
1374
|
messages: [{ role: 'user', content: 'Reply with the single word: ready' }],
|
|
1309
1375
|
})) {
|
|
1310
1376
|
heard += delta;
|
|
1311
1377
|
}
|
|
1378
|
+
if (controller.signal.aborted)
|
|
1379
|
+
return;
|
|
1312
1380
|
dom.settingsStatus.className = 'drawer-status ok';
|
|
1313
1381
|
dom.settingsStatus.textContent = heard
|
|
1314
|
-
? `Connected — ${settings.model} answered.`
|
|
1382
|
+
? `Connected — ${settings.connection === 'hermes' ? 'Hermes · ' + settings.hermesModel : settings.model} answered. Save to use this connection.`
|
|
1315
1383
|
: `Connected. It answered with silence, but that is a thinking model spending its whole token budget on thought — explanations use a bigger one.`;
|
|
1316
1384
|
}
|
|
1317
1385
|
catch (err) {
|
|
1386
|
+
if (controller.signal.aborted)
|
|
1387
|
+
return;
|
|
1318
1388
|
dom.settingsStatus.className = 'drawer-status err';
|
|
1319
1389
|
dom.settingsStatus.textContent = err.message;
|
|
1320
1390
|
}
|
|
1391
|
+
finally {
|
|
1392
|
+
if (connectionTest === controller && !controller.signal.aborted)
|
|
1393
|
+
dom.testSettings.disabled = false;
|
|
1394
|
+
}
|
|
1321
1395
|
});
|
|
1322
1396
|
// ------------------------------------------------------------------- misc --
|
|
1323
1397
|
let toastTimer = null;
|