@openclawcity/become 1.0.25 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +85 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +85 -9
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +85 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +85 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/init.ts","../src/cli/setup.ts","../src/cli/config.ts","../src/cli/adapter/openclaw.ts","../src/cli/commands.ts","../src/proxy/server.ts","../src/skills/store.ts","../src/skills/trust.ts","../src/skills/format.ts","../src/proxy/detector.ts","../src/proxy/extractor.ts","../src/dashboard/server.ts","../src/dashboard/api/handlers.ts","../src/dashboard/ui.ts","../src/cli/adapter/ironclaw.ts","../src/cli/adapter/nanoclaw.ts","../src/adapters/llm.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// Re-export from CLI modules\nexport { runSetup } from './setup.js';\nexport { start, turnOn, turnOff, showStatus } from './commands.js';\n\nimport { runSetup } from './setup.js';\nimport { start, turnOn, turnOff, showStatus } from './commands.js';\nimport { readFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst command = process.argv[2];\n\n// Read version from package.json\nlet VERSION = 'unknown';\ntry {\n const dir = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(dir, '..', 'package.json');\n VERSION = JSON.parse(readFileSync(pkgPath, 'utf-8')).version;\n} catch {\n try {\n const dir = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(dir, '..', '..', 'package.json');\n VERSION = JSON.parse(readFileSync(pkgPath, 'utf-8')).version;\n } catch { /* use 'unknown' */ }\n}\n\nasync function main() {\n switch (command) {\n case 'setup':\n await runSetup();\n break;\n case 'start':\n await start();\n break;\n case 'on':\n turnOn();\n break;\n case 'off':\n turnOff();\n break;\n case 'status':\n showStatus();\n break;\n case '--version':\n case '-v':\n case 'version':\n console.log(`become v${VERSION}`);\n break;\n default:\n console.log(`\nbecome v${VERSION} — agent-to-agent learning\n\nUsage:\n become setup Set up become (interactive wizard)\n become start Start the proxy and dashboard\n become on Route your agent through become\n become off Disconnect — agent talks directly to LLM\n become status Show current status\n become --version Show version\n`);\n }\n}\n\nmain().catch((err) => {\n console.error(err.message);\n process.exit(1);\n});\n","import * as readline from 'node:readline';\nimport { saveConfig, LLM_DEFAULTS, type BecomeConfig } from './config.js';\nimport { listOpenClawAgents } from './adapter/openclaw.js';\n\nconst AGENT_TYPES = ['openclaw', 'ironclaw', 'nanoclaw', 'generic'] as const;\nconst LLM_PROVIDERS = ['anthropic', 'openai', 'ollama', 'openrouter', 'custom'] as const;\n\nfunction ask(rl: readline.Interface, question: string): Promise<string> {\n return new Promise((resolve) => rl.question(question, resolve));\n}\n\nexport async function runSetup(): Promise<void> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n\n try {\n console.log('\\nWelcome to become — agent-to-agent learning.\\n');\n\n // Agent type\n console.log('Which agent runtime are you using?');\n AGENT_TYPES.forEach((t, i) => console.log(` ${i + 1}. ${t}`));\n const agentChoice = await ask(rl, '> ');\n const agentIdx = parseInt(agentChoice, 10) - 1;\n const agent_type = AGENT_TYPES[agentIdx] ?? 'openclaw';\n\n // If OpenClaw, ask which agent to connect\n let openclaw_agent_id: string | undefined;\n if (agent_type === 'openclaw') {\n const agents = listOpenClawAgents();\n if (agents.length > 1) {\n console.log('\\nWhich OpenClaw agent should learn from other agents?');\n agents.forEach((a, i) => console.log(` ${i + 1}. ${a.id} (${a.model})`));\n const agentPick = await ask(rl, '> ');\n const pickIdx = parseInt(agentPick, 10) - 1;\n const picked = agents[pickIdx];\n if (picked && picked.id !== '_defaults') {\n openclaw_agent_id = picked.id;\n }\n } else if (agents.length === 1 && agents[0].id !== '_defaults') {\n openclaw_agent_id = agents[0].id;\n console.log(`\\nOpenClaw agent: ${openclaw_agent_id} (${agents[0].model})`);\n }\n }\n\n // LLM provider\n console.log('\\nWhich LLM provider does your agent use?');\n LLM_PROVIDERS.forEach((p, i) => console.log(` ${i + 1}. ${p}`));\n const llmChoice = await ask(rl, '> ');\n const llmIdx = parseInt(llmChoice, 10) - 1;\n const llm_provider = LLM_PROVIDERS[llmIdx] ?? 'anthropic';\n\n // API key\n const llm_api_key = await ask(rl, '\\nYour API key: ');\n if (!llm_api_key.trim()) {\n console.log('API key is required.');\n process.exit(1);\n }\n\n // Base URL\n const defaultUrl = LLM_DEFAULTS[llm_provider]?.base_url ?? '';\n let llm_base_url = defaultUrl;\n if (llm_provider === 'custom' || !defaultUrl) {\n llm_base_url = await ask(rl, 'LLM base URL: ');\n }\n\n // Ports\n const portInput = await ask(rl, `\\nProxy port (default 30001): `);\n const proxy_port = parseInt(portInput, 10) || 30001;\n const dashInput = await ask(rl, `Dashboard port (default 30002): `);\n const dashboard_port = parseInt(dashInput, 10) || 30002;\n\n const config: BecomeConfig = {\n agent_type,\n openclaw_agent_id,\n llm_provider,\n llm_base_url,\n llm_api_key: llm_api_key.trim(),\n proxy_port,\n dashboard_port,\n auto_extract: true,\n max_skills_per_call: 15,\n max_lessons_per_day: 20,\n state: 'off',\n };\n\n saveConfig(config);\n\n console.log('\\nConfig saved to ~/.become/config.json');\n console.log('Run `become start` to begin. Ctrl+C to stop.\\n');\n } finally {\n rl.close();\n }\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\n\nexport interface BecomeConfig {\n agent_type: 'openclaw' | 'ironclaw' | 'nanoclaw' | 'generic';\n openclaw_agent_id?: string;\n llm_provider: 'anthropic' | 'openai' | 'ollama' | 'openrouter' | 'custom';\n llm_base_url: string;\n llm_api_key: string;\n proxy_port: number;\n dashboard_port: number;\n auto_extract: boolean;\n max_skills_per_call: number;\n max_lessons_per_day: number;\n state: 'on' | 'off';\n}\n\nconst DEFAULT_CONFIG: BecomeConfig = {\n agent_type: 'openclaw',\n llm_provider: 'anthropic',\n llm_base_url: 'https://api.anthropic.com',\n llm_api_key: '',\n proxy_port: 30001,\n dashboard_port: 30002,\n auto_extract: true,\n max_skills_per_call: 15,\n max_lessons_per_day: 20,\n state: 'off',\n};\n\nexport function getBecomeDir(): string {\n return join(homedir(), '.become');\n}\n\nexport function getConfigPath(): string {\n return join(getBecomeDir(), 'config.json');\n}\n\nexport function loadConfig(): BecomeConfig {\n const configPath = getConfigPath();\n if (!existsSync(configPath)) {\n throw new Error('become is not set up. Run `become setup` first.');\n }\n try {\n const raw = readFileSync(configPath, 'utf-8');\n return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };\n } catch {\n throw new Error('Invalid config. Run `become setup` to reconfigure.');\n }\n}\n\nexport function saveConfig(config: BecomeConfig): void {\n const dir = getBecomeDir();\n mkdirSync(dir, { recursive: true });\n mkdirSync(join(dir, 'skills'), { recursive: true });\n mkdirSync(join(dir, 'pending'), { recursive: true });\n mkdirSync(join(dir, 'rejected'), { recursive: true });\n mkdirSync(join(dir, 'state'), { recursive: true });\n writeFileSync(getConfigPath(), JSON.stringify(config, null, 2), 'utf-8');\n}\n\nexport function configExists(): boolean {\n return existsSync(getConfigPath());\n}\n\nexport const LLM_DEFAULTS: Record<string, { base_url: string }> = {\n anthropic: { base_url: 'https://api.anthropic.com' },\n openai: { base_url: 'https://api.openai.com' },\n ollama: { base_url: 'http://localhost:11434' },\n openrouter: { base_url: 'https://openrouter.ai/api' },\n};\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { execSync } from 'node:child_process';\nimport type { BecomeConfig } from '../config.js';\n\nconst OPENCLAW_CONFIG = join(homedir(), '.openclaw', 'openclaw.json');\nconst STATE_DIR = join(homedir(), '.become', 'state');\nconst BACKUP_PATH = join(STATE_DIR, 'original_openclaw.json');\nconst ORIGINAL_URL_PATH = join(STATE_DIR, 'original_base_url.txt');\nconst PATCHED_PROVIDER_PATH = join(STATE_DIR, 'patched_provider.txt');\n\n/**\n * Patch OpenClaw to route through become.\n *\n * Strategy: find the provider that serves the agent's model (e.g. \"openrouter\")\n * and swap its baseUrl to point at the become proxy. Don't add providers,\n * don't rename models, don't touch model IDs. Just swap the URL.\n *\n * Docs: https://docs.openclaw.ai/gateway/configuration-reference\n */\nexport function patchOpenClaw(config: BecomeConfig): void {\n if (!existsSync(OPENCLAW_CONFIG)) {\n throw new Error(`OpenClaw config not found at ${OPENCLAW_CONFIG}`);\n }\n\n const raw = readFileSync(OPENCLAW_CONFIG, 'utf-8');\n const clawConfig = parseConfig(raw);\n mkdirSync(STATE_DIR, { recursive: true });\n\n // Find which provider the primary model uses\n const primaryModel = clawConfig.agents?.defaults?.model?.primary ?? '';\n if (!primaryModel) {\n throw new Error('No default model configured in openclaw.json (agents.defaults.model.primary)');\n }\n\n // Model format is \"provider/model-path\", e.g. \"openrouter/xiaomi/mimo-v2-pro\"\n const providerName = primaryModel.split('/')[0];\n if (!providerName) {\n throw new Error(`Cannot determine provider from model: ${primaryModel}`);\n }\n\n // Check if already patched\n if (existsSync(ORIGINAL_URL_PATH)) {\n const existingUrl = readFileSync(ORIGINAL_URL_PATH, 'utf-8').trim();\n if (existingUrl) {\n console.log('become is already connected. Run `become off` first to disconnect.');\n return;\n }\n }\n\n // Find the provider in models.json (per-agent) or openclaw.json (global)\n const modelsJsonPath = getModelsJsonPath(clawConfig);\n let modelsConfig: any = null;\n let modelsSource: 'models.json' | 'openclaw.json' = 'openclaw.json';\n\n if (modelsJsonPath && existsSync(modelsJsonPath)) {\n modelsConfig = JSON.parse(readFileSync(modelsJsonPath, 'utf-8'));\n modelsSource = 'models.json';\n }\n\n // Try models.json first (per-agent), then openclaw.json global providers\n let provider: any = null;\n let providerLocation: any = null;\n\n if (modelsConfig?.providers?.[providerName]) {\n provider = modelsConfig.providers[providerName];\n providerLocation = modelsConfig.providers;\n } else if (clawConfig.models?.providers?.[providerName]) {\n provider = clawConfig.models.providers[providerName];\n providerLocation = clawConfig.models.providers;\n modelsSource = 'openclaw.json';\n }\n\n if (!provider) {\n throw new Error(\n `Provider \"${providerName}\" not found in models.json or openclaw.json. ` +\n `Your model is \"${primaryModel}\" which needs a \"${providerName}\" provider.`\n );\n }\n\n let originalUrl = provider.baseUrl;\n if (!originalUrl) {\n throw new Error(`Provider \"${providerName}\" has no baseUrl`);\n }\n\n // If the provider URL already points to localhost, it's already patched\n // from a previous run. Read the backup to get the real URL.\n if (originalUrl.includes('127.0.0.1') || originalUrl.includes('localhost')) {\n // Try to recover from backup\n if (existsSync(BACKUP_PATH)) {\n try {\n const backupRaw = readFileSync(BACKUP_PATH, 'utf-8');\n // The backup might be openclaw.json or we need models.json backup\n // For now, just inform the user\n } catch {}\n }\n // Try to read from existing state\n const savedUrl = readSafe(ORIGINAL_URL_PATH);\n if (savedUrl && !savedUrl.includes('127.0.0.1')) {\n originalUrl = savedUrl;\n console.log(` recovered original URL from state: ${originalUrl}`);\n } else {\n throw new Error(\n `Provider \"${providerName}\" baseUrl is already pointing to localhost (${originalUrl}).\\n` +\n 'This means become was previously connected but not properly restored.\\n' +\n 'Fix manually: set the baseUrl back to the real provider URL in:\\n' +\n ` ${modelsSource === 'models.json' ? getModelsJsonPath(clawConfig) : OPENCLAW_CONFIG}`\n );\n }\n }\n\n // Backup\n writeFileSync(BACKUP_PATH, raw, 'utf-8');\n writeFileSync(ORIGINAL_URL_PATH, originalUrl, 'utf-8');\n writeFileSync(PATCHED_PROVIDER_PATH, `${providerName}:${modelsSource}`, 'utf-8');\n\n // Swap the baseUrl to the proxy\n // Don't append /v1. The proxy accepts whatever path OpenClaw sends\n // and forwards it to the original upstream URL with the same path.\n provider.baseUrl = `http://127.0.0.1:${config.proxy_port}`;\n\n // Write back\n if (modelsSource === 'models.json' && modelsJsonPath) {\n writeFileSync(modelsJsonPath, JSON.stringify(modelsConfig, null, 2), 'utf-8');\n } else {\n writeFileSync(OPENCLAW_CONFIG, JSON.stringify(clawConfig, null, 2), 'utf-8');\n }\n\n console.log(` provider: ${providerName}`);\n console.log(` baseUrl: ${originalUrl} -> localhost:${config.proxy_port}`);\n\n // Restart gateway\n restartGateway();\n}\n\nexport function restoreOpenClaw(): void {\n const originalUrl = readSafe(ORIGINAL_URL_PATH);\n const patchInfo = readSafe(PATCHED_PROVIDER_PATH);\n\n if (!originalUrl || !patchInfo) {\n // Nothing to restore, clean up state files\n cleanState();\n return;\n }\n\n const [providerName, source] = patchInfo.split(':');\n\n if (source === 'models.json') {\n // Restore in models.json\n const clawConfig = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n const modelsJsonPath = getModelsJsonPath(clawConfig);\n if (modelsJsonPath && existsSync(modelsJsonPath)) {\n const modelsConfig = JSON.parse(readFileSync(modelsJsonPath, 'utf-8'));\n if (modelsConfig.providers?.[providerName]) {\n modelsConfig.providers[providerName].baseUrl = originalUrl;\n writeFileSync(modelsJsonPath, JSON.stringify(modelsConfig, null, 2), 'utf-8');\n }\n }\n } else {\n // Restore in openclaw.json\n if (existsSync(OPENCLAW_CONFIG)) {\n const clawConfig = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n if (clawConfig.models?.providers?.[providerName]) {\n clawConfig.models.providers[providerName].baseUrl = originalUrl;\n writeFileSync(OPENCLAW_CONFIG, JSON.stringify(clawConfig, null, 2), 'utf-8');\n }\n }\n }\n\n // Clean up legacy mess from old become versions (v1.0.1-v1.0.14)\n // that added a \"become\" provider and changed model IDs\n cleanLegacy();\n\n cleanState();\n restartGateway();\n}\n\n/**\n * Remove artifacts from old become versions that added a \"become\" provider\n * and changed model IDs to \"become/...\". This runs on every restore.\n */\nfunction cleanLegacy(): void {\n // Clean openclaw.json\n if (existsSync(OPENCLAW_CONFIG)) {\n try {\n const config = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n let changed = false;\n\n // Remove become provider\n if (config.models?.providers?.become) {\n delete config.models.providers.become;\n changed = true;\n }\n\n // Fix model ID if it starts with become/\n const primary = config.agents?.defaults?.model?.primary ?? '';\n if (primary.startsWith('become/')) {\n config.agents.defaults.model.primary = 'openrouter/' + primary.slice('become/'.length);\n changed = true;\n }\n\n // Remove _originalModel from any provider\n for (const prov of Object.values(config.models?.providers ?? {})) {\n if (prov && typeof prov === 'object' && '_originalModel' in prov) {\n delete (prov as Record<string, unknown>)._originalModel;\n changed = true;\n }\n }\n\n if (changed) writeFileSync(OPENCLAW_CONFIG, JSON.stringify(config, null, 2), 'utf-8');\n } catch {}\n }\n\n // Clean models.json\n try {\n const clawConfig = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n const modelsJsonPath = getModelsJsonPath(clawConfig);\n if (modelsJsonPath && existsSync(modelsJsonPath)) {\n const models = JSON.parse(readFileSync(modelsJsonPath, 'utf-8'));\n let changed = false;\n\n if (models.providers?.become) {\n delete models.providers.become;\n changed = true;\n }\n\n if (changed) writeFileSync(modelsJsonPath, JSON.stringify(models, null, 2), 'utf-8');\n }\n } catch {}\n}\n\nexport function listOpenClawAgents(): { id: string; model: string }[] {\n if (!existsSync(OPENCLAW_CONFIG)) return [];\n try {\n const config = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n const agents: any[] = config.agents?.list ?? [];\n const defaultModel = config.agents?.defaults?.model?.primary ?? 'unknown';\n\n if (agents.length === 0) {\n return [{ id: '_defaults', model: defaultModel }];\n }\n return agents.map((a: any) => ({\n id: a.id,\n model: a.model ?? defaultModel,\n }));\n } catch {\n return [];\n }\n}\n\nexport function isOpenClawPatched(): boolean {\n return existsSync(ORIGINAL_URL_PATH) && readSafe(ORIGINAL_URL_PATH) !== '';\n}\n\n// -- Helpers --\n\nfunction getModelsJsonPath(clawConfig: any): string | null {\n // Per-agent models.json path\n const agentList = clawConfig.agents?.list ?? [];\n const defaultAgent = agentList.find((a: any) => a.default) ?? agentList[0];\n\n if (defaultAgent?.agentDir) {\n return join(defaultAgent.agentDir.replace('~', homedir()), 'models.json');\n }\n\n // Default location\n const mainPath = join(homedir(), '.openclaw', 'agents', 'main', 'agent', 'models.json');\n if (existsSync(mainPath)) return mainPath;\n\n return null;\n}\n\nfunction parseConfig(raw: string): any {\n const stripped = raw\n .replace(/\\/\\/.*$/gm, '')\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/,\\s*([\\]}])/g, '$1');\n return JSON.parse(stripped);\n}\n\nfunction readSafe(path: string): string {\n try {\n return existsSync(path) ? readFileSync(path, 'utf-8').trim() : '';\n } catch {\n return '';\n }\n}\n\nfunction cleanState(): void {\n for (const f of [ORIGINAL_URL_PATH, PATCHED_PROVIDER_PATH]) {\n try { writeFileSync(f, '', 'utf-8'); } catch {}\n }\n}\n\nfunction restartGateway(): void {\n console.log('Restarting OpenClaw gateway...');\n try {\n execSync('openclaw gateway restart', { stdio: 'pipe', timeout: 15000 });\n console.log('OpenClaw gateway restarted.');\n } catch {\n console.log('\\n*** OpenClaw gateway needs a manual restart. ***');\n console.log('*** Run: openclaw gateway restart ***\\n');\n }\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { loadConfig, saveConfig, getBecomeDir, type BecomeConfig } from './config.js';\nimport { createProxyServer, type ProxyConfig } from '../proxy/server.js';\nimport { createDashboardServer } from '../dashboard/server.js';\nimport { FileSkillStore } from '../skills/store.js';\nimport { TrustManager } from '../skills/trust.js';\nimport { patchOpenClaw, restoreOpenClaw } from './adapter/openclaw.js';\nimport { patchIronClaw, restoreIronClaw } from './adapter/ironclaw.js';\nimport { patchNanoClaw, restoreNanoClaw } from './adapter/nanoclaw.js';\nimport { OpenAIAdapter, AnthropicAdapter, OllamaAdapter } from '../adapters/llm.js';\nimport type { ConversationAnalyzer } from '../learn/agent-conversations.js';\n\n/**\n * Create the LLM analyzer for lesson extraction.\n * This calls the LLM DIRECTLY (not through the proxy) to analyze conversations.\n */\nfunction createAnalyzer(config: BecomeConfig): ConversationAnalyzer {\n switch (config.llm_provider) {\n case 'anthropic':\n return { analyze: (p) => new AnthropicAdapter({ apiKey: config.llm_api_key }).complete(p) };\n case 'ollama':\n return { analyze: (p) => new OllamaAdapter({ baseUrl: config.llm_base_url }).complete(p) };\n case 'openai':\n case 'openrouter':\n case 'custom':\n default:\n return { analyze: (p) => new OpenAIAdapter({ apiKey: config.llm_api_key, baseUrl: config.llm_base_url }).complete(p) };\n }\n}\n\nexport async function start(): Promise<void> {\n const config = loadConfig();\n const baseDir = getBecomeDir();\n\n const proxyConfig: ProxyConfig = {\n port: config.proxy_port,\n llm_base_url: config.llm_base_url,\n llm_api_key: config.llm_api_key,\n llm_provider: config.llm_provider,\n baseDir,\n max_skills_per_call: config.max_skills_per_call,\n auto_extract: config.auto_extract,\n };\n\n // Connect agent FIRST so the state file with the original URL exists\n // Always run turnOn() even if state is 'on', because the state file might be missing\n try {\n turnOn();\n } catch (e) {\n console.error('Warning: could not connect agent:', e instanceof Error ? e.message : e);\n }\n\n // Read the original provider URL (written by turnOn -> patchOpenClaw/IronClaw/NanoClaw)\n const originalUrlPath = join(homedir(), '.become', 'state', 'original_base_url.txt');\n let upstreamUrl = config.llm_base_url; // fallback\n if (existsSync(originalUrlPath)) {\n const saved = readFileSync(originalUrlPath, 'utf-8').trim();\n if (saved) upstreamUrl = saved;\n }\n\n // SAFETY: never forward to ourselves (infinite loop -> OOM crash)\n if (upstreamUrl.includes('127.0.0.1') || upstreamUrl.includes('localhost')) {\n const port = config.proxy_port.toString();\n if (upstreamUrl.includes(`:${port}`)) {\n console.error(`\\nFATAL: upstream URL ${upstreamUrl} points to the become proxy itself.`);\n console.error('This would cause an infinite loop. Aborting.');\n console.error('Run `become off` to restore your config, then `become start` again.\\n');\n process.exit(1);\n }\n }\n\n console.log(`[become] upstream: ${upstreamUrl}`);\n\n const analyzer = createAnalyzer(config);\n const proxy = createProxyServer(proxyConfig, analyzer, upstreamUrl);\n await proxy.listen();\n\n // Start dashboard\n const dashboard = createDashboardServer({\n store: proxy.store,\n trust: proxy.trust,\n getProxyStats: () => proxy.stats,\n getState: () => {\n try { return loadConfig().state; } catch { return 'off'; }\n },\n setState: (state) => {\n try {\n if (state === 'on') turnOn();\n else turnOff();\n } catch (e) {\n console.error('State change failed:', e);\n }\n },\n });\n await dashboard.listen(config.dashboard_port);\n\n const approved = proxy.store.listApproved().length;\n const pending = proxy.store.listPending().length;\n const trustConfig = proxy.trust.getConfig();\n\n console.log(`\\nbecome proxy running on localhost:${config.proxy_port}`);\n console.log(`become dashboard at http://localhost:${config.dashboard_port}`);\n console.log(`\\nConnected to: ${config.agent_type}${config.openclaw_agent_id ? ` (agent: ${config.openclaw_agent_id})` : ''}`);\n console.log(`Skills loaded: ${approved} approved, ${pending} pending`);\n console.log(`Trust rules: ${trustConfig.trusted.length} trusted, ${trustConfig.blocked.length} blocked`);\n console.log('\\nYour agent is learning from other agents.');\n console.log('Dashboard: http://localhost:' + config.dashboard_port);\n console.log('Ctrl+C to stop.');\n\n // Wait a few seconds then check if any request has come through\n setTimeout(() => {\n if (proxy.stats.requests_forwarded === 0) {\n console.log('\\nWaiting for first request from your agent...');\n console.log('(If nothing happens, make sure your agent is running and talking to other agents)');\n }\n }, 10000);\n\n // Periodically log activity so user knows it's working\n const activityInterval = setInterval(() => {\n const s = proxy.stats;\n if (s.requests_forwarded > 0) {\n console.log(`[become] ${s.requests_forwarded} requests forwarded, ${s.skills_injected} skills injected, ${s.lessons_extracted} lessons extracted`);\n }\n }, 60000);\n\n // Handle shutdown: run once, don't block on gateway restart\n let shuttingDown = false;\n const shutdown = () => {\n if (shuttingDown) { process.exit(0); return; }\n shuttingDown = true;\n clearInterval(activityInterval);\n console.log('\\nShutting down...');\n try { turnOff(); } catch { /* best effort */ }\n proxy.close().catch(() => {});\n dashboard.close().catch(() => {});\n // Exit immediately, don't wait for gateway restart\n setTimeout(() => process.exit(0), 500);\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n\nexport function turnOn(): void {\n const config = loadConfig();\n\n console.log(`\\nPatching ${config.agent_type} config...`);\n console.log(` baseUrl: ${config.llm_base_url} → localhost:${config.proxy_port}`);\n\n switch (config.agent_type) {\n case 'openclaw':\n patchOpenClaw(config);\n break;\n case 'ironclaw':\n patchIronClaw(config);\n break;\n case 'nanoclaw':\n patchNanoClaw(config);\n break;\n case 'generic':\n console.log(`\\nSet these env vars in your agent's config:`);\n console.log(` OPENAI_BASE_URL=http://127.0.0.1:${config.proxy_port}/v1`);\n console.log(` ANTHROPIC_BASE_URL=http://127.0.0.1:${config.proxy_port}`);\n console.log(`Then restart your agent.\\n`);\n break;\n }\n\n config.state = 'on';\n saveConfig(config);\n console.log('\\nbecome is ON. Your agent is now learning from other agents.\\n');\n}\n\nexport function turnOff(): void {\n const config = loadConfig();\n\n console.log(`\\nRestoring ${config.agent_type} config...`);\n console.log(` baseUrl: localhost:${config.proxy_port} → ${config.llm_base_url}`);\n\n switch (config.agent_type) {\n case 'openclaw':\n restoreOpenClaw();\n break;\n case 'ironclaw':\n restoreIronClaw();\n break;\n case 'nanoclaw':\n restoreNanoClaw();\n break;\n case 'generic':\n console.log(`\\nRestore your original env vars and restart your agent.\\n`);\n break;\n }\n\n config.state = 'off';\n saveConfig(config);\n console.log('\\nbecome is OFF. Your agent talks directly to the LLM.');\n console.log('Learned skills are preserved — they\\'ll be injected when you turn become back on.\\n');\n}\n\nexport function showStatus(): void {\n const config = loadConfig();\n const baseDir = getBecomeDir();\n const store = new FileSkillStore({ baseDir });\n const trust = new TrustManager(baseDir);\n\n const approved = store.listApproved().length;\n const pending = store.listPending().length;\n const rejected = store.listRejected().length;\n const trustConfig = trust.getConfig();\n const counts = trust.getDailyCounts();\n\n console.log(`\\nState: ${config.state.toUpperCase()}`);\n console.log(`Proxy: localhost:${config.proxy_port}`);\n console.log(`Dashboard: localhost:${config.dashboard_port}`);\n console.log(`\\nSkills: ${approved} approved, ${pending} pending, ${rejected} rejected`);\n console.log(`Trust: ${trustConfig.trusted.length} trusted, ${trustConfig.blocked.length} blocked`);\n console.log(`Today: ${counts.total} lessons extracted\\n`);\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { FileSkillStore } from '../skills/store.js';\nimport { TrustManager } from '../skills/trust.js';\nimport { formatSkillsForInjection, injectSkillsIntoMessages } from '../skills/format.js';\nimport { LessonExtractor } from './extractor.js';\nimport type { ConversationAnalyzer } from '../learn/agent-conversations.js';\nimport type { SkillFile } from '../skills/store.js';\n\nexport interface ProxyConfig {\n port: number;\n llm_base_url: string;\n llm_api_key: string;\n llm_provider: 'anthropic' | 'openai' | 'ollama' | 'openrouter' | 'custom';\n baseDir: string;\n max_skills_per_call: number;\n auto_extract: boolean;\n}\n\nexport interface ProxyStats {\n requests_forwarded: number;\n skills_injected: number;\n lessons_extracted: number;\n started_at: string;\n}\n\nconst SKILL_CACHE_TTL_MS = 5000; // Refresh skill cache every 5 seconds\n\nexport function createProxyServer(config: ProxyConfig, analyzer?: ConversationAnalyzer, overrideUpstreamUrl?: string) {\n const store = new FileSkillStore({ baseDir: config.baseDir });\n const trust = new TrustManager(config.baseDir);\n const extractor = analyzer ? new LessonExtractor(store, trust, analyzer) : null;\n\n const stats: ProxyStats = {\n requests_forwarded: 0,\n skills_injected: 0,\n lessons_extracted: 0,\n started_at: new Date().toISOString(),\n };\n\n // Skill cache — avoid reading disk on every request\n let cachedSkills: SkillFile[] = [];\n let cacheTimestamp = 0;\n\n function getSkills(): SkillFile[] {\n const now = Date.now();\n if (now - cacheTimestamp > SKILL_CACHE_TTL_MS) {\n cachedSkills = store.listApproved();\n cacheTimestamp = now;\n }\n return cachedSkills;\n }\n\n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n console.log(`[become] ${req.method} ${req.url}`);\n\n // Health check\n if (req.url === '/health' && req.method === 'GET') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ status: 'ok', ...stats }));\n return;\n }\n\n // Proxy any POST request that looks like an LLM API call\n // Different providers use different paths:\n // OpenAI/OpenRouter: /v1/chat/completions or /chat/completions or /api/v1/chat/completions\n // Anthropic: /v1/messages or /messages\n // Some proxies: just /\n const url = req.url ?? '';\n const isLLMRequest = req.method === 'POST' && (\n url.includes('/chat/completions') ||\n url.includes('/messages') ||\n url === '/' ||\n url.startsWith('/v1')\n );\n\n if (!isLLMRequest) {\n // Log the rejected path so users can debug\n console.log(`[become] rejected: ${req.method} ${url}`);\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Not an LLM endpoint: ${req.method} ${url}` }));\n return;\n }\n\n try {\n // Read request body\n const rawBody = await readBody(req);\n const body = JSON.parse(rawBody);\n\n // Extract messages for injection\n const messages = body.messages;\n if (Array.isArray(messages)) {\n // Inject approved skills from cache\n const skills = getSkills().slice(0, config.max_skills_per_call);\n if (skills.length > 0) {\n const skillText = formatSkillsForInjection(skills);\n injectSkillsIntoMessages(messages, skillText);\n stats.skills_injected++;\n }\n }\n\n // Build upstream URL from the original provider URL (not the become config)\n const upstreamUrl = buildUpstreamUrl(overrideUpstreamUrl ?? config.llm_base_url, req.url!);\n\n // Build upstream headers\n const upstreamHeaders = buildUpstreamHeaders(config, req.headers);\n\n // Forward to real LLM\n const isStreaming = body.stream === true;\n const modifiedBody = JSON.stringify(body);\n\n console.log(`[become] -> ${upstreamUrl} (${isStreaming ? 'streaming' : 'non-streaming'})`);\n\n const upstreamRes = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: modifiedBody,\n });\n\n console.log(`[become] <- ${upstreamRes.status} ${upstreamRes.statusText}`);\n\n if (!upstreamRes.ok) {\n const errBody = await upstreamRes.text().catch(() => '');\n console.log(`[become] ERROR: ${errBody.slice(0, 500)}`);\n }\n\n stats.requests_forwarded++;\n\n // Forward response headers (filter out transfer-encoding to avoid mismatch)\n const responseHeaders: Record<string, string> = {};\n upstreamRes.headers.forEach((value, key) => {\n if (key.toLowerCase() !== 'transfer-encoding') {\n responseHeaders[key] = value;\n }\n });\n res.writeHead(upstreamRes.status, responseHeaders);\n\n if (isStreaming && upstreamRes.body) {\n // Stream: pipe chunks directly to client — do NOT buffer\n const reader = upstreamRes.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(value);\n }\n } finally {\n res.end();\n }\n\n // Async extraction — uses request messages only, not the response\n if (config.auto_extract && extractor && Array.isArray(messages)) {\n extractor.extract(messages)\n .then(() => { stats.lessons_extracted++; })\n .catch(() => {});\n }\n } else {\n // Non-streaming: read full response, return it, then extract\n const responseBuffer = await upstreamRes.arrayBuffer();\n res.end(Buffer.from(responseBuffer));\n\n // Async extraction\n if (config.auto_extract && extractor && Array.isArray(messages)) {\n extractor.extract(messages)\n .then(() => { stats.lessons_extracted++; })\n .catch(() => {});\n }\n }\n } catch (err) {\n console.log(`[become] EXCEPTION: ${err instanceof Error ? err.message : String(err)}`);\n // Sanitize error — never leak upstream details to client\n const safeMessage = err instanceof Error && err.message === 'Request body too large'\n ? 'Request body too large'\n : 'Failed to forward request to LLM';\n\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'application/json' });\n }\n // Always end the response, even if headers were already sent\n res.end(JSON.stringify({ error: safeMessage }));\n }\n });\n\n return {\n server,\n stats,\n store,\n trust,\n listen: (port?: number) => {\n const p = port ?? config.port;\n return new Promise<void>((resolve) => {\n server.listen(p, '127.0.0.1', () => resolve());\n });\n },\n close: () => new Promise<void>((resolve) => server.close(() => resolve())),\n };\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n const MAX_BODY = 10 * 1024 * 1024; // 10MB\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n\nfunction buildUpstreamUrl(baseUrl: string, path: string): string {\n const base = baseUrl.replace(/\\/+$/, '');\n\n // Forward to the matching upstream endpoint.\n // If agent sends /v1/messages → forward to /v1/messages (Anthropic format)\n // If agent sends /v1/chat/completions → forward to /v1/chat/completions (OpenAI format)\n // The agent is responsible for using the correct format for its provider.\n return `${base}${path}`;\n}\n\nfunction buildUpstreamHeaders(\n config: ProxyConfig,\n incomingHeaders: IncomingMessage['headers'],\n): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (config.llm_provider === 'anthropic') {\n headers['x-api-key'] = config.llm_api_key;\n headers['anthropic-version'] = '2023-06-01';\n // Forward anthropic-specific headers from agent\n const version = incomingHeaders['anthropic-version'];\n if (typeof version === 'string') headers['anthropic-version'] = version;\n const beta = incomingHeaders['anthropic-beta'];\n if (typeof beta === 'string') headers['anthropic-beta'] = beta;\n } else {\n headers['Authorization'] = `Bearer ${config.llm_api_key}`;\n }\n\n // Forward accept header for streaming\n const accept = incomingHeaders['accept'];\n if (typeof accept === 'string') headers['Accept'] = accept;\n\n return headers;\n}\n","import { readFileSync, writeFileSync, readdirSync, mkdirSync, renameSync, unlinkSync, existsSync } from 'node:fs';\nimport { join, basename } from 'node:path';\nimport { createHash } from 'node:crypto';\n\nexport interface SkillFile {\n id: string; // Filename without extension\n name: string;\n instruction: string;\n learned_from: string;\n source: string; // peer_review, conversation, collaboration, teaching\n confidence: number;\n approved_at?: string;\n created_at: string;\n}\n\nexport interface SkillStoreConfig {\n baseDir: string; // ~/.become\n}\n\nexport class FileSkillStore {\n private skillsDir: string;\n private pendingDir: string;\n private rejectedDir: string;\n\n constructor(config: SkillStoreConfig) {\n this.skillsDir = join(config.baseDir, 'skills');\n this.pendingDir = join(config.baseDir, 'pending');\n this.rejectedDir = join(config.baseDir, 'rejected');\n\n mkdirSync(this.skillsDir, { recursive: true });\n mkdirSync(this.pendingDir, { recursive: true });\n mkdirSync(this.rejectedDir, { recursive: true });\n }\n\n // ── Read ────────────────────────────────────────────────────────────────\n\n listApproved(): SkillFile[] {\n return this.readDir(this.skillsDir);\n }\n\n listPending(): SkillFile[] {\n return this.readDir(this.pendingDir);\n }\n\n listRejected(): SkillFile[] {\n return this.readDir(this.rejectedDir);\n }\n\n getApproved(id: string): SkillFile | null {\n this.validateId(id);\n return this.readFile(join(this.skillsDir, `${id}.md`));\n }\n\n // ── Write ───────────────────────────────────────────────────────────────\n\n savePending(lesson: Omit<SkillFile, 'id' | 'approved_at'>): SkillFile | null {\n // Deduplication: check if same instruction already exists\n const normalized = lesson.instruction.toLowerCase().trim();\n const allExisting = [...this.listApproved(), ...this.listPending()];\n if (allExisting.some(s => s.instruction.toLowerCase().trim() === normalized)) {\n return null;\n }\n\n const id = this.generateId(lesson.name);\n const file: SkillFile = { ...lesson, id, approved_at: undefined };\n this.writeFile(join(this.pendingDir, `${id}.md`), file);\n return file;\n }\n\n approve(id: string): boolean {\n this.validateId(id);\n const src = join(this.pendingDir, `${id}.md`);\n if (!existsSync(src)) return false;\n\n const skill = this.readFile(src);\n if (!skill) return false;\n\n skill.approved_at = new Date().toISOString();\n const dest = join(this.skillsDir, `${id}.md`);\n this.writeFile(dest, skill);\n unlinkSync(src);\n return true;\n }\n\n reject(id: string): boolean {\n this.validateId(id);\n const src = join(this.pendingDir, `${id}.md`);\n if (!existsSync(src)) return false;\n const dest = join(this.rejectedDir, `${id}.md`);\n renameSync(src, dest);\n return true;\n }\n\n disable(id: string): boolean {\n this.validateId(id);\n const src = join(this.skillsDir, `${id}.md`);\n if (!existsSync(src)) return false;\n const dest = join(this.rejectedDir, `${id}.md`);\n renameSync(src, dest);\n return true;\n }\n\n remove(id: string): boolean {\n this.validateId(id);\n for (const dir of [this.skillsDir, this.pendingDir, this.rejectedDir]) {\n const path = join(dir, `${id}.md`);\n if (existsSync(path)) {\n unlinkSync(path);\n return true;\n }\n }\n return false;\n }\n\n // ── Helpers ─────────────────────────────────────────────────────────────\n\n /**\n * Validate that an id does not contain path traversal characters.\n * Prevents attacks like id=\"../../.ssh/authorized_keys\"\n */\n private validateId(id: string): void {\n if (!id || typeof id !== 'string') throw new Error('Invalid id');\n if (id.includes('/') || id.includes('\\\\') || id.includes('..') || id.includes('\\0')) {\n throw new Error('Invalid id: path traversal detected');\n }\n }\n\n private readDir(dir: string): SkillFile[] {\n if (!existsSync(dir)) return [];\n const files = readdirSync(dir).filter(f => f.endsWith('.md'));\n const skills: SkillFile[] = [];\n for (const f of files) {\n const skill = this.readFile(join(dir, f));\n if (skill) skills.push(skill);\n }\n return skills.sort((a, b) => b.created_at.localeCompare(a.created_at));\n }\n\n private readFile(path: string): SkillFile | null {\n if (!existsSync(path)) return null;\n try {\n const content = readFileSync(path, 'utf-8');\n return this.parseSkillFile(content, basename(path, '.md'));\n } catch {\n return null;\n }\n }\n\n private writeFile(path: string, skill: SkillFile): void {\n const content = this.formatSkillFile(skill);\n writeFileSync(path, content, 'utf-8');\n }\n\n private parseSkillFile(content: string, id: string): SkillFile | null {\n const match = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n([\\s\\S]*)$/);\n if (!match) return null;\n\n const [, frontmatter, body] = match;\n const meta: Record<string, string> = {};\n for (const line of frontmatter.split('\\n')) {\n const colonIdx = line.indexOf(':');\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n if (key && value) meta[key] = value;\n }\n\n return {\n id,\n name: meta.name ?? id,\n instruction: body.trim(),\n learned_from: meta.learned_from ?? 'unknown',\n source: meta.source ?? 'conversation',\n confidence: parseFloat(meta.confidence ?? '0.5'),\n approved_at: meta.approved_at || undefined,\n created_at: meta.created_at ?? new Date().toISOString(),\n };\n }\n\n private formatSkillFile(skill: SkillFile): string {\n const lines = [\n '---',\n `name: ${skill.name}`,\n `learned_from: ${skill.learned_from}`,\n `source: ${skill.source}`,\n `confidence: ${skill.confidence}`,\n `created_at: ${skill.created_at}`,\n ];\n if (skill.approved_at) lines.push(`approved_at: ${skill.approved_at}`);\n lines.push('---');\n lines.push('');\n lines.push(skill.instruction);\n lines.push('');\n return lines.join('\\n');\n }\n\n private generateId(name: string): string {\n const clean = name.toLowerCase().replace(/[^a-z0-9]+/g, '_').slice(0, 40);\n const hash = createHash('sha256')\n .update(`${name}${Date.now()}${Math.random()}`)\n .digest('hex')\n .slice(0, 6);\n return `${clean}_${hash}`;\n }\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\n\nexport type TrustLevel = 'trusted' | 'pending' | 'blocked';\n\nexport interface TrustConfig {\n trusted: string[];\n blocked: string[];\n default: TrustLevel;\n}\n\nexport interface RateLimits {\n max_lessons_per_day: number;\n max_lessons_per_agent: number;\n max_skills_per_call: number;\n}\n\nconst DEFAULT_TRUST: TrustConfig = {\n trusted: [],\n blocked: [],\n default: 'pending',\n};\n\nconst DEFAULT_RATE_LIMITS: RateLimits = {\n max_lessons_per_day: 20,\n max_lessons_per_agent: 10,\n max_skills_per_call: 15,\n};\n\nexport class TrustManager {\n private trustPath: string;\n private statsPath: string;\n private config: TrustConfig;\n private dailyCounts: { date: string; total: number; perAgent: Record<string, number> };\n\n constructor(baseDir: string) {\n this.trustPath = join(baseDir, 'trust.json');\n this.statsPath = join(baseDir, 'state', 'daily_counts.json');\n mkdirSync(join(baseDir, 'state'), { recursive: true });\n this.config = this.loadTrust();\n this.dailyCounts = this.loadDailyCounts();\n }\n\n getLevel(agentId: string): TrustLevel {\n if (this.config.trusted.includes(agentId)) return 'trusted';\n if (this.config.blocked.includes(agentId)) return 'blocked';\n return this.config.default;\n }\n\n setLevel(agentId: string, level: TrustLevel): void {\n // Remove from all lists first\n this.config.trusted = this.config.trusted.filter((a) => a !== agentId);\n this.config.blocked = this.config.blocked.filter((a) => a !== agentId);\n\n if (level === 'trusted') this.config.trusted.push(agentId);\n if (level === 'blocked') this.config.blocked.push(agentId);\n\n this.saveTrust();\n }\n\n setDefault(level: TrustLevel): void {\n this.config.default = level;\n this.saveTrust();\n }\n\n getConfig(): TrustConfig {\n return { ...this.config };\n }\n\n // ── Rate Limiting ───────────────────────────────────────────────────────\n\n canLearn(agentId: string, limits: RateLimits = DEFAULT_RATE_LIMITS): boolean {\n this.refreshDailyCountsIfNewDay();\n\n if (this.dailyCounts.total >= limits.max_lessons_per_day) return false;\n const agentCount = this.dailyCounts.perAgent[agentId] ?? 0;\n if (agentCount >= limits.max_lessons_per_agent) return false;\n\n return true;\n }\n\n recordLesson(agentId: string): void {\n this.refreshDailyCountsIfNewDay();\n this.dailyCounts.total++;\n this.dailyCounts.perAgent[agentId] = (this.dailyCounts.perAgent[agentId] ?? 0) + 1;\n this.saveDailyCounts();\n }\n\n getDailyCounts(): { total: number; perAgent: Record<string, number> } {\n this.refreshDailyCountsIfNewDay();\n return { total: this.dailyCounts.total, perAgent: { ...this.dailyCounts.perAgent } };\n }\n\n // ── Private ─────────────────────────────────────────────────────────────\n\n private loadTrust(): TrustConfig {\n if (!existsSync(this.trustPath)) return { ...DEFAULT_TRUST, trusted: [], blocked: [] };\n try {\n const raw = JSON.parse(readFileSync(this.trustPath, 'utf-8'));\n // Validate shape — arrays must be arrays, default must be valid\n return {\n trusted: Array.isArray(raw.trusted) ? raw.trusted.filter((a: unknown) => typeof a === 'string') : [],\n blocked: Array.isArray(raw.blocked) ? raw.blocked.filter((a: unknown) => typeof a === 'string') : [],\n default: ['trusted', 'pending', 'blocked'].includes(raw.default) ? raw.default : 'pending',\n };\n } catch {\n return { ...DEFAULT_TRUST, trusted: [], blocked: [] };\n }\n }\n\n private saveTrust(): void {\n mkdirSync(dirname(this.trustPath), { recursive: true });\n writeFileSync(this.trustPath, JSON.stringify(this.config, null, 2), 'utf-8');\n }\n\n private loadDailyCounts(): { date: string; total: number; perAgent: Record<string, number> } {\n const today = new Date().toISOString().slice(0, 10);\n if (!existsSync(this.statsPath)) return { date: today, total: 0, perAgent: {} };\n try {\n const data = JSON.parse(readFileSync(this.statsPath, 'utf-8'));\n if (data.date !== today) return { date: today, total: 0, perAgent: {} };\n return data;\n } catch {\n return { date: today, total: 0, perAgent: {} };\n }\n }\n\n private saveDailyCounts(): void {\n writeFileSync(this.statsPath, JSON.stringify(this.dailyCounts, null, 2), 'utf-8');\n }\n\n private refreshDailyCountsIfNewDay(): void {\n const today = new Date().toISOString().slice(0, 10);\n if (this.dailyCounts.date !== today) {\n this.dailyCounts = { date: today, total: 0, perAgent: {} };\n }\n }\n}\n","import type { SkillFile } from './store.js';\n\n/**\n * Format approved skills as a text block for injection into the system message.\n */\nexport function formatSkillsForInjection(skills: SkillFile[]): string {\n if (skills.length === 0) return '';\n\n const lines = skills.map((s) => {\n const source = s.source === 'peer_review' ? 'from a peer review' :\n s.source === 'collaboration' ? 'from a collaboration' :\n s.source === 'teaching' ? 'from being taught' :\n 'from a conversation';\n return `- ${s.instruction} (${source})`;\n });\n\n return [\n '## Lessons learned from other agents',\n '',\n 'You have learned the following from interactions with other agents. Follow these instructions:',\n '',\n ...lines,\n ].join('\\n');\n}\n\n/**\n * Inject skill text into a messages array by prepending to the system message.\n * Mutates the messages array in place.\n */\nexport function injectSkillsIntoMessages(\n messages: { role: string; content: string }[],\n skillText: string,\n): void {\n if (!skillText) return;\n\n const sysIdx = messages.findIndex((m) => m.role === 'system');\n if (sysIdx >= 0) {\n messages[sysIdx].content = skillText + '\\n\\n---\\n\\n' + messages[sysIdx].content;\n } else {\n messages.unshift({ role: 'system', content: skillText });\n }\n}\n","/**\n * Detects whether a conversation involves another agent (vs user-to-agent).\n * Only agent-to-agent conversations trigger lesson extraction.\n */\n\nexport interface DetectionResult {\n isAgentToAgent: boolean;\n otherAgentId?: string;\n exchangeType?: 'channel' | 'dm' | 'peer_review' | 'collaboration' | 'chat';\n}\n\n// OpenClawCity channel format: [agent-name says]: ...\nconst CHANNEL_PATTERN = /^\\[([^\\]]+)\\s+says?\\]:\\s*/;\n\n// DM format: DM from agent-name: ...\nconst DM_PATTERN = /^DM\\s+from\\s+([^:]+):\\s*/;\n\n// Agent in building: agent-name in Building Name: ...\n// Requires agent-like ID (contains hyphen or underscore) to avoid false positives\n// like \"Write code in Python: ...\"\nconst BUILDING_PATTERN = /^([a-zA-Z0-9]+[-_][a-zA-Z0-9_.-]+)\\s+in\\s+[^:]+:\\s*/;\n\n// Peer review markers\nconst REVIEW_KEYWORDS = ['strengths:', 'weaknesses:', 'verdict:', 'assessment:', 'suggestions:'];\n\nexport function detectAgentConversation(\n messages: { role: string; content: string; name?: string }[],\n): DetectionResult {\n const negative: DetectionResult = { isAgentToAgent: false };\n\n if (!messages || messages.length === 0) return negative;\n\n // Check messages for agent-to-agent patterns\n for (const msg of messages) {\n if (msg.role !== 'user' && msg.role !== 'assistant') continue;\n const content = typeof msg.content === 'string' ? msg.content : '';\n\n // Pattern 1: message has a `name` field (multi-agent frameworks)\n if (msg.name && msg.role === 'user') {\n return {\n isAgentToAgent: true,\n otherAgentId: msg.name,\n exchangeType: 'chat',\n };\n }\n\n // Pattern 2: OpenClawCity channel format\n const channelMatch = content.match(CHANNEL_PATTERN);\n if (channelMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: channelMatch[1].trim(),\n exchangeType: 'channel',\n };\n }\n\n // Pattern 3: DM format\n const dmMatch = content.match(DM_PATTERN);\n if (dmMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: dmMatch[1].trim(),\n exchangeType: 'dm',\n };\n }\n\n // Pattern 4: Building format\n const buildingMatch = content.match(BUILDING_PATTERN);\n if (buildingMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: buildingMatch[1].trim(),\n exchangeType: 'chat',\n };\n }\n\n // Pattern 5: Peer review content\n const lowerContent = content.toLowerCase();\n const reviewMatches = REVIEW_KEYWORDS.filter((kw) => lowerContent.includes(kw));\n if (reviewMatches.length >= 2) {\n return {\n isAgentToAgent: true,\n otherAgentId: undefined,\n exchangeType: 'peer_review',\n };\n }\n }\n\n return negative;\n}\n\n/**\n * Extract agent-to-agent exchange text from messages for analysis.\n */\nexport function extractExchangeText(\n messages: { role: string; content: string; name?: string }[],\n): string {\n return messages\n .filter((m) => m.role === 'user' || m.role === 'assistant')\n .map((m) => {\n const speaker = m.name ?? m.role;\n const content = typeof m.content === 'string' ? m.content : '';\n return `[${speaker}]: ${content}`;\n })\n .join('\\n')\n .slice(0, 6000);\n}\n","import { detectAgentConversation, extractExchangeText } from './detector.js';\nimport type { FileSkillStore } from '../skills/store.js';\nimport type { TrustManager } from '../skills/trust.js';\nimport type { ConversationAnalyzer } from '../learn/agent-conversations.js';\n\n/**\n * Async lesson extractor. After the proxy forwards a response, this analyzes\n * the conversation for agent-to-agent lessons. Runs in the background —\n * never blocks the agent's response.\n */\nexport class LessonExtractor {\n constructor(\n private store: FileSkillStore,\n private trust: TrustManager,\n private analyzer: ConversationAnalyzer,\n ) {}\n\n /**\n * Analyze a conversation and extract lessons. Fire-and-forget.\n */\n async extract(\n messages: { role: string; content: string; name?: string }[],\n ): Promise<void> {\n const detection = detectAgentConversation(messages);\n if (!detection.isAgentToAgent) return;\n\n const agentId = detection.otherAgentId ?? 'unknown-agent';\n\n // Check trust level — skip if blocked\n const trustLevel = this.trust.getLevel(agentId);\n if (trustLevel === 'blocked') return;\n\n // Check rate limits\n if (!this.trust.canLearn(agentId)) return;\n\n const exchangeText = extractExchangeText(messages);\n if (exchangeText.length < 20) return;\n\n const prompt = `Analyze this conversation between an AI agent and another agent. Extract concrete, actionable lessons that the first agent (the \"assistant\") can learn from the other agent.\n\nCONVERSATION:\n${exchangeText.slice(0, 4000)}\n\nOutput valid JSON array:\n[{\"skill\": \"skill_name_snake_case\", \"instruction\": \"concrete actionable lesson in 1-2 sentences\", \"confidence\": 0.0-1.0}]\n\nRules:\n- Only extract lessons where the other agent clearly teaches, corrects, or shares useful knowledge\n- instruction must be concrete and actionable (\"use X when Y\" not \"consider improving\")\n- confidence: 0.9 = explicitly taught, 0.7 = clearly implied, 0.5 = suggested, below 0.5 = skip\n- Only include lessons with confidence >= 0.5\n- Max 3 lessons per conversation\n- If no real learning happened, return []`;\n\n try {\n console.log(`[become] extracting lessons from ${agentId} (${detection.exchangeType}), text length: ${exchangeText.length}`);\n const response = await this.analyzer.analyze(prompt);\n const lessons = this.parseLessons(response);\n console.log(`[become] LLM returned ${lessons.length} lessons`);\n\n for (const lesson of lessons.slice(0, 3)) {\n console.log(`[become] saving lesson: ${lesson.skill} (confidence: ${lesson.confidence})`);\n const saved = this.store.savePending({\n name: lesson.skill,\n instruction: lesson.instruction.slice(0, 500),\n learned_from: agentId,\n source: detection.exchangeType ?? 'conversation',\n confidence: lesson.confidence,\n created_at: new Date().toISOString(),\n });\n\n if (saved) {\n console.log(`[become] lesson saved: ${saved.id}`);\n this.trust.recordLesson(agentId);\n\n // Auto-approve if agent is trusted\n if (trustLevel === 'trusted') {\n this.store.approve(saved.id);\n console.log(`[become] auto-approved (trusted agent)`);\n }\n } else {\n console.log(`[become] lesson NOT saved (duplicate or store error)`);\n }\n }\n } catch (err) {\n console.log(`[become] extraction error: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n private parseLessons(response: string): { skill: string; instruction: string; confidence: number }[] {\n const jsonMatch = response.match(/\\[[\\s\\S]*\\]/);\n if (!jsonMatch) return [];\n\n try {\n const parsed = JSON.parse(jsonMatch[0]);\n if (!Array.isArray(parsed)) return [];\n return parsed.filter(\n (r: any) =>\n typeof r.skill === 'string' &&\n typeof r.instruction === 'string' &&\n typeof r.confidence === 'number' &&\n r.confidence >= 0.5 &&\n r.skill.length > 0 &&\n r.instruction.length > 0,\n );\n } catch {\n return [];\n }\n }\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { createHandlers, type DashboardDeps } from './api/handlers.js';\nimport { renderDashboardHTML } from './ui.js';\n\nexport function createDashboardServer(deps: DashboardDeps) {\n const handlers = createHandlers(deps);\n const html = renderDashboardHTML();\n\n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n // CORS restricted to localhost only — prevents external sites from\n // making API calls to the dashboard\n const origin = req.headers.origin ?? '';\n if (origin && /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(:\\d+)?$/.test(origin)) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n }\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Serve dashboard HTML at root\n if (req.url === '/' && req.method === 'GET') {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(html);\n return;\n }\n\n // API routes\n const key = `${req.method} ${req.url}`;\n const handler = handlers[key];\n\n if (!handler) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n return;\n }\n\n try {\n let body: any;\n if (req.method === 'POST' || req.method === 'DELETE') {\n const raw = await readBody(req);\n if (raw) {\n try {\n body = JSON.parse(raw);\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid JSON body' }));\n return;\n }\n }\n }\n\n const result = await handler(body);\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(result));\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Internal server error' }));\n }\n });\n\n return {\n server,\n listen: (port: number) => {\n return new Promise<void>((resolve) => {\n server.listen(port, '127.0.0.1', () => resolve());\n });\n },\n close: () => new Promise<void>((resolve) => server.close(() => resolve())),\n };\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > 1024 * 1024) { req.destroy(); reject(new Error('Too large')); return; }\n chunks.push(chunk);\n });\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n","import type { FileSkillStore } from '../../skills/store.js';\nimport type { TrustManager, TrustLevel } from '../../skills/trust.js';\n\nexport interface DashboardDeps {\n store: FileSkillStore;\n trust: TrustManager;\n getProxyStats: () => { requests_forwarded: number; skills_injected: number; lessons_extracted: number; started_at: string } | null;\n getState: () => 'on' | 'off';\n setState: (state: 'on' | 'off') => void;\n}\n\ntype Handler = (body?: any) => any;\n\nexport function createHandlers(deps: DashboardDeps): Record<string, Handler> {\n const { store, trust, getProxyStats, getState, setState } = deps;\n\n return {\n // ── Status ──────────────────────────────────────────────────────────\n 'GET /api/status': () => ({\n state: getState(),\n skills_count: store.listApproved().length,\n pending_count: store.listPending().length,\n rejected_count: store.listRejected().length,\n proxy: getProxyStats(),\n }),\n\n // ── State toggle ────────────────────────────────────────────────────\n 'POST /api/state': (body) => {\n const newState = body?.state;\n if (newState !== 'on' && newState !== 'off') {\n return { error: 'state must be \"on\" or \"off\"' };\n }\n try {\n setState(newState);\n return { state: newState };\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to change state';\n return { error: msg };\n }\n },\n\n // ── Skills (approved) ───────────────────────────────────────────────\n 'GET /api/skills': () => store.listApproved(),\n\n // ── Pending ─────────────────────────────────────────────────────────\n 'GET /api/pending': () => store.listPending(),\n\n // ── Rejected ────────────────────────────────────────────────────────\n 'GET /api/rejected': () => store.listRejected(),\n\n // ── Approve ─────────────────────────────────────────────────────────\n 'POST /api/approve': (body) => {\n const id = body?.id;\n if (!id || typeof id !== 'string') return { error: 'id required' };\n const ok = store.approve(id);\n return ok ? { ok: true } : { error: 'not found' };\n },\n\n // ── Reject ──────────────────────────────────────────────────────────\n 'POST /api/reject': (body) => {\n const id = body?.id;\n if (!id || typeof id !== 'string') return { error: 'id required' };\n const ok = store.reject(id);\n return ok ? { ok: true } : { error: 'not found' };\n },\n\n // ── Disable (approved → rejected) ───────────────────────────────────\n 'POST /api/disable': (body) => {\n const id = body?.id;\n if (!id || typeof id !== 'string') return { error: 'id required' };\n const ok = store.disable(id);\n return ok ? { ok: true } : { error: 'not found' };\n },\n\n // ── Remove permanently ──────────────────────────────────────────────\n 'DELETE /api/skill': (body) => {\n const id = body?.id;\n if (!id || typeof id !== 'string') return { error: 'id required' };\n const ok = store.remove(id);\n return ok ? { ok: true } : { error: 'not found' };\n },\n\n // ── Trust ───────────────────────────────────────────────────────────\n 'GET /api/trust': () => trust.getConfig(),\n\n 'POST /api/trust': (body) => {\n const { agent, level } = body ?? {};\n if (!agent || typeof agent !== 'string') return { error: 'agent required' };\n if (!['trusted', 'pending', 'blocked'].includes(level)) return { error: 'level must be trusted/pending/blocked' };\n trust.setLevel(agent, level as TrustLevel);\n return { ok: true };\n },\n\n 'POST /api/trust/default': (body) => {\n const { level } = body ?? {};\n if (!['trusted', 'pending', 'blocked'].includes(level)) return { error: 'level must be trusted/pending/blocked' };\n trust.setDefault(level as TrustLevel);\n return { ok: true };\n },\n\n // ── Network ─────────────────────────────────────────────────────────\n 'GET /api/network': () => {\n const approved = store.listApproved();\n const pending = store.listPending();\n const all = [...approved, ...pending];\n\n const agents: Record<string, { lessons: number; skills: string[]; trust: string }> = {};\n for (const skill of all) {\n const id = skill.learned_from;\n if (!agents[id]) {\n agents[id] = { lessons: 0, skills: [], trust: trust.getLevel(id) };\n }\n agents[id].lessons++;\n if (!agents[id].skills.includes(skill.name)) {\n agents[id].skills.push(skill.name);\n }\n }\n return agents;\n },\n\n // ── Stats ───────────────────────────────────────────────────────────\n 'GET /api/stats': () => {\n const counts = trust.getDailyCounts();\n return {\n today_lessons: counts.total,\n today_per_agent: counts.perAgent,\n total_approved: store.listApproved().length,\n total_pending: store.listPending().length,\n total_rejected: store.listRejected().length,\n proxy: getProxyStats(),\n };\n },\n };\n}\n","/**\n * Server-rendered HTML for the become dashboard.\n * Single-page app with vanilla JS — no build step needed.\n */\nexport function renderDashboardHTML(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>become</title>\n<style>\n :root { --bg: #0a0a0a; --card: #141414; --border: #262626; --text: #e5e5e5; --dim: #737373; --accent: #22d3ee; --green: #22c55e; --red: #ef4444; --amber: #f59e0b; }\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); line-height: 1.6; }\n .container { max-width: 800px; margin: 0 auto; padding: 20px; }\n h1 { font-size: 24px; font-weight: 600; margin-bottom: 4px; }\n h2 { font-size: 18px; font-weight: 600; margin-bottom: 12px; color: var(--accent); }\n .subtitle { color: var(--dim); font-size: 14px; margin-bottom: 24px; }\n\n /* Nav */\n nav { display: flex; gap: 4px; margin-bottom: 24px; border-bottom: 1px solid var(--border); padding-bottom: 8px; }\n nav button { background: none; border: none; color: var(--dim); font-size: 14px; padding: 8px 16px; cursor: pointer; border-radius: 6px 6px 0 0; }\n nav button:hover { color: var(--text); }\n nav button.active { color: var(--accent); border-bottom: 2px solid var(--accent); }\n\n /* Status bar */\n .status-bar { display: flex; gap: 16px; align-items: center; margin-bottom: 24px; padding: 12px 16px; background: var(--card); border: 1px solid var(--border); border-radius: 8px; font-size: 13px; }\n .status-dot { width: 8px; height: 8px; border-radius: 50%; }\n .status-dot.on { background: var(--green); }\n .status-dot.off { background: var(--red); }\n .status-label { font-weight: 600; }\n .status-stat { color: var(--dim); }\n\n /* Cards */\n .card { background: var(--card); border: 1px solid var(--border); border-radius: 8px; padding: 16px; margin-bottom: 12px; }\n .card-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px; }\n .card-instruction { font-size: 15px; margin-bottom: 8px; }\n .card-meta { font-size: 12px; color: var(--dim); display: flex; gap: 12px; flex-wrap: wrap; }\n .card-meta span { display: inline-flex; align-items: center; gap: 4px; }\n\n /* Buttons */\n .btn { border: none; padding: 6px 14px; border-radius: 6px; font-size: 13px; cursor: pointer; font-weight: 500; }\n .btn-approve { background: var(--green); color: #000; }\n .btn-reject { background: var(--red); color: #fff; }\n .btn-disable { background: var(--border); color: var(--text); }\n .btn-trust { background: var(--accent); color: #000; }\n .btn-small { padding: 4px 10px; font-size: 12px; }\n .btn:hover { opacity: 0.85; }\n .btn-group { display: flex; gap: 6px; }\n\n /* Badge */\n .badge { font-size: 11px; padding: 2px 8px; border-radius: 10px; font-weight: 500; }\n .badge-trusted { background: rgba(34,197,94,0.15); color: var(--green); }\n .badge-pending { background: rgba(245,158,11,0.15); color: var(--amber); }\n .badge-blocked { background: rgba(239,68,68,0.15); color: var(--red); }\n\n /* Empty state */\n .empty { text-align: center; padding: 40px; color: var(--dim); }\n\n /* Page sections */\n .page { display: none; }\n .page.active { display: block; }\n\n /* Trust settings */\n .trust-row { display: flex; justify-content: space-between; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--border); }\n .trust-row:last-child { border: none; }\n .trust-agent { font-weight: 500; }\n .trust-lessons { font-size: 13px; color: var(--dim); }\n\n /* Skill group */\n .skill-group { margin-bottom: 20px; }\n .skill-group-name { font-size: 13px; text-transform: uppercase; color: var(--dim); letter-spacing: 0.5px; margin-bottom: 8px; }\n\n /* Toggle */\n .toggle { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }\n .toggle-switch { width: 44px; height: 24px; background: var(--border); border-radius: 12px; position: relative; cursor: pointer; transition: background 0.2s; }\n .toggle-switch.on { background: var(--green); }\n .toggle-switch::after { content: ''; position: absolute; width: 18px; height: 18px; background: white; border-radius: 50%; top: 3px; left: 3px; transition: transform 0.2s; }\n .toggle-switch.on::after { transform: translateX(20px); }\n</style>\n</head>\n<body>\n<div class=\"container\">\n <h1>become</h1>\n <p class=\"subtitle\">agent-to-agent learning</p>\n\n <div class=\"status-bar\" id=\"status-bar\">\n <div class=\"status-dot\" id=\"status-dot\"></div>\n <span class=\"status-label\" id=\"status-label\">Loading...</span>\n <span class=\"status-stat\" id=\"status-skills\"></span>\n <span class=\"status-stat\" id=\"status-pending\"></span>\n </div>\n\n <nav>\n <button class=\"active\" onclick=\"showPage('pending',this)\">Pending</button>\n <button onclick=\"showPage('skills',this)\">Active Skills</button>\n <button onclick=\"showPage('network',this)\">Network</button>\n <button onclick=\"showPage('settings',this)\">Settings</button>\n </nav>\n\n <!-- Pending Page -->\n <div id=\"page-pending\" class=\"page active\"></div>\n\n <!-- Skills Page -->\n <div id=\"page-skills\" class=\"page\"></div>\n\n <!-- Network Page -->\n <div id=\"page-network\" class=\"page\"></div>\n\n <!-- Settings Page -->\n <div id=\"page-settings\" class=\"page\"></div>\n</div>\n\n<script>\nconst API = '';\n\nasync function api(method, path, body) {\n const opts = { method, headers: { 'Content-Type': 'application/json' } };\n if (body) opts.body = JSON.stringify(body);\n const res = await fetch(API + path, opts);\n return res.json();\n}\n\nfunction showPage(name, btn) {\n document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));\n document.getElementById('page-' + name).classList.add('active');\n document.querySelectorAll('nav button').forEach(b => b.classList.remove('active'));\n if (btn) btn.classList.add('active');\n if (name === 'pending') loadPending();\n if (name === 'skills') loadSkills();\n if (name === 'network') loadNetwork();\n if (name === 'settings') loadSettings();\n}\n\n// ── Status Bar ────────────────────────────────────────────────────────\nasync function loadStatus() {\n const s = await api('GET', '/api/status');\n const dot = document.getElementById('status-dot');\n const label = document.getElementById('status-label');\n dot.className = 'status-dot ' + s.state;\n label.textContent = s.state.toUpperCase();\n document.getElementById('status-skills').textContent = s.skills_count + ' skills';\n document.getElementById('status-pending').textContent = s.pending_count + ' pending';\n}\n\n// ── Pending Page ──────────────────────────────────────────────────────\nasync function loadPending() {\n const lessons = await api('GET', '/api/pending');\n const el = document.getElementById('page-pending');\n if (lessons.length === 0) {\n el.innerHTML = '<div class=\"empty\">No pending lessons. Your agent will learn as it talks to other agents.</div>';\n return;\n }\n el.innerHTML = '<h2>Pending Review (' + lessons.length + ')</h2>' +\n lessons.map(l => renderPendingCard(l)).join('');\n}\n\nfunction renderPendingCard(l) {\n return '<div class=\"card\" id=\"card-' + l.id + '\">' +\n '<div class=\"card-instruction\">' + esc(l.instruction) + '</div>' +\n '<div class=\"card-meta\">' +\n '<span>From: <strong>' + esc(l.learned_from) + '</strong></span>' +\n '<span>Source: ' + esc(l.source) + '</span>' +\n '<span>Confidence: ' + (l.confidence * 100).toFixed(0) + '%</span>' +\n '<span>Skill: ' + esc(l.name) + '</span>' +\n '</div>' +\n '<div style=\"margin-top:12px\" class=\"btn-group\">' +\n '<button class=\"btn btn-approve\" onclick=\"doApprove(\\\\''+l.id+'\\\\')\">Approve</button>' +\n '<button class=\"btn btn-reject\" onclick=\"doReject(\\\\''+l.id+'\\\\')\">Reject</button>' +\n '<button class=\"btn btn-trust btn-small\" onclick=\"doTrustAgent(\\\\''+esc(l.learned_from)+'\\\\')\">Trust Agent</button>' +\n '</div>' +\n '</div>';\n}\n\nasync function doApprove(id) {\n await api('POST', '/api/approve', { id });\n document.getElementById('card-' + id)?.remove();\n loadStatus();\n}\n\nasync function doReject(id) {\n await api('POST', '/api/reject', { id });\n document.getElementById('card-' + id)?.remove();\n loadStatus();\n}\n\nasync function doTrustAgent(agent) {\n await api('POST', '/api/trust', { agent, level: 'trusted' });\n loadPending();\n loadStatus();\n}\n\n// ── Skills Page ───────────────────────────────────────────────────────\nasync function loadSkills() {\n const skills = await api('GET', '/api/skills');\n const el = document.getElementById('page-skills');\n if (skills.length === 0) {\n el.innerHTML = '<div class=\"empty\">No active skills yet. Approve pending lessons to activate them.</div>';\n return;\n }\n\n // Group by skill name\n const groups = {};\n for (const s of skills) {\n if (!groups[s.name]) groups[s.name] = [];\n groups[s.name].push(s);\n }\n\n let html = '<h2>Active Skills (' + skills.length + ')</h2>';\n for (const [name, items] of Object.entries(groups)) {\n html += '<div class=\"skill-group\"><div class=\"skill-group-name\">' + esc(name) + '</div>';\n for (const s of items) {\n html += '<div class=\"card\" id=\"card-' + s.id + '\">' +\n '<div class=\"card-header\"><div class=\"card-instruction\">' + esc(s.instruction) + '</div>' +\n '<button class=\"btn btn-disable btn-small\" onclick=\"doDisable(\\\\''+s.id+'\\\\')\">Disable</button></div>' +\n '<div class=\"card-meta\"><span>From: ' + esc(s.learned_from) + '</span><span>Source: ' + esc(s.source) + '</span></div>' +\n '</div>';\n }\n html += '</div>';\n }\n el.innerHTML = html;\n}\n\nasync function doDisable(id) {\n await api('POST', '/api/disable', { id });\n document.getElementById('card-' + id)?.remove();\n loadStatus();\n}\n\n// ── Network Page ──────────────────────────────────────────────────────\nasync function loadNetwork() {\n const network = await api('GET', '/api/network');\n const el = document.getElementById('page-network');\n const entries = Object.entries(network);\n if (entries.length === 0) {\n el.innerHTML = '<div class=\"empty\">No agents have taught yours yet.</div>';\n return;\n }\n\n let html = '<h2>Who Taught Your Agent</h2>';\n entries.sort((a, b) => b[1].lessons - a[1].lessons);\n for (const [agent, data] of entries) {\n const d = data;\n const badgeClass = 'badge badge-' + d.trust;\n html += '<div class=\"card\"><div class=\"trust-row\">' +\n '<div><div class=\"trust-agent\">' + esc(agent) + ' <span class=\"' + badgeClass + '\">' + d.trust + '</span></div>' +\n '<div class=\"trust-lessons\">' + d.lessons + ' lesson(s): ' + d.skills.map(esc).join(', ') + '</div></div>' +\n '<div class=\"btn-group\">' +\n (d.trust !== 'trusted' ? '<button class=\"btn btn-trust btn-small\" onclick=\"setTrust(\\\\''+esc(agent)+'\\\\',\\\\'trusted\\\\')\">Trust</button>' : '') +\n (d.trust !== 'blocked' ? '<button class=\"btn btn-reject btn-small\" onclick=\"setTrust(\\\\''+esc(agent)+'\\\\',\\\\'blocked\\\\')\">Block</button>' : '') +\n (d.trust !== 'pending' ? '<button class=\"btn btn-disable btn-small\" onclick=\"setTrust(\\\\''+esc(agent)+'\\\\',\\\\'pending\\\\')\">Reset</button>' : '') +\n '</div>' +\n '</div></div>';\n }\n el.innerHTML = html;\n}\n\nasync function setTrust(agent, level) {\n await api('POST', '/api/trust', { agent, level });\n loadNetwork();\n}\n\n// ── Settings Page ─────────────────────────────────────────────────────\nasync function loadSettings() {\n const status = await api('GET', '/api/status');\n const trust = await api('GET', '/api/trust');\n const stats = await api('GET', '/api/stats');\n\n const el = document.getElementById('page-settings');\n el.innerHTML = '<h2>Settings</h2>' +\n '<div class=\"card\">' +\n '<div class=\"toggle\">' +\n '<div class=\"toggle-switch ' + status.state + '\" id=\"toggle-state\" onclick=\"toggleState()\"></div>' +\n '<span>Proxy is <strong>' + status.state.toUpperCase() + '</strong></span>' +\n '</div>' +\n '</div>' +\n '<div class=\"card\">' +\n '<h2 style=\"margin-bottom:8px\">Default Trust</h2>' +\n '<div class=\"card-meta\" style=\"margin-bottom:12px\">What happens when a new agent teaches your agent</div>' +\n '<div class=\"btn-group\">' +\n '<button class=\"btn ' + (trust.default === 'pending' ? 'btn-approve' : 'btn-disable') + '\" onclick=\"setDefaultTrust(\\\\'pending\\\\')\">Pending (review)</button>' +\n '<button class=\"btn ' + (trust.default === 'trusted' ? 'btn-approve' : 'btn-disable') + '\" onclick=\"setDefaultTrust(\\\\'trusted\\\\')\">Auto-approve</button>' +\n '<button class=\"btn ' + (trust.default === 'blocked' ? 'btn-approve' : 'btn-disable') + '\" onclick=\"setDefaultTrust(\\\\'blocked\\\\')\">Block all</button>' +\n '</div>' +\n '</div>' +\n '<div class=\"card\">' +\n '<h2 style=\"margin-bottom:8px\">Stats</h2>' +\n '<div class=\"card-meta\" style=\"flex-direction:column;gap:4px\">' +\n '<span>Approved: ' + stats.total_approved + '</span>' +\n '<span>Pending: ' + stats.total_pending + '</span>' +\n '<span>Rejected: ' + stats.total_rejected + '</span>' +\n '<span>Lessons today: ' + stats.today_lessons + '</span>' +\n '</div>' +\n '</div>' +\n '<div class=\"card\">' +\n '<h2 style=\"margin-bottom:8px;color:var(--red)\">Danger Zone</h2>' +\n '<div class=\"btn-group\">' +\n '<button class=\"btn btn-reject\" onclick=\"if(confirm(\\\\'Clear all skills?\\\\'))clearAll()\">Clear All Skills</button>' +\n '</div>' +\n '</div>';\n}\n\nasync function toggleState() {\n const el = document.getElementById('toggle-state');\n const newState = el.classList.contains('on') ? 'off' : 'on';\n await api('POST', '/api/state', { state: newState });\n loadStatus();\n loadSettings();\n}\n\nasync function setDefaultTrust(level) {\n await api('POST', '/api/trust/default', { level });\n loadSettings();\n}\n\nasync function clearAll() {\n const skills = await api('GET', '/api/skills');\n for (const s of skills) {\n await api('DELETE', '/api/skill', { id: s.id });\n }\n loadStatus();\n loadSettings();\n}\n\nfunction esc(s) {\n if (!s) return '';\n return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"').replace(/'/g,''');\n}\n\n// Init\nloadStatus();\nloadPending();\nsetInterval(loadStatus, 10000);\n</script>\n</body>\n</html>`;\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, unlinkSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { execSync } from 'node:child_process';\nimport type { BecomeConfig } from '../config.js';\n\n// IronClaw .env is at ~/.ironclaw/.env (overridable via IRONCLAW_BASE_DIR)\n// Source: https://github.com/nearai/ironclaw src/service.rs, .env.example\nconst IRONCLAW_ENV = join(process.env.IRONCLAW_BASE_DIR ?? join(homedir(), '.ironclaw'), '.env');\nconst BACKUP_PATH = join(homedir(), '.become', 'state', 'original_ironclaw.env');\nconst ORIGINAL_URL_PATH = join(homedir(), '.become', 'state', 'original_base_url.txt');\n\nexport function patchIronClaw(config: BecomeConfig): void {\n if (!existsSync(IRONCLAW_ENV)) {\n throw new Error(`IronClaw .env not found at ${IRONCLAW_ENV}`);\n }\n\n // Don't patch twice\n if (existsSync(BACKUP_PATH)) {\n console.log('become is already connected to IronClaw. Run `become off` first.');\n return;\n }\n\n // Backup\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n copyFileSync(IRONCLAW_ENV, BACKUP_PATH);\n\n // Read current .env to determine which var to patch\n // IronClaw uses LLM_BACKEND to select provider. Each provider has its own base URL var.\n // Source: src/config/llm.rs\n const content = readFileSync(IRONCLAW_ENV, 'utf-8');\n const backendMatch = content.match(/^LLM_BACKEND=(.+)$/m);\n const backend = backendMatch?.[1]?.trim().toLowerCase() ?? 'openai_compatible';\n\n const proxyUrl = `http://127.0.0.1:${config.proxy_port}`;\n const vars: Record<string, string> = {};\n\n // Patch the correct base URL var for the active backend\n switch (backend) {\n case 'anthropic':\n vars['ANTHROPIC_BASE_URL'] = proxyUrl;\n break;\n case 'ollama':\n vars['OLLAMA_BASE_URL'] = proxyUrl;\n break;\n case 'nearai':\n case 'near_ai':\n case 'near':\n vars['NEARAI_BASE_URL'] = proxyUrl;\n break;\n default:\n // openai, openai_compatible, openrouter, or any unknown value\n vars['LLM_BASE_URL'] = proxyUrl;\n break;\n }\n\n // Save the original URL so the proxy knows where to forward\n const urlVarName = Object.keys(vars)[0];\n const originalUrlMatch = content.match(new RegExp(`^${urlVarName}=(.+)$`, 'm'));\n const originalUrl = originalUrlMatch?.[1]?.trim() ?? '';\n if (originalUrl) {\n writeFileSync(ORIGINAL_URL_PATH, originalUrl, 'utf-8');\n }\n\n patchDotEnv(IRONCLAW_ENV, vars);\n\n console.log(` backend: ${backend}`);\n console.log(` patched: ${Object.keys(vars).join(', ')} -> localhost:${config.proxy_port}`);\n\n restartIronClaw();\n}\n\nexport function restoreIronClaw(): void {\n if (!existsSync(BACKUP_PATH)) {\n return;\n }\n copyFileSync(BACKUP_PATH, IRONCLAW_ENV);\n try { unlinkSync(BACKUP_PATH); } catch {}\n restartIronClaw();\n}\n\n// IronClaw has no `restart` command. Must stop + start.\n// CLI: ironclaw service {install,start,stop,status,uninstall}\n// macOS label: com.ironclaw.daemon\n// Linux unit: ironclaw.service (~/.config/systemd/user/)\n// Source: src/cli/service.rs, src/service.rs\nfunction restartIronClaw(): void {\n console.log('Restarting IronClaw...');\n\n // Try CLI stop + start first\n try {\n execSync('ironclaw service stop', { stdio: 'pipe', timeout: 10000 });\n execSync('ironclaw service start', { stdio: 'pipe', timeout: 10000 });\n console.log('IronClaw restarted.');\n return;\n } catch {}\n\n // Fallback: try launchctl (macOS)\n try {\n execSync('launchctl kickstart -k gui/$(id -u)/com.ironclaw.daemon', { stdio: 'pipe', timeout: 10000 });\n console.log('IronClaw restarted via launchctl.');\n return;\n } catch {}\n\n // Fallback: try systemd (Linux)\n try {\n execSync('systemctl --user restart ironclaw', { stdio: 'pipe', timeout: 10000 });\n console.log('IronClaw restarted via systemd.');\n return;\n } catch {}\n\n console.log('\\n*** IronClaw needs a manual restart. ***');\n console.log('*** Run: ironclaw service stop && ironclaw service start ***\\n');\n}\n\nfunction patchDotEnv(path: string, vars: Record<string, string>): void {\n let content = existsSync(path) ? readFileSync(path, 'utf-8') : '';\n for (const [key, value] of Object.entries(vars)) {\n const regex = new RegExp(`^${key}=.*$`, 'm');\n if (regex.test(content)) {\n content = content.replace(regex, `${key}=${value}`);\n } else {\n content = content.trimEnd() + (content.length > 0 ? '\\n' : '') + `${key}=${value}\\n`;\n }\n }\n writeFileSync(path, content, 'utf-8');\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, unlinkSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { execSync } from 'node:child_process';\nimport type { BecomeConfig } from '../config.js';\n\n// NanoClaw .env lives in the project root (where nanoclaw was cloned/installed).\n// NOT in ~/.nanoclaw/ (that doesn't exist).\n// Source: https://github.com/qwibitai/nanoclaw src/env.ts reads process.cwd()/.env\nconst BACKUP_PATH = join(homedir(), '.become', 'state', 'original_nanoclaw.env');\nconst PATCHED_ENV_PATH_FILE = join(homedir(), '.become', 'state', 'nanoclaw_env_path.txt');\nconst ORIGINAL_URL_PATH = join(homedir(), '.become', 'state', 'original_base_url.txt');\n\n// NanoClaw uses ANTHROPIC_BASE_URL for custom LLM endpoints.\n// It routes everything through a credential proxy (OneCLI) that\n// forwards to Anthropic or a custom ANTHROPIC_BASE_URL.\n// Source: GitHub README, src/config.ts\nconst NANOCLAW_URL_VAR = 'ANTHROPIC_BASE_URL';\n\nexport function patchNanoClaw(config: BecomeConfig): void {\n const envPath = findNanoClawEnv();\n if (!envPath) {\n throw new Error(\n 'Could not find NanoClaw .env file.\\n' +\n 'NanoClaw stores .env in its project root (where you cloned it).\\n' +\n `Set ${NANOCLAW_URL_VAR}=http://127.0.0.1:${config.proxy_port} manually in your NanoClaw .env file.`\n );\n }\n\n // Don't patch twice\n if (existsSync(BACKUP_PATH)) {\n console.log('become is already connected to NanoClaw. Run `become off` first.');\n return;\n }\n\n // Backup\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n copyFileSync(envPath, BACKUP_PATH);\n writeFileSync(PATCHED_ENV_PATH_FILE, envPath, 'utf-8');\n\n // Save original URL so the proxy knows where to forward\n const content = readFileSync(envPath, 'utf-8');\n const originalMatch = content.match(new RegExp(`^${NANOCLAW_URL_VAR}=(.+)$`, 'm'));\n const originalUrl = originalMatch?.[1]?.trim() ?? '';\n if (originalUrl) {\n writeFileSync(ORIGINAL_URL_PATH, originalUrl, 'utf-8');\n }\n\n // Patch\n patchDotEnv(envPath, {\n [NANOCLAW_URL_VAR]: `http://127.0.0.1:${config.proxy_port}`,\n });\n\n console.log(` env file: ${envPath}`);\n console.log(` patched: ${NANOCLAW_URL_VAR} -> localhost:${config.proxy_port}`);\n\n restartNanoClaw();\n}\n\nexport function restoreNanoClaw(): void {\n if (!existsSync(BACKUP_PATH)) {\n return;\n }\n\n // Use stored path to avoid restoring to wrong file\n let envPath: string | null = null;\n if (existsSync(PATCHED_ENV_PATH_FILE)) {\n envPath = readFileSync(PATCHED_ENV_PATH_FILE, 'utf-8').trim();\n }\n if (!envPath) {\n envPath = findNanoClawEnv();\n }\n if (!envPath) {\n console.log('Warning: Cannot find NanoClaw .env to restore. Backup is at ' + BACKUP_PATH);\n return;\n }\n\n copyFileSync(BACKUP_PATH, envPath);\n try { unlinkSync(BACKUP_PATH); } catch {}\n try { unlinkSync(PATCHED_ENV_PATH_FILE); } catch {}\n restartNanoClaw();\n}\n\nfunction findNanoClawEnv(): string | null {\n const candidates: string[] = [];\n\n // macOS: extract WorkingDirectory from launchd plist\n // Label: com.nanoclaw, plist at ~/Library/LaunchAgents/com.nanoclaw.plist\n // Source: launchd/com.nanoclaw.plist template, setup/service.ts\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', 'com.nanoclaw.plist');\n if (existsSync(plistPath)) {\n try {\n const plist = readFileSync(plistPath, 'utf-8');\n const match = plist.match(/<key>WorkingDirectory<\\/key>\\s*<string>([^<]+)<\\/string>/);\n if (match) candidates.push(join(match[1], '.env'));\n } catch {}\n }\n\n // Linux: extract WorkingDirectory from systemd user unit\n // Unit: ~/.config/systemd/user/nanoclaw.service\n // Source: setup/service.ts\n const userUnit = join(homedir(), '.config', 'systemd', 'user', 'nanoclaw.service');\n if (existsSync(userUnit)) {\n try {\n const unit = readFileSync(userUnit, 'utf-8');\n const match = unit.match(/WorkingDirectory=(.+)/);\n if (match) candidates.push(join(match[1].trim(), '.env'));\n } catch {}\n }\n\n // Linux root: /etc/systemd/system/nanoclaw.service\n const rootUnit = '/etc/systemd/system/nanoclaw.service';\n if (existsSync(rootUnit)) {\n try {\n const unit = readFileSync(rootUnit, 'utf-8');\n const match = unit.match(/WorkingDirectory=(.+)/);\n if (match) candidates.push(join(match[1].trim(), '.env'));\n } catch {}\n }\n\n // Common clone locations\n candidates.push(join(homedir(), 'nanoclaw', '.env'));\n candidates.push('/opt/nanoclaw/.env');\n\n for (const path of candidates) {\n if (existsSync(path)) return path;\n }\n return null;\n}\n\n// NanoClaw restart:\n// macOS: launchctl unload + load (label: com.nanoclaw)\n// Linux user: systemctl --user restart nanoclaw\n// Linux root: sudo systemctl restart nanoclaw\n// Source: setup/service.ts, launchd/com.nanoclaw.plist\nfunction restartNanoClaw(): void {\n console.log('Restarting NanoClaw...');\n\n // macOS: unload + load the plist\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', 'com.nanoclaw.plist');\n if (existsSync(plistPath)) {\n try {\n execSync(`launchctl unload \"${plistPath}\"`, { stdio: 'pipe', timeout: 10000 });\n execSync(`launchctl load \"${plistPath}\"`, { stdio: 'pipe', timeout: 10000 });\n console.log('NanoClaw restarted.');\n return;\n } catch {}\n }\n\n // Linux user-level systemd\n try {\n execSync('systemctl --user restart nanoclaw', { stdio: 'pipe', timeout: 10000 });\n console.log('NanoClaw restarted.');\n return;\n } catch {}\n\n console.log('\\n*** NanoClaw needs a manual restart. ***');\n console.log('*** macOS: launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist && launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist ***');\n console.log('*** Linux: systemctl --user restart nanoclaw ***\\n');\n}\n\nfunction patchDotEnv(path: string, vars: Record<string, string>): void {\n let content = existsSync(path) ? readFileSync(path, 'utf-8') : '';\n for (const [key, value] of Object.entries(vars)) {\n const regex = new RegExp(`^${key}=.*$`, 'm');\n if (regex.test(content)) {\n content = content.replace(regex, `${key}=${value}`);\n } else {\n content = content.trimEnd() + (content.length > 0 ? '\\n' : '') + `${key}=${value}\\n`;\n }\n }\n writeFileSync(path, content, 'utf-8');\n}\n","/**\n * LLM adapter interface — pluggable backend for skill evolution, norm detection, and scoring.\n */\nexport interface LLMAdapter {\n /** Generate a text completion */\n complete(prompt: string, opts?: LLMOptions): Promise<string>;\n\n /** Generate a structured JSON response */\n json<T = unknown>(prompt: string, opts?: LLMOptions): Promise<T>;\n}\n\nexport interface LLMOptions {\n maxTokens?: number;\n temperature?: number;\n model?: string;\n /** Request timeout in milliseconds (default: 60000) */\n timeoutMs?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\n\n// ── OpenAI-compatible adapter ───────────────────────────────────────────\n\nexport interface OpenAIConfig {\n apiKey: string;\n baseUrl?: string;\n model?: string;\n}\n\nexport class OpenAIAdapter implements LLMAdapter {\n private apiKey: string;\n private baseUrl: string;\n private defaultModel: string;\n\n constructor(config: OpenAIConfig) {\n if (!config.apiKey) throw new Error('OpenAI API key is required');\n this.apiKey = config.apiKey;\n this.baseUrl = (config.baseUrl ?? 'https://api.openai.com').replace(/\\/+$/, '');\n this.defaultModel = config.model ?? 'gpt-4o-mini';\n }\n\n async complete(prompt: string, opts?: LLMOptions): Promise<string> {\n const response = await this.request({\n model: opts?.model ?? this.defaultModel,\n messages: [{ role: 'user', content: prompt }],\n max_tokens: opts?.maxTokens ?? 2000,\n temperature: opts?.temperature ?? 0.7,\n }, opts?.timeoutMs);\n return response.choices?.[0]?.message?.content ?? '';\n }\n\n async json<T = unknown>(prompt: string, opts?: LLMOptions): Promise<T> {\n const response = await this.request({\n model: opts?.model ?? this.defaultModel,\n messages: [{ role: 'user', content: prompt }],\n max_tokens: opts?.maxTokens ?? 2000,\n temperature: opts?.temperature ?? 0.3,\n response_format: { type: 'json_object' },\n }, opts?.timeoutMs);\n const text = response.choices?.[0]?.message?.content ?? '{}';\n return JSON.parse(text) as T;\n }\n\n private async request(body: Record<string, unknown>, timeoutMs?: number): Promise<any> {\n const res = await fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs ?? DEFAULT_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'unknown error');\n throw new Error(`OpenAI API error ${res.status}: ${text.slice(0, 200)}`);\n }\n\n return res.json();\n }\n}\n\n// ── Anthropic adapter ───────────────────────────────────────────────────\n\nexport interface AnthropicConfig {\n apiKey: string;\n model?: string;\n}\n\nexport class AnthropicAdapter implements LLMAdapter {\n private apiKey: string;\n private defaultModel: string;\n\n constructor(config: AnthropicConfig) {\n if (!config.apiKey) throw new Error('Anthropic API key is required');\n this.apiKey = config.apiKey;\n this.defaultModel = config.model ?? 'claude-sonnet-4-20250514';\n }\n\n async complete(prompt: string, opts?: LLMOptions): Promise<string> {\n const res = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify({\n model: opts?.model ?? this.defaultModel,\n max_tokens: opts?.maxTokens ?? 2000,\n messages: [{ role: 'user', content: prompt }],\n }),\n signal: AbortSignal.timeout(opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'unknown error');\n throw new Error(`Anthropic API error ${res.status}: ${text.slice(0, 200)}`);\n }\n\n const data = await res.json() as any;\n return data.content?.[0]?.text ?? '';\n }\n\n async json<T = unknown>(prompt: string, opts?: LLMOptions): Promise<T> {\n const text = await this.complete(\n `${prompt}\\n\\nRespond with valid JSON only, no other text.`,\n { ...opts, temperature: opts?.temperature ?? 0.3 },\n );\n // Try parsing the whole text first, then extract JSON\n try {\n return JSON.parse(text.trim()) as T;\n } catch {\n // Extract first valid JSON object or array (non-greedy)\n const match = text.match(/\\{[\\s\\S]*?\\}(?=\\s*$|\\s*[^}\\]])/);\n const arrMatch = text.match(/\\[[\\s\\S]*?\\](?=\\s*$|\\s*[^}\\]])/);\n const candidate = match?.[0] ?? arrMatch?.[0];\n if (!candidate) throw new Error('No JSON found in response');\n return JSON.parse(candidate) as T;\n }\n }\n}\n\n// ── Ollama adapter (local models) ───────────────────────────────────────\n\nexport interface OllamaConfig {\n baseUrl?: string;\n model?: string;\n}\n\nexport class OllamaAdapter implements LLMAdapter {\n private baseUrl: string;\n private defaultModel: string;\n\n constructor(config?: OllamaConfig) {\n this.baseUrl = (config?.baseUrl ?? 'http://localhost:11434').replace(/\\/+$/, '');\n this.defaultModel = config?.model ?? 'llama3.1';\n }\n\n async complete(prompt: string, opts?: LLMOptions): Promise<string> {\n const res = await fetch(`${this.baseUrl}/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: opts?.model ?? this.defaultModel,\n prompt,\n stream: false,\n options: {\n num_predict: opts?.maxTokens ?? 2000,\n temperature: opts?.temperature ?? 0.7,\n },\n }),\n signal: AbortSignal.timeout(opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'unknown error');\n throw new Error(`Ollama error ${res.status}: ${text.slice(0, 200)}`);\n }\n\n const data = await res.json() as any;\n return data.response ?? '';\n }\n\n async json<T = unknown>(prompt: string, opts?: LLMOptions): Promise<T> {\n const res = await fetch(`${this.baseUrl}/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: opts?.model ?? this.defaultModel,\n prompt: `${prompt}\\n\\nRespond with valid JSON only.`,\n stream: false,\n format: 'json',\n options: {\n num_predict: opts?.maxTokens ?? 2000,\n temperature: opts?.temperature ?? 0.3,\n },\n }),\n signal: AbortSignal.timeout(opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'unknown error');\n throw new Error(`Ollama error ${res.status}: ${text.slice(0, 200)}`);\n }\n\n const data = await res.json() as any;\n return JSON.parse(data.response ?? '{}') as T;\n }\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4UT;;;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","names":["import_node_fs","import_node_path","import_node_os","import_node_fs","import_node_path","import_node_os","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_http","readBody","import_node_fs","import_node_path","import_node_os","import_node_child_process","BACKUP_PATH","ORIGINAL_URL_PATH","import_node_fs","import_node_path","import_node_os","import_node_child_process","BACKUP_PATH","ORIGINAL_URL_PATH","patchDotEnv","import_node_fs","import_node_path"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/init.ts","../src/cli/setup.ts","../src/cli/config.ts","../src/cli/adapter/openclaw.ts","../src/cli/commands.ts","../src/proxy/server.ts","../src/skills/store.ts","../src/skills/trust.ts","../src/skills/format.ts","../src/proxy/detector.ts","../src/proxy/extractor.ts","../src/dashboard/server.ts","../src/dashboard/api/handlers.ts","../src/dashboard/ui.ts","../src/cli/adapter/ironclaw.ts","../src/cli/adapter/nanoclaw.ts","../src/adapters/llm.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// Re-export from CLI modules\nexport { runSetup } from './setup.js';\nexport { start, turnOn, turnOff, showStatus } from './commands.js';\n\nimport { runSetup } from './setup.js';\nimport { start, turnOn, turnOff, showStatus } from './commands.js';\nimport { readFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst command = process.argv[2];\n\n// Read version from package.json\nlet VERSION = 'unknown';\ntry {\n const dir = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(dir, '..', 'package.json');\n VERSION = JSON.parse(readFileSync(pkgPath, 'utf-8')).version;\n} catch {\n try {\n const dir = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(dir, '..', '..', 'package.json');\n VERSION = JSON.parse(readFileSync(pkgPath, 'utf-8')).version;\n } catch { /* use 'unknown' */ }\n}\n\nasync function main() {\n switch (command) {\n case 'setup':\n await runSetup();\n break;\n case 'start':\n await start();\n break;\n case 'on':\n turnOn();\n break;\n case 'off':\n turnOff();\n break;\n case 'status':\n showStatus();\n break;\n case '--version':\n case '-v':\n case 'version':\n console.log(`become v${VERSION}`);\n break;\n default:\n console.log(`\nbecome v${VERSION} — agent-to-agent learning\n\nUsage:\n become setup Set up become (interactive wizard)\n become start Start the proxy and dashboard\n become on Route your agent through become\n become off Disconnect — agent talks directly to LLM\n become status Show current status\n become --version Show version\n`);\n }\n}\n\nmain().catch((err) => {\n console.error(err.message);\n process.exit(1);\n});\n","import * as readline from 'node:readline';\nimport { saveConfig, LLM_DEFAULTS, type BecomeConfig } from './config.js';\nimport { listOpenClawAgents } from './adapter/openclaw.js';\n\nconst AGENT_TYPES = ['openclaw', 'ironclaw', 'nanoclaw', 'generic'] as const;\nconst LLM_PROVIDERS = ['anthropic', 'openai', 'ollama', 'openrouter', 'custom'] as const;\n\nfunction ask(rl: readline.Interface, question: string): Promise<string> {\n return new Promise((resolve) => rl.question(question, resolve));\n}\n\nexport async function runSetup(): Promise<void> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n\n try {\n console.log('\\nWelcome to become — agent-to-agent learning.\\n');\n\n // Agent type\n console.log('Which agent runtime are you using?');\n AGENT_TYPES.forEach((t, i) => console.log(` ${i + 1}. ${t}`));\n const agentChoice = await ask(rl, '> ');\n const agentIdx = parseInt(agentChoice, 10) - 1;\n const agent_type = AGENT_TYPES[agentIdx] ?? 'openclaw';\n\n // If OpenClaw, ask which agent to connect\n let openclaw_agent_id: string | undefined;\n if (agent_type === 'openclaw') {\n const agents = listOpenClawAgents();\n if (agents.length > 1) {\n console.log('\\nWhich OpenClaw agent should learn from other agents?');\n agents.forEach((a, i) => console.log(` ${i + 1}. ${a.id} (${a.model})`));\n const agentPick = await ask(rl, '> ');\n const pickIdx = parseInt(agentPick, 10) - 1;\n const picked = agents[pickIdx];\n if (picked && picked.id !== '_defaults') {\n openclaw_agent_id = picked.id;\n }\n } else if (agents.length === 1 && agents[0].id !== '_defaults') {\n openclaw_agent_id = agents[0].id;\n console.log(`\\nOpenClaw agent: ${openclaw_agent_id} (${agents[0].model})`);\n }\n }\n\n // LLM provider\n console.log('\\nWhich LLM provider does your agent use?');\n LLM_PROVIDERS.forEach((p, i) => console.log(` ${i + 1}. ${p}`));\n const llmChoice = await ask(rl, '> ');\n const llmIdx = parseInt(llmChoice, 10) - 1;\n const llm_provider = LLM_PROVIDERS[llmIdx] ?? 'anthropic';\n\n // API key\n const llm_api_key = await ask(rl, '\\nYour API key: ');\n if (!llm_api_key.trim()) {\n console.log('API key is required.');\n process.exit(1);\n }\n\n // Base URL\n const defaultUrl = LLM_DEFAULTS[llm_provider]?.base_url ?? '';\n let llm_base_url = defaultUrl;\n if (llm_provider === 'custom' || !defaultUrl) {\n llm_base_url = await ask(rl, 'LLM base URL: ');\n }\n\n // Ports\n const portInput = await ask(rl, `\\nProxy port (default 30001): `);\n const proxy_port = parseInt(portInput, 10) || 30001;\n const dashInput = await ask(rl, `Dashboard port (default 30002): `);\n const dashboard_port = parseInt(dashInput, 10) || 30002;\n\n const config: BecomeConfig = {\n agent_type,\n openclaw_agent_id,\n llm_provider,\n llm_base_url,\n llm_api_key: llm_api_key.trim(),\n proxy_port,\n dashboard_port,\n auto_extract: true,\n max_skills_per_call: 15,\n max_lessons_per_day: 20,\n state: 'off',\n };\n\n saveConfig(config);\n\n console.log('\\nConfig saved to ~/.become/config.json');\n console.log('Run `become start` to begin. Ctrl+C to stop.\\n');\n } finally {\n rl.close();\n }\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\n\nexport interface BecomeConfig {\n agent_type: 'openclaw' | 'ironclaw' | 'nanoclaw' | 'generic';\n openclaw_agent_id?: string;\n llm_provider: 'anthropic' | 'openai' | 'ollama' | 'openrouter' | 'custom';\n llm_base_url: string;\n llm_api_key: string;\n proxy_port: number;\n dashboard_port: number;\n auto_extract: boolean;\n max_skills_per_call: number;\n max_lessons_per_day: number;\n state: 'on' | 'off';\n}\n\nconst DEFAULT_CONFIG: BecomeConfig = {\n agent_type: 'openclaw',\n llm_provider: 'anthropic',\n llm_base_url: 'https://api.anthropic.com',\n llm_api_key: '',\n proxy_port: 30001,\n dashboard_port: 30002,\n auto_extract: true,\n max_skills_per_call: 15,\n max_lessons_per_day: 20,\n state: 'off',\n};\n\nexport function getBecomeDir(): string {\n return join(homedir(), '.become');\n}\n\nexport function getConfigPath(): string {\n return join(getBecomeDir(), 'config.json');\n}\n\nexport function loadConfig(): BecomeConfig {\n const configPath = getConfigPath();\n if (!existsSync(configPath)) {\n throw new Error('become is not set up. Run `become setup` first.');\n }\n try {\n const raw = readFileSync(configPath, 'utf-8');\n return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };\n } catch {\n throw new Error('Invalid config. Run `become setup` to reconfigure.');\n }\n}\n\nexport function saveConfig(config: BecomeConfig): void {\n const dir = getBecomeDir();\n mkdirSync(dir, { recursive: true });\n mkdirSync(join(dir, 'skills'), { recursive: true });\n mkdirSync(join(dir, 'pending'), { recursive: true });\n mkdirSync(join(dir, 'rejected'), { recursive: true });\n mkdirSync(join(dir, 'state'), { recursive: true });\n writeFileSync(getConfigPath(), JSON.stringify(config, null, 2), 'utf-8');\n}\n\nexport function configExists(): boolean {\n return existsSync(getConfigPath());\n}\n\nexport const LLM_DEFAULTS: Record<string, { base_url: string }> = {\n anthropic: { base_url: 'https://api.anthropic.com' },\n openai: { base_url: 'https://api.openai.com' },\n ollama: { base_url: 'http://localhost:11434' },\n openrouter: { base_url: 'https://openrouter.ai/api' },\n};\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { execSync } from 'node:child_process';\nimport type { BecomeConfig } from '../config.js';\n\nconst OPENCLAW_CONFIG = join(homedir(), '.openclaw', 'openclaw.json');\nconst STATE_DIR = join(homedir(), '.become', 'state');\nconst BACKUP_PATH = join(STATE_DIR, 'original_openclaw.json');\nconst ORIGINAL_URL_PATH = join(STATE_DIR, 'original_base_url.txt');\nconst PATCHED_PROVIDER_PATH = join(STATE_DIR, 'patched_provider.txt');\n\n/**\n * Patch OpenClaw to route through become.\n *\n * Strategy: find the provider that serves the agent's model (e.g. \"openrouter\")\n * and swap its baseUrl to point at the become proxy. Don't add providers,\n * don't rename models, don't touch model IDs. Just swap the URL.\n *\n * Docs: https://docs.openclaw.ai/gateway/configuration-reference\n */\nexport function patchOpenClaw(config: BecomeConfig): void {\n if (!existsSync(OPENCLAW_CONFIG)) {\n throw new Error(`OpenClaw config not found at ${OPENCLAW_CONFIG}`);\n }\n\n const raw = readFileSync(OPENCLAW_CONFIG, 'utf-8');\n const clawConfig = parseConfig(raw);\n mkdirSync(STATE_DIR, { recursive: true });\n\n // Find which provider the primary model uses\n const primaryModel = clawConfig.agents?.defaults?.model?.primary ?? '';\n if (!primaryModel) {\n throw new Error('No default model configured in openclaw.json (agents.defaults.model.primary)');\n }\n\n // Model format is \"provider/model-path\", e.g. \"openrouter/xiaomi/mimo-v2-pro\"\n const providerName = primaryModel.split('/')[0];\n if (!providerName) {\n throw new Error(`Cannot determine provider from model: ${primaryModel}`);\n }\n\n // Check if already patched\n if (existsSync(ORIGINAL_URL_PATH)) {\n const existingUrl = readFileSync(ORIGINAL_URL_PATH, 'utf-8').trim();\n if (existingUrl) {\n console.log('become is already connected. Run `become off` first to disconnect.');\n return;\n }\n }\n\n // Find the provider in models.json (per-agent) or openclaw.json (global)\n const modelsJsonPath = getModelsJsonPath(clawConfig);\n let modelsConfig: any = null;\n let modelsSource: 'models.json' | 'openclaw.json' = 'openclaw.json';\n\n if (modelsJsonPath && existsSync(modelsJsonPath)) {\n modelsConfig = JSON.parse(readFileSync(modelsJsonPath, 'utf-8'));\n modelsSource = 'models.json';\n }\n\n // Try models.json first (per-agent), then openclaw.json global providers\n let provider: any = null;\n let providerLocation: any = null;\n\n if (modelsConfig?.providers?.[providerName]) {\n provider = modelsConfig.providers[providerName];\n providerLocation = modelsConfig.providers;\n } else if (clawConfig.models?.providers?.[providerName]) {\n provider = clawConfig.models.providers[providerName];\n providerLocation = clawConfig.models.providers;\n modelsSource = 'openclaw.json';\n }\n\n if (!provider) {\n throw new Error(\n `Provider \"${providerName}\" not found in models.json or openclaw.json. ` +\n `Your model is \"${primaryModel}\" which needs a \"${providerName}\" provider.`\n );\n }\n\n let originalUrl = provider.baseUrl;\n if (!originalUrl) {\n throw new Error(`Provider \"${providerName}\" has no baseUrl`);\n }\n\n // If the provider URL already points to localhost, it's already patched\n // from a previous run. Read the backup to get the real URL.\n if (originalUrl.includes('127.0.0.1') || originalUrl.includes('localhost')) {\n // Try to recover from backup\n if (existsSync(BACKUP_PATH)) {\n try {\n const backupRaw = readFileSync(BACKUP_PATH, 'utf-8');\n // The backup might be openclaw.json or we need models.json backup\n // For now, just inform the user\n } catch {}\n }\n // Try to read from existing state\n const savedUrl = readSafe(ORIGINAL_URL_PATH);\n if (savedUrl && !savedUrl.includes('127.0.0.1')) {\n originalUrl = savedUrl;\n console.log(` recovered original URL from state: ${originalUrl}`);\n } else {\n throw new Error(\n `Provider \"${providerName}\" baseUrl is already pointing to localhost (${originalUrl}).\\n` +\n 'This means become was previously connected but not properly restored.\\n' +\n 'Fix manually: set the baseUrl back to the real provider URL in:\\n' +\n ` ${modelsSource === 'models.json' ? getModelsJsonPath(clawConfig) : OPENCLAW_CONFIG}`\n );\n }\n }\n\n // Backup\n writeFileSync(BACKUP_PATH, raw, 'utf-8');\n writeFileSync(ORIGINAL_URL_PATH, originalUrl, 'utf-8');\n writeFileSync(PATCHED_PROVIDER_PATH, `${providerName}:${modelsSource}`, 'utf-8');\n\n // Swap the baseUrl to the proxy\n // Don't append /v1. The proxy accepts whatever path OpenClaw sends\n // and forwards it to the original upstream URL with the same path.\n provider.baseUrl = `http://127.0.0.1:${config.proxy_port}`;\n\n // Write back\n if (modelsSource === 'models.json' && modelsJsonPath) {\n writeFileSync(modelsJsonPath, JSON.stringify(modelsConfig, null, 2), 'utf-8');\n } else {\n writeFileSync(OPENCLAW_CONFIG, JSON.stringify(clawConfig, null, 2), 'utf-8');\n }\n\n console.log(` provider: ${providerName}`);\n console.log(` baseUrl: ${originalUrl} -> localhost:${config.proxy_port}`);\n\n // Restart gateway\n restartGateway();\n}\n\nexport function restoreOpenClaw(): void {\n const originalUrl = readSafe(ORIGINAL_URL_PATH);\n const patchInfo = readSafe(PATCHED_PROVIDER_PATH);\n\n if (!originalUrl || !patchInfo) {\n // Nothing to restore, clean up state files\n cleanState();\n return;\n }\n\n const [providerName, source] = patchInfo.split(':');\n\n if (source === 'models.json') {\n // Restore in models.json\n const clawConfig = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n const modelsJsonPath = getModelsJsonPath(clawConfig);\n if (modelsJsonPath && existsSync(modelsJsonPath)) {\n const modelsConfig = JSON.parse(readFileSync(modelsJsonPath, 'utf-8'));\n if (modelsConfig.providers?.[providerName]) {\n modelsConfig.providers[providerName].baseUrl = originalUrl;\n writeFileSync(modelsJsonPath, JSON.stringify(modelsConfig, null, 2), 'utf-8');\n }\n }\n } else {\n // Restore in openclaw.json\n if (existsSync(OPENCLAW_CONFIG)) {\n const clawConfig = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n if (clawConfig.models?.providers?.[providerName]) {\n clawConfig.models.providers[providerName].baseUrl = originalUrl;\n writeFileSync(OPENCLAW_CONFIG, JSON.stringify(clawConfig, null, 2), 'utf-8');\n }\n }\n }\n\n // Clean up legacy mess from old become versions (v1.0.1-v1.0.14)\n // that added a \"become\" provider and changed model IDs\n cleanLegacy();\n\n cleanState();\n restartGateway();\n}\n\n/**\n * Remove artifacts from old become versions that added a \"become\" provider\n * and changed model IDs to \"become/...\". This runs on every restore.\n */\nfunction cleanLegacy(): void {\n // Clean openclaw.json\n if (existsSync(OPENCLAW_CONFIG)) {\n try {\n const config = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n let changed = false;\n\n // Remove become provider\n if (config.models?.providers?.become) {\n delete config.models.providers.become;\n changed = true;\n }\n\n // Fix model ID if it starts with become/\n const primary = config.agents?.defaults?.model?.primary ?? '';\n if (primary.startsWith('become/')) {\n config.agents.defaults.model.primary = 'openrouter/' + primary.slice('become/'.length);\n changed = true;\n }\n\n // Remove _originalModel from any provider\n for (const prov of Object.values(config.models?.providers ?? {})) {\n if (prov && typeof prov === 'object' && '_originalModel' in prov) {\n delete (prov as Record<string, unknown>)._originalModel;\n changed = true;\n }\n }\n\n if (changed) writeFileSync(OPENCLAW_CONFIG, JSON.stringify(config, null, 2), 'utf-8');\n } catch {}\n }\n\n // Clean models.json\n try {\n const clawConfig = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n const modelsJsonPath = getModelsJsonPath(clawConfig);\n if (modelsJsonPath && existsSync(modelsJsonPath)) {\n const models = JSON.parse(readFileSync(modelsJsonPath, 'utf-8'));\n let changed = false;\n\n if (models.providers?.become) {\n delete models.providers.become;\n changed = true;\n }\n\n if (changed) writeFileSync(modelsJsonPath, JSON.stringify(models, null, 2), 'utf-8');\n }\n } catch {}\n}\n\nexport function listOpenClawAgents(): { id: string; model: string }[] {\n if (!existsSync(OPENCLAW_CONFIG)) return [];\n try {\n const config = parseConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n const agents: any[] = config.agents?.list ?? [];\n const defaultModel = config.agents?.defaults?.model?.primary ?? 'unknown';\n\n if (agents.length === 0) {\n return [{ id: '_defaults', model: defaultModel }];\n }\n return agents.map((a: any) => ({\n id: a.id,\n model: a.model ?? defaultModel,\n }));\n } catch {\n return [];\n }\n}\n\nexport function isOpenClawPatched(): boolean {\n return existsSync(ORIGINAL_URL_PATH) && readSafe(ORIGINAL_URL_PATH) !== '';\n}\n\n// -- Helpers --\n\nfunction getModelsJsonPath(clawConfig: any): string | null {\n // Per-agent models.json path\n const agentList = clawConfig.agents?.list ?? [];\n const defaultAgent = agentList.find((a: any) => a.default) ?? agentList[0];\n\n if (defaultAgent?.agentDir) {\n return join(defaultAgent.agentDir.replace('~', homedir()), 'models.json');\n }\n\n // Default location\n const mainPath = join(homedir(), '.openclaw', 'agents', 'main', 'agent', 'models.json');\n if (existsSync(mainPath)) return mainPath;\n\n return null;\n}\n\nfunction parseConfig(raw: string): any {\n const stripped = raw\n .replace(/\\/\\/.*$/gm, '')\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/,\\s*([\\]}])/g, '$1');\n return JSON.parse(stripped);\n}\n\nfunction readSafe(path: string): string {\n try {\n return existsSync(path) ? readFileSync(path, 'utf-8').trim() : '';\n } catch {\n return '';\n }\n}\n\nfunction cleanState(): void {\n for (const f of [ORIGINAL_URL_PATH, PATCHED_PROVIDER_PATH]) {\n try { writeFileSync(f, '', 'utf-8'); } catch {}\n }\n}\n\nfunction restartGateway(): void {\n console.log('Restarting OpenClaw gateway...');\n try {\n execSync('openclaw gateway restart', { stdio: 'pipe', timeout: 15000 });\n console.log('OpenClaw gateway restarted.');\n } catch {\n console.log('\\n*** OpenClaw gateway needs a manual restart. ***');\n console.log('*** Run: openclaw gateway restart ***\\n');\n }\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { loadConfig, saveConfig, getBecomeDir, type BecomeConfig } from './config.js';\nimport { createProxyServer, type ProxyConfig } from '../proxy/server.js';\nimport { createDashboardServer } from '../dashboard/server.js';\nimport { FileSkillStore } from '../skills/store.js';\nimport { TrustManager } from '../skills/trust.js';\nimport { patchOpenClaw, restoreOpenClaw } from './adapter/openclaw.js';\nimport { patchIronClaw, restoreIronClaw } from './adapter/ironclaw.js';\nimport { patchNanoClaw, restoreNanoClaw } from './adapter/nanoclaw.js';\nimport { OpenAIAdapter, AnthropicAdapter, OllamaAdapter } from '../adapters/llm.js';\nimport type { ConversationAnalyzer } from '../learn/agent-conversations.js';\n\n/**\n * Create the LLM analyzer for lesson extraction.\n * This calls the LLM DIRECTLY (not through the proxy) to analyze conversations.\n */\nfunction createAnalyzer(config: BecomeConfig): ConversationAnalyzer {\n switch (config.llm_provider) {\n case 'anthropic':\n return { analyze: (p) => new AnthropicAdapter({ apiKey: config.llm_api_key }).complete(p) };\n case 'ollama':\n return { analyze: (p) => new OllamaAdapter({ baseUrl: config.llm_base_url }).complete(p) };\n case 'openai':\n case 'openrouter':\n case 'custom':\n default:\n return { analyze: (p) => new OpenAIAdapter({ apiKey: config.llm_api_key, baseUrl: config.llm_base_url }).complete(p) };\n }\n}\n\nexport async function start(): Promise<void> {\n const config = loadConfig();\n const baseDir = getBecomeDir();\n\n const proxyConfig: ProxyConfig = {\n port: config.proxy_port,\n llm_base_url: config.llm_base_url,\n llm_api_key: config.llm_api_key,\n llm_provider: config.llm_provider,\n baseDir,\n max_skills_per_call: config.max_skills_per_call,\n auto_extract: config.auto_extract,\n };\n\n // Connect agent FIRST so the state file with the original URL exists\n // Always run turnOn() even if state is 'on', because the state file might be missing\n try {\n turnOn();\n } catch (e) {\n console.error('Warning: could not connect agent:', e instanceof Error ? e.message : e);\n }\n\n // Read the original provider URL (written by turnOn -> patchOpenClaw/IronClaw/NanoClaw)\n const originalUrlPath = join(homedir(), '.become', 'state', 'original_base_url.txt');\n let upstreamUrl = config.llm_base_url; // fallback\n if (existsSync(originalUrlPath)) {\n const saved = readFileSync(originalUrlPath, 'utf-8').trim();\n if (saved) upstreamUrl = saved;\n }\n\n // SAFETY: never forward to ourselves (infinite loop -> OOM crash)\n if (upstreamUrl.includes('127.0.0.1') || upstreamUrl.includes('localhost')) {\n const port = config.proxy_port.toString();\n if (upstreamUrl.includes(`:${port}`)) {\n console.error(`\\nFATAL: upstream URL ${upstreamUrl} points to the become proxy itself.`);\n console.error('This would cause an infinite loop. Aborting.');\n console.error('Run `become off` to restore your config, then `become start` again.\\n');\n process.exit(1);\n }\n }\n\n console.log(`[become] upstream: ${upstreamUrl}`);\n\n const analyzer = createAnalyzer(config);\n const proxy = createProxyServer(proxyConfig, analyzer, upstreamUrl);\n await proxy.listen();\n\n // Start dashboard\n const dashboard = createDashboardServer({\n store: proxy.store,\n trust: proxy.trust,\n getProxyStats: () => proxy.stats,\n getState: () => {\n try { return loadConfig().state; } catch { return 'off'; }\n },\n setState: (state) => {\n try {\n if (state === 'on') turnOn();\n else turnOff();\n } catch (e) {\n console.error('State change failed:', e);\n }\n },\n });\n await dashboard.listen(config.dashboard_port);\n\n const approved = proxy.store.listApproved().length;\n const pending = proxy.store.listPending().length;\n const trustConfig = proxy.trust.getConfig();\n\n console.log(`\\nbecome proxy running on localhost:${config.proxy_port}`);\n console.log(`become dashboard at http://localhost:${config.dashboard_port}`);\n console.log(`\\nConnected to: ${config.agent_type}${config.openclaw_agent_id ? ` (agent: ${config.openclaw_agent_id})` : ''}`);\n console.log(`Skills loaded: ${approved} approved, ${pending} pending`);\n console.log(`Trust rules: ${trustConfig.trusted.length} trusted, ${trustConfig.blocked.length} blocked`);\n console.log('\\nYour agent is learning from other agents.');\n console.log('Dashboard: http://localhost:' + config.dashboard_port);\n console.log('Ctrl+C to stop.');\n\n // Wait a few seconds then check if any request has come through\n setTimeout(() => {\n if (proxy.stats.requests_forwarded === 0) {\n console.log('\\nWaiting for first request from your agent...');\n console.log('(If nothing happens, make sure your agent is running and talking to other agents)');\n }\n }, 10000);\n\n // Periodically log activity so user knows it's working\n const activityInterval = setInterval(() => {\n const s = proxy.stats;\n if (s.requests_forwarded > 0) {\n console.log(`[become] ${s.requests_forwarded} requests forwarded, ${s.skills_injected} skills injected, ${s.lessons_extracted} lessons extracted`);\n }\n }, 60000);\n\n // Handle shutdown: run once, don't block on gateway restart\n let shuttingDown = false;\n const shutdown = () => {\n if (shuttingDown) { process.exit(0); return; }\n shuttingDown = true;\n clearInterval(activityInterval);\n console.log('\\nShutting down...');\n try { turnOff(); } catch { /* best effort */ }\n proxy.close().catch(() => {});\n dashboard.close().catch(() => {});\n // Exit immediately, don't wait for gateway restart\n setTimeout(() => process.exit(0), 500);\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n\nexport function turnOn(): void {\n const config = loadConfig();\n\n console.log(`\\nPatching ${config.agent_type} config...`);\n console.log(` baseUrl: ${config.llm_base_url} → localhost:${config.proxy_port}`);\n\n switch (config.agent_type) {\n case 'openclaw':\n patchOpenClaw(config);\n break;\n case 'ironclaw':\n patchIronClaw(config);\n break;\n case 'nanoclaw':\n patchNanoClaw(config);\n break;\n case 'generic':\n console.log(`\\nSet these env vars in your agent's config:`);\n console.log(` OPENAI_BASE_URL=http://127.0.0.1:${config.proxy_port}/v1`);\n console.log(` ANTHROPIC_BASE_URL=http://127.0.0.1:${config.proxy_port}`);\n console.log(`Then restart your agent.\\n`);\n break;\n }\n\n config.state = 'on';\n saveConfig(config);\n console.log('\\nbecome is ON. Your agent is now learning from other agents.\\n');\n}\n\nexport function turnOff(): void {\n const config = loadConfig();\n\n console.log(`\\nRestoring ${config.agent_type} config...`);\n console.log(` baseUrl: localhost:${config.proxy_port} → ${config.llm_base_url}`);\n\n switch (config.agent_type) {\n case 'openclaw':\n restoreOpenClaw();\n break;\n case 'ironclaw':\n restoreIronClaw();\n break;\n case 'nanoclaw':\n restoreNanoClaw();\n break;\n case 'generic':\n console.log(`\\nRestore your original env vars and restart your agent.\\n`);\n break;\n }\n\n config.state = 'off';\n saveConfig(config);\n console.log('\\nbecome is OFF. Your agent talks directly to the LLM.');\n console.log('Learned skills are preserved — they\\'ll be injected when you turn become back on.\\n');\n}\n\nexport function showStatus(): void {\n const config = loadConfig();\n const baseDir = getBecomeDir();\n const store = new FileSkillStore({ baseDir });\n const trust = new TrustManager(baseDir);\n\n const approved = store.listApproved().length;\n const pending = store.listPending().length;\n const rejected = store.listRejected().length;\n const trustConfig = trust.getConfig();\n const counts = trust.getDailyCounts();\n\n console.log(`\\nState: ${config.state.toUpperCase()}`);\n console.log(`Proxy: localhost:${config.proxy_port}`);\n console.log(`Dashboard: localhost:${config.dashboard_port}`);\n console.log(`\\nSkills: ${approved} approved, ${pending} pending, ${rejected} rejected`);\n console.log(`Trust: ${trustConfig.trusted.length} trusted, ${trustConfig.blocked.length} blocked`);\n console.log(`Today: ${counts.total} lessons extracted\\n`);\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { FileSkillStore } from '../skills/store.js';\nimport { TrustManager } from '../skills/trust.js';\nimport { formatSkillsForInjection, injectSkillsIntoMessages } from '../skills/format.js';\nimport { LessonExtractor } from './extractor.js';\nimport type { ConversationAnalyzer } from '../learn/agent-conversations.js';\nimport type { SkillFile } from '../skills/store.js';\n\nexport interface ProxyConfig {\n port: number;\n llm_base_url: string;\n llm_api_key: string;\n llm_provider: 'anthropic' | 'openai' | 'ollama' | 'openrouter' | 'custom';\n baseDir: string;\n max_skills_per_call: number;\n auto_extract: boolean;\n}\n\nexport interface ProxyStats {\n requests_forwarded: number;\n skills_injected: number;\n lessons_extracted: number;\n started_at: string;\n}\n\nconst SKILL_CACHE_TTL_MS = 5000; // Refresh skill cache every 5 seconds\n\nexport function createProxyServer(config: ProxyConfig, analyzer?: ConversationAnalyzer, overrideUpstreamUrl?: string) {\n const store = new FileSkillStore({ baseDir: config.baseDir });\n const trust = new TrustManager(config.baseDir);\n const extractor = analyzer ? new LessonExtractor(store, trust, analyzer) : null;\n\n const stats: ProxyStats = {\n requests_forwarded: 0,\n skills_injected: 0,\n lessons_extracted: 0,\n started_at: new Date().toISOString(),\n };\n\n // Skill cache — avoid reading disk on every request\n let cachedSkills: SkillFile[] = [];\n let cacheTimestamp = 0;\n\n function getSkills(): SkillFile[] {\n const now = Date.now();\n if (now - cacheTimestamp > SKILL_CACHE_TTL_MS) {\n cachedSkills = store.listApproved();\n cacheTimestamp = now;\n }\n return cachedSkills;\n }\n\n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n console.log(`[become] ${req.method} ${req.url}`);\n\n // Health check\n if (req.url === '/health' && req.method === 'GET') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ status: 'ok', ...stats }));\n return;\n }\n\n // Proxy any POST request that looks like an LLM API call\n // Different providers use different paths:\n // OpenAI/OpenRouter: /v1/chat/completions or /chat/completions or /api/v1/chat/completions\n // Anthropic: /v1/messages or /messages\n // Some proxies: just /\n const url = req.url ?? '';\n const isLLMRequest = req.method === 'POST' && (\n url.includes('/chat/completions') ||\n url.includes('/messages') ||\n url === '/' ||\n url.startsWith('/v1')\n );\n\n if (!isLLMRequest) {\n // Log the rejected path so users can debug\n console.log(`[become] rejected: ${req.method} ${url}`);\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Not an LLM endpoint: ${req.method} ${url}` }));\n return;\n }\n\n try {\n // Read request body\n const rawBody = await readBody(req);\n const body = JSON.parse(rawBody);\n\n // Extract messages for injection\n const messages = body.messages;\n\n // Debug: log message content (handles both string and Anthropic array format)\n if (Array.isArray(messages)) {\n for (const m of messages) {\n if (m.role === 'user' || m.role === 'system') {\n const text = extractText(m.content);\n const preview = text.slice(0, 300).replace(/\\n/g, '\\\\n');\n console.log(`[become] msg ${m.role}${m.name ? ` name=${m.name}` : ''}: ${preview}`);\n }\n }\n }\n\n if (Array.isArray(messages)) {\n // Inject approved skills from cache\n const skills = getSkills().slice(0, config.max_skills_per_call);\n if (skills.length > 0) {\n const skillText = formatSkillsForInjection(skills);\n injectSkillsIntoMessages(messages, skillText);\n stats.skills_injected++;\n }\n }\n\n // Build upstream URL from the original provider URL (not the become config)\n const upstreamUrl = buildUpstreamUrl(overrideUpstreamUrl ?? config.llm_base_url, req.url!);\n\n // Build upstream headers\n const upstreamHeaders = buildUpstreamHeaders(config, req.headers);\n\n // Forward to real LLM\n const isStreaming = body.stream === true;\n const modifiedBody = JSON.stringify(body);\n\n console.log(`[become] -> ${upstreamUrl} (${isStreaming ? 'streaming' : 'non-streaming'})`);\n\n const upstreamRes = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: modifiedBody,\n });\n\n console.log(`[become] <- ${upstreamRes.status} ${upstreamRes.statusText}`);\n\n if (!upstreamRes.ok) {\n const errBody = await upstreamRes.text().catch(() => '');\n console.log(`[become] ERROR: ${errBody.slice(0, 500)}`);\n }\n\n stats.requests_forwarded++;\n\n // Forward response headers (filter out transfer-encoding to avoid mismatch)\n const responseHeaders: Record<string, string> = {};\n upstreamRes.headers.forEach((value, key) => {\n if (key.toLowerCase() !== 'transfer-encoding') {\n responseHeaders[key] = value;\n }\n });\n res.writeHead(upstreamRes.status, responseHeaders);\n\n if (isStreaming && upstreamRes.body) {\n // Stream: pipe chunks directly to client — do NOT buffer\n const reader = upstreamRes.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(value);\n }\n } finally {\n res.end();\n }\n\n // Async extraction — uses request messages only, not the response\n if (config.auto_extract && extractor && Array.isArray(messages)) {\n extractor.extract(messages)\n .then(() => { stats.lessons_extracted++; })\n .catch(() => {});\n }\n } else {\n // Non-streaming: read full response, return it, then extract\n const responseBuffer = await upstreamRes.arrayBuffer();\n res.end(Buffer.from(responseBuffer));\n\n // Async extraction\n if (config.auto_extract && extractor && Array.isArray(messages)) {\n extractor.extract(messages)\n .then(() => { stats.lessons_extracted++; })\n .catch(() => {});\n }\n }\n } catch (err) {\n console.log(`[become] EXCEPTION: ${err instanceof Error ? err.message : String(err)}`);\n // Sanitize error — never leak upstream details to client\n const safeMessage = err instanceof Error && err.message === 'Request body too large'\n ? 'Request body too large'\n : 'Failed to forward request to LLM';\n\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'application/json' });\n }\n // Always end the response, even if headers were already sent\n res.end(JSON.stringify({ error: safeMessage }));\n }\n });\n\n return {\n server,\n stats,\n store,\n trust,\n listen: (port?: number) => {\n const p = port ?? config.port;\n return new Promise<void>((resolve) => {\n server.listen(p, '127.0.0.1', () => resolve());\n });\n },\n close: () => new Promise<void>((resolve) => server.close(() => resolve())),\n };\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n const MAX_BODY = 10 * 1024 * 1024; // 10MB\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n\nfunction buildUpstreamUrl(baseUrl: string, path: string): string {\n const base = baseUrl.replace(/\\/+$/, '');\n\n // Forward to the matching upstream endpoint.\n // If agent sends /v1/messages → forward to /v1/messages (Anthropic format)\n // If agent sends /v1/chat/completions → forward to /v1/chat/completions (OpenAI format)\n // The agent is responsible for using the correct format for its provider.\n return `${base}${path}`;\n}\n\nfunction buildUpstreamHeaders(\n config: ProxyConfig,\n incomingHeaders: IncomingMessage['headers'],\n): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (config.llm_provider === 'anthropic') {\n headers['x-api-key'] = config.llm_api_key;\n headers['anthropic-version'] = '2023-06-01';\n // Forward anthropic-specific headers from agent\n const version = incomingHeaders['anthropic-version'];\n if (typeof version === 'string') headers['anthropic-version'] = version;\n const beta = incomingHeaders['anthropic-beta'];\n if (typeof beta === 'string') headers['anthropic-beta'] = beta;\n } else {\n headers['Authorization'] = `Bearer ${config.llm_api_key}`;\n }\n\n // Forward accept header for streaming\n const accept = incomingHeaders['accept'];\n if (typeof accept === 'string') headers['Accept'] = accept;\n\n return headers;\n}\n\n/**\n * Extract text from message content.\n * Handles both plain string and Anthropic array format:\n * \"hello\" or [{type: \"text\", text: \"hello\"}, {type: \"tool_use\", ...}]\n */\nfunction extractText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content)) {\n return content\n .filter((c: any) => c.type === 'text' && typeof c.text === 'string')\n .map((c: any) => c.text)\n .join('\\n');\n }\n return '';\n}\n","import { readFileSync, writeFileSync, readdirSync, mkdirSync, renameSync, unlinkSync, existsSync } from 'node:fs';\nimport { join, basename } from 'node:path';\nimport { createHash } from 'node:crypto';\n\nexport interface SkillFile {\n id: string; // Filename without extension\n name: string;\n instruction: string;\n learned_from: string;\n source: string; // peer_review, conversation, collaboration, teaching\n confidence: number;\n approved_at?: string;\n created_at: string;\n}\n\nexport interface SkillStoreConfig {\n baseDir: string; // ~/.become\n}\n\nexport class FileSkillStore {\n private skillsDir: string;\n private pendingDir: string;\n private rejectedDir: string;\n\n constructor(config: SkillStoreConfig) {\n this.skillsDir = join(config.baseDir, 'skills');\n this.pendingDir = join(config.baseDir, 'pending');\n this.rejectedDir = join(config.baseDir, 'rejected');\n\n mkdirSync(this.skillsDir, { recursive: true });\n mkdirSync(this.pendingDir, { recursive: true });\n mkdirSync(this.rejectedDir, { recursive: true });\n }\n\n // ── Read ────────────────────────────────────────────────────────────────\n\n listApproved(): SkillFile[] {\n return this.readDir(this.skillsDir);\n }\n\n listPending(): SkillFile[] {\n return this.readDir(this.pendingDir);\n }\n\n listRejected(): SkillFile[] {\n return this.readDir(this.rejectedDir);\n }\n\n getApproved(id: string): SkillFile | null {\n this.validateId(id);\n return this.readFile(join(this.skillsDir, `${id}.md`));\n }\n\n // ── Write ───────────────────────────────────────────────────────────────\n\n savePending(lesson: Omit<SkillFile, 'id' | 'approved_at'>): SkillFile | null {\n // Deduplication: check if same instruction already exists\n const normalized = lesson.instruction.toLowerCase().trim();\n const allExisting = [...this.listApproved(), ...this.listPending()];\n if (allExisting.some(s => s.instruction.toLowerCase().trim() === normalized)) {\n return null;\n }\n\n const id = this.generateId(lesson.name);\n const file: SkillFile = { ...lesson, id, approved_at: undefined };\n this.writeFile(join(this.pendingDir, `${id}.md`), file);\n return file;\n }\n\n approve(id: string): boolean {\n this.validateId(id);\n const src = join(this.pendingDir, `${id}.md`);\n if (!existsSync(src)) return false;\n\n const skill = this.readFile(src);\n if (!skill) return false;\n\n skill.approved_at = new Date().toISOString();\n const dest = join(this.skillsDir, `${id}.md`);\n this.writeFile(dest, skill);\n unlinkSync(src);\n return true;\n }\n\n reject(id: string): boolean {\n this.validateId(id);\n const src = join(this.pendingDir, `${id}.md`);\n if (!existsSync(src)) return false;\n const dest = join(this.rejectedDir, `${id}.md`);\n renameSync(src, dest);\n return true;\n }\n\n disable(id: string): boolean {\n this.validateId(id);\n const src = join(this.skillsDir, `${id}.md`);\n if (!existsSync(src)) return false;\n const dest = join(this.rejectedDir, `${id}.md`);\n renameSync(src, dest);\n return true;\n }\n\n remove(id: string): boolean {\n this.validateId(id);\n for (const dir of [this.skillsDir, this.pendingDir, this.rejectedDir]) {\n const path = join(dir, `${id}.md`);\n if (existsSync(path)) {\n unlinkSync(path);\n return true;\n }\n }\n return false;\n }\n\n // ── Helpers ─────────────────────────────────────────────────────────────\n\n /**\n * Validate that an id does not contain path traversal characters.\n * Prevents attacks like id=\"../../.ssh/authorized_keys\"\n */\n private validateId(id: string): void {\n if (!id || typeof id !== 'string') throw new Error('Invalid id');\n if (id.includes('/') || id.includes('\\\\') || id.includes('..') || id.includes('\\0')) {\n throw new Error('Invalid id: path traversal detected');\n }\n }\n\n private readDir(dir: string): SkillFile[] {\n if (!existsSync(dir)) return [];\n const files = readdirSync(dir).filter(f => f.endsWith('.md'));\n const skills: SkillFile[] = [];\n for (const f of files) {\n const skill = this.readFile(join(dir, f));\n if (skill) skills.push(skill);\n }\n return skills.sort((a, b) => b.created_at.localeCompare(a.created_at));\n }\n\n private readFile(path: string): SkillFile | null {\n if (!existsSync(path)) return null;\n try {\n const content = readFileSync(path, 'utf-8');\n return this.parseSkillFile(content, basename(path, '.md'));\n } catch {\n return null;\n }\n }\n\n private writeFile(path: string, skill: SkillFile): void {\n const content = this.formatSkillFile(skill);\n writeFileSync(path, content, 'utf-8');\n }\n\n private parseSkillFile(content: string, id: string): SkillFile | null {\n const match = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n([\\s\\S]*)$/);\n if (!match) return null;\n\n const [, frontmatter, body] = match;\n const meta: Record<string, string> = {};\n for (const line of frontmatter.split('\\n')) {\n const colonIdx = line.indexOf(':');\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n if (key && value) meta[key] = value;\n }\n\n return {\n id,\n name: meta.name ?? id,\n instruction: body.trim(),\n learned_from: meta.learned_from ?? 'unknown',\n source: meta.source ?? 'conversation',\n confidence: parseFloat(meta.confidence ?? '0.5'),\n approved_at: meta.approved_at || undefined,\n created_at: meta.created_at ?? new Date().toISOString(),\n };\n }\n\n private formatSkillFile(skill: SkillFile): string {\n const lines = [\n '---',\n `name: ${skill.name}`,\n `learned_from: ${skill.learned_from}`,\n `source: ${skill.source}`,\n `confidence: ${skill.confidence}`,\n `created_at: ${skill.created_at}`,\n ];\n if (skill.approved_at) lines.push(`approved_at: ${skill.approved_at}`);\n lines.push('---');\n lines.push('');\n lines.push(skill.instruction);\n lines.push('');\n return lines.join('\\n');\n }\n\n private generateId(name: string): string {\n const clean = name.toLowerCase().replace(/[^a-z0-9]+/g, '_').slice(0, 40);\n const hash = createHash('sha256')\n .update(`${name}${Date.now()}${Math.random()}`)\n .digest('hex')\n .slice(0, 6);\n return `${clean}_${hash}`;\n }\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\n\nexport type TrustLevel = 'trusted' | 'pending' | 'blocked';\n\nexport interface TrustConfig {\n trusted: string[];\n blocked: string[];\n default: TrustLevel;\n}\n\nexport interface RateLimits {\n max_lessons_per_day: number;\n max_lessons_per_agent: number;\n max_skills_per_call: number;\n}\n\nconst DEFAULT_TRUST: TrustConfig = {\n trusted: [],\n blocked: [],\n default: 'pending',\n};\n\nconst DEFAULT_RATE_LIMITS: RateLimits = {\n max_lessons_per_day: 20,\n max_lessons_per_agent: 10,\n max_skills_per_call: 15,\n};\n\nexport class TrustManager {\n private trustPath: string;\n private statsPath: string;\n private config: TrustConfig;\n private dailyCounts: { date: string; total: number; perAgent: Record<string, number> };\n\n constructor(baseDir: string) {\n this.trustPath = join(baseDir, 'trust.json');\n this.statsPath = join(baseDir, 'state', 'daily_counts.json');\n mkdirSync(join(baseDir, 'state'), { recursive: true });\n this.config = this.loadTrust();\n this.dailyCounts = this.loadDailyCounts();\n }\n\n getLevel(agentId: string): TrustLevel {\n if (this.config.trusted.includes(agentId)) return 'trusted';\n if (this.config.blocked.includes(agentId)) return 'blocked';\n return this.config.default;\n }\n\n setLevel(agentId: string, level: TrustLevel): void {\n // Remove from all lists first\n this.config.trusted = this.config.trusted.filter((a) => a !== agentId);\n this.config.blocked = this.config.blocked.filter((a) => a !== agentId);\n\n if (level === 'trusted') this.config.trusted.push(agentId);\n if (level === 'blocked') this.config.blocked.push(agentId);\n\n this.saveTrust();\n }\n\n setDefault(level: TrustLevel): void {\n this.config.default = level;\n this.saveTrust();\n }\n\n getConfig(): TrustConfig {\n return { ...this.config };\n }\n\n // ── Rate Limiting ───────────────────────────────────────────────────────\n\n canLearn(agentId: string, limits: RateLimits = DEFAULT_RATE_LIMITS): boolean {\n this.refreshDailyCountsIfNewDay();\n\n if (this.dailyCounts.total >= limits.max_lessons_per_day) return false;\n const agentCount = this.dailyCounts.perAgent[agentId] ?? 0;\n if (agentCount >= limits.max_lessons_per_agent) return false;\n\n return true;\n }\n\n recordLesson(agentId: string): void {\n this.refreshDailyCountsIfNewDay();\n this.dailyCounts.total++;\n this.dailyCounts.perAgent[agentId] = (this.dailyCounts.perAgent[agentId] ?? 0) + 1;\n this.saveDailyCounts();\n }\n\n getDailyCounts(): { total: number; perAgent: Record<string, number> } {\n this.refreshDailyCountsIfNewDay();\n return { total: this.dailyCounts.total, perAgent: { ...this.dailyCounts.perAgent } };\n }\n\n // ── Private ─────────────────────────────────────────────────────────────\n\n private loadTrust(): TrustConfig {\n if (!existsSync(this.trustPath)) return { ...DEFAULT_TRUST, trusted: [], blocked: [] };\n try {\n const raw = JSON.parse(readFileSync(this.trustPath, 'utf-8'));\n // Validate shape — arrays must be arrays, default must be valid\n return {\n trusted: Array.isArray(raw.trusted) ? raw.trusted.filter((a: unknown) => typeof a === 'string') : [],\n blocked: Array.isArray(raw.blocked) ? raw.blocked.filter((a: unknown) => typeof a === 'string') : [],\n default: ['trusted', 'pending', 'blocked'].includes(raw.default) ? raw.default : 'pending',\n };\n } catch {\n return { ...DEFAULT_TRUST, trusted: [], blocked: [] };\n }\n }\n\n private saveTrust(): void {\n mkdirSync(dirname(this.trustPath), { recursive: true });\n writeFileSync(this.trustPath, JSON.stringify(this.config, null, 2), 'utf-8');\n }\n\n private loadDailyCounts(): { date: string; total: number; perAgent: Record<string, number> } {\n const today = new Date().toISOString().slice(0, 10);\n if (!existsSync(this.statsPath)) return { date: today, total: 0, perAgent: {} };\n try {\n const data = JSON.parse(readFileSync(this.statsPath, 'utf-8'));\n if (data.date !== today) return { date: today, total: 0, perAgent: {} };\n return data;\n } catch {\n return { date: today, total: 0, perAgent: {} };\n }\n }\n\n private saveDailyCounts(): void {\n writeFileSync(this.statsPath, JSON.stringify(this.dailyCounts, null, 2), 'utf-8');\n }\n\n private refreshDailyCountsIfNewDay(): void {\n const today = new Date().toISOString().slice(0, 10);\n if (this.dailyCounts.date !== today) {\n this.dailyCounts = { date: today, total: 0, perAgent: {} };\n }\n }\n}\n","import type { SkillFile } from './store.js';\n\n/**\n * Format approved skills as a text block for injection into the system message.\n */\nexport function formatSkillsForInjection(skills: SkillFile[]): string {\n if (skills.length === 0) return '';\n\n const lines = skills.map((s) => {\n const source = s.source === 'peer_review' ? 'from a peer review' :\n s.source === 'collaboration' ? 'from a collaboration' :\n s.source === 'teaching' ? 'from being taught' :\n 'from a conversation';\n return `- ${s.instruction} (${source})`;\n });\n\n return [\n '## Lessons learned from other agents',\n '',\n 'You have learned the following from interactions with other agents. Follow these instructions:',\n '',\n ...lines,\n ].join('\\n');\n}\n\n/**\n * Inject skill text into a messages array by prepending to the system message.\n * Mutates the messages array in place.\n */\nexport function injectSkillsIntoMessages(\n messages: { role: string; content: string }[],\n skillText: string,\n): void {\n if (!skillText) return;\n\n const sysIdx = messages.findIndex((m) => m.role === 'system');\n if (sysIdx >= 0) {\n messages[sysIdx].content = skillText + '\\n\\n---\\n\\n' + messages[sysIdx].content;\n } else {\n messages.unshift({ role: 'system', content: skillText });\n }\n}\n","/**\n * Detects whether a conversation involves another agent (vs user-to-agent).\n * Only agent-to-agent conversations trigger lesson extraction.\n */\n\nexport interface DetectionResult {\n isAgentToAgent: boolean;\n otherAgentId?: string;\n exchangeType?: 'channel' | 'dm' | 'peer_review' | 'collaboration' | 'chat' | 'mention' | 'proposal';\n}\n\n// OpenClawCity event formats (from nanoclaw-openclawcity plugin formatEventForAgent):\n// [DM from AgentName]:\n// [AgentName mentioned you in building chat]:\n// [AgentName in zone chat]:\n// [AgentName sent you a proposal]:\n// [AgentName accepted your proposal]:\n// [AgentName wants to start a conversation with you]:\n// Display names have [ replaced with ( and ] with ) to avoid breaking the format.\n\nconst OCC_DM_PATTERN = /^\\[DM from ([^\\]]+)\\]:/m;\nconst OCC_MENTION_PATTERN = /^\\[([^\\]]+) mentioned you in building chat\\]:/m;\nconst OCC_ZONE_CHAT_PATTERN = /^\\[([^\\]]+) in zone chat\\]:/m;\nconst OCC_PROPOSAL_PATTERN = /^\\[([^\\]]+) (?:sent you a proposal|accepted your proposal)\\]:/m;\nconst OCC_CONVERSATION_REQUEST = /^\\[([^\\]]+) wants to start a conversation with you\\]:/m;\n\n// Generic patterns (non-OpenClawCity)\nconst GENERIC_CHANNEL_PATTERN = /^\\[([^\\]]+)\\s+says?\\]:\\s*/m;\nconst GENERIC_DM_PATTERN = /^DM\\s+from\\s+([^:]+):\\s*/m;\n\n// Agent in building: agent-name in Building Name: ...\nconst BUILDING_PATTERN = /^([a-zA-Z0-9]+[-_][a-zA-Z0-9_.-]+)\\s+in\\s+[^:]+:\\s*/m;\n\n// Peer review markers\nconst REVIEW_KEYWORDS = ['strengths:', 'weaknesses:', 'verdict:', 'assessment:', 'suggestions:'];\n\n// Skip these (human/system messages, not agent-to-agent)\nconst SKIP_PATTERNS = [\n /^\\[Your human owner says\\]:/m,\n /^\\[Your human set a new mission/m,\n /^\\[HEARTBEAT/m,\n /^\\[Someone left you a voice message\\]/m,\n];\n\nexport function detectAgentConversation(\n messages: { role: string; content: unknown; name?: string }[],\n): DetectionResult {\n const negative: DetectionResult = { isAgentToAgent: false };\n\n if (!messages || messages.length === 0) return negative;\n\n for (const msg of messages) {\n if (msg.role !== 'user' && msg.role !== 'assistant') continue;\n const content = contentToString(msg.content);\n if (!content) continue;\n\n // Skip human/system messages\n if (SKIP_PATTERNS.some(p => p.test(content))) continue;\n\n // Pattern 1: message has a `name` field (multi-agent frameworks)\n if (msg.name && msg.role === 'user') {\n return {\n isAgentToAgent: true,\n otherAgentId: msg.name,\n exchangeType: 'chat',\n };\n }\n\n // Pattern 2: OpenClawCity DM\n const dmMatch = content.match(OCC_DM_PATTERN);\n if (dmMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: dmMatch[1].trim(),\n exchangeType: 'dm',\n };\n }\n\n // Pattern 3: OpenClawCity mention in building chat\n const mentionMatch = content.match(OCC_MENTION_PATTERN);\n if (mentionMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: mentionMatch[1].trim(),\n exchangeType: 'mention',\n };\n }\n\n // Pattern 4: OpenClawCity zone chat\n const zoneMatch = content.match(OCC_ZONE_CHAT_PATTERN);\n if (zoneMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: zoneMatch[1].trim(),\n exchangeType: 'chat',\n };\n }\n\n // Pattern 5: OpenClawCity proposal\n const proposalMatch = content.match(OCC_PROPOSAL_PATTERN);\n if (proposalMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: proposalMatch[1].trim(),\n exchangeType: 'proposal',\n };\n }\n\n // Pattern 6: OpenClawCity conversation request\n const convMatch = content.match(OCC_CONVERSATION_REQUEST);\n if (convMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: convMatch[1].trim(),\n exchangeType: 'dm',\n };\n }\n\n // Pattern 7: Generic channel format [name says]:\n const channelMatch = content.match(GENERIC_CHANNEL_PATTERN);\n if (channelMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: channelMatch[1].trim(),\n exchangeType: 'channel',\n };\n }\n\n // Pattern 8: Generic DM format\n const genericDmMatch = content.match(GENERIC_DM_PATTERN);\n if (genericDmMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: genericDmMatch[1].trim(),\n exchangeType: 'dm',\n };\n }\n\n // Pattern 9: Building format\n const buildingMatch = content.match(BUILDING_PATTERN);\n if (buildingMatch) {\n return {\n isAgentToAgent: true,\n otherAgentId: buildingMatch[1].trim(),\n exchangeType: 'chat',\n };\n }\n\n // Pattern 10: Peer review content\n const lowerContent = content.toLowerCase();\n const reviewMatches = REVIEW_KEYWORDS.filter((kw) => lowerContent.includes(kw));\n if (reviewMatches.length >= 2) {\n return {\n isAgentToAgent: true,\n otherAgentId: undefined,\n exchangeType: 'peer_review',\n };\n }\n }\n\n return negative;\n}\n\n/**\n * Extract agent-to-agent exchange text from messages for analysis.\n */\nexport function extractExchangeText(\n messages: { role: string; content: unknown; name?: string }[],\n): string {\n return messages\n .filter((m) => m.role === 'user' || m.role === 'assistant')\n .map((m) => {\n const speaker = m.name ?? m.role;\n const content = contentToString(m.content);\n return `[${speaker}]: ${content}`;\n })\n .join('\\n')\n .slice(0, 6000);\n}\n\n/**\n * Convert message content to string. Handles:\n * - Plain string: \"hello\"\n * - Anthropic array: [{type: \"text\", text: \"hello\"}, {type: \"tool_use\", ...}]\n */\nfunction contentToString(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content)) {\n return content\n .filter((c: any) => c.type === 'text' && typeof c.text === 'string')\n .map((c: any) => c.text)\n .join('\\n');\n }\n return '';\n}\n","import { detectAgentConversation, extractExchangeText } from './detector.js';\nimport type { FileSkillStore } from '../skills/store.js';\nimport type { TrustManager } from '../skills/trust.js';\nimport type { ConversationAnalyzer } from '../learn/agent-conversations.js';\n\n/**\n * Async lesson extractor. After the proxy forwards a response, this analyzes\n * the conversation for agent-to-agent lessons. Runs in the background —\n * never blocks the agent's response.\n */\nexport class LessonExtractor {\n constructor(\n private store: FileSkillStore,\n private trust: TrustManager,\n private analyzer: ConversationAnalyzer,\n ) {}\n\n /**\n * Analyze a conversation and extract lessons. Fire-and-forget.\n */\n async extract(\n messages: { role: string; content: unknown; name?: string }[],\n ): Promise<void> {\n const detection = detectAgentConversation(messages);\n if (!detection.isAgentToAgent) return;\n\n const agentId = detection.otherAgentId ?? 'unknown-agent';\n\n // Check trust level — skip if blocked\n const trustLevel = this.trust.getLevel(agentId);\n if (trustLevel === 'blocked') return;\n\n // Check rate limits\n if (!this.trust.canLearn(agentId)) return;\n\n const exchangeText = extractExchangeText(messages);\n if (exchangeText.length < 20) return;\n\n const prompt = `Analyze this conversation between an AI agent and another agent. Extract concrete, actionable lessons that the first agent (the \"assistant\") can learn from the other agent.\n\nCONVERSATION:\n${exchangeText.slice(0, 4000)}\n\nOutput valid JSON array:\n[{\"skill\": \"skill_name_snake_case\", \"instruction\": \"concrete actionable lesson in 1-2 sentences\", \"confidence\": 0.0-1.0}]\n\nRules:\n- Only extract lessons where the other agent clearly teaches, corrects, or shares useful knowledge\n- instruction must be concrete and actionable (\"use X when Y\" not \"consider improving\")\n- confidence: 0.9 = explicitly taught, 0.7 = clearly implied, 0.5 = suggested, below 0.5 = skip\n- Only include lessons with confidence >= 0.5\n- Max 3 lessons per conversation\n- If no real learning happened, return []`;\n\n try {\n console.log(`[become] extracting lessons from ${agentId} (${detection.exchangeType}), text length: ${exchangeText.length}`);\n const response = await this.analyzer.analyze(prompt);\n const lessons = this.parseLessons(response);\n console.log(`[become] LLM returned ${lessons.length} lessons`);\n\n for (const lesson of lessons.slice(0, 3)) {\n console.log(`[become] saving lesson: ${lesson.skill} (confidence: ${lesson.confidence})`);\n const saved = this.store.savePending({\n name: lesson.skill,\n instruction: lesson.instruction.slice(0, 500),\n learned_from: agentId,\n source: detection.exchangeType ?? 'conversation',\n confidence: lesson.confidence,\n created_at: new Date().toISOString(),\n });\n\n if (saved) {\n console.log(`[become] lesson saved: ${saved.id}`);\n this.trust.recordLesson(agentId);\n\n // Auto-approve if agent is trusted\n if (trustLevel === 'trusted') {\n this.store.approve(saved.id);\n console.log(`[become] auto-approved (trusted agent)`);\n }\n } else {\n console.log(`[become] lesson NOT saved (duplicate or store error)`);\n }\n }\n } catch (err) {\n console.log(`[become] extraction error: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n private parseLessons(response: string): { skill: string; instruction: string; confidence: number }[] {\n const jsonMatch = response.match(/\\[[\\s\\S]*\\]/);\n if (!jsonMatch) return [];\n\n try {\n const parsed = JSON.parse(jsonMatch[0]);\n if (!Array.isArray(parsed)) return [];\n return parsed.filter(\n (r: any) =>\n typeof r.skill === 'string' &&\n typeof r.instruction === 'string' &&\n typeof r.confidence === 'number' &&\n r.confidence >= 0.5 &&\n r.skill.length > 0 &&\n r.instruction.length > 0,\n );\n } catch {\n return [];\n }\n }\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { createHandlers, type DashboardDeps } from './api/handlers.js';\nimport { renderDashboardHTML } from './ui.js';\n\nexport function createDashboardServer(deps: DashboardDeps) {\n const handlers = createHandlers(deps);\n const html = renderDashboardHTML();\n\n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n // CORS restricted to localhost only — prevents external sites from\n // making API calls to the dashboard\n const origin = req.headers.origin ?? '';\n if (origin && /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(:\\d+)?$/.test(origin)) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n }\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Serve dashboard HTML at root\n if (req.url === '/' && req.method === 'GET') {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(html);\n return;\n }\n\n // API routes\n const key = `${req.method} ${req.url}`;\n const handler = handlers[key];\n\n if (!handler) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n return;\n }\n\n try {\n let body: any;\n if (req.method === 'POST' || req.method === 'DELETE') {\n const raw = await readBody(req);\n if (raw) {\n try {\n body = JSON.parse(raw);\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid JSON body' }));\n return;\n }\n }\n }\n\n const result = await handler(body);\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(result));\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Internal server error' }));\n }\n });\n\n return {\n server,\n listen: (port: number) => {\n return new Promise<void>((resolve) => {\n server.listen(port, '127.0.0.1', () => resolve());\n });\n },\n close: () => new Promise<void>((resolve) => server.close(() => resolve())),\n };\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > 1024 * 1024) { req.destroy(); reject(new Error('Too large')); return; }\n chunks.push(chunk);\n });\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n","import type { FileSkillStore } from '../../skills/store.js';\nimport type { TrustManager, TrustLevel } from '../../skills/trust.js';\n\nexport interface DashboardDeps {\n store: FileSkillStore;\n trust: TrustManager;\n getProxyStats: () => { requests_forwarded: number; skills_injected: number; lessons_extracted: number; started_at: string } | null;\n getState: () => 'on' | 'off';\n setState: (state: 'on' | 'off') => void;\n}\n\ntype Handler = (body?: any) => any;\n\nexport function createHandlers(deps: DashboardDeps): Record<string, Handler> {\n const { store, trust, getProxyStats, getState, setState } = deps;\n\n return {\n // ── Status ──────────────────────────────────────────────────────────\n 'GET /api/status': () => ({\n state: getState(),\n skills_count: store.listApproved().length,\n pending_count: store.listPending().length,\n rejected_count: store.listRejected().length,\n proxy: getProxyStats(),\n }),\n\n // ── State toggle ────────────────────────────────────────────────────\n 'POST /api/state': (body) => {\n const newState = body?.state;\n if (newState !== 'on' && newState !== 'off') {\n return { error: 'state must be \"on\" or \"off\"' };\n }\n try {\n setState(newState);\n return { state: newState };\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to change state';\n return { error: msg };\n }\n },\n\n // ── Skills (approved) ───────────────────────────────────────────────\n 'GET /api/skills': () => store.listApproved(),\n\n // ── Pending ─────────────────────────────────────────────────────────\n 'GET /api/pending': () => store.listPending(),\n\n // ── Rejected ────────────────────────────────────────────────────────\n 'GET /api/rejected': () => store.listRejected(),\n\n // ── Approve ─────────────────────────────────────────────────────────\n 'POST /api/approve': (body) => {\n const id = body?.id;\n if (!id || typeof id !== 'string') return { error: 'id required' };\n const ok = store.approve(id);\n return ok ? { ok: true } : { error: 'not found' };\n },\n\n // ── Reject ──────────────────────────────────────────────────────────\n 'POST /api/reject': (body) => {\n const id = body?.id;\n if (!id || typeof id !== 'string') return { error: 'id required' };\n const ok = store.reject(id);\n return ok ? { ok: true } : { error: 'not found' };\n },\n\n // ── Disable (approved → rejected) ───────────────────────────────────\n 'POST /api/disable': (body) => {\n const id = body?.id;\n if (!id || typeof id !== 'string') return { error: 'id required' };\n const ok = store.disable(id);\n return ok ? { ok: true } : { error: 'not found' };\n },\n\n // ── Remove permanently ──────────────────────────────────────────────\n 'DELETE /api/skill': (body) => {\n const id = body?.id;\n if (!id || typeof id !== 'string') return { error: 'id required' };\n const ok = store.remove(id);\n return ok ? { ok: true } : { error: 'not found' };\n },\n\n // ── Trust ───────────────────────────────────────────────────────────\n 'GET /api/trust': () => trust.getConfig(),\n\n 'POST /api/trust': (body) => {\n const { agent, level } = body ?? {};\n if (!agent || typeof agent !== 'string') return { error: 'agent required' };\n if (!['trusted', 'pending', 'blocked'].includes(level)) return { error: 'level must be trusted/pending/blocked' };\n trust.setLevel(agent, level as TrustLevel);\n return { ok: true };\n },\n\n 'POST /api/trust/default': (body) => {\n const { level } = body ?? {};\n if (!['trusted', 'pending', 'blocked'].includes(level)) return { error: 'level must be trusted/pending/blocked' };\n trust.setDefault(level as TrustLevel);\n return { ok: true };\n },\n\n // ── Network ─────────────────────────────────────────────────────────\n 'GET /api/network': () => {\n const approved = store.listApproved();\n const pending = store.listPending();\n const all = [...approved, ...pending];\n\n const agents: Record<string, { lessons: number; skills: string[]; trust: string }> = {};\n for (const skill of all) {\n const id = skill.learned_from;\n if (!agents[id]) {\n agents[id] = { lessons: 0, skills: [], trust: trust.getLevel(id) };\n }\n agents[id].lessons++;\n if (!agents[id].skills.includes(skill.name)) {\n agents[id].skills.push(skill.name);\n }\n }\n return agents;\n },\n\n // ── Stats ───────────────────────────────────────────────────────────\n 'GET /api/stats': () => {\n const counts = trust.getDailyCounts();\n return {\n today_lessons: counts.total,\n today_per_agent: counts.perAgent,\n total_approved: store.listApproved().length,\n total_pending: store.listPending().length,\n total_rejected: store.listRejected().length,\n proxy: getProxyStats(),\n };\n },\n };\n}\n","/**\n * Server-rendered HTML for the become dashboard.\n * Single-page app with vanilla JS — no build step needed.\n */\nexport function renderDashboardHTML(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>become</title>\n<style>\n :root { --bg: #0a0a0a; --card: #141414; --border: #262626; --text: #e5e5e5; --dim: #737373; --accent: #22d3ee; --green: #22c55e; --red: #ef4444; --amber: #f59e0b; }\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); line-height: 1.6; }\n .container { max-width: 800px; margin: 0 auto; padding: 20px; }\n h1 { font-size: 24px; font-weight: 600; margin-bottom: 4px; }\n h2 { font-size: 18px; font-weight: 600; margin-bottom: 12px; color: var(--accent); }\n .subtitle { color: var(--dim); font-size: 14px; margin-bottom: 24px; }\n\n /* Nav */\n nav { display: flex; gap: 4px; margin-bottom: 24px; border-bottom: 1px solid var(--border); padding-bottom: 8px; }\n nav button { background: none; border: none; color: var(--dim); font-size: 14px; padding: 8px 16px; cursor: pointer; border-radius: 6px 6px 0 0; }\n nav button:hover { color: var(--text); }\n nav button.active { color: var(--accent); border-bottom: 2px solid var(--accent); }\n\n /* Status bar */\n .status-bar { display: flex; gap: 16px; align-items: center; margin-bottom: 24px; padding: 12px 16px; background: var(--card); border: 1px solid var(--border); border-radius: 8px; font-size: 13px; }\n .status-dot { width: 8px; height: 8px; border-radius: 50%; }\n .status-dot.on { background: var(--green); }\n .status-dot.off { background: var(--red); }\n .status-label { font-weight: 600; }\n .status-stat { color: var(--dim); }\n\n /* Cards */\n .card { background: var(--card); border: 1px solid var(--border); border-radius: 8px; padding: 16px; margin-bottom: 12px; }\n .card-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px; }\n .card-instruction { font-size: 15px; margin-bottom: 8px; }\n .card-meta { font-size: 12px; color: var(--dim); display: flex; gap: 12px; flex-wrap: wrap; }\n .card-meta span { display: inline-flex; align-items: center; gap: 4px; }\n\n /* Buttons */\n .btn { border: none; padding: 6px 14px; border-radius: 6px; font-size: 13px; cursor: pointer; font-weight: 500; }\n .btn-approve { background: var(--green); color: #000; }\n .btn-reject { background: var(--red); color: #fff; }\n .btn-disable { background: var(--border); color: var(--text); }\n .btn-trust { background: var(--accent); color: #000; }\n .btn-small { padding: 4px 10px; font-size: 12px; }\n .btn:hover { opacity: 0.85; }\n .btn-group { display: flex; gap: 6px; }\n\n /* Badge */\n .badge { font-size: 11px; padding: 2px 8px; border-radius: 10px; font-weight: 500; }\n .badge-trusted { background: rgba(34,197,94,0.15); color: var(--green); }\n .badge-pending { background: rgba(245,158,11,0.15); color: var(--amber); }\n .badge-blocked { background: rgba(239,68,68,0.15); color: var(--red); }\n\n /* Empty state */\n .empty { text-align: center; padding: 40px; color: var(--dim); }\n\n /* Page sections */\n .page { display: none; }\n .page.active { display: block; }\n\n /* Trust settings */\n .trust-row { display: flex; justify-content: space-between; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--border); }\n .trust-row:last-child { border: none; }\n .trust-agent { font-weight: 500; }\n .trust-lessons { font-size: 13px; color: var(--dim); }\n\n /* Skill group */\n .skill-group { margin-bottom: 20px; }\n .skill-group-name { font-size: 13px; text-transform: uppercase; color: var(--dim); letter-spacing: 0.5px; margin-bottom: 8px; }\n\n /* Toggle */\n .toggle { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }\n .toggle-switch { width: 44px; height: 24px; background: var(--border); border-radius: 12px; position: relative; cursor: pointer; transition: background 0.2s; }\n .toggle-switch.on { background: var(--green); }\n .toggle-switch::after { content: ''; position: absolute; width: 18px; height: 18px; background: white; border-radius: 50%; top: 3px; left: 3px; transition: transform 0.2s; }\n .toggle-switch.on::after { transform: translateX(20px); }\n</style>\n</head>\n<body>\n<div class=\"container\">\n <h1>become</h1>\n <p class=\"subtitle\">agent-to-agent learning</p>\n\n <div class=\"status-bar\" id=\"status-bar\">\n <div class=\"status-dot\" id=\"status-dot\"></div>\n <span class=\"status-label\" id=\"status-label\">Loading...</span>\n <span class=\"status-stat\" id=\"status-skills\"></span>\n <span class=\"status-stat\" id=\"status-pending\"></span>\n </div>\n\n <nav>\n <button class=\"active\" onclick=\"showPage('pending',this)\">Pending</button>\n <button onclick=\"showPage('skills',this)\">Active Skills</button>\n <button onclick=\"showPage('network',this)\">Network</button>\n <button onclick=\"showPage('settings',this)\">Settings</button>\n </nav>\n\n <!-- Pending Page -->\n <div id=\"page-pending\" class=\"page active\"></div>\n\n <!-- Skills Page -->\n <div id=\"page-skills\" class=\"page\"></div>\n\n <!-- Network Page -->\n <div id=\"page-network\" class=\"page\"></div>\n\n <!-- Settings Page -->\n <div id=\"page-settings\" class=\"page\"></div>\n</div>\n\n<script>\nconst API = '';\n\nasync function api(method, path, body) {\n const opts = { method, headers: { 'Content-Type': 'application/json' } };\n if (body) opts.body = JSON.stringify(body);\n const res = await fetch(API + path, opts);\n return res.json();\n}\n\nfunction showPage(name, btn) {\n document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));\n document.getElementById('page-' + name).classList.add('active');\n document.querySelectorAll('nav button').forEach(b => b.classList.remove('active'));\n if (btn) btn.classList.add('active');\n if (name === 'pending') loadPending();\n if (name === 'skills') loadSkills();\n if (name === 'network') loadNetwork();\n if (name === 'settings') loadSettings();\n}\n\n// ── Status Bar ────────────────────────────────────────────────────────\nasync function loadStatus() {\n const s = await api('GET', '/api/status');\n const dot = document.getElementById('status-dot');\n const label = document.getElementById('status-label');\n dot.className = 'status-dot ' + s.state;\n label.textContent = s.state.toUpperCase();\n document.getElementById('status-skills').textContent = s.skills_count + ' skills';\n document.getElementById('status-pending').textContent = s.pending_count + ' pending';\n}\n\n// ── Pending Page ──────────────────────────────────────────────────────\nasync function loadPending() {\n const lessons = await api('GET', '/api/pending');\n const el = document.getElementById('page-pending');\n if (lessons.length === 0) {\n el.innerHTML = '<div class=\"empty\">No pending lessons. Your agent will learn as it talks to other agents.</div>';\n return;\n }\n el.innerHTML = '<h2>Pending Review (' + lessons.length + ')</h2>' +\n lessons.map(l => renderPendingCard(l)).join('');\n}\n\nfunction renderPendingCard(l) {\n return '<div class=\"card\" id=\"card-' + l.id + '\">' +\n '<div class=\"card-instruction\">' + esc(l.instruction) + '</div>' +\n '<div class=\"card-meta\">' +\n '<span>From: <strong>' + esc(l.learned_from) + '</strong></span>' +\n '<span>Source: ' + esc(l.source) + '</span>' +\n '<span>Confidence: ' + (l.confidence * 100).toFixed(0) + '%</span>' +\n '<span>Skill: ' + esc(l.name) + '</span>' +\n '</div>' +\n '<div style=\"margin-top:12px\" class=\"btn-group\">' +\n '<button class=\"btn btn-approve\" onclick=\"doApprove(\\\\''+l.id+'\\\\')\">Approve</button>' +\n '<button class=\"btn btn-reject\" onclick=\"doReject(\\\\''+l.id+'\\\\')\">Reject</button>' +\n '<button class=\"btn btn-trust btn-small\" onclick=\"doTrustAgent(\\\\''+esc(l.learned_from)+'\\\\')\">Trust Agent</button>' +\n '</div>' +\n '</div>';\n}\n\nasync function doApprove(id) {\n await api('POST', '/api/approve', { id });\n document.getElementById('card-' + id)?.remove();\n loadStatus();\n}\n\nasync function doReject(id) {\n await api('POST', '/api/reject', { id });\n document.getElementById('card-' + id)?.remove();\n loadStatus();\n}\n\nasync function doTrustAgent(agent) {\n await api('POST', '/api/trust', { agent, level: 'trusted' });\n loadPending();\n loadStatus();\n}\n\n// ── Skills Page ───────────────────────────────────────────────────────\nasync function loadSkills() {\n const skills = await api('GET', '/api/skills');\n const el = document.getElementById('page-skills');\n if (skills.length === 0) {\n el.innerHTML = '<div class=\"empty\">No active skills yet. Approve pending lessons to activate them.</div>';\n return;\n }\n\n // Group by skill name\n const groups = {};\n for (const s of skills) {\n if (!groups[s.name]) groups[s.name] = [];\n groups[s.name].push(s);\n }\n\n let html = '<h2>Active Skills (' + skills.length + ')</h2>';\n for (const [name, items] of Object.entries(groups)) {\n html += '<div class=\"skill-group\"><div class=\"skill-group-name\">' + esc(name) + '</div>';\n for (const s of items) {\n html += '<div class=\"card\" id=\"card-' + s.id + '\">' +\n '<div class=\"card-header\"><div class=\"card-instruction\">' + esc(s.instruction) + '</div>' +\n '<button class=\"btn btn-disable btn-small\" onclick=\"doDisable(\\\\''+s.id+'\\\\')\">Disable</button></div>' +\n '<div class=\"card-meta\"><span>From: ' + esc(s.learned_from) + '</span><span>Source: ' + esc(s.source) + '</span></div>' +\n '</div>';\n }\n html += '</div>';\n }\n el.innerHTML = html;\n}\n\nasync function doDisable(id) {\n await api('POST', '/api/disable', { id });\n document.getElementById('card-' + id)?.remove();\n loadStatus();\n}\n\n// ── Network Page ──────────────────────────────────────────────────────\nasync function loadNetwork() {\n const network = await api('GET', '/api/network');\n const el = document.getElementById('page-network');\n const entries = Object.entries(network);\n if (entries.length === 0) {\n el.innerHTML = '<div class=\"empty\">No agents have taught yours yet.</div>';\n return;\n }\n\n let html = '<h2>Who Taught Your Agent</h2>';\n entries.sort((a, b) => b[1].lessons - a[1].lessons);\n for (const [agent, data] of entries) {\n const d = data;\n const badgeClass = 'badge badge-' + d.trust;\n html += '<div class=\"card\"><div class=\"trust-row\">' +\n '<div><div class=\"trust-agent\">' + esc(agent) + ' <span class=\"' + badgeClass + '\">' + d.trust + '</span></div>' +\n '<div class=\"trust-lessons\">' + d.lessons + ' lesson(s): ' + d.skills.map(esc).join(', ') + '</div></div>' +\n '<div class=\"btn-group\">' +\n (d.trust !== 'trusted' ? '<button class=\"btn btn-trust btn-small\" onclick=\"setTrust(\\\\''+esc(agent)+'\\\\',\\\\'trusted\\\\')\">Trust</button>' : '') +\n (d.trust !== 'blocked' ? '<button class=\"btn btn-reject btn-small\" onclick=\"setTrust(\\\\''+esc(agent)+'\\\\',\\\\'blocked\\\\')\">Block</button>' : '') +\n (d.trust !== 'pending' ? '<button class=\"btn btn-disable btn-small\" onclick=\"setTrust(\\\\''+esc(agent)+'\\\\',\\\\'pending\\\\')\">Reset</button>' : '') +\n '</div>' +\n '</div></div>';\n }\n el.innerHTML = html;\n}\n\nasync function setTrust(agent, level) {\n await api('POST', '/api/trust', { agent, level });\n loadNetwork();\n}\n\n// ── Settings Page ─────────────────────────────────────────────────────\nasync function loadSettings() {\n const status = await api('GET', '/api/status');\n const trust = await api('GET', '/api/trust');\n const stats = await api('GET', '/api/stats');\n\n const el = document.getElementById('page-settings');\n el.innerHTML = '<h2>Settings</h2>' +\n '<div class=\"card\">' +\n '<div class=\"toggle\">' +\n '<div class=\"toggle-switch ' + status.state + '\" id=\"toggle-state\" onclick=\"toggleState()\"></div>' +\n '<span>Proxy is <strong>' + status.state.toUpperCase() + '</strong></span>' +\n '</div>' +\n '</div>' +\n '<div class=\"card\">' +\n '<h2 style=\"margin-bottom:8px\">Default Trust</h2>' +\n '<div class=\"card-meta\" style=\"margin-bottom:12px\">What happens when a new agent teaches your agent</div>' +\n '<div class=\"btn-group\">' +\n '<button class=\"btn ' + (trust.default === 'pending' ? 'btn-approve' : 'btn-disable') + '\" onclick=\"setDefaultTrust(\\\\'pending\\\\')\">Pending (review)</button>' +\n '<button class=\"btn ' + (trust.default === 'trusted' ? 'btn-approve' : 'btn-disable') + '\" onclick=\"setDefaultTrust(\\\\'trusted\\\\')\">Auto-approve</button>' +\n '<button class=\"btn ' + (trust.default === 'blocked' ? 'btn-approve' : 'btn-disable') + '\" onclick=\"setDefaultTrust(\\\\'blocked\\\\')\">Block all</button>' +\n '</div>' +\n '</div>' +\n '<div class=\"card\">' +\n '<h2 style=\"margin-bottom:8px\">Stats</h2>' +\n '<div class=\"card-meta\" style=\"flex-direction:column;gap:4px\">' +\n '<span>Approved: ' + stats.total_approved + '</span>' +\n '<span>Pending: ' + stats.total_pending + '</span>' +\n '<span>Rejected: ' + stats.total_rejected + '</span>' +\n '<span>Lessons today: ' + stats.today_lessons + '</span>' +\n '</div>' +\n '</div>' +\n '<div class=\"card\">' +\n '<h2 style=\"margin-bottom:8px;color:var(--red)\">Danger Zone</h2>' +\n '<div class=\"btn-group\">' +\n '<button class=\"btn btn-reject\" onclick=\"if(confirm(\\\\'Clear all skills?\\\\'))clearAll()\">Clear All Skills</button>' +\n '</div>' +\n '</div>';\n}\n\nasync function toggleState() {\n const el = document.getElementById('toggle-state');\n const newState = el.classList.contains('on') ? 'off' : 'on';\n await api('POST', '/api/state', { state: newState });\n loadStatus();\n loadSettings();\n}\n\nasync function setDefaultTrust(level) {\n await api('POST', '/api/trust/default', { level });\n loadSettings();\n}\n\nasync function clearAll() {\n const skills = await api('GET', '/api/skills');\n for (const s of skills) {\n await api('DELETE', '/api/skill', { id: s.id });\n }\n loadStatus();\n loadSettings();\n}\n\nfunction esc(s) {\n if (!s) return '';\n return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"').replace(/'/g,''');\n}\n\n// Init\nloadStatus();\nloadPending();\nsetInterval(loadStatus, 10000);\n</script>\n</body>\n</html>`;\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, unlinkSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { execSync } from 'node:child_process';\nimport type { BecomeConfig } from '../config.js';\n\n// IronClaw .env is at ~/.ironclaw/.env (overridable via IRONCLAW_BASE_DIR)\n// Source: https://github.com/nearai/ironclaw src/service.rs, .env.example\nconst IRONCLAW_ENV = join(process.env.IRONCLAW_BASE_DIR ?? join(homedir(), '.ironclaw'), '.env');\nconst BACKUP_PATH = join(homedir(), '.become', 'state', 'original_ironclaw.env');\nconst ORIGINAL_URL_PATH = join(homedir(), '.become', 'state', 'original_base_url.txt');\n\nexport function patchIronClaw(config: BecomeConfig): void {\n if (!existsSync(IRONCLAW_ENV)) {\n throw new Error(`IronClaw .env not found at ${IRONCLAW_ENV}`);\n }\n\n // Don't patch twice\n if (existsSync(BACKUP_PATH)) {\n console.log('become is already connected to IronClaw. Run `become off` first.');\n return;\n }\n\n // Backup\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n copyFileSync(IRONCLAW_ENV, BACKUP_PATH);\n\n // Read current .env to determine which var to patch\n // IronClaw uses LLM_BACKEND to select provider. Each provider has its own base URL var.\n // Source: src/config/llm.rs\n const content = readFileSync(IRONCLAW_ENV, 'utf-8');\n const backendMatch = content.match(/^LLM_BACKEND=(.+)$/m);\n const backend = backendMatch?.[1]?.trim().toLowerCase() ?? 'openai_compatible';\n\n const proxyUrl = `http://127.0.0.1:${config.proxy_port}`;\n const vars: Record<string, string> = {};\n\n // Patch the correct base URL var for the active backend\n switch (backend) {\n case 'anthropic':\n vars['ANTHROPIC_BASE_URL'] = proxyUrl;\n break;\n case 'ollama':\n vars['OLLAMA_BASE_URL'] = proxyUrl;\n break;\n case 'nearai':\n case 'near_ai':\n case 'near':\n vars['NEARAI_BASE_URL'] = proxyUrl;\n break;\n default:\n // openai, openai_compatible, openrouter, or any unknown value\n vars['LLM_BASE_URL'] = proxyUrl;\n break;\n }\n\n // Save the original URL so the proxy knows where to forward\n const urlVarName = Object.keys(vars)[0];\n const originalUrlMatch = content.match(new RegExp(`^${urlVarName}=(.+)$`, 'm'));\n const originalUrl = originalUrlMatch?.[1]?.trim() ?? '';\n if (originalUrl) {\n writeFileSync(ORIGINAL_URL_PATH, originalUrl, 'utf-8');\n }\n\n patchDotEnv(IRONCLAW_ENV, vars);\n\n console.log(` backend: ${backend}`);\n console.log(` patched: ${Object.keys(vars).join(', ')} -> localhost:${config.proxy_port}`);\n\n restartIronClaw();\n}\n\nexport function restoreIronClaw(): void {\n if (!existsSync(BACKUP_PATH)) {\n return;\n }\n copyFileSync(BACKUP_PATH, IRONCLAW_ENV);\n try { unlinkSync(BACKUP_PATH); } catch {}\n restartIronClaw();\n}\n\n// IronClaw has no `restart` command. Must stop + start.\n// CLI: ironclaw service {install,start,stop,status,uninstall}\n// macOS label: com.ironclaw.daemon\n// Linux unit: ironclaw.service (~/.config/systemd/user/)\n// Source: src/cli/service.rs, src/service.rs\nfunction restartIronClaw(): void {\n console.log('Restarting IronClaw...');\n\n // Try CLI stop + start first\n try {\n execSync('ironclaw service stop', { stdio: 'pipe', timeout: 10000 });\n execSync('ironclaw service start', { stdio: 'pipe', timeout: 10000 });\n console.log('IronClaw restarted.');\n return;\n } catch {}\n\n // Fallback: try launchctl (macOS)\n try {\n execSync('launchctl kickstart -k gui/$(id -u)/com.ironclaw.daemon', { stdio: 'pipe', timeout: 10000 });\n console.log('IronClaw restarted via launchctl.');\n return;\n } catch {}\n\n // Fallback: try systemd (Linux)\n try {\n execSync('systemctl --user restart ironclaw', { stdio: 'pipe', timeout: 10000 });\n console.log('IronClaw restarted via systemd.');\n return;\n } catch {}\n\n console.log('\\n*** IronClaw needs a manual restart. ***');\n console.log('*** Run: ironclaw service stop && ironclaw service start ***\\n');\n}\n\nfunction patchDotEnv(path: string, vars: Record<string, string>): void {\n let content = existsSync(path) ? readFileSync(path, 'utf-8') : '';\n for (const [key, value] of Object.entries(vars)) {\n const regex = new RegExp(`^${key}=.*$`, 'm');\n if (regex.test(content)) {\n content = content.replace(regex, `${key}=${value}`);\n } else {\n content = content.trimEnd() + (content.length > 0 ? '\\n' : '') + `${key}=${value}\\n`;\n }\n }\n writeFileSync(path, content, 'utf-8');\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, unlinkSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { execSync } from 'node:child_process';\nimport type { BecomeConfig } from '../config.js';\n\n// NanoClaw .env lives in the project root (where nanoclaw was cloned/installed).\n// NOT in ~/.nanoclaw/ (that doesn't exist).\n// Source: https://github.com/qwibitai/nanoclaw src/env.ts reads process.cwd()/.env\nconst BACKUP_PATH = join(homedir(), '.become', 'state', 'original_nanoclaw.env');\nconst PATCHED_ENV_PATH_FILE = join(homedir(), '.become', 'state', 'nanoclaw_env_path.txt');\nconst ORIGINAL_URL_PATH = join(homedir(), '.become', 'state', 'original_base_url.txt');\n\n// NanoClaw uses ANTHROPIC_BASE_URL for custom LLM endpoints.\n// It routes everything through a credential proxy (OneCLI) that\n// forwards to Anthropic or a custom ANTHROPIC_BASE_URL.\n// Source: GitHub README, src/config.ts\nconst NANOCLAW_URL_VAR = 'ANTHROPIC_BASE_URL';\n\nexport function patchNanoClaw(config: BecomeConfig): void {\n const envPath = findNanoClawEnv();\n if (!envPath) {\n throw new Error(\n 'Could not find NanoClaw .env file.\\n' +\n 'NanoClaw stores .env in its project root (where you cloned it).\\n' +\n `Set ${NANOCLAW_URL_VAR}=http://127.0.0.1:${config.proxy_port} manually in your NanoClaw .env file.`\n );\n }\n\n // Don't patch twice\n if (existsSync(BACKUP_PATH)) {\n console.log('become is already connected to NanoClaw. Run `become off` first.');\n return;\n }\n\n // Backup\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n copyFileSync(envPath, BACKUP_PATH);\n writeFileSync(PATCHED_ENV_PATH_FILE, envPath, 'utf-8');\n\n // Save original URL so the proxy knows where to forward\n const content = readFileSync(envPath, 'utf-8');\n const originalMatch = content.match(new RegExp(`^${NANOCLAW_URL_VAR}=(.+)$`, 'm'));\n const originalUrl = originalMatch?.[1]?.trim() ?? '';\n if (originalUrl) {\n writeFileSync(ORIGINAL_URL_PATH, originalUrl, 'utf-8');\n }\n\n // Patch\n patchDotEnv(envPath, {\n [NANOCLAW_URL_VAR]: `http://127.0.0.1:${config.proxy_port}`,\n });\n\n console.log(` env file: ${envPath}`);\n console.log(` patched: ${NANOCLAW_URL_VAR} -> localhost:${config.proxy_port}`);\n\n restartNanoClaw();\n}\n\nexport function restoreNanoClaw(): void {\n if (!existsSync(BACKUP_PATH)) {\n return;\n }\n\n // Use stored path to avoid restoring to wrong file\n let envPath: string | null = null;\n if (existsSync(PATCHED_ENV_PATH_FILE)) {\n envPath = readFileSync(PATCHED_ENV_PATH_FILE, 'utf-8').trim();\n }\n if (!envPath) {\n envPath = findNanoClawEnv();\n }\n if (!envPath) {\n console.log('Warning: Cannot find NanoClaw .env to restore. Backup is at ' + BACKUP_PATH);\n return;\n }\n\n copyFileSync(BACKUP_PATH, envPath);\n try { unlinkSync(BACKUP_PATH); } catch {}\n try { unlinkSync(PATCHED_ENV_PATH_FILE); } catch {}\n restartNanoClaw();\n}\n\nfunction findNanoClawEnv(): string | null {\n const candidates: string[] = [];\n\n // macOS: extract WorkingDirectory from launchd plist\n // Label: com.nanoclaw, plist at ~/Library/LaunchAgents/com.nanoclaw.plist\n // Source: launchd/com.nanoclaw.plist template, setup/service.ts\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', 'com.nanoclaw.plist');\n if (existsSync(plistPath)) {\n try {\n const plist = readFileSync(plistPath, 'utf-8');\n const match = plist.match(/<key>WorkingDirectory<\\/key>\\s*<string>([^<]+)<\\/string>/);\n if (match) candidates.push(join(match[1], '.env'));\n } catch {}\n }\n\n // Linux: extract WorkingDirectory from systemd user unit\n // Unit: ~/.config/systemd/user/nanoclaw.service\n // Source: setup/service.ts\n const userUnit = join(homedir(), '.config', 'systemd', 'user', 'nanoclaw.service');\n if (existsSync(userUnit)) {\n try {\n const unit = readFileSync(userUnit, 'utf-8');\n const match = unit.match(/WorkingDirectory=(.+)/);\n if (match) candidates.push(join(match[1].trim(), '.env'));\n } catch {}\n }\n\n // Linux root: /etc/systemd/system/nanoclaw.service\n const rootUnit = '/etc/systemd/system/nanoclaw.service';\n if (existsSync(rootUnit)) {\n try {\n const unit = readFileSync(rootUnit, 'utf-8');\n const match = unit.match(/WorkingDirectory=(.+)/);\n if (match) candidates.push(join(match[1].trim(), '.env'));\n } catch {}\n }\n\n // Common clone locations\n candidates.push(join(homedir(), 'nanoclaw', '.env'));\n candidates.push('/opt/nanoclaw/.env');\n\n for (const path of candidates) {\n if (existsSync(path)) return path;\n }\n return null;\n}\n\n// NanoClaw restart:\n// macOS: launchctl unload + load (label: com.nanoclaw)\n// Linux user: systemctl --user restart nanoclaw\n// Linux root: sudo systemctl restart nanoclaw\n// Source: setup/service.ts, launchd/com.nanoclaw.plist\nfunction restartNanoClaw(): void {\n console.log('Restarting NanoClaw...');\n\n // macOS: unload + load the plist\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', 'com.nanoclaw.plist');\n if (existsSync(plistPath)) {\n try {\n execSync(`launchctl unload \"${plistPath}\"`, { stdio: 'pipe', timeout: 10000 });\n execSync(`launchctl load \"${plistPath}\"`, { stdio: 'pipe', timeout: 10000 });\n console.log('NanoClaw restarted.');\n return;\n } catch {}\n }\n\n // Linux user-level systemd\n try {\n execSync('systemctl --user restart nanoclaw', { stdio: 'pipe', timeout: 10000 });\n console.log('NanoClaw restarted.');\n return;\n } catch {}\n\n console.log('\\n*** NanoClaw needs a manual restart. ***');\n console.log('*** macOS: launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist && launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist ***');\n console.log('*** Linux: systemctl --user restart nanoclaw ***\\n');\n}\n\nfunction patchDotEnv(path: string, vars: Record<string, string>): void {\n let content = existsSync(path) ? readFileSync(path, 'utf-8') : '';\n for (const [key, value] of Object.entries(vars)) {\n const regex = new RegExp(`^${key}=.*$`, 'm');\n if (regex.test(content)) {\n content = content.replace(regex, `${key}=${value}`);\n } else {\n content = content.trimEnd() + (content.length > 0 ? '\\n' : '') + `${key}=${value}\\n`;\n }\n }\n writeFileSync(path, content, 'utf-8');\n}\n","/**\n * LLM adapter interface — pluggable backend for skill evolution, norm detection, and scoring.\n */\nexport interface LLMAdapter {\n /** Generate a text completion */\n complete(prompt: string, opts?: LLMOptions): Promise<string>;\n\n /** Generate a structured JSON response */\n json<T = unknown>(prompt: string, opts?: LLMOptions): Promise<T>;\n}\n\nexport interface LLMOptions {\n maxTokens?: number;\n temperature?: number;\n model?: string;\n /** Request timeout in milliseconds (default: 60000) */\n timeoutMs?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\n\n// ── OpenAI-compatible adapter ───────────────────────────────────────────\n\nexport interface OpenAIConfig {\n apiKey: string;\n baseUrl?: string;\n model?: string;\n}\n\nexport class OpenAIAdapter implements LLMAdapter {\n private apiKey: string;\n private baseUrl: string;\n private defaultModel: string;\n\n constructor(config: OpenAIConfig) {\n if (!config.apiKey) throw new Error('OpenAI API key is required');\n this.apiKey = config.apiKey;\n this.baseUrl = (config.baseUrl ?? 'https://api.openai.com').replace(/\\/+$/, '');\n this.defaultModel = config.model ?? 'gpt-4o-mini';\n }\n\n async complete(prompt: string, opts?: LLMOptions): Promise<string> {\n const response = await this.request({\n model: opts?.model ?? this.defaultModel,\n messages: [{ role: 'user', content: prompt }],\n max_tokens: opts?.maxTokens ?? 2000,\n temperature: opts?.temperature ?? 0.7,\n }, opts?.timeoutMs);\n return response.choices?.[0]?.message?.content ?? '';\n }\n\n async json<T = unknown>(prompt: string, opts?: LLMOptions): Promise<T> {\n const response = await this.request({\n model: opts?.model ?? this.defaultModel,\n messages: [{ role: 'user', content: prompt }],\n max_tokens: opts?.maxTokens ?? 2000,\n temperature: opts?.temperature ?? 0.3,\n response_format: { type: 'json_object' },\n }, opts?.timeoutMs);\n const text = response.choices?.[0]?.message?.content ?? '{}';\n return JSON.parse(text) as T;\n }\n\n private async request(body: Record<string, unknown>, timeoutMs?: number): Promise<any> {\n const res = await fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs ?? DEFAULT_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'unknown error');\n throw new Error(`OpenAI API error ${res.status}: ${text.slice(0, 200)}`);\n }\n\n return res.json();\n }\n}\n\n// ── Anthropic adapter ───────────────────────────────────────────────────\n\nexport interface AnthropicConfig {\n apiKey: string;\n model?: string;\n}\n\nexport class AnthropicAdapter implements LLMAdapter {\n private apiKey: string;\n private defaultModel: string;\n\n constructor(config: AnthropicConfig) {\n if (!config.apiKey) throw new Error('Anthropic API key is required');\n this.apiKey = config.apiKey;\n this.defaultModel = config.model ?? 'claude-sonnet-4-20250514';\n }\n\n async complete(prompt: string, opts?: LLMOptions): Promise<string> {\n const res = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify({\n model: opts?.model ?? this.defaultModel,\n max_tokens: opts?.maxTokens ?? 2000,\n messages: [{ role: 'user', content: prompt }],\n }),\n signal: AbortSignal.timeout(opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'unknown error');\n throw new Error(`Anthropic API error ${res.status}: ${text.slice(0, 200)}`);\n }\n\n const data = await res.json() as any;\n return data.content?.[0]?.text ?? '';\n }\n\n async json<T = unknown>(prompt: string, opts?: LLMOptions): Promise<T> {\n const text = await this.complete(\n `${prompt}\\n\\nRespond with valid JSON only, no other text.`,\n { ...opts, temperature: opts?.temperature ?? 0.3 },\n );\n // Try parsing the whole text first, then extract JSON\n try {\n return JSON.parse(text.trim()) as T;\n } catch {\n // Extract first valid JSON object or array (non-greedy)\n const match = text.match(/\\{[\\s\\S]*?\\}(?=\\s*$|\\s*[^}\\]])/);\n const arrMatch = text.match(/\\[[\\s\\S]*?\\](?=\\s*$|\\s*[^}\\]])/);\n const candidate = match?.[0] ?? arrMatch?.[0];\n if (!candidate) throw new Error('No JSON found in response');\n return JSON.parse(candidate) as T;\n }\n }\n}\n\n// ── Ollama adapter (local models) ───────────────────────────────────────\n\nexport interface OllamaConfig {\n baseUrl?: string;\n model?: string;\n}\n\nexport class OllamaAdapter implements LLMAdapter {\n private baseUrl: string;\n private defaultModel: string;\n\n constructor(config?: OllamaConfig) {\n this.baseUrl = (config?.baseUrl ?? 'http://localhost:11434').replace(/\\/+$/, '');\n this.defaultModel = config?.model ?? 'llama3.1';\n }\n\n async complete(prompt: string, opts?: LLMOptions): Promise<string> {\n const res = await fetch(`${this.baseUrl}/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: opts?.model ?? this.defaultModel,\n prompt,\n stream: false,\n options: {\n num_predict: opts?.maxTokens ?? 2000,\n temperature: opts?.temperature ?? 0.7,\n },\n }),\n signal: AbortSignal.timeout(opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'unknown error');\n throw new Error(`Ollama error ${res.status}: ${text.slice(0, 200)}`);\n }\n\n const data = await res.json() as any;\n return data.response ?? '';\n }\n\n async json<T = unknown>(prompt: string, opts?: LLMOptions): Promise<T> {\n const res = await fetch(`${this.baseUrl}/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: opts?.model ?? this.defaultModel,\n prompt: `${prompt}\\n\\nRespond with valid JSON only.`,\n stream: false,\n format: 'json',\n options: {\n num_predict: opts?.maxTokens ?? 2000,\n temperature: opts?.temperature ?? 0.3,\n },\n }),\n signal: AbortSignal.timeout(opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'unknown error');\n throw new Error(`Ollama error ${res.status}: ${text.slice(0, 200)}`);\n }\n\n const data = await res.json() as any;\n return JSON.parse(data.response ?? '{}') as T;\n }\n}\n"],"mappings":"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CF;;;ACjIO,SAAS,sBAA8B;AAC5C,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["import_node_fs","import_node_path","import_node_os","import_node_fs","import_node_path","import_node_os","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_http","readBody","import_node_fs","import_node_path","import_node_os","import_node_child_process","BACKUP_PATH","ORIGINAL_URL_PATH","import_node_fs","import_node_path","import_node_os","import_node_child_process","BACKUP_PATH","ORIGINAL_URL_PATH","patchDotEnv","import_node_fs","import_node_path"]}
|