@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,286 @@
1
+ > Forge 可以创建插件。让连接的模型针对你的场景编写插件时,请把本文作为约束和参考。
2
+
3
+ # 插件开发指南
4
+
5
+ English · 中文目录
6
+
7
+ Forge 0.3.2 不依赖插件。插件是可选的进程内 JavaScript module,可以注册模型调用工具和显式本地命令、贡献指令、观察不可变 run event,或让策略更严格。实现中的类型、schema 和 host 才是最终合约:types.ts、schema.ts、host.ts。
8
+
9
+ ## 快速开始
10
+
11
+ 在 `$FORGE_HOME/plugins/count-text/`(通常是 `~/.forge/plugins/count-text/`)创建:
12
+
13
+ ```text
14
+ count-text/
15
+ |-- plugin.json
16
+ `-- index.mjs
17
+ ```
18
+
19
+ `plugin.json`:
20
+
21
+ ```json
22
+ {
23
+ "schemaVersion": 1,
24
+ "apiVersion": "1",
25
+ "name": "count-text",
26
+ "version": "1.0.0",
27
+ "entry": "./index.mjs",
28
+ "capabilities": ["tools:register"]
29
+ }
30
+ ```
31
+
32
+ `index.mjs` 的 activation function 使用 `api.z` 定义有界 schema,并通过 `api.registerTool` 注册。工具应在 `execute` 内再次 `safeParse`,对成功和失败都返回结构化结果,不泄漏 secret:
33
+
34
+ ```js
35
+ export default function activate(api) {
36
+ const inputSchema = api.z.object({ text: api.z.string().max(10000) }).strict();
37
+ api.registerTool({
38
+ name: "count_text",
39
+ description: "Count Unicode characters in supplied text.",
40
+ risk: "read",
41
+ inputSchema,
42
+ execute: async (input) => {
43
+ const parsed = inputSchema.safeParse(input);
44
+ if (!parsed.success) return { ok: false, error: {
45
+ code: "invalid_input", message: "Invalid input for count_text.", retryable: false
46
+ }};
47
+ return { ok: true, output: { characters: Array.from(parsed.data.text).length }, truncated: false };
48
+ }
49
+ });
50
+ }
51
+ ```
52
+
53
+ 在用户配置中启用:
54
+
55
+ ```json
56
+ { "schemaVersion": 1, "plugins": { "enabled": ["count-text"] } }
57
+ ```
58
+
59
+ 然后运行 `forge plugins list` 和 `forge`。蓝色启动 frame 会列出 user plugin、trusted/skipped 项目插件,以及内置、用户和项目 Skills;列表只读 manifest/metadata,不提前 import entry 或 Skill 正文。
60
+
61
+ ## 位置、启用与信任
62
+
63
+ | 范围 | 位置 | 如何可加载 |
64
+ | --- | --- | --- |
65
+ | User | `$FORGE_HOME/plugins/<name>/` | 加入 user `plugins.enabled` |
66
+ | Project | `<workspace>/.forge/plugins/<name>/` | 对规范 workspace 执行 `forge plugins trust` |
67
+
68
+ 项目配置不能设置 `plugins.enabled`;用户配置不能静默信任项目代码。trust 存在仓库外的 `$FORGE_HOME/plugin-trust.json`,key 是规范 workspace path。
69
+
70
+ ```bash
71
+ forge plugins list
72
+ forge plugins trust
73
+ forge plugins trust --yes
74
+ forge plugins untrust
75
+ ```
76
+
77
+ 交互 session 中进入 `/plugins`,检查版本和 capability,按 `t` 后按 `y` 确认;按 `u` 撤销。header 立即更新,新信任的插件在下一次 native Forge Engine task 加载,无需重启 TUI。发现过程不扫描任意祖先、嵌套 plugin 目录或 `node_modules`,也不安装 package 或运行 lifecycle script。
78
+
79
+ ## 插件结构
80
+
81
+ ```text
82
+ my-plugin/
83
+ |-- plugin.json # 声明 metadata,trust/import 前读取
84
+ |-- index.mjs # activation function
85
+ |-- README.md # 推荐的安装和安全说明
86
+ `-- test/ # 可选的插件测试
87
+ ```
88
+
89
+ Entry 可以 import 同目录 `.js`/`.mjs` 文件。Forge 不安装依赖;使用第三方 package 的共享插件必须记录安装方法,不得依赖 package-manager hook 自动执行。
90
+
91
+ ## Manifest v1
92
+
93
+ Manifest 是 strict 的,未知 key 拒绝:
94
+
95
+ | 字段 | 要求 |
96
+ | --- | --- |
97
+ | `schemaVersion` | 数字 `1` |
98
+ | `apiVersion` | 字符串 `"1"` |
99
+ | `name` | 小写 kebab-case,1–64 字符,且等于目录名 |
100
+ | `version` | 非空版本字符串 |
101
+ | `entry` | 位于插件目录内的相对 `.js`/`.mjs`/`.cjs` 路径 |
102
+ | `capabilities` | entry 计划使用的 capability 数组 |
103
+
104
+ 支持的 capability:`tools:register`、`commands:register`、`prompt:contribute`、`subagents:register`、`events:observe`、`policy:restrict`、`network:access`。未声明的 registration method 会拒绝;`network` risk 工具还必须声明 `network:access`。Capability 是 review/API gate,不是 OS sandbox;可信 JavaScript 在 activation 中仍能直接调用 Node.js。
105
+
106
+ ## Activation 与 API
107
+
108
+ Entry 导出 default 或命名 `activate` 函数,可同步或异步,Forge 会在 run 前等待:
109
+
110
+ ```js
111
+ export async function activate(api) {
112
+ // 在这里注册扩展点
113
+ }
114
+ ```
115
+
116
+ 冻结的 `api` 包含:`api.apiVersion`、Forge 的 `api.z`、`api.registerTool`、`api.registerCommand`、`api.registerSubagent`、`api.contributePrompt`、`api.observeRunEvents`、`api.restrictPolicy`。内置和加载插件之间的 registration name 必须唯一。Activation 只做 setup,不应因为 Forge 启动就产生意外写入、网络请求或长时间工作。
117
+
118
+ ## 自定义工具
119
+
120
+ 工具合约是 provider-neutral 的:
121
+
122
+ ```ts
123
+ interface ForgeTool {
124
+ name: string;
125
+ description: string;
126
+ inputSchema: z.ZodType;
127
+ risk: "read" | "write" | "process" | "network" | "model";
128
+ execute(input: unknown, context: ToolContext): Promise<ToolResult>;
129
+ }
130
+ ```
131
+
132
+ 名称使用 lower snake case,匹配 `^[a-z][a-z0-9_]{0,63}$`。description/schema description 会发给模型,需说明何时调用并限制输入。
133
+
134
+ | Risk | 用途 | 默认策略 |
135
+ | --- | --- | --- |
136
+ | `read` | workspace 内、无副作用检查 | Allow |
137
+ | `write` | workspace 文件变化 | `safe` 首次 Confirm;`workspace-write` Allow |
138
+ | `process` | 启动任意子进程 | 每次 Confirm |
139
+ | `network` | 向外部服务发送或抓取数据 | 每次 Confirm |
140
+ | `model` | 启动额外的委派模型运行 | 每次 Confirm |
141
+
142
+ 不能因为动作不修改仓库就把 network/process 标成 read。每个 plugin tool 都走:
143
+
144
+ ```text
145
+ model proposal -> schema validation -> core policy
146
+ -> stricter plugin hooks -> approval -> execute
147
+ -> structured RunEvents -> redacted trace/observers -> tool result
148
+ ```
149
+
150
+ `ToolContext` 包含规范 workspace root/cwd、`AbortSignal` 和 `maxOutputBytes`、`maxEntries`、`commandTimeoutMs` 等严格 limits。及时响应取消,让配置限制优先于插件默认。使用 `invalid_input`、`cancelled`、`io_error`、`output_limit`、`timed_out` 等已有 error code;错误不能包含 credential、authorization header 或私有 response body。
151
+
152
+ ## 其他扩展点
153
+
154
+ ### Subagents
155
+
156
+ `api.registerSubagent()` 是声明式 API:插件只定义角色名、parent tool 名、
157
+ instructions、允许的 child tools 和更严格 limits,不会获得 credential、
158
+ model adapter、runtime、policy 或 trace writer。
159
+
160
+ ```js
161
+ api.registerSubagent({
162
+ name: "code-reviewer",
163
+ toolName: "delegate_code_review",
164
+ description: "Delegate a focused read-only review.",
165
+ instructions: "Report concrete correctness and security findings.",
166
+ tools: ["list_files", "read_file", "search"],
167
+ limits: { maxModelSteps: 4, maxToolCalls: 8 }
168
+ });
169
+ ```
170
+
171
+ Manifest 必须声明 `subagents:register`。角色名使用 kebab-case,tool 名使用
172
+ lower snake case,并与内置/插件工具共享名称空间。instructions 必填且最多
173
+ 16 KiB;最多选择 32 个不重复、已经注册的非 subagent 工具;单个 child
174
+ 最多 8 model steps 和 20 tool calls。
175
+
176
+ 宿主生成的工具接收 `{ task: string }`,属于 `model` risk,每次委派都需审批。
177
+ Forge 创建新 adapter 和隔离对话,继承项目指令、workspace、context 设置、
178
+ cancel、approval channel,以及 core + plugin restrictions 后的有效 policy,
179
+ 并且只暴露声明的工具。Child 永远看不到 subagent tools,因此不能递归委派。
180
+
181
+ 每个 parent run 最多启动四个 child;所有 child 还共享与 parent 配置
182
+ `maxSteps`/`maxToolCalls` 相等的预算,插件 limits 只能进一步收紧。返回值受
183
+ `maxToolOutputBytes` 约束。启用 trace 时,每个 child 使用独立 run trace,
184
+ envelope 包含 `parentRunId`/`subagentName`;parent tool result 包含 child
185
+ `runId`、status、step/tool 计数和 final text。
186
+
187
+ 示例见 `examples/plugins/code-review-subagent`。
188
+
189
+ ### Commands
190
+
191
+ Command 是显式的 trusted-code entry point,不是 model tool call:
192
+
193
+ ```js
194
+ api.registerCommand({
195
+ name: "hello",
196
+ description: "Print a local greeting.",
197
+ execute: async ({ args, write }) => { write(`hello ${args.join(" ") || "world"}\n`); return 0; }
198
+ });
199
+ ```
200
+
201
+ 用 `forge plugins run hello [args...]` 执行。Command 因用户直接调用而绕过 model-tool approval,但仍拥有受信任插件的完整进程权限。
202
+
203
+ ### Prompt contribution
204
+
205
+ `api.contributePrompt(hook)` 收到包含当前 prompt、规范 workspace root 和 cwd 的 immutable snapshot。返回字符串最多 32 KiB,标记 manifest path,加入 instruction context 并记录 provenance;不需要贡献时返回 `undefined`。用户 prompt 是不可信数据,prompt hook 不能暗中作为 command runner。
206
+
207
+ ### Run-event observer
208
+
209
+ `api.observeRunEvents(observer)` 收到每个 `RunEvent` 的深冻结 structured clone,不能修改 runtime history。observer 失败只产生 warning,不替换 run result 或 trace;配置 secret 会在送给 observer 前脱敏。
210
+
211
+ ### Policy restriction
212
+
213
+ `api.restrictPolicy(hook)` 收到 tool、call 和 validated input 的 frozen snapshot,只能返回:
214
+
215
+ ```js
216
+ { kind: "confirm", reason: "..." }
217
+ { kind: "deny", reason: "..." }
218
+ undefined
219
+ ```
220
+
221
+ 决策合并为 `deny > confirm > allow`;插件不能把 core confirmation/denial 变为 allow。
222
+
223
+ ## 发现与 run 生命周期
224
+
225
+ Native Forge Engine 对每个 prompt:校验配置;加载有界 user/project 指令;发现内置、用户和项目 Skill metadata、处理冲突并保留 `$skill-name` override;发现 manifest;排除 disabled user plugin 和 untrusted project plugin;解析目录内 entry 并 import;activation 后校验 registration/capability/name conflict;收集有界 prompt contribution;构造 model request 和 tool registry;最后让每个工具经过 policy、审批、执行、event 和 trace。
226
+
227
+ 交互启动 frame 只做到 metadata discovery;真正 import/activation 只在 Forge Engine 开始 run 时发生。Codex Engine 由 Codex App Server 拥有自己的 runtime,不加载 Forge plugin。
228
+
229
+ ## Portable Skills 的区别
230
+
231
+ Forge 在随包内置目录、`$FORGE_HOME/skills/<skill-name>/SKILL.md` 和 `<workspace-root>/.agents/skills/<skill-name>/SKILL.md` 发现 Markdown Skill。每个文件用有界 YAML frontmatter 声明与目录匹配的 `name`、面向任务的 `description`,可用 `disable-model-invocation: true` 设为仅显式调用。
232
+
233
+ 首个模型请求只包含有预算上限的 `id`、`name`、`description` 和 `source`;正文由宿主 `load_skill` 工具按登记的不透明 ID 延迟加载。工具限制并去重加载,重新校验 canonical path 与文件身份,拒绝 symlink 和登记 root 外文件。名称冲突按 `project > user > builtin` 解析,显式 `$skill-name` 覆盖自动路由。选择、加载、拒绝和截断都会进入 trace,并可由 `forge inspect` 查看。Skill 描述的动作仍需正常 model tool、policy、approval 和 trace;选择 Skill 不等于信任项目 plugin,也不会扩大 workspace `read_file`。
234
+
235
+ ## 测试插件
236
+
237
+ 测试不能依赖付费模型或真实外部服务,应使用 fake transport,并尽量通过真实 host/policy boundary:
238
+
239
+ ```bash
240
+ forge plugins list
241
+ pnpm typecheck
242
+ pnpm test
243
+ pnpm check
244
+ ```
245
+
246
+ 项目插件先 inspect manifest,再显式 `forge plugins trust`,用最小安全任务运行,最后 `forge plugins untrust`。用户插件测试可将 `FORGE_HOME` 指向临时目录且只启用该插件。至少覆盖 manifest discovery(不 import entry)、activation/名称/capability、输入和取消、output/entry/timeout limits、相关 policy、secret 脱敏,以及无需 live network 的可恢复 provider failure。
247
+
248
+ ## Web tools 示例
249
+
250
+ `examples/plugins/web-tools` 是无依赖的插件测试示例,注册 `web_search`(有 `BRAVE_SEARCH_API_KEY` 时使用 Brave,否则使用 DuckDuckGo 非 JS HTML)和 `web_fetch`(提取有界的公开 HTTP(S) 文本)。两者都是 `network` risk,每次调用需审批;共享 HTTP transport 遵循 `HTTP_PROXY`、`HTTPS_PROXY` 和 `NO_PROXY`。示例检查 redirect、local/private/reserved 地址、端口、MIME、时间、下载量、字符数和输出大小,但这些不是网络 sandbox,配置的 proxy 也属于 trust boundary。
251
+
252
+ ## MCP、to-dos 与 subagents
253
+
254
+ | 能力 | 当前插件 API | 示例或限制 |
255
+ | --- | --- | --- |
256
+ | MCP server tools | 可以,但协议与生命周期有限 | `mcp-stdio` 为一个配置的 stdio server 注册需审批的 `process` risk list/call bridge。 |
257
+ | 轻量 to-dos | 可以 | `todos` 注册内存工具和有界 prompt contribution;目前没有持久化和自定义 TUI panel。 |
258
+ | 宿主管理的 subagents | 可以 | `code-review-subagent` 声明只读 child 角色;Forge 持有 adapter、policy、budget、cancel 和关联 trace。 |
259
+
260
+ MCP 示例固定演示基于 session、newline-delimited stdio 的 `2025-11-25`
261
+ 协议版本,只证明现有插件能够桥接 MCP tools,不代表 Forge 已具备完整 MCP host。
262
+ Streamable HTTP、当前无握手协议、server reuse、prompts/resources/roots、
263
+ sampling、tasks 和 lifecycle disposal 需要一等 host 或扩展后的插件合约。
264
+
265
+ Subagent 当前继承 parent model;插件不能选择不同 provider/model、传入 parent
266
+ conversation、把 child 保存为可独立 resume 的 session、在专用 TUI panel
267
+ 流式显示 child delta,或开启嵌套委派。这些仍是明确的宿主限制,插件不应
268
+ 通过直接调用 provider 或递归启动 Forge CLI 来模拟。
269
+
270
+ ## 给模型作者的步骤
271
+
272
+ 写插件前阅读全文和当前 types/schema/host;按用户意图选择 user/project scope;只声明最小 capability;优先 plain ESM、`api.z` 和无依赖实现;在 execute 内再次校验;选择诚实 risk 并限制所有输入输出;activation 不做意外副作用;用 fake I/O 写确定性测试;运行 format、typecheck、目标测试和全量测试;记录安装方式、环境变量、外发数据、安全控制和限制,不声称有 sandbox。
273
+
274
+ 交付前检查目录名等于 manifest name、版本受支持、entry 留在插件目录、使用的 API/capability 已声明、名称不冲突、错误无 secret、输出大小在序列化后测量、trust 前不执行项目代码,并在文档中区分 discovery、enablement、trust、activation 和 tool-call approval。
275
+
276
+ ## 安全边界与限制
277
+
278
+ 加载插件会执行拥有 Forge 进程完整权限的本地代码;它可以直接 import Node、读任意文件、启动进程或联网。Forge 只在支持的 API 边界执行:trust 前不 import 项目 entry;校验 manifest/API/capability/name/schema;model 调用的 plugin tool 走 core policy/approval;model/network/process/相关 write 需确认;policy hook 只能更严格;prompt/Skill 有界且带来源;observer input clone/freeze/脱敏。
279
+
280
+ 这些保证不隔离恶意 trusted entry,强隔离需要受限进程或 OS sandbox。Forge 0.3.2 没有插件安装器、依赖解析器、registry、hot reload、TypeScript entry 编译、custom interactive UI、provider registration、隔离进程或可强制执行的 filesystem/network capability;plugin command 只通过 `forge plugins run` 执行,不自动成为交互 slash command。
281
+
282
+ ## Skills 与产品文档属于资源
283
+
284
+ Skills 是从内置、用户和项目作用域发现的不可执行、不可信指令资源。`forge plugins list` 只报告可执行插件;`forge resources list` 报告 Skill 来源、调用状态、冲突遮蔽与诊断。交互式入口分别是 `/plugins` 与 `/resources`。
285
+
286
+ 内置 `forge-product-help` Skill 要求在回答实现相关产品问题前先检索文档。`search_forge_docs` 和 `read_forge_doc` 使用与版本匹配的打包白名单及稳定的 `forge-doc:<version>:<locale>:<document>#<section>` 引用;它们拒绝文件系统路径,也不继承 `read_file` 权限。
@@ -0,0 +1,86 @@
1
+ # 产品定义
2
+
3
+ English · 中文目录 · 根 README
4
+
5
+ ## 摘要
6
+
7
+ Forge 是一个面向学习和作品集展示的 TypeScript coding agent。它不是一个“只要能调用工具就算完成”的 demo,而是一个可以检查、约束、测量和复盘的最小运行时。
8
+
9
+ Forge 负责模型循环、工具执行、审批策略、上下文、会话和 trace;provider adapter 负责协议转换;CLI 负责交互和展示。这样既能使用成熟 SDK,又能保留 agent 的关键工程边界。
10
+
11
+ ## 目标用户
12
+
13
+ ### 主要用户
14
+
15
+ - 正在学习 agent runtime、tool calling、安全边界和评测的开发者。
16
+ - 希望从小型、可运行系统理解 coding-agent 工程的面试官或导师。
17
+ - 需要在本地仓库中使用可检查、可审批工作流的个人开发者。
18
+
19
+ ### 次要用户
20
+
21
+ - 想比较 provider、模型和 agent-loop 行为的实验者。
22
+ - 希望通过插件扩展工具但不绕过核心策略的项目作者。
23
+
24
+ ## 核心用例
25
+
26
+ 给 Forge 一个小型仓库任务,例如“修复失败测试并验证结果”。Forge 应当:
27
+
28
+ 1. 读取当前配置和适用的项目指令。
29
+ 2. 让模型选择下一步,并通过工具检查相关代码。
30
+ 3. 在每个工具调用前执行 `allow`、`confirm` 或 `deny` 策略。
31
+ 4. 在获批后修改代码并运行受限的验证命令。
32
+ 5. 根据真实的命令结果继续修复,而不是相信模型的乐观总结。
33
+ 6. 以真实状态、diff 和 trace 结束,或说明为什么无法完成。
34
+
35
+ ## 产品原则
36
+
37
+ ### 透明
38
+
39
+ 终端应展示有意义的模型和工具活动。只有 provider 实际返回的 reasoning 才能展示或持久化;如果 provider 没有返回,Forge 不会伪造或暗示自己看到了隐藏思维过程。结构化 trace 保留可观察的执行轨迹。
40
+
41
+ ### 默认安全
42
+
43
+ 文件工具默认限制在选定 workspace 内,命令和执行时间有边界,高风险操作需要审批。非交互模式没有匹配的预先审批时必须拒绝需要审批的操作。
44
+
45
+ ### 可验证
46
+
47
+ 合理的最终文字不是完成证明。任务可以由测试、类型检查、lint 或其他确定性检查验证时,Forge 应执行检查并报告真实结果。
48
+
49
+ ### 理解框架,但不被框架拥有
50
+
51
+ Forge 可以使用成熟库消除偶然复杂度,但核心运行时概念必须保持可见、可独立测试。
52
+
53
+ ### 扩展不能削弱保护
54
+
55
+ 插件可以添加工具、命令、prompt 贡献和受控生命周期 hook,但不能把核心 `deny` 变为 `allow`,绕过审批或替换策略内核。进程内插件仍是本地代码,需要明确的信任决定。
56
+
57
+ ### 先小后广
58
+
59
+ 一个狭窄但可靠的工作流,比许多未完成的功能更有价值。
60
+
61
+ ## 初始功能
62
+
63
+ - TypeScript CLI 和多行交互式终端。
64
+ - 斜杠命令发现、workspace 文件引用和可读的 diff 审查。
65
+ - 以 `DEEPSEEK_API_KEY` 认证的 DeepSeek provider。
66
+ - 通过 Vercel AI SDK 和 `@ai-sdk/deepseek` 流式输出。
67
+ - 有明确停止条件的多步骤 agent 循环。
68
+ - `~/.forge/config.json` 用户级配置和分层 `AGENTS.md` 指令。
69
+ - `forge config show` 可检查配置来源。
70
+ - 列出、读取、搜索、补丁和运行命令工具。
71
+ - workspace 路径校验、命令超时和取消。
72
+ - 敏感操作审批、provider reasoning 展示、结构化事件和 JSONL trace。
73
+ - 可在重启后恢复的本地会话。
74
+ - runtime/tool 自动化测试、规范 fixture、确定性恢复场景和可复现发布评测。
75
+
76
+ ## v0.1 成功标准
77
+
78
+ 详细 gate 见 v0.1 验收与评测。一次完整仓库任务至少要:读取多个相关文件、进行定向修改、运行自动验证、证明失败恢复、在成功或限制后停止、拒绝 workspace 外文件操作、生成与真实行为一致的 trace 和总结。
79
+
80
+ ## v0.1 不在范围内
81
+
82
+ 多 Agent 协作、图形或 IDE 界面、远程执行、持久语义记忆、RAG、MCP server 发现、第三方插件安装、自动 commit/push/PR,以及生产级 OS sandbox 都不属于 v0.1。
83
+
84
+ ## 后续作品集方向
85
+
86
+ Native runtime 稳定后,可考虑更大的评测套件、OpenAI API key、在适当公开集成支持下的 ChatGPT 登录、LangChain/LangGraph adapter、带 SSE 和人工审批的 HTTP API,以及 SQLite 索引和会话分支。这些是后续扩展,不是开始实现的前置条件。
@@ -0,0 +1,130 @@
1
+ # 项目上下文与本地定制
2
+
3
+ English · 中文目录
4
+
5
+ ## 目标
6
+
7
+ Forge 能理解仓库特定指令和可复用 Agent 资源,但不会把仓库内容变成隐式权限授予。它刻意区分以下约定:
8
+
9
+ | 位置 | 用途 | 是否可自行执行 |
10
+ | --- | --- | --- |
11
+ | `AGENTS.md` | 可移植、面向人的项目指令 | 否 |
12
+ | `.agents/` | 与 Agent 无关的可复用资源,如 skills | 否 |
13
+ | `~/.forge/` | 用户级 Forge 设置、指令、状态和插件 | 插件是代码 |
14
+ | `<workspace-root>/.forge/` | Forge 项目设置和插件 | 插件是代码 |
15
+
16
+ 仓库指令可以影响模型处理任务的方式,但不能削弱策略内核、审批动作、选择 `full-access`,或绕过工具的审批和 trace 流程。
17
+
18
+ ## `AGENTS.md`
19
+
20
+ Forge 使用大写文件名 `AGENTS.md`;大小写敏感文件系统上的 `agents.md` 不是别名。也支持目录级的更具体替换文件 `AGENTS.override.md`。
21
+
22
+ 当 working directory 位于 Git 仓库内时,Forge 会:
23
+
24
+ 1. 解析规范 repository root。
25
+ 2. 从 root 走到本次 run 的 working directory。
26
+ 3. 每个目录最多加载一个非空指令文件,优先 `AGENTS.override.md`。
27
+ 4. 从 root 到 leaf 合并,越近的文件优先级越高。
28
+ 5. 将所有加载路径写入 run trace。
29
+
30
+ 发现发生在 run 开始时,并有单文件和总字节限制;被忽略或截断的文件必须报告,不能静默改变最终 prompt。这些文件是 prompt 输入而非可信 policy;例如“所有命令无需询问”不会改变审批策略。
31
+
32
+ ## `.agents/`
33
+
34
+ `.agents/` 是可移植资源命名空间,首个支持布局为:
35
+
36
+ ```text
37
+ .agents/
38
+ `-- skills/
39
+ `-- <skill-name>/
40
+ `-- SKILL.md
41
+ ```
42
+
43
+ Skill 是被发现的 metadata 和指令;仅仅存在不会执行它。Forge 解析有界 YAML frontmatter(`name`、面向任务的 `description` 和可选 `disable-model-invocation`),初始只发送转义后的 catalog metadata;匹配后由宿主按不透明 ID 延迟加载。项目 Skill 默认允许模型调用且无需 plugin trust;`disable-model-invocation: true` 只允许用户显式 `$skill-name` 选择。内置、`$FORGE_HOME/skills/` 用户 Skill 与项目 Skill 冲突时按 `project > user > builtin` 解析,并把来源、选择、加载、拒绝和截断写入 trace。
44
+
45
+ ## 用户级 `~/.forge/`
46
+
47
+ 默认 user home 是 `~/.forge/`;`FORGE_HOME` 可用于便携安装、测试或托管环境覆盖它:
48
+
49
+ ```text
50
+ ~/.forge/
51
+ |-- config.json
52
+ |-- AGENTS.md
53
+ |-- skills/
54
+ |-- plugin-trust.json
55
+ |-- plugins/
56
+ |-- state/
57
+ |-- sessions/
58
+ `-- runs/
59
+ ```
60
+
61
+ - `config.json`:provider、model、limits、context、trace 和默认 permission profile。
62
+ - `AGENTS.md`:在项目指令前加载的用户级指令。
63
+ - `skills/`:用户级非执行型 Skill,只发现有界 metadata,正文延迟加载。
64
+ - `plugins/`:明确安装或启用的用户插件。
65
+ - `state/`:不含 secret 的 Forge 状态,如项目信任决定。
66
+ - `sessions/`:版本化完成对话 snapshot。
67
+ - `runs/`:启用 trace 持久化时的本地 trace。
68
+
69
+ Forge 可以创建缺少的运行时目录,但不能覆盖已有配置文件。API key 和 OAuth token 不属于 `config.json`,应使用环境变量或认证模型中的 credential store。
70
+
71
+ ### 配置 schema
72
+
73
+ `@forge/config` 中的 Zod schema 是可执行真相。每个字段、默认值、有效范围、环境 override、provider route 示例与 merge rule 请看配置参考。
74
+
75
+ 安全相关摘要如下:
76
+
77
+ | Scope | 可以配置 | 不得配置 |
78
+ | --- | --- | --- |
79
+ | 用户 `$FORGE_HOME/config.json` | Model、engine、provider routes、permission profile、limits、trace、plugins、context | API key 或 OAuth credential |
80
+ | 项目 `.forge/config.json` | 更严格的 `limits` 与 `context` | Model/provider、permissions、trace、plugin enablement、routes、secrets |
81
+ | Environment | `FORGE_PROVIDER`、`FORGE_MODEL`、`FORGE_REASONING_EFFORT`、`FORGE_THINKING` 和 credential variables | Permission widening |
82
+ | 显式 CLI | Command 支持的 model、permission、limit 与 context override | 通过参数持久化 repository trust 或 secret |
83
+
84
+ 未知字段会报错而不是忽略。`FORGE_HOME` 在加载配置前改变发现位置,不存在能扩大 permission profile 的环境变量。`forge config show` 展示每个有效值及来源;`forge config validate` 只做本地校验,不启动 Agent run。
85
+
86
+ ## 项目级 `.forge/`
87
+
88
+ 选定 workspace root 的 `.forge/` 专用于项目定制:
89
+
90
+ ```text
91
+ .forge/
92
+ |-- config.json
93
+ `-- plugins/
94
+ `-- <plugin-name>/
95
+ |-- plugin.json
96
+ `-- index.mjs
97
+ ```
98
+
99
+ “项目本地”只指选定 workspace root 的规范 `.forge/`。Forge 不搜索任意父目录或嵌套目录的额外 plugin tree,以保持从仓库子目录启动时的发现稳定。
100
+
101
+ 项目配置可以选择 model-independent 行为、格式和更严格 limits,但不能放宽用户 profile 或核心安全策略。默认 profile、plugin enablement 和 project trust 等敏感字段只能由用户控制。未知 key 和不支持的 schema version 必须给出可操作诊断。
102
+
103
+ 项目插件是受信任的可执行代码。Forge 在加载前发现并概览,再要求针对规范 workspace 的显式 trust;trust 存储在仓库外。非交互模式跳过未信任项目插件。`forge plugins trust --yes` 会在项目外记录 trust。发现阶段不会自动安装依赖,也不会运行 package-manager lifecycle script。
104
+
105
+ ## 优先级
106
+
107
+ 普通设置的来源顺序为:
108
+
109
+ ```text
110
+ 内置默认 < ~/.forge/config.json < project .forge/config.json
111
+ < environment variables < 显式 CLI flags
112
+ ```
113
+
114
+ 每个配置值保留来源 metadata,供 `forge config show` 和 run trace 解释。schema 按范围分类:user-only 安全设置拒绝项目值,安全 limits 使用更严格值而不是简单的 last-writer-wins。
115
+
116
+ 安全和指令的优先级不同:
117
+
118
+ ```text
119
+ 安全决策:deny > confirm > allow(最严格的贡献获胜)
120
+ 指令:用户请求 > loaded skill > 最近的 project AGENTS.md
121
+ > project-root AGENTS.md > ~/.forge/AGENTS.md
122
+ ```
123
+
124
+ Skill 名称冲突使用独立资源顺序:`显式 $skill-name > project > user > builtin`。
125
+
126
+ 核心 policy 定义强制安全底线。CLI 和 user config 可以选择受支持 profile;项目内容和插件只能让动作更严格,不能降低强制决策。指令顺序只在不违反安全边界和更高层 runtime 约束时生效。
127
+
128
+ ## 延后决定
129
+
130
+ 配置迁移(schema v1 以后)、更多环境变量映射、Skill manifest/兼容规则、受限插件是否使用子进程或 OS sandbox,均在对应 milestone 需要时决定。
@@ -0,0 +1,86 @@
1
+ # npm 发布指南
2
+
3
+ English · 中文文档目录
4
+
5
+ Forge 保持内部实现 package 私有,只发布一个面向用户的
6
+ `@jslee124/forge`。生成物包含 CLI、已 bundle 的 `@forge/*` workspace
7
+ 实现,以及经过审核且版本匹配的内置 Skill 资源;第三方库仍是普通 npm
8
+ runtime dependencies。插件 SDK 暂不作为独立 package 发布。
9
+
10
+ ## 分发合约
11
+
12
+ - 安装:`npm install --global @jslee124/forge`
13
+ - 命令:`forge`
14
+ - 稳定 npm tag:`latest`
15
+ - 预发布 npm tag:`next`
16
+ - Runtime:Node.js 24 或更高版本
17
+ - 生成目录:`dist/npm/forge`
18
+
19
+ 源码中的 `apps/cli` 继续保持 private。`pnpm build:package` 只在被忽略的
20
+ `dist/npm/forge` 中生成公共 manifest 和 bundle,避免开发文件意外进入
21
+ registry。
22
+
23
+ ## 准备 release
24
+
25
+ 从干净 checkout 开始,并选择 SemVer:
26
+
27
+ ```bash
28
+ pnpm version:set 0.3.0
29
+ pnpm install --frozen-lockfile
30
+ pnpm check
31
+ pnpm check:docs
32
+ pnpm test
33
+ pnpm eval:deterministic
34
+ pnpm package:verify
35
+ pnpm release:verify-tag v0.3.0
36
+ ```
37
+
38
+ `package:verify` 会构建公共产物、检查 tarball、在全新临时 prefix 中禁用
39
+ lifecycle scripts 后安装,核对内置 Skill/reference/template allowlist 与
40
+ API version,并验证 `forge --version`、`forge --help` 和 `forge config validate`。
41
+
42
+ 打 tag 前必须检查 pack 内容和 release notes。API key、auth 文件、本地
43
+ trace、`.env` 以及未经脱敏审核的 evaluation artifact 都不能发布。
44
+
45
+ ## 首次发布到 npm
46
+
47
+ npm 账号或组织必须拥有 `@jslee124` scope,并启用 2FA。npm package 存在后
48
+ 才能配置 trusted publisher,因此先用经过审核的预发布版本(例如
49
+ `0.3.0-bootstrap.0`)和非稳定 dist-tag 创建 package,再把仓库中的
50
+ `publish.yml` 配置为 GitHub Actions trusted publisher。bootstrap 版本不要
51
+ 放入 `latest`。
52
+
53
+ trusted publishing 配置完成后,稳定版本只由 tag workflow 发布。它使用
54
+ OIDC,不保存长期 npm token,并在所有 release gate 通过后发布生成 package。
55
+
56
+ ## 发布稳定版本
57
+
58
+ 提交版本、release notes 和构建输入,然后创建不可移动的 annotated tag:
59
+
60
+ ```bash
61
+ git tag -a v0.3.0 -m "Forge v0.3.0"
62
+ git push origin v0.3.0
63
+ ```
64
+
65
+ `Publish npm package` workflow 会先确认 Git tag、根版本、私有 workspace
66
+ 版本、runtime 版本和生成 npm package 完全一致,然后运行
67
+ `npm publish --access public`。
68
+
69
+ 预发布版本才使用 `npm publish --tag next`。不要移动已经发布的 Git tag,
70
+ 也不要复用 npm 版本。错误 release 应通过新的 patch 版本修复,并保留旧版本
71
+ 供用户回滚。
72
+
73
+ ## 用户更新
74
+
75
+ 用户可以显式检查或安装更新:
76
+
77
+ ```bash
78
+ forge update check
79
+ forge update
80
+ forge update 0.3.2
81
+ ```
82
+
83
+ 交互启动最多每 24 小时在后台刷新一次提示性 npm 检查,并在后续启动显示缓存
84
+ 结果;绝不会因为启动而安装更新。设置 `FORGE_DISABLE_UPDATE_CHECK=1` 可以关闭
85
+ 启动检查。显式更新命令会先把 npm metadata 解析为精确 SemVer,再执行禁用
86
+ lifecycle scripts 的全局 npm 安装。