Skip to content
dsh.fish
Bundle

dsh-code-lens

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

Source
lisycotana
License
MIT
Updated
Updated 7 days ago

Readme

# dsh-code-lens

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:

```json
{ "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

```sh
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):

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

```sh
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:

```sh
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

Install

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

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source