1000行代码实现极简版openclaw(附源码)(9)

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

08 - 配置系统和 CLI github 源码(欢迎star)

目标

实现配置管理和命令行接口。

配置管理

创建 src/config/manager.ts

import { z } from 'zod';
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';

const AgentSchema = z.object({
  model: z.string().default('deepseek-chat'),
  apiKey: z.string().default(''),
  maxToolDepth: z.number().default(10),
});

const GatewaySchema = z.object({
  workspace: z.string().default(join(homedir(), '.turboclaw')),
  agent: AgentSchema,
  channels: z.array(z.object({
    type: z.enum(['terminal', 'websocket']),
    enabled: z.boolean().default(true),
  })).default([{ type: 'terminal', enabled: true }]),
});

export type Config = z.infer<typeof GatewaySchema>;

export class ConfigManager {
  private config: Config;
  private configPath: string;

  constructor() {
    this.configPath = join(homedir(), '.turboclaw', 'config.json');
    this.config = this.load();
  }

  get(): Config { return this.config; }

  private load(): Config {
    let fileConfig = {};
    if (existsSync(this.configPath)) {
      try {
        fileConfig = JSON.parse(readFileSync(this.configPath, 'utf-8'));
      } catch {}
    }

    // 环境变量覆盖
    const envConfig: any = {};
    if (process.env.TURBOCLAW_API_KEY) {
      envConfig.agent = { apiKey: process.env.TURBOCLAW_API_KEY };
    }
    if (process.env.TURBOCLAW_MODEL) {
      envConfig.agent = { ...envConfig.agent, model: process.env.TURBOCLAW_MODEL };
    }

    const merged = { ...fileConfig, ...envConfig };
    return GatewaySchema.parse(merged);
  }

  initWorkspace(): void {
    if (!existsSync(this.config.workspace)) {
      mkdirSync(this.config.workspace, { recursive: true });
    }
    if (!existsSync(this.configPath)) {
      writeFileSync(this.configPath, JSON.stringify(this.config, null, 2));
    }
  }
}

CLI 入口

创建 src/cli.ts

import { ConfigManager } from './config/manager.js';
import { Gateway } from './core/gateway.js';
import { Agent } from './core/agent.js';
import { ToolRegistry, createFileSystemTools, createShellTools } from './tools/registry.js';
import { MemoryStore, createMemoryTools } from './memory/store.js';

const command = process.argv[2];

async function main() {
  const configManager = new ConfigManager();

  switch (command) {
    case 'init':
      configManager.initWorkspace();
      break;

    case 'start':
    case undefined:
      await startGateway(configManager);
      break;

    case 'send':
      await sendMessage(configManager, process.argv[3]);
      break;

    case 'status':
      showStatus(configManager);
      break;

    default:
      console.log('用法: turboclaw [init|start|send <message>|status]');
  }
}

async function startGateway(manager: ConfigManager): Promise<void> {
  const config = manager.get();
  const gateway = new Gateway(config);
  process.on('SIGINT', () => gateway.stop().then(() => process.exit(0)));
  await gateway.start();
}

async function sendMessage(manager: ConfigManager, content?: string): Promise<void> {
  if (!content) {
    console.error('请提供消息内容');
    process.exit(1);
  }

  const config = manager.get();
  
  // 创建临时组件
  const tools = new ToolRegistry();
  for (const t of createFileSystemTools(config.workspace)) tools.register(t);
  for (const t of createShellTools(config.workspace, false)) tools.register(t);
  
  const memoryStore = new MemoryStore(config.workspace);
  await memoryStore.init();
  for (const t of createMemoryTools(memoryStore)) tools.register(t);

  const agent = new Agent(config.agent, tools);
  const session = { id: 'cli', channelType: 'cli', messages: [], createdAt: Date.now(), updatedAt: Date.now(), metadata: {} };

  const response = await agent.process(content, session);
  console.log(`AI: ${response.content}`);
}

function showStatus(manager: ConfigManager): void {
  const config = manager.get();
  console.log('=== TurboClaw 状态 ===');
  console.log(`工作目录: ${config.workspace}`);
  console.log(`模型: ${config.agent.model}`);
  console.log(`API Key: ${config.agent.apiKey ? '已设置' : '未设置'}`);
}

main().catch(console.error);

关键点

  1. 配置优先级:环境变量 > 配置文件 > 默认值
  2. 工作目录:默认在用户目录下(~/.turboclaw
  3. 命令设计:init, start, send, status

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lch丶lch

创作不易,赠我咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值