@namzu/sdk 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +86 -0
- package/dist/__tests__/replay-public-surface.test.d.ts +2 -0
- package/dist/__tests__/replay-public-surface.test.d.ts.map +1 -0
- package/dist/__tests__/replay-public-surface.test.js +45 -0
- package/dist/__tests__/replay-public-surface.test.js.map +1 -0
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/bridge/a2a/task.d.ts +2 -2
- package/dist/bridge/a2a/task.d.ts.map +1 -1
- package/dist/bridge/a2a/task.js.map +1 -1
- package/dist/config/runtime.d.ts +24 -25
- package/dist/config/runtime.d.ts.map +1 -1
- package/dist/config/runtime.js.map +1 -1
- package/dist/contracts/api.d.ts +2 -2
- package/dist/contracts/api.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +1 -2
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/schemas.d.ts +10 -10
- package/dist/index.d.ts +3 -103
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -89
- package/dist/index.js.map +1 -1
- package/dist/manager/agent/__tests__/lifecycle.test.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts +1 -1
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +1 -1
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/run/persistence.d.ts +3 -3
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/manager/thread/__tests__/lifecycle.test.js.map +1 -1
- package/dist/manager/thread/lifecycle.d.ts +1 -1
- package/dist/manager/thread/lifecycle.d.ts.map +1 -1
- package/dist/plugin/loader.d.ts +0 -5
- package/dist/plugin/loader.d.ts.map +1 -1
- package/dist/plugin/loader.js +1 -13
- package/dist/plugin/loader.js.map +1 -1
- package/dist/public-runtime.d.ts +70 -0
- package/dist/public-runtime.d.ts.map +1 -0
- package/dist/public-runtime.js +108 -0
- package/dist/public-runtime.js.map +1 -0
- package/dist/public-tools.d.ts +19 -0
- package/dist/public-tools.d.ts.map +1 -0
- package/dist/public-tools.js +34 -0
- package/dist/public-tools.js.map +1 -0
- package/dist/public-types.d.ts +55 -0
- package/dist/public-types.d.ts.map +1 -0
- package/dist/public-types.js +14 -0
- package/dist/public-types.js.map +1 -0
- package/dist/rag/rag-tool.d.ts +1 -1
- package/dist/run/LimitChecker.d.ts +0 -1
- package/dist/run/LimitChecker.d.ts.map +1 -1
- package/dist/run/LimitChecker.js +0 -6
- package/dist/run/LimitChecker.js.map +1 -1
- package/dist/run/reporter.d.ts +2 -2
- package/dist/run/reporter.d.ts.map +1 -1
- package/dist/run/reporter.js.map +1 -1
- package/dist/runtime/query/__tests__/checkpoint.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/checkpoint.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/checkpoint.test.js +150 -0
- package/dist/runtime/query/__tests__/checkpoint.test.js.map +1 -0
- package/dist/runtime/query/checkpoint.d.ts +23 -0
- package/dist/runtime/query/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/checkpoint.js +49 -0
- package/dist/runtime/query/checkpoint.js.map +1 -1
- package/dist/runtime/query/context.d.ts +0 -2
- package/dist/runtime/query/context.d.ts.map +1 -1
- package/dist/runtime/query/context.js +0 -4
- package/dist/runtime/query/context.js.map +1 -1
- package/dist/runtime/query/index.d.ts +3 -3
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/replay/__tests__/mutate.test.d.ts +2 -0
- package/dist/runtime/query/replay/__tests__/mutate.test.d.ts.map +1 -0
- package/dist/runtime/query/replay/__tests__/mutate.test.js +123 -0
- package/dist/runtime/query/replay/__tests__/mutate.test.js.map +1 -0
- package/dist/runtime/query/replay/__tests__/prepare.test.d.ts +2 -0
- package/dist/runtime/query/replay/__tests__/prepare.test.d.ts.map +1 -0
- package/dist/runtime/query/replay/__tests__/prepare.test.js +171 -0
- package/dist/runtime/query/replay/__tests__/prepare.test.js.map +1 -0
- package/dist/runtime/query/replay/list.d.ts +24 -0
- package/dist/runtime/query/replay/list.d.ts.map +1 -0
- package/dist/runtime/query/replay/list.js +21 -0
- package/dist/runtime/query/replay/list.js.map +1 -0
- package/dist/runtime/query/replay/mutate.d.ts +17 -0
- package/dist/runtime/query/replay/mutate.d.ts.map +1 -0
- package/dist/runtime/query/replay/mutate.js +62 -0
- package/dist/runtime/query/replay/mutate.js.map +1 -0
- package/dist/runtime/query/replay/prepare.d.ts +56 -0
- package/dist/runtime/query/replay/prepare.d.ts.map +1 -0
- package/dist/runtime/query/replay/prepare.js +65 -0
- package/dist/runtime/query/replay/prepare.js.map +1 -0
- package/dist/runtime/query/result.d.ts +2 -2
- package/dist/runtime/query/result.d.ts.map +1 -1
- package/dist/session/__tests__/integration/_fixtures.d.ts +4 -4
- package/dist/session/__tests__/integration/_fixtures.d.ts.map +1 -1
- package/dist/session/__tests__/integration/_fixtures.js.map +1 -1
- package/dist/session/__tests__/integration/archive-gate.test.js.map +1 -1
- package/dist/session/__tests__/integration/capacity-caps.test.js.map +1 -1
- package/dist/session/__tests__/integration/e2e-spawn.test.js.map +1 -1
- package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js.map +1 -1
- package/dist/session/__tests__/integration/handoff-single-e2e.test.js.map +1 -1
- package/dist/session/__tests__/integration/prev-artifact-dag.test.js.map +1 -1
- package/dist/session/__tests__/integration/retention-archive.test.js.map +1 -1
- package/dist/session/__tests__/integration/spawn-rollback.test.js.map +1 -1
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.js +1 -1
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.js.map +1 -1
- package/dist/session/errors.d.ts +1 -1
- package/dist/session/errors.d.ts.map +1 -1
- package/dist/session/events/index.d.ts +3 -3
- package/dist/session/events/index.d.ts.map +1 -1
- package/dist/session/events/index.js +3 -2
- package/dist/session/events/index.js.map +1 -1
- package/dist/session/handoff/__tests__/broadcast.test.js.map +1 -1
- package/dist/session/handoff/__tests__/capacity.test.js.map +1 -1
- package/dist/session/handoff/__tests__/single.test.js.map +1 -1
- package/dist/session/handoff/assignment.d.ts +1 -1
- package/dist/session/handoff/assignment.d.ts.map +1 -1
- package/dist/session/handoff/broadcast.d.ts.map +1 -1
- package/dist/session/handoff/broadcast.js.map +1 -1
- package/dist/session/handoff/single.d.ts.map +1 -1
- package/dist/session/handoff/single.js.map +1 -1
- package/dist/session/index.d.ts +0 -1
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +7 -6
- package/dist/session/index.js.map +1 -1
- package/dist/session/intervention/__tests__/prev-artifact.test.js.map +1 -1
- package/dist/session/intervention/prev-artifact.d.ts +1 -1
- package/dist/session/intervention/prev-artifact.d.ts.map +1 -1
- package/dist/session/retention/__tests__/archive.test.js.map +1 -1
- package/dist/session/retention/__tests__/disk-backend.test.js.map +1 -1
- package/dist/session/retention/archive.d.ts +1 -1
- package/dist/session/retention/archive.d.ts.map +1 -1
- package/dist/session/retention/backend.d.ts +4 -4
- package/dist/session/retention/backend.d.ts.map +1 -1
- package/dist/session/retention/disk-backend.d.ts +1 -1
- package/dist/session/retention/disk-backend.d.ts.map +1 -1
- package/dist/session/retention/index.d.ts +3 -3
- package/dist/session/retention/index.d.ts.map +1 -1
- package/dist/session/retention/index.js +4 -2
- package/dist/session/retention/index.js.map +1 -1
- package/dist/session/status/__tests__/derive.test.d.ts +2 -0
- package/dist/session/status/__tests__/derive.test.d.ts.map +1 -0
- package/dist/session/{hierarchy/__tests__/session.test.js → status/__tests__/derive.test.js} +2 -2
- package/dist/session/status/__tests__/derive.test.js.map +1 -0
- package/dist/session/status/derive.d.ts +33 -0
- package/dist/session/status/derive.d.ts.map +1 -0
- package/dist/session/{hierarchy/session.js → status/derive.js} +6 -1
- package/dist/session/status/derive.js.map +1 -0
- package/dist/session/summary/__tests__/materialize.test.js +2 -1
- package/dist/session/summary/__tests__/materialize.test.js.map +1 -1
- package/dist/session/summary/errors.d.ts +43 -0
- package/dist/session/summary/errors.d.ts.map +1 -0
- package/dist/session/summary/errors.js +37 -0
- package/dist/session/summary/errors.js.map +1 -0
- package/dist/session/summary/index.d.ts +4 -3
- package/dist/session/summary/index.d.ts.map +1 -1
- package/dist/session/summary/index.js +5 -4
- package/dist/session/summary/index.js.map +1 -1
- package/dist/session/summary/materialize.d.ts +2 -2
- package/dist/session/summary/materialize.d.ts.map +1 -1
- package/dist/session/summary/materialize.js +2 -1
- package/dist/session/summary/materialize.js.map +1 -1
- package/dist/session/workspace/__tests__/git-worktree.test.js.map +1 -1
- package/dist/session/workspace/driver.d.ts +2 -2
- package/dist/session/workspace/driver.d.ts.map +1 -1
- package/dist/session/workspace/git-worktree.d.ts +1 -1
- package/dist/session/workspace/git-worktree.d.ts.map +1 -1
- package/dist/session/workspace/git-worktree.js.map +1 -1
- package/dist/session/workspace/index.d.ts +1 -1
- package/dist/session/workspace/index.d.ts.map +1 -1
- package/dist/session/workspace/index.js +3 -2
- package/dist/session/workspace/index.js.map +1 -1
- package/dist/store/run/disk.d.ts +4 -4
- package/dist/store/run/disk.d.ts.map +1 -1
- package/dist/store/run/disk.js.map +1 -1
- package/dist/store/session/__tests__/disk.test.js.map +1 -1
- package/dist/store/session/__tests__/memory.test.js.map +1 -1
- package/dist/store/session/disk.d.ts +6 -6
- package/dist/store/session/disk.d.ts.map +1 -1
- package/dist/store/session/disk.js +1 -1
- package/dist/store/session/disk.js.map +1 -1
- package/dist/store/session/index.d.ts +1 -1
- package/dist/store/session/index.d.ts.map +1 -1
- package/dist/store/session/index.js +2 -1
- package/dist/store/session/index.js.map +1 -1
- package/dist/store/session/linkage.d.ts +1 -1
- package/dist/store/session/linkage.d.ts.map +1 -1
- package/dist/store/session/memory.d.ts +5 -5
- package/dist/store/session/memory.d.ts.map +1 -1
- package/dist/store/session/memory.js +1 -1
- package/dist/store/session/memory.js.map +1 -1
- package/dist/store/thread/disk.d.ts +1 -1
- package/dist/store/thread/disk.d.ts.map +1 -1
- package/dist/store/thread/memory.d.ts +1 -1
- package/dist/store/thread/memory.d.ts.map +1 -1
- package/dist/telemetry/attributes.d.ts +0 -1
- package/dist/telemetry/attributes.d.ts.map +1 -1
- package/dist/telemetry/attributes.js +0 -3
- package/dist/telemetry/attributes.js.map +1 -1
- package/dist/telemetry/runtime-accessors.d.ts +1 -2
- package/dist/telemetry/runtime-accessors.d.ts.map +1 -1
- package/dist/telemetry/runtime-accessors.js +1 -4
- package/dist/telemetry/runtime-accessors.js.map +1 -1
- package/dist/tools/builtins/bash.d.ts +1 -1
- package/dist/tools/builtins/computer-use.d.ts +4 -4
- package/dist/tools/builtins/edit.d.ts +1 -1
- package/dist/tools/builtins/glob.d.ts +1 -1
- package/dist/tools/builtins/grep.d.ts +1 -1
- package/dist/tools/builtins/ls.d.ts +1 -1
- package/dist/tools/builtins/read-file.d.ts +1 -1
- package/dist/tools/builtins/search-tools.d.ts +1 -1
- package/dist/tools/builtins/write-file.d.ts +1 -1
- package/dist/types/agent/task.d.ts +2 -2
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/{session/hierarchy/project.d.ts → types/project/entity.d.ts} +4 -4
- package/dist/types/project/entity.d.ts.map +1 -0
- package/dist/types/project/entity.js +2 -0
- package/dist/types/project/entity.js.map +1 -0
- package/dist/types/project/index.d.ts +2 -0
- package/dist/types/project/index.d.ts.map +1 -0
- package/dist/types/project/index.js +4 -0
- package/dist/types/project/index.js.map +1 -0
- package/dist/types/retention/archive-backend-ref.d.ts.map +1 -0
- package/dist/types/retention/archive-backend-ref.js.map +1 -0
- package/dist/types/retention/index.d.ts +4 -0
- package/dist/types/retention/index.d.ts.map +1 -0
- package/dist/types/retention/index.js +4 -0
- package/dist/types/retention/index.js.map +1 -0
- package/dist/types/retention/policy.d.ts.map +1 -0
- package/dist/types/retention/policy.js.map +1 -0
- package/dist/types/run/entity.d.ts +56 -0
- package/dist/types/run/entity.d.ts.map +1 -0
- package/dist/types/run/entity.js +2 -0
- package/dist/types/run/entity.js.map +1 -0
- package/dist/types/run/events.d.ts +2 -2
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/index.d.ts +7 -1
- package/dist/types/run/index.d.ts.map +1 -1
- package/dist/types/run/index.js +8 -9
- package/dist/types/run/index.js.map +1 -1
- package/dist/{session/hierarchy → types/run}/lineage.d.ts +1 -1
- package/dist/types/run/lineage.d.ts.map +1 -0
- package/dist/types/run/lineage.js.map +1 -0
- package/dist/types/run/replay.d.ts +53 -0
- package/dist/types/run/replay.d.ts.map +1 -0
- package/dist/types/run/replay.js +15 -0
- package/dist/types/run/replay.js.map +1 -0
- package/dist/types/run/schema-version.d.ts.map +1 -0
- package/dist/types/run/schema-version.js.map +1 -0
- package/dist/{session/events/types.d.ts → types/run/subsession-events.d.ts} +5 -5
- package/dist/types/run/subsession-events.d.ts.map +1 -0
- package/dist/types/run/subsession-events.js +2 -0
- package/dist/types/run/subsession-events.js.map +1 -0
- package/dist/{session/hierarchy → types/session}/actor.d.ts +1 -1
- package/dist/types/session/actor.d.ts.map +1 -0
- package/dist/{session/hierarchy → types/session}/actor.js.map +1 -1
- package/dist/types/session/entity.d.ts +51 -0
- package/dist/types/session/entity.d.ts.map +1 -0
- package/dist/types/session/entity.js +2 -0
- package/dist/types/session/entity.js.map +1 -0
- package/dist/types/session/index.d.ts +4 -0
- package/dist/types/session/index.d.ts.map +1 -1
- package/dist/{store → types}/session/messages.d.ts +2 -2
- package/dist/{store → types}/session/messages.d.ts.map +1 -1
- package/dist/types/session/messages.js.map +1 -0
- package/dist/types/session/store.d.ts +6 -6
- package/dist/types/session/store.d.ts.map +1 -1
- package/dist/{session/hierarchy → types/session}/sub-session.d.ts +9 -9
- package/dist/types/session/sub-session.d.ts.map +1 -0
- package/dist/types/session/sub-session.js.map +1 -0
- package/dist/{session → types}/summary/deliverable.d.ts +2 -2
- package/dist/types/summary/deliverable.d.ts.map +1 -0
- package/dist/types/summary/deliverable.js.map +1 -0
- package/dist/types/summary/index.d.ts +4 -0
- package/dist/types/summary/index.d.ts.map +1 -0
- package/dist/types/summary/index.js +4 -0
- package/dist/types/summary/index.js.map +1 -0
- package/dist/{session → types}/summary/ref.d.ts +9 -36
- package/dist/types/summary/ref.d.ts.map +1 -0
- package/dist/types/summary/ref.js +28 -0
- package/dist/types/summary/ref.js.map +1 -0
- package/dist/{session/hierarchy/tenant.d.ts → types/tenant/entity.d.ts} +2 -2
- package/dist/types/tenant/entity.d.ts.map +1 -0
- package/dist/types/tenant/entity.js +2 -0
- package/dist/types/tenant/entity.js.map +1 -0
- package/dist/types/tenant/index.d.ts +2 -0
- package/dist/types/tenant/index.d.ts.map +1 -0
- package/dist/types/tenant/index.js +4 -0
- package/dist/types/tenant/index.js.map +1 -0
- package/dist/{session/hierarchy/thread.d.ts → types/thread/entity.d.ts} +31 -7
- package/dist/types/thread/entity.d.ts.map +1 -0
- package/dist/types/thread/entity.js +2 -0
- package/dist/types/thread/entity.js.map +1 -0
- package/dist/types/thread/index.d.ts +1 -0
- package/dist/types/thread/index.d.ts.map +1 -1
- package/dist/types/thread/store.d.ts +1 -1
- package/dist/types/thread/store.d.ts.map +1 -1
- package/dist/types/workspace/index.d.ts +2 -0
- package/dist/types/workspace/index.d.ts.map +1 -0
- package/dist/types/workspace/index.js +7 -0
- package/dist/types/workspace/index.js.map +1 -0
- package/dist/{session → types}/workspace/ref.d.ts +1 -1
- package/dist/types/workspace/ref.d.ts.map +1 -0
- package/dist/types/workspace/ref.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/replay-public-surface.test.ts +54 -0
- package/src/agents/SupervisorAgent.ts +1 -1
- package/src/bridge/a2a/task.ts +4 -4
- package/src/config/runtime.ts +0 -2
- package/src/contracts/api.ts +2 -2
- package/src/contracts/index.ts +1 -3
- package/src/index.ts +11 -362
- package/src/manager/agent/__tests__/lifecycle.test.ts +2 -2
- package/src/manager/agent/lifecycle.ts +5 -5
- package/src/manager/run/persistence.ts +4 -4
- package/src/manager/thread/__tests__/lifecycle.test.ts +1 -1
- package/src/manager/thread/lifecycle.ts +2 -2
- package/src/plugin/loader.ts +0 -16
- package/src/public-runtime.ts +373 -0
- package/src/public-tools.ts +63 -0
- package/src/public-types.ts +156 -0
- package/src/run/LimitChecker.ts +0 -9
- package/src/run/reporter.ts +3 -3
- package/src/runtime/query/__tests__/checkpoint.test.ts +169 -0
- package/src/runtime/query/checkpoint.ts +54 -0
- package/src/runtime/query/context.ts +0 -5
- package/src/runtime/query/index.ts +4 -4
- package/src/runtime/query/replay/__tests__/mutate.test.ts +134 -0
- package/src/runtime/query/replay/__tests__/prepare.test.ts +207 -0
- package/src/runtime/query/replay/list.ts +32 -0
- package/src/runtime/query/replay/mutate.ts +76 -0
- package/src/runtime/query/replay/prepare.ts +114 -0
- package/src/runtime/query/result.ts +2 -2
- package/src/session/__tests__/integration/_fixtures.ts +2 -2
- package/src/session/__tests__/integration/archive-gate.test.ts +1 -1
- package/src/session/__tests__/integration/capacity-caps.test.ts +1 -1
- package/src/session/__tests__/integration/e2e-spawn.test.ts +1 -1
- package/src/session/__tests__/integration/handoff-broadcast-e2e.test.ts +1 -1
- package/src/session/__tests__/integration/handoff-single-e2e.test.ts +1 -1
- package/src/session/__tests__/integration/prev-artifact-dag.test.ts +4 -1
- package/src/session/__tests__/integration/retention-archive.test.ts +1 -1
- package/src/session/__tests__/integration/spawn-rollback.test.ts +2 -2
- package/src/session/__tests__/integration/summary-materialization-e2e.test.ts +1 -1
- package/src/session/errors.ts +1 -1
- package/src/session/events/index.ts +5 -4
- package/src/session/handoff/__tests__/broadcast.test.ts +1 -1
- package/src/session/handoff/__tests__/capacity.test.ts +1 -1
- package/src/session/handoff/__tests__/single.test.ts +1 -1
- package/src/session/handoff/assignment.ts +1 -1
- package/src/session/handoff/broadcast.ts +2 -2
- package/src/session/handoff/single.ts +2 -2
- package/src/session/index.ts +7 -6
- package/src/session/intervention/__tests__/prev-artifact.test.ts +4 -1
- package/src/session/intervention/prev-artifact.ts +1 -1
- package/src/session/retention/__tests__/archive.test.ts +3 -3
- package/src/session/retention/__tests__/disk-backend.test.ts +4 -4
- package/src/session/retention/archive.ts +2 -2
- package/src/session/retention/backend.ts +4 -4
- package/src/session/retention/disk-backend.ts +4 -4
- package/src/session/retention/index.ts +6 -4
- package/src/session/{hierarchy/__tests__/session.test.ts → status/__tests__/derive.test.ts} +3 -2
- package/src/session/{hierarchy/session.ts → status/derive.ts} +9 -55
- package/src/session/summary/__tests__/materialize.test.ts +4 -7
- package/src/session/summary/errors.ts +51 -0
- package/src/session/summary/index.ts +7 -10
- package/src/session/summary/materialize.ts +4 -5
- package/src/session/workspace/__tests__/git-worktree.test.ts +1 -1
- package/src/session/workspace/driver.ts +2 -2
- package/src/session/workspace/git-worktree.ts +1 -1
- package/src/session/workspace/index.ts +7 -6
- package/src/store/run/disk.ts +4 -4
- package/src/store/session/__tests__/disk.test.ts +2 -2
- package/src/store/session/__tests__/memory.test.ts +2 -2
- package/src/store/session/disk.ts +12 -12
- package/src/store/session/index.ts +3 -2
- package/src/store/session/linkage.ts +1 -1
- package/src/store/session/memory.ts +6 -6
- package/src/store/thread/disk.ts +1 -1
- package/src/store/thread/memory.ts +1 -1
- package/src/telemetry/attributes.ts +0 -4
- package/src/telemetry/runtime-accessors.ts +1 -5
- package/src/types/agent/task.ts +2 -2
- package/src/{session/hierarchy/project.ts → types/project/entity.ts} +3 -3
- package/src/types/project/index.ts +4 -0
- package/src/types/retention/index.ts +6 -0
- package/src/types/run/entity.ts +63 -0
- package/src/types/run/events.ts +6 -6
- package/src/types/run/index.ts +16 -9
- package/src/{session/hierarchy → types/run}/lineage.ts +1 -1
- package/src/types/run/replay.ts +61 -0
- package/src/{session/events/types.ts → types/run/subsession-events.ts} +4 -4
- package/src/{session/hierarchy → types/session}/actor.ts +1 -1
- package/src/types/session/entity.ts +59 -0
- package/src/types/session/index.ts +15 -0
- package/src/{store → types}/session/messages.ts +2 -2
- package/src/types/session/store.ts +6 -6
- package/src/{session/hierarchy → types/session}/sub-session.ts +9 -9
- package/src/{session → types}/summary/deliverable.ts +2 -2
- package/src/types/summary/index.ts +18 -0
- package/src/{session → types}/summary/ref.ts +9 -44
- package/src/{session/hierarchy/tenant.ts → types/tenant/entity.ts} +1 -1
- package/src/types/tenant/index.ts +4 -0
- package/src/{session/hierarchy/thread.ts → types/thread/entity.ts} +30 -6
- package/src/types/thread/index.ts +1 -0
- package/src/types/thread/store.ts +1 -1
- package/src/types/workspace/index.ts +12 -0
- package/src/{session → types}/workspace/ref.ts +1 -1
- package/dist/contracts/ids.d.ts +0 -2
- package/dist/contracts/ids.d.ts.map +0 -1
- package/dist/contracts/ids.js +0 -2
- package/dist/contracts/ids.js.map +0 -1
- package/dist/session/events/schema-version.d.ts.map +0 -1
- package/dist/session/events/schema-version.js.map +0 -1
- package/dist/session/events/types.d.ts.map +0 -1
- package/dist/session/events/types.js +0 -2
- package/dist/session/events/types.js.map +0 -1
- package/dist/session/hierarchy/__tests__/session.test.d.ts +0 -2
- package/dist/session/hierarchy/__tests__/session.test.d.ts.map +0 -1
- package/dist/session/hierarchy/__tests__/session.test.js.map +0 -1
- package/dist/session/hierarchy/actor.d.ts.map +0 -1
- package/dist/session/hierarchy/index.d.ts +0 -9
- package/dist/session/hierarchy/index.d.ts.map +0 -1
- package/dist/session/hierarchy/index.js +0 -4
- package/dist/session/hierarchy/index.js.map +0 -1
- package/dist/session/hierarchy/lineage.d.ts.map +0 -1
- package/dist/session/hierarchy/lineage.js.map +0 -1
- package/dist/session/hierarchy/project.d.ts.map +0 -1
- package/dist/session/hierarchy/project.js +0 -2
- package/dist/session/hierarchy/project.js.map +0 -1
- package/dist/session/hierarchy/session.d.ts +0 -71
- package/dist/session/hierarchy/session.d.ts.map +0 -1
- package/dist/session/hierarchy/session.js.map +0 -1
- package/dist/session/hierarchy/sub-session.d.ts.map +0 -1
- package/dist/session/hierarchy/sub-session.js.map +0 -1
- package/dist/session/hierarchy/tenant.d.ts.map +0 -1
- package/dist/session/hierarchy/tenant.js +0 -2
- package/dist/session/hierarchy/tenant.js.map +0 -1
- package/dist/session/hierarchy/thread.d.ts.map +0 -1
- package/dist/session/hierarchy/thread.js +0 -2
- package/dist/session/hierarchy/thread.js.map +0 -1
- package/dist/session/retention/archive-backend-ref.d.ts.map +0 -1
- package/dist/session/retention/archive-backend-ref.js.map +0 -1
- package/dist/session/retention/policy.d.ts.map +0 -1
- package/dist/session/retention/policy.js.map +0 -1
- package/dist/session/summary/deliverable.d.ts.map +0 -1
- package/dist/session/summary/deliverable.js.map +0 -1
- package/dist/session/summary/ref.d.ts.map +0 -1
- package/dist/session/summary/ref.js +0 -51
- package/dist/session/summary/ref.js.map +0 -1
- package/dist/session/workspace/ref.d.ts.map +0 -1
- package/dist/session/workspace/ref.js.map +0 -1
- package/dist/store/session/messages.js.map +0 -1
- package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts +0 -140
- package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts.map +0 -1
- package/dist/tools/builtins/__tests__/structuredOutput.example.js +0 -183
- package/dist/tools/builtins/__tests__/structuredOutput.example.js.map +0 -1
- package/dist/types/run/state.d.ts +0 -30
- package/dist/types/run/state.d.ts.map +0 -1
- package/dist/types/run/state.js +0 -2
- package/dist/types/run/state.js.map +0 -1
- package/src/contracts/ids.ts +0 -1
- package/src/session/hierarchy/index.ts +0 -18
- package/src/tools/builtins/__tests__/structuredOutput.example.ts +0 -221
- package/src/types/run/state.ts +0 -35
- /package/dist/{session → types}/retention/archive-backend-ref.d.ts +0 -0
- /package/dist/{session → types}/retention/archive-backend-ref.js +0 -0
- /package/dist/{session → types}/retention/policy.d.ts +0 -0
- /package/dist/{session → types}/retention/policy.js +0 -0
- /package/dist/{session/hierarchy → types/run}/lineage.js +0 -0
- /package/dist/{session/events → types/run}/schema-version.d.ts +0 -0
- /package/dist/{session/events → types/run}/schema-version.js +0 -0
- /package/dist/{session/hierarchy → types/session}/actor.js +0 -0
- /package/dist/{store → types}/session/messages.js +0 -0
- /package/dist/{session/hierarchy → types/session}/sub-session.js +0 -0
- /package/dist/{session → types}/summary/deliverable.js +0 -0
- /package/dist/{session → types}/workspace/ref.js +0 -0
- /package/src/{session → types}/retention/archive-backend-ref.ts +0 -0
- /package/src/{session → types}/retention/policy.ts +0 -0
- /package/src/{session/events → types/run}/schema-version.ts +0 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import type { RunDiskStore } from '../../../store/run/disk.js'
|
|
3
|
+
import type { CheckpointId, IterationCheckpoint } from '../../../types/hitl/index.js'
|
|
4
|
+
import type { EmergencySaveId, RunId } from '../../../types/ids/index.js'
|
|
5
|
+
import type { EmergencySaveData } from '../../../types/run/emergency.js'
|
|
6
|
+
import { CheckpointManager, projectEmergencyToCheckpoint } from '../checkpoint.js'
|
|
7
|
+
|
|
8
|
+
function makeCheckpoint(overrides: Partial<IterationCheckpoint> = {}): IterationCheckpoint {
|
|
9
|
+
return {
|
|
10
|
+
id: 'cp_test_a' as CheckpointId,
|
|
11
|
+
runId: 'run_test' as RunId,
|
|
12
|
+
iteration: 1,
|
|
13
|
+
messages: [{ role: 'user', content: 'hello' }],
|
|
14
|
+
tokenUsage: {
|
|
15
|
+
promptTokens: 0,
|
|
16
|
+
completionTokens: 0,
|
|
17
|
+
totalTokens: 0,
|
|
18
|
+
cachedTokens: 0,
|
|
19
|
+
cacheWriteTokens: 0,
|
|
20
|
+
},
|
|
21
|
+
costInfo: {
|
|
22
|
+
inputCostPer1M: 0,
|
|
23
|
+
outputCostPer1M: 0,
|
|
24
|
+
totalCost: 0,
|
|
25
|
+
cacheDiscount: 0,
|
|
26
|
+
},
|
|
27
|
+
guardState: { iterationCount: 1, elapsedMs: 100 },
|
|
28
|
+
createdAt: Date.now(),
|
|
29
|
+
...overrides,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function makeStoreStub(checkpoints: IterationCheckpoint[]): RunDiskStore {
|
|
34
|
+
return {
|
|
35
|
+
listCheckpoints: async () => checkpoints,
|
|
36
|
+
} as unknown as RunDiskStore
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('CheckpointManager.listEntries', () => {
|
|
40
|
+
it('projects stored checkpoints to CheckpointListEntry', async () => {
|
|
41
|
+
const store = makeStoreStub([
|
|
42
|
+
makeCheckpoint({
|
|
43
|
+
id: 'cp_a' as CheckpointId,
|
|
44
|
+
iteration: 1,
|
|
45
|
+
createdAt: 1000,
|
|
46
|
+
messages: [
|
|
47
|
+
{ role: 'user', content: 'hi' },
|
|
48
|
+
{ role: 'assistant', content: 'hello' },
|
|
49
|
+
],
|
|
50
|
+
}),
|
|
51
|
+
makeCheckpoint({
|
|
52
|
+
id: 'cp_b' as CheckpointId,
|
|
53
|
+
iteration: 2,
|
|
54
|
+
createdAt: 2000,
|
|
55
|
+
messages: [
|
|
56
|
+
{ role: 'user', content: 'hi' },
|
|
57
|
+
{ role: 'assistant', content: 'hello' },
|
|
58
|
+
{ role: 'user', content: 'more' },
|
|
59
|
+
],
|
|
60
|
+
}),
|
|
61
|
+
])
|
|
62
|
+
|
|
63
|
+
const mgr = new CheckpointManager(store)
|
|
64
|
+
const entries = await mgr.listEntries()
|
|
65
|
+
|
|
66
|
+
expect(entries).toHaveLength(2)
|
|
67
|
+
expect(entries[0]).toEqual({
|
|
68
|
+
id: 'cp_a',
|
|
69
|
+
runId: 'run_test',
|
|
70
|
+
iteration: 1,
|
|
71
|
+
createdAt: 1000,
|
|
72
|
+
messageCount: 2,
|
|
73
|
+
})
|
|
74
|
+
expect(entries[1]).toEqual({
|
|
75
|
+
id: 'cp_b',
|
|
76
|
+
runId: 'run_test',
|
|
77
|
+
iteration: 2,
|
|
78
|
+
createdAt: 2000,
|
|
79
|
+
messageCount: 3,
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('returns empty array when no checkpoints exist', async () => {
|
|
84
|
+
const mgr = new CheckpointManager(makeStoreStub([]))
|
|
85
|
+
expect(await mgr.listEntries()).toEqual([])
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('does not include full checkpoint payload fields', async () => {
|
|
89
|
+
const mgr = new CheckpointManager(
|
|
90
|
+
makeStoreStub([
|
|
91
|
+
makeCheckpoint({
|
|
92
|
+
toolResultHashes: { call_x: 'hash' },
|
|
93
|
+
branchStack: [{ agentId: 'a', decision: 'd', confidence: 1, timestamp: 0 }],
|
|
94
|
+
}),
|
|
95
|
+
]),
|
|
96
|
+
)
|
|
97
|
+
const [entry] = await mgr.listEntries()
|
|
98
|
+
expect(entry).not.toHaveProperty('tokenUsage')
|
|
99
|
+
expect(entry).not.toHaveProperty('costInfo')
|
|
100
|
+
expect(entry).not.toHaveProperty('toolResultHashes')
|
|
101
|
+
expect(entry).not.toHaveProperty('branchStack')
|
|
102
|
+
expect(entry).not.toHaveProperty('guardState')
|
|
103
|
+
expect(entry).not.toHaveProperty('messages')
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
function makeEmergencyDump(overrides: Partial<EmergencySaveData> = {}): EmergencySaveData {
|
|
108
|
+
return {
|
|
109
|
+
id: 'esave_dump_a' as EmergencySaveId,
|
|
110
|
+
runId: 'run_victim' as RunId,
|
|
111
|
+
messages: [
|
|
112
|
+
{ role: 'user', content: 'before the crash' },
|
|
113
|
+
{ role: 'assistant', content: 'working' },
|
|
114
|
+
],
|
|
115
|
+
tokenUsage: {
|
|
116
|
+
promptTokens: 10,
|
|
117
|
+
completionTokens: 5,
|
|
118
|
+
totalTokens: 15,
|
|
119
|
+
cachedTokens: 0,
|
|
120
|
+
cacheWriteTokens: 0,
|
|
121
|
+
},
|
|
122
|
+
currentIteration: 7,
|
|
123
|
+
startedAt: 1_000,
|
|
124
|
+
savedAt: 2_500,
|
|
125
|
+
processSignal: 'SIGTERM',
|
|
126
|
+
...overrides,
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
describe('projectEmergencyToCheckpoint', () => {
|
|
131
|
+
it('produces an IterationCheckpoint with all required fields', () => {
|
|
132
|
+
const dump = makeEmergencyDump()
|
|
133
|
+
const cp = projectEmergencyToCheckpoint(dump)
|
|
134
|
+
|
|
135
|
+
expect(cp.runId).toBe('run_victim')
|
|
136
|
+
expect(cp.iteration).toBe(7)
|
|
137
|
+
expect(cp.messages).toBe(dump.messages)
|
|
138
|
+
expect(cp.tokenUsage).toBe(dump.tokenUsage)
|
|
139
|
+
expect(cp.createdAt).toBe(2_500)
|
|
140
|
+
expect(cp.guardState).toEqual({ iterationCount: 7, elapsedMs: 1_500 })
|
|
141
|
+
expect(cp.costInfo).toEqual({
|
|
142
|
+
inputCostPer1M: 0,
|
|
143
|
+
outputCostPer1M: 0,
|
|
144
|
+
totalCost: 0,
|
|
145
|
+
cacheDiscount: 0,
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('derives a deterministic CheckpointId from the emergency save id', () => {
|
|
150
|
+
const dump = makeEmergencyDump({ id: 'esave_xyz123' as EmergencySaveId })
|
|
151
|
+
const cp1 = projectEmergencyToCheckpoint(dump)
|
|
152
|
+
const cp2 = projectEmergencyToCheckpoint(dump)
|
|
153
|
+
|
|
154
|
+
expect(cp1.id).toBe('cp_emergency_xyz123')
|
|
155
|
+
expect(cp1.id).toBe(cp2.id)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it('clamps guardState.elapsedMs to 0 when savedAt precedes startedAt', () => {
|
|
159
|
+
const cp = projectEmergencyToCheckpoint(makeEmergencyDump({ startedAt: 2_000, savedAt: 1_000 }))
|
|
160
|
+
expect(cp.guardState.elapsedMs).toBe(0)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it('leaves optional fields (toolResultHashes, branchStack, activeNode) unset', () => {
|
|
164
|
+
const cp = projectEmergencyToCheckpoint(makeEmergencyDump())
|
|
165
|
+
expect(cp.toolResultHashes).toBeUndefined()
|
|
166
|
+
expect(cp.branchStack).toBeUndefined()
|
|
167
|
+
expect(cp.activeNode).toBeUndefined()
|
|
168
|
+
})
|
|
169
|
+
})
|
|
@@ -8,9 +8,52 @@ import type {
|
|
|
8
8
|
IterationCheckpoint,
|
|
9
9
|
} from '../../types/hitl/index.js'
|
|
10
10
|
import type { AssistantMessage } from '../../types/message/index.js'
|
|
11
|
+
import type { EmergencySaveData } from '../../types/run/emergency.js'
|
|
12
|
+
import type { CheckpointListEntry } from '../../types/run/replay.js'
|
|
13
|
+
import { ZERO_COST } from '../../utils/cost.js'
|
|
11
14
|
import { buildToolResultHashes } from '../../utils/hash.js'
|
|
12
15
|
import { generateCheckpointId } from '../../utils/id.js'
|
|
13
16
|
|
|
17
|
+
function toCheckpointListEntry(cp: IterationCheckpoint): CheckpointListEntry {
|
|
18
|
+
return {
|
|
19
|
+
id: cp.id,
|
|
20
|
+
runId: cp.runId,
|
|
21
|
+
iteration: cp.iteration,
|
|
22
|
+
createdAt: cp.createdAt,
|
|
23
|
+
messageCount: cp.messages.length,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Project an {@link EmergencySaveData} dump to an {@link IterationCheckpoint}
|
|
29
|
+
* shape so `replay({ fromCheckpoint: 'emergency' })` can consume it through
|
|
30
|
+
* the same restore path as any other checkpoint.
|
|
31
|
+
*
|
|
32
|
+
* The projection is lossy: `costInfo`, `guardState.elapsedMs`,
|
|
33
|
+
* `toolResultHashes`, `branchStack`, and `activeNode` are not captured at
|
|
34
|
+
* emergency-save time and default to zero/empty values. The synthetic
|
|
35
|
+
* checkpoint id is derived deterministically from the emergency save id so
|
|
36
|
+
* re-projecting the same dump yields the same {@link CheckpointId}.
|
|
37
|
+
*
|
|
38
|
+
* See ses_005-deterministic-replay design §2 + §5.2.
|
|
39
|
+
*/
|
|
40
|
+
export function projectEmergencyToCheckpoint(dump: EmergencySaveData): IterationCheckpoint {
|
|
41
|
+
const emergencySuffix = dump.id.replace(/^esave_/, '')
|
|
42
|
+
return {
|
|
43
|
+
id: `cp_emergency_${emergencySuffix}` as CheckpointId,
|
|
44
|
+
runId: dump.runId,
|
|
45
|
+
iteration: dump.currentIteration,
|
|
46
|
+
messages: dump.messages,
|
|
47
|
+
tokenUsage: dump.tokenUsage,
|
|
48
|
+
costInfo: { ...ZERO_COST },
|
|
49
|
+
guardState: {
|
|
50
|
+
iterationCount: dump.currentIteration,
|
|
51
|
+
elapsedMs: Math.max(0, dump.savedAt - dump.startedAt),
|
|
52
|
+
},
|
|
53
|
+
createdAt: dump.savedAt,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
14
57
|
export class CheckpointManager {
|
|
15
58
|
private store: RunDiskStore
|
|
16
59
|
|
|
@@ -60,6 +103,17 @@ export class CheckpointManager {
|
|
|
60
103
|
return this.store.listCheckpoints()
|
|
61
104
|
}
|
|
62
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Listing projection used by the public `listCheckpoints` API. Returns
|
|
108
|
+
* only the fields a consumer needs to pick a fork point for
|
|
109
|
+
* {@link import('./replay/prepare.js').prepareReplayState} — not the
|
|
110
|
+
* full checkpoint payload. See ses_005-deterministic-replay design §3.1.
|
|
111
|
+
*/
|
|
112
|
+
async listEntries(): Promise<CheckpointListEntry[]> {
|
|
113
|
+
const checkpoints = await this.store.listCheckpoints()
|
|
114
|
+
return checkpoints.map(toCheckpointListEntry)
|
|
115
|
+
}
|
|
116
|
+
|
|
63
117
|
async prune(keepLast: number): Promise<void> {
|
|
64
118
|
const all = await this.list()
|
|
65
119
|
if (all.length <= keepLast) return
|
|
@@ -99,11 +99,6 @@ export interface RunContext {
|
|
|
99
99
|
*/
|
|
100
100
|
const migrationPromises = new Map<string, Promise<FilesystemMigrationResult>>()
|
|
101
101
|
|
|
102
|
-
/** Testing hook — clears the first-call guard cache. */
|
|
103
|
-
export function __resetMigrationGuardForTests(): void {
|
|
104
|
-
migrationPromises.clear()
|
|
105
|
-
}
|
|
106
|
-
|
|
107
102
|
export class RunContextFactory {
|
|
108
103
|
/**
|
|
109
104
|
* Run the boot-time filesystem migration for `rootDir` at most once per
|
|
@@ -27,7 +27,7 @@ import { type Message, createSystemMessage } from '../../types/message/index.js'
|
|
|
27
27
|
import type { AgentPersona } from '../../types/persona/index.js'
|
|
28
28
|
import type { LLMProvider } from '../../types/provider/index.js'
|
|
29
29
|
import type { TaskRouterConfig } from '../../types/router/index.js'
|
|
30
|
-
import type {
|
|
30
|
+
import type { AgentRunConfig, Run, RunEvent, RunEventListener } from '../../types/run/index.js'
|
|
31
31
|
import type { Sandbox, SandboxProvider } from '../../types/sandbox/index.js'
|
|
32
32
|
import type { ProjectId, ThreadId } from '../../types/session/ids.js'
|
|
33
33
|
import type { Skill } from '../../types/skills/index.js'
|
|
@@ -136,7 +136,7 @@ export interface QueryParams {
|
|
|
136
136
|
invocationState?: InvocationState
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
export async function* query(params: QueryParams): AsyncGenerator<RunEvent,
|
|
139
|
+
export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run> {
|
|
140
140
|
// Boot-time filesystem migration (session-hierarchy.md §13.4.1). First
|
|
141
141
|
// call per process per root actually runs; subsequent calls short-circuit
|
|
142
142
|
// via the in-memory guard in `context.ts`. Kept here rather than inside
|
|
@@ -335,7 +335,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Agen
|
|
|
335
335
|
|
|
336
336
|
const tracer = getTracer()
|
|
337
337
|
|
|
338
|
-
return yield* (async function* (): AsyncGenerator<RunEvent,
|
|
338
|
+
return yield* (async function* (): AsyncGenerator<RunEvent, Run> {
|
|
339
339
|
const rootSpan = tracer.startSpan(agentRunSpanName(params.agentName))
|
|
340
340
|
rootSpan.setAttributes({
|
|
341
341
|
[NAMZU.RUN_ID]: ctx.runMgr.id,
|
|
@@ -515,7 +515,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Agen
|
|
|
515
515
|
export async function drainQuery(
|
|
516
516
|
params: Omit<QueryParams, 'resumeHandler'> & { resumeHandler?: ResumeHandler },
|
|
517
517
|
listener?: RunEventListener,
|
|
518
|
-
): Promise<
|
|
518
|
+
): Promise<Run> {
|
|
519
519
|
const fullParams: QueryParams = {
|
|
520
520
|
...params,
|
|
521
521
|
resumeHandler: params.resumeHandler ?? autoApproveHandler,
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import type { ToolCallId } from '../../../../types/ids/index.js'
|
|
3
|
+
import type { AssistantMessage, Message, ToolMessage } from '../../../../types/message/index.js'
|
|
4
|
+
import { type Mutation, MutationNotApplicableError } from '../../../../types/run/replay.js'
|
|
5
|
+
import { applyMutations } from '../mutate.js'
|
|
6
|
+
|
|
7
|
+
function assistantWithCalls(toolCallIds: string[]): AssistantMessage {
|
|
8
|
+
return {
|
|
9
|
+
role: 'assistant',
|
|
10
|
+
content: null,
|
|
11
|
+
toolCalls: toolCallIds.map((id) => ({
|
|
12
|
+
id,
|
|
13
|
+
type: 'function',
|
|
14
|
+
function: { name: 'noop', arguments: '{}' },
|
|
15
|
+
})),
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('applyMutations / injectToolResponse', () => {
|
|
20
|
+
it('appends a ToolMessage when the toolCallId is pending', () => {
|
|
21
|
+
const messages: Message[] = [
|
|
22
|
+
{ role: 'user', content: 'do stuff' },
|
|
23
|
+
assistantWithCalls(['call_a', 'call_b']),
|
|
24
|
+
{ role: 'tool', content: 'a done', toolCallId: 'call_a' },
|
|
25
|
+
]
|
|
26
|
+
const mutations: Mutation[] = [
|
|
27
|
+
{
|
|
28
|
+
type: 'injectToolResponse',
|
|
29
|
+
toolCallId: 'call_b' as ToolCallId,
|
|
30
|
+
response: { success: true, output: 'mocked-b', data: { x: 1 } },
|
|
31
|
+
},
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const result = applyMutations(messages, mutations)
|
|
35
|
+
|
|
36
|
+
expect(result).toHaveLength(4)
|
|
37
|
+
const last = result[3] as ToolMessage
|
|
38
|
+
expect(last.role).toBe('tool')
|
|
39
|
+
expect(last.toolCallId).toBe('call_b')
|
|
40
|
+
expect(last.content).toBe('mocked-b')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('throws MutationNotApplicableError when no pending tool calls exist', () => {
|
|
44
|
+
const messages: Message[] = [
|
|
45
|
+
{ role: 'user', content: 'hi' },
|
|
46
|
+
{ role: 'assistant', content: 'hello' },
|
|
47
|
+
]
|
|
48
|
+
expect(() =>
|
|
49
|
+
applyMutations(messages, [
|
|
50
|
+
{
|
|
51
|
+
type: 'injectToolResponse',
|
|
52
|
+
toolCallId: 'call_missing' as ToolCallId,
|
|
53
|
+
response: { success: true, output: 'x' },
|
|
54
|
+
},
|
|
55
|
+
]),
|
|
56
|
+
).toThrow(MutationNotApplicableError)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('throws with availableToolCallIds populated when toolCallId is not pending', () => {
|
|
60
|
+
const messages: Message[] = [
|
|
61
|
+
{ role: 'user', content: 'do stuff' },
|
|
62
|
+
assistantWithCalls(['call_a', 'call_b']),
|
|
63
|
+
]
|
|
64
|
+
try {
|
|
65
|
+
applyMutations(messages, [
|
|
66
|
+
{
|
|
67
|
+
type: 'injectToolResponse',
|
|
68
|
+
toolCallId: 'call_z' as ToolCallId,
|
|
69
|
+
response: { success: true, output: 'x' },
|
|
70
|
+
},
|
|
71
|
+
])
|
|
72
|
+
expect.fail('expected MutationNotApplicableError')
|
|
73
|
+
} catch (err) {
|
|
74
|
+
expect(err).toBeInstanceOf(MutationNotApplicableError)
|
|
75
|
+
const e = err as MutationNotApplicableError
|
|
76
|
+
expect(e.availableToolCallIds).toEqual(['call_a', 'call_b'])
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('considers a tool call satisfied only when a subsequent ToolMessage responds to it', () => {
|
|
81
|
+
const messages: Message[] = [
|
|
82
|
+
{ role: 'user', content: 'do stuff' },
|
|
83
|
+
assistantWithCalls(['call_a', 'call_b', 'call_c']),
|
|
84
|
+
{ role: 'tool', content: 'a done', toolCallId: 'call_a' },
|
|
85
|
+
{ role: 'tool', content: 'c done', toolCallId: 'call_c' },
|
|
86
|
+
]
|
|
87
|
+
try {
|
|
88
|
+
applyMutations(messages, [
|
|
89
|
+
{
|
|
90
|
+
type: 'injectToolResponse',
|
|
91
|
+
toolCallId: 'call_a' as ToolCallId,
|
|
92
|
+
response: { success: true, output: 're-answered' },
|
|
93
|
+
},
|
|
94
|
+
])
|
|
95
|
+
expect.fail('expected MutationNotApplicableError — call_a already satisfied')
|
|
96
|
+
} catch (err) {
|
|
97
|
+
const e = err as MutationNotApplicableError
|
|
98
|
+
expect(e.availableToolCallIds).toEqual(['call_b'])
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('applies mutations in order so a later mutation sees earlier ones', () => {
|
|
103
|
+
const messages: Message[] = [
|
|
104
|
+
{ role: 'user', content: 'two calls pending' },
|
|
105
|
+
assistantWithCalls(['call_x', 'call_y']),
|
|
106
|
+
]
|
|
107
|
+
const result = applyMutations(messages, [
|
|
108
|
+
{
|
|
109
|
+
type: 'injectToolResponse',
|
|
110
|
+
toolCallId: 'call_x' as ToolCallId,
|
|
111
|
+
response: { success: true, output: 'x-result' },
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: 'injectToolResponse',
|
|
115
|
+
toolCallId: 'call_y' as ToolCallId,
|
|
116
|
+
response: { success: true, output: 'y-result' },
|
|
117
|
+
},
|
|
118
|
+
])
|
|
119
|
+
|
|
120
|
+
expect(result).toHaveLength(4)
|
|
121
|
+
expect((result[2] as ToolMessage).toolCallId).toBe('call_x')
|
|
122
|
+
expect((result[3] as ToolMessage).toolCallId).toBe('call_y')
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('returns the original messages unchanged when the mutation list is empty', () => {
|
|
126
|
+
const messages: Message[] = [
|
|
127
|
+
{ role: 'user', content: 'no-op' },
|
|
128
|
+
{ role: 'assistant', content: 'ok' },
|
|
129
|
+
]
|
|
130
|
+
const result = applyMutations(messages, [])
|
|
131
|
+
expect(result).toEqual(messages)
|
|
132
|
+
expect(result).not.toBe(messages)
|
|
133
|
+
})
|
|
134
|
+
})
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { mkdir, mkdtemp, writeFile } from 'node:fs/promises'
|
|
2
|
+
import { tmpdir } from 'node:os'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
5
|
+
import type { CheckpointId, IterationCheckpoint } from '../../../../types/hitl/index.js'
|
|
6
|
+
import type { EmergencySaveId, RunId, ToolCallId } from '../../../../types/ids/index.js'
|
|
7
|
+
import type { AssistantMessage, ToolMessage } from '../../../../types/message/index.js'
|
|
8
|
+
import type { EmergencySaveData } from '../../../../types/run/emergency.js'
|
|
9
|
+
import type { Mutation } from '../../../../types/run/replay.js'
|
|
10
|
+
import { prepareReplayState } from '../prepare.js'
|
|
11
|
+
|
|
12
|
+
const RUN_ID = 'run_source' as RunId
|
|
13
|
+
|
|
14
|
+
function makeCheckpoint(overrides: Partial<IterationCheckpoint>): IterationCheckpoint {
|
|
15
|
+
return {
|
|
16
|
+
id: 'cp_default' as CheckpointId,
|
|
17
|
+
runId: RUN_ID,
|
|
18
|
+
iteration: 1,
|
|
19
|
+
messages: [{ role: 'user', content: 'hi' }],
|
|
20
|
+
tokenUsage: {
|
|
21
|
+
promptTokens: 0,
|
|
22
|
+
completionTokens: 0,
|
|
23
|
+
totalTokens: 0,
|
|
24
|
+
cachedTokens: 0,
|
|
25
|
+
cacheWriteTokens: 0,
|
|
26
|
+
},
|
|
27
|
+
costInfo: { inputCostPer1M: 0, outputCostPer1M: 0, totalCost: 0, cacheDiscount: 0 },
|
|
28
|
+
guardState: { iterationCount: 1, elapsedMs: 0 },
|
|
29
|
+
createdAt: Date.now(),
|
|
30
|
+
...overrides,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function seedCheckpoint(baseDir: string, cp: IterationCheckpoint): Promise<void> {
|
|
35
|
+
const cpDir = join(baseDir, cp.runId, 'checkpoints')
|
|
36
|
+
await mkdir(cpDir, { recursive: true })
|
|
37
|
+
await writeFile(join(cpDir, `${cp.id}.json`), JSON.stringify(cp), 'utf-8')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function seedEmergency(emergencyDir: string, dump: EmergencySaveData): Promise<void> {
|
|
41
|
+
await mkdir(emergencyDir, { recursive: true })
|
|
42
|
+
await writeFile(join(emergencyDir, `${dump.runId}.json`), JSON.stringify(dump), 'utf-8')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe('prepareReplayState', () => {
|
|
46
|
+
let baseDir: string
|
|
47
|
+
let emergencyDir: string
|
|
48
|
+
|
|
49
|
+
beforeEach(async () => {
|
|
50
|
+
const wrapper = await mkdtemp(join(tmpdir(), 'namzu-prepare-replay-'))
|
|
51
|
+
baseDir = join(wrapper, 'runs')
|
|
52
|
+
emergencyDir = join(wrapper, 'emergency')
|
|
53
|
+
await mkdir(baseDir, { recursive: true })
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
afterEach(async () => {
|
|
57
|
+
// Per-test tmpdir isolation; vitest cleans tmpdir between runs.
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('resolves a specific CheckpointId and returns the checkpoint messages', async () => {
|
|
61
|
+
const cp = makeCheckpoint({
|
|
62
|
+
id: 'cp_one' as CheckpointId,
|
|
63
|
+
iteration: 3,
|
|
64
|
+
messages: [
|
|
65
|
+
{ role: 'user', content: 'start' },
|
|
66
|
+
{ role: 'assistant', content: 'ok' },
|
|
67
|
+
],
|
|
68
|
+
})
|
|
69
|
+
await seedCheckpoint(baseDir, cp)
|
|
70
|
+
|
|
71
|
+
const prepared = await prepareReplayState({
|
|
72
|
+
baseDir,
|
|
73
|
+
runId: RUN_ID,
|
|
74
|
+
fromCheckpoint: 'cp_one' as CheckpointId,
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
expect(prepared.sourceCheckpoint.id).toBe('cp_one')
|
|
78
|
+
expect(prepared.messages).toEqual(cp.messages)
|
|
79
|
+
expect(prepared.attribution.sourceRunId).toBe(RUN_ID)
|
|
80
|
+
expect(prepared.attribution.fromCheckpointId).toBe('cp_one')
|
|
81
|
+
expect(prepared.attribution.mutations).toEqual([])
|
|
82
|
+
expect(prepared.attribution.replayedAt).toBeGreaterThan(0)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it("resolves 'latest' to the checkpoint with the highest iteration", async () => {
|
|
86
|
+
await seedCheckpoint(baseDir, makeCheckpoint({ id: 'cp_a' as CheckpointId, iteration: 1 }))
|
|
87
|
+
await seedCheckpoint(baseDir, makeCheckpoint({ id: 'cp_b' as CheckpointId, iteration: 5 }))
|
|
88
|
+
await seedCheckpoint(baseDir, makeCheckpoint({ id: 'cp_c' as CheckpointId, iteration: 3 }))
|
|
89
|
+
|
|
90
|
+
const prepared = await prepareReplayState({
|
|
91
|
+
baseDir,
|
|
92
|
+
runId: RUN_ID,
|
|
93
|
+
fromCheckpoint: 'latest',
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
expect(prepared.sourceCheckpoint.id).toBe('cp_b')
|
|
97
|
+
expect(prepared.sourceCheckpoint.iteration).toBe(5)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it("throws when 'latest' is requested but no checkpoints exist", async () => {
|
|
101
|
+
await expect(
|
|
102
|
+
prepareReplayState({
|
|
103
|
+
baseDir,
|
|
104
|
+
runId: RUN_ID,
|
|
105
|
+
fromCheckpoint: 'latest',
|
|
106
|
+
}),
|
|
107
|
+
).rejects.toThrow(/No checkpoints found/)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('throws when a specific CheckpointId does not resolve', async () => {
|
|
111
|
+
await expect(
|
|
112
|
+
prepareReplayState({
|
|
113
|
+
baseDir,
|
|
114
|
+
runId: RUN_ID,
|
|
115
|
+
fromCheckpoint: 'cp_missing' as CheckpointId,
|
|
116
|
+
}),
|
|
117
|
+
).rejects.toThrow(/not found/)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
it('applies injectToolResponse mutations at the fork point', async () => {
|
|
121
|
+
const assistantMsg: AssistantMessage = {
|
|
122
|
+
role: 'assistant',
|
|
123
|
+
content: null,
|
|
124
|
+
toolCalls: [{ id: 'call_a', type: 'function', function: { name: 'noop', arguments: '{}' } }],
|
|
125
|
+
}
|
|
126
|
+
const cp = makeCheckpoint({
|
|
127
|
+
id: 'cp_with_tool' as CheckpointId,
|
|
128
|
+
messages: [{ role: 'user', content: 'run tool' }, assistantMsg],
|
|
129
|
+
})
|
|
130
|
+
await seedCheckpoint(baseDir, cp)
|
|
131
|
+
|
|
132
|
+
const mutations: Mutation[] = [
|
|
133
|
+
{
|
|
134
|
+
type: 'injectToolResponse',
|
|
135
|
+
toolCallId: 'call_a' as ToolCallId,
|
|
136
|
+
response: { success: true, output: 'mocked-a' },
|
|
137
|
+
},
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
const prepared = await prepareReplayState({
|
|
141
|
+
baseDir,
|
|
142
|
+
runId: RUN_ID,
|
|
143
|
+
fromCheckpoint: 'cp_with_tool' as CheckpointId,
|
|
144
|
+
mutate: mutations,
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
expect(prepared.messages).toHaveLength(3)
|
|
148
|
+
const appended = prepared.messages[2] as ToolMessage
|
|
149
|
+
expect(appended.role).toBe('tool')
|
|
150
|
+
expect(appended.toolCallId).toBe('call_a')
|
|
151
|
+
expect(appended.content).toBe('mocked-a')
|
|
152
|
+
expect(prepared.attribution.mutations).toEqual(mutations)
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it("resolves 'emergency' via the emergency dump and projects it to a checkpoint", async () => {
|
|
156
|
+
const dump: EmergencySaveData = {
|
|
157
|
+
id: 'esave_xyz' as EmergencySaveId,
|
|
158
|
+
runId: RUN_ID,
|
|
159
|
+
messages: [{ role: 'user', content: 'before crash' }],
|
|
160
|
+
tokenUsage: {
|
|
161
|
+
promptTokens: 4,
|
|
162
|
+
completionTokens: 2,
|
|
163
|
+
totalTokens: 6,
|
|
164
|
+
cachedTokens: 0,
|
|
165
|
+
cacheWriteTokens: 0,
|
|
166
|
+
},
|
|
167
|
+
currentIteration: 9,
|
|
168
|
+
startedAt: 1_000,
|
|
169
|
+
savedAt: 2_000,
|
|
170
|
+
processSignal: 'SIGTERM',
|
|
171
|
+
}
|
|
172
|
+
await seedEmergency(emergencyDir, dump)
|
|
173
|
+
|
|
174
|
+
const prepared = await prepareReplayState({
|
|
175
|
+
baseDir,
|
|
176
|
+
runId: RUN_ID,
|
|
177
|
+
fromCheckpoint: 'emergency',
|
|
178
|
+
emergencyDir,
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
expect(prepared.sourceCheckpoint.id).toBe('cp_emergency_xyz')
|
|
182
|
+
expect(prepared.sourceCheckpoint.iteration).toBe(9)
|
|
183
|
+
expect(prepared.messages).toEqual(dump.messages)
|
|
184
|
+
expect(prepared.attribution.fromCheckpointId).toBe('cp_emergency_xyz')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it("throws when 'emergency' is requested without emergencyDir", async () => {
|
|
188
|
+
await expect(
|
|
189
|
+
prepareReplayState({
|
|
190
|
+
baseDir,
|
|
191
|
+
runId: RUN_ID,
|
|
192
|
+
fromCheckpoint: 'emergency',
|
|
193
|
+
}),
|
|
194
|
+
).rejects.toThrow(/emergencyDir/)
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
it("throws when 'emergency' dump file is missing", async () => {
|
|
198
|
+
await expect(
|
|
199
|
+
prepareReplayState({
|
|
200
|
+
baseDir,
|
|
201
|
+
runId: RUN_ID,
|
|
202
|
+
fromCheckpoint: 'emergency',
|
|
203
|
+
emergencyDir,
|
|
204
|
+
}),
|
|
205
|
+
).rejects.toThrow(/No emergency dump/)
|
|
206
|
+
})
|
|
207
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { RunDiskStore } from '../../../store/run/disk.js'
|
|
2
|
+
import type { RunId } from '../../../types/ids/index.js'
|
|
3
|
+
import type { CheckpointListEntry } from '../../../types/run/replay.js'
|
|
4
|
+
import type { Logger } from '../../../utils/logger.js'
|
|
5
|
+
import { CheckpointManager } from '../checkpoint.js'
|
|
6
|
+
|
|
7
|
+
export interface ListCheckpointsInput {
|
|
8
|
+
/** Directory that contains `<runId>/` for the target run. */
|
|
9
|
+
baseDir: string
|
|
10
|
+
/** Run whose checkpoints should be listed. */
|
|
11
|
+
runId: RunId
|
|
12
|
+
logger?: Logger
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Read-only listing of a run's checkpoints for use with {@link
|
|
17
|
+
* import('./prepare.js').prepareReplayState}. Returns the public
|
|
18
|
+
* {@link CheckpointListEntry} projection — just enough for a caller to
|
|
19
|
+
* pick a fork point — not the full `IterationCheckpoint` payload.
|
|
20
|
+
*
|
|
21
|
+
* Entries are returned in the order the underlying store returns them
|
|
22
|
+
* (disk store sorts by `createdAt` ascending). Callers that want a
|
|
23
|
+
* specific order should sort client-side.
|
|
24
|
+
*
|
|
25
|
+
* See ses_005-deterministic-replay/design.md §3.1.
|
|
26
|
+
*/
|
|
27
|
+
export async function listCheckpoints(input: ListCheckpointsInput): Promise<CheckpointListEntry[]> {
|
|
28
|
+
const store = new RunDiskStore({ baseDir: input.baseDir, logger: input.logger })
|
|
29
|
+
await store.initRun(input.runId)
|
|
30
|
+
const mgr = new CheckpointManager(store)
|
|
31
|
+
return mgr.listEntries()
|
|
32
|
+
}
|