跳转到内容

实例边界与并发调度

一次会话总落在某个目录实例上:配置、权限边界、状态缓存与调度 Runner 都挂在这个作用域。同目录复用同一实例;同会话同时只跑一个主任务(prompt 或 shell),避免两个 runLoop 写乱消息。

实例上下文至少包含:当前 directory、worktree、project。它是作用域根键,而不是可有可无的三个字段。

flowchart TD
Call[业务调用] --> Prov[Instance.provide directory]
Prov --> Cache{缓存命中?}
Cache -->|是| Reuse[复用实例]
Cache -->|否| Boot[boot + 写入缓存]
Reuse --> Run[在上下文中执行]
Boot --> Run

reload 会释放同目录旧实例再 boot:目录未变,但项目、版本控制或配置可能已变,必须丢弃缓存态。

用户侧的边界:工作空间(租户)与 directory

Section titled “用户侧的边界:工作空间(租户)与 directory”

内核按 directory 组织实例,产品层不再让用户选目录,两层边界要分开看:

层边界作用
产品 / 数据租户(控制台展示为工作空间)与所有者会话、消息、审批、审计等按租户与所有者隔离;Postgres 下由行级安全策略兜底
用户文件文件沙箱生产把用户文件放对象存储,key 前缀含租户,不暴露服务器路径
内核运行上下文directory(平台根)决定工具在哪条路径、哪套配置上跑

由此有三条结论:

  • directory 仍决定文件工具的相对路径与配置、能力发现的根,但它对应运维固定的平台根,不再是用户打开的文件夹。控制台请求通常不带目录,运行时取进程启动目录。
  • 跨租户不可见不靠目录区分,靠请求上下文里的租户与所有者、存储行隔离,以及沙箱前缀。
  • 会话上另有一个可选字段登记控制面的执行环境(本地目录或远程代理)。本地开发通常留空,它与租户边界不是同一概念。

排查串数据时先分清现象:同目录下不同租户串了,还是租户上下文没绑上导致行隔离失效。

概念含义
directory运行时平台根:工具执行与配置发现的路径根;控制台不传目录时取进程启动目录
worktree仓库或项目根边界
sandbox(解析结果)检出顶路径,常作为 worktree 使用

路径是否算“内部”:落在 directory 内,或落在 worktree 内(非 git 且 worktree 退化为根时跳过第二项)。否则可能触发外部目录类权限。另有一层 git worktree 列表用于多分支并行工作区,与上述运行时 sandbox 字符串不是同一概念。

每会话一个 Runner:

状态含义
Idle空闲
RunningrunLoop 进行中
Shellshell 单飞
ShellThenRunshell 进行中且已排队 run
  • 已有 run 时再次 ensureRunning:等待同一结果,不另开外环
  • shell 仅在 Idle 可启动;忙则返回忙错误
  • cancel 可中断当前 run 或 shell
stateDiagram-v2
[*] --> Idle
Idle --> Running: prompt
Idle --> Shell: shell
Running --> Idle: 完成 / 取消
Shell --> Idle: 完成 / 取消
Shell --> ShellThenRun: 排队 prompt
ShellThenRun --> Running: shell 结束

客户端侧:同步 HTTP 会等到该会话任务结束;同时可通过 SSE 观察 busy 与 Part 增量。Effect 运行时里等待不会堵死整个进程,其它会话与事件连接仍可前进。

现象优先核对
改配置不生效实例是否 reload;是否连错 directory
跨租户看到他人数据请求上下文的租户与所有者是否绑定;存储行隔离是否生效
外部路径被拒containsPath 与 external_directory 权限
prompt 报忙同会话是否已有 run/shell
两路写入交错是否绕过 Runner 并发调 loop(不应发生)

相关阅读: