@jslee124/forge 0.3.0 → 0.3.2

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.
Files changed (35) hide show
  1. package/dist/index.js +1189 -90
  2. package/package.json +2 -1
  3. package/resources/docs/en/ARCHITECTURE.md +519 -0
  4. package/resources/docs/en/AUTHENTICATION.md +224 -0
  5. package/resources/docs/en/CLI_UI.md +266 -0
  6. package/resources/docs/en/CONFIGURATION.md +263 -0
  7. package/resources/docs/en/CONTEXT_MANAGEMENT.md +692 -0
  8. package/resources/docs/en/GETTING_STARTED.md +241 -0
  9. package/resources/docs/en/PLUGINS.md +622 -0
  10. package/resources/docs/en/PRODUCT.md +157 -0
  11. package/resources/docs/en/PROJECT_CONTEXT.md +225 -0
  12. package/resources/docs/en/RELEASING.md +94 -0
  13. package/resources/docs/en/SECURITY.md +272 -0
  14. package/resources/docs/en/SESSIONS.md +134 -0
  15. package/resources/docs/en/TROUBLESHOOTING.md +256 -0
  16. package/resources/docs/index.json +24334 -0
  17. package/resources/docs/zh-CN/ARCHITECTURE.md +174 -0
  18. package/resources/docs/zh-CN/AUTHENTICATION.md +96 -0
  19. package/resources/docs/zh-CN/CLI_UI.md +112 -0
  20. package/resources/docs/zh-CN/CONFIGURATION.md +221 -0
  21. package/resources/docs/zh-CN/CONTEXT_MANAGEMENT.md +200 -0
  22. package/resources/docs/zh-CN/GETTING_STARTED.md +193 -0
  23. package/resources/docs/zh-CN/PLUGINS.md +286 -0
  24. package/resources/docs/zh-CN/PRODUCT.md +86 -0
  25. package/resources/docs/zh-CN/PROJECT_CONTEXT.md +130 -0
  26. package/resources/docs/zh-CN/RELEASING.md +86 -0
  27. package/resources/docs/zh-CN/SECURITY.md +92 -0
  28. package/resources/docs/zh-CN/SESSIONS.md +69 -0
  29. package/resources/docs/zh-CN/TROUBLESHOOTING.md +185 -0
  30. package/resources/skills/forge-plugin-creator/SKILL.md +70 -0
  31. package/resources/skills/forge-plugin-creator/references/plugin-api.md +36 -0
  32. package/resources/skills/forge-plugin-creator/templates/index.mjs +30 -0
  33. package/resources/skills/forge-plugin-creator/templates/plugin.json +8 -0
  34. package/resources/skills/forge-plugin-creator/templates/plugin.test-template.ts +14 -0
  35. package/resources/skills/forge-product-help/SKILL.md +16 -0
@@ -0,0 +1,174 @@
1
+ # 架构
2
+
3
+ English · 中文目录
4
+
5
+ ## 状态
6
+
7
+ 本文描述 `dev` 分支当前架构与 package 边界依据。接口代码块是便于理解的简化草图,不是稳定 public SDK;checkout 中的 TypeScript types 与 tests 才是权威。
8
+
9
+ ## 实现基线
10
+
11
+ | 领域 | 当前决定 | 原因 |
12
+ | --- | --- | --- |
13
+ | Runtime | Node.js 24 LTS | 使用受支持的 LTS 和当前平台 API |
14
+ | Package manager | pnpm 11.18.0 | 快速、严格的依赖布局和 workspace 支持 |
15
+ | Module | 仅 ESM | 不维护双 ESM/CommonJS 输出 |
16
+ | 仓库形态 | pnpm monorepo | 不拆仓库也能看见 runtime 边界 |
17
+ | Build | TypeScript project references + `tsc -b` | 先以包方向约束替代 bundler |
18
+ | CLI 解析 | Commander | 成熟、轻量的进程命令和 help parser |
19
+ | 交互 UI | Ink + React | 处理终端渲染和键盘,不把 runtime 搬进 UI |
20
+ | 校验 | Zod | 在配置和工具输入之间共享 runtime validation |
21
+ | 格式/lint | Biome | 一个快速、配置面小的工具 |
22
+ | 测试 | Vitest | 快速 TypeScript 测试和易写 fake |
23
+ | 首个 provider | `@ai-sdk/deepseek` 的 DeepSeek | 泛化前先证明一条 provider 路径 |
24
+ | 首个 model | `deepseek-v4-flash` | 支持 tool 和 thinking 的快速模型 |
25
+ | 进程执行 | Node `spawn`、`shell: false` | 保持 program/args 结构化,避免隐式 shell 解析 |
26
+
27
+ 根 `package.json` 是 private,并通过 `packageManager` 固定 pnpm。每个 workspace package 使用 ESM;依赖版本由 lockfile 固定,文档只固定 runtime/package-manager 基线。
28
+
29
+ ### Monorepo 布局
30
+
31
+ ```text
32
+ apps/
33
+ `-- cli/ # @forge/cli:解析、渲染、审批 UI
34
+ packages/
35
+ |-- core/ # @forge/core:循环、事件、策略合约
36
+ |-- codex-app-server/ # Codex JSON-RPC transport 和 auth 边界
37
+ |-- model-deepseek/ # DeepSeek AI SDK translation
38
+ |-- model-compat/ # OpenAI-compatible route translation
39
+ |-- model-openai/ # OpenAI Responses API translation
40
+ |-- auth/ # provider-neutral API-key resolution
41
+ |-- persistence/ # session snapshots、JSONL traces、redaction
42
+ |-- plugin-api/ # 可执行 plugin discovery、trust、host 与 API v1
43
+ |-- resources/ # 非执行型 Skill catalog 与安全延迟加载
44
+ |-- tools/ # 内置工具实现
45
+ `-- config/ # 配置和 context loading
46
+ fixtures/ # integration test 的小型仓库任务
47
+ evals/ # task manifest、grader、runner、报告
48
+ ```
49
+
50
+ `evals/` 是 private workspace package。Live runner 使用真实 CLI run boundary,将 fixture 复制到临时 workspace,注入窄审批 channel,保存正常 trace,并在 Agent 停止后调用外部 grader。生成物只有在选定报告后才发布。
51
+
52
+ ### CLI 与进程约定
53
+
54
+ | 退出码 | 含义 |
55
+ | --- | --- |
56
+ | `0` | 运行完成且所需验证成功 |
57
+ | `1` | 未恢复的 runtime、provider 或工具失败 |
58
+ | `2` | CLI 用法或配置无效 |
59
+ | `3` | 未成功停止,包括触达限制 |
60
+ | `4` | 必需动作被拒绝或无审批 channel |
61
+ | `130` | 用户 Ctrl+C 取消 |
62
+
63
+ 工具失败可能作为 observation 返回模型,不一定立即决定进程退出码;只有终止 run 状态决定退出码。普通用户错误默认不打印 stack trace。
64
+
65
+ ## 系统上下文
66
+
67
+ ```text
68
+ User -> CLI -> Agent Runtime
69
+ |-- Model Adapter -> Auth Manager -> AI SDK -> Provider
70
+ |-- Context Loader -> Instructions
71
+ |-- Resource Catalog -> load_skill
72
+ |-- Plugin Host -> Contributions
73
+ |-- Policy Kernel -> Tool Executor
74
+ `-- Run Events -> Terminal + Trace
75
+ ```
76
+
77
+ ## 组件职责
78
+
79
+ ### CLI
80
+
81
+ CLI 负责命令和配置解析、持久化交互 session、多行编辑、斜杠补全、`@` 文件引用、workspace 选择、流式事件和 diff 渲染、敏感操作审批、通过 `AbortSignal` 转发取消,以及选择退出码。它不包含 agent loop 或工具实现;Commander 负责进程命令,Ink 只负责交互 presentation。文件 mention 只携带 workspace-relative path,不绕过 `read_file`、workspace 校验、policy 或 trace。
82
+
83
+ 每个交互 prompt 开始新的有界 run 和审批实例;下一 prompt 只携带已完成的 user/assistant text。session 可以跨重启恢复,但 tool continuation 和审批只属于产生它们的 run。
84
+
85
+ ### Agent runtime
86
+
87
+ Runtime 拥有 run state/step count、conversation message、model/tool 循环、provider reasoning block、停止条件、工具校验和 dispatch、审批检查、project context、受控 plugin hook、event emission 和最终 status。它依赖 model、tools、approval、trace 的接口,从而可以独立测试。
88
+
89
+ ### Model adapter
90
+
91
+ 初始 adapter 使用 Vercel AI SDK 和 `@ai-sdk/deepseek` 流式传输。它只执行一次 provider turn 并把 stream 映射为 Forge event;多步骤循环由 Forge 控制,不交给 `ToolLoopAgent` 或 `stopWhen`。AI SDK tool definition 不带直接 execute callback;Forge 只有在 policy 记录决策后才验证和执行。
92
+
93
+ DeepSeek thinking tool call 要把 provider reasoning content 原样放入后续 tool-result turn,因此 adapter 返回和可观察事件并列的 opaque continuation。Core 可以保存并交还同一个 adapter,但不能从终端文字重构或丢弃 metadata。Provider 返回的 reasoning 作为 typed response part 输出;没有返回时不得伪造。
94
+
95
+ ### Authentication manager
96
+
97
+ 认证与 transport 分离。Native Forge Engine 通过 provider-neutral manager 先解析 `DEEPSEEK_API_KEY`/`OPENAI_API_KEY` 等环境变量,再读取 Forge owner-only credential store,然后交给 provider adapter;Codex Engine 通过 stdio JSON-RPC 启动官方 Codex App Server。Forge 发起 managed browser/device-code login,但 Codex 拥有 OAuth client identity、callback、token、持久化、刷新和 logout。Forge 不复制其他应用 credentials,也不静默读取 `~/.codex/auth.json`。
98
+
99
+ ### Project context loader
100
+
101
+ Loader 先解析 `FORGE_HOME`(默认用户 `~/.forge/`),校验配置,再解析规范 workspace 和 working directory。配置从默认、用户、项目、环境和 CLI 合并,同时保留 provenance;user-only 和 strictness-only key 不可被普通覆盖。它按 root 到 leaf 读取 `AGENTS.md`,在每层优先 `AGENTS.override.md`,发现 `.agents/` 和 `.forge/`,并且只有 workspace 明确 trust 后才交给 plugin host 项目插件。项目 context 可以让 prompt 更严格,但不能授予权限或读取 secret。
102
+
103
+ ### Plugin host
104
+
105
+ Plugin host 是扩展边界,不是安全 authority。受信任插件可注册 custom tool、user command、prompt、immutable event observer、有界的宿主管理 subagent 角色、特定 lifecycle hook,或让 policy 更严格。声明 `network:access` 的 network tool 每次调用都需确认;所有 custom tool 仍经过 policy kernel 和 executor。进程内 JavaScript plugin 是本地可信代码,API capability 不是隔离;强隔离需要子进程或 OS sandbox。
106
+
107
+ Subagent 声明会变成 `model` risk 的 parent tool。由宿主而非插件创建 child adapter、隔离对话、继承 policy/approval、共享预算、取消链路、有界结果和关联 trace。Child 工具集合排除所有 subagent tool,因此委派深度固定为一层。当前继承 parent model,不支持跨模型路由或可独立 resume 的 child session。
108
+
109
+ ### Tools 与审批策略
110
+
111
+ 每个工具有唯一名称、model-facing 描述、Zod input schema、执行函数、risk 分类和结构化结果。初始工具包括 `list_files`、`read_file`、`search`、`create_file`、`apply_patch`、`run_command`,以及示例 plugin 的 `web_search`/`web_fetch` 和 `delegate_code_review`。
112
+
113
+ 策略在执行前返回:
114
+
115
+ ```text
116
+ allow 无需交互执行
117
+ confirm 执行前询问用户
118
+ deny 不执行
119
+ ```
120
+
121
+ 策略检查规范路径、写入、破坏性命令、time/output/call limits 和审批 UI。默认是 workspace 读/列/搜 allow,首次写入 confirm,同一 run 已批准范围内的后续写入 allow,所有进程和注册网络工具 confirm,workspace 外内置文件操作 deny,无审批 channel 的必需动作 deny。符号链接必须在决策前解析;`run_command` 用 `spawn`/`shell:false`,但确认、超时、输出限制和 trace 不是 OS 隔离。
122
+
123
+ ### Hooks、事件和 trace
124
+
125
+ 行为改变型 hook 与不可变观察 event 分开。Lifecycle hook 有类型化返回值;policy contribution 可以把 allow 提高到 confirm/deny,但不能降低强制决策;`RunEvent` 是 renderer、trace 和 metrics 共用的 immutable observation。事件包括 `run.started`、`model.started`、`model.reasoning`、`tool.proposed`、`tool.approved`、`tool.denied`、`tool.completed`、`tool.failed`、`run.completed`、`run.failed` 和 `run.cancelled`。Trace 不得保存 API key 或已知 secret。
126
+
127
+ ### Session 与 run
128
+
129
+ Session 是持久用户对话,run 是一次有界 prompt 调用;一个 session 可包含多个 run,每个 run 有自己的 trace、limits、policy 和 terminal status。Session store 位于 application boundary,保存完成的 user/assistant turn 和有序 run ID,不保存 provider continuation、pending approval、活跃子进程或 in-progress tool call。Resume 重新加载当前配置/指令并创建新 run,因此不会把旧权限当 authority。
130
+
131
+ ## 核心接口草图
132
+
133
+ ```ts
134
+ interface ModelAdapter {
135
+ stream(request: ModelRequest, signal: AbortSignal): AsyncIterable<ModelStreamEvent>;
136
+ }
137
+ interface AuthenticationManager {
138
+ resolve(provider: string, signal: AbortSignal): Promise<ModelCredential>;
139
+ logout(provider: string): Promise<void>;
140
+ }
141
+ interface ForgeTool<Input, Output> {
142
+ name: string;
143
+ description: string;
144
+ inputSchema: ZodType<Input>;
145
+ risk: ToolRisk;
146
+ execute(input: Input, context: ToolContext): Promise<ToolResult<Output>>;
147
+ }
148
+ interface ApprovalPolicy { evaluate(action: ProposedAction): Promise<ApprovalDecision>; }
149
+ interface TraceWriter { append(event: RunEvent): Promise<void>; }
150
+ ```
151
+
152
+ 这些是设计草图,不是稳定 public API。
153
+
154
+ ## Run 生命周期
155
+
156
+ ```text
157
+ created -> running <-> awaiting_approval
158
+ | |
159
+ +--> completed +--> failed / cancelled / limit_reached
160
+ ```
161
+
162
+ 只有 terminal state 能结束 run。自然语言声称成功不能覆盖 runtime 记录的失败验证。
163
+
164
+ ## 依赖方向与上下文所有权
165
+
166
+ CLI、native runtime、AI SDK adapter、auth manager、context loader、tools 和 trace 实现都依赖 core interface;plugin host 依赖 core extension interface;core 不得 import CLI rendering、具体 provider、plugin implementation 或未来的 LangChain adapter。
167
+
168
+ Milestone 10 将 context ownership 分开:core 负责分类、预算计算、事件和停止;adapter 负责 model window、估算、overflow 分类和 continuation projection;persistence 负责 session-v2 checkpoint;CLI 负责 `/context`、`/compact`、Codex wrapper budget 和 inspection rendering。规范 transcript 永远不被 active model view 替换。兼容 route 的 continuation 仍是 opaque adapter state,provider metadata 由 transport 保存。
169
+
170
+ ## 测试策略与延后决定
171
+
172
+ 测试覆盖路径、stop condition、policy、symlink、missing UI、临时 workspace 工具、fake model runtime、AI SDK message/tool translation、fake credential/refresh、context hierarchy/provenance、plugin hook 不削弱决策,以及小型 fixture 的端到端任务。默认 suite 不需要真实模型调用。
173
+
174
+ SQL/数据库存储、更多 provider、外部 workspace 审批、OS sandbox、plugin 子进程、分布式 trace 和更复杂的恢复语义,只有在对应 milestone 需要时决定。
@@ -0,0 +1,96 @@
1
+ # 认证模型
2
+
3
+ English · 中文目录
4
+
5
+ ## 状态
6
+
7
+ Forge 支持通过 `DEEPSEEK_API_KEY` 和 `OPENAI_API_KEY` 使用 DeepSeek/OpenAI API key,也支持通过官方 Codex App Server 使用 ChatGPT 订阅。用户配置的 provider route 还可以使用明确选择的 bearer credential,或对本地/self-hosted endpoint 不使用认证。Forge 展示登录命令和 browser/device-code 指引;Codex 负责 OAuth、凭据持久化、刷新和撤销。
8
+
9
+ | 方法 | 用途 | 状态 |
10
+ | --- | --- | --- |
11
+ | DeepSeek API key | 本地开发和自动化 | 已实现 |
12
+ | OpenAI API key | 按用量计费的 OpenAI API | 已实现 |
13
+ | Provider route bearer key | OpenAI-compatible gateway | 已实现 |
14
+ | 无认证 provider route | 本地 Ollama/vLLM 风格 server | 已实现 |
15
+ | Sign in with ChatGPT | 通过 Codex App Server 使用 OpenAI 订阅 | 已实现 |
16
+ | Codex access token | 受信任企业自动化 | 延后 |
17
+
18
+ DeepSeek 的官方 endpoint 是 `https://api.deepseek.com`,初始 adapter 使用官方 AI SDK provider package。模型 ID 保持可配置,因为 provider 的模型生命周期与 Forge release 不同。参考:[DeepSeek API model documentation](https://api-docs.deepseek.com/quick_start/pricing/)、[AI SDK DeepSeek provider](https://ai-sdk.dev/providers/ai-sdk-providers/deepseek)。OpenAI 的产品集成使用公开的 [Codex App Server](https://developers.openai.com/codex/app-server),不复制其他应用的 OAuth client identity,也不把未公开的 ChatGPT endpoint 当作稳定合约。
19
+
20
+ ## 架构边界
21
+
22
+ ```text
23
+ Forge Engine: Forge Runtime -> Model Adapter -> DeepSeek 或 OpenAI API
24
+
25
+ Codex Engine: Forge CLI -> Codex App Server -> ChatGPT 订阅
26
+ ```
27
+
28
+ Codex Engine 不是 Forge `ModelAdapter` 的包装:App Server 自己拥有完整 agent runtime、turn、tools、sandbox、审批和 history。Provider-neutral authentication manager 会先读取显式环境变量,再读取 Forge 的用户级 owner-only credential store,最后把 key 交给选定 adapter。缺失凭据时给出可操作错误,但不打印 key 或 stack trace。凭据不会复制到 Forge 配置、prompt、trace、plugin event 或仓库文件。
29
+
30
+ ## OpenAI-compatible provider route
31
+
32
+ Route 只能在 `$FORGE_HOME/config.json` 的 `providers` 中声明;仓库 `.forge/config.json` 不得决定凭据发送到哪里。
33
+
34
+ ```json
35
+ {
36
+ "schemaVersion": 1,
37
+ "providers": {
38
+ "my-gateway": {
39
+ "api": "openai-responses",
40
+ "baseUrl": "https://gateway.example/openai/v1",
41
+ "auth": { "type": "bearer", "apiKeyEnv": "GATEWAY_API_KEY" },
42
+ "models": [
43
+ {
44
+ "id": "reasoning-model",
45
+ "contextWindow": 128000,
46
+ "maxOutputTokens": 8192,
47
+ "reasoningGears": { "none": "none", "high": "high" }
48
+ }
49
+ ]
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ `auth.type` 必填。`bearer` 读取声明的环境变量,或先推导 `FORGE_<ROUTE>_API_KEY`,再查 Forge 保存的 credential;`none` 不读取也不发送 key。保存的 route credential 与规范 `baseUrl` 绑定,endpoint 变化后旧 key 会被拒绝,直到重新保存。
56
+
57
+ 远程 endpoint 要求 HTTPS;只有 loopback host 允许普通 HTTP。包含 credential、query 或 fragment 的 URL 会被拒绝。模型发现不跟随 redirect,限制为 4 MiB 和 15 秒,并且是可选的,因为用户可以手动填写 model ID。
58
+
59
+ 省略 reasoning 设置表示 **provider default**,不等于禁用 reasoning。每个 `reasoningGears` 将 Forge UI 等级映射为发给 provider 的精确 wire value;如果 endpoint 支持关闭 reasoning,必须显式写出 `"none": "none"`。缺失 capability metadata 时 Forge 报告 unknown,保留 provider default,不猜测,也不发起付费探测请求。
60
+
61
+ OpenAI API key 与 ChatGPT 订阅独立计费。只有订阅的用户不需要创建或导出 `OPENAI_API_KEY`,可以继续使用 `model.provider = "deepseek"` 或 `forge codex`。
62
+
63
+ ## 兼容性要求
64
+
65
+ - 使用公开记录的 App Server 产品集成流程。
66
+ - Forge 不提供或复制 OAuth client identity。
67
+ - 由 Codex 执行 token exchange、refresh、revoke 和 account selection。
68
+ - 面向用户的文案明确区分订阅访问和按用量计费的 API。
69
+
70
+ Forge 不得复制其他应用的 client secret、把逆向 endpoint 当永久 API、要求用户在聊天中粘贴 token、直接读取或修改 `~/.codex/auth.json`,或把 credential 存入当前仓库。
71
+
72
+ ## 凭据存储
73
+
74
+ 交互式 `/login` 可以把 API key 保存到 `$FORGE_HOME/auth.json`。目录权限为 `0700`,文件为 `0600`,更新是原子的,环境变量优先。这是受文件权限保护的明文 fallback,不是 OS keychain;ChatGPT 订阅 credential 完全由 Codex App Server 所有。`/logout` 会移除选择的 Forge credential,或请求 Codex 注销 ChatGPT 订阅。移除第三方 route 是单独的确认操作,会删除 route、models 和保存的 credential;无法替父 shell 取消环境变量。
75
+
76
+ 当前 runtime 查找顺序是:provider 的显式/约定环境变量;项目外、仅 owner 可读的 `$FORGE_HOME/auth.json`。OS credential store 比明文 file storage 更理想,但目前仍是后续改进;自动化推荐使用环境变量注入。凭据不得进入 prompt、run event、JSONL trace、plugin event、telemetry 或普通错误信息。
77
+
78
+ ## 刷新与并发
79
+
80
+ Codex App Server 负责订阅 token 刷新和持久化,Forge 永远不接收 OAuth access/refresh token。凭据更新必须原子完成;刷新失败不能在错误处理前破坏最后一个已知凭据。OAuth refresh 应 single-flight,避免并发请求竞争同一个 refresh token。
81
+
82
+ ## 命令
83
+
84
+ ```text
85
+ forge auth login openai
86
+ forge auth status openai
87
+ forge auth status openai-api
88
+ forge auth logout openai
89
+ forge models list --provider openai
90
+ forge codex "Inspect this repository" --model <id> --reasoning-effort <effort>
91
+ forge run "Inspect this repository" --provider openai --model gpt-5.4-mini --reasoning-effort low
92
+ ```
93
+
94
+ 无头环境使用 `forge auth login openai --method device-code`。Forge 展示官方 verification URL 和 code,并等待 App Server 完成通知;browser callback 校验和 PKCE 由 Codex 负责。`forge auth status openai-api` 会报告当前生效的是环境 credential 还是已保存 credential,但不发起付费验证请求;`forge auth login openai-api` 会引导用户使用带掩码的交互 `/login` 或 `OPENAI_API_KEY`,普通子命令不会从命令参数读取 secret。
95
+
96
+ `/model` 会发现当前 Codex catalog,并展示不按 reasoning effort 重复的 native API models。独立的 `/effort` 和 Shift+Tab 使用当前模型支持的等级。普通 engine/provider/model/reasoning 设置保存到 `$FORGE_HOME/config.json`;credential 则独立存在环境变量、`$FORGE_HOME/auth.json` 或 Codex-owned storage。选择 ChatGPT 条目后,后续交互 prompt 通过 Codex Engine 路由。
@@ -0,0 +1,112 @@
1
+ # 交互式 CLI UI
2
+
3
+ English · 中文目录
4
+
5
+ ## 状态
6
+
7
+ 本文描述已实现的 Milestone 4.6 终端体验。Ink 提供交互式 renderer;非交互命令和 Forge 自有 runtime 保持原有边界。
8
+
9
+ ## 目标
10
+
11
+ 交互 CLI 应让常见 coding-agent 操作可发现,同时不把 agent loop、工具或策略决策移出 Forge core。UI 包括:
12
+
13
+ - 多行 prompt editor;
14
+ - 可发现的斜杠命令补全;
15
+ - `@` workspace 文件补全;
16
+ - 清晰区分 reasoning、答案、工具活动和 run 状态;
17
+ - 终端原生 Markdown(标题、列表、引用、链接、行内代码、强调、代码块);
18
+ - 文件写入审批前的可读 diff 审查;
19
+ - 仅用键盘操作和可预测取消;
20
+ - 蓝色 Forge frame 内的启动能力摘要。
21
+
22
+ Ink 只负责交互 renderer,Commander 负责进程级命令解析;React/Ink 留在 `apps/cli`,`@forge/core` 不依赖终端框架。Forge 使用 full-frame Ink 更新,避免 resize 后留下旧行。
23
+
24
+ ## 启动能力摘要
25
+
26
+ 首个 prompt 前,蓝色 frame 列出启用的 user plugin、标记为 `trusted` 或 `untrusted, skipped` 的项目插件,以及发现的内置、用户和项目 Skills。这里只读取 manifest 和 Skill metadata,不为显示名称而 import 项目插件;实际 plugin activation 只发生在 native Forge Engine run。Native run 会发布有界 Skill catalog 并延迟加载匹配正文,显式 `$skill-name` 保留为 override。Codex Engine 有独立工具 runtime,因此列表描述的是 Forge 资源,不是 Codex 工具。
27
+
28
+ `/plugins` 打开 metadata-only 审查面板,显示项目插件版本、capability 和当前 workspace trust。信任需要在进程内权限警告后再次按 `y` 确认;同一面板可撤销。决定成功后立即刷新启动 frame,但插件 activation 延迟到下一次 native Forge Engine 任务。
29
+
30
+ ## 交互状态
31
+
32
+ ```text
33
+ editing
34
+ |-- "/" --> selecting_command -- execute/insert --> editing
35
+ |-- "@" --> selecting_file ---- insert ---------> editing
36
+ `-- submit --> running --> awaiting_approval --> running --> editing
37
+ `---------------- completed ------------^
38
+ ```
39
+
40
+ 只有当前状态消费键盘。Ctrl+C 先关闭补全菜单,再取消运行;Forge 空闲时保留原有的显式退出行为。
41
+
42
+ ## Prompt editor
43
+
44
+ - 没有补全或审批菜单占用 Enter 时,非空 prompt 提交。
45
+ - Shift+Enter 插入换行不提交;Meta+Enter(`ESC+Enter`)等价。
46
+ - 老终端无法区分 Shift+Enter 时,Ctrl+J 作为可移植换行 fallback;footer 应显示当前可用快捷键。
47
+ - 已知兼容终端(如 VS Code、Ghostty)直接启用 enhanced keyboard protocol,其他终端使用 Ctrl+J 或 Meta+Enter。
48
+ - 组装 user message 时原样保留换行。
49
+ - 左右移动、退格、删除、Home/End、粘贴、Unicode 和 resize 不能破坏 buffer 或显示。
50
+ - 补全菜单打开时上下移动选项;菜单关闭时未来可用于 prompt history,但不是 Milestone 4.6 要求。
51
+ - Shift+Tab 在当前模型支持的 thinking-effort 等级间循环。
52
+
53
+ ## 斜杠命令补全
54
+
55
+ 当 `/` 是首个非空白字符时打开命令列表,后续字符按命令名过滤。同一个 registry 同时驱动补全和 `/help`,避免两处漂移。当前包括 `/help`、`/new`、`/clear`、`/context`、`/compact`、`/plugins`、`/login`、`/logout`、`/model`、`/delete-model`、`/effort`、`/resume` 和 `/exit`。
56
+
57
+ `/model` 打开键盘 picker,发现当前 ChatGPT/Codex models、配置的 API providers,并按 model 而非 effort 重复显示;`/effort` 是独立的 model-specific picker,`/effort <level>` 可直接设置支持的等级,两者原子保存。`/logout` 移除选定的保存 credential,但不假装能取消父 shell 的环境变量。`/delete-model` 只显示用户配置的 provider model,需要确认,且不能删除当前 active model。
58
+
59
+ `/login` 总是列出已配置的第三方 route,包括完整 Base URL、API type、认证模式、状态和 model 数量。route 管理可以添加/恢复 model、删除 model、logout 或 remove provider;删除 model 不删除 route/credential,logout 保留 signed-out route,remove provider 是单独的确认操作且不能移除 active provider。
60
+
61
+ 只有 `/models` 返回受认可且有界的 capability metadata 时,model setup 才预填 reasoning levels,并标记 discovered 或 manual。没有 metadata 时 Enter 保留 provider default;Forge 不把缺失 metadata 猜成无 reasoning model,也不发起付费探测。
62
+
63
+ - Up/Down 改变高亮命令。
64
+ - Enter 执行高亮命令。
65
+ - Tab 补全名称但不执行。
66
+ - Escape 关闭菜单且不改输入。
67
+ - 普通句子或路径中间的 `/` 不打开命令菜单。
68
+
69
+ ## Workspace 文件引用
70
+
71
+ 输入 `@` 会列出选定 workspace 下的有界文件。当前 token 后的文字按相对路径做不区分大小写的 fuzzy matching:
72
+
73
+ - 候选是 workspace-relative,显示分隔符固定为 `/`;
74
+ - `.git`、依赖目录、build output 和规范 workspace 外路径排除;
75
+ - 最多显示 10 个候选,并提示是否还有更多;
76
+ - 上下移动,Enter/Tab 插入,Escape 关闭;
77
+ - 插入可见 mention,同时在 editor state 保留结构化 `{ path }`,有空格的路径不依赖重新解析展示文字;
78
+ - 发现只读、有界、可取消,不会为每个按键调用模型或外部 shell。
79
+
80
+ 提交时 Forge 发送用户文字和 workspace-relative path 列表。mention 不会自动注入完整文件内容;模型需要内容时,仍通过正常 policy/trace 的 `read_file` 获取。
81
+
82
+ ## 粘贴图片附件
83
+
84
+ 当 bracketed paste 或终端拖放以绝对图片路径开始时,Forge 从文字移除路径并显示紧凑的 `[Image #N] filename`。支持 OS/终端把截图放到临时目录的场景;引号路径、shell-escaped 空格和 `file://` 都接受。文字 composer 为空时按 Backspace 移除最近附件。
85
+
86
+ 这是明确的用户动作,因此附件可以在 workspace 外;Forge 不扫描普通 prompt 中的路径,也不会扩大模型文件工具的 workspace 边界。当前模型必须支持 image input。
87
+
88
+ ## Diff 审查
89
+
90
+ 文件写入审批前必须在独立面板展示精确变更:操作和路径(create/modify/delete)、文件摘要和行数、带新旧行号的 unified diff、带 `+/-` 的新增/删除行、清晰的 file/hunk header、已知文件类型的语法高亮,以及触达安全显示限制时的截断说明。
91
+
92
+ 审批不能只依赖颜色;`--no-color`、无色终端和色觉差异都必须保留 `+/-`、header 和行号。超过安全审查限制的 diff 不可审批,不能把未展示的部分默认为已审查。控制项要说明范围:首次 workspace 写入的审批只覆盖本次 run 的后续 workspace 写入,进程命令仍需单独审批。
93
+
94
+ 网络工具审批使用专用面板,展示注册工具名和将发送到外部的有界 URL 或搜索词;plugin secret 和任意 input object 不渲染为预览。
95
+
96
+ ## 登录面板
97
+
98
+ 浏览器登录是独立面板,不是 transcript 文本。Codex auth surface 以带独立地址字段的结构化 `login` event 报告 URL,因此 UI 不需要从文本块重新解析。
99
+
100
+ 登录 URL 通常比终端宽很多。面板使用单个 OSC 8 hyperlink,使 Ink 换行后完整 URL 仍可点击;不支持的终端仍显示完整可复制地址。escape sequence 不计入显示宽度,否则边框会错位。
101
+
102
+ ## Rendering 边界
103
+
104
+ CLI 可以把 runtime event 变成 message block、tool activity row、status indicator 和 diff panel,但不能从展示状态推断成功,也不能解析之前渲染的终端文本。Core event 和审批请求是 source of truth;交互与非交互命令继续共享 Forge runtime、workspace 校验、policy gateway 和工具执行。
105
+
106
+ 模型 Markdown 是有界的终端子集,不是 HTML。流式输出中的不完整结构必须可渲染,且应在样式化前移除模型提供的 ANSI 控制序列。
107
+
108
+ ## 测试策略
109
+
110
+ 确定性 UI 测试应覆盖斜杠菜单、文件过滤和 workspace escape、结构化 mention、Enter/Shift+Enter/Meta+Enter/Ctrl+J、多行/粘贴/Unicode/resize/取消、editing/completion/running/approval 状态、插件/Skill 启动列表和 trust label,以及 create/modify、多 hunk、无色、截断和审批范围的 diff。UI 测试不应发起付费请求;组件测试使用脚本化输入和 event,另用小型 pseudo-terminal 集成测试验证代表性终端的按键序列。
111
+
112
+ `/resources` 显示每个已发现 Skill 的来源、描述、自动或仅显式调用状态、遮蔽关系与有界诊断;它不会导入插件 entry 或提前加载 Skill 正文。`/plugins` 仍只处理可执行插件,并引导用户通过 `/resources` 查看 Skills。
@@ -0,0 +1,221 @@
1
+ # 配置参考
2
+
3
+ English · 中文文档目录
4
+
5
+ 这篇页面说明 `@forge/config` 当前实现的 schema version 1。当前设置和优先级以本页为入口;`AGENTS.md`、Skills 与资源目录见项目上下文。
6
+
7
+ ## 修改前先检查
8
+
9
+ ```bash
10
+ pnpm forge config validate
11
+ pnpm forge config show
12
+ ```
13
+
14
+ `validate` 会打印 Forge 实际检查的用户配置和项目配置路径;`show` 会展示每个有效值、来源、Forge home 和规范 workspace root。这两条命令都不会调用模型。
15
+
16
+ ## 文件与优先级
17
+
18
+ Forge 按以下顺序加载:
19
+
20
+ ```text
21
+ built-in defaults
22
+ < $FORGE_HOME/config.json 用户配置
23
+ < <workspace-root>/.forge/config.json
24
+ < 支持的环境变量
25
+ < 显式 CLI flags
26
+ ```
27
+
28
+ `FORGE_HOME` 默认是 `~/.forge`。在 Git 仓库中,规范仓库根目录是 workspace root;不在 Git 仓库时使用当前目录。
29
+
30
+ 这不是无限制的“后者覆盖前者”:
31
+
32
+ - 用户配置可以设置全部 schema 字段。
33
+ - 项目配置只能设置 `limits` 和 `context`。
34
+ - 项目 limit 只有比用户当前值更严格时才会生效。
35
+ - 项目 context mode 只能从 `off` 收紧到 `warn`/`compact`,或从 `warn` 收紧到 `compact`。
36
+ - Model、permission、trace、用户 plugin enablement 和 provider route 都是 user-only 字段;写入项目配置会直接报错。
37
+ - 未知字段和不支持的 schema version 都是错误。
38
+
39
+ 因此仓库内容无法自行选择 credential 发送目标、启用可执行 plugin 或扩大安全 limit。
40
+
41
+ ## 一个实用的用户配置
42
+
43
+ 只需要写出想覆盖的值,省略字段会保留默认值:
44
+
45
+ ```json
46
+ {
47
+ "schemaVersion": 1,
48
+ "model": {
49
+ "engine": "forge",
50
+ "provider": "deepseek",
51
+ "id": "deepseek-v4-flash",
52
+ "reasoningEffort": "medium",
53
+ "thinking": "enabled"
54
+ },
55
+ "permissionProfile": "safe",
56
+ "limits": {
57
+ "maxSteps": 12,
58
+ "maxToolCalls": 40,
59
+ "commandTimeoutMs": 60000,
60
+ "maxToolOutputBytes": 65536
61
+ },
62
+ "trace": { "enabled": true },
63
+ "plugins": { "enabled": [] },
64
+ "context": {
65
+ "mode": "warn",
66
+ "reservedOutputTokens": 4096,
67
+ "bufferTokens": 8192,
68
+ "recentTailTokens": 12000,
69
+ "summaryTargetTokens": 1200
70
+ }
71
+ }
72
+ ```
73
+
74
+ 交互式 `/model`、`/effort`、`/login` 和 provider 管理只会修改相关的用户字段,并使用校验后原子替换的方式保存。
75
+
76
+ ## 字段参考
77
+
78
+ ### Model 与 runtime
79
+
80
+ | 字段 | 默认值 | 可接受值 | 说明 |
81
+ | --- | --- | --- | --- |
82
+ | `model.engine` | `forge` | `forge`、`codex` | 交互式模型选择使用 native Forge Engine 或独立 Codex Engine。 |
83
+ | `model.provider` | `deepseek` | `deepseek`、`openai` 或已经配置的 route name | Native Forge Engine provider。自定义 route 必须存在于 `providers`。 |
84
+ | `model.id` | `deepseek-v4-flash` | 非空 model ID | 只选择 `openai` 时默认使用 `gpt-5.4-mini`;自定义 route 使用其第一个 model。 |
85
+ | `model.reasoningEffort` | `medium` | `none`、`minimal`、`low`、`medium`、`high`、`xhigh`、`max`、`ultra` | 实际模型可能只支持子集;`ultra` 只适用于明确公开该能力的 Codex model。 |
86
+ | `model.thinking` | `enabled` | `enabled`、`disabled` | Native provider 的 thinking mode,仍受 provider capability 限制。 |
87
+
88
+ 切换 provider 而没有显式指定 model 时,Forge 会选择该 provider 默认值。推荐通过 `/model` 选择,因为它会展示发现或配置的 capability;reasoning effort 通过 `/effort` 独立修改。
89
+
90
+ ### Permission 与 runtime limits
91
+
92
+ | 字段 | 默认值 | 有效范围 | 含义 |
93
+ | --- | ---: | --- | --- |
94
+ | `permissionProfile` | `safe` | `safe`、`workspace-write` | `safe` 确认首次写入和每条命令;`workspace-write` 自动允许 workspace 文件写入,但命令、网络工具和委派模型运行仍需确认。 |
95
+ | `limits.maxSteps` | `12` | 正整数 | 一次 run 最多 model turns。 |
96
+ | `limits.maxToolCalls` | `40` | 正整数 | 一次 run 最多 proposed tool calls。 |
97
+ | `limits.commandTimeoutMs` | `60000` | 正整数 | 进程命令 duration 上限。 |
98
+ | `limits.maxToolOutputBytes` | `65536` | 正整数 | 单次工具执行最多保留的输出。 |
99
+
100
+ Forge 没有实现 `full-access` profile。获批子进程也没有 OS sandbox,详见安全模型。
101
+
102
+ ### Trace 与 plugins
103
+
104
+ | 字段 | 默认值 | 说明 |
105
+ | --- | --- | --- |
106
+ | `trace.enabled` | `true` | Native Forge Engine 事件写入 `$FORGE_HOME/runs`;Codex Engine 是另一套 runtime,不经过该 trace pipeline。 |
107
+ | `plugins.enabled` | `[]` | `$FORGE_HOME/plugins` 下启用的用户 plugin 名称。项目 plugin 使用 workspace trust,不使用这个列表。 |
108
+
109
+ 用户 plugin 和受信任项目 plugin 都是进程内 JavaScript。Enable/trust 是代码信任决策,不是普通开关;详见插件开发与信任。
110
+
111
+ ### Context budget
112
+
113
+ | 字段 | 默认值 | 有效范围 | 项目 merge 规则 |
114
+ | --- | ---: | --- | --- |
115
+ | `context.mode` | `warn` | `off`、`warn`、`compact` | 项目只能选择更严格模式。 |
116
+ | `context.reservedOutputTokens` | `4096` | 1–2,000,000 | 项目可以增加 reserve。 |
117
+ | `context.bufferTokens` | `8192` | 1–2,000,000 | 项目可以增加 safety buffer。 |
118
+ | `context.recentTailTokens` | `12000` | 0–2,000,000 | 项目可以减少原样保留的近期历史预算。 |
119
+ | `context.summaryTargetTokens` | `1200` | 64–2,000,000 | 项目可以减少 checkpoint target。 |
120
+
121
+ `warn` 会测量并报告压力,但不自动生成 checkpoint;`compact` 允许在实现的预算规则需要时自动生成 checkpoint。`/compact` 始终可作为显式交互操作。无论哪种模式,规范 session transcript 都会独立保留。详见上下文管理。
122
+
123
+ ## 安全的项目配置
124
+
125
+ 仓库可以提交更小、更严格的配置:
126
+
127
+ ```json
128
+ {
129
+ "schemaVersion": 1,
130
+ "limits": {
131
+ "maxSteps": 8,
132
+ "maxToolCalls": 20,
133
+ "commandTimeoutMs": 30000
134
+ },
135
+ "context": {
136
+ "mode": "compact",
137
+ "bufferTokens": 12000,
138
+ "recentTailTokens": 8000
139
+ }
140
+ }
141
+ ```
142
+
143
+ 以下内容会被拒绝,因为仓库不能自行选择 model 或扩大权限:
144
+
145
+ ```json
146
+ {
147
+ "schemaVersion": 1,
148
+ "model": { "provider": "some-endpoint" },
149
+ "permissionProfile": "workspace-write"
150
+ }
151
+ ```
152
+
153
+ ## 环境变量
154
+
155
+ ### 配置选择
156
+
157
+ | 变量 | 用途 |
158
+ | --- | --- |
159
+ | `FORGE_HOME` | 覆盖用户配置、credential、plugin、session 与 trace 根目录。 |
160
+ | `FORGE_PROVIDER` | 选择 `deepseek`、`openai` 或已配置的 provider route。 |
161
+ | `FORGE_MODEL` | 选择 model ID。 |
162
+ | `FORGE_REASONING_EFFORT` | 选择 schema 支持的 reasoning level。 |
163
+ | `FORGE_THINKING` | 选择 `enabled` 或 `disabled`。 |
164
+
165
+ 不存在用于扩大 permission profile 的环境变量。
166
+
167
+ ### Credentials
168
+
169
+ | 变量 | 用途 |
170
+ | --- | --- |
171
+ | `DEEPSEEK_API_KEY` | DeepSeek API 认证。 |
172
+ | `OPENAI_API_KEY` | 按用量计费的 OpenAI API,与 ChatGPT subscription 无关。 |
173
+ | Route 声明变量 | Route 可通过 `auth.apiKeyEnv` 指定,例如 `GATEWAY_API_KEY`。 |
174
+ | `FORGE_<ROUTE>_API_KEY` | Bearer route 没有显式 `apiKeyEnv` 时的推导 fallback;连字符变下划线。 |
175
+
176
+ Credential 环境变量优先于 `$FORGE_HOME/auth.json`,secret value 永远不属于 `config.json`。
177
+
178
+ ### 可选 plugin 网络变量
179
+
180
+ 仓库中的 `web-tools` 示例通过 Forge 共享 HTTP dispatcher 支持 `HTTP_PROXY`、`HTTPS_PROXY` 与 `NO_PROXY`,也支持小写别名。这些变量影响可选网络 plugin,不影响内置 workspace tools。`BRAVE_SEARCH_API_KEY` 只由该示例的搜索 provider 使用。
181
+
182
+ ## OpenAI-compatible routes
183
+
184
+ Provider route 是 user-only 配置,因为它决定 protocol、endpoint 和 credential 绑定。最小本地 route 示例:
185
+
186
+ ```json
187
+ {
188
+ "schemaVersion": 1,
189
+ "providers": {
190
+ "local": {
191
+ "api": "openai-completions",
192
+ "baseUrl": "http://127.0.0.1:11434/v1",
193
+ "auth": { "type": "none" },
194
+ "models": [
195
+ {
196
+ "id": "local-model",
197
+ "contextWindow": 32768,
198
+ "maxOutputTokens": 4096,
199
+ "reasoningGears": false,
200
+ "supportsImages": false
201
+ }
202
+ ]
203
+ }
204
+ }
205
+ }
206
+ ```
207
+
208
+ 支持的 `api` 值、远程 HTTPS 要求、bearer key 绑定、model discovery 限制与 reasoning metadata 见认证模型。
209
+
210
+ ## 常见错误
211
+
212
+ - **修改了错误文件:** 使用 `forge config validate` 查看实际路径,用 `forge config show` 查看来源。
213
+ - **把 user-only 字段放进 `.forge/config.json`:** 把 model、permission、trace、plugin 和 provider 字段移到 `$FORGE_HOME/config.json`。
214
+ - **新增未知字段:** schema version 1 是 strict,拼写错误不会被静默忽略。
215
+ - **把 `reasoningEffort: "none"` 当成 provider default:** 省略才表示 provider default;显式 `none` 只会在 provider mapping 支持时发送。
216
+ - **把 API key 写进配置:** 删除它;若已提交则立即轮换,然后改用 `/login` 或环境变量。
217
+ - **期待 Forge 修改父 shell:** `/logout` 能移除保存的 credential,但不能取消父 shell 导出的环境变量。
218
+
219
+ ## Skill 调用偏好
220
+
221
+ 用户配置可以把 Skill 名称写入 `resources.disabledModelInvocation`。`forge resources disable <name>` 与 `forge resources enable <name>` 会更新这个仅限用户的设置。关闭自动调用不会修改 Skill 或仓库,也不会禁用显式 `$name` 请求;项目配置不能设置 `resources`。