Commit Graph

13 Commits

Author SHA1 Message Date
Yichen Jiang
ba329b16ce Merge remote-tracking branch 'origin/master' into codex/agent-session-jsonl-location
# Conflicts:
#	docs/module-graph.md
#	docs/rfc/INDEX.md
#	packages/core/agent-core/tests/agent-core.spec.ts
#	pnpm-lock.yaml
2026-07-13 16:18:44 +08:00
Tianyi Cui
28e04ff4fb refactor(core): simplify scoped agent lifecycles 2026-07-12 22:36:04 +08:00
Yichen Jiang
eea0a99985 feat: expose agent session log location 2026-07-10 20:52:27 +08:00
Hypatia May
c7fba41ba9 Inline session fork parameters 2026-07-07 09:04:49 +08:00
Hypatia May
37aac7f313 fix: collapse session fork to one api 2026-07-06 13:57:59 +08:00
Hypatia May
0bf8749128 fix: fold session fork into session store 2026-07-06 12:35:34 +08:00
Hypatia May
828c3f85c9 fix review findings: skip collided SCHEMA_VERSION 3; reject marker-less surface events
P1: both merge parents shipped SCHEMA_VERSION=3 for different layouts (surface
columns vs seed_length), so an on-disk 3 was ambiguous and wrongly accepted.
Bump to 4 (merged layout) so the version check rejects both sibling v3s.

P2: a surface-eligible event with no surfaceOp lands in the log but vanishes
from deriveMessages() (surface is the sole derivation path). The typed append
overload enforces the marker only when the type arg is a literal; it collapses
to optional when widened to the union (a caller iterating raw events). Guard at
runtime in both append() and the seed constructor — no backward-compat for
surface-less logs. Shared seed fixtures carry surfaceOp explicitly and the
appendLog helper forwards it verbatim (no synthesized default). Exports
isSurfaceEligibleType. Regression tests for all three, each verified to fail
on the unfixed code.

Gates: typecheck, test (1115), snapshot (14), doc-sync, lint, build, hygiene green.
2026-06-24 17:45:48 +08:00
Hypatia May
6089e226bc refactor(session): make surface the sole derivation path, drop legacy fallback 2026-06-23 13:05:59 +08:00
Tianyi Cui
b0422f2a50 fix review findings: bump session format version + restore late turn-end warn
Codex review of the trace-event fold found two merge-blockers.

Blocker #1 — format version. Folding usage onto assistant/message and removing
the standalone usage/error events changed the persisted SessionEventMap shape,
which per the AGENTS.md "bump the version and reject — don't migrate" policy
requires a backend to reject any non-current log. Centralize the version in an
exported SESSION_FORMAT_VERSION constant (dsh-session), read by both write sites
(Session constructor default, SessionStore.prepare header) and the coordinator's
load-time assertVersion check. The constant is pinned at 0: while unreleased the
on-disk format is unstable/pre-release, so breaking shape churn is absorbed at v0
(no monotonic bump until the first tagged release) and any non-0 log is rejected
on load — no migration. Update every test/fixture/doc that stamps a
currently-written header to the constant, bump the ACP snapshot fixture + golden
headers to v0, and keep the version-rejection test meaningful by switching its
bad value to a clearly non-current 99. AGENTS.md documents both the monotonic
(SQLite SCHEMA_VERSION) and pinned-0 (session log) pre-release stances.

Blocker #2 — restore the late turn-end warn. failTurn now sets the error reason
only while the turn is still open; once turn/end is appended (a throwing
agent/turn-end listener after closeTurn) the reason can no longer reach the
durable log, so the late throw is logged via ctx.logger.warn instead of
vanishing into a futile post-close assignment. A regression test asserts the
warn fires.

Also guard the normal-step assistant/message append with the same
content-or-usage condition as the max-tokens branch (a content-less, usage-less
step records no trace-only row), with a covering test.
2026-06-21 11:08:10 +08:00
Tianyi Cui
d6a2ab30c8 feat(types): brand bash ids + stop brand erosion; extract Branded to dsh-brand
Type-only change (brands are zero-cost casts; no runtime/wire impact). Closes
the two gaps in the "brand ids that cross package boundaries" policy and fixes
the dependency direction so a capability package never pulls in an unrelated one.

- Extract the `Branded<B>` primitive into a new standalone type-only package
  `@deepseek-ai/dsh-brand` (packages/util/brand) with no harness-package deps.
  dsh-llm keeps its owned CallId but imports Branded from dsh-brand; dsh-session,
  dsh-agent, and dsh-bash all import Branded from there. dsh-bash depends on
  dsh-brand ALONE — never on dsh-llm or dsh-session (the architectural fix: a
  generic execution backend must not couple to the LLM or session vocabulary).
- Mint BashTaskId + OwnerToken in dsh-bash and thread them through BashTask.id,
  the get/ownerOf/list/readOutput/kill seam, the bash-local generation site, and
  the dsh-tool-bash validate/access surface. OwnerToken is a DISTINCT brand from
  SessionId so the seam stays decoupled; dsh-tool-bash is the single boundary
  that casts SessionId -> OwnerToken.
- Brand at the SOURCE, not via mid-pipeline casts: agent-loop's Config types
  agents[].id as AgentId and resumeSessionId as SessionId, so the brand enters
  at the config boundary and the inner create()/resume casts disappear (only the
  genuinely-new per-run session-id string is cast).
- Stop brand erosion: propagate CallId/SessionId/AgentId to the registry/store
  Map keys and public params/exports (SessionStore, AgentRegistry + factory
  options, the ACP session-id surface + ToolPresenter CallId map, the
  persistence coordinator, invariants pendingCalls, the pi-ai tool-call maps).
- Docs: document BashTaskId/OwnerToken in bash.md (type-equiv re-pasted), point
  the Branded type-equiv at dsh-brand, fix stale param types in the session/
  agent/bash READMEs, regenerate the cordis catalog + module graph.

Implements docs/rfc/proposed/architecture/2026-06-20-branded-ids.md
2026-06-21 07:19:59 +08:00
Tianyi Cui
5f9d10c587 fix review findings: stale seam docs + race-free doneFor test helper
Codex review of the PR2 diff caught doc/comment sites doc-sync does not gate
(core-data-structures prose) and a latent test-helper race:
- docs/core-data-structures/persistence.md + bash.md, sqlite README, and two
  source comments (coordinator.ts, jsonl.spec.ts) still listed the removed
  has/delete/get/list methods — updated to the surviving four-method
  persistence surface and the get/list-free bash seam.
- doneFor(ctx, id) attached its onTaskDone listener lazily, after the task
  could already have closed (e.g. `true`), so it could miss the completion and
  hang. Replaced with trackCompletions(ctx): one eagerly-installed listener
  (mounted in setup() before any task starts) records every completion, and
  doneFor resolves immediately for an already-finished task or on completion
  otherwise. Race-free, and there is no get-by-id seam left to poll instead.
2026-06-21 02:45:21 +08:00
Tianyi Cui
7792347c4f simplify(seams): prune dead methods from the persistence and bash seams
Two capability seams carried abstract methods no production consumer calls.
A method no consumer programs against is not a seam — it is speculative
surface every implementation must still provide and test.

- SessionPersistence: remove has() and delete(), the coordinator's
  has/delete/deleteCore, and the PersistenceBackend.deleteStored hook (with its
  jsonl + sqlite + in-spec memory-stub impls). Surviving service surface:
  create/append/load/list. Production uses only load() (resume) and list()
  (ACP session/list).
- BashExecutor: remove get(id) and list(), the abstract decls and the
  LocalBashExecutor impls. The internal tasks map survives (it backs
  ownerOf/readOutput/kill); get/list were pure public accessors over it with no
  shipping caller and no bash_list tool.
- Migrate tests that reached through ctx.bash.get(id) to the public completion
  seam: a doneFor(id) helper over onTaskDone awaits a task by id, and the
  HMR-reload ownership test now proves task survival through A's own bash_output
  ([status: running]) plus ownerOf + B-rejection — a stronger through-the-tool
  assertion than the removed lookup peek.
- Update seam READMEs (six -> four service methods, drop the deleteStored hook
  and the get/list row) and the two implemented persistence RFCs in place.

Implements docs/rfc/implemented/simplification/2026-06-20-prune-dead-seam-methods.md
2026-06-21 02:17:27 +08:00
Tianyi Cui
d02e9f1bd6 Reorganize packages into a modular hierarchy
Move the 18 flat packages/<name> packages into role-grouped dirs:
core/, llm/, bash/, session-persistence/, ui/, support/. Group dirs are
pure containers; each package keeps its @deepseek-ai/dsh-* name.

Collapse the per-package tsconfig paths maps (base + typecheck) into one
@deepseek-ai/dsh-* wildcard with a candidate per group, and derive the
publint list from the hierarchy. Update all depth-coupled globs/configs
(workspace, tsdown, vitest, eslint, knip, tsconfig includes/refs,
per-package tsconfigs, generators, doc-script scopes, type-equiv manifest)
and the cross-package/script relative imports in tests.

Fix doc-typecheck's workspacePaths() to parse tsconfig JSONC via the
TypeScript API instead of a regex comment-strip, which corrupted the
new wildcard `/*/` path candidates.

WIP: doc cross-links and package/RFC docs still to update.
2026-06-20 22:55:20 +08:00