Commit Graph
14 Commits
Author SHA1 Message Date
Tianyi Cui cbcbbf8825 fix(claude-code-mods): make Blast Radius holds independent of sleep 2026-10-06 10:20:25 +08:00
Tianyi Cui ab112b82cd test(mods): canonicalize Windows directory fixtures 2026-10-06 01:31:52 +08:00
Tianyi Cui ffd791a110 fix(session): use committed directories in hooks and consumers 2026-10-06 01:31:51 +08:00
Tianyi Cui a161070a76 test(experimental): run the example mod tests through a spec the coverage lane inventories
The coverage partitions list *.spec.ts files only, so the published
*.test.ts files reached no partition and the test kit's mount paths went
uncovered there. examples.spec.ts imports them by computed path; the kit
resolves the mod under test from the outermost describe when the file runs
through a spec.
2026-10-03 06:03:30 +08:00
Tianyi Cui 233032b8f4 fix(experimental): close the mods bridge review findings
- Disposal cancels detached runs before the engine waits for timer callbacks,
  so a callback parked in a $ call ends instead of blocking unload.
- A forgotten band wakes and ends its watch streams; a refresh asked for
  during a pass joins one more pass that settles after it; the Web band drops
  an ended stream so the next subscriber opens a fresh one.
- $ has Claude Code's namespaces: an unserved member rejects with
  'no implementation for <namespace>.<member>' instead of a TypeError.
- A .catch handler's next makes the rewrite check; a tool rename is refused
  like an argument rewrite; a null op answer is reported as no answer;
  defineMod returns its disposer from apply; the live turn record is copied
  before the chain freezes it; prompt.submit is raised only for batches with
  a human message and names the submitting mod as origin.
- $.http.fetch bounds the body while streaming; bandColumns/bandRows are
  Config; the client package drops its stale gateway edges; the source
  overlay lives in the package and anchors its entries to the file, and the
  dsh installation no longer depends on the experimental packages.
2026-10-03 05:18:32 +08:00
Tianyi Cui 34f52880b0 test(experimental): typecheck the mod test fixtures and example wrappers
Hook results spread the typed result from beneath, element props accept an
explicit undefined as a JavaScript mod passes it, the band's registry
payload is narrowed by assertion, and the example wrappers join the Host
typecheck project.
2026-10-03 03:28:09 +08:00
Tianyi Cui 57126d8baf feat(experimental): draw the mods' AbovePrompt band and expose it over a Remote
The bridge keeps one band per session: ui.render is raised through the
mods in load order, the tree's buttons keep their onPress host-side behind
per-drawing action ids, a $.state read during a render subscribes the band
to that slot, and $.ui.open/close/invalidate, the end of a tool.call chain,
and turn.complete redraw it. ClaudeCodeMods is a TypertRemoteService:
watchBand streams snapshots, pressBand runs a button and redraws. null is
an accepted hook answer (a surface drawn empty).
2026-10-03 02:17:21 +08:00
Tianyi Cui f1715c67ec refactor(experimental): make mods DSH plugins and drop the persistence change
A mod is now a plugin built with defineMod() around its register(on,
options); the bridge is the ClaudeCodeMods service (ctx.claudeCodeMods)
that keeps the loaded mods and raises their events. The plugin.json /
hooks.json loader, pluginDirs, and dynamic imports are gone.

prompt.submit context becomes text blocks appended to the human's own
prompt message and $.prompt.submit queues a user-sourced message, so the
bridge adds no message source kind: the persistence record and the
regenerated schema are removed and the artifacts match master again.

Engine correctness from the review round: next() is memoized and every
started run beneath is awaited before a hook's answer settles; a rewritten
tool argument skips the hook with a report pointing at the pre-tool input
rewrite proposal; timers belong to the session whose event started them;
$.tool.call injects a tool's deferred contexts; $.clock.sleep honors the
event signal; a built-in tool answered with { result } is validated against
its output schema before it becomes an error-shaped result; hooks on events
this host never raises are reported at load.

Examples: the three mods from the Claude Code blog post under examples/,
Token Weather and its test unchanged, Blast Radius and Replay Theater
completed from the published fragments, run by their own tests through a
claude-code/testing alias over the new test kit ($.ui.mount/find/press).
2026-10-03 01:38:21 +08:00
Tianyi Cui 600034d653 fix(experimental): harden the mods bridge after review
- prompt.submit sees and rewrites only the human's own messages, gains the
  rewritten text on an image-only prompt, and keeps only typed result fields
- a mod's $.tool.call reaches only the mods loaded before it, attributed to
  the caller, instead of re-entering every mod through the pipeline
- a .catch handler shares the failed hook's beneath state so nothing beneath
  runs twice; a late next from an abandoned handler is ignored
- hook results are validated before use; detached runs report rejections
- session.end keeps $.state readable until its hooks settle; agent creation
  cancellation abandons a waiting session.start hook; agents is read lazily
- a success a hook marks isError becomes a failure; replacement entries clear
  on tools/result; per-agent registrations drop with the agent
- $.store writes are serialized per plugin and bounded in UTF-8 bytes;
  $.http.fetch bodies are bounded; timers refuse rescheduling after unload
  and unload awaits running callbacks; regex matchers reset lastIndex
2026-10-02 13:18:17 +08:00
Tianyi Cui 7555272e97 test(experimental): widen the budget-pause timing margin for loaded CI hosts 2026-10-02 11:55:14 +08:00
Tianyi Cui 6e948732d1 test(experimental): cover the mods bridge's process cwd fallback on Windows and list the package in the release family
Also narrow the mod tool's rendered value to the string its schema admits and
bind the registration's catch before calling it untyped.
2026-10-02 11:53:56 +08:00
Tianyi Cui ca83aecbc8 test(experimental): keep mods bridge specs platform-stable
Resolve expected module paths through the platform path module and keep
the signal-termination assertion to POSIX, where a self-killed child has no
exit code.
2026-10-02 11:36:41 +08:00
Tianyi Cui 54fa38795f fix(experimental): drop unknown casts from the mods bridge and its tests
Type the mod tool's output as the answering text, read JSON into a typed
unknown, and replace the test doubles that went through unknown with a
real $ over a slow invoke, an Agent-comparable facts object, loosely typed
on() calls, and the Loader's own import path.
2026-10-02 11:27:47 +08:00
Tianyi Cui 35873604ad feat(experimental): add Claude Code mods bridge
Add @deepseek-ai/dsh-experimental-claude-code-mods, an alpha bridge that
loads Claude Code mods (plugin directories whose hooks/hooks.json names a
hooks module), runs register(on, options) unchanged, and raises the mod
events from harness extension points: session.start on agent/created,
prompt.submit and turn.start on agent/pre-step, tool.call around
tools/execute, turn.complete on turn/end, session.end on agent/disposed,
and command.run from registered commands. The $ mods API is served over
composed services (commands, tools, user-questions, fs, subprocess,
storage domain, projections); unserved members fail by name.

Includes a middleware chain with Claude Code's failure rules and budget
clock, a claude-code/testing-style test kit, fixtures from the mods
tutorial, full-loop and Loader composition tests, the attribution-only
claude-code-mods message source with its persistence record, and the
regenerated catalogs.
2026-10-02 11:10:41 +08:00