@wastedcode/memex 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +291 -0
- package/dist/cli/client.d.ts +35 -0
- package/dist/cli/client.js +183 -0
- package/dist/cli/client.js.map +1 -0
- package/dist/cli/commands/chown.d.ts +2 -0
- package/dist/cli/commands/chown.js +22 -0
- package/dist/cli/commands/chown.js.map +1 -0
- package/dist/cli/commands/config.d.ts +2 -0
- package/dist/cli/commands/config.js +132 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/create.d.ts +2 -0
- package/dist/cli/commands/create.js +21 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/destroy.d.ts +2 -0
- package/dist/cli/commands/destroy.js +34 -0
- package/dist/cli/commands/destroy.js.map +1 -0
- package/dist/cli/commands/ingest.d.ts +2 -0
- package/dist/cli/commands/ingest.js +74 -0
- package/dist/cli/commands/ingest.js.map +1 -0
- package/dist/cli/commands/lint.d.ts +2 -0
- package/dist/cli/commands/lint.js +46 -0
- package/dist/cli/commands/lint.js.map +1 -0
- package/dist/cli/commands/list.d.ts +2 -0
- package/dist/cli/commands/list.js +28 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/login.d.ts +2 -0
- package/dist/cli/commands/login.js +51 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/logs.d.ts +2 -0
- package/dist/cli/commands/logs.js +26 -0
- package/dist/cli/commands/logs.js.map +1 -0
- package/dist/cli/commands/query.d.ts +2 -0
- package/dist/cli/commands/query.js +48 -0
- package/dist/cli/commands/query.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +2 -0
- package/dist/cli/commands/serve.js +14 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.js +66 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/daemon/auth.d.ts +31 -0
- package/dist/daemon/auth.js +84 -0
- package/dist/daemon/auth.js.map +1 -0
- package/dist/daemon/db.d.ts +36 -0
- package/dist/daemon/db.js +181 -0
- package/dist/daemon/db.js.map +1 -0
- package/dist/daemon/namespace.d.ts +34 -0
- package/dist/daemon/namespace.js +74 -0
- package/dist/daemon/namespace.js.map +1 -0
- package/dist/daemon/peercred.d.ts +15 -0
- package/dist/daemon/peercred.js +19 -0
- package/dist/daemon/peercred.js.map +1 -0
- package/dist/daemon/queue.d.ts +26 -0
- package/dist/daemon/queue.js +126 -0
- package/dist/daemon/queue.js.map +1 -0
- package/dist/daemon/routes.d.ts +38 -0
- package/dist/daemon/routes.js +258 -0
- package/dist/daemon/routes.js.map +1 -0
- package/dist/daemon/runner.d.ts +25 -0
- package/dist/daemon/runner.js +195 -0
- package/dist/daemon/runner.js.map +1 -0
- package/dist/daemon/scaffold.d.ts +38 -0
- package/dist/daemon/scaffold.js +141 -0
- package/dist/daemon/scaffold.js.map +1 -0
- package/dist/daemon/server.d.ts +11 -0
- package/dist/daemon/server.js +145 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon.d.ts +1 -0
- package/dist/daemon.js +55 -0
- package/dist/daemon.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/constants.d.ts +17 -0
- package/dist/lib/constants.js +30 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/errors.d.ts +32 -0
- package/dist/lib/errors.js +64 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/prompts/ingest.d.ts +9 -0
- package/dist/lib/prompts/ingest.js +48 -0
- package/dist/lib/prompts/ingest.js.map +1 -0
- package/dist/lib/prompts/lint.d.ts +8 -0
- package/dist/lib/prompts/lint.js +62 -0
- package/dist/lib/prompts/lint.js.map +1 -0
- package/dist/lib/prompts/query.d.ts +8 -0
- package/dist/lib/prompts/query.js +37 -0
- package/dist/lib/prompts/query.js.map +1 -0
- package/dist/lib/prompts/wiki.d.ts +11 -0
- package/dist/lib/prompts/wiki.js +112 -0
- package/dist/lib/prompts/wiki.js.map +1 -0
- package/dist/lib/types.d.ts +76 -0
- package/dist/lib/types.js +3 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/standalone/memex.mjs +2313 -0
- package/dist/standalone/memex.mjs.map +7 -0
- package/package.json +54 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/daemon/db.ts", "../../src/lib/errors.ts", "../../src/lib/constants.ts", "../../src/daemon/namespace.ts", "../../src/daemon/scaffold.ts", "../../src/daemon/auth.ts", "../../src/lib/prompts/ingest.ts", "../../src/lib/prompts/query.ts", "../../src/lib/prompts/lint.ts", "../../src/lib/prompts/wiki.ts", "../../src/daemon/runner.ts", "../../src/daemon/queue.ts", "../../src/daemon/routes.ts", "../../src/daemon/peercred.ts", "../../src/daemon/server.ts", "../../src/daemon.ts", "../../src/index.ts", "../../src/cli/commands/serve.ts", "../../src/cli/commands/create.ts", "../../src/cli/client.ts", "../../src/cli/commands/destroy.ts", "../../src/cli/commands/config.ts", "../../src/cli/commands/login.ts", "../../src/cli/commands/ingest.ts", "../../src/cli/commands/query.ts", "../../src/cli/commands/lint.ts", "../../src/cli/commands/logs.ts", "../../src/cli/commands/list.ts", "../../src/cli/commands/chown.ts", "../../src/cli/commands/status.ts"],
|
|
4
|
+
"sourcesContent": ["import BetterSqlite3 from 'better-sqlite3';\nimport type {\n Wiki, WikiConfig, QueueJob, JobType, JobStatus, JobResult, AuditEntry,\n} from '../lib/types.js';\n\nexport class Database {\n private db: BetterSqlite3.Database;\n\n constructor(dbPath: string) {\n this.db = new BetterSqlite3(dbPath);\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('foreign_keys = ON');\n }\n\n // \u2500\u2500 Schema \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n initialize(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS wikis (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n owner_uid INTEGER NOT NULL,\n default_model TEXT NOT NULL DEFAULT 'sonnet',\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n\n CREATE TABLE IF NOT EXISTS queue_jobs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n wiki_id TEXT NOT NULL REFERENCES wikis(id) ON DELETE CASCADE,\n type TEXT NOT NULL,\n payload TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n retry_count INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n started_at TEXT,\n completed_at TEXT,\n result TEXT\n );\n\n CREATE TABLE IF NOT EXISTS audit_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n wiki_id TEXT NOT NULL REFERENCES wikis(id) ON DELETE CASCADE,\n action TEXT NOT NULL,\n detail TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n\n CREATE INDEX IF NOT EXISTS idx_queue_wiki_status\n ON queue_jobs(wiki_id, status);\n CREATE INDEX IF NOT EXISTS idx_audit_wiki\n ON audit_log(wiki_id);\n CREATE INDEX IF NOT EXISTS idx_audit_created\n ON audit_log(created_at);\n `);\n\n }\n\n close(): void {\n this.db.close();\n }\n\n // \u2500\u2500 Wikis \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n createWiki(id: string, name: string, ownerUid: number): Wiki {\n const stmt = this.db.prepare(`\n INSERT INTO wikis (id, name, owner_uid) VALUES (?, ?, ?)\n RETURNING *\n `);\n return stmt.get(id, name, ownerUid) as Wiki;\n }\n\n getWiki(id: string): Wiki | undefined {\n return this.db.prepare('SELECT * FROM wikis WHERE id = ?').get(id) as Wiki | undefined;\n }\n\n listWikis(ownerUid?: number): Wiki[] {\n if (ownerUid !== undefined) {\n return this.db.prepare('SELECT * FROM wikis WHERE owner_uid = ? ORDER BY created_at').all(ownerUid) as Wiki[];\n }\n return this.db.prepare('SELECT * FROM wikis ORDER BY created_at').all() as Wiki[];\n }\n\n chownWiki(id: string, newOwnerUid: number): Wiki {\n const stmt = this.db.prepare(\n 'UPDATE wikis SET owner_uid = ? WHERE id = ? RETURNING *'\n );\n return stmt.get(newOwnerUid, id) as Wiki;\n }\n\n updateWiki(id: string, config: WikiConfig): Wiki {\n const sets: string[] = [];\n const values: unknown[] = [];\n\n if (config.name !== undefined) {\n sets.push('name = ?');\n values.push(config.name);\n }\n if (config.default_model !== undefined) {\n sets.push('default_model = ?');\n values.push(config.default_model);\n }\n\n if (sets.length === 0) {\n return this.getWiki(id) as Wiki;\n }\n\n values.push(id);\n const stmt = this.db.prepare(\n `UPDATE wikis SET ${sets.join(', ')} WHERE id = ? RETURNING *`\n );\n return stmt.get(...values) as Wiki;\n }\n\n deleteWiki(id: string): void {\n this.db.prepare('DELETE FROM wikis WHERE id = ?').run(id);\n }\n\n // \u2500\u2500 Jobs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n createJob(wikiId: string, type: JobType, payload: object): QueueJob {\n const stmt = this.db.prepare(`\n INSERT INTO queue_jobs (wiki_id, type, payload)\n VALUES (?, ?, ?)\n RETURNING *\n `);\n return stmt.get(wikiId, type, JSON.stringify(payload)) as QueueJob;\n }\n\n getJob(jobId: number): QueueJob | undefined {\n return this.db.prepare('SELECT * FROM queue_jobs WHERE id = ?').get(jobId) as QueueJob | undefined;\n }\n\n listJobs(wikiId: string, opts?: { status?: JobStatus; limit?: number }): QueueJob[] {\n let sql = 'SELECT * FROM queue_jobs WHERE wiki_id = ?';\n const params: unknown[] = [wikiId];\n\n if (opts?.status) {\n sql += ' AND status = ?';\n params.push(opts.status);\n }\n\n sql += ' ORDER BY id DESC';\n\n if (opts?.limit) {\n sql += ' LIMIT ?';\n params.push(opts.limit);\n }\n\n return this.db.prepare(sql).all(...params) as QueueJob[];\n }\n\n /**\n * Atomically claim the next pending job for a wiki.\n * Sets status to 'running' and records started_at.\n */\n claimNextJob(wikiId: string): QueueJob | undefined {\n const stmt = this.db.prepare(`\n UPDATE queue_jobs\n SET status = 'running', started_at = datetime('now')\n WHERE id = (\n SELECT id FROM queue_jobs\n WHERE wiki_id = ? AND status = 'pending'\n ORDER BY id ASC\n LIMIT 1\n )\n RETURNING *\n `);\n return stmt.get(wikiId) as QueueJob | undefined;\n }\n\n completeJob(jobId: number, result: JobResult): void {\n this.db.prepare(`\n UPDATE queue_jobs\n SET status = 'completed', completed_at = datetime('now'), result = ?\n WHERE id = ?\n `).run(JSON.stringify(result), jobId);\n }\n\n failJob(jobId: number, error: string): void {\n this.db.prepare(`\n UPDATE queue_jobs\n SET status = 'failed', completed_at = datetime('now'), result = ?\n WHERE id = ?\n `).run(JSON.stringify({ success: false, error }), jobId);\n }\n\n getPendingJobCount(wikiId: string): number {\n const row = this.db.prepare(\n \"SELECT COUNT(*) as count FROM queue_jobs WHERE wiki_id = ? AND status IN ('pending', 'running')\"\n ).get(wikiId) as { count: number };\n return row.count;\n }\n\n /**\n * On daemon startup: reset jobs that were 'running' when the process died.\n * They get re-queued as 'pending'.\n */\n resetStaleJobs(): number {\n const info = this.db.prepare(`\n UPDATE queue_jobs\n SET status = 'pending', retry_count = retry_count + 1\n WHERE status = 'running'\n `).run();\n return info.changes;\n }\n\n /** Get wiki IDs that have pending jobs (for startup drain). */\n wikisWithPendingJobs(): string[] {\n const rows = this.db.prepare(\n \"SELECT DISTINCT wiki_id FROM queue_jobs WHERE status = 'pending'\"\n ).all() as { wiki_id: string }[];\n return rows.map(r => r.wiki_id);\n }\n\n // \u2500\u2500 Audit \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n logAudit(wikiId: string, action: string, detail?: string): void {\n this.db.prepare(\n 'INSERT INTO audit_log (wiki_id, action, detail) VALUES (?, ?, ?)'\n ).run(wikiId, action, detail ?? null);\n }\n\n getAuditLog(wikiId: string, limit: number = 50): AuditEntry[] {\n return this.db.prepare(\n 'SELECT * FROM audit_log WHERE wiki_id = ? ORDER BY id DESC LIMIT ?'\n ).all(wikiId, limit) as AuditEntry[];\n }\n}\n", "export class MemexError extends Error {\n constructor(\n message: string,\n public code: string,\n public statusCode: number = 500\n ) {\n super(message);\n this.name = 'MemexError';\n }\n}\n\nexport class WikiNotFoundError extends MemexError {\n constructor(wikiId: string) {\n super(`Wiki '${wikiId}' not found`, 'WIKI_NOT_FOUND', 404);\n }\n}\n\nexport class WikiExistsError extends MemexError {\n constructor(wikiId: string) {\n super(`Wiki '${wikiId}' already exists`, 'WIKI_EXISTS', 409);\n }\n}\n\nexport class JobNotFoundError extends MemexError {\n constructor(jobId: number) {\n super(`Job #${jobId} not found`, 'JOB_NOT_FOUND', 404);\n }\n}\n\nexport class NamespaceError extends MemexError {\n constructor(message: string) {\n super(message, 'NAMESPACE_ERROR', 500);\n }\n}\n\nexport class CapabilityError extends MemexError {\n constructor() {\n super(\n 'CAP_SYS_ADMIN is required for mount namespace isolation.\\n' +\n 'Options:\\n' +\n ' 1. Run the daemon as root: sudo memex serve\\n' +\n ' 2. Use systemd with AmbientCapabilities=CAP_SYS_ADMIN\\n' +\n ' 3. Grant capability: sudo setcap cap_sys_admin+ep $(which node)',\n 'NO_CAP_SYS_ADMIN',\n 500\n );\n }\n}\n\nexport class NoCredentialsError extends MemexError {\n constructor(wikiId: string) {\n super(\n `No credentials configured for wiki '${wikiId}'.\\n` +\n 'Set credentials with:\\n' +\n ` memex login ${wikiId} (OAuth)\\n` +\n ` memex config ${wikiId} --set-key (API key)`,\n 'NO_CREDENTIALS',\n 400\n );\n }\n}\n\nexport class ForbiddenError extends MemexError {\n constructor(wikiId: string) {\n super(`Access denied to wiki '${wikiId}'`, 'FORBIDDEN', 403);\n }\n}\n\nexport class ValidationError extends MemexError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n }\n}\n\nexport class DaemonNotRunningError extends MemexError {\n constructor() {\n super(\n 'Cannot connect to memex daemon.\\n' +\n 'Start it with: memex serve',\n 'DAEMON_NOT_RUNNING',\n 502\n );\n }\n}\n", "import type { JobType, JobLimits } from './types.js';\n\n// \u2500\u2500 Paths (overridable via env) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const DATA_DIR = process.env['MEMEX_DATA_DIR'] ?? '/var/lib/memex';\nexport const RUN_DIR = process.env['MEMEX_RUN_DIR'] ?? '/run/memex';\nexport const SOCKET_PATH = process.env['MEMEX_SOCKET_PATH'] ?? `${RUN_DIR}/memex.sock`;\nexport const DB_PATH = `${DATA_DIR}/memex.db`;\nexport const WIKIS_DIR = `${DATA_DIR}/wikis`;\nexport const NS_DIR = `${RUN_DIR}/ns`;\n\n// Mount target inside namespaces \u2014 must exist on host as empty directory\nexport const WORKSPACE_MOUNT = '/workspace';\n\n// \u2500\u2500 Job limits \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const JOB_LIMITS: Record<JobType, JobLimits> = {\n ingest: { timeout_ms: 5 * 60_000, max_turns: 25 },\n query: { timeout_ms: 2 * 60_000, max_turns: 15 },\n lint: { timeout_ms: 10 * 60_000, max_turns: 30 },\n};\n\n// \u2500\u2500 Process management \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const SIGTERM_GRACE_MS = 5_000;\nexport const AUTO_LINT_INTERVAL = 10;\nexport const JOB_POLL_INTERVAL_MS = 500;\n\n// \u2500\u2500 Claude defaults \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const DEFAULT_MODEL = 'sonnet';\nexport const BASE_ALLOWED_TOOLS = ['Read', 'Write', 'Edit', 'Glob', 'Grep'];\n\n/** Tools that may be added via .tools/allowed-tools.txt. Bash and other shell/code tools are excluded. */\nexport const ALLOWED_TOOLS_WHITELIST = new Set([\n 'Read', 'Write', 'Edit', 'Glob', 'Grep',\n 'NotebookEdit', 'WebFetch', 'WebSearch',\n]);\n\n// \u2500\u2500 Validation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const WIKI_ID_PATTERN = /^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/;\n", "import { execFileSync } from 'node:child_process';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { CapabilityError } from '../lib/errors.js';\nimport { WIKIS_DIR, WORKSPACE_MOUNT } from '../lib/constants.js';\n\n/**\n * Per-job mount namespace isolation.\n *\n * Instead of persistent namespaces (which require kernel-specific unshare --mount=<file>),\n * we wrap each job command in `unshare -m -- sh -c '...'`. The namespace lives and dies\n * with the process. Simpler, more portable, same isolation.\n */\nexport class NamespaceManager {\n constructor(\n private wikisDir: string = WIKIS_DIR,\n ) {}\n\n /**\n * Verify that we have CAP_SYS_ADMIN by attempting a trivial namespace operation.\n */\n checkCapabilities(): void {\n try {\n execFileSync('unshare', ['-m', '--', 'true'], { stdio: 'pipe' });\n } catch {\n throw new CapabilityError();\n }\n }\n\n /**\n * Ensure the /workspace mount target exists on the host.\n */\n ensureDirectories(): void {\n mkdirSync(WORKSPACE_MOUNT, { recursive: true });\n }\n\n /**\n * Verify a wiki's directory exists.\n */\n validateWiki(wikiId: string): void {\n const wikiDir = join(this.wikisDir, wikiId);\n if (!existsSync(wikiDir)) {\n throw new Error(`Wiki directory does not exist: ${wikiDir}`);\n }\n }\n\n /**\n * Build the command + args to run a command inside a fresh mount namespace\n * with the wiki's directory bind-mounted to /workspace.\n *\n * Returns [command, ...args] to pass to spawn().\n * The caller appends their actual command (e.g. claude -p ...) to innerArgs.\n */\n wrapCommand(wikiId: string, innerCommand: string[]): { command: string; args: string[] } {\n const wikiDir = join(this.wikisDir, wikiId);\n\n // Build a shell script that:\n // 1. Bind-mounts the wiki dir to /workspace\n // 2. Remounts nosuid,nodev\n // 3. cd into /workspace\n // 4. exec the inner command\n const script = [\n `mount --bind ${shellEscape(wikiDir)} ${shellEscape(WORKSPACE_MOUNT)}`,\n `mount -o remount,nosuid,nodev ${shellEscape(WORKSPACE_MOUNT)}`,\n `cd ${shellEscape(WORKSPACE_MOUNT)}`,\n `exec ${innerCommand.map(shellEscape).join(' ')}`,\n ].join(' && ');\n\n return {\n command: 'unshare',\n args: ['-m', '--propagation', 'private', '--', 'sh', '-c', script],\n };\n }\n}\n\nfunction shellEscape(s: string): string {\n // Wrap in single quotes, escaping any existing single quotes\n return \"'\" + s.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n", "import { mkdirSync, writeFileSync, rmSync, readFileSync, existsSync } from 'node:fs';\nimport { join, basename } from 'node:path';\nimport { WIKIS_DIR } from '../lib/constants.js';\n\nconst DEFAULT_CLAUDE_MD = `# Wiki Agent \u2014 Conventions\n\nThis file is auto-discovered by Claude Code and extends the base system prompt.\nUse it to define wiki-specific conventions, domain vocabulary, and wiki structure.\n\nThe base system prompt handles core wiki behavior (index, schema, connections, log).\nThis file is for YOUR customizations on top of that.\n\n## Domain\n\n_(Describe what this knowledge base is about)_\n\n## Conventions\n\n_(Add wiki-specific filing rules, vocabulary, categories, and preferences here)_\n\n## Things to ignore\n\n_(Topics, patterns, or noise that should be skipped during ingestion)_\n`;\n\n// Schema is intentionally minimal \u2014 the LLM will create a proper one on first ingest\n// when it sees the actual content and can establish meaningful conventions.\nconst DEFAULT_SCHEMA_MD = `# Schema\n\nThis file documents the conventions for this knowledge base.\nIt will be created and maintained by the wiki agent as content is ingested.\n\n_(This is a new knowledge base. The schema will be populated on first ingest.)_\n`;\n\nconst DEFAULT_INDEX_MD = `# Index\n\nOne-line summary of every wiki page, organized by category.\nA reader should understand the shape of the knowledge base from this file alone.\n\n_(No pages yet. The index will be populated as content is ingested.)_\n`;\n\nconst DEFAULT_LOG_MD = `# Activity Log\n\nChronological record of knowledge base activity.\n\n---\n`;\n\nexport class WikiScaffold {\n constructor(private wikisDir: string = WIKIS_DIR) {}\n\n /**\n * Create the full directory structure and default files for a new wiki.\n */\n create(wikiId: string): void {\n const base = this.wikiDir(wikiId);\n\n // Directories\n mkdirSync(join(base, '.claude'), { recursive: true, mode: 0o700 });\n mkdirSync(join(base, '.tools'), { recursive: true });\n mkdirSync(join(base, 'wiki', 'raw'), { recursive: true });\n\n // Default files\n writeFileSync(join(base, '.claude.md'), DEFAULT_CLAUDE_MD);\n writeFileSync(join(base, 'wiki', '_schema.md'), DEFAULT_SCHEMA_MD);\n writeFileSync(join(base, 'wiki', '_index.md'), DEFAULT_INDEX_MD);\n writeFileSync(join(base, 'wiki', '_log.md'), DEFAULT_LOG_MD);\n }\n\n /**\n * Remove a wiki's directory tree.\n */\n destroy(wikiId: string, keepData: boolean = false): void {\n if (keepData) return;\n const dir = this.wikiDir(wikiId);\n if (existsSync(dir)) {\n rmSync(dir, { recursive: true, force: true });\n }\n }\n\n /**\n * Get the host filesystem path for a wiki's root directory.\n */\n wikiDir(wikiId: string): string {\n return join(this.wikisDir, wikiId);\n }\n\n /**\n * Write a file into the wiki's wiki/raw/ directory.\n * Prefixes with a timestamp to avoid collisions.\n * Returns the stored filename (relative to wiki/raw/).\n */\n writeRawFile(wikiId: string, filename: string, content: Buffer): string {\n const rawDir = join(this.wikiDir(wikiId), 'wiki', 'raw');\n mkdirSync(rawDir, { recursive: true });\n\n const ts = new Date().toISOString().replace(/[-:]/g, '').replace(/\\.\\d+Z$/, '');\n const stored = `${ts}-${sanitizeFilename(basename(filename))}`;\n writeFileSync(join(rawDir, stored), content);\n return stored;\n }\n\n /**\n * Read the wiki's .claude.md content.\n */\n readClaudeMd(wikiId: string): string {\n const p = join(this.wikiDir(wikiId), '.claude.md');\n if (!existsSync(p)) return '';\n return readFileSync(p, 'utf-8');\n }\n\n /**\n * Write the allowed-tools.txt file for a wiki.\n */\n writeAllowedTools(wikiId: string, tools: string[]): void {\n const toolsDir = join(this.wikiDir(wikiId), '.tools');\n mkdirSync(toolsDir, { recursive: true });\n const content = tools.length > 0\n ? tools.join('\\n') + '\\n'\n : '';\n writeFileSync(join(toolsDir, 'allowed-tools.txt'), content);\n }\n\n /**\n * Read the current allowed-tools.txt for a wiki.\n */\n readAllowedTools(wikiId: string): string[] {\n const p = join(this.wikiDir(wikiId), '.tools', 'allowed-tools.txt');\n if (!existsSync(p)) return [];\n return readFileSync(p, 'utf-8')\n .split('\\n')\n .map(l => l.trim())\n .filter(l => l && !l.startsWith('#'));\n }\n\n /**\n * Check if a wiki directory exists on disk.\n */\n exists(wikiId: string): boolean {\n return existsSync(this.wikiDir(wikiId));\n }\n}\n\n/**\n * Strip dangerous characters from filenames while preserving the extension.\n */\nfunction sanitizeFilename(name: string): string {\n return name.replace(/[^a-zA-Z0-9._-]/g, '_');\n}\n", "import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { WIKIS_DIR } from '../lib/constants.js';\nimport { NoCredentialsError } from '../lib/errors.js';\n\nexport class AuthManager {\n constructor(\n private wikisDir: string = WIKIS_DIR,\n private globalApiKey?: string,\n ) {}\n\n /**\n * Resolve credentials for a wiki, returning environment variables\n * to set on the claude child process.\n *\n * Priority:\n * 1. Per-wiki API key file (.claude/api-key)\n * 2. Per-wiki OAuth credentials (.claude/.credentials.json exists)\n * 3. Global ANTHROPIC_API_KEY from daemon environment\n */\n resolveCredentials(wikiId: string): Record<string, string> {\n const claudeDir = this.configDir(wikiId);\n\n // 1. Per-wiki API key\n const apiKeyPath = join(claudeDir, 'api-key');\n if (existsSync(apiKeyPath)) {\n const key = readFileSync(apiKeyPath, 'utf-8').trim();\n if (key) {\n return {\n ANTHROPIC_API_KEY: key,\n CLAUDE_CONFIG_DIR: claudeDir,\n };\n }\n }\n\n // 2. Per-wiki OAuth credentials\n const credsPath = join(claudeDir, '.credentials.json');\n if (existsSync(credsPath)) {\n return {\n CLAUDE_CONFIG_DIR: claudeDir,\n };\n }\n\n // 3. Global API key\n if (this.globalApiKey) {\n return {\n ANTHROPIC_API_KEY: this.globalApiKey,\n CLAUDE_CONFIG_DIR: claudeDir,\n };\n }\n\n throw new NoCredentialsError(wikiId);\n }\n\n /**\n * Store an API key for a wiki.\n */\n setApiKey(wikiId: string, key: string): void {\n const claudeDir = this.configDir(wikiId);\n mkdirSync(claudeDir, { recursive: true, mode: 0o700 });\n const apiKeyPath = join(claudeDir, 'api-key');\n writeFileSync(apiKeyPath, key.trim(), { mode: 0o600 });\n }\n\n /**\n * Get the CLAUDE_CONFIG_DIR path for a wiki.\n */\n configDir(wikiId: string): string {\n return join(this.wikisDir, wikiId, '.claude');\n }\n\n /**\n * Store OAuth credentials for a wiki by copying .credentials.json content.\n */\n setCredentials(wikiId: string, credentialsJson: string): void {\n const claudeDir = this.configDir(wikiId);\n mkdirSync(claudeDir, { recursive: true, mode: 0o700 });\n const credsPath = join(claudeDir, '.credentials.json');\n writeFileSync(credsPath, credentialsJson, { mode: 0o600 });\n }\n\n /**\n * Check if a wiki has valid credentials (any method).\n */\n hasCredentials(wikiId: string): boolean {\n const claudeDir = this.configDir(wikiId);\n const apiKeyPath = join(claudeDir, 'api-key');\n const credsPath = join(claudeDir, '.credentials.json');\n return existsSync(apiKeyPath) || existsSync(credsPath) || !!this.globalApiKey;\n }\n}\n", "import type { IngestPayload } from '../types.js';\n\n/**\n * Build the prompt for an ingest job.\n *\n * Claude reads the raw source files and integrates them into the wiki.\n * This is not just filing \u2014 it's building understanding. The wiki should\n * get richer with every ingest, not just wider.\n */\nexport function buildIngestPrompt(payload: IngestPayload): string {\n const fileList = payload.files\n .map(f => `- raw/${f}`)\n .join('\\n');\n\n return `New source documents have been added to the knowledge base.\n\nSource files to process:\n${fileList}\n\nIntegrate these into the wiki:\n\n1. Read each source file listed above.\n2. Read _schema.md for current conventions (create it if it doesn't exist \u2014 this is a new knowledge base).\n3. Read _index.md to see what's already filed.\n4. Search existing wiki pages for related content (grep for names, topics, themes).\n5. For each source document:\n a. Extract key facts, concepts, entities, and relationships.\n b. Determine which existing pages should be updated and which new pages should be created.\n c. Create or update wiki pages with the extracted information.\n d. Maintain bidirectional links \u2014 if you link A\u2192B, update B\u2192A too.\n e. Update _index.md with current summaries for all affected pages.\n6. Append a dated ingest entry to _log.md summarizing what was ingested and what pages were affected.\n\nRules:\n- NEVER modify files in raw/ \u2014 they are immutable sources\n- Prefer updating existing pages over creating duplicates\n- If a source contradicts existing wiki content, UPDATE the existing page \u2014 resolve or flag the contradiction\n- Keep pages focused \u2014 one topic per page\n- Use descriptive kebab-case paths: themes/pricing-feedback.md, customers/acme-corp.md\n- Every page must have a ## Related section with labeled, bidirectional links\n- The \"reason\" for each change should articulate what it ADDS to the knowledge base \u2014 not mechanics\n\nAfter completing all file operations, output ONLY valid JSON (no markdown fences, no explanation):\n{\n \"summary\": \"one-line human summary of what you filed\",\n \"operations\": [\n {\"action\": \"create|update\", \"path\": \"relative/path.md\", \"reason\": \"what this adds to the knowledge base\"}\n ]\n}`;\n}\n", "import type { QueryPayload } from '../types.js';\n\n/**\n * Build the prompt for a query job.\n *\n * Claude searches the wiki and synthesizes an answer grounded in the\n * knowledge base. It's not a generic assistant \u2014 it's the voice of the wiki.\n */\nexport function buildQueryPrompt(payload: QueryPayload): string {\n let prompt = `You are the voice of a living knowledge base. Answer the user's question by searching the wiki files in this directory.\n\nQuestion: ${payload.question}\n\nRULES:\n1. ONLY reference information that exists in the wiki files. Never use training data for facts.\n2. Always cite the specific file path when referencing information (e.g. \\`themes/pricing.md\\`).\n3. If the wiki has no relevant information, say so clearly: \"The knowledge base doesn't have information on that topic yet.\"\n4. If you notice contradictions between pages, mention them.\n5. If coverage is thin on a topic, note it: \"Coverage on X is thin \u2014 only one source.\"\n6. If your answer synthesizes multiple pages into new insight, mention it could be saved to the wiki as a new page.\n7. Keep responses concise and specific. Cite evidence, don't summarize generically.\n\nTo answer:\n- Read _index.md to understand what's in the knowledge base\n- Search for relevant files using grep and glob\n- Read the files that seem relevant\n- Synthesize an answer grounded in what you found\n\nProvide your answer as plain markdown. Be concise but thorough.`;\n\n if (payload.history && payload.history.length > 0) {\n prompt += '\\n\\nConversation so far:\\n';\n for (const turn of payload.history) {\n prompt += `${turn}\\n\\n`;\n }\n prompt += 'Answer the last message.';\n }\n\n return prompt;\n}\n", "/**\n * Build the prompt for a lint/maintenance job.\n *\n * Claude examines the knowledge base holistically. Finds contradictions,\n * stale claims, orphan pages, missing connections. Applies confident fixes\n * directly, flags everything else in a report.\n */\nexport function buildLintPrompt(): string {\n const date = new Date().toISOString().split('T')[0];\n\n return `Perform a thorough health check on this knowledge base. Today is ${date}.\n\nRead all wiki files (glob **/*.md, excluding raw/) and check for:\n\n1. **Contradictions** \u2014 pages making conflicting claims about the same entity or fact\n2. **Stale claims** \u2014 date-stamped statements that may no longer be current\n3. **Orphan pages** \u2014 pages with no inbound links from other pages' ## Related sections\n4. **Missing pages** \u2014 concepts mentioned across multiple pages that deserve their own page\n5. **Duplicate pages** \u2014 topics covered by two pages that should be merged\n6. **Missing cross-references** \u2014 pages discussing entities with their own pages but not linking\n7. **Index accuracy** \u2014 _index.md entries that don't match file content, or missing entries\n8. **Schema drift** \u2014 actual patterns that don't match _schema.md conventions\n\nFor issues you're CONFIDENT about, fix them directly:\n- Add missing cross-references and ## Related links (bidirectional)\n- Correct _index.md entries\n- Add ## Related sections to pages that lack them\n- Fix schema drift in _schema.md\n\nFor issues requiring human judgment (contradictions, merges, stale facts), note them in your report but do NOT change the files.\n\nDo NOT rewrite pages for style \u2014 only fix semantic issues.\n\nAfter making fixes, append a lint entry to _log.md.\n\nOutput a markdown health check report:\n\n# Knowledge Base Health Check \u2014 ${date}\n\n## Contradictions\n(numbered list with specific pages and quotes)\n\n## Stale Claims\n(numbered list with page, claim, and age)\n\n## Orphan Pages\n(list with page path and suggested connections)\n\n## Missing Cross-References\n(specific A\u2192B links that should exist)\n\n## Auto-Fixes Applied\n(list of changes you made directly)\n\n## Flagged for Review\n(issues needing human judgment)\n\n## Statistics\n- Total pages: N\n- Pages with ## Related: N\n- Orphan pages: N`;\n}\n", "/**\n * Wiki system prompt \u2014 injected via --append-system-prompt.\n *\n * This IS the product. Every sentence is a product decision.\n * Not stored as CLAUDE.md (we don't rely on auto-discovery for core behavior).\n * Passed explicitly to each claude -p invocation for full control.\n *\n * Users extend via .claude.md (auto-discovered by Claude Code).\n * This prompt provides the baseline; .claude.md provides wiki-specific customization.\n */\n\n// ---------------------------------------------------------------------------\n// The prompt is the product.\n//\n// This system prompt defines how Claude thinks about the knowledge base.\n// Every sentence is a product decision. Edit with the same care as a core\n// algorithm \u2014 test changes, review results, document iterations.\n// ---------------------------------------------------------------------------\n\nexport function getWikiSystemPrompt(): string {\n return `You are the curator of a living knowledge base. Your job is not just to file information \u2014 it's to build and maintain a persistent, compounding artifact where every conversation makes the whole richer.\n\nThink of yourself as the curator of a wiki, not a filing clerk. When you process a source, you're not just extracting facts \u2014 you're integrating new understanding into an evolving body of knowledge. The connections between documents are as valuable as the documents themselves.\n\nOn every call, think about:\n1. What does this source add to what we already know?\n2. Does it confirm, extend, or contradict existing understanding?\n3. Which existing pages need to know about this? Which pages does this need to know about?\n4. Are there patterns emerging that deserve their own page?\n5. Should any conventions or filing rules be updated based on what we've learned?\n\nIMPORTANT: You are operating in a sandboxed wiki directory. Only read and write files within this directory using relative paths. Do not use absolute paths. Do not attempt to access files outside this directory.\n\n## Directory structure\n\n- \\`_schema.md\\` \u2014 Filing conventions, categories, domain vocabulary, filing heuristics. YOUR institutional memory.\n- \\`_index.md\\` \u2014 One-line summary of every wiki page, organized by category. The table of contents.\n- \\`_log.md\\` \u2014 Chronological activity log. You maintain this.\n- \\`raw/\\` \u2014 Immutable source documents. NEVER modify or delete these files.\n- Everything else \u2014 Wiki pages organized by entity and topic.\n\n## Your responsibilities\n\n### 1. Schema (_schema.md)\nYou own the schema. Update it when you establish or refine conventions \u2014 new categories, naming patterns, domain vocabulary, filing heuristics, things to ignore.\n\nOn the FIRST call for a new knowledge base (no _schema.md exists), CREATE it with the conventions you establish. Suggested starting categories (adapt to what fits):\n- customers/ \u2014 profiles and feedback per person or company\n- themes/ \u2014 cross-cutting topics\n- products/ \u2014 organized by product area\n- research/ \u2014 deep dives and analyses\n- reference/ \u2014 factual reference material\n\n### 2. Index (_index.md)\nALWAYS keep _index.md current. Every wiki page gets a one-line summary: what it contains, how many connections, what matters most. Organize by category. A reader should understand the shape of the entire knowledge base by reading only the index.\n\nFormat:\n\\`\\`\\`\n## category\n- path/to/file.md \u2014 One-line semantic summary [N connections]\n\\`\\`\\`\n\n### 3. Connections (## Related)\nEvery wiki page you create or update MUST have a \\`## Related\\` section at the bottom with labeled, bidirectional links:\n\n\\`\\`\\`\n## Related\n- **Topic:** [themes/pricing.md](themes/pricing.md) \u2014 related pricing analysis\n- **Entity:** [customers/acme.md](customers/acme.md) \u2014 mentioned in their feedback\n- **Contradicts:** [research/market-size.md](research/market-size.md) \u2014 conflicting data point\n\\`\\`\\`\n\nConnection labels should be domain-appropriate: Topic, Entity, Source, Contradicts, See also, etc.\n\nCRITICAL: If you add a link from A to B, you MUST also update B to link back to A. Both sides of every connection. Always.\n\n### 4. Activity log (_log.md)\nAfter completing any operation, append an entry to _log.md:\n\n\\`\\`\\`\n## [YYYY-MM-DD HH:MM] type | source\nSummary of what happened\n- Detail 1\n- Detail 2\n\\`\\`\\`\n\nTypes: ingest, lint, query. If _log.md doesn't exist, create it with a header.\n\n### 5. Contradictions\nWhen new information conflicts with an existing page, UPDATE the existing page \u2014 resolve the contradiction or flag it clearly. Never file contradictory claims in separate pages without acknowledging the conflict.\n\n### 6. Look up before writing\nALWAYS read existing files before creating new ones. Search with grep and glob. Prefer updating existing pages over creating duplicates. The knowledge base should grow deeper, not just wider.\n\n### 7. Source references\nEach wiki page should reference its raw sources: \\`*Source: [raw/filename.md](raw/filename.md)*\\`\n\n### 8. Ongoing tuning\nAs you process more sources, notice patterns:\n- Are certain categories getting too broad? Split them.\n- Are there clusters of related pages that need a synthesis page?\n- Is the schema still serving the content well? Evolve it.\n- Are naming conventions consistent? Fix drift.\n\nUpdate _schema.md to reflect what you learn.\n\n## Page format\n- Organize by entity and topic, not by date\n- kebab-case for all file paths\n- Self-contained and readable with no other context\n- Preserve key quotes verbatim with attribution and date\n- Include source references`;\n}\n", "import { spawn, type ChildProcess } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { NamespaceManager } from './namespace.js';\nimport type { AuthManager } from './auth.js';\nimport type { Database } from './db.js';\nimport type { QueueJob, JobResult, IngestPayload, QueryPayload } from '../lib/types.js';\nimport {\n JOB_LIMITS, SIGTERM_GRACE_MS, BASE_ALLOWED_TOOLS, ALLOWED_TOOLS_WHITELIST, DEFAULT_MODEL, WORKSPACE_MOUNT,\n} from '../lib/constants.js';\nimport { buildIngestPrompt } from '../lib/prompts/ingest.js';\nimport { buildQueryPrompt } from '../lib/prompts/query.js';\nimport { buildLintPrompt } from '../lib/prompts/lint.js';\nimport { getWikiSystemPrompt } from '../lib/prompts/wiki.js';\n\nexport class ClaudeRunner {\n private active = new Map<number, ChildProcess>();\n\n constructor(\n private namespace: NamespaceManager,\n private auth: AuthManager,\n private db: Database,\n private wikisDir: string,\n ) {}\n\n async run(job: QueueJob): Promise<JobResult> {\n const startTime = Date.now();\n const wikiId = job.wiki_id;\n const wiki = this.db.getWiki(wikiId);\n const model = wiki?.default_model ?? DEFAULT_MODEL;\n const limits = JOB_LIMITS[job.type as keyof typeof JOB_LIMITS];\n\n // Build the task prompt\n const prompt = this.buildPrompt(job);\n\n // Resolve credentials\n const credEnv = this.auth.resolveCredentials(wikiId);\n\n // Resolve allowed tools\n const tools = this.resolveTools(wikiId);\n\n // Build claude -p command args\n const claudeArgs = this.buildClaudeArgs(prompt, model, limits.max_turns, tools, wikiId);\n\n // Wrap in a per-job mount namespace\n const wrapped = this.namespace.wrapCommand(wikiId, claudeArgs);\n\n // Build environment\n const env: Record<string, string> = {\n ...filterEnv(process.env),\n ...credEnv,\n HOME: WORKSPACE_MOUNT,\n };\n\n // If CLAUDE_CONFIG_DIR was set by auth, remap it to namespace path\n if (credEnv['CLAUDE_CONFIG_DIR']) {\n env['CLAUDE_CONFIG_DIR'] = `${WORKSPACE_MOUNT}/.claude`;\n }\n\n return new Promise<JobResult>((resolve) => {\n const child = spawn(wrapped.command, wrapped.args, {\n env,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Close stdin immediately \u2014 prompt is passed via -p flag, not stdin\n child.stdin!.end();\n\n this.active.set(job.id, child);\n\n const stdout: Buffer[] = [];\n const stderr: Buffer[] = [];\n\n child.stdout!.on('data', (chunk: Buffer) => stdout.push(chunk));\n child.stderr!.on('data', (chunk: Buffer) => stderr.push(chunk));\n\n // Timeout management: SIGTERM \u2192 grace period \u2192 SIGKILL\n const timeout = setTimeout(() => {\n console.warn(`[runner] Job #${job.id} timed out after ${limits.timeout_ms}ms, sending SIGTERM`);\n child.kill('SIGTERM');\n\n setTimeout(() => {\n if (!child.killed) {\n console.warn(`[runner] Job #${job.id} did not exit after SIGTERM grace period, sending SIGKILL`);\n child.kill('SIGKILL');\n }\n }, SIGTERM_GRACE_MS);\n }, limits.timeout_ms);\n\n child.on('close', (code) => {\n clearTimeout(timeout);\n this.active.delete(job.id);\n\n const duration_ms = Date.now() - startTime;\n const rawOut = Buffer.concat(stdout).toString('utf-8');\n const rawErr = Buffer.concat(stderr).toString('utf-8');\n\n // Parse JSON output from claude --output-format json\n // Claude wraps output in { result: \"...\", ... }\n let output = rawOut;\n try {\n const envelope = JSON.parse(rawOut);\n const text = envelope.result ?? '';\n // Try to parse the result text as structured JSON from the prompt\n try {\n output = JSON.stringify(JSON.parse(text));\n } catch {\n output = text.trim() || rawOut;\n }\n } catch {\n // Claude output wasn't JSON \u2014 use raw stdout\n }\n\n if (rawErr) {\n console.error(`[runner] Job #${job.id} stderr: ${rawErr.slice(0, 500)}`);\n }\n\n // On failure, include stderr in output so the error is visible\n const finalOutput = code === 0\n ? output\n : [output, rawErr].filter(Boolean).join('\\n').trim() || `claude exited with code ${code}`;\n\n resolve({\n success: code === 0,\n output: finalOutput,\n exit_code: code ?? 1,\n duration_ms,\n });\n });\n });\n }\n\n /**\n * Kill an active job's process. Used during graceful shutdown.\n */\n kill(jobId: number): void {\n const child = this.active.get(jobId);\n if (child) {\n child.kill('SIGTERM');\n setTimeout(() => {\n if (!child.killed) child.kill('SIGKILL');\n }, SIGTERM_GRACE_MS);\n }\n }\n\n /**\n * Kill all active processes. Used during daemon shutdown.\n */\n killAll(): void {\n for (const [jobId] of this.active) {\n this.kill(jobId);\n }\n }\n\n get activeCount(): number {\n return this.active.size;\n }\n\n // \u2500\u2500 Private \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private buildPrompt(job: QueueJob): string {\n const payload = JSON.parse(job.payload);\n\n switch (job.type) {\n case 'ingest':\n return buildIngestPrompt(payload as IngestPayload);\n case 'query':\n return buildQueryPrompt(payload as QueryPayload);\n case 'lint':\n return buildLintPrompt();\n default:\n return `Unknown job type: ${job.type}`;\n }\n }\n\n private resolveTools(wikiId: string): string[] {\n const tools = [...BASE_ALLOWED_TOOLS];\n\n const allowedPath = join(this.wikisDir, wikiId, '.tools', 'allowed-tools.txt');\n if (existsSync(allowedPath)) {\n const extra = readFileSync(allowedPath, 'utf-8')\n .split('\\n')\n .map(l => l.trim())\n .filter(l => l && !l.startsWith('#') && ALLOWED_TOOLS_WHITELIST.has(l));\n tools.push(...extra);\n }\n\n return [...new Set(tools)]; // dedupe\n }\n\n private buildClaudeArgs(\n prompt: string,\n model: string,\n maxTurns: number,\n tools: string[],\n wikiId: string,\n ): string[] {\n const toolStr = tools.join(',');\n const args = [\n 'claude',\n '-p', prompt,\n '--model', model,\n '--max-turns', String(maxTurns),\n '--output-format', 'json',\n '--tools', toolStr, // restrict which tools EXIST (hard boundary)\n '--allowedTools', toolStr, // pre-approve those tools (no interactive prompts)\n ];\n\n // Append wiki system prompt\n const systemPrompt = getWikiSystemPrompt();\n args.push('--append-system-prompt', systemPrompt);\n\n // MCP config (if the wiki has one)\n const mcpPath = join(this.wikisDir, wikiId, '.tools', 'mcp.json');\n if (existsSync(mcpPath)) {\n // Inside the namespace, this will be at /workspace/.tools/mcp.json\n args.push('--mcp-config', `${WORKSPACE_MOUNT}/.tools/mcp.json`);\n }\n\n return args;\n }\n}\n\n/**\n * Filter process.env to only include safe environment variables.\n * Exclude anything that could leak host info or interfere with Claude.\n */\nfunction filterEnv(env: NodeJS.ProcessEnv): Record<string, string> {\n const safe: Record<string, string> = {};\n const keep = ['PATH', 'LANG', 'LC_ALL', 'TERM', 'NODE_ENV'];\n for (const key of keep) {\n if (env[key]) safe[key] = env[key];\n }\n return safe;\n}\n", "import type { Database } from './db.js';\nimport type { ClaudeRunner } from './runner.js';\nimport { AUTO_LINT_INTERVAL } from '../lib/constants.js';\n\ninterface WikiState {\n active: boolean; // is a drain loop running for this wiki?\n pending: boolean; // has new work arrived while drain loop was active?\n ingestCount: number; // ingests since last auto-lint\n}\n\nexport class QueueManager {\n private wikis = new Map<string, WikiState>();\n private shuttingDown = false;\n\n constructor(\n private db: Database,\n private runner: ClaudeRunner,\n private autoLintInterval: number = AUTO_LINT_INTERVAL,\n ) {}\n\n /**\n * Start draining queues. Called on daemon startup.\n * Kicks off drain loops for all wikis with pending jobs.\n */\n start(): void {\n const wikisWithWork = this.db.wikisWithPendingJobs();\n for (const wikiId of wikisWithWork) {\n this.notify(wikiId);\n }\n console.log(`[queue] Started. ${wikisWithWork.length} wiki(s) have pending work.`);\n }\n\n /**\n * Signal that a wiki has new work to process.\n * If the wiki isn't already draining, starts a drain loop.\n */\n notify(wikiId: string): void {\n if (this.shuttingDown) return;\n\n let state = this.wikis.get(wikiId);\n if (!state) {\n state = { active: false, pending: false, ingestCount: 0 };\n this.wikis.set(wikiId, state);\n }\n\n if (state.active) {\n // Drain loop already running \u2014 just flag that new work exists\n state.pending = true;\n } else {\n // No active drain loop \u2014 start one\n this.drainWiki(wikiId, state);\n }\n }\n\n /**\n * Graceful shutdown. Waits for active jobs to finish.\n */\n async stop(): Promise<void> {\n this.shuttingDown = true;\n console.log('[queue] Shutting down...');\n\n // Wait for all active drain loops to complete their current job\n const maxWait = 30_000;\n const start = Date.now();\n\n while (this.runner.activeCount > 0 && Date.now() - start < maxWait) {\n await sleep(500);\n }\n\n if (this.runner.activeCount > 0) {\n console.warn(`[queue] ${this.runner.activeCount} job(s) still active after ${maxWait}ms, killing`);\n this.runner.killAll();\n }\n\n console.log('[queue] Shutdown complete.');\n }\n\n // \u2500\u2500 Private \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async drainWiki(wikiId: string, state: WikiState): Promise<void> {\n state.active = true;\n state.pending = false;\n\n try {\n while (!this.shuttingDown) {\n const job = this.db.claimNextJob(wikiId);\n if (!job) break; // no more pending jobs\n\n console.log(`[queue] Running job #${job.id} (${job.type}) for wiki '${wikiId}'`);\n\n try {\n const result = await this.runner.run(job);\n\n if (result.success) {\n this.db.completeJob(job.id, result);\n this.db.logAudit(wikiId, `job.${job.type}.completed`, `job #${job.id} (${result.duration_ms}ms)`);\n console.log(`[queue] Job #${job.id} completed in ${result.duration_ms}ms`);\n } else {\n this.db.failJob(job.id, result.output);\n this.db.logAudit(wikiId, `job.${job.type}.failed`, `job #${job.id}: ${result.output.slice(0, 200)}`);\n console.error(`[queue] Job #${job.id} failed (exit ${result.exit_code})`);\n }\n\n // Auto-lint tracking\n if (job.type === 'ingest' && result.success) {\n state.ingestCount++;\n if (this.autoLintInterval > 0 && state.ingestCount >= this.autoLintInterval) {\n state.ingestCount = 0;\n this.scheduleAutoLint(wikiId);\n }\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this.db.failJob(job.id, msg);\n this.db.logAudit(wikiId, `job.${job.type}.error`, `job #${job.id}: ${msg}`);\n console.error(`[queue] Job #${job.id} error: ${msg}`);\n }\n }\n } finally {\n state.active = false;\n\n // If new work arrived while we were draining, restart\n if (state.pending && !this.shuttingDown) {\n this.drainWiki(wikiId, state);\n }\n }\n }\n\n private scheduleAutoLint(wikiId: string): void {\n // Check if there's already a pending lint job to avoid stacking\n const pendingLints = this.db.listJobs(wikiId, { status: 'pending' })\n .filter(j => j.type === 'lint');\n\n if (pendingLints.length > 0) {\n console.log(`[queue] Skipping auto-lint for '${wikiId}' \u2014 lint already pending`);\n return;\n }\n\n console.log(`[queue] Scheduling auto-lint for '${wikiId}' after ${this.autoLintInterval} ingests`);\n this.db.createJob(wikiId, 'lint', {});\n // No need to notify \u2014 we're already in the drain loop and will pick it up\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n", "import type { ServerResponse } from 'node:http';\nimport type { Database } from './db.js';\nimport type { WikiScaffold } from './scaffold.js';\nimport type { NamespaceManager } from './namespace.js';\nimport type { QueueManager } from './queue.js';\nimport type { AuthManager } from './auth.js';\nimport type {\n RouteResponse, CreateWikiRequest, SubmitJobRequest, WikiConfig, JobType,\n} from '../lib/types.js';\nimport { WIKI_ID_PATTERN, JOB_POLL_INTERVAL_MS, ALLOWED_TOOLS_WHITELIST, BASE_ALLOWED_TOOLS } from '../lib/constants.js';\nimport {\n WikiNotFoundError, WikiExistsError, JobNotFoundError, ValidationError, ForbiddenError,\n} from '../lib/errors.js';\n\ninterface RouteContext {\n wait?: boolean;\n res?: ServerResponse;\n callerUid: number;\n}\n\ntype Route = {\n method: string;\n pattern: RegExp;\n handler: (params: Record<string, string>, body: unknown, ctx: RouteContext) => Promise<RouteResponse>;\n};\n\nexport class RouteHandler {\n private routes: Route[];\n\n constructor(\n private db: Database,\n private scaffold: WikiScaffold,\n private namespace: NamespaceManager,\n private queue: QueueManager,\n private auth: AuthManager,\n ) {\n this.routes = [\n { method: 'POST', pattern: /^\\/wikis$/, handler: this.createWiki.bind(this) },\n { method: 'GET', pattern: /^\\/wikis$/, handler: this.listWikis.bind(this) },\n { method: 'GET', pattern: /^\\/wikis\\/(?<id>[^/]+)$/, handler: this.getWiki.bind(this) },\n { method: 'DELETE', pattern: /^\\/wikis\\/(?<id>[^/]+)$/, handler: this.destroyWiki.bind(this) },\n { method: 'PUT', pattern: /^\\/wikis\\/(?<id>[^/]+)\\/config$/, handler: this.updateConfig.bind(this) },\n { method: 'POST', pattern: /^\\/wikis\\/(?<id>[^/]+)\\/chown$/, handler: this.chownWiki.bind(this) },\n { method: 'POST', pattern: /^\\/wikis\\/(?<id>[^/]+)\\/api-key$/, handler: this.setApiKey.bind(this) },\n { method: 'POST', pattern: /^\\/wikis\\/(?<id>[^/]+)\\/credentials$/, handler: this.setCredentials.bind(this) },\n { method: 'POST', pattern: /^\\/wikis\\/(?<id>[^/]+)\\/jobs$/, handler: this.submitJob.bind(this) },\n { method: 'GET', pattern: /^\\/wikis\\/(?<id>[^/]+)\\/jobs\\/(?<jobId>\\d+)$/, handler: this.getJob.bind(this) },\n { method: 'GET', pattern: /^\\/wikis\\/(?<id>[^/]+)\\/jobs$/, handler: this.listJobs.bind(this) },\n { method: 'GET', pattern: /^\\/wikis\\/(?<id>[^/]+)\\/logs$/, handler: this.getAuditLog.bind(this) },\n { method: 'POST', pattern: /^\\/wikis\\/(?<id>[^/]+)\\/ingest-file$/, handler: this.receiveFile.bind(this) },\n ];\n }\n\n async handle(method: string, path: string, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n for (const route of this.routes) {\n if (route.method !== method) continue;\n const match = path.match(route.pattern);\n if (match) {\n return route.handler(match.groups ?? {}, body, ctx);\n }\n }\n\n return { status: 404, body: { ok: false, error: 'Not found' } };\n }\n\n // \u2500\u2500 Wiki CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async createWiki(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const b = requireBody(body);\n const id = b.id as string | undefined;\n const name = b.name as string | undefined;\n\n if (!id || !WIKI_ID_PATTERN.test(id)) {\n throw new ValidationError(\n `Invalid wiki ID '${id}'. Must be 3-64 chars, lowercase alphanumeric and hyphens, ` +\n 'cannot start or end with a hyphen.'\n );\n }\n\n if (this.db.getWiki(id)) {\n throw new WikiExistsError(id);\n }\n\n const wiki = this.db.createWiki(id, name ?? id, ctx.callerUid);\n this.scaffold.create(id);\n this.namespace.validateWiki(id);\n this.db.logAudit(id, 'wiki.created');\n\n return { status: 201, body: { ok: true, data: wiki } };\n }\n\n private async listWikis(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikis = this.db.listWikis(ctx.callerUid);\n return { status: 200, body: { ok: true, data: wikis } };\n }\n\n private async getWiki(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wiki = this.requireWiki(params['id']!, ctx.callerUid);\n const pendingJobs = this.db.getPendingJobCount(wiki.id);\n return {\n status: 200,\n body: { ok: true, data: { ...wiki, pending_jobs: pendingJobs } },\n };\n }\n\n private async destroyWiki(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n this.requireWiki(wikiId, ctx.callerUid);\n\n const keepData = body && typeof body === 'object' && 'keepData' in body\n ? Boolean((body as { keepData: unknown }).keepData)\n : false;\n\n this.scaffold.destroy(wikiId, keepData);\n this.db.deleteWiki(wikiId);\n\n return { status: 200, body: { ok: true } };\n }\n\n private async chownWiki(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n\n // Root (uid 0) can chown any wiki; otherwise only the current owner can transfer\n const wiki = this.db.getWiki(wikiId);\n if (!wiki) throw new WikiNotFoundError(wikiId);\n if (ctx.callerUid !== 0 && wiki.owner_uid !== ctx.callerUid) {\n throw new ForbiddenError(wikiId);\n }\n\n const b = requireBody(body);\n const newOwnerUid = b.uid as number | undefined;\n if (newOwnerUid === undefined || typeof newOwnerUid !== 'number' || !Number.isInteger(newOwnerUid) || newOwnerUid < 0) {\n throw new ValidationError('uid (non-negative integer) is required');\n }\n\n const updated = this.db.chownWiki(wikiId, newOwnerUid);\n this.db.logAudit(wikiId, 'wiki.chown', `uid ${ctx.callerUid} \u2192 ${newOwnerUid}`);\n\n return { status: 200, body: { ok: true, data: updated } };\n }\n\n private async updateConfig(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n this.requireWiki(wikiId, ctx.callerUid);\n\n const config = requireBody(body) as WikiConfig;\n\n // Handle allowed_tools separately \u2014 validated and written to disk\n if (config.allowed_tools !== undefined) {\n if (!Array.isArray(config.allowed_tools)) {\n throw new ValidationError('allowed_tools must be an array of tool names');\n }\n const invalid = config.allowed_tools.filter(t => !ALLOWED_TOOLS_WHITELIST.has(t));\n if (invalid.length > 0) {\n const allowed = [...ALLOWED_TOOLS_WHITELIST].filter(t => !BASE_ALLOWED_TOOLS.includes(t));\n throw new ValidationError(\n `Invalid tools: ${invalid.join(', ')}. ` +\n `Allowed extras: ${allowed.join(', ')}`\n );\n }\n this.scaffold.writeAllowedTools(wikiId, config.allowed_tools);\n this.db.logAudit(wikiId, 'wiki.allowed_tools_updated', JSON.stringify(config.allowed_tools));\n }\n\n // Pass remaining DB-backed fields\n const { allowed_tools: _, ...dbConfig } = config;\n if (Object.keys(dbConfig).length > 0) {\n const wiki = this.db.updateWiki(wikiId, dbConfig);\n this.db.logAudit(wikiId, 'wiki.config_updated', JSON.stringify(dbConfig));\n return { status: 200, body: { ok: true, data: wiki } };\n }\n\n const wiki = this.db.getWiki(wikiId);\n return { status: 200, body: { ok: true, data: wiki } };\n }\n\n // \u2500\u2500 Auth \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async setApiKey(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n this.requireWiki(wikiId, ctx.callerUid);\n\n const b = requireBody(body);\n const key = b.key as string | undefined;\n if (!key || typeof key !== 'string') {\n throw new ValidationError('API key is required');\n }\n\n this.auth.setApiKey(wikiId, key);\n this.db.logAudit(wikiId, 'wiki.api_key_set');\n\n return { status: 200, body: { ok: true } };\n }\n\n private async setCredentials(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n this.requireWiki(wikiId, ctx.callerUid);\n\n const b = requireBody(body);\n const credentials = b.credentials as string | undefined;\n if (!credentials || typeof credentials !== 'string') {\n throw new ValidationError('credentials (JSON string) is required');\n }\n\n // Validate it's actually JSON\n try {\n JSON.parse(credentials);\n } catch {\n throw new ValidationError('credentials must be valid JSON');\n }\n\n this.auth.setCredentials(wikiId, credentials);\n this.db.logAudit(wikiId, 'wiki.credentials_set');\n\n return { status: 200, body: { ok: true } };\n }\n\n // \u2500\u2500 Jobs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async submitJob(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n this.requireWiki(wikiId, ctx.callerUid);\n\n const b = requireBody(body);\n const type = b.type as string;\n const payload = b.payload as object | undefined;\n if (!type || !isValidJobType(type)) {\n throw new ValidationError(`Invalid job type '${type}'. Must be one of: ingest, query, lint`);\n }\n\n const job = this.db.createJob(wikiId, type, payload ?? {});\n this.queue.notify(wikiId);\n this.db.logAudit(wikiId, `job.${type}.submitted`, `job #${job.id}`);\n\n // If wait mode, poll until job completes\n if (ctx.wait) {\n const result = await this.waitForJob(job.id);\n return { status: 200, body: { ok: true, data: result } };\n }\n\n return { status: 202, body: { ok: true, data: job } };\n }\n\n private async getJob(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n this.requireWiki(wikiId, ctx.callerUid);\n const jobId = Number(params['jobId']);\n const job = this.db.getJob(jobId);\n if (!job || job.wiki_id !== wikiId) throw new JobNotFoundError(jobId);\n return { status: 200, body: { ok: true, data: job } };\n }\n\n private async listJobs(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n this.requireWiki(wikiId, ctx.callerUid);\n const jobs = this.db.listJobs(wikiId, { limit: 50 });\n return { status: 200, body: { ok: true, data: jobs } };\n }\n\n // \u2500\u2500 Audit \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async getAuditLog(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n this.requireWiki(wikiId, ctx.callerUid);\n const log = this.db.getAuditLog(wikiId);\n return { status: 200, body: { ok: true, data: log } };\n }\n\n // \u2500\u2500 File upload \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async receiveFile(params: Record<string, string>, body: unknown, ctx: RouteContext): Promise<RouteResponse> {\n const wikiId = params['id']!;\n this.requireWiki(wikiId, ctx.callerUid);\n\n const b = requireBody(body);\n const filename = b.filename as string | undefined;\n const content = b.content as string | undefined;\n if (!filename || typeof filename !== 'string' || !content || typeof content !== 'string') {\n throw new ValidationError('filename (string) and content (base64 string) are required');\n }\n\n const buffer = Buffer.from(content, 'base64');\n const stored = this.scaffold.writeRawFile(wikiId, filename, buffer);\n\n return { status: 201, body: { ok: true, data: { filename: stored } } };\n }\n\n // \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private requireWiki(wikiId: string, callerUid: number) {\n const wiki = this.db.getWiki(wikiId);\n if (!wiki) throw new WikiNotFoundError(wikiId);\n if (wiki.owner_uid !== callerUid) throw new ForbiddenError(wikiId);\n return wiki;\n }\n\n private waitForJob(jobId: number, timeoutMs: number = 10 * 60_000): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs;\n const check = () => {\n const job = this.db.getJob(jobId);\n if (!job || job.status === 'completed' || job.status === 'failed') {\n resolve(job);\n } else if (Date.now() > deadline) {\n resolve(job); // return current state rather than error \u2014 client can poll again\n } else {\n setTimeout(check, JOB_POLL_INTERVAL_MS);\n }\n };\n check();\n });\n }\n}\n\nfunction isValidJobType(type: string): type is JobType {\n return type === 'ingest' || type === 'query' || type === 'lint';\n}\n\n/**\n * Validate that a request body is a non-null object.\n * Throws ValidationError if not.\n */\nfunction requireBody(body: unknown): Record<string, unknown> {\n if (!body || typeof body !== 'object' || Array.isArray(body)) {\n throw new ValidationError('Request body must be a JSON object');\n }\n return body as Record<string, unknown>;\n}\n", "import { createRequire } from 'node:module';\nimport type { Socket } from 'node:net';\n\nconst require = createRequire(import.meta.url);\n\ninterface PeerCred {\n uid: number;\n gid: number;\n pid: number;\n}\n\n// Load the native N-API addon compiled by node-gyp\nconst addon: { getPeerCred(fd: number): PeerCred } = require('../../build/Release/peercred.node');\n\n/**\n * Extract the kernel-verified credentials (uid, gid, pid) of the peer\n * process connected to a Unix domain socket.\n *\n * Uses SO_PEERCRED \u2014 the kernel fills this in at connect() time,\n * so it cannot be spoofed by the client.\n */\nexport function getPeerCred(socket: Socket): PeerCred {\n const handle = (socket as any)._handle;\n if (!handle || typeof handle.fd !== 'number' || handle.fd < 0) {\n throw new Error('Cannot get file descriptor from socket');\n }\n return addon.getPeerCred(handle.fd);\n}\n", "import { createServer, type IncomingMessage, type ServerResponse, type Server } from 'node:http';\nimport type { Socket } from 'node:net';\nimport { existsSync, unlinkSync, chmodSync } from 'node:fs';\nimport type { RouteHandler } from './routes.js';\nimport type { ApiResponse } from '../lib/types.js';\nimport { getPeerCred } from './peercred.js';\n\nexport class DaemonServer {\n private server: Server;\n private socketUids = new WeakMap<Socket, number>();\n\n constructor(\n private socketPath: string,\n private routes: RouteHandler,\n ) {\n this.server = createServer((req, res) => {\n this.handleRequest(req, res).catch(err => {\n console.error('[server] Unhandled error:', err);\n if (!res.headersSent) {\n sendJson(res, 500, { ok: false, error: 'Internal server error' });\n }\n });\n });\n\n // Extract peer credentials at connection time (before any HTTP parsing).\n // SO_PEERCRED is set by the kernel at connect() \u2014 it's immutable and unspoofable.\n this.server.on('connection', (socket: Socket) => {\n try {\n const cred = getPeerCred(socket);\n this.socketUids.set(socket, cred.uid);\n } catch (err) {\n console.error('[server] Failed to get peer credentials:', err);\n socket.destroy();\n }\n });\n }\n\n async start(): Promise<void> {\n // Remove stale socket file\n if (existsSync(this.socketPath)) {\n unlinkSync(this.socketPath);\n }\n\n return new Promise((resolve, reject) => {\n this.server.on('error', reject);\n this.server.listen(this.socketPath, () => {\n chmodSync(this.socketPath, 0o666);\n console.log(`[server] Listening on ${this.socketPath}`);\n resolve();\n });\n });\n }\n\n async stop(): Promise<void> {\n return new Promise((resolve) => {\n this.server.close(() => {\n if (existsSync(this.socketPath)) {\n try { unlinkSync(this.socketPath); } catch { /* ignore */ }\n }\n resolve();\n });\n });\n }\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const method = (req.method ?? 'GET').toUpperCase();\n const url = req.url ?? '/';\n\n // Parse body for POST/PUT\n let body: unknown = undefined;\n if (method === 'POST' || method === 'PUT') {\n body = await readBody(req);\n }\n\n // Check for streaming (wait) mode on job submission\n const urlObj = new URL(url, 'http://localhost');\n const wait = urlObj.searchParams.get('wait') === 'true';\n\n // Retrieve the caller's UID from the underlying socket\n const socket = req.socket as Socket;\n const callerUid = this.socketUids.get(socket);\n if (callerUid === undefined) {\n sendJson(res, 500, { ok: false, error: 'Could not determine caller identity' });\n return;\n }\n\n try {\n const result = await this.routes.handle(method, urlObj.pathname, body, {\n wait,\n res, // pass response for streaming login output\n callerUid,\n });\n\n // If the route already handled the response (e.g., streaming), skip\n if (res.writableEnded) return;\n\n sendJson(res, result.status, result.body);\n } catch (err) {\n if (res.writableEnded) return;\n\n if (err && typeof err === 'object' && 'statusCode' in err) {\n const memexErr = err as { statusCode: number; message: string; code: string };\n sendJson(res, memexErr.statusCode, {\n ok: false,\n error: memexErr.message,\n });\n } else {\n console.error('[server] Error handling request:', err);\n sendJson(res, 500, { ok: false, error: 'Internal server error' });\n }\n }\n }\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: ApiResponse): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n });\n res.end(json);\n}\n\n// 100 MB \u2014 enough for large PDFs/images encoded as base64\nconst MAX_BODY_BYTES = 100 * 1024 * 1024;\n\nasync function readBody(req: IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let totalSize = 0;\n\n req.on('data', (chunk: Buffer) => {\n totalSize += chunk.length;\n if (totalSize > MAX_BODY_BYTES) {\n req.destroy();\n reject(new Error(`Request body exceeds ${MAX_BODY_BYTES} bytes`));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n const raw = Buffer.concat(chunks).toString('utf-8');\n if (!raw) {\n resolve(undefined);\n return;\n }\n try {\n resolve(JSON.parse(raw));\n } catch {\n reject(new Error('Invalid JSON body'));\n }\n });\n req.on('error', reject);\n });\n}\n", "import { mkdirSync } from 'node:fs';\nimport { Database } from './daemon/db.js';\nimport { NamespaceManager } from './daemon/namespace.js';\nimport { WikiScaffold } from './daemon/scaffold.js';\nimport { AuthManager } from './daemon/auth.js';\nimport { ClaudeRunner } from './daemon/runner.js';\nimport { QueueManager } from './daemon/queue.js';\nimport { RouteHandler } from './daemon/routes.js';\nimport { DaemonServer } from './daemon/server.js';\nimport {\n DATA_DIR, RUN_DIR, SOCKET_PATH, DB_PATH, WIKIS_DIR,\n AUTO_LINT_INTERVAL,\n} from './lib/constants.js';\n\nexport async function startDaemon(): Promise<void> {\n console.log('[memex] Starting daemon...');\n\n // \u2500\u2500 Ensure directories \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n for (const dir of [DATA_DIR, WIKIS_DIR, RUN_DIR]) {\n mkdirSync(dir, { recursive: true });\n }\n\n // \u2500\u2500 Database \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const db = new Database(DB_PATH);\n db.initialize();\n\n const staleCount = db.resetStaleJobs();\n if (staleCount > 0) {\n console.log(`[memex] Reset ${staleCount} stale job(s) from previous run`);\n }\n\n // \u2500\u2500 Namespace manager \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const namespace = new NamespaceManager(WIKIS_DIR);\n namespace.checkCapabilities();\n namespace.ensureDirectories();\n\n // \u2500\u2500 Components \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const scaffold = new WikiScaffold(WIKIS_DIR);\n const auth = new AuthManager(WIKIS_DIR, process.env['ANTHROPIC_API_KEY']);\n const runner = new ClaudeRunner(namespace, auth, db, WIKIS_DIR);\n const queue = new QueueManager(db, runner, AUTO_LINT_INTERVAL);\n const routes = new RouteHandler(db, scaffold, namespace, queue, auth);\n const server = new DaemonServer(SOCKET_PATH, routes);\n\n // \u2500\u2500 Start \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n await server.start();\n queue.start();\n\n const wikiCount = db.listWikis().length;\n console.log(`[memex] Daemon ready (PID ${process.pid})`);\n console.log(`[memex] Socket: ${SOCKET_PATH}`);\n console.log(`[memex] Data: ${DATA_DIR}`);\n console.log(`[memex] Wikis: ${wikiCount}`);\n\n // \u2500\u2500 Graceful shutdown \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const shutdown = async (signal: string) => {\n console.log(`\\n[memex] Received ${signal}, shutting down...`);\n\n await queue.stop();\n await server.stop();\n db.close();\n\n console.log('[memex] Shutdown complete.');\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n}\n", "#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { serveCommand } from './cli/commands/serve.js';\nimport { createCommand } from './cli/commands/create.js';\nimport { destroyCommand } from './cli/commands/destroy.js';\nimport { configCommand } from './cli/commands/config.js';\nimport { loginCommand } from './cli/commands/login.js';\nimport { ingestCommand } from './cli/commands/ingest.js';\nimport { queryCommand } from './cli/commands/query.js';\nimport { lintCommand } from './cli/commands/lint.js';\nimport { logsCommand } from './cli/commands/logs.js';\nimport { listCommand } from './cli/commands/list.js';\nimport { chownCommand } from './cli/commands/chown.js';\nimport { statusCommand } from './cli/commands/status.js';\n\nconst program = new Command();\n\nprogram\n .name('memex')\n .description('Isolated, queued claude -p runtime for persistent knowledge bases')\n .version('0.1.0');\n\nprogram.addCommand(serveCommand);\nprogram.addCommand(createCommand);\nprogram.addCommand(destroyCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(loginCommand);\nprogram.addCommand(ingestCommand);\nprogram.addCommand(queryCommand);\nprogram.addCommand(lintCommand);\nprogram.addCommand(logsCommand);\nprogram.addCommand(listCommand);\nprogram.addCommand(chownCommand);\nprogram.addCommand(statusCommand);\n\nprogram.parseAsync().catch((err) => {\n console.error(err.message ?? err);\n process.exit(1);\n});\n", "import { Command } from 'commander';\n\nexport const serveCommand = new Command('serve')\n .description('Start the memex daemon')\n .action(async () => {\n try {\n const { startDaemon } = await import('../../daemon.js');\n await startDaemon();\n } catch (err) {\n console.error(err instanceof Error ? err.message : err);\n process.exit(1);\n }\n });\n", "import { Command } from 'commander';\nimport { MemexClient } from '../client.js';\n\nexport const createCommand = new Command('create')\n .description('Create a new wiki')\n .argument('<wikiId>', 'Wiki identifier (lowercase alphanumeric + hyphens, 3-64 chars)')\n .option('--name <name>', 'Display name for the wiki')\n .action(async (wikiId: string, opts: { name?: string }) => {\n const client = new MemexClient();\n const resp = await client.createWiki(wikiId, opts.name);\n\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n\n const wiki = resp.data as { id: string; name: string; created_at: string };\n console.log(`Created wiki '${wiki.id}' (${wiki.name})`);\n console.log(`\\nNext steps:`);\n console.log(` memex login ${wiki.id} # authenticate with Claude`);\n console.log(` memex config ${wiki.id} --edit # customize wiki agent`);\n console.log(` memex ingest ${wiki.id} file.md # add content`);\n });\n", "import { request as httpRequest, type RequestOptions } from 'node:http';\nimport { readFileSync } from 'node:fs';\nimport { basename } from 'node:path';\nimport type {\n ApiResponse, Wiki, WikiConfig, QueueJob, JobType, AuditEntry,\n} from '../lib/types.js';\nimport { SOCKET_PATH, JOB_POLL_INTERVAL_MS } from '../lib/constants.js';\nimport { DaemonNotRunningError } from '../lib/errors.js';\n\nexport class MemexClient {\n constructor(private socketPath: string = SOCKET_PATH) {}\n\n // \u2500\u2500 Generic request \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async request<T = unknown>(method: string, path: string, body?: unknown): Promise<ApiResponse<T>> {\n return new Promise((resolve, reject) => {\n const opts: RequestOptions = {\n socketPath: this.socketPath,\n method,\n path,\n headers: { 'Content-Type': 'application/json' },\n };\n\n const req = httpRequest(opts, (res) => {\n const chunks: Buffer[] = [];\n res.on('data', (chunk: Buffer) => chunks.push(chunk));\n res.on('end', () => {\n const raw = Buffer.concat(chunks).toString('utf-8');\n try {\n resolve(JSON.parse(raw) as ApiResponse<T>);\n } catch {\n resolve({ ok: false, error: raw } as ApiResponse<T>);\n }\n });\n });\n\n req.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'ECONNREFUSED' || err.code === 'ENOENT') {\n reject(new DaemonNotRunningError());\n } else {\n reject(err);\n }\n });\n\n if (body !== undefined) {\n req.write(JSON.stringify(body));\n }\n req.end();\n });\n }\n\n /**\n * Make a request and stream the raw response body chunks.\n * Used for login flow where we stream CLI output.\n */\n async stream(method: string, path: string, body?: unknown): Promise<AsyncIterable<string>> {\n return new Promise((resolve, reject) => {\n const opts: RequestOptions = {\n socketPath: this.socketPath,\n method,\n path,\n headers: { 'Content-Type': 'application/json' },\n };\n\n const req = httpRequest(opts, (res) => {\n // Track response errors so the async iterator can propagate them\n let responseError: Error | null = null;\n res.on('error', (err) => { responseError = err; });\n\n const iterable: AsyncIterable<string> = {\n [Symbol.asyncIterator]() {\n return {\n next() {\n return new Promise((resolveNext, rejectNext) => {\n if (responseError) {\n rejectNext(responseError);\n return;\n }\n const onData = (chunk: Buffer) => {\n res.removeListener('end', onEnd);\n res.removeListener('error', onError);\n resolveNext({ value: chunk.toString('utf-8'), done: false });\n };\n const onEnd = () => {\n res.removeListener('data', onData);\n res.removeListener('error', onError);\n resolveNext({ value: '', done: true });\n };\n const onError = (err: Error) => {\n res.removeListener('data', onData);\n res.removeListener('end', onEnd);\n rejectNext(err);\n };\n res.once('data', onData);\n res.once('end', onEnd);\n res.once('error', onError);\n });\n },\n };\n },\n };\n resolve(iterable);\n });\n\n req.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'ECONNREFUSED' || err.code === 'ENOENT') {\n reject(new DaemonNotRunningError());\n } else {\n reject(err);\n }\n });\n\n if (body !== undefined) {\n req.write(JSON.stringify(body));\n }\n req.end();\n });\n }\n\n // \u2500\u2500 Convenience methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n createWiki(id: string, name?: string) {\n return this.request<Wiki>('POST', '/wikis', { id, name });\n }\n\n listWikis() {\n return this.request<Wiki[]>('GET', '/wikis');\n }\n\n getWiki(id: string) {\n return this.request<Wiki & { pending_jobs: number }>('GET', `/wikis/${id}`);\n }\n\n destroyWiki(id: string, keepData: boolean = false) {\n return this.request('DELETE', `/wikis/${id}`, { keepData });\n }\n\n updateConfig(wikiId: string, config: WikiConfig) {\n return this.request<Wiki>('PUT', `/wikis/${wikiId}/config`, config);\n }\n\n chownWiki(wikiId: string, uid: number) {\n return this.request<Wiki>('POST', `/wikis/${wikiId}/chown`, { uid });\n }\n\n setApiKey(wikiId: string, key: string) {\n return this.request('POST', `/wikis/${wikiId}/api-key`, { key });\n }\n\n setCredentials(wikiId: string, credentials: string) {\n return this.request('POST', `/wikis/${wikiId}/credentials`, { credentials });\n }\n\n submitJob(wikiId: string, type: JobType, payload: object, wait: boolean = false) {\n const path = `/wikis/${wikiId}/jobs` + (wait ? '?wait=true' : '');\n return this.request<QueueJob>('POST', path, { type, payload });\n }\n\n getJob(wikiId: string, jobId: number) {\n return this.request<QueueJob>('GET', `/wikis/${wikiId}/jobs/${jobId}`);\n }\n\n listJobs(wikiId: string) {\n return this.request<QueueJob[]>('GET', `/wikis/${wikiId}/jobs`);\n }\n\n getAuditLog(wikiId: string, limit?: number) {\n const path = `/wikis/${wikiId}/logs` + (limit ? `?limit=${limit}` : '');\n return this.request<AuditEntry[]>('GET', path);\n }\n\n /**\n * Upload a local file to the daemon for ingestion into a wiki's raw/ directory.\n */\n async uploadFile(wikiId: string, localPath: string): Promise<ApiResponse<{ filename: string }>> {\n const content = readFileSync(localPath);\n const filename = basename(localPath);\n return this.request<{ filename: string }>('POST', `/wikis/${wikiId}/ingest-file`, {\n filename,\n content: content.toString('base64'),\n });\n }\n\n /**\n * Submit a job and poll until it completes.\n */\n async waitForJob(wikiId: string, jobId: number, onPoll?: (job: QueueJob) => void): Promise<QueueJob> {\n while (true) {\n const resp = await this.getJob(wikiId, jobId);\n if (!resp.ok || !resp.data) {\n throw new Error(resp.error ?? 'Failed to get job status');\n }\n\n const job = resp.data;\n if (onPoll) onPoll(job);\n\n if (job.status === 'completed' || job.status === 'failed') {\n return job;\n }\n\n await sleep(JOB_POLL_INTERVAL_MS);\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n", "import { Command } from 'commander';\nimport { createInterface } from 'node:readline';\nimport { MemexClient } from '../client.js';\n\nexport const destroyCommand = new Command('destroy')\n .description('Destroy a wiki and its data')\n .argument('<wikiId>', 'Wiki to destroy')\n .option('--keep-data', 'Keep wiki files on disk (only remove registration)')\n .option('-y, --yes', 'Skip confirmation prompt')\n .action(async (wikiId: string, opts: { keepData?: boolean; yes?: boolean }) => {\n if (!opts.yes) {\n const confirmed = await confirm(\n `This will destroy wiki '${wikiId}'${opts.keepData ? ' (keeping data)' : ' and ALL its data'}. Continue? [y/N] `\n );\n if (!confirmed) {\n console.log('Aborted.');\n process.exit(0);\n }\n }\n\n const client = new MemexClient();\n const resp = await client.destroyWiki(wikiId, opts.keepData ?? false);\n\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n\n console.log(`Destroyed wiki '${wikiId}'${opts.keepData ? ' (data preserved)' : ''}`);\n });\n\nfunction confirm(question: string): Promise<boolean> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');\n });\n });\n}\n", "import { Command } from 'commander';\nimport { createInterface } from 'node:readline';\nimport { execFileSync } from 'node:child_process';\nimport { MemexClient } from '../client.js';\nimport { WIKIS_DIR, ALLOWED_TOOLS_WHITELIST, BASE_ALLOWED_TOOLS } from '../../lib/constants.js';\nimport { join } from 'node:path';\n\nexport const configCommand = new Command('config')\n .description('Configure a wiki')\n .argument('<wikiId>', 'Wiki to configure')\n .option('--edit', 'Open .claude.md in $EDITOR')\n .option('--set-key', 'Set the API key for this wiki')\n .option('--model <model>', 'Set the default model (e.g., sonnet, opus, haiku)')\n .option('--allowed-tools <tools>', 'Set allowed tools (comma-separated, e.g., WebSearch,WebFetch)')\n .option('--list-tools', 'Show available tools and current configuration')\n .action(async (wikiId: string, opts: { edit?: boolean; setKey?: boolean; model?: string; allowedTools?: string; listTools?: boolean }) => {\n const client = new MemexClient();\n\n // Verify wiki exists\n const wikiResp = await client.getWiki(wikiId);\n if (!wikiResp.ok) {\n console.error(`Error: ${wikiResp.error}`);\n process.exit(1);\n }\n\n if (opts.edit) {\n const editor = process.env['EDITOR'] || process.env['VISUAL'] || 'vi';\n const claudeMdPath = join(WIKIS_DIR, wikiId, '.claude.md');\n try {\n execFileSync(editor, [claudeMdPath], { stdio: 'inherit' });\n console.log(`Updated .claude.md for '${wikiId}'`);\n } catch {\n console.error(`Failed to open editor. Set $EDITOR environment variable.`);\n process.exit(1);\n }\n return;\n }\n\n if (opts.setKey) {\n const key = await promptSecret('API key: ');\n const resp = await client.setApiKey(wikiId, key);\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n console.log(`API key set for '${wikiId}'`);\n return;\n }\n\n if (opts.listTools) {\n const extras = [...ALLOWED_TOOLS_WHITELIST].filter(t => !BASE_ALLOWED_TOOLS.includes(t));\n console.log(`Base tools (always enabled): ${BASE_ALLOWED_TOOLS.join(', ')}`);\n console.log(`Available extras: ${extras.join(', ')}`);\n console.log(`\\nTo enable extras: memex config ${wikiId} --allowed-tools ${extras.join(',')}`);\n return;\n }\n\n if (opts.allowedTools !== undefined) {\n const tools = opts.allowedTools\n ? opts.allowedTools.split(',').map(t => t.trim()).filter(Boolean)\n : [];\n const resp = await client.updateConfig(wikiId, { allowed_tools: tools });\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n if (tools.length === 0) {\n console.log(`Allowed tools reset to base set for '${wikiId}'`);\n } else {\n console.log(`Allowed tools set for '${wikiId}': ${tools.join(', ')}`);\n }\n return;\n }\n\n if (opts.model) {\n const resp = await client.updateConfig(wikiId, { default_model: opts.model });\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n console.log(`Model set to '${opts.model}' for '${wikiId}'`);\n return;\n }\n\n // No option specified \u2014 show current config\n const wiki = wikiResp.data!;\n console.log(`Wiki: ${wiki.id}`);\n console.log(`Name: ${wiki.name}`);\n console.log(`Model: ${wiki.default_model}`);\n console.log(`Created: ${wiki.created_at}`);\n console.log(`\\nConfig file: ${join(WIKIS_DIR, wikiId, '.claude.md')}`);\n });\n\nfunction promptSecret(prompt: string): Promise<string> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n // Disable echo for secret input\n if (process.stdin.isTTY) {\n process.stdout.write(prompt);\n const stdin = process.stdin;\n stdin.setRawMode(true);\n stdin.resume();\n let input = '';\n const onData = (chunk: Buffer) => {\n const char = chunk.toString('utf-8');\n if (char === '\\n' || char === '\\r') {\n stdin.setRawMode(false);\n stdin.removeListener('data', onData);\n process.stdout.write('\\n');\n rl.close();\n resolve(input);\n } else if (char === '\\x7f' || char === '\\x08') {\n // Backspace\n if (input.length > 0) {\n input = input.slice(0, -1);\n }\n } else if (char === '\\x03') {\n // Ctrl+C\n rl.close();\n process.exit(0);\n } else {\n input += char;\n }\n };\n stdin.on('data', onData);\n } else {\n // Non-TTY (piped input)\n rl.question(prompt, (answer) => {\n rl.close();\n resolve(answer);\n });\n }\n });\n}\n", "import { Command } from 'commander';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { MemexClient } from '../client.js';\n\nconst DEFAULT_CREDS_PATH = join(homedir(), '.claude', '.credentials.json');\n\nexport const loginCommand = new Command('login')\n .description('Copy Claude credentials into a wiki')\n .argument('<wikiId>', 'Wiki to authenticate')\n .option('--credentials <path>', 'Path to .credentials.json', DEFAULT_CREDS_PATH)\n .option('--api-key <key>', 'Use an API key instead of OAuth credentials')\n .action(async (wikiId: string, opts: { credentials: string; apiKey?: string }) => {\n const client = new MemexClient();\n\n const wikiResp = await client.getWiki(wikiId);\n if (!wikiResp.ok) {\n console.error(`Error: ${wikiResp.error}`);\n process.exit(1);\n }\n\n // API key mode\n if (opts.apiKey) {\n const resp = await client.setApiKey(wikiId, opts.apiKey);\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n console.log(`API key stored for wiki '${wikiId}'.`);\n return;\n }\n\n // Credentials file mode (default)\n const credsPath = opts.credentials;\n if (!existsSync(credsPath)) {\n console.error(`Error: Credentials file not found: ${credsPath}`);\n console.error(`\\nRun 'claude auth login' first, or pass --credentials <path>`);\n process.exit(1);\n }\n\n const credentials = readFileSync(credsPath, 'utf-8');\n\n try {\n JSON.parse(credentials);\n } catch {\n console.error(`Error: ${credsPath} is not valid JSON`);\n process.exit(1);\n }\n\n const resp = await client.setCredentials(wikiId, credentials);\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n\n console.log(`Credentials copied from ${credsPath} to wiki '${wikiId}'.`);\n });\n", "import { Command } from 'commander';\nimport { existsSync } from 'node:fs';\nimport { MemexClient } from '../client.js';\n\nexport const ingestCommand = new Command('ingest')\n .description('Ingest source files into a wiki')\n .argument('<wikiId>', 'Target wiki')\n .argument('<files...>', 'Files to ingest (pdf, md, html, txt, images, etc.)')\n .option('--async', 'Return job ID immediately instead of waiting')\n .action(async (wikiId: string, files: string[], opts: { async?: boolean }) => {\n const client = new MemexClient();\n\n // Validate files exist locally\n for (const file of files) {\n if (!existsSync(file)) {\n console.error(`File not found: ${file}`);\n process.exit(1);\n }\n }\n\n // Upload each file to the daemon\n const storedFiles: string[] = [];\n for (const file of files) {\n process.stdout.write(`Uploading ${file}...`);\n const resp = await client.uploadFile(wikiId, file);\n if (!resp.ok) {\n console.error(` failed: ${resp.error}`);\n process.exit(1);\n }\n storedFiles.push(resp.data!.filename);\n console.log(` done (${resp.data!.filename})`);\n }\n\n // Submit ingest job\n const jobResp = await client.submitJob(wikiId, 'ingest', { files: storedFiles });\n if (!jobResp.ok) {\n console.error(`Error: ${jobResp.error}`);\n process.exit(1);\n }\n\n const job = jobResp.data!;\n console.log(`\\nIngest job #${job.id} submitted`);\n\n if (opts.async) {\n console.log(`Check status: memex status ${wikiId} ${job.id}`);\n return;\n }\n\n // Wait for completion\n process.stdout.write('Processing');\n const result = await client.waitForJob(wikiId, job.id, () => {\n process.stdout.write('.');\n });\n console.log();\n\n if (result.status === 'completed') {\n const parsed = safeParseResult(result.result);\n console.log('\\nIngest complete.');\n if (parsed?.output) {\n console.log(parsed.output);\n }\n } else {\n console.error('\\nIngest failed.');\n const parsed = safeParseResult(result.result);\n if (parsed) {\n console.error(parsed.error ?? parsed.output ?? result.result);\n }\n process.exit(1);\n }\n });\n\nfunction safeParseResult(raw: string | null): Record<string, string> | null {\n if (!raw) return null;\n try {\n return JSON.parse(raw);\n } catch {\n return { output: raw };\n }\n}\n", "import { Command } from 'commander';\nimport { MemexClient } from '../client.js';\n\nexport const queryCommand = new Command('query')\n .description('Ask a question against a wiki')\n .argument('<wikiId>', 'Target wiki')\n .argument('<question>', 'Question to ask')\n .option('--async', 'Return job ID immediately instead of waiting')\n .action(async (wikiId: string, question: string, opts: { async?: boolean }) => {\n const client = new MemexClient();\n\n const jobResp = await client.submitJob(wikiId, 'query', { question });\n if (!jobResp.ok) {\n console.error(`Error: ${jobResp.error}`);\n process.exit(1);\n }\n\n const job = jobResp.data!;\n\n if (opts.async) {\n console.log(`Query job #${job.id} submitted`);\n console.log(`Check status: memex status ${wikiId} ${job.id}`);\n return;\n }\n\n // Wait for completion\n process.stdout.write('Thinking');\n const result = await client.waitForJob(wikiId, job.id, () => {\n process.stdout.write('.');\n });\n console.log('\\n');\n\n if (result.status === 'completed') {\n const parsed = safeParseResult(result.result);\n console.log(parsed?.output ?? result.result ?? '(no output)');\n } else {\n console.error('Query failed.');\n const parsed = safeParseResult(result.result);\n console.error(parsed?.error ?? parsed?.output ?? result.result);\n process.exit(1);\n }\n });\n\nfunction safeParseResult(raw: string | null): Record<string, string> | null {\n if (!raw) return null;\n try {\n return JSON.parse(raw);\n } catch {\n return { output: raw };\n }\n}\n", "import { Command } from 'commander';\nimport { MemexClient } from '../client.js';\n\nexport const lintCommand = new Command('lint')\n .description('Run a maintenance health check on a wiki')\n .argument('<wikiId>', 'Target wiki')\n .option('--async', 'Return job ID immediately instead of waiting')\n .action(async (wikiId: string, opts: { async?: boolean }) => {\n const client = new MemexClient();\n\n const jobResp = await client.submitJob(wikiId, 'lint', {});\n if (!jobResp.ok) {\n console.error(`Error: ${jobResp.error}`);\n process.exit(1);\n }\n\n const job = jobResp.data!;\n\n if (opts.async) {\n console.log(`Lint job #${job.id} submitted`);\n console.log(`Check status: memex status ${wikiId} ${job.id}`);\n return;\n }\n\n process.stdout.write('Checking wiki health');\n const result = await client.waitForJob(wikiId, job.id, () => {\n process.stdout.write('.');\n });\n console.log('\\n');\n\n if (result.status === 'completed') {\n const parsed = safeParseResult(result.result);\n console.log(parsed?.output ?? result.result ?? '(no output)');\n } else {\n console.error('Lint failed.');\n const parsed = safeParseResult(result.result);\n console.error(parsed?.error ?? parsed?.output ?? result.result);\n process.exit(1);\n }\n });\n\nfunction safeParseResult(raw: string | null): Record<string, string> | null {\n if (!raw) return null;\n try {\n return JSON.parse(raw);\n } catch {\n return { output: raw };\n }\n}\n", "import { Command } from 'commander';\nimport { MemexClient } from '../client.js';\nimport type { AuditEntry } from '../../lib/types.js';\n\nexport const logsCommand = new Command('logs')\n .description('View audit log for a wiki')\n .argument('<wikiId>', 'Target wiki')\n .option('--tail <n>', 'Number of entries to show', '20')\n .action(async (wikiId: string, opts: { tail: string }) => {\n const client = new MemexClient();\n const limit = parseInt(opts.tail, 10) || 20;\n\n const resp = await client.getAuditLog(wikiId, limit);\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n\n const entries = (resp.data ?? []) as AuditEntry[];\n if (entries.length === 0) {\n console.log('No audit log entries.');\n return;\n }\n\n // Print in chronological order (API returns newest first)\n for (const entry of entries.reverse()) {\n const detail = entry.detail ? ` \u2014 ${entry.detail}` : '';\n console.log(`[${entry.created_at}] ${entry.action}${detail}`);\n }\n });\n", "import { Command } from 'commander';\nimport { MemexClient } from '../client.js';\nimport type { Wiki } from '../../lib/types.js';\n\nexport const listCommand = new Command('list')\n .description('List all wikis')\n .action(async () => {\n const client = new MemexClient();\n const resp = await client.listWikis();\n\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n\n const wikis = (resp.data ?? []) as Wiki[];\n if (wikis.length === 0) {\n console.log('No wikis. Create one with: memex create <wikiId>');\n return;\n }\n\n // Print as table\n const header = padRow('ID', 'NAME', 'MODEL', 'CREATED');\n console.log(header);\n console.log('-'.repeat(header.length));\n\n for (const wiki of wikis) {\n console.log(padRow(wiki.id, wiki.name, wiki.default_model, wiki.created_at));\n }\n });\n\nfunction padRow(id: string, name: string, model: string, created: string): string {\n return `${id.padEnd(24)} ${name.padEnd(24)} ${model.padEnd(10)} ${created}`;\n}\n", "import { Command } from 'commander';\nimport { MemexClient } from '../client.js';\nimport type { Wiki } from '../../lib/types.js';\n\nexport const chownCommand = new Command('chown')\n .description('Transfer wiki ownership to another user (by UID)')\n .argument('<wikiId>', 'Wiki identifier')\n .argument('<uid>', 'New owner UID (numeric)')\n .action(async (wikiId: string, uidStr: string) => {\n const uid = Number(uidStr);\n if (!Number.isInteger(uid) || uid < 0) {\n console.error(`Error: uid must be a non-negative integer, got '${uidStr}'`);\n process.exit(1);\n }\n\n const client = new MemexClient();\n const resp = await client.chownWiki(wikiId, uid);\n\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n\n const wiki = resp.data as Wiki;\n console.log(`Transferred wiki '${wiki.id}' to uid ${wiki.owner_uid}`);\n });\n", "import { Command } from 'commander';\nimport { MemexClient } from '../client.js';\nimport type { QueueJob } from '../../lib/types.js';\n\nexport const statusCommand = new Command('status')\n .description('Check job status for a wiki')\n .argument('<wikiId>', 'Target wiki')\n .argument('[jobId]', 'Specific job ID (omit to list recent jobs)')\n .action(async (wikiId: string, jobId?: string) => {\n const client = new MemexClient();\n\n if (jobId) {\n // Show single job\n const resp = await client.getJob(wikiId, parseInt(jobId, 10));\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n\n const job = resp.data as QueueJob;\n console.log(`Job #${job.id}`);\n console.log(` Type: ${job.type}`);\n console.log(` Status: ${job.status}`);\n console.log(` Created: ${job.created_at}`);\n if (job.started_at) console.log(` Started: ${job.started_at}`);\n if (job.completed_at) console.log(` Completed: ${job.completed_at}`);\n\n if (job.result) {\n try {\n const parsed = JSON.parse(job.result);\n if (parsed.output) {\n console.log(`\\nOutput:\\n${parsed.output}`);\n }\n if (parsed.error) {\n console.log(`\\nError:\\n${parsed.error}`);\n }\n if (parsed.duration_ms) {\n console.log(`\\nDuration: ${parsed.duration_ms}ms`);\n }\n } catch {\n console.log(`\\nResult: ${job.result}`);\n }\n }\n } else {\n // List recent jobs\n const resp = await client.listJobs(wikiId);\n if (!resp.ok) {\n console.error(`Error: ${resp.error}`);\n process.exit(1);\n }\n\n const jobs = (resp.data ?? []) as QueueJob[];\n if (jobs.length === 0) {\n console.log(`No jobs for wiki '${wikiId}'.`);\n return;\n }\n\n const header = padRow('ID', 'TYPE', 'STATUS', 'CREATED');\n console.log(header);\n console.log('-'.repeat(header.length));\n\n for (const job of jobs) {\n console.log(padRow(\n String(job.id),\n job.type,\n job.status,\n job.created_at,\n ));\n }\n }\n });\n\nfunction padRow(id: string, type: string, status: string, created: string): string {\n return `${id.padEnd(8)} ${type.padEnd(10)} ${status.padEnd(12)} ${created}`;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["mkdirSync", "existsSync", "join", "existsSync", "readFileSync", "writeFileSync", "mkdirSync", "join", "existsSync", "readFileSync", "join", "wiki", "require", "existsSync", "mkdirSync", "Command", "startDaemon", "Command", "readFileSync", "basename", "sleep", "Command", "Command", "Command", "Command", "createInterface", "execFileSync", "join", "Command", "execFileSync", "createInterface", "Command", "readFileSync", "existsSync", "join", "join", "Command", "resp", "existsSync", "readFileSync", "Command", "existsSync", "Command", "existsSync", "Command", "Command", "safeParseResult", "Command", "Command", "safeParseResult", "Command", "Command", "Command", "Command", "Command", "Command", "Command", "Command", "padRow", "Command"]
|
|
7
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wastedcode/memex",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Isolated, queued claude -p runtime for persistent knowledge bases",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20.0.0"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"memex": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"install": "node-gyp rebuild",
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"bundle": "node esbuild.config.js",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"clean": "rm -rf dist",
|
|
18
|
+
"prepublishOnly": "npm run build && npm run bundle"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/wastedcode/memex.git"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/wastedcode/memex#readme",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/wastedcode/memex/issues"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"memex",
|
|
30
|
+
"wiki",
|
|
31
|
+
"knowledge-base",
|
|
32
|
+
"claude",
|
|
33
|
+
"ai",
|
|
34
|
+
"daemon",
|
|
35
|
+
"cli"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"files": [
|
|
42
|
+
"dist"
|
|
43
|
+
],
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"better-sqlite3": "^12.8.0",
|
|
46
|
+
"commander": "^14.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
50
|
+
"@types/node": "^22.15.0",
|
|
51
|
+
"esbuild": "^0.28.0",
|
|
52
|
+
"typescript": "^5.7.3"
|
|
53
|
+
}
|
|
54
|
+
}
|