@deepseek-ai/dsh-experimental-forge 0.0.0-stage → 0.2.2-alpha.3
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.
- package/LICENSE +21 -0
- package/README.i18n.yaml +37 -0
- package/README.md +103 -2
- package/README.zh.md +104 -0
- package/lib/index.js +537 -0
- package/lib/types/index.d.ts +185 -0
- package/lib/types/keys.d.ts +10 -0
- package/lib/types/schedule.d.ts +22 -0
- package/lib/types/types.d.ts +226 -0
- package/locale/de.json +6 -0
- package/locale/en.json +6 -0
- package/locale/es.json +6 -0
- package/locale/fr.json +6 -0
- package/locale/ja.json +6 -0
- package/locale/pt.json +6 -0
- package/locale/ru.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +42 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeepSeek
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
2
|
+
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
3
|
+
# After editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/experimental/forge/README.md
|
|
5
|
+
/:
|
|
6
|
+
en: 58d73ee11cb9ecde
|
|
7
|
+
zh: 04213727345a58a2
|
|
8
|
+
/deepseek-ai-dsh-experimental-forge:
|
|
9
|
+
en: cf24b0ee1e2732e8
|
|
10
|
+
zh: bb4e76d2b69b84d8
|
|
11
|
+
/deepseek-ai-dsh-experimental-forge/summary:
|
|
12
|
+
en: 2d79427980c092c3
|
|
13
|
+
zh: ee18048c6cc0aeec
|
|
14
|
+
/deepseek-ai-dsh-experimental-forge/table-of-contents:
|
|
15
|
+
en: d152484eb41ac6b4
|
|
16
|
+
zh: 2f8a621b991260a1
|
|
17
|
+
/deepseek-ai-dsh-experimental-forge/use-this-package:
|
|
18
|
+
en: 9ca86ee541048ff2
|
|
19
|
+
zh: 7aef4feb76542dd6
|
|
20
|
+
/deepseek-ai-dsh-experimental-forge/understand-the-implementation:
|
|
21
|
+
en: e193cb547c47069b
|
|
22
|
+
zh: faa517522402ea41
|
|
23
|
+
/deepseek-ai-dsh-experimental-forge/further-exploration:
|
|
24
|
+
en: bb13125144d413d5
|
|
25
|
+
zh: a6832dad7a093bfe
|
|
26
|
+
/deepseek-ai-dsh-experimental-forge/model-experience:
|
|
27
|
+
en: a62b9af05181f74f
|
|
28
|
+
zh: 64b8b0aa18c64c57
|
|
29
|
+
/deepseek-ai-dsh-experimental-forge/model-experience/kv-cache-effect:
|
|
30
|
+
en: 1675c9fcae96936c
|
|
31
|
+
zh: 5cd2a82aeca3160a
|
|
32
|
+
/deepseek-ai-dsh-experimental-forge/known-limitations-and-deferred-work:
|
|
33
|
+
en: 0721de59f78c48e6
|
|
34
|
+
zh: 094ca6e3bba766ba
|
|
35
|
+
/deepseek-ai-dsh-experimental-forge/known-limitations-and-deferred-work/dev-note:
|
|
36
|
+
en: e67f633dc6fe7773
|
|
37
|
+
zh: 3bb0c20c93f16f98
|
package/README.md
CHANGED
|
@@ -1,3 +1,104 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "Register code host providers and poll change request status through one provider-neutral service."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
# @deepseek-ai/dsh-experimental-forge
|
|
7
|
+
|
|
8
|
+
English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
Read and act on pull requests and merge requests without coupling consumers to one code host. A provider maps remote and change request URLs to provider-neutral references, finds change requests by head branch, reads their status in batches, reads their diffs and files, and marks drafts ready or merges on request. Watchers of one change request share a single polling loop whose cadence follows check, mergeability, and lifecycle state.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
Mount the registry with at least one provider package, such as the GitHub provider.
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
- name: '@deepseek-ai/dsh-experimental-forge'
|
|
32
|
+
- name: '@deepseek-ai/dsh-experimental-forge-github'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`ctx.forge.register(provider)` is an effect on the calling fiber and returns an async disposer that cancels and drains that registration's calls. Results arriving after cancellation are discarded. One provider serves one forge family; registering a second provider for the same family throws. Registration changes announce `forge/providers-changed`; registering a provider polls its existing watches immediately. `repositoryFromRemote(url)` and `changeRequestFromUrl(url)` ask providers in registration order and return the first match. `changeRequestUrl(ref)`, `findByHead(repository, branch, signal)`, and `readiness(repository, signal)` delegate to the provider of the reference's forge and throw when none is registered; `readiness` reports whether the provider can reach the host with current credentials.
|
|
36
|
+
|
|
37
|
+
`markReady(ref, signal)` marks a draft ready for review, and `merge(ref, { method, headSha }, signal)` merges a change request only while its head is still `headSha`. Both delegate to the provider of the reference's forge, throw when none is registered, and resolve to undefined once the host accepted the change or to a `ForgeActionFailure`: `unauthenticated`, `stale` when the head moved past `headSha`, or `failed` with the host's reason. After either settles, a watched change request is polled at once. Snapshots carry `mergeReady`, whether the host would merge the change request now for the signed-in user, and `mergeMethods`, the methods the repository accepts with that user's usual one first.
|
|
38
|
+
|
|
39
|
+
`diff(ref, signal)` reads the change request's unified patch as the host computes it, with `a/` and `b/` path prefixes, and `fileText(ref, commit, path, signal)` reads one file of its repository at a commit. Both delegate to the provider of the reference's forge, throw when none is registered, and resolve to the text or to a `ForgeFailure`, which is `too-large` when the host or the provider refuses an answer over its size limit. `fileUrl(ref, commit, path)` returns the web page of that file at that commit.
|
|
40
|
+
|
|
41
|
+
`fetchChecks(ref, signal)` reads one change request’s complete checks on demand. It has its own `fetchTimeoutMs` deadline and does not occupy the polling batch or publish to its watchers. Failure leaves previously polled snapshots intact. A provider without `fetchChecks` returns `unavailable`. Caller cancellation and provider or service disposal abort the read; disposal waits for it to settle.
|
|
42
|
+
|
|
43
|
+
`ctx.forge.watch(ref, listener)` is also an effect. The first watcher of a change request polls it at once; `latest(ref)` returns the most recent result. Each forge has at most one polling fetch in flight, and that fetch includes every due change request of the forge. An open change request is polled every `activeIntervalMs` while checks are pending or mergeability is unknown, and every `idleIntervalMs` otherwise. Closed change requests use `idleIntervalMs` to detect reopening; merged requests stop automatic polling. `refresh(ref)` polls a watched change request at once, including after a terminal state; if a fetch is already in flight for its forge, another fetch starts immediately after it settles. A failed read repeats after `activeIntervalMs` doubled for each consecutive failure, up to `maxBackoffMs`, which must be at least `activeIntervalMs`. Unregistering a provider settles its watched change requests as `unavailable`. Polling stops when the last watcher leaves. The [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-experimental-forge) lists the defaults.
|
|
44
|
+
|
|
45
|
+
Reaching `fetchTimeoutMs` aborts the fetch signal with `FORGE_FETCH_TIMEOUT`. Providers must stop their work and settle when the signal aborts; rejected fetches become `unavailable` failures. A provider that ignores cancellation can stall polling and service disposal.
|
|
46
|
+
|
|
47
|
+
Providers may implement `submitReview` to publish a line comment or a completed review at an explicit head commit. The registry returns unsupported when that capability is absent and refreshes watched status after a submission. Successful writes return their web URL; failures distinguish changed heads, refusals, and unknown outcomes. Callers must reconcile unknown outcomes before another submission. Pending drafts belong to the consumer, not the polling registry.
|
|
48
|
+
|
|
49
|
+
-----
|
|
50
|
+
|
|
51
|
+
<a id="understand-the-implementation"></a>
|
|
52
|
+
## Understand the implementation
|
|
53
|
+
|
|
54
|
+
<details>
|
|
55
|
+
<summary>Implementation internals — click to expand</summary>
|
|
56
|
+
|
|
57
|
+
One timer covers all watched change requests. When it fires, the service groups due change requests by forge and starts one batched provider fetch per idle forge. A listener that throws is logged and skipped. Disposing the service aborts in-flight fetches and waits for them to settle.
|
|
58
|
+
|
|
59
|
+
| Source | Responsibility |
|
|
60
|
+
|---|---|
|
|
61
|
+
| [`src/index.ts`](src/index.ts) | Provider registration, URL mapping, watch lifetime, and batched polling |
|
|
62
|
+
| [`src/schedule.ts`](src/schedule.ts) | Delay before the next poll of one change request |
|
|
63
|
+
| [`src/keys.ts`](src/keys.ts) | Case-insensitive canonical identity of a change request |
|
|
64
|
+
| [`src/types.ts`](src/types.ts) | Repository, change request, status, and provider types |
|
|
65
|
+
|
|
66
|
+
</details>
|
|
67
|
+
|
|
68
|
+
-----
|
|
69
|
+
|
|
70
|
+
<a id="further-exploration"></a>
|
|
71
|
+
## Further Exploration
|
|
72
|
+
|
|
73
|
+
- [Forge subsystem](../../../docs/subsystems/forge.md) — provider contract, change request types, and service reference.
|
|
74
|
+
- [GitHub provider](../forge-github/README.md) — the provider for GitHub hosts.
|
|
75
|
+
- [Session bindings](../forge-session/README.md) — the consumer that binds change requests to Sessions.
|
|
76
|
+
- [Binding decision](../../../.agents/notes/implemented/feature/2026-10-09-session-change-request-bindings.md) — why bindings derive from shell results and status stays on the host.
|
|
77
|
+
|
|
78
|
+
-----
|
|
79
|
+
|
|
80
|
+
<a id="model-experience"></a>
|
|
81
|
+
## Model Experience
|
|
82
|
+
|
|
83
|
+
None, as providers and watchers exchange code host status without contributing model context.
|
|
84
|
+
|
|
85
|
+
#### KV Cache effect
|
|
86
|
+
|
|
87
|
+
None. No model request contains data from this package.
|
|
88
|
+
|
|
89
|
+
## Known Limitations and Deferred Work
|
|
90
|
+
|
|
91
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
92
|
+
|
|
93
|
+
- **Polling only** — status reaches watchers on the next scheduled poll or `refresh`; there is no webhook intake.
|
|
94
|
+
- **Process-local results** — latest results live in memory and are lost on restart; the next watcher polls again.
|
|
95
|
+
|
|
96
|
+
<a id="dev-note"></a>
|
|
97
|
+
### Dev Note
|
|
98
|
+
|
|
99
|
+
<details>
|
|
100
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
101
|
+
|
|
102
|
+
None.
|
|
103
|
+
|
|
104
|
+
</details>
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "通过一个提供方无关的服务注册代码托管提供方并轮询变更请求状态。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-experimental-forge
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
读取并操作 pull request 与 merge request,而不把消费方绑定到某一个代码托管平台。提供方把远端 URL 和变更请求(change request,即 pull request 或 merge request)URL 映射为提供方无关的引用,按 head 分支查找变更请求,批量读取其状态,读取其 diff 与文件,并按请求把草稿标记为可评审或合并变更请求。同一变更请求的所有监听方共享一个轮询循环,轮询节奏随检查、可合并性与生命周期状态变化。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [了解实现](#understand-the-implementation)
|
|
18
|
+
- [深入探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与待办工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
将注册表与至少一个提供方包一起挂载,例如 GitHub 提供方。
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
- name: '@deepseek-ai/dsh-experimental-forge'
|
|
32
|
+
- name: '@deepseek-ai/dsh-experimental-forge-github'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`ctx.forge.register(provider)` 是调用方 fiber 上的 effect,返回异步 disposer,取消并等待该次注册的调用结束。取消后到达的结果会被丢弃。一个提供方服务一个 forge 家族;为同一家族注册第二个提供方会抛错。注册变化会发出 `forge/providers-changed`;注册提供方会立即轮询其已有监听。`repositoryFromRemote(url)` 与 `changeRequestFromUrl(url)` 按注册顺序询问提供方并返回第一个匹配结果。`changeRequestUrl(ref)`、`findByHead(repository, branch, signal)` 与 `readiness(repository, signal)` 委托给引用所属 forge 的提供方,没有注册提供方时抛错;`readiness` 报告提供方能否用当前凭据访问该主机。
|
|
36
|
+
|
|
37
|
+
`markReady(ref, signal)` 把草稿标记为可评审;`merge(ref, { method, headSha }, signal)` 只在 head 仍是 `headSha` 时合并变更请求。两者都委托给引用所属 forge 的提供方,没有注册提供方时抛错;主机接受时 resolve 为 undefined,否则为 `ForgeActionFailure`:`unauthenticated`、head 已越过 `headSha` 时的 `stale`,或带主机原因的 `failed`。两者结束后,被监听的变更请求会立即重新轮询。快照带有 `mergeReady`(主机现在是否会为已登录用户合并该变更请求)与 `mergeMethods`(仓库接受的合并方式,该用户常用的方式排在最前)。
|
|
38
|
+
|
|
39
|
+
`diff(ref, signal)` 读取托管平台计算出的变更请求统一补丁,路径带 `a/` 与 `b/` 前缀;`fileText(ref, commit, path, signal)` 读取其仓库中某个提交下的一个文件。两者都委托给引用所属 forge 的提供方,没有注册提供方时抛错,resolve 为文本或 `ForgeFailure`;托管平台或提供方因结果超过其大小上限而拒绝时,失败为 `too-large`。`fileUrl(ref, commit, path)` 返回该文件在该提交下的网页地址。
|
|
40
|
+
|
|
41
|
+
`fetchChecks(ref, signal)` 按需读取单个变更请求的完整检查,使用独立的 `fetchTimeoutMs` 时限,不占用轮询批次,也不向其监听方发布结果。读取失败时保留已有轮询快照。提供方未实现 `fetchChecks` 时返回 `unavailable`。调用方取消、提供方或服务销毁都会中止读取;销毁会等待读取结束。
|
|
42
|
+
|
|
43
|
+
`ctx.forge.watch(ref, listener)` 同样是 effect。变更请求的第一个监听方会立即触发轮询;`latest(ref)` 返回最近一次结果。每个 forge 同时最多只有一次轮询读取在进行,这次读取包含该 forge 所有到期的变更请求。打开状态的变更请求在检查未完成或可合并性未知时每 `activeIntervalMs` 轮询一次,否则每 `idleIntervalMs` 轮询一次。已关闭的变更请求按 `idleIntervalMs` 轮询以检测重新打开;已合并的停止自动轮询。`refresh(ref)` 立即轮询一个被监听的变更请求,已结束的也包括在内;该 forge 已有读取在进行时,等待其结束后立即再读一次。读取失败后,重试间隔为 `activeIntervalMs` 按连续失败次数翻倍,最长 `maxBackoffMs`;该值必须大于或等于 `activeIntervalMs`。注销提供方会让其被监听的变更请求以 `unavailable` 结束。最后一个监听方离开后轮询停止。默认值见[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-experimental-forge)。
|
|
44
|
+
|
|
45
|
+
达到 `fetchTimeoutMs` 时,读取信号会以 `FORGE_FETCH_TIMEOUT` 中止。提供方必须在信号中止时停止工作并结束请求;被拒绝的读取会转为 `unavailable` 失败。忽略取消的提供方可能阻塞轮询和服务销毁。
|
|
46
|
+
|
|
47
|
+
provider 可以实现 `submitReview`,在指定的 head 提交上发布行内评论或完整评审。未实现该能力时,注册表返回不支持;提交结束后会刷新受关注的状态。成功的写操作返回网页 URL;失败区分 head 变化、明确拒绝与结果不明。调用方必须先核对结果不明的操作,再次提交。待提交草稿由消费者管理,不由轮询注册表保存。
|
|
48
|
+
|
|
49
|
+
-----
|
|
50
|
+
|
|
51
|
+
<a id="understand-the-implementation"></a>
|
|
52
|
+
## 了解实现
|
|
53
|
+
|
|
54
|
+
<details>
|
|
55
|
+
<summary>实现细节——点击展开</summary>
|
|
56
|
+
|
|
57
|
+
一个定时器覆盖所有被监听的变更请求。定时器触发时,服务按 forge 对到期的变更请求分组,并为每个空闲的 forge 发起一次批量读取。抛错的监听方会被记录日志并跳过。销毁服务会中止进行中的读取,并等待它们结束。
|
|
58
|
+
|
|
59
|
+
| 源码 | 职责 |
|
|
60
|
+
|---|---|
|
|
61
|
+
| [`src/index.ts`](src/index.ts) | 提供方注册、URL 映射、监听生命周期与批量轮询 |
|
|
62
|
+
| [`src/schedule.ts`](src/schedule.ts) | 计算单个变更请求距下次轮询的延迟 |
|
|
63
|
+
| [`src/keys.ts`](src/keys.ts) | 变更请求不区分大小写的规范标识 |
|
|
64
|
+
| [`src/types.ts`](src/types.ts) | 仓库、变更请求、状态与提供方类型 |
|
|
65
|
+
|
|
66
|
+
</details>
|
|
67
|
+
|
|
68
|
+
-----
|
|
69
|
+
|
|
70
|
+
<a id="further-exploration"></a>
|
|
71
|
+
## 深入探索
|
|
72
|
+
|
|
73
|
+
- [Forge 子系统](../../../docs/subsystems/forge.zh.md)——提供方契约、变更请求类型与服务参考。
|
|
74
|
+
- [GitHub 提供方](../forge-github/README.zh.md)——服务 GitHub 主机的提供方。
|
|
75
|
+
- [Session 绑定](../forge-session/README.zh.md)——把变更请求绑定到 Session 的消费方。
|
|
76
|
+
- [绑定决策](../../../.agents/notes/implemented/feature/2026-10-09-session-change-request-bindings.zh.md)——为何绑定从 shell 结果派生、状态只留在宿主侧。
|
|
77
|
+
|
|
78
|
+
-----
|
|
79
|
+
|
|
80
|
+
<a id="model-experience"></a>
|
|
81
|
+
## 模型体验
|
|
82
|
+
|
|
83
|
+
无:提供方与监听方只交换代码托管平台的状态,不贡献模型上下文。
|
|
84
|
+
|
|
85
|
+
#### KV Cache 影响
|
|
86
|
+
|
|
87
|
+
无。任何模型请求都不包含本包的数据。
|
|
88
|
+
|
|
89
|
+
## 已知限制与待办工作
|
|
90
|
+
|
|
91
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
92
|
+
|
|
93
|
+
- **仅轮询**——状态在下一次计划轮询或 `refresh` 时才送达监听方;没有 webhook 接入。
|
|
94
|
+
- **结果只在进程内**——最近结果保存在内存中,重启后丢失;下一个监听方会重新轮询。
|
|
95
|
+
|
|
96
|
+
<a id="dev-note"></a>
|
|
97
|
+
### 开发备注
|
|
98
|
+
|
|
99
|
+
<details>
|
|
100
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
101
|
+
|
|
102
|
+
无。
|
|
103
|
+
|
|
104
|
+
</details>
|