Development & Runtime

dsh-code-lens

lisycotana/dsh-code-lens · ★ 0

lisycotana

Observability for DeepSeek Harness code-mode sub-dispatches — the tool calls a run code program makes that the model never sees.

License
MIT
Added
2026-08-23
Maintenance
active
Install kind
github

No manifest check is available; listing does not imply compatibility or security review.

安装

dsh plugin --profile web add github:lisycotana/dsh-code-lens

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: en · Read Chinese README

Table of contents
  1. The gap this fills
  2. What it gives you
  3. Install
  4. Design notes
  5. Verified against
  6. Note for plugin authors
  7. License

Observability for DeepSeek Harness code-mode sub-dispatches — the tool calls a run_code program makes that the model never sees.

The gap this fills

In code mode the model writes a TypeScript program that orchestrates tool calls. The program receives every result in full. The model receives none of them — only whatever the program finally returns. Both dispatch boundaries are still recorded on the session log.

That produces a three-way split with no equivalent outside code mode:

program model session log
sub-call arguments ✅ ❌ ✅
sub-call results ✅ ❌ ✅

dsh is the only harness that draws this distinction, because it is the only one where a tool call can happen inside a program the model wrote. The data is recorded and nothing surfaces it. This plugin does.

What it gives you

A codeLens session projection — whole-session totals, readable from the UI without touching the log:

{ "programs": 1, "dispatches": 2, "settled": 2, "errors": 1, "dispatchMs": 340, "hiddenBytes": 1027 }

hiddenBytes is the payload the program consumed and the log preserved while the model saw none of it.

A code_lens tool — lets the model audit its own program after the fact:

run_code call_abc: 2 sub-calls, 1 errors, 340ms, 1027B hidden from context
  call_abc:code:1  bash  ok     140ms  3B
  call_abc:code:2  read  error  190ms  1024B

Install

dsh plugin --profile web add dsh-code-lens
dsh --profile web

Development, without packaging — note the file:// URL (a bare G:/... path is parsed as a URL scheme on Windows):

# scratch/cordis.yml
- insert:
    - id: code-lens
      name: 'file:///G:/dsh-plugins/dsh-code-lens/index.js'
dsh --profile web --patch ./scratch/cordis.yml

Design notes

  • Zero dependencies. The projection registry's runtime contract is structural — it calls schema.parse(value) and nothing else — so the view validator is hand-written rather than pinning a zod copy that could drift from the host's.
  • Never appends from the observer. session/event listeners run inside the publication window of the append that produced the event, and Session.append() throws on reentry. This plugin only reads there.
  • Both registries are optional. sessionProjections and tools are acquired through ctx.inject, so the plugin stays loadable in headless assemblies that compose neither.
  • Holes in sub-call numbering are normal. A sub-call queued but abandoned by run settlement logs neither event, so a start without a settle is a valid terminal state, not a leak. turn/end drops the leftovers so persisted state cannot grow forever.
  • Pairing is by subCallId; timing comes from the event envelope time — neither event carries a duration.

Verified against

@deepseek-ai/dsh@0.1.0-rc.6, Node 24, DeepSeek-V4 via the headless profile.

Real session output — one run_code program reading eight files:

run_code call_00_lMDLou1XAHEXiQYgKbUR9330: 9 sub-calls, 0 errors, 23ms, 1312B hidden from context
  call_00_lMDLou1XAHEXiQYgKbUR9330:code:1  read  ok  6ms  164B
  ...
  call_00_lMDLou1XAHEXiQYgKbUR9330:code:8  read  ok  2ms  164B
  call_00_lMDLou1XAHEXiQYgKbUR9330:code:9  code_lens  unsettled  —  0B

The model reported only "24 lines" — those 1312 bytes never entered its context. The trailing unsettled row is code_lens observing its own in-flight call, which is the documented terminal state for a start whose settle has not landed.

To reproduce, code mode must be on. The headless bundle already wires the tools row to an environment variable, so no patch is needed:

DSH_TOOLS_MODE=code dsh --profile headless --patch ./scratch/cordis.yml "…"

Unit-level checks: verify-integration.mjs (projection fold through the real SessionStore/SessionProjections) and verify-tool.mjs (tool registration and execution).

Note for plugin authors

ctx.tools.register() takes the wire schema — a complete JSON Schema object. defineTool accepts the author-facing shorthand (a bare property map) and compiles it. Passing the shorthand straight to register() reaches the provider as type: null and the request is rejected:

INVALID_REQUEST: Invalid schema for function 'x':
schema must be a JSON Schema of 'type: "object"', got 'type: null'.

This plugin writes the object root explicitly, and validates its own argument, because defineTool's compiled validator is what it gives up in exchange for staying dependency-free. (A plain-JS plugin installed outside the harness tree cannot resolve @deepseek-ai/dsh-tools as a bare specifier.)

License

MIT