AlexKaiqi/dsh-block-to-file0

dsh-block-to-file

block-to-file runtime plugin: atomically commits fenced file blocks with Git blob observations, multi-file transactions, and ref CAS

包名
dsh-block-to-file
版本
0.1.0-rc.6
许可证
MIT
最近更新
2026年8月22日

安装

此插件尚未提供可验证的 bundle,或兼容性检查未通过。请先阅读仓库说明。 阅读完整 README ↗

Configuration

b2f:
  root: "$WS"                # expands $WS / $DSH_B2F_ROOT; DSH_B2F_ROOT env wins
  editFormat: git_diff       # git_diff | replace | none
  maxEditDrift: 200          # lines a mode=diff hunk may drift from its @@ line
  maxFileSize: 1048576
  maxTotalSize: 2097152
  maxFilesPerMessage: 16
  diffLineLimit: 200
  canonicalRef: refs/heads/agent-canonical
  maxCasRetries: 8
  tempFileKeep: 16

Set editFormat: none to disable partial edits entirely.

Each settled transaction is emitted as b2f/transaction with the full report. Per-block editFormat, editsProposed, editsApplied, and fuzz are carried on every result, so first-apply success rate, retry counts, and drift tolerance can be compared across dialects without this plugin aggregating anything.

root must be an absolute workspace path, but it does not need to be a Git worktree. On first use b2f snapshots the workspace into its private bare store and creates canonicalRef from that baseline; after that the canonical ref is the only publication source of truth. Existing or nested Git worktrees contribute their tracked files without exposing their .git object stores. Unrelated concurrent b2f commits are retained when a candidate is rebuilt on the latest canonical head.

Usage

Install from npm and add the package to the DSH profile:

npm install dsh-block-to-file
dsh plugin --profile web add dsh-block-to-file

During local development, link this checkout instead (pnpm install && pnpm build, then dsh plugin --profile web add "$PWD").

Mount the plugin in the Host composition, where its b2f service can be shared by every Agent session:

- id: block-to-file
  name: 'dsh-block-to-file'
  config:
    root: $WS

Do not mount this service provider as a loose row in an Agent preset. A preset that owns b2f must isolate the b2f service and place every consumer in that same isolate realm.

b2f replaces the model-facing str_replace_editor write path. Remove or disable the official editor in YOUR composition (preset / overlay) — this package intentionally does not patch or remove any official plugin.

For generic per-agent checkouts or sandboxes, install a path-aware root resolver at activation time and retain its Fiber-scoped disposer. Return undefined for paths the resolver does not own so older registrations or the default Session workspace can handle them:

const dispose = ctx.b2f.registerRootResolver(
  (agent, session, paths) => paths?.every(isCheckoutPath)
    ? {
        root: checkoutRootFor(agent, session),
        scope: 'checkout',
        authorization: 'mounted-workspace',
      }
    : undefined,
)
ctx.effect(() => dispose)

A consumer that owns an external canonical store may also register an async publisher. Same-message tools await the newest publisher that claims the transaction; a rejection becomes publication-failed and blocks those tools. A successful receipt is rendered separately from the local workspace commit:

const disposePublisher = ctx.b2f.registerPublisher(async request => {
  if (request.scope !== 'checkout') return undefined
  const result = await publishCanonical(request)
  return { scope: 'example', revision: result.revision, noOp: result.noOp }
})
ctx.effect(() => disposePublisher)

Every path is resolved independently. If one message spans more than one root or named scope, the whole transaction fails with MIXED_ROOT_SCOPE. Resolvers may prepare a scope asynchronously. The newest resolver returning a claim wins. Roots that need asynchronous preparation are skipped by the pre-step snapshot and captured on demand at commit time, so an async resolver never fails an agent step. When ctx.sandboxPolicy is mounted, b2f consumes that same per-Session policy: read-only rejects every mutation, workspace-write accepts the Session root and trusted mounted-workspace claims, and danger-full-access retains the configured b2f boundary. The default resolver uses session.header.cwd, falling back to the static config.root / $WS / $DSH_B2F_ROOT value. b2f pins an agent's canonical snapshot when its repository view is first prepared and advances it only after commit or stale feedback. When ctx.fs is mounted, a successful b2f settlement resolves and stats each result through that provider and emits fs/observed before same-message tools run. Provider-native FsVersion values are deliberately not reused as Git blob observations; a read-capable plugin with exact b2f version information may instead call ctx.b2f.recordObservation(agentId, {...}).