2026-06-11 10:52:45 +08:00
|
|
|
{
|
|
|
|
|
"extends": "./tsconfig.base.json",
|
2026-06-17 23:41:18 +08:00
|
|
|
"compilerOptions": {
|
2026-06-22 09:03:28 +08:00
|
|
|
"noEmit": true,
|
|
|
|
|
"rewriteRelativeImportExtensions": false
|
2026-06-17 23:41:18 +08:00
|
|
|
},
|
|
|
|
|
"include": [
|
|
|
|
|
"examples/*/src/**/*.ts",
|
|
|
|
|
"examples/*/start.ts",
|
|
|
|
|
"examples/*/tests/**/*.ts",
|
2026-06-22 00:35:51 +08:00
|
|
|
"packages/*/*/tests/**/*.ts",
|
2026-06-17 23:41:18 +08:00
|
|
|
"scripts/**/*.ts"
|
|
|
|
|
],
|
|
|
|
|
"references": [
|
|
|
|
|
{ "path": "./vendor/cosmokit" },
|
|
|
|
|
{ "path": "./vendor/schemastery" },
|
|
|
|
|
{ "path": "./vendor/cordis" },
|
|
|
|
|
{ "path": "./vendor/loader" },
|
|
|
|
|
{ "path": "./vendor/include" },
|
|
|
|
|
{ "path": "./vendor/group" },
|
|
|
|
|
{ "path": "./vendor/timer" },
|
|
|
|
|
{ "path": "./vendor/hmr" },
|
|
|
|
|
{ "path": "./vendor/logger-console" },
|
2026-06-22 00:51:41 +08:00
|
|
|
{ "path": "./packages/util/brand" },
|
|
|
|
|
{ "path": "./packages/llm/llm" },
|
|
|
|
|
{ "path": "./packages/core/session" },
|
|
|
|
|
{ "path": "./packages/session-persistence/session-persistence" },
|
|
|
|
|
{ "path": "./packages/session-persistence/session-persistence-jsonl" },
|
|
|
|
|
{ "path": "./packages/session-persistence/session-persistence-sqlite" },
|
|
|
|
|
{ "path": "./packages/core/system-prompt" },
|
|
|
|
|
{ "path": "./packages/core/agent" },
|
|
|
|
|
{ "path": "./packages/core/tools" },
|
|
|
|
|
{ "path": "./packages/core/agent-loop" },
|
|
|
|
|
{ "path": "./packages/core/agent-core" },
|
|
|
|
|
{ "path": "./packages/bash/bash" },
|
|
|
|
|
{ "path": "./packages/llm/llm-deepseek" },
|
|
|
|
|
{ "path": "./packages/llm/llm-pi-ai" },
|
|
|
|
|
{ "path": "./packages/bash/bash-local" },
|
|
|
|
|
{ "path": "./packages/bash/tool-bash" },
|
2026-06-28 17:24:45 +08:00
|
|
|
{ "path": "./packages/fs/fs" },
|
|
|
|
|
{ "path": "./packages/fs/fs-local" },
|
fix(fs): address review — rename to dsh-fs-policy, fs/*-intent events, RFC currency, ENOTDIR
Rename per review naming decisions:
- package dsh-file-context → dsh-fs-policy (dir, package name, plugin name,
tsconfig refs, importers, type-equiv manifest, generated catalog + module-graph)
- events fs/write-expectation → fs/write-intent, fs/edit-expectation → fs/edit-intent
(fs/observed unchanged); type FsWriteExpectation → FsWriteIntent, "expectation"
wording → "intent" throughout
- exported FileContextExec → FsPolicyExec
Make the implemented RFCs describe what shipped, not the superseded designs:
the 2026-06-17 capability-seam + tool-schemas RFCs no longer place policy on
ctx.fs or use full/partial-view authorization, and the fsspec RFC's ctx.fileContext
service prose is rewritten to the fs/* event-gate reality (freshness-based auth).
Sharpen docs/rfc/implemented/AGENTS.md: a rename is a fact to fix IN PLACE — the
"new RFC" escape hatch is for macro decision reversals only, not renames.
Code fixes from review:
- fsio.ts resolveLocalTarget/probe translate ENOTDIR (a parent path segment is a
file) into the structured FsError taxonomy instead of leaking a raw Node error;
resolve reports FS_NOT_FOUND, probe reports absent. Regression tests proven to
fail on the unfixed code.
- tool-fs HMR test now asserts prompt sections (not just tool schemas) are
withdrawn on disposal.
- fs/observed is a plain (unguarded) ctx.emit: correct the fs-policy comment,
filesystem.md, and tool-fs module doc that wrongly claimed the tool "contains"
a throwing listener; a throw surfaces as the tool's isError result.
- drop the false "loaded by the default product config" claim (no config wires
the fs tools yet), the duplicate ctx.bash service-map row, the stale
FileReadRequest catalog link-map entry, and the fs/fs README EOF blank line;
correct the dsh-fs package.json description.
2026-07-02 03:12:38 +08:00
|
|
|
{ "path": "./packages/fs/fs-policy" },
|
2026-06-28 17:24:45 +08:00
|
|
|
{ "path": "./packages/fs/tool-fs" },
|
2026-06-25 09:10:50 +08:00
|
|
|
{ "path": "./packages/compact/compact" },
|
2026-06-25 17:30:42 +08:00
|
|
|
{ "path": "./packages/compact/compact-basic" },
|
2026-06-26 19:18:46 +08:00
|
|
|
{ "path": "./packages/web/web" },
|
|
|
|
|
{ "path": "./packages/web/web-search-exa" },
|
|
|
|
|
{ "path": "./packages/web/web-search-perplexity" },
|
2026-06-29 15:21:12 +08:00
|
|
|
{ "path": "./packages/web/web-search-deepseek" },
|
2026-06-26 19:18:46 +08:00
|
|
|
{ "path": "./packages/web/web-fetch-local" },
|
|
|
|
|
{ "path": "./packages/web/tool-web" },
|
2026-06-22 00:51:41 +08:00
|
|
|
{ "path": "./packages/support/invariants" },
|
|
|
|
|
{ "path": "./packages/ui/acp" },
|
|
|
|
|
{ "path": "./packages/ui/acp-agent" },
|
|
|
|
|
{ "path": "./packages/ui/stdio-agent" },
|
|
|
|
|
{ "path": "./packages/support/ui-stdio" },
|
2026-06-22 14:35:35 +08:00
|
|
|
{ "path": "./packages/support/llm-replay" },
|
|
|
|
|
{ "path": "./packages/subagent/subagent" },
|
|
|
|
|
{ "path": "./packages/support/subagent-mock" },
|
2026-06-22 14:43:51 +08:00
|
|
|
{ "path": "./packages/subagent/tool-subagent" },
|
|
|
|
|
{ "path": "./packages/subagent/subagent-inprocess" },
|
|
|
|
|
{ "path": "./packages/subagent/subagent-spawn" },
|
2026-06-22 14:58:03 +08:00
|
|
|
{ "path": "./packages/subagent/subagent-fork" },
|
feat(tool-todo): add the model-facing todo_write tool
Add @deepseek-ai/dsh-tool-todo (a new packages/todo/ group): a model-facing
todo_write(todos: [{content, status}]) tool with whole-list-replace semantics.
Each call appends the full list as a todo/write event to the calling agent's
session log; the current list is the most recent such event (last-write-wins).
Single-owner — a non-agent caller is rejected. Beyond the schema's
type/required/enum checks, execute rejects empty/duplicate content and more than
one in_progress task, narrowing the loosely-typed args into a real TodoItem[].
Both UIs render off the existing session/event: the stdio UI prints a glyphed
checklist; the ACP bridge maps the list to a `plan` sessionUpdate (todosToPlan
synthesizes the priority ACP requires; status maps 1:1). Wired into the
coding-agent, acp-agent, and snapshot example configs with a system-prompt nudge.
Tests: unit (schema, validation, append/replace, no-agent rejection, presentCall,
HMR-safety, Loader export-shape guard), full-loop integration through the agent
loop, the ACP todosToPlan mapping + stream-update arm, the stdio render arm, and
a session/load replay that re-emits the plan. New-group TS wiring added to
tsconfig.base/json/build. RFC + a doc-inventory sweep (architecture, packages
README, AGENTS layout, cookbook group list, example READMEs) ship with it.
The todo-plan ACP snapshot scenario is recorded separately (needs an API key).
2026-06-29 10:30:52 +08:00
|
|
|
{ "path": "./packages/subagent/subagent-acp" },
|
feat(hooks): dsh-hook-protocol — shared Claude Code / Codex hook wire-protocol core
The two hook bridges (dsh-hooks-claude, dsh-hooks-codex) would otherwise duplicate
the bulk of the protocol — Codex deliberately reimplements a SUBSET of the Claude
Code protocol (same hooks.json shape, exit-code/stdout contract, command-hook
model). This library holds the genuinely-identical primitives; each bridge owns
only what differs (per-event stdin payload, env/substitution, decision mapping).
New packages/hooks/ group; hook-protocol is a LIBRARY (no plugin, registers/injects
nothing):
- matcher: matchesMatcher(pattern, query, mode) — the one dialect axis collapsed to
a mode param (claude = literal-or-regex with pipe alternation; codex = always
unanchored regex). Match-all on absent/''/'*'; invalid regex matches nothing.
- codec: parseHookOutput(exit, stdout, stderr) → dialect-neutral HookOutput. Exit 0
→ lenient JSON; exit 2 → blocking error (stderr = reason, surfaced as
decision:'block'); other → non-blocking. Parses the CC superset
(continue/stopReason/decision/hookSpecificOutput.{permissionDecision,
additionalContext,updatedInput}/systemMessage); permissionDecision overrides the
legacy top-level decision.
- runner: runHook(bash, hook, opts, now) — runs a command hook via ctx.bash (stdin
payload + trusted-plugin env), honors timeoutSec, never throws (executor reject →
non-blocking-error HookOutput). Injected clock for testable durations.
- merge: mergeHookOutputs — most-restrictive fold (deny>ask>allow, sticky stop,
block reasons joined, context/system-messages accumulated).
- hook/* session events (declaration-merged into SessionEventMap, log-only like
compact/*) + appendHookInvoked/appendHookResult helpers.
updatedInput is parsed but NOT honored (deferred pre-tool-input-rewrite RFC); a
bridge logs+warns. 47 unit tests at per-file 100% (matcher per-mode, codec per
exit-code/field, runner plumbing w/ stub executor, merge precedence, hook/*
helpers). RFC: implemented/feature/2026-06-30-hook-protocol-lib.md.
2026-07-01 00:38:06 +08:00
|
|
|
{ "path": "./packages/todo/tool-todo" },
|
feat(hooks): dsh-hooks-claude + dsh-hooks-codex bridges (hooks stack PR-F)
The two bridge plugins that run a user's existing Claude Code / Codex hook
config on the harness's typed interception seams, built on the shared
dsh-hook-protocol library. A bridge is a faithfulness adapter, not a power
tool: anything it does a native cordis plugin does more powerfully — the
bridge exists only to run UNMODIFIED external hooks.
- dsh-hooks-claude: CC dialect. Seven hook points (SessionStart,
UserPromptSubmit, PreToolUse, PostToolUse, Stop, SubagentStart,
SubagentStop), CC per-event stdin payloads, env + ${CLAUDE_PLUGIN_ROOT}/
${CLAUDE_PROJECT_DIR} substitution, literal-or-regex matcher.
- dsh-hooks-codex: Codex dialect — a deliberate subset. Five hook points,
always-regex matcher, snake_case payloads (turn_id/model, no trailing
newline), no env/substitution, block-only decisions.
Both map the neutral merged outcome onto the seam's typed Decision and stamp
an explicit {kind:'plugin'} source on injected context (so it is never
mislabeled as a user prompt). Config parse-failure is contained; only command
hooks run. updatedInput is logged+warned (input rewrite deferred); the Stop
loop-guard is deferred (TODO).
Tests: per-file 100% — config-parse unit branches + per-seam mappings
end-to-end through the REAL loop + REAL bash + REAL shell scripts (scripted
mock model only) + a real-Loader export-shape guard. A keyless ACP snapshot
scenario (hook-prompt-block) proves a UserPromptSubmit hook blocks a prompt
end-to-end (rejected turn -> ACP cancelled, hook/* events in the log); a
with-key e2e (hooks.e2e.ts) proves a PreToolUse hook blocks real bash
(verified on disk). The snapshot normalizer now scrubs hook/result.durationMs.
RFC: docs/rfc/implemented/feature/2026-06-30-hook-bridges.md
2026-07-01 04:22:00 +08:00
|
|
|
{ "path": "./packages/hooks/hook-protocol" },
|
|
|
|
|
{ "path": "./packages/hooks/hooks-claude" },
|
|
|
|
|
{ "path": "./packages/hooks/hooks-codex" }
|
2026-06-17 23:41:18 +08:00
|
|
|
]
|
2026-06-11 10:52:45 +08:00
|
|
|
}
|