Files
deepseek-harness/packages/experimental/forge/README.md
T
Yichen Jiang d0fc1f6458 feat(forge): show the changes of a Session and of its change requests
The forge panel opens a changes view in the right sidebar for the
checkout's local changes and for the diff of each change request.

- ForgePanelController reads local diffs in the branch, uncommitted,
  unstaged, and staged scopes through Git in the Session's read-only
  sandbox, change request diffs through the forge provider, and the text
  of a changed file to expand unchanged lines. Change request patches stay
  cached by head commit and base branch within maxCachedDiffBytes. A local
  diff over maxDiffBytes fails as forgePanel/diff-too-large, and a provider
  read over its output limit fails as too-large, which the view explains
  with a link to the code host; a gh timeout fails as unavailable.
- forge adds the diff, fileText, and fileUrl provider methods and the
  too-large failure code, and forge-github implements them with gh.
- The panel shows a local changes card that opens the view and asks the
  Agent for a change request. The view collapses files past a line
  budget, draws lines side by side or in one column with optional
  wrapping, expands unchanged lines on request, and collapses or expands
  every file from its toolbar; file headers use a bare chevron.
- The checkout row copies the worktree or project directory path, the
  refresh glyph turns while a refresh runs, change request cards keep
  their actions while collapsed, and the header entry uses the shared
  compact button.
- client-ui-forge classifies changeRequestKey and FsError as
  peer-required Host imports, which keeps forge and dsh-fs as its peers.
2026-10-20 13:34:27 +08:00

6.1 KiB

description, kind
description kind
Register code host providers and poll change request status through one provider-neutral service. package-reference

@deepseek-ai/dsh-experimental-forge

English | 中文

Summary

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.

Table of Contents


Use this package

Mount the registry with at least one provider package, such as the GitHub provider.

- name: '@deepseek-ai/dsh-experimental-forge'
- name: '@deepseek-ai/dsh-experimental-forge-github'

ctx.forge.register(provider) is an effect on the calling fiber and returns its disposer. One provider serves one forge family; registering a second provider for the same family throws. 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.

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.

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.

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 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 and merged change requests are not polled again. refresh(ref) polls a watched change request at once, including after a terminal state; a fetch already in flight for its forge serves the request. A failed read repeats after activeIntervalMs doubled for each consecutive failure, up to maxBackoffMs. A fetch that exceeds fetchTimeoutMs settles as an unavailable failure whose message names FORGE_FETCH_TIMEOUT. Unregistering a provider settles its watched change requests as unavailable. Polling stops when the last watcher leaves. The configuration catalog lists the defaults.


Understand the implementation

Implementation internals — click to expand

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.

Source Responsibility
src/index.ts Provider registration, URL mapping, watch lifetime, and batched polling
src/schedule.ts Delay before the next poll of one change request
src/keys.ts Case-insensitive canonical identity of a change request
src/types.ts Repository, change request, status, and provider types

Further Exploration


Model Experience

None, as providers and watchers exchange code host status without contributing model context.

KV Cache effect

None. No model request contains data from this package.

Known Limitations and Deferred Work

  • Polling only — status reaches watchers on the next scheduled poll or refresh; there is no webhook intake.
  • Process-local results — latest results live in memory and are lost on restart; the next watcher polls again.

Dev Note

Working context for maintainers — click to expand

None.