@k-leumas/queque-cli 0.1.0 → 0.2.0-beta.2

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 CHANGED
@@ -1,178 +1,92 @@
1
1
  # QueQue
2
2
 
3
- QueQue is a `zsh`-integrated command helper that is intended to open from a literal `??` trigger in your live shell buffer, gather the text around the cursor, and return an explainable shell command back into the buffer instead of executing it for you.
3
+ **Turn natural-language intent into a shell command — without leaving the terminal.**
4
4
 
5
- ## Current Status
5
+ Type your intent, hit `??`, pick a command. It lands in your buffer ready to run or edit. No browser, no prompt takeover, no clipboard gymnastics.
6
6
 
7
- This repository is still in early Phase 1.
7
+ <!-- demo gif goes here -->
8
8
 
9
- - The TypeScript CLI scaffold exists.
10
- - The `qq client` and `qq daemon` command surfaces exist.
11
- - The real `zsh` widget and shell sourcing script do **not** exist yet.
9
+ ## Install
12
10
 
13
- That means you can wire up the CLI for active development today, but you cannot yet source a finished `??` shell integration from this repo.
11
+ **Homebrew (recommended)**
14
12
 
15
- ## Prerequisites
16
-
17
- - `zsh`
18
- - Node `24.14.1`
19
- - `pnpm`
20
-
21
- If you use `nvm`:
22
-
23
- ```bash
24
- nvm use
25
- corepack enable
26
- pnpm install
13
+ ```zsh
14
+ brew tap k-leumas/queque
15
+ brew install queque-cli
27
16
  ```
28
17
 
29
- ## Local Development
30
-
31
- Install dependencies and start the watch build in one terminal:
18
+ **npm**
32
19
 
33
- ```bash
34
- pnpm install
35
- pnpm dev
20
+ ```zsh
21
+ npm install -g @k-leumas/queque-cli
36
22
  ```
37
23
 
38
- That keeps `dist/cli/main.js` rebuilt as you edit `src/cli/main.ts`.
24
+ ## Setup
39
25
 
40
- If you want a simple restart wrapper that logs when it reacts to file changes, run:
26
+ Add the shell integration to your `.zshrc`:
41
27
 
42
- ```bash
43
- pnpm dev:restart
44
- ```
45
-
46
- It rebuilds first, then starts the dev command, and logs when it sees a change and restarts.
47
-
48
- In another terminal, use the current checks:
49
-
50
- ```bash
51
- pnpm typecheck
52
- pnpm test:run
53
- pnpm build
54
- ```
55
-
56
- ## Load The CLI In Your Shell Today
57
-
58
- Because the project already defines a `qq` bin that points at `dist/cli/main.js`, the simplest development setup is to add a shell function that executes the built file from your checkout.
59
-
60
- Add this to `~/.zshrc`:
61
-
62
- ```bash
63
- export QQ_DEV_ROOT="$HOME/dev/queque"
64
-
65
- qq() {
66
- node "$QQ_DEV_ROOT/dist/cli/main.js" "$@"
67
- }
68
- ```
69
-
70
- Then reload your shell:
71
-
72
- ```bash
28
+ ```zsh
29
+ qq init zsh >> ~/.zshrc
73
30
  source ~/.zshrc
74
31
  ```
75
32
 
76
- With `pnpm dev` running, every rebuild updates the code behind `qq` immediately.
77
-
78
- ## Live Debug Log
79
-
80
- For shell/widget debugging, you can opt into a plain-text log by setting:
33
+ Set your Anthropic API key:
81
34
 
82
- ```bash
83
- export QQ_DEBUG_LOG_FILE=/tmp/qq-debug.log
35
+ ```zsh
36
+ export ANTHROPIC_API_KEY="sk-ant-..."
84
37
  ```
85
38
 
86
- When enabled, the repo writes to:
39
+ That's it.
87
40
 
88
- ```bash
89
- /tmp/qq-debug.log
90
- ```
91
-
92
- You can watch it live with:
93
-
94
- ```bash
95
- tail -f /tmp/qq-debug.log
96
- ```
97
-
98
- If you want to change the location, point `QQ_DEBUG_LOG_FILE` somewhere else before sourcing your shell config.
41
+ ## Usage
99
42
 
100
- The interactive shell hook also prewarms the daemon once per shell session, so the first `??` does not pay the full startup cost.
43
+ Type anything before `??` and QueQue turns it into a shell command:
101
44
 
102
- ## Claude Provider
103
-
104
- The foreground client can now ask Claude for a strict JSON command suggestion.
105
-
106
- Set these environment variables before running the client:
107
-
108
- ```bash
109
- # read from .env.local in the repo root, or export directly
110
- ANTHROPIC_API_KEY="..."
111
- # optional
112
- QQ_MODEL="claude-3-haiku-20240307"
113
45
  ```
114
-
115
- If `QQ_MODEL` is omitted, the provider asks Anthropic for the available models and picks the cheapest one it can see. You can still force a specific model with `QQ_MODEL` if you need to.
116
-
117
- The LLM mode is selected with:
118
-
119
- ```bash
120
- qq client --request-file /tmp/request.json --result-file /tmp/result.json --result-mode llm
46
+ list files by size??
47
+ find docker containers using port 3000??
48
+ git undo last commit but keep changes??
121
49
  ```
122
50
 
123
- When the current directory is inside a git repository, the prompt includes the repo root, branch, and dirty state as extra context.
124
-
125
- ## Smoke-Test The Current CLI
126
-
127
- Right now the commands are scaffolds and intentionally fail with explicit `not implemented` errors. That is still useful for verifying your shell wiring.
128
-
129
- ```bash
130
- qq --help
131
- qq client --request-file /tmp/request.json --result-file /tmp/result.json
132
- qq daemon --socket /tmp/qq-test.sock
133
- qq daemon --ensure --socket /tmp/qq-test.sock
134
- ```
51
+ A selection UI opens in-terminal. Pick a command with arrow keys or fuzzy search, press `Enter`, and the command lands in your buffer — ready to run or edit before you commit.
135
52
 
136
- Expected result today: help output works, and the command handlers exit with `not implemented` messages instead of performing real work.
53
+ Press `Esc` to cancel and return to what you were typing.
137
54
 
138
- ## Commit Workflow
55
+ ### Inside Zellij
139
56
 
140
- This repo now uses:
57
+ QueQue detects Zellij automatically and opens in a floating pane instead of inline. Same trigger, same result, better layout.
141
58
 
142
- - `commitlint` to enforce Conventional Commits
143
- - `lefthook` to run Git hooks locally
144
- - `biome` for formatting and linting
59
+ ## Requirements
145
60
 
146
- After `pnpm install`, Lefthook installs automatically through the `prepare` script.
61
+ - zsh
62
+ - Node.js ≥ 20
63
+ - [jq](https://jqlang.github.io/jq/)
64
+ - `ANTHROPIC_API_KEY`
147
65
 
148
- Current hook behavior:
66
+ ## Configuration
149
67
 
150
- - `pre-commit`: runs `biome check --write --staged` and `pnpm test:run`
151
- - `commit-msg`: runs `commitlint --edit`
68
+ | Variable | Default | Description |
69
+ |---|---|---|
70
+ | `ANTHROPIC_API_KEY` | — | Required. Your Anthropic API key. |
71
+ | `QQ_MODEL` | auto | Override the Claude model (e.g. `claude-haiku-4-5-20251001`). |
72
+ | `QQ_DEBUG_LOG_FILE` | — | Path to write a debug log (e.g. `/tmp/qq.log`). |
152
73
 
153
- Examples of valid commit messages:
74
+ ## Contributing
154
75
 
155
- ```text
156
- feat: add daemon bootstrap
157
- fix: handle missing request file
158
- docs: document shell wiring
159
- chore: add biome and commit hooks
76
+ ```zsh
77
+ git clone https://github.com/k-leumas/queque
78
+ cd queque
79
+ pnpm install
80
+ pnpm dev # watch build
81
+ pnpm test:run # run tests
160
82
  ```
161
83
 
162
- ## Future `zsh` Integration
163
-
164
- Once the repo adds `shell/zsh/qq.zsh`, the shell wiring will look more like this:
165
-
166
- ```bash
167
- export QQ_DEV_ROOT="$HOME/dev/queque"
84
+ To wire up the dev build as the live `??` trigger:
168
85
 
169
- qq() {
170
- node "$QQ_DEV_ROOT/dist/cli/main.js" "$@"
171
- }
172
-
173
- if [[ -f "$QQ_DEV_ROOT/shell/zsh/qq.zsh" ]]; then
174
- source "$QQ_DEV_ROOT/shell/zsh/qq.zsh"
175
- fi
86
+ ```zsh
87
+ export QQ_DEV_ROOT="$PWD"
88
+ qq init zsh >> ~/.zshrc
89
+ source ~/.zshrc
176
90
  ```
177
91
 
178
- At that point, `qq` will still resolve to your local checkout, and the sourced widget file can register the `??` trigger against the same development build.
92
+ Changes to `src/` rebuild automatically and the widget picks them up immediately.
package/dist/cli/main.js CHANGED
@@ -1,3 +1,5 @@
1
+ #!/usr/bin/env node
2
+
1
3
  // src/cli/main.ts
2
4
  import * as fs2 from "fs";
3
5
  import { cac } from "cac";
@@ -434,19 +436,19 @@ var CONNECT_TIMEOUT_MS = 500;
434
436
  var POLL_INTERVAL_MS = 50;
435
437
  var POLL_MAX_ATTEMPTS = 40;
436
438
  function tryConnect(socketPath2) {
437
- return new Promise((resolve2) => {
439
+ return new Promise((resolve3) => {
438
440
  const timer = setTimeout(() => {
439
441
  client.destroy();
440
- resolve2(false);
442
+ resolve3(false);
441
443
  }, CONNECT_TIMEOUT_MS);
442
444
  const client = net.createConnection(socketPath2, () => {
443
445
  clearTimeout(timer);
444
446
  client.destroy();
445
- resolve2(true);
447
+ resolve3(true);
446
448
  });
447
449
  client.on("error", () => {
448
450
  clearTimeout(timer);
449
- resolve2(false);
451
+ resolve3(false);
450
452
  });
451
453
  });
452
454
  }
@@ -973,7 +975,7 @@ async function runForegroundClient(args) {
973
975
  ttyWriteStream.write(`\x1B[${MODAL_VIEWPORT_LINES}A`);
974
976
  ttyWriteStream.write("\x1B7");
975
977
  }
976
- await new Promise((resolve2) => {
978
+ await new Promise((resolve3) => {
977
979
  let unmount;
978
980
  let resolved = false;
979
981
  const buildCandidateElement = (candidates, errorState) => React.createElement(CandidateSelect, {
@@ -1021,7 +1023,7 @@ async function runForegroundClient(args) {
1021
1023
  process.off("SIGTERM", cleanupOnSignal);
1022
1024
  app.unmount();
1023
1025
  clearScrollReserve();
1024
- resolve2();
1026
+ resolve3();
1025
1027
  };
1026
1028
  fetchCandidates(envelope, request.rbuffer).then((candidates) => {
1027
1029
  void appendDebugLog("client", "candidates received", { count: candidates.length });
@@ -1118,7 +1120,7 @@ var ipcResponseSchema = z4.discriminatedUnion("kind", [
1118
1120
 
1119
1121
  // src/daemon/server.ts
1120
1122
  function startDaemonServer(socketPath2) {
1121
- return new Promise((resolve2, reject) => {
1123
+ return new Promise((resolve3, reject) => {
1122
1124
  const MAX_BUF_BYTES = 64 * 1024;
1123
1125
  const server = net2.createServer((socket) => {
1124
1126
  let buf = "";
@@ -1177,7 +1179,7 @@ function startDaemonServer(socketPath2) {
1177
1179
  server.on("error", reject);
1178
1180
  server.listen(socketPath2, () => {
1179
1181
  void appendDebugLog("daemon", "listening", { socketPath: socketPath2 });
1180
- resolve2(server);
1182
+ resolve3(server);
1181
1183
  });
1182
1184
  });
1183
1185
  }
@@ -1205,6 +1207,23 @@ async function daemonCommand(options) {
1205
1207
  });
1206
1208
  }
1207
1209
 
1210
+ // src/cli/commands/init.ts
1211
+ import { readFileSync as readFileSync2 } from "fs";
1212
+ import { dirname as dirname3, resolve as resolve2 } from "path";
1213
+ import { fileURLToPath as fileURLToPath3 } from "url";
1214
+ var __dirname = dirname3(fileURLToPath3(import.meta.url));
1215
+ var SUPPORTED_SHELLS = ["zsh"];
1216
+ function shellScriptPath(shell) {
1217
+ return resolve2(__dirname, "../../shell", shell, `queque.${shell}`);
1218
+ }
1219
+ function initCommand(shell) {
1220
+ if (!SUPPORTED_SHELLS.includes(shell)) {
1221
+ console.error(`Unsupported shell: '${shell}'. Supported: ${SUPPORTED_SHELLS.join(", ")}`);
1222
+ process.exit(1);
1223
+ }
1224
+ process.stdout.write(readFileSync2(shellScriptPath(shell), "utf8"));
1225
+ }
1226
+
1208
1227
  // src/cli/main.ts
1209
1228
  function requiredOption(name, value) {
1210
1229
  if (!value) {
@@ -1244,6 +1263,12 @@ async function main(argv = process.argv.slice(2)) {
1244
1263
  const resultFile = requiredOption("--result-file", options.resultFile);
1245
1264
  await clientCommand({ requestFile, resultFile, resultMode: options.resultMode });
1246
1265
  });
1266
+ cli.command(
1267
+ "init <shell>",
1268
+ 'Print shell integration script (add `eval "$(qq init zsh)"` to ~/.zshrc)'
1269
+ ).action((shell) => {
1270
+ initCommand(shell);
1271
+ });
1247
1272
  cli.command("daemon").option("--socket <path>", "Unix socket path for the daemon").option("--ensure", "Ensure the daemon is running before returning").action(async (options) => {
1248
1273
  await daemonCommand(options);
1249
1274
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/main.ts","../../src/context/providers/filesystem-context.ts","../../src/context/providers/git-context.ts","../../src/shared/debug-log.ts","../../src/shared/vcs-context.ts","../../src/registry/context-providers.ts","../../src/registry/provider-backends.ts","../../src/registry/shell-adapters.ts","../../src/registry/storage-hooks.ts","../../src/registry/bootstrap.ts","../../src/client/run-foreground.ts","../../src/contracts/request.ts","../../src/contracts/shell.ts","../../src/intent/router.ts","../../src/context/base-context.ts","../../src/context/pipeline.ts","../../src/daemon/bootstrap.ts","../../src/providers/claude.ts","../../src/contracts/candidates.ts","../../src/shared/env-file.ts","../../src/providers/detect.ts","../../src/shared/socket-path.ts","../../src/ui/CandidateSelect.tsx","../../src/ui/ControlsLine.tsx","../../src/ui/LoadingSpinner.tsx","../../src/ui/Modal.tsx","../../src/ui/SearchInput.tsx","../../src/client/result-writer.ts","../../src/cli/commands/client.ts","../../src/daemon/server.ts","../../src/contracts/ipc.ts","../../src/cli/commands/daemon.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport { cac } from 'cac';\nimport { bootstrapBuiltins } from '../registry/bootstrap.js';\nimport { clientCommand } from './commands/client.js';\nimport { daemonCommand } from './commands/daemon.js';\n\ntype ClientOptions = {\n requestFile?: string;\n resultFile?: string;\n resultMode?: string;\n};\n\ntype DaemonOptions = {\n socket?: string;\n ensure?: boolean;\n};\n\nfunction requiredOption(name: string, value: string | undefined): string {\n if (!value) {\n throw new Error(`Missing required option: ${name}`);\n }\n\n return value;\n}\n\n// ---------------------------------------------------------------------------\n// Top-level error handlers — FIFO safety net (RUN-02 Pitfall 3)\n//\n// These handlers fire when an error escapes the async main() chain entirely\n// (e.g. a synchronous throw from Ink internals or a void async call that\n// rejects after the Promise resolves). Without them a crash would leave the\n// zsh widget blocking on the FIFO read for up to 30 seconds.\n//\n// Both handlers:\n// 1. Read the FIFO path from process.env.QQ_RESULT_FILE (exported by the\n// zsh widget before zellij run, so it is always available in the env).\n// 2. Write {\"kind\":\"cancel\"}\\n to that path using synchronous writeFileSync\n// (writeShellResult is async-unsafe inside an exception handler).\n// 3. Call process.exit(1) unconditionally — the exit prevents re-entry.\n//\n// Security note (T-04-03-01): QQ_RESULT_FILE is set by the trusted zsh widget\n// (mktemp -d /tmp/qq-sess.XXXXXX), so we validate the path before writing to\n// prevent an attacker-controlled env var from redirecting writes to arbitrary files.\n// ---------------------------------------------------------------------------\n\n// Matches paths created by: mktemp -d /tmp/qq-sess.XXXXXX\nconst QQ_RESULT_FILE_PATTERN = /^\\/tmp\\/qq-sess\\.[A-Za-z0-9]+\\//;\n\nprocess.on('uncaughtException', (err: Error) => {\n console.error('QueQue: uncaught exception:', err.message);\n const resultFile = process.env.QQ_RESULT_FILE;\n if (resultFile && QQ_RESULT_FILE_PATTERN.test(resultFile)) {\n try {\n fs.writeFileSync(resultFile, '{\"kind\":\"cancel\"}\\n');\n } catch {\n // Ignore write failures (FIFO reader may already be gone)\n }\n }\n process.exit(1);\n});\n\nprocess.on('unhandledRejection', (reason: unknown) => {\n const message = reason instanceof Error ? reason.message : String(reason);\n console.error('QueQue: unhandled rejection:', message);\n const resultFile = process.env.QQ_RESULT_FILE;\n if (resultFile && QQ_RESULT_FILE_PATTERN.test(resultFile)) {\n try {\n fs.writeFileSync(resultFile, '{\"kind\":\"cancel\"}\\n');\n } catch {\n // Ignore write failures (FIFO reader may already be gone)\n }\n }\n process.exit(1);\n});\n\nexport async function main(argv = process.argv.slice(2)): Promise<void> {\n bootstrapBuiltins();\n const cli = cac('qq');\n\n cli\n .command('client')\n .option('--request-file <path>', 'Path to the serialized shell request')\n .option('--result-file <path>', 'Path to write the serialized shell result')\n .option('--result-mode <mode>', 'Result mode: llm | cancel | replace-buffer-fixture')\n .action(async (options: ClientOptions) => {\n const requestFile = requiredOption('--request-file', options.requestFile);\n const resultFile = requiredOption('--result-file', options.resultFile);\n\n await clientCommand({ requestFile, resultFile, resultMode: options.resultMode });\n });\n\n cli\n .command('daemon')\n .option('--socket <path>', 'Unix socket path for the daemon')\n .option('--ensure', 'Ensure the daemon is running before returning')\n .action(async (options: DaemonOptions) => {\n await daemonCommand(options);\n });\n\n cli.help();\n cli.parse(['node', 'qq', ...argv], { run: false });\n\n await cli.runMatchedCommand();\n}\n\nconst isDirectRun = process.argv[1]\n ? import.meta.url === new URL(`file://${process.argv[1]}`).href\n : false;\n\nif (isDirectRun) {\n void main().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exitCode = 1;\n });\n}\n","import type { ContextChunk } from '../../contracts/request.js';\nimport type { ContextProvider, GatherContextInput } from '../provider.js';\n\nconst FILENAME_RE = /\\b[\\w.-]+\\.\\w{2,6}\\b/g;\n\nexport const filesystemContextProvider: ContextProvider = {\n id: 'filesystem-context',\n intents: ['filesystem'],\n async gather(input: GatherContextInput): Promise<ContextChunk> {\n const match = input.base.queryText.match(FILENAME_RE);\n\n return {\n kind: 'filesystem',\n payload: {\n cwd: input.base.cwd,\n apparentFilename: match?.[0] ?? null,\n },\n };\n },\n};\n","import { execFile } from 'node:child_process';\nimport { statSync } from 'node:fs';\nimport { promisify } from 'node:util';\nimport type { ContextChunk } from '../../contracts/request.js';\nimport { appendDebugLog } from '../../shared/debug-log.js';\nimport { detectVcsContext } from '../../shared/vcs-context.js';\nimport type { ContextProvider, GatherContextInput } from '../provider.js';\n\nconst execFileAsync = promisify(execFile);\nconst GIT_TIMEOUT_MS = 5000;\n\nfunction assertSafeCwd(cwd: string): void {\n let st: ReturnType<typeof statSync>;\n try {\n st = statSync(cwd);\n } catch {\n throw new Error(`cwd not accessible: ${cwd}`);\n }\n if (!st.isDirectory()) throw new Error(`cwd is not a directory: ${cwd}`);\n}\n\nfunction unescapeGitPath(s: string): string {\n return s\n .replace(/\\\\([0-7]{3})/g, (_, oct) => String.fromCodePoint(parseInt(oct, 8)))\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\\\\/g, '\\\\');\n}\n\nfunction stripQuotes(value: string): string {\n if (value.startsWith('\"') && value.endsWith('\"')) {\n return unescapeGitPath(value.slice(1, -1));\n }\n\n return value;\n}\n\n/** @internal For direct unit coverage of porcelain edge cases. */\nexport function parsePorcelainLine(line: string): string | null {\n if (line.length < 4) {\n return null;\n }\n\n const rest = line.slice(3);\n const renameSeparator = ' -> ';\n const renameIndex = rest.indexOf(renameSeparator);\n\n if (renameIndex !== -1) {\n return stripQuotes(rest.slice(renameIndex + renameSeparator.length));\n }\n\n return stripQuotes(rest);\n}\n\nasync function getChangedFiles(cwd: string): Promise<string[]> {\n try {\n assertSafeCwd(cwd);\n const { stdout } = await execFileAsync('git', ['-C', cwd, 'status', '--porcelain'], {\n encoding: 'utf8',\n timeout: GIT_TIMEOUT_MS,\n });\n\n return stdout\n .split('\\n')\n .filter(Boolean)\n .map(parsePorcelainLine)\n .filter((path): path is string => path !== null);\n } catch {\n return [];\n }\n}\n\nexport const gitContextProvider: ContextProvider = {\n id: 'git-context',\n intents: ['codebase', 'shell-command'],\n async gather(input: GatherContextInput): Promise<ContextChunk | null> {\n if (\n input.decision.intent === 'shell-command' &&\n !input.decision.signals.includes('git-prefix')\n ) {\n return null;\n }\n\n try {\n const vcs = await detectVcsContext(input.base.cwd);\n if (vcs.kind === 'none') {\n return null;\n }\n\n const changedFiles = await getChangedFiles(input.base.cwd);\n\n void appendDebugLog('context', 'git provider gathered', {\n cwd: input.base.cwd,\n branch: vcs.branch,\n dirty: vcs.dirty,\n changedFiles: changedFiles.length,\n });\n\n return {\n kind: 'git',\n payload: {\n cwd: vcs.cwd,\n root: vcs.root,\n branch: vcs.branch,\n dirty: vcs.dirty,\n changedFiles,\n },\n };\n } catch (error) {\n void appendDebugLog('context', 'git provider failed', {\n cwd: input.base.cwd,\n message: error instanceof Error ? error.message : String(error),\n });\n\n return null;\n }\n },\n};\n","import * as fsp from 'node:fs/promises';\n\nexport const debugLogPath =\n process.env.QQ_DEBUG_LOG_FILE ?? `/tmp/qq-${process.getuid?.() ?? 'unknown'}-debug.log`;\n\nfunction formatDetails(details: unknown): string {\n if (details === undefined) return '';\n try {\n return ` ${JSON.stringify(details)}`;\n } catch {\n return ' [unserializable-details]';\n }\n}\n\nexport async function appendDebugLog(\n scope: string,\n message: string,\n details?: unknown,\n): Promise<void> {\n const line = `${new Date().toISOString()} [${scope}] ${message}${formatDetails(details)}\\n`;\n\n try {\n await fsp.appendFile(debugLogPath, line, { encoding: 'utf-8', mode: 0o600 });\n } catch {\n // Debug logging must never break the user flow.\n }\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\nexport type VcsContext =\n | {\n kind: 'none';\n cwd: string;\n }\n | {\n kind: 'git';\n cwd: string;\n root: string;\n branch: string | null;\n dirty: boolean;\n };\n\nasync function runGit(cwd: string, args: string[]): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync('git', ['-C', cwd, ...args], { encoding: 'utf8' });\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\nexport async function detectVcsContext(cwd: string): Promise<VcsContext> {\n const insideWorkTree = await runGit(cwd, ['rev-parse', '--is-inside-work-tree']);\n\n if (insideWorkTree !== 'true') {\n return { kind: 'none', cwd };\n }\n\n const root = (await runGit(cwd, ['rev-parse', '--show-toplevel'])) ?? cwd;\n const branch = (await runGit(cwd, ['branch', '--show-current'])) || null;\n const dirty = Boolean((await runGit(cwd, ['status', '--porcelain=v1']))?.length);\n\n return {\n kind: 'git',\n cwd,\n root,\n branch,\n dirty,\n };\n}\n","import type { ContextProvider } from '../context/provider.js';\n\nconst registry = new Map<string, ContextProvider>();\n\nexport function registerContextProvider(descriptor: ContextProvider): void {\n if (registry.has(descriptor.id)) {\n throw new Error(`Context provider already registered: \"${descriptor.id}\"`);\n }\n\n registry.set(descriptor.id, descriptor);\n}\n\nexport function getContextProvider(id: string): ContextProvider | undefined {\n return registry.get(id);\n}\n\nexport function listContextProviders(): ContextProvider[] {\n return Array.from(registry.values());\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function clearContextProviders(): void {\n registry.clear();\n}\n","/**\n * PHASE 2 STUB — Provider Backends Registry\n *\n * This seam exists before the runtime uses it so provider registration can\n * move through one internal path instead of hardcoding Claude first and\n * refactoring later. Example future use: register an OpenAI backend alongside Claude.\n */\nexport interface ProviderBackendDescriptor {\n id: string;\n name: string;\n description: string;\n}\n\nconst registry = new Map<string, ProviderBackendDescriptor>();\n\nexport function registerProviderBackend(descriptor: ProviderBackendDescriptor): void {\n if (registry.has(descriptor.id)) {\n throw new Error(`Provider backend already registered: \"${descriptor.id}\"`);\n }\n\n registry.set(descriptor.id, descriptor);\n}\n\nexport function getProviderBackend(id: string): ProviderBackendDescriptor | undefined {\n return registry.get(id);\n}\n\nexport function listProviderBackends(): ProviderBackendDescriptor[] {\n return Array.from(registry.values());\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function clearProviderBackends(): void {\n registry.clear();\n}\n","/**\n * PHASE 2 STUB — Shell Adapters Registry\n *\n * This seam exists before additional shells ship so every built-in and future\n * adapter can register through the same path. Example future use: add a bash adapter\n * without rewriting the surrounding pipeline or bootstrap code.\n */\nexport interface ShellAdapterDescriptor {\n id: string;\n shell: string;\n description: string;\n}\n\nconst registry = new Map<string, ShellAdapterDescriptor>();\n\nexport function registerShellAdapter(descriptor: ShellAdapterDescriptor): void {\n if (registry.has(descriptor.id)) {\n throw new Error(`Shell adapter already registered: \"${descriptor.id}\"`);\n }\n\n registry.set(descriptor.id, descriptor);\n}\n\nexport function getShellAdapter(id: string): ShellAdapterDescriptor | undefined {\n return registry.get(id);\n}\n\nexport function listShellAdapters(): ShellAdapterDescriptor[] {\n return Array.from(registry.values());\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function clearShellAdapters(): void {\n registry.clear();\n}\n","/**\n * PHASE 2 STUB — Storage Hooks Registry\n *\n * This seam exists before persistence lands so storage behavior can grow behind\n * a registry instead of direct call-site wiring. Example future use: register a\n * SQLite-backed session history hook without changing client flow code.\n */\nexport interface StorageHookDescriptor {\n id: string;\n description: string;\n}\n\nconst registry = new Map<string, StorageHookDescriptor>();\n\nexport function registerStorageHook(descriptor: StorageHookDescriptor): void {\n if (registry.has(descriptor.id)) {\n throw new Error(`Storage hook already registered: \"${descriptor.id}\"`);\n }\n\n registry.set(descriptor.id, descriptor);\n}\n\nexport function getStorageHook(id: string): StorageHookDescriptor | undefined {\n return registry.get(id);\n}\n\nexport function listStorageHooks(): StorageHookDescriptor[] {\n return Array.from(registry.values());\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function clearStorageHooks(): void {\n registry.clear();\n}\n","import { filesystemContextProvider } from '../context/providers/filesystem-context.js';\nimport { gitContextProvider } from '../context/providers/git-context.js';\nimport { registerContextProvider } from './context-providers.js';\nimport { registerProviderBackend } from './provider-backends.js';\nimport { registerShellAdapter } from './shell-adapters.js';\nimport { registerStorageHook } from './storage-hooks.js';\n\nlet bootstrapped = false;\n\n/**\n * Registers all Phase 2 built-ins into their respective registries.\n *\n * This is the single source of truth for what built-ins exist in Phase 2.\n * Callers should invoke it at startup; repeated calls are safe no-ops.\n */\nexport function bootstrapBuiltins(): void {\n if (bootstrapped) {\n return;\n }\n\n bootstrapped = true;\n\n registerContextProvider(gitContextProvider);\n registerContextProvider(filesystemContextProvider);\n\n registerShellAdapter({\n id: 'zsh',\n shell: 'zsh',\n description: 'zsh ZLE widget adapter (Phase 2 built-in)',\n });\n\n registerStorageHook({\n id: 'noop',\n description: 'No-op storage hook (default — no persistence)',\n });\n registerStorageHook({\n id: 'memory',\n description: 'In-memory storage hook (test and ephemeral use)',\n });\n\n registerProviderBackend({\n id: 'claude',\n name: 'Claude (Anthropic)',\n description: 'Anthropic Claude adapter — default LLM backend',\n });\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function resetBootstrap(): void {\n bootstrapped = false;\n}\n","import * as fsp from 'node:fs/promises';\nimport * as tty from 'node:tty';\nimport { render } from 'ink';\nimport React from 'react';\nimport { gatherContext } from '../context/pipeline.js';\nimport type { NormalizedRequest } from '../contracts/request.js';\nimport { shellRequestSchema } from '../contracts/shell.js';\nimport { ensureDaemon } from '../daemon/bootstrap.js';\nimport { classifyIntent } from '../intent/router.js';\nimport { fetchCandidates } from '../providers/claude.js';\nimport { detectProvider } from '../providers/detect.js';\nimport { appendDebugLog } from '../shared/debug-log.js';\nimport { socketPathForUid } from '../shared/socket-path.js';\nimport { CandidateSelect } from '../ui/CandidateSelect.js';\nimport { writeShellResult } from './result-writer.js';\n\n/**\n * Splits a command + explanation into shell buffer halves.\n *\n * Cursor lands before the first placeholder (text wrapped in `<...>`), so the\n * user can immediately type the first required value. Angle brackets are\n * stripped from all placeholders so the shell buffer looks natural.\n * If no placeholders are present, cursor lands after the command, before the\n * ` # explanation` comment.\n */\nexport function buildShellBuffers(\n command: string,\n explanation: string,\n): { lbuffer: string; rbuffer: string } {\n const comment = ` # ${explanation}`;\n const stripped = command.replace(/<([^>]+)>/g, '$1');\n const firstAngle = command.indexOf('<');\n if (firstAngle >= 0) {\n return {\n lbuffer: stripped.slice(0, firstAngle),\n rbuffer: stripped.slice(firstAngle) + comment,\n };\n }\n return { lbuffer: command, rbuffer: comment };\n}\n\nexport interface ForegroundClientArgs {\n requestFile: string;\n resultFile: string;\n /**\n * Selects the deterministic result mode for this Phase 1 seam:\n *\n * cancel — write {kind:'cancel'} immediately (Esc simulation)\n * replace-buffer-fixture — write a deterministic {kind:'replace-buffer'} result\n * derived from the shell request so the zsh bridge can\n * round-trip an accepted selection end-to-end without\n * the Phase 4 TUI being built yet.\n * llm — call Claude and map its JSON response to shell output\n */\n resultMode: 'cancel' | 'replace-buffer-fixture' | 'llm';\n}\n\n/**\n * Runs the foreground client loop.\n *\n * 1. Opens /dev/tty for interactive stdio (does not assume inherited stdio is a TTY).\n * 2. Reads and validates the shell request file.\n * 3. Ensures the background daemon is running.\n * 4. Emits a deterministic shell result based on `resultMode`.\n *\n * Phase 4 will replace step 4 with a real Ink TUI loop — the shell contract\n * and daemon bootstrap seam are established here without any UI framework imports.\n */\nexport async function runForegroundClient(args: ForegroundClientArgs): Promise<void> {\n const { requestFile, resultFile, resultMode } = args;\n const uid = typeof process.getuid === 'function' ? process.getuid() : 0;\n const socketPath = socketPathForUid(uid);\n\n const inZellij = process.env.ZELLIJ !== undefined;\n\n void appendDebugLog('client', 'foreground start', {\n requestFile,\n resultFile,\n resultMode,\n socketPath,\n inZellij,\n });\n\n // Always open /dev/tty for interactive stdio.\n // Outside Zellij: ZLE redirects process.stdin from /dev/null, so /dev/tty is required.\n // Inside Zellij (zellij run): process.stdin is not wired to the pane PTY by zellij run,\n // but /dev/tty always refers to the controlling terminal which IS the pane PTY.\n const ttyHandle = await fsp.open('/dev/tty', 'r+').catch(() => null);\n\n try {\n // Read and validate the shell request\n const raw = await fsp.readFile(requestFile, 'utf-8');\n const request = shellRequestSchema.parse(JSON.parse(raw.trim()));\n\n void appendDebugLog('client', 'request parsed', request);\n\n const detectedProvider = await detectProvider();\n void appendDebugLog('client', 'provider detected', { kind: detectedProvider.kind });\n\n // Ensure the daemon is reachable before we do anything interactive\n await ensureDaemon(socketPath);\n void appendDebugLog('client', 'daemon ensured', { socketPath });\n\n // Deterministic result seam — Phase 4 replaces this with the Ink TUI\n if (resultMode === 'replace-buffer-fixture') {\n // Derive a fixture from the request so the result is deterministic and\n // exercise the full zsh bridge round-trip without needing user input.\n const fixtureLbuffer = request.lbuffer || 'echo hello';\n await writeShellResult(resultFile, {\n kind: 'replace-buffer',\n lbuffer: fixtureLbuffer,\n rbuffer: request.rbuffer,\n });\n void appendDebugLog('client', 'wrote replace-buffer result', {\n resultFile,\n lbuffer: fixtureLbuffer,\n rbuffer: request.rbuffer,\n });\n } else if (resultMode === 'llm') {\n try {\n const decision = classifyIntent({ ...request, intent: 'unknown' as const, confidence: 0 });\n void appendDebugLog('client', 'intent classified', {\n intent: decision.intent,\n signals: decision.signals,\n });\n\n const normalized: NormalizedRequest = {\n ...request,\n intent: decision.intent,\n confidence: decision.confidence,\n };\n const envelope = await gatherContext(normalized);\n void appendDebugLog('client', 'context gathered', {\n extraCount: envelope.extras.length,\n });\n\n // D-07: Open modal before fetchCandidates resolves — spinner shows immediately.\n // D-03: No single-candidate fast-accept bypass — all paths go through the modal.\n // D-05: No raw ANSI loading indicator — spinner is inside the Ink component.\n\n // Try to create TTY streams from /dev/tty for Ink.\n // This works in all contexts (ZSH widget, zellij run pane, plain terminal).\n // Falls back to process.stdin/stdout if /dev/tty was unavailable (e.g. tests).\n let ttyReadStream: tty.ReadStream | undefined;\n let ttyWriteStream: tty.WriteStream | undefined;\n if (ttyHandle) {\n try {\n ttyReadStream = new tty.ReadStream(ttyHandle.fd);\n ttyWriteStream = new tty.WriteStream(ttyHandle.fd);\n } catch {\n // Synthetic fd (e.g. tests) — Ink will use process.stdin/stdout\n }\n }\n\n // Reserve exactly as many lines as the TUI needs (header + filter + up to 3\n // candidates × 3 rows + controls + 2 buffer = 16). This scrolls previous\n // terminal content up by only 16 lines so it stays visible above the TUI,\n // rather than filling the whole screen.\n // Skipped in Zellij: the floating pane starts with a clean screen.\n const MODAL_VIEWPORT_LINES = 16;\n if (ttyWriteStream && !inZellij) {\n ttyWriteStream.write('\\n'.repeat(MODAL_VIEWPORT_LINES));\n ttyWriteStream.write(`\\x1b[${MODAL_VIEWPORT_LINES}A`);\n // Save cursor at the top of the reserved area. Restored in clearScrollReserve\n // so cleanup always erases from the right position regardless of where Ink\n // leaves the cursor after unmount.\n ttyWriteStream.write('\\x1b7');\n }\n\n await new Promise<void>((resolve) => {\n let unmount: (() => void) | undefined;\n let resolved = false;\n\n // Build initial element with null candidates (D-06 loading state)\n const buildCandidateElement = (\n candidates: Parameters<typeof CandidateSelect>[0]['candidates'],\n errorState?: boolean,\n ) =>\n React.createElement(CandidateSelect, {\n candidates,\n initialQuery: request.lbuffer,\n error: errorState,\n onSelect: async (command: string, explanation: string) => {\n if (resolved) return;\n resolved = true;\n const { lbuffer, rbuffer } = buildShellBuffers(command, explanation);\n await writeShellResult(resultFile, {\n kind: 'replace-buffer',\n lbuffer,\n rbuffer,\n query: request.lbuffer,\n });\n unmount?.();\n },\n onCancel: async () => {\n if (resolved) return;\n resolved = true;\n await writeShellResult(resultFile, { kind: 'cancel' });\n unmount?.();\n },\n });\n\n // Force interactive:true so Ink uses cursor-repositioning mode regardless of\n // CI env vars (is-in-ci checks process.env.CI which many devtools set) and\n // regardless of whether isTTY is correctly reported on a manually-constructed\n // tty.WriteStream. We already confirmed /dev/tty opens, so it is a real terminal.\n const renderOptions =\n ttyReadStream && ttyWriteStream\n ? { stdin: ttyReadStream, stdout: ttyWriteStream, interactive: true }\n : { interactive: true };\n\n const app = render(buildCandidateElement(null), renderOptions);\n\n // Restore cursor to the saved position (top of reserved area) then clear\n // to end of screen. This works regardless of where Ink left the cursor.\n const clearScrollReserve = () => {\n if (ttyWriteStream && !inZellij) {\n try {\n ttyWriteStream.write('\\x1b8\\x1b[J');\n } catch {\n // TTY may already be gone (e.g. SIGHUP fired because terminal closed)\n }\n }\n };\n\n const cleanupOnSignal = () => {\n app.unmount();\n clearScrollReserve();\n process.exit(0);\n };\n process.once('SIGHUP', cleanupOnSignal);\n process.once('SIGTERM', cleanupOnSignal);\n\n unmount = () => {\n process.off('SIGHUP', cleanupOnSignal);\n process.off('SIGTERM', cleanupOnSignal);\n app.unmount();\n clearScrollReserve();\n resolve();\n };\n\n // D-07: fetch candidates concurrently — rerender() pushes them into the live modal.\n fetchCandidates(envelope, request.rbuffer)\n .then((candidates) => {\n void appendDebugLog('client', 'candidates received', { count: candidates.length });\n app.rerender(buildCandidateElement(candidates));\n })\n .catch(async (err) => {\n const message = err instanceof Error ? err.message : String(err);\n void appendDebugLog('client', 'llm request failed', { message });\n if (resolved) return;\n resolved = true;\n try {\n await writeShellResult(resultFile, {\n kind: 'error',\n message: `QueQue: ${message} — press any key`,\n });\n } finally {\n unmount?.();\n }\n });\n });\n\n void appendDebugLog('client', 'wrote llm result', { resultFile });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n void appendDebugLog('client', 'llm request failed', {\n message,\n });\n await writeShellResult(resultFile, {\n kind: 'error',\n message: `QueQue: ${message} — press any key`,\n });\n }\n } else {\n await writeShellResult(resultFile, { kind: 'cancel' });\n void appendDebugLog('client', 'wrote cancel result', { resultFile });\n }\n } finally {\n await ttyHandle?.close();\n }\n}\n","import { z } from 'zod';\nimport { shellRequestSchema } from './shell.js';\n\n/**\n * Broad intent categories classified before any context gathering.\n * Kept intentionally coarse for MVP — see RESEARCH.md for rationale.\n *\n * Taxonomy contract (enforced by classifyIntent in src/intent/router.ts):\n * 'shell-command' — query looks like a shell command or git invocation\n * 'codebase' — query has an explicit file-path signal or is a pkg-manager script (D-01, D-02)\n * 'filesystem' — query describes a file system operation (rename, move, find)\n * 'general' — non-empty query with no strong signal (lowest-confidence fallback)\n * 'unknown' — ONLY for the empty-string query; no other input should produce this value\n */\nexport const requestIntentSchema = z.enum([\n 'shell-command',\n 'codebase',\n 'filesystem',\n 'general',\n 'unknown',\n]);\n\nexport type RequestIntent = z.infer<typeof requestIntentSchema>;\n\n/**\n * Normalized internal request — shell transport plus inferred intent.\n * Consumers downstream of the shell bridge work with this type, not ShellRequest.\n */\nexport const normalizedRequestSchema = shellRequestSchema.extend({\n intent: requestIntentSchema,\n confidence: z.number().min(0).max(1),\n});\n\nexport type NormalizedRequest = z.infer<typeof normalizedRequestSchema>;\n\n/**\n * Always-present base context derived from the normalized request and\n * process globals. Never requires I/O.\n */\nexport const baseContextSchema = z.object({\n queryText: z.string(),\n cwd: z.string(),\n ttyPath: z.string(),\n shellPid: z.number().int().positive(),\n /** Hardcoded 'zsh' for Phase 2 — cross-shell support is v2 scope. */\n shellName: z.literal('zsh'),\n platform: z.string(),\n timestamp: z.string(),\n});\n\nexport type BaseContext = z.infer<typeof baseContextSchema>;\n\n/**\n * Result of the intent classifier. Includes signals for debugging\n * why a request was routed to a particular intent.\n */\nexport const intentDecisionSchema = z.object({\n intent: requestIntentSchema,\n confidence: z.number().min(0).max(1),\n signals: z.array(z.string()),\n});\n\nexport type IntentDecision = z.infer<typeof intentDecisionSchema>;\n\n/**\n * A typed chunk of extra context gathered by an intent-gated provider.\n * Discriminated on `kind` so consumers can narrow safely.\n *\n * D-05/D-06 structural enforcement: neither variant has any field for file\n * content (bytes, text, lines). File names only. A future provider that needs\n * to include file content MUST add a new `kind` variant and will require an\n * explicit privacy review — it cannot sneak content in through the existing variants.\n */\nexport const contextChunkSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('git'),\n payload: z.object({\n cwd: z.string(),\n root: z.string(),\n branch: z.string().nullable(),\n dirty: z.boolean(),\n /** File paths only (from git status --porcelain). No diff content, no file bytes. */\n changedFiles: z.array(z.string()),\n }),\n }),\n z.object({\n kind: z.literal('filesystem'),\n payload: z.object({\n cwd: z.string(),\n /** Apparent filename extracted from query text. No file bytes read. */\n apparentFilename: z.string().nullable(),\n }),\n }),\n]);\n\nexport type ContextChunk = z.infer<typeof contextChunkSchema>;\n\n/**\n * Fully assembled context passed to the provider adapter.\n * base is always populated; extras contains only intent-relevant chunks.\n */\nexport const contextEnvelopeSchema = z.object({\n base: baseContextSchema,\n extras: z.array(contextChunkSchema),\n});\n\nexport type ContextEnvelope = z.infer<typeof contextEnvelopeSchema>;\n","import { z } from 'zod';\n\n/**\n * Shell request — sent from the zsh widget to the qq client.\n * Carries the raw ZLE buffer state using split-buffer fields to avoid\n * cross-runtime cursor index math between Node and zsh.\n */\nexport const shellRequestSchema = z.object({\n version: z.literal(1),\n ttyPath: z.string(),\n cwd: z.string().regex(/^\\/[^\\0]*$/, 'cwd must be an absolute POSIX path'),\n shellPid: z.number().int().positive(),\n lbuffer: z.string(),\n rbuffer: z.string(),\n});\n\nexport type ShellRequest = z.infer<typeof shellRequestSchema>;\n\n/**\n * Shell result — written by the qq client so the zsh widget can apply it.\n *\n * Three variants:\n * cancel — leave LBUFFER/RBUFFER untouched (Esc or dismiss)\n * replace-buffer — overwrite LBUFFER and RBUFFER with the chosen command\n * error — provider or client error; message shown to user, buffers restored\n *\n * The deprecated {buffer, cursor} shape is intentionally excluded.\n * Numeric cursor offsets create Unicode index mismatches between Node (UTF-16)\n * and zsh (character-oriented).\n */\nexport const shellResultSchema = z.discriminatedUnion('kind', [\n z\n .object({\n kind: z.literal('cancel'),\n })\n .strict(),\n z.object({\n kind: z.literal('replace-buffer'),\n lbuffer: z.string(),\n rbuffer: z.string(),\n query: z.string().optional(),\n }),\n z.object({\n kind: z.literal('error'),\n message: z.string(),\n }),\n]);\n\nexport type ShellResult = z.infer<typeof shellResultSchema>;\n","import {\n type IntentDecision,\n type NormalizedRequest,\n requestIntentSchema,\n} from '../contracts/request.js';\n\n/**\n * D-03: git prefix — query (after trim) begins with 'git ' (literal).\n *\n * Scope notes (Phase 2):\n * - Leading whitespace: the ZLE widget strips leading whitespace from the buffer\n * before the '??' trigger is sent, so `query.trim()` handles any remaining edge.\n * - 'command git status' patterns: out of Phase 2 scope. These are forwarded as\n * shell-command via SHELL_COMMAND_RE below, without the git-prefix signal.\n * The git-prefix signal is used by the git context provider (D-09) to include\n * git context for `git *` subcommand queries.\n */\nconst GIT_PREFIX_RE = /^git\\s/;\n\n/**\n * D-02: package manager script prefixes that always qualify as codebase intent.\n * Matches only at the start of the query to distinguish literal invocations\n * (\"pnpm build\") from natural language (\"how to run pnpm build\").\n */\nconst PKG_MANAGER_RE =\n /^(npm|pnpm|yarn)\\s+(test|build|lint|run|start|dev|check|format|typecheck)\\b/i;\n\n/**\n * Filesystem operation keywords routed before generic file-path detection.\n * This keeps prompts like \"rename hero.png to hero-banner.png\" in filesystem\n * even though the query also contains file-looking tokens.\n */\nconst FILESYSTEM_KEYWORDS_RE =\n /\\b(?:rename|move(?:\\s+file)?|find\\s+files?|copy|delete|list\\s+files?|image|folder|directory)\\b/i;\n\n/**\n * Shell command signals: well-known command prefixes and pipe operator.\n * Checked BEFORE file-path signal so \"ls ./foo.txt\" routes as shell-command, not codebase.\n */\nconst SHELL_COMMAND_RE =\n /^(ls|echo|grep|awk|sed|curl|wget|ssh|cat|head|tail|cd|pwd|mkdir|touch|chmod|cp|mv|rm|which|man|ps|kill|sudo|command)\\s|\\|/;\n\n/**\n * D-01: file path signal detection.\n * Matches: path separators (/), relative paths (./), tilde paths (~/),\n * dotfiles (.env, .zshrc), and bare extensions (utils.py, index.html).\n */\nconst FILE_PATH_RE =\n /(?:\\/|\\.\\/|~\\/|\\.[a-zA-Z][\\w-]*(?:\\.\\w+)?(?=\\s|$)|\\b[\\w-]+\\.(?:ts|tsx|js|jsx|mjs|cjs|py|go|rs|rb|java|sh|md|json|yaml|yml|toml|env|html|css|scss|txt|xml|svg|png|jpg|jpeg|gif|pdf|zip|tar|gz|lock|config)(?:\\b|$))/;\n\nexport function classifyIntent(request: NormalizedRequest): IntentDecision {\n const query = request.lbuffer.trim();\n\n // Empty query (including whitespace-only) → unknown (the ONLY path to this value)\n if (query.length === 0) {\n return {\n intent: requestIntentSchema.enum.unknown,\n confidence: 1,\n signals: ['empty-query'],\n };\n }\n\n if (GIT_PREFIX_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum['shell-command'],\n confidence: 1,\n signals: ['git-prefix'],\n };\n }\n\n if (PKG_MANAGER_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum.codebase,\n confidence: 1,\n signals: ['pkg-manager-script'],\n };\n }\n\n if (FILESYSTEM_KEYWORDS_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum.filesystem,\n confidence: 0.85,\n signals: ['filesystem-keyword'],\n };\n }\n\n if (SHELL_COMMAND_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum['shell-command'],\n confidence: 0.8,\n signals: ['shell-command-signal'],\n };\n }\n\n if (FILE_PATH_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum.codebase,\n confidence: 0.9,\n signals: ['file-path-signal'],\n };\n }\n\n return {\n intent: requestIntentSchema.enum.general,\n confidence: 0.5,\n signals: ['no-strong-signal'],\n };\n}\n","import type { BaseContext, NormalizedRequest } from '../contracts/request.js';\n\n/**\n * Derives the always-present base context from the normalized request and\n * process globals. Synchronous — requires no I/O.\n */\nexport function buildBaseContext(request: NormalizedRequest): BaseContext {\n return {\n queryText: request.lbuffer.trim(),\n cwd: request.cwd,\n ttyPath: request.ttyPath,\n shellPid: request.shellPid,\n shellName: 'zsh',\n platform: process.platform,\n timestamp: new Date().toISOString(),\n };\n}\n","import type { ContextEnvelope, NormalizedRequest } from '../contracts/request.js';\nimport { classifyIntent } from '../intent/router.js';\nimport { listContextProviders } from '../registry/context-providers.js';\nimport { appendDebugLog } from '../shared/debug-log.js';\nimport { buildBaseContext } from './base-context.js';\n\nexport async function gatherContext(request: NormalizedRequest): Promise<ContextEnvelope> {\n void appendDebugLog('context', 'pipeline start', {\n lbuffer: request.lbuffer,\n intent: request.intent,\n });\n\n const base = buildBaseContext(request);\n const decision = classifyIntent(request);\n\n void appendDebugLog('context', 'intent decision', {\n intent: decision.intent,\n signals: decision.signals,\n });\n\n const extras: ContextEnvelope['extras'] = [];\n const providers = listContextProviders();\n\n for (const provider of providers) {\n const supportsAllIntents = provider.intents.includes('*');\n const supportsIntent = provider.intents.includes(decision.intent);\n\n if (!supportsAllIntents && !supportsIntent) {\n continue;\n }\n\n try {\n const chunk = await provider.gather({ base, decision });\n if (chunk !== null) {\n extras.push(chunk);\n void appendDebugLog('context', 'provider chunk gathered', {\n providerId: provider.id,\n kind: chunk.kind,\n });\n }\n } catch (error) {\n void appendDebugLog('context', 'provider error', {\n providerId: provider.id,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n const envelope: ContextEnvelope = { base, extras };\n\n void appendDebugLog('context', 'envelope assembled', { extraCount: extras.length });\n\n return envelope;\n}\n","import { spawn } from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as net from 'node:net';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { appendDebugLog } from '../shared/debug-log.js';\n\nconst CONNECT_TIMEOUT_MS = 500;\nconst POLL_INTERVAL_MS = 50;\nconst POLL_MAX_ATTEMPTS = 40; // 2 seconds total\n\n/**\n * Attempts to connect to the daemon socket at `socketPath`.\n * Resolves true if the connection succeeds, false on any error.\n */\nfunction tryConnect(socketPath: string): Promise<boolean> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n client.destroy();\n resolve(false);\n }, CONNECT_TIMEOUT_MS);\n\n const client = net.createConnection(socketPath, () => {\n clearTimeout(timer);\n client.destroy();\n resolve(true);\n });\n\n client.on('error', () => {\n clearTimeout(timer);\n resolve(false);\n });\n });\n}\n\n/**\n * Polls the socket path until the daemon becomes connectable or\n * the attempt limit is reached.\n */\nasync function waitForSocket(\n socketPath: string,\n maxAttempts = POLL_MAX_ATTEMPTS,\n): Promise<boolean> {\n for (let i = 0; i < maxAttempts; i++) {\n if (await tryConnect(socketPath)) return true;\n await new Promise<void>((res) => setTimeout(res, POLL_INTERVAL_MS));\n }\n\n return false;\n}\n\n/**\n * Validates that `socketPath` is a safe daemon socket path.\n *\n * Rejects any path that does not resolve to /tmp/qq-*.sock to prevent\n * path-traversal attacks where a caller-controlled path could cause\n * fs.unlinkSync to delete arbitrary files or the daemon to listen on\n * an attacker-chosen location.\n */\nfunction assertSafeSocketPath(socketPath: string): void {\n const resolved = path.resolve(socketPath);\n const base = path.basename(resolved);\n const dir = path.dirname(resolved);\n const tmpRoots = ['/tmp', '/private/tmp'];\n if (!tmpRoots.includes(dir) || !base.startsWith('qq-') || !base.endsWith('.sock')) {\n throw new Error(`unsafe socket path rejected: ${socketPath}`);\n }\n}\n\n/**\n * Ensures a qq daemon is running at `socketPath`.\n *\n * Algorithm:\n * 1. Try to connect. If it succeeds, return immediately.\n * 2. If the socket file exists but the connect failed, unlink it (stale socket).\n * 3. Spawn `qq daemon --socket <path>` as a detached, unreferenced child.\n * 4. Poll until the new daemon starts listening, then return.\n *\n * Throws if the daemon does not start within the poll window.\n * Throws if `socketPath` is not a safe /tmp/qq-*.sock path.\n */\nexport async function ensureDaemon(socketPath: string): Promise<void> {\n assertSafeSocketPath(socketPath);\n void appendDebugLog('daemon', 'ensure start', { socketPath });\n\n // Fast path: daemon is already running\n if (await tryConnect(socketPath)) {\n void appendDebugLog('daemon', 'already running', { socketPath });\n return;\n }\n\n // Unlink stale socket file if present.\n //\n // TOCTOU note: there is a narrow window between the failed tryConnect above\n // and this unlink where a concurrent ensureDaemon call (e.g. from a second\n // terminal tab) may have already started a fresh daemon and be listening on\n // the socket. Unlinking here would destroy that live socket. This is\n // acceptable for the MVP (single active session assumed) but will need a\n // file-based lock (O_EXCL) before multi-window use is supported.\n try {\n fs.unlinkSync(socketPath);\n } catch {\n // File may not exist — that is fine\n }\n\n // Resolve the current bundled CLI entrypoint.\n // In the built runtime, import.meta.url points at dist/cli/main.js, which is\n // the exact script we want the detached daemon process to execute.\n const qqBin = process.execPath; // Node executable\n const qqScript = fileURLToPath(import.meta.url);\n\n if (!fs.existsSync(qqScript)) {\n void appendDebugLog('daemon', 'script missing', { qqScript });\n throw new Error(`qq daemon script not found at: ${qqScript}. Run 'pnpm build' first.`);\n }\n\n void appendDebugLog('daemon', 'spawning daemon', { qqScript, socketPath });\n const child = spawn(qqBin, [qqScript, 'daemon', '--socket', socketPath], {\n detached: true,\n stdio: 'ignore',\n });\n\n // Detach so the foreground client can exit without killing the daemon\n child.unref();\n\n const started = await waitForSocket(socketPath);\n if (!started) {\n void appendDebugLog('daemon', 'startup timeout', { socketPath });\n throw new Error(`qq daemon did not start within the expected window (${socketPath})`);\n }\n\n void appendDebugLog('daemon', 'daemon ready', { socketPath });\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport { type CandidateList, candidateListSchema } from '../contracts/candidates.js';\nimport type { ContextEnvelope } from '../contracts/request.js';\nimport { appendDebugLog } from '../shared/debug-log.js';\nimport { readEnvValueFromDotEnvLocal } from '../shared/env-file.js';\nimport type { LLMAdapter } from './provider.js';\n\nconst DEFAULT_MODEL = 'claude-haiku-4-5-20251001';\n\nfunction resolveModel(): string {\n return process.env.QQ_MODEL ?? readEnvValueFromDotEnvLocal('QQ_MODEL') ?? DEFAULT_MODEL;\n}\n\nfunction extractText(content: Array<{ type: string; text?: string }>): string {\n return content\n .filter((block) => block.type === 'text' && typeof block.text === 'string')\n .map((block) => block.text ?? '')\n .join('')\n .trim();\n}\n\nfunction stripCodeFence(raw: string): string {\n const m = raw.trim().match(/^```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?```\\s*$/);\n return m ? m[1].trim() : raw.trim();\n}\n\nfunction parseCandidates(text: string): CandidateList {\n let parsed: unknown;\n try {\n parsed = JSON.parse(stripCodeFence(text));\n } catch {\n // Not JSON at all — treat entire text as a plain command (prose fallback)\n const trimmed = text.trim();\n return [{ command: trimmed || 'echo \"\"', explanation: '' }];\n }\n // Valid JSON but wrong schema — do not use raw JSON text as a command\n try {\n return candidateListSchema.parse(parsed);\n } catch {\n return [{ command: 'echo \"\"', explanation: 'QueQue: unexpected response format' }];\n }\n}\n\nfunction shouldForceSelector(): boolean {\n const configured =\n process.env.QQ_FORCE_SELECTOR ?? readEnvValueFromDotEnvLocal('QQ_FORCE_SELECTOR');\n return configured === '1' || configured === 'true';\n}\n\nfunction ensureSelectableCandidates(candidates: CandidateList): CandidateList {\n if (!shouldForceSelector() || candidates.length >= 2) {\n return candidates;\n }\n\n const [first] = candidates;\n\n return [\n first,\n {\n command: first.command,\n explanation:\n first.explanation.length > 0\n ? `${first.explanation} (forced duplicate for selector testing)`\n : 'Forced duplicate for selector testing.',\n },\n ];\n}\n\nfunction buildPrompt(envelope: ContextEnvelope): string {\n const gitChunk = envelope.extras.find((chunk) => chunk.kind === 'git');\n\n return [\n 'Return ONLY a JSON array of 1-3 shell command candidates, most likely first.',\n 'Each item must have exactly these keys: \"command\" and \"explanation\".',\n 'No markdown, no prose, no code fences. Raw JSON array only.',\n '',\n 'The command should be safe to place back into a shell buffer.',\n '',\n 'Shell context:',\n JSON.stringify(\n {\n cwd: envelope.base.cwd,\n queryText: envelope.base.queryText,\n platform: envelope.base.platform,\n shellName: envelope.base.shellName,\n ...(gitChunk ? { versionControl: gitChunk.payload } : {}),\n },\n null,\n 2,\n ),\n ].join('\\n');\n}\n\n/**\n * Calls Claude with the assembled context envelope and returns ranked command candidates.\n *\n * `rbuffer` remains a side parameter because it is shell transport state, not context.\n * The envelope describes the request intent and execution environment, while Phase 4's\n * TUI remains responsible for deciding how the raw shell buffers are rewritten.\n */\nexport async function fetchCandidates(\n envelope: ContextEnvelope,\n rbuffer: string = '',\n): Promise<CandidateList> {\n const apiKey = process.env.ANTHROPIC_API_KEY ?? readEnvValueFromDotEnvLocal('ANTHROPIC_API_KEY');\n if (!apiKey) {\n throw new Error('ANTHROPIC_API_KEY is required in the environment or .env.local');\n }\n\n const client = new Anthropic({ apiKey });\n const prompt = buildPrompt(envelope);\n const model = resolveModel();\n\n void appendDebugLog('provider', 'request start', {\n model,\n cwd: envelope.base.cwd,\n rbufferLength: rbuffer.length,\n extras: envelope.extras.map((chunk) => chunk.kind),\n });\n\n try {\n const response = await client.messages.create(\n {\n model,\n max_tokens: 1024,\n temperature: 0,\n system:\n 'You are QueQue, a terminal shell assistant. Return ONLY a JSON array of command candidates, ranked with the most correct/direct command first. No prose, no markdown, no code fences. When a command requires a value the user must supply (hostname, filename, branch name, etc.), wrap it in angle brackets: <placeholder>. Use descriptive names like <user@host>, <filename>, <branch-name>. Do not use angle brackets for optional flags or known values.',\n messages: [{ role: 'user', content: prompt }],\n },\n {\n timeout: 25_000, // 25s — slightly under the zsh 30s FIFO timeout\n },\n );\n\n const text = extractText(response.content);\n const candidates = ensureSelectableCandidates(parseCandidates(text));\n\n void appendDebugLog('provider', 'response parsed', {\n model,\n candidateCount: candidates.length,\n forceSelector: shouldForceSelector(),\n });\n\n return candidates;\n } catch (error) {\n void appendDebugLog('provider', 'request failed', {\n model,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n}\n\nexport const claudeAdapter: LLMAdapter = {\n fetchCandidates,\n};\n","import { z } from 'zod';\n\nexport const commandCandidateSchema = z.object({\n command: z.string().min(1),\n explanation: z.string(),\n});\n\nexport type CommandCandidate = z.infer<typeof commandCandidateSchema>;\n\nexport const candidateListSchema = z.array(commandCandidateSchema).min(1).max(5);\n\nexport type CandidateList = z.infer<typeof candidateListSchema>;\n","import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nfunction findUp(startDir: string, filename: string): string | null {\n let current = startDir;\n\n while (true) {\n const candidate = join(current, filename);\n if (existsSync(candidate)) {\n return candidate;\n }\n\n const parent = dirname(current);\n if (parent === current) {\n return null;\n }\n\n current = parent;\n }\n}\n\nfunction parseEnvFile(content: string): Map<string, string> {\n const values = new Map<string, string>();\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith('#')) {\n continue;\n }\n\n const match = line.match(/^(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);\n if (!match) {\n continue;\n }\n\n const [, key, rawValue] = match;\n let value = rawValue.trim();\n\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n values.set(key, value);\n }\n\n return values;\n}\n\n// Module-level cache: keyed by \"key\\0startDir\" so different start directories\n// are cached independently. Null means the key was not found. Undefined means\n// the entry has not been populated yet (Map.get returns undefined for missing keys).\nconst envCache = new Map<string, string | null>();\n\nexport function readEnvValueFromDotEnvLocal(\n key: string,\n startDir = dirname(fileURLToPath(import.meta.url)),\n): string | null {\n const cacheKey = `${key}\\0${startDir}`;\n if (envCache.has(cacheKey)) {\n return envCache.get(cacheKey) ?? null;\n }\n\n const envPath = findUp(startDir, '.env.local');\n if (!envPath) {\n envCache.set(cacheKey, null);\n return null;\n }\n\n const values = parseEnvFile(readFileSync(envPath, 'utf8'));\n const result = values.get(key) ?? null;\n envCache.set(cacheKey, result);\n return result;\n}\n","import { execSync } from 'node:child_process';\nimport * as fsp from 'node:fs/promises';\nimport * as os from 'node:os';\n\nexport type DetectedProvider =\n | { kind: 'anthropic-key' }\n | { kind: 'claude-cli' }\n | { kind: 'ollama'; baseUrl: string }\n | { kind: 'openai-key' }\n | { kind: 'none' };\n\nfunction claudeOnPath(): boolean {\n try {\n execSync('which claude', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function claudeAuthFileExists(): Promise<boolean> {\n const home = os.homedir();\n const candidates = [`${home}/.claude/.credentials.json`, `${home}/.claude/credentials.json`];\n for (const p of candidates) {\n try {\n await fsp.stat(p);\n return true;\n } catch {\n // file not found — try next\n }\n }\n return false;\n}\n\nasync function ollamaHealthy(): Promise<boolean> {\n try {\n const res = await fetch('http://localhost:11434/api/tags', {\n signal: AbortSignal.timeout(300),\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n\nexport async function detectProvider(): Promise<DetectedProvider> {\n // Step 1 — Anthropic key env\n if (process.env.ANTHROPIC_API_KEY) {\n return { kind: 'anthropic-key' };\n }\n\n // Step 2 — Claude CLI: binary on PATH + auth file present\n if (claudeOnPath() && (await claudeAuthFileExists())) {\n return { kind: 'claude-cli' };\n }\n\n // Step 3 — Ollama health check\n if (await ollamaHealthy()) {\n return { kind: 'ollama', baseUrl: 'http://localhost:11434' };\n }\n\n // Step 4 — OpenAI key env\n if (process.env.OPENAI_API_KEY) {\n return { kind: 'openai-key' };\n }\n\n // Step 5 — nothing found\n return { kind: 'none' };\n}\n","/**\n * Returns the Unix socket path for the qq daemon for a given UID.\n *\n * Always uses /tmp to avoid the macOS TMPDIR path-length issue.\n * Node documents a 103-byte macOS limit on Unix socket paths, and\n * macOS TMPDIR paths are often too long (e.g. /var/folders/...).\n *\n * Example: socketPathForUid(501) === '/tmp/qq-501.sock'\n */\nexport function socketPathForUid(uid: number): string {\n return `/tmp/qq-${uid}.sock`;\n}\n\n/**\n * Returns the Unix socket path for the current process's UID.\n */\nexport function socketPath(): string {\n return socketPathForUid(process.getuid?.() ?? 0);\n}\n","import { Box, Text, useInput } from 'ink';\nimport { type ReactElement, useEffect, useState } from 'react';\nimport type { CandidateList } from '../contracts/candidates.js';\nimport { ControlsLine } from './ControlsLine.js';\nimport { LoadingSpinner } from './LoadingSpinner.js';\nimport { Modal } from './Modal.js';\nimport { SearchInput } from './SearchInput.js';\n\n/**\n * Props for CandidateSelect.\n *\n * D-06: candidates is nullable — null means loading state (spinner shown).\n */\ninterface Props {\n candidates: CandidateList | null;\n initialQuery?: string;\n onSelect: (command: string, explanation: string) => void;\n onCancel: () => void;\n error?: boolean;\n}\n\n/**\n * Filter candidates by case-insensitive substring match on command text.\n * Returns the full list unchanged when query is empty or falsy.\n */\nfunction filterCandidates(candidates: CandidateList, query: string): CandidateList {\n if (!query) return candidates;\n const lower = query.toLowerCase();\n return candidates.filter((c) => c.command.toLowerCase().includes(lower));\n}\n\n/**\n * Monocle-style candidate selector.\n *\n * Keys:\n * ↑ / ↓ — move selection (wraps)\n * Enter — accept selected command\n * Esc — cancel and restore shell buffer\n * Backspace — delete last char from live search query\n * Any printable char → live search (appended to query)\n */\nexport function CandidateSelect({\n candidates,\n initialQuery,\n onSelect,\n onCancel,\n error,\n}: Props): ReactElement {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [query, setQuery] = useState(initialQuery ?? '');\n\n // Reset selectedIndex when candidates arrive (Pitfall 2 fix).\n // Also clear initialQuery pre-filter if it produces zero matches — the lbuffer\n // was already used as context for Claude; filtering candidates by it too is\n // harmful when no command literally contains the lbuffer text.\n // biome-ignore lint/correctness/useExhaustiveDependencies: candidates is a prop; reset on arrival is intentional\n useEffect(() => {\n setSelectedIndex(0);\n if (candidates && candidates.length > 0 && filterCandidates(candidates, query).length === 0) {\n setQuery('');\n }\n }, [candidates]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: reset selectedIndex when query changes to prevent out-of-bounds access after filter narrows visible list\n useEffect(() => {\n setSelectedIndex(0);\n }, [query]);\n\n // Single useInput handler with null-guards (Pitfall 3 fix)\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n return;\n }\n\n if (key.backspace) {\n setQuery((q) => q.slice(0, -1));\n return;\n }\n\n // key.return must be checked before the generic input handler — in raw mode\n // Enter sends '\\r' as `input` (truthy), which would otherwise be consumed by\n // setQuery and prevent the accept action from firing.\n if (key.return && candidates) {\n const visible = filterCandidates(candidates, query);\n if (visible.length === 0) return;\n const selected = visible[selectedIndex] ?? visible[0]!;\n const explanation = selected.explanation || `see man ${selected.command.split(' ')[0]}`;\n onSelect(selected.command, explanation);\n return;\n }\n\n if (input && !key.ctrl && !key.meta) {\n setQuery((q) => q + input);\n return;\n }\n\n // Navigation: guard against null candidates\n if (key.upArrow && candidates) {\n const visible = filterCandidates(candidates, query);\n setSelectedIndex((i) => (i === 0 ? visible.length - 1 : i - 1));\n return;\n }\n\n if (key.downArrow && candidates) {\n const visible = filterCandidates(candidates, query);\n setSelectedIndex((i) => (i + 1) % visible.length);\n return;\n }\n });\n\n let content: ReactElement;\n if (error === true) {\n content = (\n <Box marginTop={1}>\n <Text dimColor>{'provider error — press esc to return'}</Text>\n </Box>\n );\n } else if (candidates === null) {\n content = (\n <Box marginTop={1}>\n <LoadingSpinner />\n </Box>\n );\n } else {\n const visible = filterCandidates(candidates, query);\n if (visible.length === 0) {\n content = (\n <Box marginTop={1}>\n <Text dimColor>{'no matches — try a different query'}</Text>\n </Box>\n );\n } else {\n content = (\n <Box flexDirection=\"column\" marginTop={1}>\n {visible.map((candidate, index) => {\n const active = index === selectedIndex;\n return (\n <Box key={candidate.command} flexDirection=\"column\" marginBottom={1}>\n <Box>\n {active ? <Text color=\"ansi256(166)\">{'┌> '}</Text> : <Text>{' '}</Text>}\n <Text bold={active} color={active ? 'white' : undefined} dimColor={!active}>\n {candidate.command}\n </Text>\n </Box>\n {candidate.explanation.length > 0 && (\n <Box>\n <Text>{' '}</Text>\n <Text dimColor>{candidate.explanation}</Text>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n }\n }\n\n return (\n <Modal>\n {initialQuery && initialQuery.length > 0 && (\n <Box>\n <Text dimColor>{`queque › ${initialQuery}`}</Text>\n </Box>\n )}\n <SearchInput query={query} />\n {content}\n <ControlsLine />\n </Modal>\n );\n}\n","import { Box, Text } from 'ink';\nimport type { ReactElement } from 'react';\n\nexport function ControlsLine(): ReactElement {\n return (\n <Box marginTop={1}>\n <Text backgroundColor=\"ansi256(238)\" color=\"white\" bold>\n {' ↑↓ '}\n </Text>\n <Text backgroundColor=\"ansi256(245)\" color=\"black\">\n {' select '}\n </Text>\n <Text dimColor>{' · '}</Text>\n <Text backgroundColor=\"ansi256(238)\" color=\"white\" bold>\n {' enter '}\n </Text>\n <Text backgroundColor=\"ansi256(245)\" color=\"black\">\n {' accept '}\n </Text>\n <Text dimColor>{' · '}</Text>\n <Text backgroundColor=\"ansi256(238)\" color=\"white\" bold>\n {' esc '}\n </Text>\n <Text backgroundColor=\"ansi256(245)\" color=\"black\">\n {' cancel '}\n </Text>\n </Box>\n );\n}\n","import { Text } from 'ink';\nimport { type ReactElement, useEffect, useState } from 'react';\n\nconst FRAMES = ['thinking…', 'thinking.', 'thinking..', 'thinking…'];\n\nexport function LoadingSpinner(): ReactElement {\n const [frame, setFrame] = useState(0);\n\n useEffect(() => {\n const id = setInterval(() => {\n setFrame((f) => (f + 1) % FRAMES.length);\n }, 200);\n return () => clearInterval(id);\n }, []);\n\n return <Text dimColor>{FRAMES[frame]}</Text>;\n}\n","import { Box } from 'ink';\nimport type { ReactElement, ReactNode } from 'react';\n\ninterface ModalProps {\n children: ReactNode;\n width?: number;\n}\n\nexport function Modal({ children, width = 80 }: ModalProps): ReactElement {\n return (\n <Box flexDirection=\"column\" paddingX={1} width={width}>\n {children}\n </Box>\n );\n}\n","import { Box, Text } from 'ink';\nimport type { ReactElement } from 'react';\n\ninterface SearchInputProps {\n query: string;\n}\n\nexport function SearchInput({ query }: SearchInputProps): ReactElement {\n return (\n <Box>\n <Text color=\"cyan\" bold>\n {'FILTER: '}\n </Text>\n {query ? <Text>{query}</Text> : <Text dimColor>{'type to filter…'}</Text>}\n </Box>\n );\n}\n","import * as fsp from 'node:fs/promises';\nimport { type ShellResult, shellResultSchema } from '../contracts/shell.js';\n\n/**\n * Validates a ShellResult and writes newline-terminated JSON to `resultFile`.\n *\n * Write strategy depends on the type of `resultFile`:\n *\n * - Named pipe (FIFO): writes directly via fsp.writeFile() because rename(2)\n * would replace the FIFO inode and break the waiting reader. Direct write\n * delivers data to the open reader immediately.\n *\n * - Regular file: atomic rename — the JSON is first written to a sibling\n * `.tmp` file and then renamed into place. On the same filesystem,\n * rename(2) is atomic, so the zsh bridge will never observe a partial write.\n * If the process is killed after the tmp write but before the rename, the\n * result file simply does not appear and the zsh bridge falls back to\n * cancel — no data corruption.\n *\n * Throws if the result does not conform to the ShellResult schema.\n */\nexport async function writeShellResult(resultFile: string, result: ShellResult): Promise<void> {\n // Validate the result shape — catch programming errors early\n const parsed = shellResultSchema.parse(result);\n\n const line = `${JSON.stringify(parsed)}\\n`;\n\n // Detect named pipe: rename(2) would replace the FIFO inode and break\n // the waiting zsh reader. Direct writeFile delivers data to the open reader.\n let isFifo = false;\n try {\n const st = await fsp.stat(resultFile);\n isFifo = st.isFIFO();\n } catch {\n // Path does not exist yet (regular file not created yet) — not a FIFO\n }\n\n if (isFifo) {\n // Named pipe: direct write — no atomic rename\n await fsp.writeFile(resultFile, line, { encoding: 'utf-8' });\n } else {\n // Regular file: atomic rename for zero-partial-write guarantee\n const tmpFile = `${resultFile}.tmp`;\n await fsp.writeFile(tmpFile, line, { encoding: 'utf-8' });\n await fsp.rename(tmpFile, resultFile);\n }\n}\n","import { runForegroundClient } from '../../client/run-foreground.js';\nimport { appendDebugLog } from '../../shared/debug-log.js';\n\nexport interface ClientCommandOptions {\n requestFile: string;\n resultFile: string;\n resultMode?: string;\n}\n\n/**\n * Real client command handler.\n *\n * `qq client --request-file <path> --result-file <path> [--result-mode <mode>]`\n *\n * Dispatches to the foreground client loop. The `--result-mode` flag selects\n * the deterministic Phase 1 seam:\n * cancel — emit a cancel result (default)\n * replace-buffer-fixture — emit a deterministic replace-buffer result\n *\n * Free of Ink and React imports — Phase 4 will wire the TUI inside\n * runForegroundClient without changing this handler.\n */\nconst VALID_MODES = ['cancel', 'replace-buffer-fixture', 'llm'] as const;\ntype ResultMode = (typeof VALID_MODES)[number];\n\nfunction parseResultMode(mode: string | undefined): ResultMode {\n if (mode === undefined || mode === 'llm') return 'llm';\n if (mode === 'cancel') return 'cancel';\n if (mode === 'replace-buffer-fixture') return 'replace-buffer-fixture';\n void appendDebugLog('client', `unknown --result-mode \"${mode}\", defaulting to cancel`);\n return 'cancel';\n}\n\nexport async function clientCommand(options: ClientCommandOptions): Promise<void> {\n const resultMode = parseResultMode(options.resultMode);\n\n void appendDebugLog('client', 'command start', {\n requestFile: options.requestFile,\n resultFile: options.resultFile,\n resultMode,\n });\n\n await runForegroundClient({\n requestFile: options.requestFile,\n resultFile: options.resultFile,\n resultMode,\n });\n}\n","import * as net from 'node:net';\nimport { ipcRequestSchema } from '../contracts/ipc.js';\nimport { appendDebugLog } from '../shared/debug-log.js';\n\n/**\n * Starts the daemon Unix-socket server.\n *\n * Handles newline-delimited JSON IPC messages. Supported requests:\n * {kind: 'ping'} → {kind: 'pong'}\n * {kind: 'ensure-session'} → {kind: 'session-ready', socketPath}\n * {kind: 'run-query'} → {kind: 'query-accepted', requestId}\n *\n * The server is intentionally free of Ink, React, and /dev/tty assumptions —\n * it runs fully in the background without a TTY.\n */\nexport function startDaemonServer(socketPath: string): Promise<net.Server> {\n return new Promise((resolve, reject) => {\n const MAX_BUF_BYTES = 64 * 1024; // 64 KB — generous for any realistic IPC message\n\n // TODO(CR-005): Add session token authentication before Phase 4 LLM integration.\n // Generate a random token in ensureDaemon, write it to a chmod-600 file in\n // /tmp/qq-<uid>/, and require clients to send it as the first IPC frame field.\n const server = net.createServer((socket) => {\n let buf = '';\n void appendDebugLog('daemon', 'socket connected', { socketPath });\n\n socket.on('data', (chunk) => {\n if (buf.length + chunk.length > MAX_BUF_BYTES) {\n socket.destroy(new Error('IPC message too large'));\n return;\n }\n buf += chunk.toString();\n let nl = buf.indexOf('\\n');\n\n while (nl !== -1) {\n const line = buf.slice(0, nl).trim();\n buf = buf.slice(nl + 1);\n nl = buf.indexOf('\\n');\n\n if (!line) continue;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n // Ignore malformed messages — keep connection alive\n continue;\n }\n\n const result = ipcRequestSchema.safeParse(parsed);\n if (!result.success) {\n // Unknown message kind — ignore silently\n void appendDebugLog('daemon', 'ignored unknown request', { line });\n continue;\n }\n\n const req = result.data;\n void appendDebugLog('daemon', 'request received', req);\n\n switch (req.kind) {\n case 'ping': {\n socket.write(`${JSON.stringify({ kind: 'pong' })}\\n`);\n void appendDebugLog('daemon', 'replied pong');\n break;\n }\n case 'ensure-session': {\n socket.write(`${JSON.stringify({ kind: 'session-ready', socketPath })}\\n`);\n void appendDebugLog('daemon', 'replied session-ready', { socketPath });\n break;\n }\n case 'run-query': {\n const requestId = Math.random().toString(36).slice(2);\n socket.write(`${JSON.stringify({ kind: 'query-accepted', requestId })}\\n`);\n void appendDebugLog('daemon', 'replied query-accepted', { requestId });\n break;\n }\n }\n }\n });\n\n socket.on('error', () => {\n // Connection errors are per-socket, not fatal to the server\n });\n });\n\n server.on('error', reject);\n\n server.listen(socketPath, () => {\n void appendDebugLog('daemon', 'listening', { socketPath });\n resolve(server);\n });\n });\n}\n","import { z } from 'zod';\nimport { shellRequestSchema } from './shell.js';\n\n/**\n * IPC request — sent from the foreground client to the daemon over a Unix socket.\n */\nexport const ipcRequestSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('ping'),\n }),\n z.object({\n kind: z.literal('ensure-session'),\n shellPid: z.number().int().positive(),\n ttyPath: z.string(),\n }),\n z.object({\n kind: z.literal('run-query'),\n request: shellRequestSchema,\n }),\n]);\n\nexport type IpcRequest = z.infer<typeof ipcRequestSchema>;\n\n/**\n * IPC response — returned by the daemon for each request kind.\n */\nexport const ipcResponseSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('pong'),\n }),\n z.object({\n kind: z.literal('session-ready'),\n socketPath: z.string(),\n }),\n z.object({\n kind: z.literal('query-accepted'),\n requestId: z.string(),\n }),\n]);\n\nexport type IpcResponse = z.infer<typeof ipcResponseSchema>;\n","import { ensureDaemon } from '../../daemon/bootstrap.js';\nimport { startDaemonServer } from '../../daemon/server.js';\nimport { appendDebugLog } from '../../shared/debug-log.js';\nimport { socketPath as defaultSocketPath } from '../../shared/socket-path.js';\n\nexport interface DaemonCommandOptions {\n socket?: string;\n ensure?: boolean;\n}\n\n/**\n * Real daemon command handler.\n *\n * `qq daemon --socket <path>` — starts the daemon server and blocks.\n * `qq daemon --socket <path> --ensure` — ensures a daemon is running, then exits.\n *\n * Free of Ink, React, and /dev/tty assumptions.\n */\nexport async function daemonCommand(options: DaemonCommandOptions): Promise<void> {\n const sock = options.socket ?? defaultSocketPath();\n void appendDebugLog('daemon', 'command start', { socket: sock, ensure: options.ensure });\n\n if (options.ensure) {\n await ensureDaemon(sock);\n void appendDebugLog('daemon', 'ensure command complete', { socket: sock });\n return;\n }\n\n // Start the server and block indefinitely\n const server = await startDaemonServer(sock);\n void appendDebugLog('daemon', 'server started', { socket: sock });\n\n // Graceful shutdown on SIGTERM / SIGINT\n const shutdown = () => {\n void appendDebugLog('daemon', 'shutdown', { socket: sock });\n server.close(() => {\n process.exit(0);\n });\n };\n\n process.once('SIGTERM', shutdown);\n process.once('SIGINT', shutdown);\n\n // Keep the process alive\n await new Promise<void>(() => {\n // Never resolves — daemon runs until signal\n });\n}\n"],"mappings":"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","names":["fs","execFile","promisify","execFileAsync","promisify","execFile","path","registry","registry","registry","fsp","z","z","socketPath","resolve","z","existsSync","dirname","fileURLToPath","fsp","Box","Text","useEffect","useState","Text","jsx","Box","jsx","Box","Text","jsx","jsxs","jsx","jsxs","useState","useEffect","Box","Text","fsp","socketPath","resolve","net","z","z","socketPath","resolve"]}
1
+ {"version":3,"sources":["../../src/cli/main.ts","../../src/context/providers/filesystem-context.ts","../../src/context/providers/git-context.ts","../../src/shared/debug-log.ts","../../src/shared/vcs-context.ts","../../src/registry/context-providers.ts","../../src/registry/provider-backends.ts","../../src/registry/shell-adapters.ts","../../src/registry/storage-hooks.ts","../../src/registry/bootstrap.ts","../../src/client/run-foreground.ts","../../src/contracts/request.ts","../../src/contracts/shell.ts","../../src/intent/router.ts","../../src/context/base-context.ts","../../src/context/pipeline.ts","../../src/daemon/bootstrap.ts","../../src/providers/claude.ts","../../src/contracts/candidates.ts","../../src/shared/env-file.ts","../../src/providers/detect.ts","../../src/shared/socket-path.ts","../../src/ui/CandidateSelect.tsx","../../src/ui/ControlsLine.tsx","../../src/ui/LoadingSpinner.tsx","../../src/ui/Modal.tsx","../../src/ui/SearchInput.tsx","../../src/client/result-writer.ts","../../src/cli/commands/client.ts","../../src/daemon/server.ts","../../src/contracts/ipc.ts","../../src/cli/commands/daemon.ts","../../src/cli/commands/init.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport { cac } from 'cac';\nimport { bootstrapBuiltins } from '../registry/bootstrap.js';\nimport { clientCommand } from './commands/client.js';\nimport { daemonCommand } from './commands/daemon.js';\nimport { initCommand } from './commands/init.js';\n\ntype ClientOptions = {\n requestFile?: string;\n resultFile?: string;\n resultMode?: string;\n};\n\ntype DaemonOptions = {\n socket?: string;\n ensure?: boolean;\n};\n\nfunction requiredOption(name: string, value: string | undefined): string {\n if (!value) {\n throw new Error(`Missing required option: ${name}`);\n }\n\n return value;\n}\n\n// ---------------------------------------------------------------------------\n// Top-level error handlers — FIFO safety net (RUN-02 Pitfall 3)\n//\n// These handlers fire when an error escapes the async main() chain entirely\n// (e.g. a synchronous throw from Ink internals or a void async call that\n// rejects after the Promise resolves). Without them a crash would leave the\n// zsh widget blocking on the FIFO read for up to 30 seconds.\n//\n// Both handlers:\n// 1. Read the FIFO path from process.env.QQ_RESULT_FILE (exported by the\n// zsh widget before zellij run, so it is always available in the env).\n// 2. Write {\"kind\":\"cancel\"}\\n to that path using synchronous writeFileSync\n// (writeShellResult is async-unsafe inside an exception handler).\n// 3. Call process.exit(1) unconditionally — the exit prevents re-entry.\n//\n// Security note (T-04-03-01): QQ_RESULT_FILE is set by the trusted zsh widget\n// (mktemp -d /tmp/qq-sess.XXXXXX), so we validate the path before writing to\n// prevent an attacker-controlled env var from redirecting writes to arbitrary files.\n// ---------------------------------------------------------------------------\n\n// Matches paths created by: mktemp -d /tmp/qq-sess.XXXXXX\nconst QQ_RESULT_FILE_PATTERN = /^\\/tmp\\/qq-sess\\.[A-Za-z0-9]+\\//;\n\nprocess.on('uncaughtException', (err: Error) => {\n console.error('QueQue: uncaught exception:', err.message);\n const resultFile = process.env.QQ_RESULT_FILE;\n if (resultFile && QQ_RESULT_FILE_PATTERN.test(resultFile)) {\n try {\n fs.writeFileSync(resultFile, '{\"kind\":\"cancel\"}\\n');\n } catch {\n // Ignore write failures (FIFO reader may already be gone)\n }\n }\n process.exit(1);\n});\n\nprocess.on('unhandledRejection', (reason: unknown) => {\n const message = reason instanceof Error ? reason.message : String(reason);\n console.error('QueQue: unhandled rejection:', message);\n const resultFile = process.env.QQ_RESULT_FILE;\n if (resultFile && QQ_RESULT_FILE_PATTERN.test(resultFile)) {\n try {\n fs.writeFileSync(resultFile, '{\"kind\":\"cancel\"}\\n');\n } catch {\n // Ignore write failures (FIFO reader may already be gone)\n }\n }\n process.exit(1);\n});\n\nexport async function main(argv = process.argv.slice(2)): Promise<void> {\n bootstrapBuiltins();\n const cli = cac('qq');\n\n cli\n .command('client')\n .option('--request-file <path>', 'Path to the serialized shell request')\n .option('--result-file <path>', 'Path to write the serialized shell result')\n .option('--result-mode <mode>', 'Result mode: llm | cancel | replace-buffer-fixture')\n .action(async (options: ClientOptions) => {\n const requestFile = requiredOption('--request-file', options.requestFile);\n const resultFile = requiredOption('--result-file', options.resultFile);\n\n await clientCommand({ requestFile, resultFile, resultMode: options.resultMode });\n });\n\n cli\n .command(\n 'init <shell>',\n 'Print shell integration script (add `eval \"$(qq init zsh)\"` to ~/.zshrc)',\n )\n .action((shell: string) => {\n initCommand(shell);\n });\n\n cli\n .command('daemon')\n .option('--socket <path>', 'Unix socket path for the daemon')\n .option('--ensure', 'Ensure the daemon is running before returning')\n .action(async (options: DaemonOptions) => {\n await daemonCommand(options);\n });\n\n cli.help();\n cli.parse(['node', 'qq', ...argv], { run: false });\n\n await cli.runMatchedCommand();\n}\n\nconst isDirectRun = process.argv[1]\n ? import.meta.url === new URL(`file://${process.argv[1]}`).href\n : false;\n\nif (isDirectRun) {\n void main().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exitCode = 1;\n });\n}\n","import type { ContextChunk } from '../../contracts/request.js';\nimport type { ContextProvider, GatherContextInput } from '../provider.js';\n\nconst FILENAME_RE = /\\b[\\w.-]+\\.\\w{2,6}\\b/g;\n\nexport const filesystemContextProvider: ContextProvider = {\n id: 'filesystem-context',\n intents: ['filesystem'],\n async gather(input: GatherContextInput): Promise<ContextChunk> {\n const match = input.base.queryText.match(FILENAME_RE);\n\n return {\n kind: 'filesystem',\n payload: {\n cwd: input.base.cwd,\n apparentFilename: match?.[0] ?? null,\n },\n };\n },\n};\n","import { execFile } from 'node:child_process';\nimport { statSync } from 'node:fs';\nimport { promisify } from 'node:util';\nimport type { ContextChunk } from '../../contracts/request.js';\nimport { appendDebugLog } from '../../shared/debug-log.js';\nimport { detectVcsContext } from '../../shared/vcs-context.js';\nimport type { ContextProvider, GatherContextInput } from '../provider.js';\n\nconst execFileAsync = promisify(execFile);\nconst GIT_TIMEOUT_MS = 5000;\n\nfunction assertSafeCwd(cwd: string): void {\n let st: ReturnType<typeof statSync>;\n try {\n st = statSync(cwd);\n } catch {\n throw new Error(`cwd not accessible: ${cwd}`);\n }\n if (!st.isDirectory()) throw new Error(`cwd is not a directory: ${cwd}`);\n}\n\nfunction unescapeGitPath(s: string): string {\n return s\n .replace(/\\\\([0-7]{3})/g, (_, oct) => String.fromCodePoint(parseInt(oct, 8)))\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\\\\/g, '\\\\');\n}\n\nfunction stripQuotes(value: string): string {\n if (value.startsWith('\"') && value.endsWith('\"')) {\n return unescapeGitPath(value.slice(1, -1));\n }\n\n return value;\n}\n\n/** @internal For direct unit coverage of porcelain edge cases. */\nexport function parsePorcelainLine(line: string): string | null {\n if (line.length < 4) {\n return null;\n }\n\n const rest = line.slice(3);\n const renameSeparator = ' -> ';\n const renameIndex = rest.indexOf(renameSeparator);\n\n if (renameIndex !== -1) {\n return stripQuotes(rest.slice(renameIndex + renameSeparator.length));\n }\n\n return stripQuotes(rest);\n}\n\nasync function getChangedFiles(cwd: string): Promise<string[]> {\n try {\n assertSafeCwd(cwd);\n const { stdout } = await execFileAsync('git', ['-C', cwd, 'status', '--porcelain'], {\n encoding: 'utf8',\n timeout: GIT_TIMEOUT_MS,\n });\n\n return stdout\n .split('\\n')\n .filter(Boolean)\n .map(parsePorcelainLine)\n .filter((path): path is string => path !== null);\n } catch {\n return [];\n }\n}\n\nexport const gitContextProvider: ContextProvider = {\n id: 'git-context',\n intents: ['codebase', 'shell-command'],\n async gather(input: GatherContextInput): Promise<ContextChunk | null> {\n if (\n input.decision.intent === 'shell-command' &&\n !input.decision.signals.includes('git-prefix')\n ) {\n return null;\n }\n\n try {\n const vcs = await detectVcsContext(input.base.cwd);\n if (vcs.kind === 'none') {\n return null;\n }\n\n const changedFiles = await getChangedFiles(input.base.cwd);\n\n void appendDebugLog('context', 'git provider gathered', {\n cwd: input.base.cwd,\n branch: vcs.branch,\n dirty: vcs.dirty,\n changedFiles: changedFiles.length,\n });\n\n return {\n kind: 'git',\n payload: {\n cwd: vcs.cwd,\n root: vcs.root,\n branch: vcs.branch,\n dirty: vcs.dirty,\n changedFiles,\n },\n };\n } catch (error) {\n void appendDebugLog('context', 'git provider failed', {\n cwd: input.base.cwd,\n message: error instanceof Error ? error.message : String(error),\n });\n\n return null;\n }\n },\n};\n","import * as fsp from 'node:fs/promises';\n\nexport const debugLogPath =\n process.env.QQ_DEBUG_LOG_FILE ?? `/tmp/qq-${process.getuid?.() ?? 'unknown'}-debug.log`;\n\nfunction formatDetails(details: unknown): string {\n if (details === undefined) return '';\n try {\n return ` ${JSON.stringify(details)}`;\n } catch {\n return ' [unserializable-details]';\n }\n}\n\nexport async function appendDebugLog(\n scope: string,\n message: string,\n details?: unknown,\n): Promise<void> {\n const line = `${new Date().toISOString()} [${scope}] ${message}${formatDetails(details)}\\n`;\n\n try {\n await fsp.appendFile(debugLogPath, line, { encoding: 'utf-8', mode: 0o600 });\n } catch {\n // Debug logging must never break the user flow.\n }\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\nexport type VcsContext =\n | {\n kind: 'none';\n cwd: string;\n }\n | {\n kind: 'git';\n cwd: string;\n root: string;\n branch: string | null;\n dirty: boolean;\n };\n\nasync function runGit(cwd: string, args: string[]): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync('git', ['-C', cwd, ...args], { encoding: 'utf8' });\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\nexport async function detectVcsContext(cwd: string): Promise<VcsContext> {\n const insideWorkTree = await runGit(cwd, ['rev-parse', '--is-inside-work-tree']);\n\n if (insideWorkTree !== 'true') {\n return { kind: 'none', cwd };\n }\n\n const root = (await runGit(cwd, ['rev-parse', '--show-toplevel'])) ?? cwd;\n const branch = (await runGit(cwd, ['branch', '--show-current'])) || null;\n const dirty = Boolean((await runGit(cwd, ['status', '--porcelain=v1']))?.length);\n\n return {\n kind: 'git',\n cwd,\n root,\n branch,\n dirty,\n };\n}\n","import type { ContextProvider } from '../context/provider.js';\n\nconst registry = new Map<string, ContextProvider>();\n\nexport function registerContextProvider(descriptor: ContextProvider): void {\n if (registry.has(descriptor.id)) {\n throw new Error(`Context provider already registered: \"${descriptor.id}\"`);\n }\n\n registry.set(descriptor.id, descriptor);\n}\n\nexport function getContextProvider(id: string): ContextProvider | undefined {\n return registry.get(id);\n}\n\nexport function listContextProviders(): ContextProvider[] {\n return Array.from(registry.values());\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function clearContextProviders(): void {\n registry.clear();\n}\n","/**\n * PHASE 2 STUB — Provider Backends Registry\n *\n * This seam exists before the runtime uses it so provider registration can\n * move through one internal path instead of hardcoding Claude first and\n * refactoring later. Example future use: register an OpenAI backend alongside Claude.\n */\nexport interface ProviderBackendDescriptor {\n id: string;\n name: string;\n description: string;\n}\n\nconst registry = new Map<string, ProviderBackendDescriptor>();\n\nexport function registerProviderBackend(descriptor: ProviderBackendDescriptor): void {\n if (registry.has(descriptor.id)) {\n throw new Error(`Provider backend already registered: \"${descriptor.id}\"`);\n }\n\n registry.set(descriptor.id, descriptor);\n}\n\nexport function getProviderBackend(id: string): ProviderBackendDescriptor | undefined {\n return registry.get(id);\n}\n\nexport function listProviderBackends(): ProviderBackendDescriptor[] {\n return Array.from(registry.values());\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function clearProviderBackends(): void {\n registry.clear();\n}\n","/**\n * PHASE 2 STUB — Shell Adapters Registry\n *\n * This seam exists before additional shells ship so every built-in and future\n * adapter can register through the same path. Example future use: add a bash adapter\n * without rewriting the surrounding pipeline or bootstrap code.\n */\nexport interface ShellAdapterDescriptor {\n id: string;\n shell: string;\n description: string;\n}\n\nconst registry = new Map<string, ShellAdapterDescriptor>();\n\nexport function registerShellAdapter(descriptor: ShellAdapterDescriptor): void {\n if (registry.has(descriptor.id)) {\n throw new Error(`Shell adapter already registered: \"${descriptor.id}\"`);\n }\n\n registry.set(descriptor.id, descriptor);\n}\n\nexport function getShellAdapter(id: string): ShellAdapterDescriptor | undefined {\n return registry.get(id);\n}\n\nexport function listShellAdapters(): ShellAdapterDescriptor[] {\n return Array.from(registry.values());\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function clearShellAdapters(): void {\n registry.clear();\n}\n","/**\n * PHASE 2 STUB — Storage Hooks Registry\n *\n * This seam exists before persistence lands so storage behavior can grow behind\n * a registry instead of direct call-site wiring. Example future use: register a\n * SQLite-backed session history hook without changing client flow code.\n */\nexport interface StorageHookDescriptor {\n id: string;\n description: string;\n}\n\nconst registry = new Map<string, StorageHookDescriptor>();\n\nexport function registerStorageHook(descriptor: StorageHookDescriptor): void {\n if (registry.has(descriptor.id)) {\n throw new Error(`Storage hook already registered: \"${descriptor.id}\"`);\n }\n\n registry.set(descriptor.id, descriptor);\n}\n\nexport function getStorageHook(id: string): StorageHookDescriptor | undefined {\n return registry.get(id);\n}\n\nexport function listStorageHooks(): StorageHookDescriptor[] {\n return Array.from(registry.values());\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function clearStorageHooks(): void {\n registry.clear();\n}\n","import { filesystemContextProvider } from '../context/providers/filesystem-context.js';\nimport { gitContextProvider } from '../context/providers/git-context.js';\nimport { registerContextProvider } from './context-providers.js';\nimport { registerProviderBackend } from './provider-backends.js';\nimport { registerShellAdapter } from './shell-adapters.js';\nimport { registerStorageHook } from './storage-hooks.js';\n\nlet bootstrapped = false;\n\n/**\n * Registers all Phase 2 built-ins into their respective registries.\n *\n * This is the single source of truth for what built-ins exist in Phase 2.\n * Callers should invoke it at startup; repeated calls are safe no-ops.\n */\nexport function bootstrapBuiltins(): void {\n if (bootstrapped) {\n return;\n }\n\n bootstrapped = true;\n\n registerContextProvider(gitContextProvider);\n registerContextProvider(filesystemContextProvider);\n\n registerShellAdapter({\n id: 'zsh',\n shell: 'zsh',\n description: 'zsh ZLE widget adapter (Phase 2 built-in)',\n });\n\n registerStorageHook({\n id: 'noop',\n description: 'No-op storage hook (default — no persistence)',\n });\n registerStorageHook({\n id: 'memory',\n description: 'In-memory storage hook (test and ephemeral use)',\n });\n\n registerProviderBackend({\n id: 'claude',\n name: 'Claude (Anthropic)',\n description: 'Anthropic Claude adapter — default LLM backend',\n });\n}\n\n/**\n * @internal\n * For test isolation only — do not call in production code.\n */\nexport function resetBootstrap(): void {\n bootstrapped = false;\n}\n","import * as fsp from 'node:fs/promises';\nimport * as tty from 'node:tty';\nimport { render } from 'ink';\nimport React from 'react';\nimport { gatherContext } from '../context/pipeline.js';\nimport type { NormalizedRequest } from '../contracts/request.js';\nimport { shellRequestSchema } from '../contracts/shell.js';\nimport { ensureDaemon } from '../daemon/bootstrap.js';\nimport { classifyIntent } from '../intent/router.js';\nimport { fetchCandidates } from '../providers/claude.js';\nimport { detectProvider } from '../providers/detect.js';\nimport { appendDebugLog } from '../shared/debug-log.js';\nimport { socketPathForUid } from '../shared/socket-path.js';\nimport { CandidateSelect } from '../ui/CandidateSelect.js';\nimport { writeShellResult } from './result-writer.js';\n\n/**\n * Splits a command + explanation into shell buffer halves.\n *\n * Cursor lands before the first placeholder (text wrapped in `<...>`), so the\n * user can immediately type the first required value. Angle brackets are\n * stripped from all placeholders so the shell buffer looks natural.\n * If no placeholders are present, cursor lands after the command, before the\n * ` # explanation` comment.\n */\nexport function buildShellBuffers(\n command: string,\n explanation: string,\n): { lbuffer: string; rbuffer: string } {\n const comment = ` # ${explanation}`;\n const stripped = command.replace(/<([^>]+)>/g, '$1');\n const firstAngle = command.indexOf('<');\n if (firstAngle >= 0) {\n return {\n lbuffer: stripped.slice(0, firstAngle),\n rbuffer: stripped.slice(firstAngle) + comment,\n };\n }\n return { lbuffer: command, rbuffer: comment };\n}\n\nexport interface ForegroundClientArgs {\n requestFile: string;\n resultFile: string;\n /**\n * Selects the deterministic result mode for this Phase 1 seam:\n *\n * cancel — write {kind:'cancel'} immediately (Esc simulation)\n * replace-buffer-fixture — write a deterministic {kind:'replace-buffer'} result\n * derived from the shell request so the zsh bridge can\n * round-trip an accepted selection end-to-end without\n * the Phase 4 TUI being built yet.\n * llm — call Claude and map its JSON response to shell output\n */\n resultMode: 'cancel' | 'replace-buffer-fixture' | 'llm';\n}\n\n/**\n * Runs the foreground client loop.\n *\n * 1. Opens /dev/tty for interactive stdio (does not assume inherited stdio is a TTY).\n * 2. Reads and validates the shell request file.\n * 3. Ensures the background daemon is running.\n * 4. Emits a deterministic shell result based on `resultMode`.\n *\n * Phase 4 will replace step 4 with a real Ink TUI loop — the shell contract\n * and daemon bootstrap seam are established here without any UI framework imports.\n */\nexport async function runForegroundClient(args: ForegroundClientArgs): Promise<void> {\n const { requestFile, resultFile, resultMode } = args;\n const uid = typeof process.getuid === 'function' ? process.getuid() : 0;\n const socketPath = socketPathForUid(uid);\n\n const inZellij = process.env.ZELLIJ !== undefined;\n\n void appendDebugLog('client', 'foreground start', {\n requestFile,\n resultFile,\n resultMode,\n socketPath,\n inZellij,\n });\n\n // Always open /dev/tty for interactive stdio.\n // Outside Zellij: ZLE redirects process.stdin from /dev/null, so /dev/tty is required.\n // Inside Zellij (zellij run): process.stdin is not wired to the pane PTY by zellij run,\n // but /dev/tty always refers to the controlling terminal which IS the pane PTY.\n const ttyHandle = await fsp.open('/dev/tty', 'r+').catch(() => null);\n\n try {\n // Read and validate the shell request\n const raw = await fsp.readFile(requestFile, 'utf-8');\n const request = shellRequestSchema.parse(JSON.parse(raw.trim()));\n\n void appendDebugLog('client', 'request parsed', request);\n\n const detectedProvider = await detectProvider();\n void appendDebugLog('client', 'provider detected', { kind: detectedProvider.kind });\n\n // Ensure the daemon is reachable before we do anything interactive\n await ensureDaemon(socketPath);\n void appendDebugLog('client', 'daemon ensured', { socketPath });\n\n // Deterministic result seam — Phase 4 replaces this with the Ink TUI\n if (resultMode === 'replace-buffer-fixture') {\n // Derive a fixture from the request so the result is deterministic and\n // exercise the full zsh bridge round-trip without needing user input.\n const fixtureLbuffer = request.lbuffer || 'echo hello';\n await writeShellResult(resultFile, {\n kind: 'replace-buffer',\n lbuffer: fixtureLbuffer,\n rbuffer: request.rbuffer,\n });\n void appendDebugLog('client', 'wrote replace-buffer result', {\n resultFile,\n lbuffer: fixtureLbuffer,\n rbuffer: request.rbuffer,\n });\n } else if (resultMode === 'llm') {\n try {\n const decision = classifyIntent({ ...request, intent: 'unknown' as const, confidence: 0 });\n void appendDebugLog('client', 'intent classified', {\n intent: decision.intent,\n signals: decision.signals,\n });\n\n const normalized: NormalizedRequest = {\n ...request,\n intent: decision.intent,\n confidence: decision.confidence,\n };\n const envelope = await gatherContext(normalized);\n void appendDebugLog('client', 'context gathered', {\n extraCount: envelope.extras.length,\n });\n\n // D-07: Open modal before fetchCandidates resolves — spinner shows immediately.\n // D-03: No single-candidate fast-accept bypass — all paths go through the modal.\n // D-05: No raw ANSI loading indicator — spinner is inside the Ink component.\n\n // Try to create TTY streams from /dev/tty for Ink.\n // This works in all contexts (ZSH widget, zellij run pane, plain terminal).\n // Falls back to process.stdin/stdout if /dev/tty was unavailable (e.g. tests).\n let ttyReadStream: tty.ReadStream | undefined;\n let ttyWriteStream: tty.WriteStream | undefined;\n if (ttyHandle) {\n try {\n ttyReadStream = new tty.ReadStream(ttyHandle.fd);\n ttyWriteStream = new tty.WriteStream(ttyHandle.fd);\n } catch {\n // Synthetic fd (e.g. tests) — Ink will use process.stdin/stdout\n }\n }\n\n // Reserve exactly as many lines as the TUI needs (header + filter + up to 3\n // candidates × 3 rows + controls + 2 buffer = 16). This scrolls previous\n // terminal content up by only 16 lines so it stays visible above the TUI,\n // rather than filling the whole screen.\n // Skipped in Zellij: the floating pane starts with a clean screen.\n const MODAL_VIEWPORT_LINES = 16;\n if (ttyWriteStream && !inZellij) {\n ttyWriteStream.write('\\n'.repeat(MODAL_VIEWPORT_LINES));\n ttyWriteStream.write(`\\x1b[${MODAL_VIEWPORT_LINES}A`);\n // Save cursor at the top of the reserved area. Restored in clearScrollReserve\n // so cleanup always erases from the right position regardless of where Ink\n // leaves the cursor after unmount.\n ttyWriteStream.write('\\x1b7');\n }\n\n await new Promise<void>((resolve) => {\n let unmount: (() => void) | undefined;\n let resolved = false;\n\n // Build initial element with null candidates (D-06 loading state)\n const buildCandidateElement = (\n candidates: Parameters<typeof CandidateSelect>[0]['candidates'],\n errorState?: boolean,\n ) =>\n React.createElement(CandidateSelect, {\n candidates,\n initialQuery: request.lbuffer,\n error: errorState,\n onSelect: async (command: string, explanation: string) => {\n if (resolved) return;\n resolved = true;\n const { lbuffer, rbuffer } = buildShellBuffers(command, explanation);\n await writeShellResult(resultFile, {\n kind: 'replace-buffer',\n lbuffer,\n rbuffer,\n query: request.lbuffer,\n });\n unmount?.();\n },\n onCancel: async () => {\n if (resolved) return;\n resolved = true;\n await writeShellResult(resultFile, { kind: 'cancel' });\n unmount?.();\n },\n });\n\n // Force interactive:true so Ink uses cursor-repositioning mode regardless of\n // CI env vars (is-in-ci checks process.env.CI which many devtools set) and\n // regardless of whether isTTY is correctly reported on a manually-constructed\n // tty.WriteStream. We already confirmed /dev/tty opens, so it is a real terminal.\n const renderOptions =\n ttyReadStream && ttyWriteStream\n ? { stdin: ttyReadStream, stdout: ttyWriteStream, interactive: true }\n : { interactive: true };\n\n const app = render(buildCandidateElement(null), renderOptions);\n\n // Restore cursor to the saved position (top of reserved area) then clear\n // to end of screen. This works regardless of where Ink left the cursor.\n const clearScrollReserve = () => {\n if (ttyWriteStream && !inZellij) {\n try {\n ttyWriteStream.write('\\x1b8\\x1b[J');\n } catch {\n // TTY may already be gone (e.g. SIGHUP fired because terminal closed)\n }\n }\n };\n\n const cleanupOnSignal = () => {\n app.unmount();\n clearScrollReserve();\n process.exit(0);\n };\n process.once('SIGHUP', cleanupOnSignal);\n process.once('SIGTERM', cleanupOnSignal);\n\n unmount = () => {\n process.off('SIGHUP', cleanupOnSignal);\n process.off('SIGTERM', cleanupOnSignal);\n app.unmount();\n clearScrollReserve();\n resolve();\n };\n\n // D-07: fetch candidates concurrently — rerender() pushes them into the live modal.\n fetchCandidates(envelope, request.rbuffer)\n .then((candidates) => {\n void appendDebugLog('client', 'candidates received', { count: candidates.length });\n app.rerender(buildCandidateElement(candidates));\n })\n .catch(async (err) => {\n const message = err instanceof Error ? err.message : String(err);\n void appendDebugLog('client', 'llm request failed', { message });\n if (resolved) return;\n resolved = true;\n try {\n await writeShellResult(resultFile, {\n kind: 'error',\n message: `QueQue: ${message} — press any key`,\n });\n } finally {\n unmount?.();\n }\n });\n });\n\n void appendDebugLog('client', 'wrote llm result', { resultFile });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n void appendDebugLog('client', 'llm request failed', {\n message,\n });\n await writeShellResult(resultFile, {\n kind: 'error',\n message: `QueQue: ${message} — press any key`,\n });\n }\n } else {\n await writeShellResult(resultFile, { kind: 'cancel' });\n void appendDebugLog('client', 'wrote cancel result', { resultFile });\n }\n } finally {\n await ttyHandle?.close();\n }\n}\n","import { z } from 'zod';\nimport { shellRequestSchema } from './shell.js';\n\n/**\n * Broad intent categories classified before any context gathering.\n * Kept intentionally coarse for MVP — see RESEARCH.md for rationale.\n *\n * Taxonomy contract (enforced by classifyIntent in src/intent/router.ts):\n * 'shell-command' — query looks like a shell command or git invocation\n * 'codebase' — query has an explicit file-path signal or is a pkg-manager script (D-01, D-02)\n * 'filesystem' — query describes a file system operation (rename, move, find)\n * 'general' — non-empty query with no strong signal (lowest-confidence fallback)\n * 'unknown' — ONLY for the empty-string query; no other input should produce this value\n */\nexport const requestIntentSchema = z.enum([\n 'shell-command',\n 'codebase',\n 'filesystem',\n 'general',\n 'unknown',\n]);\n\nexport type RequestIntent = z.infer<typeof requestIntentSchema>;\n\n/**\n * Normalized internal request — shell transport plus inferred intent.\n * Consumers downstream of the shell bridge work with this type, not ShellRequest.\n */\nexport const normalizedRequestSchema = shellRequestSchema.extend({\n intent: requestIntentSchema,\n confidence: z.number().min(0).max(1),\n});\n\nexport type NormalizedRequest = z.infer<typeof normalizedRequestSchema>;\n\n/**\n * Always-present base context derived from the normalized request and\n * process globals. Never requires I/O.\n */\nexport const baseContextSchema = z.object({\n queryText: z.string(),\n cwd: z.string(),\n ttyPath: z.string(),\n shellPid: z.number().int().positive(),\n /** Hardcoded 'zsh' for Phase 2 — cross-shell support is v2 scope. */\n shellName: z.literal('zsh'),\n platform: z.string(),\n timestamp: z.string(),\n});\n\nexport type BaseContext = z.infer<typeof baseContextSchema>;\n\n/**\n * Result of the intent classifier. Includes signals for debugging\n * why a request was routed to a particular intent.\n */\nexport const intentDecisionSchema = z.object({\n intent: requestIntentSchema,\n confidence: z.number().min(0).max(1),\n signals: z.array(z.string()),\n});\n\nexport type IntentDecision = z.infer<typeof intentDecisionSchema>;\n\n/**\n * A typed chunk of extra context gathered by an intent-gated provider.\n * Discriminated on `kind` so consumers can narrow safely.\n *\n * D-05/D-06 structural enforcement: neither variant has any field for file\n * content (bytes, text, lines). File names only. A future provider that needs\n * to include file content MUST add a new `kind` variant and will require an\n * explicit privacy review — it cannot sneak content in through the existing variants.\n */\nexport const contextChunkSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('git'),\n payload: z.object({\n cwd: z.string(),\n root: z.string(),\n branch: z.string().nullable(),\n dirty: z.boolean(),\n /** File paths only (from git status --porcelain). No diff content, no file bytes. */\n changedFiles: z.array(z.string()),\n }),\n }),\n z.object({\n kind: z.literal('filesystem'),\n payload: z.object({\n cwd: z.string(),\n /** Apparent filename extracted from query text. No file bytes read. */\n apparentFilename: z.string().nullable(),\n }),\n }),\n]);\n\nexport type ContextChunk = z.infer<typeof contextChunkSchema>;\n\n/**\n * Fully assembled context passed to the provider adapter.\n * base is always populated; extras contains only intent-relevant chunks.\n */\nexport const contextEnvelopeSchema = z.object({\n base: baseContextSchema,\n extras: z.array(contextChunkSchema),\n});\n\nexport type ContextEnvelope = z.infer<typeof contextEnvelopeSchema>;\n","import { z } from 'zod';\n\n/**\n * Shell request — sent from the zsh widget to the qq client.\n * Carries the raw ZLE buffer state using split-buffer fields to avoid\n * cross-runtime cursor index math between Node and zsh.\n */\nexport const shellRequestSchema = z.object({\n version: z.literal(1),\n ttyPath: z.string(),\n cwd: z.string().regex(/^\\/[^\\0]*$/, 'cwd must be an absolute POSIX path'),\n shellPid: z.number().int().positive(),\n lbuffer: z.string(),\n rbuffer: z.string(),\n});\n\nexport type ShellRequest = z.infer<typeof shellRequestSchema>;\n\n/**\n * Shell result — written by the qq client so the zsh widget can apply it.\n *\n * Three variants:\n * cancel — leave LBUFFER/RBUFFER untouched (Esc or dismiss)\n * replace-buffer — overwrite LBUFFER and RBUFFER with the chosen command\n * error — provider or client error; message shown to user, buffers restored\n *\n * The deprecated {buffer, cursor} shape is intentionally excluded.\n * Numeric cursor offsets create Unicode index mismatches between Node (UTF-16)\n * and zsh (character-oriented).\n */\nexport const shellResultSchema = z.discriminatedUnion('kind', [\n z\n .object({\n kind: z.literal('cancel'),\n })\n .strict(),\n z.object({\n kind: z.literal('replace-buffer'),\n lbuffer: z.string(),\n rbuffer: z.string(),\n query: z.string().optional(),\n }),\n z.object({\n kind: z.literal('error'),\n message: z.string(),\n }),\n]);\n\nexport type ShellResult = z.infer<typeof shellResultSchema>;\n","import {\n type IntentDecision,\n type NormalizedRequest,\n requestIntentSchema,\n} from '../contracts/request.js';\n\n/**\n * D-03: git prefix — query (after trim) begins with 'git ' (literal).\n *\n * Scope notes (Phase 2):\n * - Leading whitespace: the ZLE widget strips leading whitespace from the buffer\n * before the '??' trigger is sent, so `query.trim()` handles any remaining edge.\n * - 'command git status' patterns: out of Phase 2 scope. These are forwarded as\n * shell-command via SHELL_COMMAND_RE below, without the git-prefix signal.\n * The git-prefix signal is used by the git context provider (D-09) to include\n * git context for `git *` subcommand queries.\n */\nconst GIT_PREFIX_RE = /^git\\s/;\n\n/**\n * D-02: package manager script prefixes that always qualify as codebase intent.\n * Matches only at the start of the query to distinguish literal invocations\n * (\"pnpm build\") from natural language (\"how to run pnpm build\").\n */\nconst PKG_MANAGER_RE =\n /^(npm|pnpm|yarn)\\s+(test|build|lint|run|start|dev|check|format|typecheck)\\b/i;\n\n/**\n * Filesystem operation keywords routed before generic file-path detection.\n * This keeps prompts like \"rename hero.png to hero-banner.png\" in filesystem\n * even though the query also contains file-looking tokens.\n */\nconst FILESYSTEM_KEYWORDS_RE =\n /\\b(?:rename|move(?:\\s+file)?|find\\s+files?|copy|delete|list\\s+files?|image|folder|directory)\\b/i;\n\n/**\n * Shell command signals: well-known command prefixes and pipe operator.\n * Checked BEFORE file-path signal so \"ls ./foo.txt\" routes as shell-command, not codebase.\n */\nconst SHELL_COMMAND_RE =\n /^(ls|echo|grep|awk|sed|curl|wget|ssh|cat|head|tail|cd|pwd|mkdir|touch|chmod|cp|mv|rm|which|man|ps|kill|sudo|command)\\s|\\|/;\n\n/**\n * D-01: file path signal detection.\n * Matches: path separators (/), relative paths (./), tilde paths (~/),\n * dotfiles (.env, .zshrc), and bare extensions (utils.py, index.html).\n */\nconst FILE_PATH_RE =\n /(?:\\/|\\.\\/|~\\/|\\.[a-zA-Z][\\w-]*(?:\\.\\w+)?(?=\\s|$)|\\b[\\w-]+\\.(?:ts|tsx|js|jsx|mjs|cjs|py|go|rs|rb|java|sh|md|json|yaml|yml|toml|env|html|css|scss|txt|xml|svg|png|jpg|jpeg|gif|pdf|zip|tar|gz|lock|config)(?:\\b|$))/;\n\nexport function classifyIntent(request: NormalizedRequest): IntentDecision {\n const query = request.lbuffer.trim();\n\n // Empty query (including whitespace-only) → unknown (the ONLY path to this value)\n if (query.length === 0) {\n return {\n intent: requestIntentSchema.enum.unknown,\n confidence: 1,\n signals: ['empty-query'],\n };\n }\n\n if (GIT_PREFIX_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum['shell-command'],\n confidence: 1,\n signals: ['git-prefix'],\n };\n }\n\n if (PKG_MANAGER_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum.codebase,\n confidence: 1,\n signals: ['pkg-manager-script'],\n };\n }\n\n if (FILESYSTEM_KEYWORDS_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum.filesystem,\n confidence: 0.85,\n signals: ['filesystem-keyword'],\n };\n }\n\n if (SHELL_COMMAND_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum['shell-command'],\n confidence: 0.8,\n signals: ['shell-command-signal'],\n };\n }\n\n if (FILE_PATH_RE.test(query)) {\n return {\n intent: requestIntentSchema.enum.codebase,\n confidence: 0.9,\n signals: ['file-path-signal'],\n };\n }\n\n return {\n intent: requestIntentSchema.enum.general,\n confidence: 0.5,\n signals: ['no-strong-signal'],\n };\n}\n","import type { BaseContext, NormalizedRequest } from '../contracts/request.js';\n\n/**\n * Derives the always-present base context from the normalized request and\n * process globals. Synchronous — requires no I/O.\n */\nexport function buildBaseContext(request: NormalizedRequest): BaseContext {\n return {\n queryText: request.lbuffer.trim(),\n cwd: request.cwd,\n ttyPath: request.ttyPath,\n shellPid: request.shellPid,\n shellName: 'zsh',\n platform: process.platform,\n timestamp: new Date().toISOString(),\n };\n}\n","import type { ContextEnvelope, NormalizedRequest } from '../contracts/request.js';\nimport { classifyIntent } from '../intent/router.js';\nimport { listContextProviders } from '../registry/context-providers.js';\nimport { appendDebugLog } from '../shared/debug-log.js';\nimport { buildBaseContext } from './base-context.js';\n\nexport async function gatherContext(request: NormalizedRequest): Promise<ContextEnvelope> {\n void appendDebugLog('context', 'pipeline start', {\n lbuffer: request.lbuffer,\n intent: request.intent,\n });\n\n const base = buildBaseContext(request);\n const decision = classifyIntent(request);\n\n void appendDebugLog('context', 'intent decision', {\n intent: decision.intent,\n signals: decision.signals,\n });\n\n const extras: ContextEnvelope['extras'] = [];\n const providers = listContextProviders();\n\n for (const provider of providers) {\n const supportsAllIntents = provider.intents.includes('*');\n const supportsIntent = provider.intents.includes(decision.intent);\n\n if (!supportsAllIntents && !supportsIntent) {\n continue;\n }\n\n try {\n const chunk = await provider.gather({ base, decision });\n if (chunk !== null) {\n extras.push(chunk);\n void appendDebugLog('context', 'provider chunk gathered', {\n providerId: provider.id,\n kind: chunk.kind,\n });\n }\n } catch (error) {\n void appendDebugLog('context', 'provider error', {\n providerId: provider.id,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n const envelope: ContextEnvelope = { base, extras };\n\n void appendDebugLog('context', 'envelope assembled', { extraCount: extras.length });\n\n return envelope;\n}\n","import { spawn } from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as net from 'node:net';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { appendDebugLog } from '../shared/debug-log.js';\n\nconst CONNECT_TIMEOUT_MS = 500;\nconst POLL_INTERVAL_MS = 50;\nconst POLL_MAX_ATTEMPTS = 40; // 2 seconds total\n\n/**\n * Attempts to connect to the daemon socket at `socketPath`.\n * Resolves true if the connection succeeds, false on any error.\n */\nfunction tryConnect(socketPath: string): Promise<boolean> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n client.destroy();\n resolve(false);\n }, CONNECT_TIMEOUT_MS);\n\n const client = net.createConnection(socketPath, () => {\n clearTimeout(timer);\n client.destroy();\n resolve(true);\n });\n\n client.on('error', () => {\n clearTimeout(timer);\n resolve(false);\n });\n });\n}\n\n/**\n * Polls the socket path until the daemon becomes connectable or\n * the attempt limit is reached.\n */\nasync function waitForSocket(\n socketPath: string,\n maxAttempts = POLL_MAX_ATTEMPTS,\n): Promise<boolean> {\n for (let i = 0; i < maxAttempts; i++) {\n if (await tryConnect(socketPath)) return true;\n await new Promise<void>((res) => setTimeout(res, POLL_INTERVAL_MS));\n }\n\n return false;\n}\n\n/**\n * Validates that `socketPath` is a safe daemon socket path.\n *\n * Rejects any path that does not resolve to /tmp/qq-*.sock to prevent\n * path-traversal attacks where a caller-controlled path could cause\n * fs.unlinkSync to delete arbitrary files or the daemon to listen on\n * an attacker-chosen location.\n */\nfunction assertSafeSocketPath(socketPath: string): void {\n const resolved = path.resolve(socketPath);\n const base = path.basename(resolved);\n const dir = path.dirname(resolved);\n const tmpRoots = ['/tmp', '/private/tmp'];\n if (!tmpRoots.includes(dir) || !base.startsWith('qq-') || !base.endsWith('.sock')) {\n throw new Error(`unsafe socket path rejected: ${socketPath}`);\n }\n}\n\n/**\n * Ensures a qq daemon is running at `socketPath`.\n *\n * Algorithm:\n * 1. Try to connect. If it succeeds, return immediately.\n * 2. If the socket file exists but the connect failed, unlink it (stale socket).\n * 3. Spawn `qq daemon --socket <path>` as a detached, unreferenced child.\n * 4. Poll until the new daemon starts listening, then return.\n *\n * Throws if the daemon does not start within the poll window.\n * Throws if `socketPath` is not a safe /tmp/qq-*.sock path.\n */\nexport async function ensureDaemon(socketPath: string): Promise<void> {\n assertSafeSocketPath(socketPath);\n void appendDebugLog('daemon', 'ensure start', { socketPath });\n\n // Fast path: daemon is already running\n if (await tryConnect(socketPath)) {\n void appendDebugLog('daemon', 'already running', { socketPath });\n return;\n }\n\n // Unlink stale socket file if present.\n //\n // TOCTOU note: there is a narrow window between the failed tryConnect above\n // and this unlink where a concurrent ensureDaemon call (e.g. from a second\n // terminal tab) may have already started a fresh daemon and be listening on\n // the socket. Unlinking here would destroy that live socket. This is\n // acceptable for the MVP (single active session assumed) but will need a\n // file-based lock (O_EXCL) before multi-window use is supported.\n try {\n fs.unlinkSync(socketPath);\n } catch {\n // File may not exist — that is fine\n }\n\n // Resolve the current bundled CLI entrypoint.\n // In the built runtime, import.meta.url points at dist/cli/main.js, which is\n // the exact script we want the detached daemon process to execute.\n const qqBin = process.execPath; // Node executable\n const qqScript = fileURLToPath(import.meta.url);\n\n if (!fs.existsSync(qqScript)) {\n void appendDebugLog('daemon', 'script missing', { qqScript });\n throw new Error(`qq daemon script not found at: ${qqScript}. Run 'pnpm build' first.`);\n }\n\n void appendDebugLog('daemon', 'spawning daemon', { qqScript, socketPath });\n const child = spawn(qqBin, [qqScript, 'daemon', '--socket', socketPath], {\n detached: true,\n stdio: 'ignore',\n });\n\n // Detach so the foreground client can exit without killing the daemon\n child.unref();\n\n const started = await waitForSocket(socketPath);\n if (!started) {\n void appendDebugLog('daemon', 'startup timeout', { socketPath });\n throw new Error(`qq daemon did not start within the expected window (${socketPath})`);\n }\n\n void appendDebugLog('daemon', 'daemon ready', { socketPath });\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport { type CandidateList, candidateListSchema } from '../contracts/candidates.js';\nimport type { ContextEnvelope } from '../contracts/request.js';\nimport { appendDebugLog } from '../shared/debug-log.js';\nimport { readEnvValueFromDotEnvLocal } from '../shared/env-file.js';\nimport type { LLMAdapter } from './provider.js';\n\nconst DEFAULT_MODEL = 'claude-haiku-4-5-20251001';\n\nfunction resolveModel(): string {\n return process.env.QQ_MODEL ?? readEnvValueFromDotEnvLocal('QQ_MODEL') ?? DEFAULT_MODEL;\n}\n\nfunction extractText(content: Array<{ type: string; text?: string }>): string {\n return content\n .filter((block) => block.type === 'text' && typeof block.text === 'string')\n .map((block) => block.text ?? '')\n .join('')\n .trim();\n}\n\nfunction stripCodeFence(raw: string): string {\n const m = raw.trim().match(/^```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?```\\s*$/);\n return m ? m[1].trim() : raw.trim();\n}\n\nfunction parseCandidates(text: string): CandidateList {\n let parsed: unknown;\n try {\n parsed = JSON.parse(stripCodeFence(text));\n } catch {\n // Not JSON at all — treat entire text as a plain command (prose fallback)\n const trimmed = text.trim();\n return [{ command: trimmed || 'echo \"\"', explanation: '' }];\n }\n // Valid JSON but wrong schema — do not use raw JSON text as a command\n try {\n return candidateListSchema.parse(parsed);\n } catch {\n return [{ command: 'echo \"\"', explanation: 'QueQue: unexpected response format' }];\n }\n}\n\nfunction shouldForceSelector(): boolean {\n const configured =\n process.env.QQ_FORCE_SELECTOR ?? readEnvValueFromDotEnvLocal('QQ_FORCE_SELECTOR');\n return configured === '1' || configured === 'true';\n}\n\nfunction ensureSelectableCandidates(candidates: CandidateList): CandidateList {\n if (!shouldForceSelector() || candidates.length >= 2) {\n return candidates;\n }\n\n const [first] = candidates;\n\n return [\n first,\n {\n command: first.command,\n explanation:\n first.explanation.length > 0\n ? `${first.explanation} (forced duplicate for selector testing)`\n : 'Forced duplicate for selector testing.',\n },\n ];\n}\n\nfunction buildPrompt(envelope: ContextEnvelope): string {\n const gitChunk = envelope.extras.find((chunk) => chunk.kind === 'git');\n\n return [\n 'Return ONLY a JSON array of 1-3 shell command candidates, most likely first.',\n 'Each item must have exactly these keys: \"command\" and \"explanation\".',\n 'No markdown, no prose, no code fences. Raw JSON array only.',\n '',\n 'The command should be safe to place back into a shell buffer.',\n '',\n 'Shell context:',\n JSON.stringify(\n {\n cwd: envelope.base.cwd,\n queryText: envelope.base.queryText,\n platform: envelope.base.platform,\n shellName: envelope.base.shellName,\n ...(gitChunk ? { versionControl: gitChunk.payload } : {}),\n },\n null,\n 2,\n ),\n ].join('\\n');\n}\n\n/**\n * Calls Claude with the assembled context envelope and returns ranked command candidates.\n *\n * `rbuffer` remains a side parameter because it is shell transport state, not context.\n * The envelope describes the request intent and execution environment, while Phase 4's\n * TUI remains responsible for deciding how the raw shell buffers are rewritten.\n */\nexport async function fetchCandidates(\n envelope: ContextEnvelope,\n rbuffer: string = '',\n): Promise<CandidateList> {\n const apiKey = process.env.ANTHROPIC_API_KEY ?? readEnvValueFromDotEnvLocal('ANTHROPIC_API_KEY');\n if (!apiKey) {\n throw new Error('ANTHROPIC_API_KEY is required in the environment or .env.local');\n }\n\n const client = new Anthropic({ apiKey });\n const prompt = buildPrompt(envelope);\n const model = resolveModel();\n\n void appendDebugLog('provider', 'request start', {\n model,\n cwd: envelope.base.cwd,\n rbufferLength: rbuffer.length,\n extras: envelope.extras.map((chunk) => chunk.kind),\n });\n\n try {\n const response = await client.messages.create(\n {\n model,\n max_tokens: 1024,\n temperature: 0,\n system:\n 'You are QueQue, a terminal shell assistant. Return ONLY a JSON array of command candidates, ranked with the most correct/direct command first. No prose, no markdown, no code fences. When a command requires a value the user must supply (hostname, filename, branch name, etc.), wrap it in angle brackets: <placeholder>. Use descriptive names like <user@host>, <filename>, <branch-name>. Do not use angle brackets for optional flags or known values.',\n messages: [{ role: 'user', content: prompt }],\n },\n {\n timeout: 25_000, // 25s — slightly under the zsh 30s FIFO timeout\n },\n );\n\n const text = extractText(response.content);\n const candidates = ensureSelectableCandidates(parseCandidates(text));\n\n void appendDebugLog('provider', 'response parsed', {\n model,\n candidateCount: candidates.length,\n forceSelector: shouldForceSelector(),\n });\n\n return candidates;\n } catch (error) {\n void appendDebugLog('provider', 'request failed', {\n model,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n}\n\nexport const claudeAdapter: LLMAdapter = {\n fetchCandidates,\n};\n","import { z } from 'zod';\n\nexport const commandCandidateSchema = z.object({\n command: z.string().min(1),\n explanation: z.string(),\n});\n\nexport type CommandCandidate = z.infer<typeof commandCandidateSchema>;\n\nexport const candidateListSchema = z.array(commandCandidateSchema).min(1).max(5);\n\nexport type CandidateList = z.infer<typeof candidateListSchema>;\n","import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nfunction findUp(startDir: string, filename: string): string | null {\n let current = startDir;\n\n while (true) {\n const candidate = join(current, filename);\n if (existsSync(candidate)) {\n return candidate;\n }\n\n const parent = dirname(current);\n if (parent === current) {\n return null;\n }\n\n current = parent;\n }\n}\n\nfunction parseEnvFile(content: string): Map<string, string> {\n const values = new Map<string, string>();\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith('#')) {\n continue;\n }\n\n const match = line.match(/^(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);\n if (!match) {\n continue;\n }\n\n const [, key, rawValue] = match;\n let value = rawValue.trim();\n\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n values.set(key, value);\n }\n\n return values;\n}\n\n// Module-level cache: keyed by \"key\\0startDir\" so different start directories\n// are cached independently. Null means the key was not found. Undefined means\n// the entry has not been populated yet (Map.get returns undefined for missing keys).\nconst envCache = new Map<string, string | null>();\n\nexport function readEnvValueFromDotEnvLocal(\n key: string,\n startDir = dirname(fileURLToPath(import.meta.url)),\n): string | null {\n const cacheKey = `${key}\\0${startDir}`;\n if (envCache.has(cacheKey)) {\n return envCache.get(cacheKey) ?? null;\n }\n\n const envPath = findUp(startDir, '.env.local');\n if (!envPath) {\n envCache.set(cacheKey, null);\n return null;\n }\n\n const values = parseEnvFile(readFileSync(envPath, 'utf8'));\n const result = values.get(key) ?? null;\n envCache.set(cacheKey, result);\n return result;\n}\n","import { execSync } from 'node:child_process';\nimport * as fsp from 'node:fs/promises';\nimport * as os from 'node:os';\n\nexport type DetectedProvider =\n | { kind: 'anthropic-key' }\n | { kind: 'claude-cli' }\n | { kind: 'ollama'; baseUrl: string }\n | { kind: 'openai-key' }\n | { kind: 'none' };\n\nfunction claudeOnPath(): boolean {\n try {\n execSync('which claude', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function claudeAuthFileExists(): Promise<boolean> {\n const home = os.homedir();\n const candidates = [`${home}/.claude/.credentials.json`, `${home}/.claude/credentials.json`];\n for (const p of candidates) {\n try {\n await fsp.stat(p);\n return true;\n } catch {\n // file not found — try next\n }\n }\n return false;\n}\n\nasync function ollamaHealthy(): Promise<boolean> {\n try {\n const res = await fetch('http://localhost:11434/api/tags', {\n signal: AbortSignal.timeout(300),\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n\nexport async function detectProvider(): Promise<DetectedProvider> {\n // Step 1 — Anthropic key env\n if (process.env.ANTHROPIC_API_KEY) {\n return { kind: 'anthropic-key' };\n }\n\n // Step 2 — Claude CLI: binary on PATH + auth file present\n if (claudeOnPath() && (await claudeAuthFileExists())) {\n return { kind: 'claude-cli' };\n }\n\n // Step 3 — Ollama health check\n if (await ollamaHealthy()) {\n return { kind: 'ollama', baseUrl: 'http://localhost:11434' };\n }\n\n // Step 4 — OpenAI key env\n if (process.env.OPENAI_API_KEY) {\n return { kind: 'openai-key' };\n }\n\n // Step 5 — nothing found\n return { kind: 'none' };\n}\n","/**\n * Returns the Unix socket path for the qq daemon for a given UID.\n *\n * Always uses /tmp to avoid the macOS TMPDIR path-length issue.\n * Node documents a 103-byte macOS limit on Unix socket paths, and\n * macOS TMPDIR paths are often too long (e.g. /var/folders/...).\n *\n * Example: socketPathForUid(501) === '/tmp/qq-501.sock'\n */\nexport function socketPathForUid(uid: number): string {\n return `/tmp/qq-${uid}.sock`;\n}\n\n/**\n * Returns the Unix socket path for the current process's UID.\n */\nexport function socketPath(): string {\n return socketPathForUid(process.getuid?.() ?? 0);\n}\n","import { Box, Text, useInput } from 'ink';\nimport { type ReactElement, useEffect, useState } from 'react';\nimport type { CandidateList } from '../contracts/candidates.js';\nimport { ControlsLine } from './ControlsLine.js';\nimport { LoadingSpinner } from './LoadingSpinner.js';\nimport { Modal } from './Modal.js';\nimport { SearchInput } from './SearchInput.js';\n\n/**\n * Props for CandidateSelect.\n *\n * D-06: candidates is nullable — null means loading state (spinner shown).\n */\ninterface Props {\n candidates: CandidateList | null;\n initialQuery?: string;\n onSelect: (command: string, explanation: string) => void;\n onCancel: () => void;\n error?: boolean;\n}\n\n/**\n * Filter candidates by case-insensitive substring match on command text.\n * Returns the full list unchanged when query is empty or falsy.\n */\nfunction filterCandidates(candidates: CandidateList, query: string): CandidateList {\n if (!query) return candidates;\n const lower = query.toLowerCase();\n return candidates.filter((c) => c.command.toLowerCase().includes(lower));\n}\n\n/**\n * Monocle-style candidate selector.\n *\n * Keys:\n * ↑ / ↓ — move selection (wraps)\n * Enter — accept selected command\n * Esc — cancel and restore shell buffer\n * Backspace — delete last char from live search query\n * Any printable char → live search (appended to query)\n */\nexport function CandidateSelect({\n candidates,\n initialQuery,\n onSelect,\n onCancel,\n error,\n}: Props): ReactElement {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [query, setQuery] = useState(initialQuery ?? '');\n\n // Reset selectedIndex when candidates arrive (Pitfall 2 fix).\n // Also clear initialQuery pre-filter if it produces zero matches — the lbuffer\n // was already used as context for Claude; filtering candidates by it too is\n // harmful when no command literally contains the lbuffer text.\n // biome-ignore lint/correctness/useExhaustiveDependencies: candidates is a prop; reset on arrival is intentional\n useEffect(() => {\n setSelectedIndex(0);\n if (candidates && candidates.length > 0 && filterCandidates(candidates, query).length === 0) {\n setQuery('');\n }\n }, [candidates]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: reset selectedIndex when query changes to prevent out-of-bounds access after filter narrows visible list\n useEffect(() => {\n setSelectedIndex(0);\n }, [query]);\n\n // Single useInput handler with null-guards (Pitfall 3 fix)\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n return;\n }\n\n if (key.backspace) {\n setQuery((q) => q.slice(0, -1));\n return;\n }\n\n // key.return must be checked before the generic input handler — in raw mode\n // Enter sends '\\r' as `input` (truthy), which would otherwise be consumed by\n // setQuery and prevent the accept action from firing.\n if (key.return && candidates) {\n const visible = filterCandidates(candidates, query);\n if (visible.length === 0) return;\n const selected = visible[selectedIndex] ?? visible[0]!;\n const explanation = selected.explanation || `see man ${selected.command.split(' ')[0]}`;\n onSelect(selected.command, explanation);\n return;\n }\n\n if (input && !key.ctrl && !key.meta) {\n setQuery((q) => q + input);\n return;\n }\n\n // Navigation: guard against null candidates\n if (key.upArrow && candidates) {\n const visible = filterCandidates(candidates, query);\n setSelectedIndex((i) => (i === 0 ? visible.length - 1 : i - 1));\n return;\n }\n\n if (key.downArrow && candidates) {\n const visible = filterCandidates(candidates, query);\n setSelectedIndex((i) => (i + 1) % visible.length);\n return;\n }\n });\n\n let content: ReactElement;\n if (error === true) {\n content = (\n <Box marginTop={1}>\n <Text dimColor>{'provider error — press esc to return'}</Text>\n </Box>\n );\n } else if (candidates === null) {\n content = (\n <Box marginTop={1}>\n <LoadingSpinner />\n </Box>\n );\n } else {\n const visible = filterCandidates(candidates, query);\n if (visible.length === 0) {\n content = (\n <Box marginTop={1}>\n <Text dimColor>{'no matches — try a different query'}</Text>\n </Box>\n );\n } else {\n content = (\n <Box flexDirection=\"column\" marginTop={1}>\n {visible.map((candidate, index) => {\n const active = index === selectedIndex;\n return (\n <Box key={candidate.command} flexDirection=\"column\" marginBottom={1}>\n <Box>\n {active ? <Text color=\"ansi256(166)\">{'┌> '}</Text> : <Text>{' '}</Text>}\n <Text bold={active} color={active ? 'white' : undefined} dimColor={!active}>\n {candidate.command}\n </Text>\n </Box>\n {candidate.explanation.length > 0 && (\n <Box>\n <Text>{' '}</Text>\n <Text dimColor>{candidate.explanation}</Text>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n }\n }\n\n return (\n <Modal>\n {initialQuery && initialQuery.length > 0 && (\n <Box>\n <Text dimColor>{`queque › ${initialQuery}`}</Text>\n </Box>\n )}\n <SearchInput query={query} />\n {content}\n <ControlsLine />\n </Modal>\n );\n}\n","import { Box, Text } from 'ink';\nimport type { ReactElement } from 'react';\n\nexport function ControlsLine(): ReactElement {\n return (\n <Box marginTop={1}>\n <Text backgroundColor=\"ansi256(238)\" color=\"white\" bold>\n {' ↑↓ '}\n </Text>\n <Text backgroundColor=\"ansi256(245)\" color=\"black\">\n {' select '}\n </Text>\n <Text dimColor>{' · '}</Text>\n <Text backgroundColor=\"ansi256(238)\" color=\"white\" bold>\n {' enter '}\n </Text>\n <Text backgroundColor=\"ansi256(245)\" color=\"black\">\n {' accept '}\n </Text>\n <Text dimColor>{' · '}</Text>\n <Text backgroundColor=\"ansi256(238)\" color=\"white\" bold>\n {' esc '}\n </Text>\n <Text backgroundColor=\"ansi256(245)\" color=\"black\">\n {' cancel '}\n </Text>\n </Box>\n );\n}\n","import { Text } from 'ink';\nimport { type ReactElement, useEffect, useState } from 'react';\n\nconst FRAMES = ['thinking…', 'thinking.', 'thinking..', 'thinking…'];\n\nexport function LoadingSpinner(): ReactElement {\n const [frame, setFrame] = useState(0);\n\n useEffect(() => {\n const id = setInterval(() => {\n setFrame((f) => (f + 1) % FRAMES.length);\n }, 200);\n return () => clearInterval(id);\n }, []);\n\n return <Text dimColor>{FRAMES[frame]}</Text>;\n}\n","import { Box } from 'ink';\nimport type { ReactElement, ReactNode } from 'react';\n\ninterface ModalProps {\n children: ReactNode;\n width?: number;\n}\n\nexport function Modal({ children, width = 80 }: ModalProps): ReactElement {\n return (\n <Box flexDirection=\"column\" paddingX={1} width={width}>\n {children}\n </Box>\n );\n}\n","import { Box, Text } from 'ink';\nimport type { ReactElement } from 'react';\n\ninterface SearchInputProps {\n query: string;\n}\n\nexport function SearchInput({ query }: SearchInputProps): ReactElement {\n return (\n <Box>\n <Text color=\"cyan\" bold>\n {'FILTER: '}\n </Text>\n {query ? <Text>{query}</Text> : <Text dimColor>{'type to filter…'}</Text>}\n </Box>\n );\n}\n","import * as fsp from 'node:fs/promises';\nimport { type ShellResult, shellResultSchema } from '../contracts/shell.js';\n\n/**\n * Validates a ShellResult and writes newline-terminated JSON to `resultFile`.\n *\n * Write strategy depends on the type of `resultFile`:\n *\n * - Named pipe (FIFO): writes directly via fsp.writeFile() because rename(2)\n * would replace the FIFO inode and break the waiting reader. Direct write\n * delivers data to the open reader immediately.\n *\n * - Regular file: atomic rename — the JSON is first written to a sibling\n * `.tmp` file and then renamed into place. On the same filesystem,\n * rename(2) is atomic, so the zsh bridge will never observe a partial write.\n * If the process is killed after the tmp write but before the rename, the\n * result file simply does not appear and the zsh bridge falls back to\n * cancel — no data corruption.\n *\n * Throws if the result does not conform to the ShellResult schema.\n */\nexport async function writeShellResult(resultFile: string, result: ShellResult): Promise<void> {\n // Validate the result shape — catch programming errors early\n const parsed = shellResultSchema.parse(result);\n\n const line = `${JSON.stringify(parsed)}\\n`;\n\n // Detect named pipe: rename(2) would replace the FIFO inode and break\n // the waiting zsh reader. Direct writeFile delivers data to the open reader.\n let isFifo = false;\n try {\n const st = await fsp.stat(resultFile);\n isFifo = st.isFIFO();\n } catch {\n // Path does not exist yet (regular file not created yet) — not a FIFO\n }\n\n if (isFifo) {\n // Named pipe: direct write — no atomic rename\n await fsp.writeFile(resultFile, line, { encoding: 'utf-8' });\n } else {\n // Regular file: atomic rename for zero-partial-write guarantee\n const tmpFile = `${resultFile}.tmp`;\n await fsp.writeFile(tmpFile, line, { encoding: 'utf-8' });\n await fsp.rename(tmpFile, resultFile);\n }\n}\n","import { runForegroundClient } from '../../client/run-foreground.js';\nimport { appendDebugLog } from '../../shared/debug-log.js';\n\nexport interface ClientCommandOptions {\n requestFile: string;\n resultFile: string;\n resultMode?: string;\n}\n\n/**\n * Real client command handler.\n *\n * `qq client --request-file <path> --result-file <path> [--result-mode <mode>]`\n *\n * Dispatches to the foreground client loop. The `--result-mode` flag selects\n * the deterministic Phase 1 seam:\n * cancel — emit a cancel result (default)\n * replace-buffer-fixture — emit a deterministic replace-buffer result\n *\n * Free of Ink and React imports — Phase 4 will wire the TUI inside\n * runForegroundClient without changing this handler.\n */\nconst VALID_MODES = ['cancel', 'replace-buffer-fixture', 'llm'] as const;\ntype ResultMode = (typeof VALID_MODES)[number];\n\nfunction parseResultMode(mode: string | undefined): ResultMode {\n if (mode === undefined || mode === 'llm') return 'llm';\n if (mode === 'cancel') return 'cancel';\n if (mode === 'replace-buffer-fixture') return 'replace-buffer-fixture';\n void appendDebugLog('client', `unknown --result-mode \"${mode}\", defaulting to cancel`);\n return 'cancel';\n}\n\nexport async function clientCommand(options: ClientCommandOptions): Promise<void> {\n const resultMode = parseResultMode(options.resultMode);\n\n void appendDebugLog('client', 'command start', {\n requestFile: options.requestFile,\n resultFile: options.resultFile,\n resultMode,\n });\n\n await runForegroundClient({\n requestFile: options.requestFile,\n resultFile: options.resultFile,\n resultMode,\n });\n}\n","import * as net from 'node:net';\nimport { ipcRequestSchema } from '../contracts/ipc.js';\nimport { appendDebugLog } from '../shared/debug-log.js';\n\n/**\n * Starts the daemon Unix-socket server.\n *\n * Handles newline-delimited JSON IPC messages. Supported requests:\n * {kind: 'ping'} → {kind: 'pong'}\n * {kind: 'ensure-session'} → {kind: 'session-ready', socketPath}\n * {kind: 'run-query'} → {kind: 'query-accepted', requestId}\n *\n * The server is intentionally free of Ink, React, and /dev/tty assumptions —\n * it runs fully in the background without a TTY.\n */\nexport function startDaemonServer(socketPath: string): Promise<net.Server> {\n return new Promise((resolve, reject) => {\n const MAX_BUF_BYTES = 64 * 1024; // 64 KB — generous for any realistic IPC message\n\n // TODO(CR-005): Add session token authentication before Phase 4 LLM integration.\n // Generate a random token in ensureDaemon, write it to a chmod-600 file in\n // /tmp/qq-<uid>/, and require clients to send it as the first IPC frame field.\n const server = net.createServer((socket) => {\n let buf = '';\n void appendDebugLog('daemon', 'socket connected', { socketPath });\n\n socket.on('data', (chunk) => {\n if (buf.length + chunk.length > MAX_BUF_BYTES) {\n socket.destroy(new Error('IPC message too large'));\n return;\n }\n buf += chunk.toString();\n let nl = buf.indexOf('\\n');\n\n while (nl !== -1) {\n const line = buf.slice(0, nl).trim();\n buf = buf.slice(nl + 1);\n nl = buf.indexOf('\\n');\n\n if (!line) continue;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n // Ignore malformed messages — keep connection alive\n continue;\n }\n\n const result = ipcRequestSchema.safeParse(parsed);\n if (!result.success) {\n // Unknown message kind — ignore silently\n void appendDebugLog('daemon', 'ignored unknown request', { line });\n continue;\n }\n\n const req = result.data;\n void appendDebugLog('daemon', 'request received', req);\n\n switch (req.kind) {\n case 'ping': {\n socket.write(`${JSON.stringify({ kind: 'pong' })}\\n`);\n void appendDebugLog('daemon', 'replied pong');\n break;\n }\n case 'ensure-session': {\n socket.write(`${JSON.stringify({ kind: 'session-ready', socketPath })}\\n`);\n void appendDebugLog('daemon', 'replied session-ready', { socketPath });\n break;\n }\n case 'run-query': {\n const requestId = Math.random().toString(36).slice(2);\n socket.write(`${JSON.stringify({ kind: 'query-accepted', requestId })}\\n`);\n void appendDebugLog('daemon', 'replied query-accepted', { requestId });\n break;\n }\n }\n }\n });\n\n socket.on('error', () => {\n // Connection errors are per-socket, not fatal to the server\n });\n });\n\n server.on('error', reject);\n\n server.listen(socketPath, () => {\n void appendDebugLog('daemon', 'listening', { socketPath });\n resolve(server);\n });\n });\n}\n","import { z } from 'zod';\nimport { shellRequestSchema } from './shell.js';\n\n/**\n * IPC request — sent from the foreground client to the daemon over a Unix socket.\n */\nexport const ipcRequestSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('ping'),\n }),\n z.object({\n kind: z.literal('ensure-session'),\n shellPid: z.number().int().positive(),\n ttyPath: z.string(),\n }),\n z.object({\n kind: z.literal('run-query'),\n request: shellRequestSchema,\n }),\n]);\n\nexport type IpcRequest = z.infer<typeof ipcRequestSchema>;\n\n/**\n * IPC response — returned by the daemon for each request kind.\n */\nexport const ipcResponseSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('pong'),\n }),\n z.object({\n kind: z.literal('session-ready'),\n socketPath: z.string(),\n }),\n z.object({\n kind: z.literal('query-accepted'),\n requestId: z.string(),\n }),\n]);\n\nexport type IpcResponse = z.infer<typeof ipcResponseSchema>;\n","import { ensureDaemon } from '../../daemon/bootstrap.js';\nimport { startDaemonServer } from '../../daemon/server.js';\nimport { appendDebugLog } from '../../shared/debug-log.js';\nimport { socketPath as defaultSocketPath } from '../../shared/socket-path.js';\n\nexport interface DaemonCommandOptions {\n socket?: string;\n ensure?: boolean;\n}\n\n/**\n * Real daemon command handler.\n *\n * `qq daemon --socket <path>` — starts the daemon server and blocks.\n * `qq daemon --socket <path> --ensure` — ensures a daemon is running, then exits.\n *\n * Free of Ink, React, and /dev/tty assumptions.\n */\nexport async function daemonCommand(options: DaemonCommandOptions): Promise<void> {\n const sock = options.socket ?? defaultSocketPath();\n void appendDebugLog('daemon', 'command start', { socket: sock, ensure: options.ensure });\n\n if (options.ensure) {\n await ensureDaemon(sock);\n void appendDebugLog('daemon', 'ensure command complete', { socket: sock });\n return;\n }\n\n // Start the server and block indefinitely\n const server = await startDaemonServer(sock);\n void appendDebugLog('daemon', 'server started', { socket: sock });\n\n // Graceful shutdown on SIGTERM / SIGINT\n const shutdown = () => {\n void appendDebugLog('daemon', 'shutdown', { socket: sock });\n server.close(() => {\n process.exit(0);\n });\n };\n\n process.once('SIGTERM', shutdown);\n process.once('SIGINT', shutdown);\n\n // Keep the process alive\n await new Promise<void>(() => {\n // Never resolves — daemon runs until signal\n });\n}\n","import { readFileSync } from 'fs';\nimport { dirname, resolve } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst SUPPORTED_SHELLS = ['zsh'] as const;\ntype Shell = (typeof SUPPORTED_SHELLS)[number];\n\nfunction shellScriptPath(shell: Shell): string {\n return resolve(__dirname, '../../shell', shell, `queque.${shell}`);\n}\n\nexport function initCommand(shell: string): void {\n if (!SUPPORTED_SHELLS.includes(shell as Shell)) {\n console.error(`Unsupported shell: '${shell}'. Supported: ${SUPPORTED_SHELLS.join(', ')}`);\n process.exit(1);\n }\n process.stdout.write(readFileSync(shellScriptPath(shell as Shell), 'utf8'));\n}\n"],"mappings":"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","names":["fs","execFile","promisify","execFileAsync","promisify","execFile","path","registry","registry","registry","fsp","z","z","socketPath","resolve","z","existsSync","dirname","fileURLToPath","fsp","Box","Text","useEffect","useState","Text","jsx","Box","jsx","Box","Text","jsx","jsxs","jsx","jsxs","useState","useEffect","Box","Text","fsp","socketPath","resolve","net","z","z","socketPath","resolve","readFileSync","dirname","resolve","fileURLToPath"]}
package/package.json CHANGED
@@ -3,10 +3,10 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.1.0",
6
+ "version": "0.2.0-beta.2",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/k-leumas/queque.git"
9
+ "url": "git+https://github.com/k-leumas/queque.git"
10
10
  },
11
11
  "files": [
12
12
  "dist",
@@ -39,7 +39,6 @@
39
39
  "zod": "4.1.5"
40
40
  },
41
41
  "devDependencies": {
42
- "@types/node": "24.10.1",
43
42
  "@biomejs/biome": "^2.2.4",
44
43
  "@commitlint/cli": "^20.1.0",
45
44
  "@commitlint/config-conventional": "^20.0.0",
@@ -47,13 +46,15 @@
47
46
  "@semantic-release/commit-analyzer": "^13.0.1",
48
47
  "@semantic-release/git": "^10.0.1",
49
48
  "@semantic-release/github": "^12.0.0",
49
+ "@semantic-release/npm": "^13.1.5",
50
50
  "@semantic-release/release-notes-generator": "^14.1.0",
51
+ "@types/node": "24.10.1",
51
52
  "@types/react": "^19.2.2",
53
+ "lefthook": "^1.13.6",
54
+ "semantic-release": "^25.0.2",
52
55
  "tsup": "8.5.1",
53
56
  "typescript": "6.0.3",
54
- "vitest": "4.0.4",
55
- "lefthook": "^1.13.6",
56
- "semantic-release": "^25.0.2"
57
+ "vitest": "4.0.4"
57
58
  },
58
59
  "pnpm": {
59
60
  "onlyBuiltDependencies": [
File without changes