@openacp/cli 0.2.5 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -25
- package/dist/chunk-3F7TYQ4H.js +1820 -0
- package/dist/chunk-3F7TYQ4H.js.map +1 -0
- package/dist/chunk-5KBEVENA.js +412 -0
- package/dist/chunk-5KBEVENA.js.map +1 -0
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +153 -45
- package/dist/index.js +15 -10
- package/dist/index.js.map +1 -1
- package/dist/{main-66K7T7MJ.js → main-VWRGYSPB.js} +31 -29
- package/dist/main-VWRGYSPB.js.map +1 -0
- package/dist/{setup-NLOC2GFD.js → setup-4EBTX2NJ.js} +4 -33
- package/dist/setup-4EBTX2NJ.js.map +1 -0
- package/package.json +6 -3
- package/dist/chunk-6YLIH7L5.js +0 -669
- package/dist/chunk-6YLIH7L5.js.map +0 -1
- package/dist/chunk-M5ZYTPZY.js +0 -220
- package/dist/chunk-M5ZYTPZY.js.map +0 -1
- package/dist/main-66K7T7MJ.js.map +0 -1
- package/dist/setup-NLOC2GFD.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../packages/core/src/streams.ts","../../packages/core/src/stderr-capture.ts","../../packages/core/src/agent-instance.ts","../../packages/core/src/agent-manager.ts","../../packages/core/src/session.ts","../../packages/core/src/session-manager.ts","../../packages/core/src/notification.ts","../../packages/core/src/core.ts"],"sourcesContent":["import type { Writable, Readable } from 'node:stream'\n\nexport function nodeToWebWritable(nodeStream: Writable): WritableStream<Uint8Array> {\n return new WritableStream<Uint8Array>({\n write(chunk) {\n return new Promise<void>((resolve, reject) => {\n nodeStream.write(Buffer.from(chunk), (err) => {\n if (err) reject(err)\n else resolve()\n })\n })\n },\n })\n}\n\nexport function nodeToWebReadable(nodeStream: Readable): ReadableStream<Uint8Array> {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n nodeStream.on('data', (chunk: Buffer) => {\n controller.enqueue(new Uint8Array(chunk))\n })\n nodeStream.on('end', () => controller.close())\n nodeStream.on('error', (err) => controller.error(err))\n },\n })\n}\n","export class StderrCapture {\n private lines: string[] = []\n\n constructor(private maxLines: number = 50) {}\n\n append(chunk: string): void {\n this.lines.push(...chunk.split('\\n').filter(Boolean))\n if (this.lines.length > this.maxLines) {\n this.lines = this.lines.slice(-this.maxLines)\n }\n }\n\n getLastLines(): string {\n return this.lines.join('\\n')\n }\n}\n","import { spawn, execSync, type ChildProcess } from 'node:child_process'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { randomUUID } from 'node:crypto'\nimport { ClientSideConnection, ndJsonStream } from '@agentclientprotocol/sdk'\nimport type { Agent, Client, PromptResponse, PermissionOption as SdkPermissionOption } from '@agentclientprotocol/sdk'\nimport { nodeToWebWritable, nodeToWebReadable } from './streams.js'\nimport { StderrCapture } from './stderr-capture.js'\nimport type { AgentDefinition, AgentEvent, PermissionRequest } from './types.js'\nimport { log } from './log.js'\n\n/** Resolve an agent command to a directly executable form (avoids shell wrappers) */\nfunction resolveAgentCommand(cmd: string): { command: string; args: string[] } {\n // 1. Check local node_modules for the package's actual JS entry point\n const packageDirs = [\n path.resolve(process.cwd(), 'node_modules', '@zed-industries', cmd, 'dist', 'index.js'),\n path.resolve(process.cwd(), 'node_modules', cmd, 'dist', 'index.js'),\n ]\n for (const jsPath of packageDirs) {\n if (fs.existsSync(jsPath)) {\n return { command: process.execPath, args: [jsPath] }\n }\n }\n\n // 2. Check local .bin — if it's a JS file with shebang, run with node directly\n const localBin = path.resolve(process.cwd(), 'node_modules', '.bin', cmd)\n if (fs.existsSync(localBin)) {\n const content = fs.readFileSync(localBin, 'utf-8')\n if (content.startsWith('#!/usr/bin/env node')) {\n return { command: process.execPath, args: [localBin] }\n }\n // Shell wrapper — try to find the target JS file\n const match = content.match(/\"([^\"]+\\.js)\"/)\n if (match) {\n const target = path.resolve(path.dirname(localBin), match[1])\n if (fs.existsSync(target)) {\n return { command: process.execPath, args: [target] }\n }\n }\n }\n\n // 3. Try resolving from PATH using which\n try {\n const fullPath = execSync(`which ${cmd}`, { encoding: 'utf-8' }).trim()\n if (fullPath) {\n const content = fs.readFileSync(fullPath, 'utf-8')\n if (content.startsWith('#!/usr/bin/env node')) {\n return { command: process.execPath, args: [fullPath] }\n }\n }\n } catch {\n // which failed\n }\n\n // 4. Fallback: use command as-is\n return { command: cmd, args: [] }\n}\n\ninterface TerminalState {\n process: ChildProcess\n output: string\n exitStatus: { exitCode: number | null; signal: string | null } | null\n}\n\nexport class AgentInstance {\n private connection!: ClientSideConnection\n private child!: ChildProcess\n private stderrCapture!: StderrCapture\n private terminals: Map<string, TerminalState> = new Map()\n\n sessionId!: string\n agentName: string\n\n // Callbacks — set by core when wiring events\n onSessionUpdate: (event: AgentEvent) => void = () => {}\n onPermissionRequest: (request: PermissionRequest) => Promise<string> = async () => ''\n\n private constructor(agentName: string) {\n this.agentName = agentName\n }\n\n static async spawn(agentDef: AgentDefinition, workingDirectory: string): Promise<AgentInstance> {\n const instance = new AgentInstance(agentDef.name)\n\n // 1. Resolve command: find the actual JS entry point to avoid shell wrappers\n const resolved = resolveAgentCommand(agentDef.command)\n log.debug(`Spawning agent \"${agentDef.name}\" → ${resolved.command} ${resolved.args.join(' ')}`)\n\n // Spawn subprocess\n instance.child = spawn(resolved.command, [...resolved.args, ...agentDef.args], {\n stdio: ['pipe', 'pipe', 'pipe'],\n cwd: workingDirectory,\n env: { ...process.env, ...agentDef.env },\n })\n\n // 2. Handle spawn errors (e.g., command not found)\n await new Promise<void>((resolve, reject) => {\n instance.child.on('error', (err) => {\n reject(new Error(`Failed to spawn agent \"${agentDef.name}\": ${err.message}. Is \"${agentDef.command}\" installed?`))\n })\n instance.child.on('spawn', () => resolve())\n })\n\n // 3. Capture stderr\n instance.stderrCapture = new StderrCapture(50)\n instance.child.stderr!.on('data', (chunk: Buffer) => {\n instance.stderrCapture.append(chunk.toString())\n })\n\n // 3. Create ACP stream\n const toAgent = nodeToWebWritable(instance.child.stdin!)\n const fromAgent = nodeToWebReadable(instance.child.stdout!)\n const stream = ndJsonStream(toAgent, fromAgent)\n\n // 4. Create ClientSideConnection\n instance.connection = new ClientSideConnection(\n (_agent: Agent): Client => instance.createClient(_agent),\n stream,\n )\n\n // 5. ACP handshake\n await instance.connection.initialize({\n protocolVersion: 1,\n clientCapabilities: {\n fs: { readTextFile: true, writeTextFile: true },\n terminal: true,\n },\n })\n\n // 6. Create session\n const response = await instance.connection.newSession({\n cwd: workingDirectory,\n mcpServers: [],\n })\n instance.sessionId = response.sessionId\n\n // 7. Crash detection\n instance.child.on('exit', (code, signal) => {\n if (code !== 0 && code !== null) {\n const stderr = instance.stderrCapture.getLastLines()\n instance.onSessionUpdate({\n type: 'error',\n message: `Agent crashed (exit code ${code})\\n${stderr}`,\n })\n }\n })\n\n instance.connection.closed.then(() => {\n // Connection closed — may be normal shutdown or crash\n log.debug('ACP connection closed for', instance.agentName)\n })\n\n log.info(`Agent \"${agentDef.name}\" spawned with session ${response.sessionId}`)\n return instance\n }\n\n // createClient — implemented in Task 6b\n private createClient(_agent: Agent): Client {\n const self = this\n const MAX_OUTPUT_BYTES = 1024 * 1024 // 1MB cap\n\n return {\n // ── Session updates ──────────────────────────────────────────────────\n async sessionUpdate(params) {\n const update = params.update\n let event: AgentEvent | null = null\n\n switch (update.sessionUpdate) {\n case 'agent_message_chunk':\n if (update.content.type === 'text') {\n event = { type: 'text', content: update.content.text }\n }\n break\n case 'agent_thought_chunk':\n if (update.content.type === 'text') {\n event = { type: 'thought', content: update.content.text }\n }\n break\n case 'tool_call':\n event = {\n type: 'tool_call',\n id: update.toolCallId,\n name: update.title,\n kind: update.kind ?? undefined,\n status: update.status ?? 'pending',\n content: update.content ?? undefined,\n }\n break\n case 'tool_call_update':\n event = {\n type: 'tool_update',\n id: update.toolCallId,\n status: update.status ?? 'pending',\n content: update.content ?? undefined,\n }\n break\n case 'plan':\n event = { type: 'plan', entries: update.entries }\n break\n case 'usage_update':\n event = {\n type: 'usage',\n tokensUsed: update.used,\n contextSize: update.size,\n cost: update.cost ?? undefined,\n }\n break\n case 'available_commands_update':\n event = { type: 'commands_update', commands: update.availableCommands }\n break\n default:\n // Unknown update type — ignore\n return\n }\n\n if (event !== null) {\n self.onSessionUpdate(event)\n }\n },\n\n // ── Permission requests ──────────────────────────────────────────────\n async requestPermission(params) {\n const permissionRequest: PermissionRequest = {\n id: params.toolCall.toolCallId,\n description: params.toolCall.title ?? params.toolCall.toolCallId,\n options: params.options.map((opt: SdkPermissionOption) => ({\n id: opt.optionId,\n label: opt.name,\n isAllow: opt.kind === 'allow_once' || opt.kind === 'allow_always',\n })),\n }\n\n const selectedOptionId = await self.onPermissionRequest(permissionRequest)\n return {\n outcome: { outcome: 'selected' as const, optionId: selectedOptionId },\n }\n },\n\n // ── File operations ──────────────────────────────────────────────────\n async readTextFile(params) {\n const content = await fs.promises.readFile(params.path, 'utf-8')\n return { content }\n },\n\n async writeTextFile(params) {\n await fs.promises.mkdir(path.dirname(params.path), { recursive: true })\n await fs.promises.writeFile(params.path, params.content, 'utf-8')\n return {}\n },\n\n // ── Terminal operations ──────────────────────────────────────────────\n async createTerminal(params) {\n const terminalId = randomUUID()\n const args = params.args ?? []\n const env: Record<string, string> = {}\n for (const ev of params.env ?? []) {\n env[ev.name] = ev.value\n }\n\n const childProcess = spawn(params.command, args, {\n cwd: params.cwd ?? undefined,\n env: { ...process.env, ...env },\n shell: false,\n })\n\n const state: TerminalState = {\n process: childProcess,\n output: '',\n exitStatus: null,\n }\n self.terminals.set(terminalId, state)\n\n const outputByteLimit = params.outputByteLimit ?? MAX_OUTPUT_BYTES\n\n const appendOutput = (chunk: string) => {\n state.output += chunk\n // Truncate from the beginning if over limit\n const bytes = Buffer.byteLength(state.output, 'utf-8')\n if (bytes > outputByteLimit) {\n // Find truncation point at character boundary\n const excess = bytes - outputByteLimit\n state.output = state.output.slice(excess)\n }\n }\n\n childProcess.stdout?.on('data', (chunk: Buffer) => appendOutput(chunk.toString()))\n childProcess.stderr?.on('data', (chunk: Buffer) => appendOutput(chunk.toString()))\n\n childProcess.on('exit', (code, signal) => {\n state.exitStatus = { exitCode: code, signal }\n })\n\n return { terminalId }\n },\n\n async terminalOutput(params) {\n const state = self.terminals.get(params.terminalId)\n if (!state) {\n throw new Error(`Terminal not found: ${params.terminalId}`)\n }\n return {\n output: state.output,\n truncated: false,\n exitStatus: state.exitStatus\n ? { exitCode: state.exitStatus.exitCode, signal: state.exitStatus.signal }\n : undefined,\n }\n },\n\n async waitForTerminalExit(params) {\n const state = self.terminals.get(params.terminalId)\n if (!state) {\n throw new Error(`Terminal not found: ${params.terminalId}`)\n }\n if (state.exitStatus !== null) {\n return { exitCode: state.exitStatus.exitCode, signal: state.exitStatus.signal }\n }\n return new Promise((resolve) => {\n state.process.on('exit', (code, signal) => {\n resolve({ exitCode: code, signal })\n })\n })\n },\n\n async killTerminal(params) {\n const state = self.terminals.get(params.terminalId)\n if (!state) {\n throw new Error(`Terminal not found: ${params.terminalId}`)\n }\n state.process.kill('SIGTERM')\n return {}\n },\n\n async releaseTerminal(params) {\n const state = self.terminals.get(params.terminalId)\n if (!state) {\n return\n }\n state.process.kill('SIGKILL')\n self.terminals.delete(params.terminalId)\n },\n }\n }\n\n async prompt(text: string): Promise<PromptResponse> {\n return this.connection.prompt({\n sessionId: this.sessionId,\n prompt: [{ type: 'text', text }],\n })\n }\n\n async cancel(): Promise<void> {\n await this.connection.cancel({ sessionId: this.sessionId })\n }\n\n async destroy(): Promise<void> {\n // Cleanup terminals\n for (const [, t] of this.terminals) {\n t.process.kill('SIGKILL')\n }\n this.terminals.clear()\n\n // Kill agent subprocess\n this.child.kill('SIGTERM')\n setTimeout(() => {\n if (!this.child.killed) this.child.kill('SIGKILL')\n }, 10_000)\n }\n}\n","import type { Config } from './config.js'\nimport type { AgentDefinition } from './types.js'\nimport { AgentInstance } from './agent-instance.js'\n\nexport class AgentManager {\n constructor(private config: Config) {}\n\n getAvailableAgents(): AgentDefinition[] {\n return Object.entries(this.config.agents).map(([name, cfg]) => ({\n name,\n command: cfg.command,\n args: cfg.args,\n workingDirectory: cfg.workingDirectory,\n env: cfg.env,\n }))\n }\n\n getAgent(name: string): AgentDefinition | undefined {\n const cfg = this.config.agents[name]\n if (!cfg) return undefined\n return { name, ...cfg }\n }\n\n async spawn(agentName: string, workingDirectory: string): Promise<AgentInstance> {\n const agentDef = this.getAgent(agentName)\n if (!agentDef) throw new Error(`Agent \"${agentName}\" not found in config`)\n return AgentInstance.spawn(agentDef, workingDirectory)\n }\n}\n","import { nanoid } from 'nanoid'\nimport type { AgentInstance } from './agent-instance.js'\nimport type { ChannelAdapter } from './channel.js'\nimport type { SessionStatus } from './types.js'\nimport { log } from './log.js'\n\nexport class Session {\n id: string\n channelId: string\n threadId: string = ''\n agentName: string\n workingDirectory: string\n agentInstance: AgentInstance\n status: SessionStatus = 'initializing'\n name?: string\n promptQueue: string[] = []\n promptRunning: boolean = false\n createdAt: Date = new Date()\n adapter?: ChannelAdapter // Set by wireSessionEvents for renaming\n pendingPermission?: { requestId: string; resolve: (optionId: string) => void }\n\n constructor(opts: {\n id?: string\n channelId: string\n agentName: string\n workingDirectory: string\n agentInstance: AgentInstance\n }) {\n this.id = opts.id || nanoid(12)\n this.channelId = opts.channelId\n this.agentName = opts.agentName\n this.workingDirectory = opts.workingDirectory\n this.agentInstance = opts.agentInstance\n }\n\n async enqueuePrompt(text: string): Promise<void> {\n if (this.promptRunning) {\n this.promptQueue.push(text)\n log.debug(`Prompt queued for session ${this.id} (${this.promptQueue.length} in queue)`)\n return\n }\n await this.runPrompt(text)\n }\n\n private async runPrompt(text: string): Promise<void> {\n this.promptRunning = true\n this.status = 'active'\n\n try {\n await this.agentInstance.prompt(text)\n\n // Auto-name after first user prompt\n if (!this.name) {\n await this.autoName()\n }\n } catch (err) {\n this.status = 'error'\n log.error(`Prompt failed for session ${this.id}:`, err)\n } finally {\n this.promptRunning = false\n\n // Process next queued prompt\n if (this.promptQueue.length > 0) {\n const next = this.promptQueue.shift()!\n await this.runPrompt(next)\n }\n }\n }\n\n // NOTE: This injects a summary prompt into the agent's conversation history.\n // Known Phase 1 limitation — the agent sees this prompt in its context.\n private async autoName(): Promise<void> {\n let title = ''\n const prevHandler = this.agentInstance.onSessionUpdate\n this.agentInstance.onSessionUpdate = (event) => {\n if (event.type === 'text') title += event.content\n }\n\n try {\n await this.agentInstance.prompt(\n 'Summarize this conversation in max 5 words for a topic title. Reply ONLY with the title, nothing else.'\n )\n this.name = title.trim().slice(0, 50)\n\n // Rename the topic on the channel\n if (this.adapter && this.name) {\n await this.adapter.renameSessionThread(this.id, this.name)\n }\n } catch {\n this.name = `Session ${this.id.slice(0, 6)}`\n } finally {\n this.agentInstance.onSessionUpdate = prevHandler\n }\n }\n\n async cancel(): Promise<void> {\n this.status = 'cancelled'\n await this.agentInstance.cancel()\n }\n\n async destroy(): Promise<void> {\n await this.agentInstance.destroy()\n }\n}\n","import type { AgentManager } from './agent-manager.js'\nimport { Session } from './session.js'\n\nexport class SessionManager {\n private sessions: Map<string, Session> = new Map()\n\n async createSession(\n channelId: string,\n agentName: string,\n workingDirectory: string,\n agentManager: AgentManager,\n ): Promise<Session> {\n const agentInstance = await agentManager.spawn(agentName, workingDirectory)\n const session = new Session({ channelId, agentName, workingDirectory, agentInstance })\n this.sessions.set(session.id, session)\n return session\n }\n\n getSession(sessionId: string): Session | undefined {\n return this.sessions.get(sessionId)\n }\n\n getSessionByThread(channelId: string, threadId: string): Session | undefined {\n for (const session of this.sessions.values()) {\n if (session.channelId === channelId && session.threadId === threadId) {\n return session\n }\n }\n return undefined\n }\n\n async cancelSession(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId)\n if (session) await session.cancel()\n }\n\n listSessions(channelId?: string): Session[] {\n const all = Array.from(this.sessions.values())\n if (channelId) return all.filter(s => s.channelId === channelId)\n return all\n }\n\n async destroyAll(): Promise<void> {\n for (const session of this.sessions.values()) {\n await session.destroy()\n }\n this.sessions.clear()\n }\n}\n","import type { ChannelAdapter } from './channel.js'\nimport type { NotificationMessage } from './types.js'\n\nexport class NotificationManager {\n constructor(private adapters: Map<string, ChannelAdapter>) {}\n\n async notify(channelId: string, notification: NotificationMessage): Promise<void> {\n const adapter = this.adapters.get(channelId)\n if (adapter) {\n await adapter.sendNotification(notification)\n }\n }\n\n async notifyAll(notification: NotificationMessage): Promise<void> {\n for (const adapter of this.adapters.values()) {\n await adapter.sendNotification(notification)\n }\n }\n}\n","import { ConfigManager } from './config.js'\nimport { AgentManager } from './agent-manager.js'\nimport { SessionManager } from './session-manager.js'\nimport { NotificationManager } from './notification.js'\nimport { ChannelAdapter } from './channel.js'\nimport { Session } from './session.js'\nimport type { IncomingMessage, AgentEvent, OutgoingMessage, PermissionRequest } from './types.js'\nimport { log } from './log.js'\n\nexport class OpenACPCore {\n configManager: ConfigManager\n agentManager: AgentManager\n sessionManager: SessionManager\n notificationManager: NotificationManager\n adapters: Map<string, ChannelAdapter> = new Map()\n\n constructor(configManager: ConfigManager) {\n this.configManager = configManager\n const config = configManager.get()\n this.agentManager = new AgentManager(config)\n this.sessionManager = new SessionManager()\n this.notificationManager = new NotificationManager(this.adapters)\n }\n\n registerAdapter(name: string, adapter: ChannelAdapter): void {\n this.adapters.set(name, adapter)\n }\n\n async start(): Promise<void> {\n for (const adapter of this.adapters.values()) {\n await adapter.start()\n }\n }\n\n async stop(): Promise<void> {\n // 1. Notify users\n try {\n await this.notificationManager.notifyAll({\n sessionId: 'system',\n type: 'error',\n summary: 'OpenACP is shutting down',\n })\n } catch { /* best effort */ }\n\n // 2. Destroy all sessions\n await this.sessionManager.destroyAll()\n\n // 3. Stop adapters\n for (const adapter of this.adapters.values()) {\n await adapter.stop()\n }\n }\n\n // --- Message Routing ---\n\n async handleMessage(message: IncomingMessage): Promise<void> {\n const config = this.configManager.get()\n\n // Security: check allowed user IDs\n if (config.security.allowedUserIds.length > 0) {\n if (!config.security.allowedUserIds.includes(message.userId)) return\n }\n\n // Check concurrent session limit\n const activeSessions = this.sessionManager.listSessions()\n .filter(s => s.status === 'active' || s.status === 'initializing')\n if (activeSessions.length >= config.security.maxConcurrentSessions) {\n const adapter = this.adapters.get(message.channelId)\n if (adapter) {\n await adapter.sendMessage('system', {\n type: 'error',\n text: `Max concurrent sessions (${config.security.maxConcurrentSessions}) reached. Cancel a session first.`,\n })\n }\n return\n }\n\n // Find session by thread\n const session = this.sessionManager.getSessionByThread(message.channelId, message.threadId)\n if (!session) return\n\n // Forward to session\n await session.enqueuePrompt(message.text)\n }\n\n async handleNewSession(\n channelId: string,\n agentName?: string,\n workspacePath?: string,\n ): Promise<Session> {\n const config = this.configManager.get()\n const resolvedAgent = agentName || config.defaultAgent\n const resolvedWorkspace = this.configManager.resolveWorkspace(\n workspacePath || config.agents[resolvedAgent]?.workingDirectory\n )\n\n const session = await this.sessionManager.createSession(\n channelId, resolvedAgent, resolvedWorkspace, this.agentManager\n )\n\n // Wire events\n const adapter = this.adapters.get(channelId)\n if (adapter) {\n this.wireSessionEvents(session, adapter)\n }\n\n return session\n }\n\n async handleNewChat(\n channelId: string,\n currentThreadId: string,\n ): Promise<Session | null> {\n const currentSession = this.sessionManager.getSessionByThread(channelId, currentThreadId)\n if (!currentSession) return null\n\n return this.handleNewSession(\n channelId,\n currentSession.agentName,\n currentSession.workingDirectory,\n )\n }\n\n // --- Event Wiring ---\n\n private toOutgoingMessage(event: AgentEvent): OutgoingMessage {\n switch (event.type) {\n case 'text':\n return { type: 'text', text: event.content }\n case 'thought':\n return { type: 'thought', text: event.content }\n case 'tool_call':\n return { type: 'tool_call', text: event.name, metadata: { id: event.id, kind: event.kind, status: event.status, content: event.content, locations: event.locations } }\n case 'tool_update':\n return { type: 'tool_update', text: '', metadata: { id: event.id, status: event.status, content: event.content } }\n case 'plan':\n return { type: 'plan', text: '', metadata: { entries: event.entries } }\n case 'usage':\n return { type: 'usage', text: '', metadata: { tokensUsed: event.tokensUsed, contextSize: event.contextSize, cost: event.cost } }\n case 'commands_update':\n // Log but don't surface to user (Phase 3 feature)\n log.debug('Commands update:', event.commands)\n return { type: 'text', text: '' } // no-op for now\n default:\n return { type: 'text', text: '' }\n }\n }\n\n // Public — adapters call this for assistant session wiring\n wireSessionEvents(session: Session, adapter: ChannelAdapter): void {\n // Set adapter reference for autoName → renameSessionThread\n session.adapter = adapter\n\n session.agentInstance.onSessionUpdate = (event: AgentEvent) => {\n switch (event.type) {\n case 'text':\n case 'thought':\n case 'tool_call':\n case 'tool_update':\n case 'plan':\n case 'usage':\n adapter.sendMessage(session.id, this.toOutgoingMessage(event))\n break\n\n case 'session_end':\n session.status = 'finished'\n adapter.sendMessage(session.id, { type: 'session_end', text: `Done (${event.reason})` })\n this.notificationManager.notify(session.channelId, {\n sessionId: session.id,\n sessionName: session.name,\n type: 'completed',\n summary: `Session \"${session.name || session.id}\" completed`,\n })\n break\n\n case 'error':\n adapter.sendMessage(session.id, { type: 'error', text: event.message })\n this.notificationManager.notify(session.channelId, {\n sessionId: session.id,\n sessionName: session.name,\n type: 'error',\n summary: event.message,\n })\n break\n\n case 'commands_update':\n log.debug('Commands available:', event.commands)\n break\n }\n }\n\n session.agentInstance.onPermissionRequest = async (request: PermissionRequest) => {\n // Set pending BEFORE sending UI to avoid race condition\n const promise = new Promise<string>((resolve) => {\n session.pendingPermission = { requestId: request.id, resolve }\n })\n\n // Send permission UI to session topic (notification is sent by adapter)\n await adapter.sendPermissionRequest(session.id, request)\n\n // Wait for user response — adapter resolves this promise\n return promise\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-M5ZYTPZY.js
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
// packages/core/src/log.ts
|
|
2
|
-
var log = {
|
|
3
|
-
info: (...args) => console.log((/* @__PURE__ */ new Date()).toISOString(), "[INFO]", ...args),
|
|
4
|
-
warn: (...args) => console.warn((/* @__PURE__ */ new Date()).toISOString(), "[WARN]", ...args),
|
|
5
|
-
error: (...args) => console.error((/* @__PURE__ */ new Date()).toISOString(), "[ERROR]", ...args),
|
|
6
|
-
debug: (...args) => {
|
|
7
|
-
if (process.env.OPENACP_DEBUG) console.log((/* @__PURE__ */ new Date()).toISOString(), "[DEBUG]", ...args);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
// packages/core/src/config.ts
|
|
12
|
-
import { z } from "zod";
|
|
13
|
-
import * as fs from "fs";
|
|
14
|
-
import * as path from "path";
|
|
15
|
-
import * as os from "os";
|
|
16
|
-
var BaseChannelSchema = z.object({
|
|
17
|
-
enabled: z.boolean().default(false),
|
|
18
|
-
adapter: z.string().optional()
|
|
19
|
-
// package name for plugin adapters
|
|
20
|
-
}).passthrough();
|
|
21
|
-
var PLUGINS_DIR = path.join(os.homedir(), ".openacp", "plugins");
|
|
22
|
-
var AgentSchema = z.object({
|
|
23
|
-
command: z.string(),
|
|
24
|
-
args: z.array(z.string()).default([]),
|
|
25
|
-
workingDirectory: z.string().optional(),
|
|
26
|
-
env: z.record(z.string(), z.string()).default({})
|
|
27
|
-
});
|
|
28
|
-
var ConfigSchema = z.object({
|
|
29
|
-
channels: z.record(z.string(), BaseChannelSchema),
|
|
30
|
-
agents: z.record(z.string(), AgentSchema),
|
|
31
|
-
defaultAgent: z.string(),
|
|
32
|
-
workspace: z.object({
|
|
33
|
-
baseDir: z.string().default("~/openacp-workspace")
|
|
34
|
-
}).default({}),
|
|
35
|
-
security: z.object({
|
|
36
|
-
allowedUserIds: z.array(z.string()).default([]),
|
|
37
|
-
maxConcurrentSessions: z.number().default(5),
|
|
38
|
-
sessionTimeoutMinutes: z.number().default(60)
|
|
39
|
-
}).default({})
|
|
40
|
-
});
|
|
41
|
-
function expandHome(p) {
|
|
42
|
-
if (p.startsWith("~")) {
|
|
43
|
-
return path.join(os.homedir(), p.slice(1));
|
|
44
|
-
}
|
|
45
|
-
return p;
|
|
46
|
-
}
|
|
47
|
-
var DEFAULT_CONFIG = {
|
|
48
|
-
channels: {
|
|
49
|
-
telegram: {
|
|
50
|
-
enabled: false,
|
|
51
|
-
botToken: "YOUR_BOT_TOKEN_HERE",
|
|
52
|
-
chatId: 0,
|
|
53
|
-
notificationTopicId: null,
|
|
54
|
-
assistantTopicId: null
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
agents: {
|
|
58
|
-
claude: { command: "claude-agent-acp", args: [], env: {} },
|
|
59
|
-
codex: { command: "codex", args: ["--acp"], env: {} }
|
|
60
|
-
},
|
|
61
|
-
defaultAgent: "claude",
|
|
62
|
-
workspace: { baseDir: "~/openacp-workspace" },
|
|
63
|
-
security: { allowedUserIds: [], maxConcurrentSessions: 5, sessionTimeoutMinutes: 60 }
|
|
64
|
-
};
|
|
65
|
-
var ConfigManager = class {
|
|
66
|
-
config;
|
|
67
|
-
configPath;
|
|
68
|
-
constructor() {
|
|
69
|
-
this.configPath = process.env.OPENACP_CONFIG_PATH || expandHome("~/.openacp/config.json");
|
|
70
|
-
}
|
|
71
|
-
async load() {
|
|
72
|
-
const dir = path.dirname(this.configPath);
|
|
73
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
74
|
-
if (!fs.existsSync(this.configPath)) {
|
|
75
|
-
fs.writeFileSync(this.configPath, JSON.stringify(DEFAULT_CONFIG, null, 2));
|
|
76
|
-
log.info(`Config created at ${this.configPath}`);
|
|
77
|
-
log.info("Please edit it with your Telegram bot token and chat ID, then restart.");
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
80
|
-
const raw = JSON.parse(fs.readFileSync(this.configPath, "utf-8"));
|
|
81
|
-
this.applyEnvOverrides(raw);
|
|
82
|
-
const result = ConfigSchema.safeParse(raw);
|
|
83
|
-
if (!result.success) {
|
|
84
|
-
log.error("Config validation failed:");
|
|
85
|
-
for (const issue of result.error.issues) {
|
|
86
|
-
log.error(` ${issue.path.join(".")}: ${issue.message}`);
|
|
87
|
-
}
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
|
-
this.config = result.data;
|
|
91
|
-
}
|
|
92
|
-
get() {
|
|
93
|
-
return this.config;
|
|
94
|
-
}
|
|
95
|
-
async save(updates) {
|
|
96
|
-
const raw = JSON.parse(fs.readFileSync(this.configPath, "utf-8"));
|
|
97
|
-
this.deepMerge(raw, updates);
|
|
98
|
-
fs.writeFileSync(this.configPath, JSON.stringify(raw, null, 2));
|
|
99
|
-
const result = ConfigSchema.safeParse(raw);
|
|
100
|
-
if (result.success) {
|
|
101
|
-
this.config = result.data;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
resolveWorkspace(input) {
|
|
105
|
-
if (!input) {
|
|
106
|
-
const resolved2 = expandHome(this.config.workspace.baseDir);
|
|
107
|
-
fs.mkdirSync(resolved2, { recursive: true });
|
|
108
|
-
return resolved2;
|
|
109
|
-
}
|
|
110
|
-
if (input.startsWith("/") || input.startsWith("~")) {
|
|
111
|
-
const resolved2 = expandHome(input);
|
|
112
|
-
fs.mkdirSync(resolved2, { recursive: true });
|
|
113
|
-
return resolved2;
|
|
114
|
-
}
|
|
115
|
-
const name = input.toLowerCase();
|
|
116
|
-
const resolved = path.join(expandHome(this.config.workspace.baseDir), name);
|
|
117
|
-
fs.mkdirSync(resolved, { recursive: true });
|
|
118
|
-
return resolved;
|
|
119
|
-
}
|
|
120
|
-
async exists() {
|
|
121
|
-
return fs.existsSync(this.configPath);
|
|
122
|
-
}
|
|
123
|
-
getConfigPath() {
|
|
124
|
-
return this.configPath;
|
|
125
|
-
}
|
|
126
|
-
async writeNew(config) {
|
|
127
|
-
const dir = path.dirname(this.configPath);
|
|
128
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
129
|
-
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));
|
|
130
|
-
}
|
|
131
|
-
applyEnvOverrides(raw) {
|
|
132
|
-
const overrides = [
|
|
133
|
-
["OPENACP_TELEGRAM_BOT_TOKEN", ["channels", "telegram", "botToken"]],
|
|
134
|
-
["OPENACP_TELEGRAM_CHAT_ID", ["channels", "telegram", "chatId"]],
|
|
135
|
-
["OPENACP_DEFAULT_AGENT", ["defaultAgent"]]
|
|
136
|
-
];
|
|
137
|
-
for (const [envVar, configPath] of overrides) {
|
|
138
|
-
const value = process.env[envVar];
|
|
139
|
-
if (value !== void 0) {
|
|
140
|
-
let target = raw;
|
|
141
|
-
for (let i = 0; i < configPath.length - 1; i++) {
|
|
142
|
-
if (!target[configPath[i]]) target[configPath[i]] = {};
|
|
143
|
-
target = target[configPath[i]];
|
|
144
|
-
}
|
|
145
|
-
const key = configPath[configPath.length - 1];
|
|
146
|
-
target[key] = key === "chatId" ? Number(value) : value;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
deepMerge(target, source) {
|
|
151
|
-
for (const key of Object.keys(source)) {
|
|
152
|
-
if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
|
|
153
|
-
if (!target[key]) target[key] = {};
|
|
154
|
-
this.deepMerge(target[key], source[key]);
|
|
155
|
-
} else {
|
|
156
|
-
target[key] = source[key];
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
// packages/core/src/plugin-manager.ts
|
|
163
|
-
import { execSync } from "child_process";
|
|
164
|
-
import * as fs2 from "fs";
|
|
165
|
-
import * as path2 from "path";
|
|
166
|
-
import { createRequire } from "module";
|
|
167
|
-
function ensurePluginsDir() {
|
|
168
|
-
fs2.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
169
|
-
const pkgPath = path2.join(PLUGINS_DIR, "package.json");
|
|
170
|
-
if (!fs2.existsSync(pkgPath)) {
|
|
171
|
-
fs2.writeFileSync(pkgPath, JSON.stringify({ name: "openacp-plugins", private: true, dependencies: {} }, null, 2));
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function installPlugin(packageName) {
|
|
175
|
-
ensurePluginsDir();
|
|
176
|
-
log.info(`Installing ${packageName}...`);
|
|
177
|
-
execSync(`npm install ${packageName} --prefix "${PLUGINS_DIR}"`, { stdio: "inherit" });
|
|
178
|
-
log.info(`${packageName} installed successfully.`);
|
|
179
|
-
}
|
|
180
|
-
function uninstallPlugin(packageName) {
|
|
181
|
-
ensurePluginsDir();
|
|
182
|
-
log.info(`Uninstalling ${packageName}...`);
|
|
183
|
-
execSync(`npm uninstall ${packageName} --prefix "${PLUGINS_DIR}"`, { stdio: "inherit" });
|
|
184
|
-
log.info(`${packageName} uninstalled.`);
|
|
185
|
-
}
|
|
186
|
-
function listPlugins() {
|
|
187
|
-
const pkgPath = path2.join(PLUGINS_DIR, "package.json");
|
|
188
|
-
if (!fs2.existsSync(pkgPath)) return {};
|
|
189
|
-
const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
|
|
190
|
-
return pkg.dependencies || {};
|
|
191
|
-
}
|
|
192
|
-
async function loadAdapterFactory(packageName) {
|
|
193
|
-
try {
|
|
194
|
-
const require2 = createRequire(path2.join(PLUGINS_DIR, "package.json"));
|
|
195
|
-
const resolved = require2.resolve(packageName);
|
|
196
|
-
const mod = await import(resolved);
|
|
197
|
-
const factory = mod.adapterFactory || mod.default;
|
|
198
|
-
if (!factory || typeof factory.createAdapter !== "function") {
|
|
199
|
-
log.error(`Plugin ${packageName} does not export a valid AdapterFactory (needs .createAdapter())`);
|
|
200
|
-
return null;
|
|
201
|
-
}
|
|
202
|
-
return factory;
|
|
203
|
-
} catch (err) {
|
|
204
|
-
log.error(`Failed to load plugin ${packageName}:`, err);
|
|
205
|
-
log.error(`Run: npx openacp install ${packageName}`);
|
|
206
|
-
return null;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export {
|
|
211
|
-
log,
|
|
212
|
-
PLUGINS_DIR,
|
|
213
|
-
expandHome,
|
|
214
|
-
ConfigManager,
|
|
215
|
-
installPlugin,
|
|
216
|
-
uninstallPlugin,
|
|
217
|
-
listPlugins,
|
|
218
|
-
loadAdapterFactory
|
|
219
|
-
};
|
|
220
|
-
//# sourceMappingURL=chunk-M5ZYTPZY.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../packages/core/src/log.ts","../../packages/core/src/config.ts","../../packages/core/src/plugin-manager.ts"],"sourcesContent":["export const log = {\n info: (...args: unknown[]) => console.log(new Date().toISOString(), '[INFO]', ...args),\n warn: (...args: unknown[]) => console.warn(new Date().toISOString(), '[WARN]', ...args),\n error: (...args: unknown[]) => console.error(new Date().toISOString(), '[ERROR]', ...args),\n debug: (...args: unknown[]) => {\n if (process.env.OPENACP_DEBUG) console.log(new Date().toISOString(), '[DEBUG]', ...args)\n },\n}\n","import { z } from 'zod'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport { log } from './log.js'\n\nconst BaseChannelSchema = z.object({\n enabled: z.boolean().default(false),\n adapter: z.string().optional(), // package name for plugin adapters\n}).passthrough()\n\nexport const PLUGINS_DIR = path.join(os.homedir(), '.openacp', 'plugins')\n\nconst AgentSchema = z.object({\n command: z.string(),\n args: z.array(z.string()).default([]),\n workingDirectory: z.string().optional(),\n env: z.record(z.string(), z.string()).default({}),\n})\n\nexport const ConfigSchema = z.object({\n channels: z.record(z.string(), BaseChannelSchema),\n agents: z.record(z.string(), AgentSchema),\n defaultAgent: z.string(),\n workspace: z.object({\n baseDir: z.string().default('~/openacp-workspace'),\n }).default({}),\n security: z.object({\n allowedUserIds: z.array(z.string()).default([]),\n maxConcurrentSessions: z.number().default(5),\n sessionTimeoutMinutes: z.number().default(60),\n }).default({}),\n})\n\nexport type Config = z.infer<typeof ConfigSchema>\n\nexport function expandHome(p: string): string {\n if (p.startsWith('~')) {\n return path.join(os.homedir(), p.slice(1))\n }\n return p\n}\n\nconst DEFAULT_CONFIG = {\n channels: {\n telegram: {\n enabled: false,\n botToken: \"YOUR_BOT_TOKEN_HERE\",\n chatId: 0,\n notificationTopicId: null,\n assistantTopicId: null\n }\n },\n agents: {\n claude: { command: \"claude-agent-acp\", args: [], env: {} },\n codex: { command: \"codex\", args: [\"--acp\"], env: {} }\n },\n defaultAgent: \"claude\",\n workspace: { baseDir: \"~/openacp-workspace\" },\n security: { allowedUserIds: [], maxConcurrentSessions: 5, sessionTimeoutMinutes: 60 }\n}\n\nexport class ConfigManager {\n private config!: Config\n private configPath: string\n\n constructor() {\n this.configPath = process.env.OPENACP_CONFIG_PATH || expandHome('~/.openacp/config.json')\n }\n\n async load(): Promise<void> {\n // 1. Ensure directory exists\n const dir = path.dirname(this.configPath)\n fs.mkdirSync(dir, { recursive: true })\n\n // 2. If config file doesn't exist, create default\n if (!fs.existsSync(this.configPath)) {\n fs.writeFileSync(this.configPath, JSON.stringify(DEFAULT_CONFIG, null, 2))\n log.info(`Config created at ${this.configPath}`)\n log.info('Please edit it with your Telegram bot token and chat ID, then restart.')\n process.exit(1)\n }\n\n // 3. Read and parse\n const raw = JSON.parse(fs.readFileSync(this.configPath, 'utf-8'))\n\n // 4. Apply env var overrides\n this.applyEnvOverrides(raw)\n\n // 5. Validate with Zod\n const result = ConfigSchema.safeParse(raw)\n if (!result.success) {\n log.error('Config validation failed:')\n for (const issue of result.error.issues) {\n log.error(` ${issue.path.join('.')}: ${issue.message}`)\n }\n process.exit(1)\n }\n this.config = result.data\n }\n\n get(): Config {\n return this.config\n }\n\n async save(updates: Record<string, unknown>): Promise<void> {\n // Read current file, merge updates, write back\n const raw = JSON.parse(fs.readFileSync(this.configPath, 'utf-8'))\n this.deepMerge(raw, updates)\n fs.writeFileSync(this.configPath, JSON.stringify(raw, null, 2))\n // Re-validate and update in-memory config\n const result = ConfigSchema.safeParse(raw)\n if (result.success) {\n this.config = result.data\n }\n }\n\n resolveWorkspace(input?: string): string {\n if (!input) {\n const resolved = expandHome(this.config.workspace.baseDir)\n fs.mkdirSync(resolved, { recursive: true })\n return resolved\n }\n if (input.startsWith('/') || input.startsWith('~')) {\n const resolved = expandHome(input)\n fs.mkdirSync(resolved, { recursive: true })\n return resolved\n }\n // Named workspace → lowercase, under baseDir\n const name = input.toLowerCase()\n const resolved = path.join(expandHome(this.config.workspace.baseDir), name)\n fs.mkdirSync(resolved, { recursive: true })\n return resolved\n }\n\n async exists(): Promise<boolean> {\n return fs.existsSync(this.configPath)\n }\n\n getConfigPath(): string {\n return this.configPath\n }\n\n async writeNew(config: Config): Promise<void> {\n const dir = path.dirname(this.configPath)\n fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2))\n }\n\n private applyEnvOverrides(raw: Record<string, unknown>): void {\n const overrides: [string, string[]][] = [\n ['OPENACP_TELEGRAM_BOT_TOKEN', ['channels', 'telegram', 'botToken']],\n ['OPENACP_TELEGRAM_CHAT_ID', ['channels', 'telegram', 'chatId']],\n ['OPENACP_DEFAULT_AGENT', ['defaultAgent']],\n ]\n for (const [envVar, configPath] of overrides) {\n const value = process.env[envVar]\n if (value !== undefined) {\n let target = raw as Record<string, any>\n for (let i = 0; i < configPath.length - 1; i++) {\n if (!target[configPath[i]]) target[configPath[i]] = {}\n target = target[configPath[i]]\n }\n const key = configPath[configPath.length - 1]\n // Convert chatId to number\n target[key] = key === 'chatId' ? Number(value) : value\n }\n }\n }\n\n private deepMerge(target: Record<string, any>, source: Record<string, any>): void {\n for (const key of Object.keys(source)) {\n if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {\n if (!target[key]) target[key] = {}\n this.deepMerge(target[key], source[key])\n } else {\n target[key] = source[key]\n }\n }\n }\n}\n","import { execSync } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { createRequire } from 'node:module'\nimport { PLUGINS_DIR } from './config.js'\nimport { log } from './log.js'\nimport type { ChannelAdapter } from './channel.js'\n\nexport interface AdapterFactory {\n name: string\n createAdapter(core: any, config: any): ChannelAdapter\n}\n\nfunction ensurePluginsDir(): void {\n fs.mkdirSync(PLUGINS_DIR, { recursive: true })\n const pkgPath = path.join(PLUGINS_DIR, 'package.json')\n if (!fs.existsSync(pkgPath)) {\n fs.writeFileSync(pkgPath, JSON.stringify({ name: 'openacp-plugins', private: true, dependencies: {} }, null, 2))\n }\n}\n\nexport function installPlugin(packageName: string): void {\n ensurePluginsDir()\n log.info(`Installing ${packageName}...`)\n execSync(`npm install ${packageName} --prefix \"${PLUGINS_DIR}\"`, { stdio: 'inherit' })\n log.info(`${packageName} installed successfully.`)\n}\n\nexport function uninstallPlugin(packageName: string): void {\n ensurePluginsDir()\n log.info(`Uninstalling ${packageName}...`)\n execSync(`npm uninstall ${packageName} --prefix \"${PLUGINS_DIR}\"`, { stdio: 'inherit' })\n log.info(`${packageName} uninstalled.`)\n}\n\nexport function listPlugins(): Record<string, string> {\n const pkgPath = path.join(PLUGINS_DIR, 'package.json')\n if (!fs.existsSync(pkgPath)) return {}\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))\n return pkg.dependencies || {}\n}\n\nexport async function loadAdapterFactory(packageName: string): Promise<AdapterFactory | null> {\n try {\n const require = createRequire(path.join(PLUGINS_DIR, 'package.json'))\n const resolved = require.resolve(packageName)\n const mod = await import(resolved)\n\n // Plugin must export `adapterFactory` or default export conforming to AdapterFactory\n const factory: AdapterFactory | undefined = mod.adapterFactory || mod.default\n if (!factory || typeof factory.createAdapter !== 'function') {\n log.error(`Plugin ${packageName} does not export a valid AdapterFactory (needs .createAdapter())`)\n return null\n }\n return factory\n } catch (err) {\n log.error(`Failed to load plugin ${packageName}:`, err)\n log.error(`Run: npx openacp install ${packageName}`)\n return null\n }\n}\n"],"mappings":"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","names":["resolved","fs","path","require"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../packages/core/src/main.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ConfigManager } from './config.js'\nimport { OpenACPCore } from './core.js'\nimport { loadAdapterFactory } from './plugin-manager.js'\nimport { log } from './log.js'\n\nlet shuttingDown = false\n\nexport async function startServer() {\n // 1. Check config exists, run setup if not\n const configManager = new ConfigManager()\n const configExists = await configManager.exists()\n\n if (!configExists) {\n const { runSetup } = await import('./setup.js')\n const shouldStart = await runSetup(configManager)\n if (!shouldStart) process.exit(0)\n }\n\n // 2. Load config (validates with Zod)\n await configManager.load()\n const config = configManager.get()\n log.info('Config loaded from', configManager.getConfigPath())\n\n // 3. Create core\n const core = new OpenACPCore(configManager)\n\n // 4. Register adapters from config\n for (const [channelName, channelConfig] of Object.entries(config.channels)) {\n if (!channelConfig.enabled) continue\n\n if (channelName === 'telegram') {\n // Built-in adapter — try bundled import first, fall back to relative path for dev\n let TelegramAdapter: any\n try {\n // @ts-ignore — optional peer dependency, may not be installed\n const mod = await import('@openacp/adapter-telegram')\n TelegramAdapter = mod.TelegramAdapter\n } catch {\n // Dev mode: resolve from workspace via relative path\n const adapterPath = new URL('../../adapters/telegram/dist/index.js', import.meta.url).pathname\n const mod = await import(adapterPath)\n TelegramAdapter = mod.TelegramAdapter\n }\n core.registerAdapter('telegram', new TelegramAdapter(core, channelConfig))\n log.info('Telegram adapter registered (built-in)')\n } else if (channelConfig.adapter) {\n // Plugin adapter\n const factory = await loadAdapterFactory(channelConfig.adapter)\n if (factory) {\n const adapter = factory.createAdapter(core, channelConfig)\n core.registerAdapter(channelName, adapter)\n log.info(`${channelName} adapter registered (plugin: ${channelConfig.adapter})`)\n } else {\n log.error(`Skipping channel \"${channelName}\" — adapter \"${channelConfig.adapter}\" failed to load`)\n }\n } else {\n log.error(`Channel \"${channelName}\" has no built-in adapter. Set \"adapter\" field to a plugin package.`)\n }\n }\n\n if (core.adapters.size === 0) {\n log.error('No channels enabled. Enable at least one channel in config.')\n process.exit(1)\n }\n\n // 5. Start\n await core.start()\n\n // 6. Log ready\n const agents = Object.keys(config.agents).join(', ')\n log.info(`OpenACP started. Agents: ${agents}`)\n log.info('Press Ctrl+C to stop.')\n\n // 7. Graceful shutdown\n const shutdown = async (signal: string) => {\n if (shuttingDown) return\n shuttingDown = true\n log.info(`${signal} received. Shutting down...`)\n\n try {\n await core.stop()\n } catch (err) {\n log.error('Error during shutdown:', err)\n }\n\n process.exit(0)\n }\n\n process.on('SIGINT', () => shutdown('SIGINT'))\n process.on('SIGTERM', () => shutdown('SIGTERM'))\n\n process.on('uncaughtException', (err) => {\n log.error('Uncaught exception:', err)\n })\n\n process.on('unhandledRejection', (err) => {\n log.error('Unhandled rejection:', err)\n })\n}\n\n// Direct execution for dev (node packages/core/dist/main.js)\nconst isDirectExecution = process.argv[1]?.endsWith('main.js')\nif (isDirectExecution) {\n startServer().catch((err) => {\n log.error('Fatal:', err)\n process.exit(1)\n })\n}\n"],"mappings":";;;;;;;;;;;AAOA,IAAI,eAAe;AAEnB,eAAsB,cAAc;AAElC,QAAM,gBAAgB,IAAI,cAAc;AACxC,QAAM,eAAe,MAAM,cAAc,OAAO;AAEhD,MAAI,CAAC,cAAc;AACjB,UAAM,EAAE,SAAS,IAAI,MAAM,OAAO,sBAAY;AAC9C,UAAM,cAAc,MAAM,SAAS,aAAa;AAChD,QAAI,CAAC,YAAa,SAAQ,KAAK,CAAC;AAAA,EAClC;AAGA,QAAM,cAAc,KAAK;AACzB,QAAM,SAAS,cAAc,IAAI;AACjC,MAAI,KAAK,sBAAsB,cAAc,cAAc,CAAC;AAG5D,QAAM,OAAO,IAAI,YAAY,aAAa;AAG1C,aAAW,CAAC,aAAa,aAAa,KAAK,OAAO,QAAQ,OAAO,QAAQ,GAAG;AAC1E,QAAI,CAAC,cAAc,QAAS;AAE5B,QAAI,gBAAgB,YAAY;AAE9B,UAAI;AACJ,UAAI;AAEF,cAAM,MAAM,MAAM,OAAO,2BAA2B;AACpD,0BAAkB,IAAI;AAAA,MACxB,QAAQ;AAEN,cAAM,cAAc,IAAI,IAAI,yCAAyC,YAAY,GAAG,EAAE;AACtF,cAAM,MAAM,MAAM,OAAO;AACzB,0BAAkB,IAAI;AAAA,MACxB;AACA,WAAK,gBAAgB,YAAY,IAAI,gBAAgB,MAAM,aAAa,CAAC;AACzE,UAAI,KAAK,wCAAwC;AAAA,IACnD,WAAW,cAAc,SAAS;AAEhC,YAAM,UAAU,MAAM,mBAAmB,cAAc,OAAO;AAC9D,UAAI,SAAS;AACX,cAAM,UAAU,QAAQ,cAAc,MAAM,aAAa;AACzD,aAAK,gBAAgB,aAAa,OAAO;AACzC,YAAI,KAAK,GAAG,WAAW,gCAAgC,cAAc,OAAO,GAAG;AAAA,MACjF,OAAO;AACL,YAAI,MAAM,qBAAqB,WAAW,qBAAgB,cAAc,OAAO,kBAAkB;AAAA,MACnG;AAAA,IACF,OAAO;AACL,UAAI,MAAM,YAAY,WAAW,qEAAqE;AAAA,IACxG;AAAA,EACF;AAEA,MAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,QAAI,MAAM,6DAA6D;AACvE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,KAAK,MAAM;AAGjB,QAAM,SAAS,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AACnD,MAAI,KAAK,4BAA4B,MAAM,EAAE;AAC7C,MAAI,KAAK,uBAAuB;AAGhC,QAAM,WAAW,OAAO,WAAmB;AACzC,QAAI,aAAc;AAClB,mBAAe;AACf,QAAI,KAAK,GAAG,MAAM,6BAA6B;AAE/C,QAAI;AACF,YAAM,KAAK,KAAK;AAAA,IAClB,SAAS,KAAK;AACZ,UAAI,MAAM,0BAA0B,GAAG;AAAA,IACzC;AAEA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,GAAG,UAAU,MAAM,SAAS,QAAQ,CAAC;AAC7C,UAAQ,GAAG,WAAW,MAAM,SAAS,SAAS,CAAC;AAE/C,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,QAAI,MAAM,uBAAuB,GAAG;AAAA,EACtC,CAAC;AAED,UAAQ,GAAG,sBAAsB,CAAC,QAAQ;AACxC,QAAI,MAAM,wBAAwB,GAAG;AAAA,EACvC,CAAC;AACH;AAGA,IAAM,oBAAoB,QAAQ,KAAK,CAAC,GAAG,SAAS,SAAS;AAC7D,IAAI,mBAAmB;AACrB,cAAY,EAAE,MAAM,CAAC,QAAQ;AAC3B,QAAI,MAAM,UAAU,GAAG;AACvB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../packages/core/src/setup.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { input, select } from '@inquirer/prompts'\nimport type { Config, ConfigManager } from './config.js'\n\n// --- Telegram validation ---\n\nexport async function validateBotToken(token: string): Promise<\n { ok: true; botName: string; botUsername: string } | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getMe`)\n const data = await res.json() as { ok: boolean; result?: { first_name: string; username: string }; description?: string }\n if (data.ok && data.result) {\n return { ok: true, botName: data.result.first_name, botUsername: data.result.username }\n }\n return { ok: false, error: data.description || 'Invalid token' }\n } catch (err) {\n return { ok: false, error: (err as Error).message }\n }\n}\n\nexport async function validateChatId(token: string, chatId: number): Promise<\n { ok: true; title: string; isForum: boolean } | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getChat`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ chat_id: chatId }),\n })\n const data = await res.json() as {\n ok: boolean\n result?: { title: string; type: string; is_forum?: boolean }\n description?: string\n }\n if (!data.ok || !data.result) {\n return { ok: false, error: data.description || 'Invalid chat ID' }\n }\n if (data.result.type !== 'supergroup') {\n return { ok: false, error: `Chat is \"${data.result.type}\", must be a supergroup` }\n }\n return { ok: true, title: data.result.title, isForum: data.result.is_forum === true }\n } catch (err) {\n return { ok: false, error: (err as Error).message }\n }\n}\n\n// --- Agent detection ---\n\n// Commands listed in priority order — first match wins per agent\nconst KNOWN_AGENTS: Array<{ name: string; commands: string[] }> = [\n { name: 'claude', commands: ['claude-agent-acp', 'claude-code', 'claude'] },\n { name: 'codex', commands: ['codex'] },\n]\n\nfunction commandExists(cmd: string): boolean {\n // Check system PATH\n try {\n execFileSync('which', [cmd], { stdio: 'pipe' })\n return true\n } catch {\n // not in PATH\n }\n // Check node_modules/.bin (walks up from cwd)\n let dir = process.cwd()\n while (true) {\n const binPath = path.join(dir, 'node_modules', '.bin', cmd)\n if (fs.existsSync(binPath)) return true\n const parent = path.dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return false\n}\n\nexport async function detectAgents(): Promise<Array<{ name: string; command: string }>> {\n const found: Array<{ name: string; command: string }> = []\n for (const agent of KNOWN_AGENTS) {\n // Find all available commands for this agent (PATH + node_modules/.bin)\n const available: string[] = []\n for (const cmd of agent.commands) {\n if (commandExists(cmd)) {\n available.push(cmd)\n }\n }\n if (available.length > 0) {\n // Prefer claude-agent-acp over claude/claude-code (priority order)\n const preferred = available[0]\n found.push({ name: agent.name, command: preferred })\n }\n }\n return found\n}\n\nexport async function validateAgentCommand(command: string): Promise<boolean> {\n try {\n execFileSync('which', [command], { stdio: 'pipe' })\n return true\n } catch {\n return false\n }\n}\n\n// --- Setup steps ---\n\nexport async function setupTelegram(): Promise<Config['channels'][string]> {\n console.log('\\n--- Step 1: Telegram Setup ---\\n')\n\n let botToken = ''\n let botUsername = ''\n let botName = ''\n\n while (true) {\n botToken = await input({\n message: 'Telegram bot token (from @BotFather):',\n validate: (val) => val.trim().length > 0 || 'Token cannot be empty',\n })\n botToken = botToken.trim()\n\n console.log('Validating bot token...')\n const result = await validateBotToken(botToken)\n if (result.ok) {\n botUsername = result.botUsername\n botName = result.botName\n console.log(`✓ Bot \"${botName}\" (@${botUsername}) connected`)\n break\n }\n console.log(`✗ Validation failed: ${result.error}`)\n const action = await select({\n message: 'What would you like to do?',\n choices: [\n { name: 'Re-enter token', value: 'retry' },\n { name: 'Skip validation (use token as-is)', value: 'skip' },\n ],\n })\n if (action === 'skip') break\n }\n\n let chatId = 0\n\n while (true) {\n const chatIdStr = await input({\n message: 'Telegram supergroup chat ID (e.g. -1001234567890):',\n validate: (val) => {\n const n = Number(val.trim())\n if (isNaN(n) || !Number.isInteger(n)) return 'Chat ID must be an integer'\n return true\n },\n })\n chatId = Number(chatIdStr.trim())\n\n console.log('Validating chat ID...')\n const result = await validateChatId(botToken, chatId)\n if (result.ok) {\n if (!result.isForum) {\n console.log(`⚠ Warning: \"${result.title}\" does not have Topics enabled.`)\n console.log(' Please enable Topics in group settings → Topics → Enable.')\n } else {\n console.log(`✓ Connected to \"${result.title}\" (Topics enabled)`)\n }\n break\n }\n console.log(`✗ Validation failed: ${result.error}`)\n if (result.error.includes('must be a supergroup')) {\n console.log(' Tip: Create a Supergroup in Telegram, then enable Topics in group settings.')\n }\n const action = await select({\n message: 'What would you like to do?',\n choices: [\n { name: 'Re-enter chat ID', value: 'retry' },\n { name: 'Skip validation (use chat ID as-is)', value: 'skip' },\n ],\n })\n if (action === 'skip') break\n }\n\n return {\n enabled: true,\n botToken,\n chatId,\n notificationTopicId: null,\n assistantTopicId: null,\n }\n}\n\nexport async function setupAgents(): Promise<{ agents: Config['agents']; defaultAgent: string }> {\n console.log('\\n--- Step 2: Agent Setup ---\\n')\n\n console.log('Detecting agents in PATH...')\n const detected = await detectAgents()\n\n const agents: Config['agents'] = {}\n\n if (detected.length > 0) {\n for (const agent of detected) {\n agents[agent.name] = { command: agent.command, args: [], env: {} }\n }\n console.log(`Found: ${detected.map(a => `${a.name} (${a.command})`).join(', ')}`)\n } else {\n // Fallback to claude-agent-acp as default\n agents['claude'] = { command: 'claude-agent-acp', args: [], env: {} }\n console.log('No agents detected. Using default: claude (claude-agent-acp)')\n }\n\n const defaultAgent = Object.keys(agents)[0]\n console.log(`Default agent: ${defaultAgent}`)\n\n return { agents, defaultAgent }\n}\n\nexport async function setupWorkspace(): Promise<{ baseDir: string }> {\n console.log('\\n--- Step 3: Workspace Setup ---\\n')\n\n const baseDir = await input({\n message: 'Workspace base directory:',\n default: '~/openacp-workspace',\n validate: (val) => val.trim().length > 0 || 'Path cannot be empty',\n })\n\n return { baseDir: baseDir.trim() }\n}\n\nexport async function setupSecurity(): Promise<Config['security']> {\n console.log('\\n--- Step 4: Security Setup ---\\n')\n\n const userIdsStr = await input({\n message: 'Allowed Telegram user IDs (comma-separated, or leave empty to allow all):',\n default: '',\n })\n\n const allowedUserIds = userIdsStr.trim()\n ? userIdsStr.split(',').map(id => id.trim()).filter(id => id.length > 0)\n : []\n\n const maxConcurrentStr = await input({\n message: 'Max concurrent sessions:',\n default: '5',\n validate: (val) => {\n const n = Number(val)\n return (!isNaN(n) && Number.isInteger(n) && n > 0) || 'Must be a positive integer'\n },\n })\n\n const timeoutStr = await input({\n message: 'Session timeout (minutes):',\n default: '60',\n validate: (val) => {\n const n = Number(val)\n return (!isNaN(n) && Number.isInteger(n) && n > 0) || 'Must be a positive integer'\n },\n })\n\n return {\n allowedUserIds,\n maxConcurrentSessions: Number(maxConcurrentStr),\n sessionTimeoutMinutes: Number(timeoutStr),\n }\n}\n\n// --- Orchestrator ---\n\nfunction printWelcomeBanner(): void {\n console.log(`\n┌──────────────────────────────────────┐\n│ │\n│ Welcome to OpenACP! │\n│ │\n│ Let's set up your configuration. │\n│ │\n└──────────────────────────────────────┘\n`)\n}\n\nfunction printConfigSummary(config: Config): void {\n console.log('\\n--- Configuration Summary ---\\n')\n\n console.log('Telegram:')\n const tg = config.channels.telegram as Record<string, any> | undefined\n if (tg) {\n const token = String(tg.botToken || '')\n console.log(` Bot token: ${token.slice(0, 8)}...${token.slice(-4)}`)\n console.log(` Chat ID: ${tg.chatId}`)\n }\n\n console.log('\\nAgents:')\n for (const [name, agent] of Object.entries(config.agents)) {\n const marker = name === config.defaultAgent ? ' (default)' : ''\n console.log(` ${name}: ${agent.command}${marker}`)\n }\n\n console.log(`\\nWorkspace: ${config.workspace.baseDir}`)\n}\n\nexport async function runSetup(configManager: ConfigManager): Promise<boolean> {\n printWelcomeBanner()\n\n try {\n const telegram = await setupTelegram()\n const { agents, defaultAgent } = await setupAgents()\n const workspace = await setupWorkspace()\n const security = { allowedUserIds: [] as string[], maxConcurrentSessions: 5, sessionTimeoutMinutes: 60 }\n\n const config: Config = {\n channels: { telegram },\n agents,\n defaultAgent,\n workspace,\n security,\n }\n\n printConfigSummary(config)\n\n try {\n await configManager.writeNew(config)\n } catch (writeErr) {\n console.error(`\\n✗ Failed to write config to ${configManager.getConfigPath()}`)\n console.error(` Error: ${(writeErr as Error).message}`)\n console.error(' Check that you have write permissions to this path.')\n return false\n }\n console.log(`\\n✓ Config saved to ${configManager.getConfigPath()}`)\n console.log('Starting OpenACP...\\n')\n\n return true\n } catch (err) {\n // Ctrl+C from inquirer throws ExitPromptError\n if ((err as Error).name === 'ExitPromptError') {\n console.log('\\nSetup cancelled.')\n return false\n }\n throw err\n }\n}\n"],"mappings":"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","names":[]}
|