内部模块: Project & Instance (项目上下文)

项目识别和实例状态管理。

1. 概览 (Overview)

  • 路径: packages/opencode/src/project/
  • 定位: 管理当前工作目录的项目上下文和状态隔离。
  • 核心文件: project.ts, instance.ts, state.ts

2. 核心概念

概念说明
Project项目元信息 (名称、VCS 类型、根目录)
Instance运行时上下文 (工作目录、状态缓存)
State按实例隔离的状态管理

3. Project 识别

Project.fromDirectory 自动识别项目类型:

export async function fromDirectory(directory: string) {
  // 查找 Git 根目录
  const gitRoot = await findGitRoot(directory)
  
  // 确定项目 ID (基于路径 hash)
  const id = createHash(directory)
  
  return {
    project: {
      id,
      name: path.basename(directory),
      vcs: gitRoot ? "git" : "none",
      root: gitRoot || directory,
    },
    sandbox: worktree || directory,  // 沙箱目录
  }
}

4. Instance 管理

Instance 是项目运行时的上下文容器:

export const Instance = {
  // 创建或获取实例
  async provide<R>(input: { 
    directory: string
    init?: () => Promise<any>
    fn: () => R 
  }): Promise<R> {
    let existing = cache.get(input.directory)
    if (!existing) {
      existing = (async () => {
        const { project, sandbox } = await Project.fromDirectory(input.directory)
        return { directory: input.directory, worktree: sandbox, project }
      })()
      cache.set(input.directory, existing)
    }
    const ctx = await existing
    return context.provide(ctx, async () => input.fn())
  },
 
  // 当前目录
  get directory() {
    return context.use().directory
  },
 
  // 工作树目录 (可能是 worktree)
  get worktree() {
    return context.use().worktree
  },
 
  // 项目信息
  get project() {
    return context.use().project
  },
}

5. State 隔离

不同项目有独立的状态空间:

// 创建按实例隔离的状态
export function state<S>(
  init: () => S, 
  dispose?: (state: Awaited<S>) => Promise<void>
): () => S {
  return State.create(
    () => Instance.directory,  // 使用目录作为 key
    init, 
    dispose
  )
}
 
// 使用示例
const sessionState = Instance.state(async () => {
  return {
    sessions: new Map<string, Session>(),
    pending: new Set<string>(),
  }
}, async (state) => {
  // 清理逻辑
  for (const session of state.sessions.values()) {
    await session.close()
  }
})
 
// 访问当前实例的状态
const current = sessionState()

6. 实例生命周期

7. 使用场景

场景 1: 多项目并行

// 同时处理两个项目
await Promise.all([
  Instance.provide({ directory: "/project-a", fn: handleA }),
  Instance.provide({ directory: "/project-b", fn: handleB }),
])
// 两个项目有独立的状态

场景 2: Worktree 沙箱

// 在 Worktree 中执行
const ctx = await Instance.provide({
  directory: "/home/user/project",
  fn: async () => {
    // Instance.worktree 可能指向
    // ~/.opencode/data/worktree/proj-id/brave-tiger
    console.log(Instance.worktree)
  }
})

8. 与其他模块的关系

几乎所有核心模块都使用 Instance.state() 来管理状态。

9. 总结

Project/Instance 模块提供了 多项目隔离 的基础:

  • 项目识别: 自动检测 Git 项目
  • 上下文传递: 使用 AsyncLocalStorage
  • 状态隔离: 每个项目独立的状态空间
  • 生命周期: 完善的初始化和清理机制