@openclawcity/become 1.0.2 → 1.0.4
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 +216 -129
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +210 -123
- package/dist/cli.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/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/openclaw.ts","../src/cli/adapter/ironclaw.ts","../src/cli/adapter/nanoclaw.ts","../src/cli/commands.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// Re-export from new CLI entry point\nexport { runSetup } from './setup.js';\nexport { start, turnOn, turnOff, showStatus } from './commands.js';\n\n// When run directly, delegate to the new CLI\nimport { runSetup } from './setup.js';\nimport { start, turnOn, turnOff, showStatus } from './commands.js';\n\nconst command = process.argv[2];\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 'init':\n // Legacy: init command for DB setup\n console.log('The `init` command is no longer needed. Use `become setup` instead.');\n break;\n default:\n console.log(`\nbecome — agent-to-agent learning\n\nUsage:\n become setup Set up become (interactive wizard)\n become start Start the proxy server\n become on Route your agent through become\n become off Disconnect — agent talks directly to LLM\n become status Show current status\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';\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 // LLM provider\n console.log('\\nWhich LLM provider?');\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 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 start the proxy and dashboard.');\n console.log('Run `become on` to route your agent through become.\\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 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 { 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) {\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 // 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 // Only proxy POST requests to LLM endpoints\n const isOpenAI = req.url === '/v1/chat/completions';\n const isAnthropic = req.url === '/v1/messages';\n\n if (req.method !== 'POST' || (!isOpenAI && !isAnthropic)) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found. Use POST /v1/chat/completions or /v1/messages' }));\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 — always match the incoming format\n const upstreamUrl = buildUpstreamUrl(config, 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 const upstreamRes = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: modifiedBody,\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 // 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(config: ProxyConfig, path: string): string {\n const base = config.llm_base_url.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 const response = await this.analyzer.analyze(prompt);\n const lessons = this.parseLessons(response);\n\n for (const lesson of lessons.slice(0, 3)) {\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 this.trust.recordLesson(agentId);\n\n // Auto-approve if agent is trusted\n if (trustLevel === 'trusted') {\n this.store.approve(saved.id);\n }\n }\n }\n } catch {\n // Extraction failure is never fatal\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 } 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 BACKUP_PATH = join(homedir(), '.become', 'state', 'original_openclaw.json');\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 = JSON.parse(raw);\n\n // Backup original (only if not already patched by become)\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n if (!clawConfig.models?.providers?.become) {\n writeFileSync(BACKUP_PATH, raw, 'utf-8');\n }\n\n // Store original model for restore (in become state, NOT in openclaw config)\n const originalModel = clawConfig.agents?.defaults?.model?.primary ?? '';\n const originalModelPath = join(homedir(), '.become', 'state', 'original_model.txt');\n writeFileSync(originalModelPath, originalModel, 'utf-8');\n\n // Extract the model ID (strip provider prefix if present)\n const modelId = originalModel.includes('/') ? originalModel.split('/').slice(1).join('/') : originalModel;\n\n // Add become as a provider with required models array\n if (!clawConfig.models) clawConfig.models = {};\n if (!clawConfig.models.providers) clawConfig.models.providers = {};\n\n // OpenClaw requires models as array of objects with at least { id }\n // See: https://docs.openclaw.ai/gateway/configuration-reference\n clawConfig.models.providers.become = {\n api: config.llm_provider === 'openai' ? 'openai-completions' : 'anthropic-messages',\n baseUrl: `http://127.0.0.1:${config.proxy_port}`,\n apiKey: config.llm_api_key,\n models: [\n { id: modelId, name: `${modelId} via become` },\n ],\n };\n\n // Patch primary model to use become provider\n if (originalModel) {\n clawConfig.agents.defaults.model.primary = `become/${modelId}`;\n }\n\n writeFileSync(OPENCLAW_CONFIG, JSON.stringify(clawConfig, null, 2), 'utf-8');\n\n // Restart gateway\n try {\n execSync('openclaw gateway restart', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart OpenClaw gateway. Restart it manually: openclaw gateway restart');\n }\n}\n\nexport function restoreOpenClaw(): void {\n if (!existsSync(OPENCLAW_CONFIG)) {\n throw new Error(`OpenClaw config not found at ${OPENCLAW_CONFIG}`);\n }\n\n // If we have a clean backup, use it\n if (existsSync(BACKUP_PATH)) {\n const backup = readFileSync(BACKUP_PATH, 'utf-8');\n const backupConfig = JSON.parse(backup);\n // Only restore if backup is clean (no become provider)\n if (!backupConfig.models?.providers?.become) {\n writeFileSync(OPENCLAW_CONFIG, backup, 'utf-8');\n } else {\n // Backup is corrupted; manually remove become from current config\n manualRestore();\n }\n } else {\n // No backup; manually remove become from current config\n manualRestore();\n }\n\n try {\n execSync('openclaw gateway restart', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart OpenClaw gateway. Restart it manually: openclaw gateway restart');\n }\n}\n\nfunction manualRestore(): void {\n const raw = readFileSync(OPENCLAW_CONFIG, 'utf-8');\n const config = JSON.parse(raw);\n\n // Restore original model from saved file\n const originalModelPath = join(homedir(), '.become', 'state', 'original_model.txt');\n if (existsSync(originalModelPath)) {\n const originalModel = readFileSync(originalModelPath, 'utf-8').trim();\n if (originalModel && config.agents?.defaults?.model) {\n config.agents.defaults.model.primary = originalModel;\n }\n }\n\n // Remove become provider\n if (config.models?.providers?.become) {\n delete config.models.providers.become;\n }\n\n // Clean up _originalModel from any provider (legacy bug)\n for (const provider of Object.values(config.models?.providers ?? {})) {\n if (provider && typeof provider === 'object' && '_originalModel' in provider) {\n delete (provider as Record<string, unknown>)._originalModel;\n }\n }\n\n writeFileSync(OPENCLAW_CONFIG, JSON.stringify(config, null, 2), 'utf-8');\n}\n\nexport function isOpenClawPatched(): boolean {\n if (!existsSync(OPENCLAW_CONFIG)) return false;\n try {\n const config = JSON.parse(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n return !!config.models?.providers?.become;\n } catch {\n return false;\n }\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync } 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 IRONCLAW_ENV = join(homedir(), '.ironclaw', '.env');\nconst BACKUP_PATH = join(homedir(), '.become', 'state', 'original_ironclaw.env');\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 // Backup\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n copyFileSync(IRONCLAW_ENV, BACKUP_PATH);\n\n // Patch\n patchDotEnv(IRONCLAW_ENV, {\n LLM_BASE_URL: `http://127.0.0.1:${config.proxy_port}/v1`,\n });\n\n try {\n execSync('ironclaw service restart', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart IronClaw. Restart it manually: ironclaw service restart');\n }\n}\n\nexport function restoreIronClaw(): void {\n if (!existsSync(BACKUP_PATH)) {\n throw new Error('No backup found. Was become ever turned on?');\n }\n copyFileSync(BACKUP_PATH, IRONCLAW_ENV);\n try {\n execSync('ironclaw service restart', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart IronClaw. Restart it manually: ironclaw service restart');\n }\n}\n\nfunction patchDotEnv(path: string, vars: Record<string, string>): void {\n let content = 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 += `\\n${key}=${value}`;\n }\n }\n writeFileSync(path, content, 'utf-8');\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync } 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 BACKUP_PATH = join(homedir(), '.become', 'state', 'original_nanoclaw.env');\n\nexport function patchNanoClaw(config: BecomeConfig): void {\n const envPath = findNanoClawEnv();\n if (!envPath) {\n throw new Error('Could not find NanoClaw .env. Set ANTHROPIC_BASE_URL manually to http://127.0.0.1:' + config.proxy_port);\n }\n\n // Backup\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n copyFileSync(envPath, BACKUP_PATH);\n\n // Patch\n patchDotEnv(envPath, {\n ANTHROPIC_BASE_URL: `http://127.0.0.1:${config.proxy_port}`,\n });\n\n // Restart\n restartNanoClaw();\n}\n\nexport function restoreNanoClaw(): void {\n const envPath = findNanoClawEnv();\n if (!existsSync(BACKUP_PATH) || !envPath) {\n throw new Error('No backup found. Was become ever turned on?');\n }\n copyFileSync(BACKUP_PATH, envPath);\n restartNanoClaw();\n}\n\nfunction findNanoClawEnv(): string | null {\n // Check common locations\n const candidates = [\n join(homedir(), '.nanoclaw', '.env'),\n join(homedir(), '.config', 'nanoclaw', '.env'),\n ];\n\n // Check launchd plist for macOS\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', 'ai.nanoclaw.agent.plist');\n if (existsSync(plistPath)) {\n try {\n const plist = readFileSync(plistPath, 'utf-8');\n const match = plist.match(/<string>([^<]*\\.env)<\\/string>/);\n if (match) candidates.unshift(match[1]);\n } catch {}\n }\n\n for (const path of candidates) {\n if (existsSync(path)) return path;\n }\n return null;\n}\n\nfunction restartNanoClaw(): void {\n try {\n // Try launchctl first (macOS)\n execSync('launchctl kickstart -k gui/$(id -u)/ai.nanoclaw.agent', { stdio: 'pipe', timeout: 15000 });\n } catch {\n try {\n // Try systemd (Linux)\n execSync('systemctl --user restart nanoclaw', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart NanoClaw. Restart it manually.');\n }\n }\n}\n\nfunction patchDotEnv(path: string, vars: Record<string, string>): void {\n let content = 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 += `\\n${key}=${value}`;\n }\n }\n writeFileSync(path, content, 'utf-8');\n}\n","import { loadConfig, saveConfig, getBecomeDir } 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';\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 const proxy = createProxyServer(proxyConfig);\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(`\\nSkills loaded: ${approved} approved, ${pending} pending`);\n console.log(`Trust rules: ${trustConfig.trusted.length} trusted, ${trustConfig.blocked.length} blocked`);\n\n if (config.state === 'on') {\n console.log('\\nProxy is ACTIVE — your agent is learning from other agents.');\n } else {\n console.log('\\nProxy is IDLE — run `become on` to route your agent through become.');\n }\n console.log('Use `become off` to disconnect. Ctrl+C to stop.\\n');\n\n // Handle shutdown\n const shutdown = async () => {\n console.log('\\nShutting down...');\n await Promise.all([proxy.close(), dashboard.close()]);\n process.exit(0);\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"],"mappings":"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","names":["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_fs","import_node_path","import_node_os","import_node_child_process","BACKUP_PATH","import_node_fs","import_node_path","import_node_os","import_node_child_process","BACKUP_PATH","patchDotEnv"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/init.ts","../src/cli/setup.ts","../src/cli/config.ts","../src/cli/adapter/openclaw.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/cli/commands.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// Re-export from new CLI entry point\nexport { runSetup } from './setup.js';\nexport { start, turnOn, turnOff, showStatus } from './commands.js';\n\n// When run directly, delegate to the new CLI\nimport { runSetup } from './setup.js';\nimport { start, turnOn, turnOff, showStatus } from './commands.js';\n\nconst command = process.argv[2];\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 'init':\n // Legacy: init command for DB setup\n console.log('The `init` command is no longer needed. Use `become setup` instead.');\n break;\n default:\n console.log(`\nbecome — agent-to-agent learning\n\nUsage:\n become setup Set up become (interactive wizard)\n become start Start the proxy server\n become on Route your agent through become\n become off Disconnect — agent talks directly to LLM\n become status Show current status\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 start the proxy and dashboard.');\n console.log('Run `become on` to route your agent through become.\\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 BACKUP_PATH = join(homedir(), '.become', 'state', 'original_openclaw.json');\nconst ORIGINAL_MODEL_PATH = join(homedir(), '.become', 'state', 'original_model.txt');\nconst PATCHED_AGENT_PATH = join(homedir(), '.become', 'state', 'patched_agent.txt');\n\ninterface OpenClawAgent {\n id: string;\n model?: string;\n workspace?: string;\n agentDir?: string;\n [key: string]: unknown;\n}\n\n/**\n * Read openclaw.json, list available agents, and patch the selected one\n * to route through the become proxy.\n *\n * OpenClaw provider schema (docs.openclaw.ai/gateway/configuration-reference):\n * models.providers.<id> = { api, baseUrl, apiKey, models: [{ id, name? }] }\n */\nexport function patchOpenClaw(config: BecomeConfig, agentId?: string): 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 = parseOpenClawConfig(raw);\n\n // Refuse to patch if already patched (prevents double-patch corruption)\n if (clawConfig.models?.providers?.become) {\n console.log('become is already connected. Run `become off` first to disconnect.');\n return;\n }\n\n // Backup original\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n writeFileSync(BACKUP_PATH, raw, 'utf-8');\n\n // Determine which agent to patch\n const agents: OpenClawAgent[] = clawConfig.agents?.list ?? [];\n let originalModel: string;\n let patchedAgentId: string;\n\n if (agents.length > 0 && agentId) {\n // Patch a specific agent from agents.list\n const agent = agents.find((a) => a.id === agentId);\n if (!agent) {\n throw new Error(`Agent \"${agentId}\" not found in agents.list. Available: ${agents.map((a) => a.id).join(', ')}`);\n }\n originalModel = agent.model ?? clawConfig.agents?.defaults?.model?.primary ?? '';\n patchedAgentId = agentId;\n\n const modelId = stripProvider(originalModel);\n if (!modelId) {\n throw new Error('No model configured for this agent. Set a model in openclaw.json first.');\n }\n agent.model = `become/${modelId}`;\n } else {\n // No agents.list or no specific agent requested: patch defaults\n originalModel = clawConfig.agents?.defaults?.model?.primary ?? '';\n patchedAgentId = '_defaults';\n\n const modelId = stripProvider(originalModel);\n if (!modelId) {\n throw new Error('No default model configured. Set agents.defaults.model.primary in openclaw.json first.');\n }\n if (!clawConfig.agents) clawConfig.agents = {};\n if (!clawConfig.agents.defaults) clawConfig.agents.defaults = {};\n if (!clawConfig.agents.defaults.model) clawConfig.agents.defaults.model = {};\n clawConfig.agents.defaults.model.primary = `become/${modelId}`;\n }\n\n // Store original model and patched agent for restore\n writeFileSync(ORIGINAL_MODEL_PATH, originalModel, 'utf-8');\n writeFileSync(PATCHED_AGENT_PATH, patchedAgentId, 'utf-8');\n\n // Add become as a provider\n // Schema: https://docs.openclaw.ai/gateway/configuration-reference\n const modelId = stripProvider(originalModel);\n if (!clawConfig.models) clawConfig.models = {};\n if (!clawConfig.models.providers) clawConfig.models.providers = {};\n\n clawConfig.models.providers.become = {\n api: config.llm_provider === 'openai' || config.llm_provider === 'openrouter'\n ? 'openai-completions' : 'anthropic-messages',\n baseUrl: `http://127.0.0.1:${config.proxy_port}`,\n apiKey: config.llm_api_key,\n models: [\n { id: modelId, name: `${modelId} via become` },\n ],\n };\n\n writeFileSync(OPENCLAW_CONFIG, JSON.stringify(clawConfig, null, 2), 'utf-8');\n\n // Restart gateway\n try {\n execSync('openclaw gateway restart', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart OpenClaw gateway. Restart it manually: openclaw gateway restart');\n }\n}\n\nexport function restoreOpenClaw(): void {\n if (!existsSync(OPENCLAW_CONFIG)) {\n throw new Error(`OpenClaw config not found at ${OPENCLAW_CONFIG}`);\n }\n\n // If we have a clean backup, use it\n if (existsSync(BACKUP_PATH)) {\n const backup = readFileSync(BACKUP_PATH, 'utf-8');\n const backupConfig = parseOpenClawConfig(backup);\n if (!backupConfig.models?.providers?.become) {\n writeFileSync(OPENCLAW_CONFIG, backup, 'utf-8');\n restartGateway();\n return;\n }\n }\n\n // Backup is missing or corrupted; manually restore\n const raw = readFileSync(OPENCLAW_CONFIG, 'utf-8');\n const config = parseOpenClawConfig(raw);\n\n // Read which agent was patched and what the original model was\n const patchedAgentId = readStateFile(PATCHED_AGENT_PATH);\n const originalModel = readStateFile(ORIGINAL_MODEL_PATH);\n\n if (originalModel) {\n const agents: OpenClawAgent[] = config.agents?.list ?? [];\n\n if (patchedAgentId && patchedAgentId !== '_defaults') {\n // Restore specific agent\n const agent = agents.find((a) => a.id === patchedAgentId);\n if (agent) {\n agent.model = originalModel;\n }\n } else {\n // Restore defaults\n if (config.agents?.defaults?.model) {\n config.agents.defaults.model.primary = originalModel;\n }\n }\n }\n\n // Remove become provider\n if (config.models?.providers?.become) {\n delete config.models.providers.become;\n }\n\n // Clean up _originalModel from any provider (legacy bug from v1.0.1)\n for (const provider of Object.values(config.models?.providers ?? {})) {\n if (provider && typeof provider === 'object' && '_originalModel' in provider) {\n delete (provider as Record<string, unknown>)._originalModel;\n }\n }\n\n writeFileSync(OPENCLAW_CONFIG, JSON.stringify(config, null, 2), 'utf-8');\n restartGateway();\n}\n\n/**\n * List available agents from openclaw.json.\n * Returns agents from agents.list, or a single \"default\" entry if no list exists.\n */\nexport function listOpenClawAgents(): { id: string; model: string }[] {\n if (!existsSync(OPENCLAW_CONFIG)) return [];\n\n try {\n const config = parseOpenClawConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n const agents: OpenClawAgent[] = config.agents?.list ?? [];\n const defaultModel = unbecome(config.agents?.defaults?.model?.primary ?? 'unknown');\n\n if (agents.length === 0) {\n return [{ id: '_defaults', model: defaultModel }];\n }\n\n return agents.map((a) => ({\n id: a.id,\n model: unbecome(a.model ?? defaultModel),\n }));\n } catch {\n return [];\n }\n}\n\nexport function isOpenClawPatched(): boolean {\n if (!existsSync(OPENCLAW_CONFIG)) return false;\n try {\n const config = parseOpenClawConfig(readFileSync(OPENCLAW_CONFIG, 'utf-8'));\n return !!config.models?.providers?.become;\n } catch {\n return false;\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────\n\nfunction stripProvider(model: string): string {\n return model.includes('/') ? model.split('/').slice(1).join('/') : model;\n}\n\n/** Strip the become/ prefix if present (for display purposes) */\nfunction unbecome(model: string): string {\n return model.startsWith('become/') ? model.replace('become/', '') : model;\n}\n\n/**\n * Parse openclaw.json. OpenClaw uses JSON5 (allows comments, trailing commas).\n * We strip comments and trailing commas before parsing with standard JSON.parse.\n */\nfunction parseOpenClawConfig(raw: string): any {\n // Strip single-line comments (// ...) and multi-line comments (/* ... */)\n const stripped = raw\n .replace(/\\/\\/.*$/gm, '')\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/,\\s*([\\]}])/g, '$1'); // trailing commas\n return JSON.parse(stripped);\n}\n\nfunction readStateFile(path: string): string {\n try {\n return existsSync(path) ? readFileSync(path, 'utf-8').trim() : '';\n } catch {\n return '';\n }\n}\n\nfunction restartGateway(): void {\n try {\n execSync('openclaw gateway restart', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart OpenClaw gateway. Restart it manually: openclaw gateway restart');\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) {\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 // 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 // Only proxy POST requests to LLM endpoints\n const isOpenAI = req.url === '/v1/chat/completions';\n const isAnthropic = req.url === '/v1/messages';\n\n if (req.method !== 'POST' || (!isOpenAI && !isAnthropic)) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found. Use POST /v1/chat/completions or /v1/messages' }));\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 — always match the incoming format\n const upstreamUrl = buildUpstreamUrl(config, 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 const upstreamRes = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: modifiedBody,\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 // 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(config: ProxyConfig, path: string): string {\n const base = config.llm_base_url.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 const response = await this.analyzer.analyze(prompt);\n const lessons = this.parseLessons(response);\n\n for (const lesson of lessons.slice(0, 3)) {\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 this.trust.recordLesson(agentId);\n\n // Auto-approve if agent is trusted\n if (trustLevel === 'trusted') {\n this.store.approve(saved.id);\n }\n }\n }\n } catch {\n // Extraction failure is never fatal\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 } 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 IRONCLAW_ENV = join(homedir(), '.ironclaw', '.env');\nconst BACKUP_PATH = join(homedir(), '.become', 'state', 'original_ironclaw.env');\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 // Backup\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n copyFileSync(IRONCLAW_ENV, BACKUP_PATH);\n\n // Patch\n patchDotEnv(IRONCLAW_ENV, {\n LLM_BASE_URL: `http://127.0.0.1:${config.proxy_port}/v1`,\n });\n\n try {\n execSync('ironclaw service restart', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart IronClaw. Restart it manually: ironclaw service restart');\n }\n}\n\nexport function restoreIronClaw(): void {\n if (!existsSync(BACKUP_PATH)) {\n throw new Error('No backup found. Was become ever turned on?');\n }\n copyFileSync(BACKUP_PATH, IRONCLAW_ENV);\n try {\n execSync('ironclaw service restart', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart IronClaw. Restart it manually: ironclaw service restart');\n }\n}\n\nfunction patchDotEnv(path: string, vars: Record<string, string>): void {\n let content = 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 += `\\n${key}=${value}`;\n }\n }\n writeFileSync(path, content, 'utf-8');\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync } 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 BACKUP_PATH = join(homedir(), '.become', 'state', 'original_nanoclaw.env');\n\nexport function patchNanoClaw(config: BecomeConfig): void {\n const envPath = findNanoClawEnv();\n if (!envPath) {\n throw new Error('Could not find NanoClaw .env. Set ANTHROPIC_BASE_URL manually to http://127.0.0.1:' + config.proxy_port);\n }\n\n // Backup\n mkdirSync(join(homedir(), '.become', 'state'), { recursive: true });\n copyFileSync(envPath, BACKUP_PATH);\n\n // Patch\n patchDotEnv(envPath, {\n ANTHROPIC_BASE_URL: `http://127.0.0.1:${config.proxy_port}`,\n });\n\n // Restart\n restartNanoClaw();\n}\n\nexport function restoreNanoClaw(): void {\n const envPath = findNanoClawEnv();\n if (!existsSync(BACKUP_PATH) || !envPath) {\n throw new Error('No backup found. Was become ever turned on?');\n }\n copyFileSync(BACKUP_PATH, envPath);\n restartNanoClaw();\n}\n\nfunction findNanoClawEnv(): string | null {\n // Check common locations\n const candidates = [\n join(homedir(), '.nanoclaw', '.env'),\n join(homedir(), '.config', 'nanoclaw', '.env'),\n ];\n\n // Check launchd plist for macOS\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', 'ai.nanoclaw.agent.plist');\n if (existsSync(plistPath)) {\n try {\n const plist = readFileSync(plistPath, 'utf-8');\n const match = plist.match(/<string>([^<]*\\.env)<\\/string>/);\n if (match) candidates.unshift(match[1]);\n } catch {}\n }\n\n for (const path of candidates) {\n if (existsSync(path)) return path;\n }\n return null;\n}\n\nfunction restartNanoClaw(): void {\n try {\n // Try launchctl first (macOS)\n execSync('launchctl kickstart -k gui/$(id -u)/ai.nanoclaw.agent', { stdio: 'pipe', timeout: 15000 });\n } catch {\n try {\n // Try systemd (Linux)\n execSync('systemctl --user restart nanoclaw', { stdio: 'pipe', timeout: 15000 });\n } catch {\n console.log('Warning: Could not restart NanoClaw. Restart it manually.');\n }\n }\n}\n\nfunction patchDotEnv(path: string, vars: Record<string, string>): void {\n let content = 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 += `\\n${key}=${value}`;\n }\n }\n writeFileSync(path, content, 'utf-8');\n}\n","import { loadConfig, saveConfig, getBecomeDir } 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';\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 const proxy = createProxyServer(proxyConfig);\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(`\\nSkills loaded: ${approved} approved, ${pending} pending`);\n console.log(`Trust rules: ${trustConfig.trusted.length} trusted, ${trustConfig.blocked.length} blocked`);\n\n if (config.state === 'on') {\n console.log('\\nProxy is ACTIVE — your agent is learning from other agents.');\n } else {\n console.log('\\nProxy is IDLE — run `become on` to route your agent through become.');\n }\n console.log('Use `become off` to disconnect. Ctrl+C to stop.\\n');\n\n // Handle shutdown\n const shutdown = async () => {\n console.log('\\nShutting down...');\n await Promise.all([proxy.close(), dashboard.close()]);\n process.exit(0);\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, config.openclaw_agent_id);\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"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","modelId","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","import_node_fs","import_node_path","import_node_os","import_node_child_process","BACKUP_PATH","patchDotEnv"]}
|