@namzu/sdk 0.1.8 → 0.2.0
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 +16 -0
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +5 -3
- package/dist/agents/ReactiveAgent.js.map +1 -1
- package/dist/agents/RouterAgent.d.ts.map +1 -1
- package/dist/agents/RouterAgent.js +3 -0
- package/dist/agents/RouterAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js +18 -5
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/bridge/a2a/mapper.d.ts.map +1 -1
- package/dist/bridge/a2a/mapper.js +6 -0
- package/dist/bridge/a2a/mapper.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/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +6 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/constants/a2a/index.d.ts +2 -2
- package/dist/constants/a2a/index.d.ts.map +1 -1
- package/dist/constants/a2a/index.js.map +1 -1
- package/dist/contracts/api.d.ts +22 -3
- package/dist/contracts/api.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +3 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/gateway/local.d.ts.map +1 -1
- package/dist/gateway/local.js +6 -0
- package/dist/gateway/local.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/manager/agent/__tests__/lifecycle.test.d.ts +2 -0
- package/dist/manager/agent/__tests__/lifecycle.test.d.ts.map +1 -0
- package/dist/manager/agent/__tests__/lifecycle.test.js +302 -0
- package/dist/manager/agent/__tests__/lifecycle.test.js.map +1 -0
- package/dist/manager/agent/lifecycle.d.ts +58 -3
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +311 -12
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/run/persistence.d.ts +8 -1
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +15 -0
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/run/reporter.d.ts.map +1 -1
- package/dist/run/reporter.js +25 -0
- package/dist/run/reporter.js.map +1 -1
- package/dist/runtime/query/__tests__/context.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/context.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/context.test.js +84 -0
- package/dist/runtime/query/__tests__/context.test.js.map +1 -0
- package/dist/runtime/query/context.d.ts +55 -2
- package/dist/runtime/query/context.d.ts.map +1 -1
- package/dist/runtime/query/context.js +48 -8
- package/dist/runtime/query/context.js.map +1 -1
- package/dist/runtime/query/events.d.ts.map +1 -1
- package/dist/runtime/query/events.js +8 -0
- package/dist/runtime/query/events.js.map +1 -1
- package/dist/runtime/query/index.d.ts +25 -2
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +11 -1
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/session/__tests__/integration/_fixtures.d.ts +115 -0
- package/dist/session/__tests__/integration/_fixtures.d.ts.map +1 -0
- package/dist/session/__tests__/integration/_fixtures.js +198 -0
- package/dist/session/__tests__/integration/_fixtures.js.map +1 -0
- package/dist/session/__tests__/integration/capacity-caps.test.d.ts +13 -0
- package/dist/session/__tests__/integration/capacity-caps.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/capacity-caps.test.js +116 -0
- package/dist/session/__tests__/integration/capacity-caps.test.js.map +1 -0
- package/dist/session/__tests__/integration/e2e-spawn.test.d.ts +18 -0
- package/dist/session/__tests__/integration/e2e-spawn.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/e2e-spawn.test.js +226 -0
- package/dist/session/__tests__/integration/e2e-spawn.test.js.map +1 -0
- package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts +15 -0
- package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/event-stream-ordering.test.js +323 -0
- package/dist/session/__tests__/integration/event-stream-ordering.test.js.map +1 -0
- package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts +12 -0
- package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js +170 -0
- package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js.map +1 -0
- package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts +18 -0
- package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/handoff-illegal-transition.test.js +146 -0
- package/dist/session/__tests__/integration/handoff-illegal-transition.test.js.map +1 -0
- package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts +15 -0
- package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/handoff-single-e2e.test.js +163 -0
- package/dist/session/__tests__/integration/handoff-single-e2e.test.js.map +1 -0
- package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts +12 -0
- package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js +157 -0
- package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js.map +1 -0
- package/dist/session/__tests__/integration/migration-filesystem.test.d.ts +11 -0
- package/dist/session/__tests__/integration/migration-filesystem.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/migration-filesystem.test.js +140 -0
- package/dist/session/__tests__/integration/migration-filesystem.test.js.map +1 -0
- package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts +13 -0
- package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/migration-id-prefix.test.js +84 -0
- package/dist/session/__tests__/integration/migration-id-prefix.test.js.map +1 -0
- package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts +14 -0
- package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/prev-artifact-dag.test.js +241 -0
- package/dist/session/__tests__/integration/prev-artifact-dag.test.js.map +1 -0
- package/dist/session/__tests__/integration/retention-archive.test.d.ts +12 -0
- package/dist/session/__tests__/integration/retention-archive.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/retention-archive.test.js +186 -0
- package/dist/session/__tests__/integration/retention-archive.test.js.map +1 -0
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts +18 -0
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.js +200 -0
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.js.map +1 -0
- package/dist/session/__tests__/integration/tenant-isolation.test.d.ts +14 -0
- package/dist/session/__tests__/integration/tenant-isolation.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/tenant-isolation.test.js +180 -0
- package/dist/session/__tests__/integration/tenant-isolation.test.js.map +1 -0
- package/dist/session/errors.d.ts +60 -0
- package/dist/session/errors.d.ts.map +1 -0
- package/dist/session/errors.js +50 -0
- package/dist/session/errors.js.map +1 -0
- package/dist/session/events/index.d.ts +4 -0
- package/dist/session/events/index.d.ts.map +1 -0
- package/dist/session/events/index.js +8 -0
- package/dist/session/events/index.js.map +1 -0
- package/dist/session/events/schema-version.d.ts +13 -0
- package/dist/session/events/schema-version.d.ts.map +1 -0
- package/dist/session/events/schema-version.js +12 -0
- package/dist/session/events/schema-version.js.map +1 -0
- package/dist/session/events/types.d.ts +64 -0
- package/dist/session/events/types.d.ts.map +1 -0
- package/dist/session/events/types.js +2 -0
- package/dist/session/events/types.js.map +1 -0
- package/dist/session/handoff/__tests__/broadcast.test.d.ts +2 -0
- package/dist/session/handoff/__tests__/broadcast.test.d.ts.map +1 -0
- package/dist/session/handoff/__tests__/broadcast.test.js +243 -0
- package/dist/session/handoff/__tests__/broadcast.test.js.map +1 -0
- package/dist/session/handoff/__tests__/capacity.test.d.ts +2 -0
- package/dist/session/handoff/__tests__/capacity.test.d.ts.map +1 -0
- package/dist/session/handoff/__tests__/capacity.test.js +100 -0
- package/dist/session/handoff/__tests__/capacity.test.js.map +1 -0
- package/dist/session/handoff/__tests__/single.test.d.ts +2 -0
- package/dist/session/handoff/__tests__/single.test.d.ts.map +1 -0
- package/dist/session/handoff/__tests__/single.test.js +230 -0
- package/dist/session/handoff/__tests__/single.test.js.map +1 -0
- package/dist/session/handoff/assignment.d.ts +59 -0
- package/dist/session/handoff/assignment.d.ts.map +1 -0
- package/dist/session/handoff/assignment.js +11 -0
- package/dist/session/handoff/assignment.js.map +1 -0
- package/dist/session/handoff/broadcast.d.ts +47 -0
- package/dist/session/handoff/broadcast.d.ts.map +1 -0
- package/dist/session/handoff/broadcast.js +296 -0
- package/dist/session/handoff/broadcast.js.map +1 -0
- package/dist/session/handoff/capacity.d.ts +66 -0
- package/dist/session/handoff/capacity.d.ts.map +1 -0
- package/dist/session/handoff/capacity.js +60 -0
- package/dist/session/handoff/capacity.js.map +1 -0
- package/dist/session/handoff/events.d.ts +66 -0
- package/dist/session/handoff/events.d.ts.map +1 -0
- package/dist/session/handoff/events.js +13 -0
- package/dist/session/handoff/events.js.map +1 -0
- package/dist/session/handoff/index.d.ts +12 -0
- package/dist/session/handoff/index.d.ts.map +1 -0
- package/dist/session/handoff/index.js +9 -0
- package/dist/session/handoff/index.js.map +1 -0
- package/dist/session/handoff/single.d.ts +62 -0
- package/dist/session/handoff/single.d.ts.map +1 -0
- package/dist/session/handoff/single.js +217 -0
- package/dist/session/handoff/single.js.map +1 -0
- package/dist/session/handoff/version.d.ts +52 -0
- package/dist/session/handoff/version.d.ts.map +1 -0
- package/dist/session/handoff/version.js +36 -0
- package/dist/session/handoff/version.js.map +1 -0
- package/dist/session/hierarchy/__tests__/session.test.d.ts +2 -0
- package/dist/session/hierarchy/__tests__/session.test.d.ts.map +1 -0
- package/dist/session/hierarchy/__tests__/session.test.js +67 -0
- package/dist/session/hierarchy/__tests__/session.test.js.map +1 -0
- package/dist/session/hierarchy/actor.d.ts +26 -0
- package/dist/session/hierarchy/actor.d.ts.map +1 -0
- package/dist/session/hierarchy/actor.js +2 -0
- package/dist/session/hierarchy/actor.js.map +1 -0
- package/dist/session/hierarchy/index.d.ts +8 -0
- package/dist/session/hierarchy/index.d.ts.map +1 -0
- package/dist/session/hierarchy/index.js +4 -0
- package/dist/session/hierarchy/index.js.map +1 -0
- package/dist/session/hierarchy/lineage.d.ts +15 -0
- package/dist/session/hierarchy/lineage.d.ts.map +1 -0
- package/dist/session/hierarchy/lineage.js +2 -0
- package/dist/session/hierarchy/lineage.js.map +1 -0
- package/dist/session/hierarchy/project.d.ts +40 -0
- package/dist/session/hierarchy/project.d.ts.map +1 -0
- package/dist/session/hierarchy/project.js +2 -0
- package/dist/session/hierarchy/project.js.map +1 -0
- package/dist/session/hierarchy/session.d.ts +59 -0
- package/dist/session/hierarchy/session.d.ts.map +1 -0
- package/dist/session/hierarchy/session.js +51 -0
- package/dist/session/hierarchy/session.js.map +1 -0
- package/dist/session/hierarchy/sub-session.d.ts +76 -0
- package/dist/session/hierarchy/sub-session.d.ts.map +1 -0
- package/dist/session/hierarchy/sub-session.js +2 -0
- package/dist/session/hierarchy/sub-session.js.map +1 -0
- package/dist/session/hierarchy/tenant.d.ts +13 -0
- package/dist/session/hierarchy/tenant.d.ts.map +1 -0
- package/dist/session/hierarchy/tenant.js +2 -0
- package/dist/session/hierarchy/tenant.js.map +1 -0
- package/dist/session/index.d.ts +10 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +15 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/intervention/__tests__/prev-artifact.test.d.ts +2 -0
- package/dist/session/intervention/__tests__/prev-artifact.test.d.ts.map +1 -0
- package/dist/session/intervention/__tests__/prev-artifact.test.js +179 -0
- package/dist/session/intervention/__tests__/prev-artifact.test.js.map +1 -0
- package/dist/session/intervention/index.d.ts +3 -0
- package/dist/session/intervention/index.d.ts.map +1 -0
- package/dist/session/intervention/index.js +8 -0
- package/dist/session/intervention/index.js.map +1 -0
- package/dist/session/intervention/prev-artifact.d.ts +103 -0
- package/dist/session/intervention/prev-artifact.d.ts.map +1 -0
- package/dist/session/intervention/prev-artifact.js +112 -0
- package/dist/session/intervention/prev-artifact.js.map +1 -0
- package/dist/session/migration/__tests__/filesystem.test.d.ts +2 -0
- package/dist/session/migration/__tests__/filesystem.test.d.ts.map +1 -0
- package/dist/session/migration/__tests__/filesystem.test.js +188 -0
- package/dist/session/migration/__tests__/filesystem.test.js.map +1 -0
- package/dist/session/migration/__tests__/id-prefix.test.d.ts +2 -0
- package/dist/session/migration/__tests__/id-prefix.test.d.ts.map +1 -0
- package/dist/session/migration/__tests__/id-prefix.test.js +83 -0
- package/dist/session/migration/__tests__/id-prefix.test.js.map +1 -0
- package/dist/session/migration/__tests__/marker.test.d.ts +2 -0
- package/dist/session/migration/__tests__/marker.test.d.ts.map +1 -0
- package/dist/session/migration/__tests__/marker.test.js +75 -0
- package/dist/session/migration/__tests__/marker.test.js.map +1 -0
- package/dist/session/migration/errors.d.ts +26 -0
- package/dist/session/migration/errors.d.ts.map +1 -0
- package/dist/session/migration/errors.js +22 -0
- package/dist/session/migration/errors.js.map +1 -0
- package/dist/session/migration/filesystem.d.ts +94 -0
- package/dist/session/migration/filesystem.d.ts.map +1 -0
- package/dist/session/migration/filesystem.js +319 -0
- package/dist/session/migration/filesystem.js.map +1 -0
- package/dist/session/migration/id-prefix.d.ts +98 -0
- package/dist/session/migration/id-prefix.d.ts.map +1 -0
- package/dist/session/migration/id-prefix.js +116 -0
- package/dist/session/migration/id-prefix.js.map +1 -0
- package/dist/session/migration/index.d.ts +8 -0
- package/dist/session/migration/index.d.ts.map +1 -0
- package/dist/session/migration/index.js +8 -0
- package/dist/session/migration/index.js.map +1 -0
- package/dist/session/migration/marker.d.ts +57 -0
- package/dist/session/migration/marker.d.ts.map +1 -0
- package/dist/session/migration/marker.js +111 -0
- package/dist/session/migration/marker.js.map +1 -0
- package/dist/session/retention/__tests__/archive.test.d.ts +2 -0
- package/dist/session/retention/__tests__/archive.test.d.ts.map +1 -0
- package/dist/session/retention/__tests__/archive.test.js +252 -0
- package/dist/session/retention/__tests__/archive.test.js.map +1 -0
- package/dist/session/retention/__tests__/disk-backend.test.d.ts +2 -0
- package/dist/session/retention/__tests__/disk-backend.test.d.ts.map +1 -0
- package/dist/session/retention/__tests__/disk-backend.test.js +154 -0
- package/dist/session/retention/__tests__/disk-backend.test.js.map +1 -0
- package/dist/session/retention/archive-backend-ref.d.ts +18 -0
- package/dist/session/retention/archive-backend-ref.d.ts.map +1 -0
- package/dist/session/retention/archive-backend-ref.js +2 -0
- package/dist/session/retention/archive-backend-ref.js.map +1 -0
- package/dist/session/retention/archive.d.ts +130 -0
- package/dist/session/retention/archive.d.ts.map +1 -0
- package/dist/session/retention/archive.js +203 -0
- package/dist/session/retention/archive.js.map +1 -0
- package/dist/session/retention/backend.d.ts +101 -0
- package/dist/session/retention/backend.d.ts.map +1 -0
- package/dist/session/retention/backend.js +15 -0
- package/dist/session/retention/backend.js.map +1 -0
- package/dist/session/retention/disk-backend.d.ts +59 -0
- package/dist/session/retention/disk-backend.d.ts.map +1 -0
- package/dist/session/retention/disk-backend.js +236 -0
- package/dist/session/retention/disk-backend.js.map +1 -0
- package/dist/session/retention/index.d.ts +9 -0
- package/dist/session/retention/index.d.ts.map +1 -0
- package/dist/session/retention/index.js +6 -0
- package/dist/session/retention/index.js.map +1 -0
- package/dist/session/retention/policy.d.ts +49 -0
- package/dist/session/retention/policy.d.ts.map +1 -0
- package/dist/session/retention/policy.js +21 -0
- package/dist/session/retention/policy.js.map +1 -0
- package/dist/session/summary/__tests__/materialize.test.d.ts +2 -0
- package/dist/session/summary/__tests__/materialize.test.d.ts.map +1 -0
- package/dist/session/summary/__tests__/materialize.test.js +269 -0
- package/dist/session/summary/__tests__/materialize.test.js.map +1 -0
- package/dist/session/summary/deliverable.d.ts +74 -0
- package/dist/session/summary/deliverable.d.ts.map +1 -0
- package/dist/session/summary/deliverable.js +20 -0
- package/dist/session/summary/deliverable.js.map +1 -0
- package/dist/session/summary/index.d.ts +6 -0
- package/dist/session/summary/index.d.ts.map +1 -0
- package/dist/session/summary/index.js +9 -0
- package/dist/session/summary/index.js.map +1 -0
- package/dist/session/summary/materialize.d.ts +82 -0
- package/dist/session/summary/materialize.d.ts.map +1 -0
- package/dist/session/summary/materialize.js +117 -0
- package/dist/session/summary/materialize.js.map +1 -0
- package/dist/session/summary/ref.d.ts +91 -0
- package/dist/session/summary/ref.d.ts.map +1 -0
- package/dist/session/summary/ref.js +51 -0
- package/dist/session/summary/ref.js.map +1 -0
- package/dist/session/workspace/__tests__/git-worktree.test.d.ts +2 -0
- package/dist/session/workspace/__tests__/git-worktree.test.d.ts.map +1 -0
- package/dist/session/workspace/__tests__/git-worktree.test.js +244 -0
- package/dist/session/workspace/__tests__/git-worktree.test.js.map +1 -0
- package/dist/session/workspace/__tests__/path-builder.test.d.ts +2 -0
- package/dist/session/workspace/__tests__/path-builder.test.d.ts.map +1 -0
- package/dist/session/workspace/__tests__/path-builder.test.js +37 -0
- package/dist/session/workspace/__tests__/path-builder.test.js.map +1 -0
- package/dist/session/workspace/driver.d.ts +55 -0
- package/dist/session/workspace/driver.d.ts.map +1 -0
- package/dist/session/workspace/driver.js +12 -0
- package/dist/session/workspace/driver.js.map +1 -0
- package/dist/session/workspace/git-worktree.d.ts +65 -0
- package/dist/session/workspace/git-worktree.d.ts.map +1 -0
- package/dist/session/workspace/git-worktree.js +156 -0
- package/dist/session/workspace/git-worktree.js.map +1 -0
- package/dist/session/workspace/index.d.ts +8 -0
- package/dist/session/workspace/index.d.ts.map +1 -0
- package/dist/session/workspace/index.js +7 -0
- package/dist/session/workspace/index.js.map +1 -0
- package/dist/session/workspace/path-builder.d.ts +50 -0
- package/dist/session/workspace/path-builder.d.ts.map +1 -0
- package/dist/session/workspace/path-builder.js +50 -0
- package/dist/session/workspace/path-builder.js.map +1 -0
- package/dist/session/workspace/ref.d.ts +46 -0
- package/dist/session/workspace/ref.d.ts.map +1 -0
- package/dist/session/workspace/ref.js +11 -0
- package/dist/session/workspace/ref.js.map +1 -0
- package/dist/session/workspace/registry.d.ts +26 -0
- package/dist/session/workspace/registry.d.ts.map +1 -0
- package/dist/session/workspace/registry.js +35 -0
- package/dist/session/workspace/registry.js.map +1 -0
- package/dist/store/conversation/memory.d.ts +22 -0
- package/dist/store/conversation/memory.d.ts.map +1 -1
- package/dist/store/conversation/memory.js +22 -0
- package/dist/store/conversation/memory.js.map +1 -1
- package/dist/store/session/__tests__/disk.test.d.ts +2 -0
- package/dist/store/session/__tests__/disk.test.d.ts.map +1 -0
- package/dist/store/session/__tests__/disk.test.js +240 -0
- package/dist/store/session/__tests__/disk.test.js.map +1 -0
- package/dist/store/session/__tests__/memory.test.d.ts +2 -0
- package/dist/store/session/__tests__/memory.test.d.ts.map +1 -0
- package/dist/store/session/__tests__/memory.test.js +217 -0
- package/dist/store/session/__tests__/memory.test.js.map +1 -0
- package/dist/store/session/disk.d.ts +85 -0
- package/dist/store/session/disk.d.ts.map +1 -0
- package/dist/store/session/disk.js +757 -0
- package/dist/store/session/disk.js.map +1 -0
- package/dist/store/session/index.d.ts +7 -0
- package/dist/store/session/index.d.ts.map +1 -0
- package/dist/store/session/index.js +11 -0
- package/dist/store/session/index.js.map +1 -0
- package/dist/store/session/linkage.d.ts +38 -0
- package/dist/store/session/linkage.d.ts.map +1 -0
- package/dist/store/session/linkage.js +64 -0
- package/dist/store/session/linkage.js.map +1 -0
- package/dist/store/session/memory.d.ts +48 -0
- package/dist/store/session/memory.d.ts.map +1 -0
- package/dist/store/session/memory.js +322 -0
- package/dist/store/session/memory.js.map +1 -0
- package/dist/store/session/messages.d.ts +20 -0
- package/dist/store/session/messages.d.ts.map +1 -0
- package/dist/store/session/messages.js +12 -0
- package/dist/store/session/messages.js.map +1 -0
- package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts +1 -1
- package/dist/types/agent/base.d.ts +28 -1
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +50 -2
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/agent/task.js.map +1 -1
- package/dist/types/conversation/index.d.ts +7 -0
- package/dist/types/conversation/index.d.ts.map +1 -1
- package/dist/types/ids/index.d.ts +26 -3
- package/dist/types/ids/index.d.ts.map +1 -1
- package/dist/types/ids/index.js +8 -1
- package/dist/types/ids/index.js.map +1 -1
- package/dist/types/invocation/__tests__/state.test.js +36 -29
- package/dist/types/invocation/__tests__/state.test.js.map +1 -1
- package/dist/types/invocation/index.d.ts +20 -4
- package/dist/types/invocation/index.d.ts.map +1 -1
- package/dist/types/invocation/index.js +10 -7
- package/dist/types/invocation/index.js.map +1 -1
- package/dist/types/run/config.d.ts +11 -1
- package/dist/types/run/config.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +26 -1
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/index.d.ts.map +1 -1
- package/dist/types/run/index.js +8 -0
- package/dist/types/run/index.js.map +1 -1
- package/dist/types/run/metadata.d.ts +24 -1
- package/dist/types/run/metadata.d.ts.map +1 -1
- package/dist/types/run/status.d.ts +26 -0
- package/dist/types/run/status.d.ts.map +1 -0
- package/dist/types/run/status.js +2 -0
- package/dist/types/run/status.js.map +1 -0
- package/dist/types/session/ids.d.ts +18 -0
- package/dist/types/session/ids.d.ts.map +1 -0
- package/dist/types/session/ids.js +12 -0
- package/dist/types/session/ids.js.map +1 -0
- package/dist/types/session/index.d.ts +3 -0
- package/dist/types/session/index.d.ts.map +1 -0
- package/dist/types/session/index.js +5 -0
- package/dist/types/session/index.js.map +1 -0
- package/dist/types/session/store.d.ts +188 -0
- package/dist/types/session/store.d.ts.map +1 -0
- package/dist/types/session/store.js +14 -0
- package/dist/types/session/store.js.map +1 -0
- package/dist/utils/id.d.ts +18 -1
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +42 -4
- package/dist/utils/id.js.map +1 -1
- package/package.json +1 -1
- package/src/agents/ReactiveAgent.ts +7 -3
- package/src/agents/RouterAgent.ts +5 -0
- package/src/agents/SupervisorAgent.ts +26 -6
- package/src/bridge/a2a/mapper.ts +7 -0
- package/src/bridge/a2a/task.ts +2 -2
- package/src/bridge/sse/mapper.ts +8 -1
- package/src/constants/a2a/index.ts +2 -2
- package/src/contracts/api.ts +23 -3
- package/src/contracts/index.ts +2 -0
- package/src/gateway/local.ts +6 -0
- package/src/index.ts +14 -0
- package/src/manager/agent/__tests__/lifecycle.test.ts +452 -0
- package/src/manager/agent/lifecycle.ts +434 -19
- package/src/manager/run/persistence.ts +20 -1
- package/src/run/reporter.ts +28 -0
- package/src/runtime/query/__tests__/context.test.ts +101 -0
- package/src/runtime/query/context.ts +106 -10
- package/src/runtime/query/events.ts +8 -0
- package/src/runtime/query/index.ts +41 -3
- package/src/session/__tests__/integration/_fixtures.ts +282 -0
- package/src/session/__tests__/integration/capacity-caps.test.ts +164 -0
- package/src/session/__tests__/integration/e2e-spawn.test.ts +278 -0
- package/src/session/__tests__/integration/event-stream-ordering.test.ts +403 -0
- package/src/session/__tests__/integration/handoff-broadcast-e2e.test.ts +245 -0
- package/src/session/__tests__/integration/handoff-illegal-transition.test.ts +179 -0
- package/src/session/__tests__/integration/handoff-single-e2e.test.ts +220 -0
- package/src/session/__tests__/integration/hierarchy-lifecycle.test.ts +237 -0
- package/src/session/__tests__/integration/migration-filesystem.test.ts +209 -0
- package/src/session/__tests__/integration/migration-id-prefix.test.ts +101 -0
- package/src/session/__tests__/integration/prev-artifact-dag.test.ts +318 -0
- package/src/session/__tests__/integration/retention-archive.test.ts +231 -0
- package/src/session/__tests__/integration/summary-materialization-e2e.test.ts +237 -0
- package/src/session/__tests__/integration/tenant-isolation.test.ts +282 -0
- package/src/session/errors.ts +70 -0
- package/src/session/events/index.ts +16 -0
- package/src/session/events/schema-version.ts +13 -0
- package/src/session/events/types.ts +71 -0
- package/src/session/handoff/__tests__/broadcast.test.ts +350 -0
- package/src/session/handoff/__tests__/capacity.test.ts +123 -0
- package/src/session/handoff/__tests__/single.test.ts +316 -0
- package/src/session/handoff/assignment.ts +62 -0
- package/src/session/handoff/broadcast.ts +381 -0
- package/src/session/handoff/capacity.ts +121 -0
- package/src/session/handoff/events.ts +72 -0
- package/src/session/handoff/index.ts +29 -0
- package/src/session/handoff/single.ts +288 -0
- package/src/session/handoff/version.ts +59 -0
- package/src/session/hierarchy/__tests__/session.test.ts +92 -0
- package/src/session/hierarchy/actor.ts +17 -0
- package/src/session/hierarchy/index.ts +17 -0
- package/src/session/hierarchy/lineage.ts +15 -0
- package/src/session/hierarchy/project.ts +41 -0
- package/src/session/hierarchy/session.ts +97 -0
- package/src/session/hierarchy/sub-session.ts +92 -0
- package/src/session/hierarchy/tenant.ts +13 -0
- package/src/session/index.ts +15 -0
- package/src/session/intervention/__tests__/prev-artifact.test.ts +234 -0
- package/src/session/intervention/index.ts +16 -0
- package/src/session/intervention/prev-artifact.ts +180 -0
- package/src/session/migration/__tests__/filesystem.test.ts +263 -0
- package/src/session/migration/__tests__/id-prefix.test.ts +101 -0
- package/src/session/migration/__tests__/marker.test.ts +84 -0
- package/src/session/migration/errors.ts +23 -0
- package/src/session/migration/filesystem.ts +401 -0
- package/src/session/migration/id-prefix.ts +146 -0
- package/src/session/migration/index.ts +38 -0
- package/src/session/migration/marker.ts +131 -0
- package/src/session/retention/__tests__/archive.test.ts +316 -0
- package/src/session/retention/__tests__/disk-backend.test.ts +180 -0
- package/src/session/retention/archive-backend-ref.ts +17 -0
- package/src/session/retention/archive.ts +281 -0
- package/src/session/retention/backend.ts +107 -0
- package/src/session/retention/disk-backend.ts +304 -0
- package/src/session/retention/index.ts +16 -0
- package/src/session/retention/policy.ts +53 -0
- package/src/session/summary/__tests__/materialize.test.ts +341 -0
- package/src/session/summary/deliverable.ts +84 -0
- package/src/session/summary/index.ts +31 -0
- package/src/session/summary/materialize.ts +169 -0
- package/src/session/summary/ref.ts +104 -0
- package/src/session/workspace/__tests__/git-worktree.test.ts +258 -0
- package/src/session/workspace/__tests__/path-builder.test.ts +51 -0
- package/src/session/workspace/driver.ts +60 -0
- package/src/session/workspace/git-worktree.ts +209 -0
- package/src/session/workspace/index.ts +25 -0
- package/src/session/workspace/path-builder.ts +71 -0
- package/src/session/workspace/ref.ts +50 -0
- package/src/session/workspace/registry.ts +42 -0
- package/src/store/conversation/memory.ts +23 -0
- package/src/store/session/__tests__/disk.test.ts +346 -0
- package/src/store/session/__tests__/memory.test.ts +327 -0
- package/src/store/session/disk.ts +920 -0
- package/src/store/session/index.ts +14 -0
- package/src/store/session/linkage.ts +80 -0
- package/src/store/session/memory.ts +400 -0
- package/src/store/session/messages.ts +21 -0
- package/src/types/agent/base.ts +31 -1
- package/src/types/agent/task.ts +58 -2
- package/src/types/conversation/index.ts +7 -0
- package/src/types/ids/index.ts +41 -3
- package/src/types/invocation/__tests__/state.test.ts +37 -29
- package/src/types/invocation/index.ts +26 -10
- package/src/types/run/config.ts +12 -1
- package/src/types/run/events.ts +36 -1
- package/src/types/run/index.ts +8 -0
- package/src/types/run/metadata.ts +24 -1
- package/src/types/run/status.ts +33 -0
- package/src/types/session/ids.ts +34 -0
- package/src/types/session/index.ts +28 -0
- package/src/types/session/store.ts +229 -0
- package/src/utils/id.ts +55 -4
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot-time filesystem re-layout — `.namzu/threads/{thd_X}/` →
|
|
3
|
+
* `.namzu/projects/{prj_legacy_<X>}/sessions/ses_legacy_default/runs/...`.
|
|
4
|
+
*
|
|
5
|
+
* Trigger: first {@link RunContextFactory.build} call per process. The
|
|
6
|
+
* factory invokes {@link DefaultFilesystemMigrator.migrate} before resolving
|
|
7
|
+
* any path so legacy runs are never orphaned by the new layout.
|
|
8
|
+
*
|
|
9
|
+
* See session-hierarchy.md §13.4.1 for the detection / trigger / atomicity
|
|
10
|
+
* contract. Concurrency model:
|
|
11
|
+
*
|
|
12
|
+
* 1. Main marker present → short-circuit `already_migrated`. Idempotent.
|
|
13
|
+
* 2. Legacy `.namzu/threads/` absent → write the main marker and return
|
|
14
|
+
* `noop_no_legacy`. This plants the marker on fresh installs so the
|
|
15
|
+
* `threads/` detection branch is only ever entered once.
|
|
16
|
+
* 3. Legacy layout detected → acquire the `.tmp` lock via `wx`; on
|
|
17
|
+
* EEXIST another boot is mid-migration. The loser waits 100ms and
|
|
18
|
+
* re-checks the main marker — cooperating, not competing. Roadmap
|
|
19
|
+
* Risk #4 mitigation.
|
|
20
|
+
* 4. Per-legacy-thread: rename the whole `runs/` subtree in a single
|
|
21
|
+
* `fs.rename` call (cross-OS atomic on the same filesystem; different
|
|
22
|
+
* filesystems fall back to copy-then-unlink via Node's default — a
|
|
23
|
+
* known limitation documented below).
|
|
24
|
+
* 5. Synthesize `project.json` + `session.json` via write-tmp-rename
|
|
25
|
+
* (Convention #8) so partial crashes leave no half-serialised state.
|
|
26
|
+
* 6. Write main marker last — presence of the marker is the canonical
|
|
27
|
+
* "migration done" signal.
|
|
28
|
+
*
|
|
29
|
+
* Known limitations:
|
|
30
|
+
* - Cross-filesystem moves: Node's `fs.rename` rejects with `EXDEV` when
|
|
31
|
+
* source and target live on different filesystems. This migrator does
|
|
32
|
+
* NOT fall back to copy-then-unlink; the error surfaces as
|
|
33
|
+
* {@link FilesystemMigrationError} with op `'rename_runs'`. Consumers
|
|
34
|
+
* running `.namzu/threads` and `.namzu/projects` on different mounts
|
|
35
|
+
* must migrate manually (documented INTERP flag).
|
|
36
|
+
* - `UNKNOWN_TENANT_ID`: legacy threads have no tenant denormalisation on
|
|
37
|
+
* disk. The synthesised project.json carries the sentinel so consumers
|
|
38
|
+
* know these are legacy-rehomed and can either tag-then-retain or
|
|
39
|
+
* reject until a real tenant is assigned (policy is consumer-owned).
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
import { mkdir, readdir, rename, stat } from 'node:fs/promises'
|
|
43
|
+
import { join } from 'node:path'
|
|
44
|
+
import type { TenantId } from '../../types/ids/index.js'
|
|
45
|
+
import { UNKNOWN_TENANT_ID } from '../../types/ids/index.js'
|
|
46
|
+
import type { ProjectId, SessionId } from '../../types/session/ids.js'
|
|
47
|
+
import { FilesystemMigrationError } from './errors.js'
|
|
48
|
+
import { acquireMigrationLock, readMarker, releaseMigrationLock, writeMarker } from './marker.js'
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Sentinel SessionId used for legacy pre-0.2.0 runs that pre-date the
|
|
52
|
+
* Session entity. Every migrated thread collapses into this single session
|
|
53
|
+
* so consumers can still address the runs through the new layout.
|
|
54
|
+
*/
|
|
55
|
+
export const LEGACY_DEFAULT_SESSION_ID = 'ses_legacy_default' as SessionId
|
|
56
|
+
|
|
57
|
+
/** Prefix for projects synthesised from legacy `thd_*` folders. */
|
|
58
|
+
export const LEGACY_DEFAULT_PROJECT_PREFIX = 'prj_legacy_'
|
|
59
|
+
|
|
60
|
+
/** Marker version string persisted at `.migration/v0.2.0`. */
|
|
61
|
+
export const MIGRATION_VERSION = '0.2.0'
|
|
62
|
+
|
|
63
|
+
/** Marker file path relative to rootDir. */
|
|
64
|
+
export const MARKER_REL_PATH = join('.migration', 'v0.2.0')
|
|
65
|
+
|
|
66
|
+
/** In-flight lock file path relative to rootDir. */
|
|
67
|
+
export const LOCK_REL_PATH = join('.migration', 'v0.2.0.tmp')
|
|
68
|
+
|
|
69
|
+
/** Delay before the loser re-checks the main marker on lock contention. */
|
|
70
|
+
const LOCK_WAIT_MS = 100
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Result of a migration attempt. `kind` discriminates the three outcomes;
|
|
74
|
+
* `migratedThreads` is only non-empty for `kind: 'migrated'`. Sinks and
|
|
75
|
+
* callers can switch on `kind` without string parsing.
|
|
76
|
+
*/
|
|
77
|
+
export interface FilesystemMigrationResult {
|
|
78
|
+
kind: 'migrated' | 'already_migrated' | 'noop_no_legacy'
|
|
79
|
+
migratedThreads: readonly { legacyThreadId: string; newProjectId: ProjectId }[]
|
|
80
|
+
markerPath: string
|
|
81
|
+
at: Date
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Event emitted on successful migration (`kind === 'migrated'` only). */
|
|
85
|
+
export interface FilesystemMigrationEvent {
|
|
86
|
+
type: 'filesystem.migrated'
|
|
87
|
+
result: FilesystemMigrationResult
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Sink contract — one `emit` method. */
|
|
91
|
+
export interface FilesystemMigrationSink {
|
|
92
|
+
emit(event: FilesystemMigrationEvent): void
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const NOOP_FILESYSTEM_MIGRATION_SINK: FilesystemMigrationSink = {
|
|
96
|
+
emit() {},
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Interface so consumers can inject a stub migrator in tests. */
|
|
100
|
+
export interface FilesystemMigrator {
|
|
101
|
+
migrate(rootDir: string): Promise<FilesystemMigrationResult>
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Persisted synthetic `project.json` shape. Matches
|
|
106
|
+
* `store/session/disk.ts:PersistedProject` plus a `_legacy: true` flag so
|
|
107
|
+
* readers can distinguish auto-synthesised records from real ones.
|
|
108
|
+
*/
|
|
109
|
+
interface SyntheticProject {
|
|
110
|
+
id: ProjectId
|
|
111
|
+
tenantId: TenantId
|
|
112
|
+
name: string
|
|
113
|
+
config: {
|
|
114
|
+
maxDelegationDepth: number
|
|
115
|
+
maxDelegationWidth: number
|
|
116
|
+
maxInterventionDepth: number
|
|
117
|
+
}
|
|
118
|
+
createdAt: string
|
|
119
|
+
updatedAt: string
|
|
120
|
+
_legacy: true
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Persisted synthetic `session.json` shape. Matches
|
|
125
|
+
* `store/session/disk.ts:PersistedSession` minimally. Status is `idle` so
|
|
126
|
+
* any read path that drills into these sessions does not mistake them for
|
|
127
|
+
* active work. `_legacy: true` flags them as auto-synthesised.
|
|
128
|
+
*/
|
|
129
|
+
interface SyntheticSession {
|
|
130
|
+
id: SessionId
|
|
131
|
+
projectId: ProjectId
|
|
132
|
+
tenantId: TenantId
|
|
133
|
+
status: 'idle'
|
|
134
|
+
currentActor: null
|
|
135
|
+
previousActors: readonly []
|
|
136
|
+
workspaceId: null
|
|
137
|
+
ownerVersion: 0
|
|
138
|
+
createdAt: string
|
|
139
|
+
updatedAt: string
|
|
140
|
+
_legacy: true
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Default implementation. Migration is driven by the contract documented in
|
|
145
|
+
* the module header — readers should trace concerns to this comment rather
|
|
146
|
+
* than re-deriving from code.
|
|
147
|
+
*/
|
|
148
|
+
export class DefaultFilesystemMigrator implements FilesystemMigrator {
|
|
149
|
+
constructor(private readonly sink: FilesystemMigrationSink = NOOP_FILESYSTEM_MIGRATION_SINK) {}
|
|
150
|
+
|
|
151
|
+
async migrate(rootDir: string): Promise<FilesystemMigrationResult> {
|
|
152
|
+
const markerPath = join(rootDir, MARKER_REL_PATH)
|
|
153
|
+
const lockPath = join(rootDir, LOCK_REL_PATH)
|
|
154
|
+
const threadsDir = join(rootDir, 'threads')
|
|
155
|
+
const projectsDir = join(rootDir, 'projects')
|
|
156
|
+
|
|
157
|
+
// Step 1: completed-marker short-circuit (cheapest idempotency check).
|
|
158
|
+
const existing = await readMarker(markerPath)
|
|
159
|
+
if (existing) {
|
|
160
|
+
return {
|
|
161
|
+
kind: 'already_migrated',
|
|
162
|
+
migratedThreads: [],
|
|
163
|
+
markerPath,
|
|
164
|
+
at: existing.at,
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Step 2: legacy absent → no-op. Plant the marker so subsequent boots
|
|
169
|
+
// do not re-enter this branch. Fresh installs fall through here.
|
|
170
|
+
const threadsExists = await directoryExists(threadsDir)
|
|
171
|
+
if (!threadsExists) {
|
|
172
|
+
const at = new Date()
|
|
173
|
+
try {
|
|
174
|
+
await writeMarker(markerPath, {
|
|
175
|
+
version: MIGRATION_VERSION,
|
|
176
|
+
at,
|
|
177
|
+
migratedThreads: [],
|
|
178
|
+
})
|
|
179
|
+
} catch (cause) {
|
|
180
|
+
throw new FilesystemMigrationError({
|
|
181
|
+
op: 'write_marker',
|
|
182
|
+
path: markerPath,
|
|
183
|
+
cause,
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
kind: 'noop_no_legacy',
|
|
188
|
+
migratedThreads: [],
|
|
189
|
+
markerPath,
|
|
190
|
+
at,
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Step 3: cooperate on the tmp lock.
|
|
195
|
+
try {
|
|
196
|
+
await acquireMigrationLock(lockPath)
|
|
197
|
+
} catch (err) {
|
|
198
|
+
const code = (err as NodeJS.ErrnoException).code
|
|
199
|
+
if (code === 'EEXIST') {
|
|
200
|
+
// Another boot is mid-migration — wait and re-read the main marker.
|
|
201
|
+
await sleep(LOCK_WAIT_MS)
|
|
202
|
+
const follow = await readMarker(markerPath)
|
|
203
|
+
if (follow) {
|
|
204
|
+
return {
|
|
205
|
+
kind: 'already_migrated',
|
|
206
|
+
migratedThreads: [],
|
|
207
|
+
markerPath,
|
|
208
|
+
at: follow.at,
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Main marker still absent — the winning boot is still going OR
|
|
212
|
+
// crashed. We re-throw so the caller sees a contention surface
|
|
213
|
+
// rather than silently assuming success.
|
|
214
|
+
throw new FilesystemMigrationError({
|
|
215
|
+
op: 'acquire_lock',
|
|
216
|
+
path: lockPath,
|
|
217
|
+
cause: err,
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
throw new FilesystemMigrationError({
|
|
221
|
+
op: 'acquire_lock',
|
|
222
|
+
path: lockPath,
|
|
223
|
+
cause: err,
|
|
224
|
+
})
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
// Step 4a: enumerate legacy thread dirs.
|
|
229
|
+
let entries: string[]
|
|
230
|
+
try {
|
|
231
|
+
entries = await readdir(threadsDir)
|
|
232
|
+
} catch (cause) {
|
|
233
|
+
throw new FilesystemMigrationError({
|
|
234
|
+
op: 'enumerate_threads',
|
|
235
|
+
path: threadsDir,
|
|
236
|
+
cause,
|
|
237
|
+
})
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const migrated: { legacyThreadId: string; newProjectId: ProjectId }[] = []
|
|
241
|
+
const now = new Date()
|
|
242
|
+
|
|
243
|
+
for (const entry of entries) {
|
|
244
|
+
// Accept only `thd_*` (and tolerate `prj_*` legacy in case of
|
|
245
|
+
// rerun after a partial-crash-with-renamed-but-no-marker).
|
|
246
|
+
if (!entry.startsWith('thd_')) continue
|
|
247
|
+
|
|
248
|
+
const legacyThreadId = entry
|
|
249
|
+
const suffix = legacyThreadId.slice('thd_'.length)
|
|
250
|
+
const newProjectId = `${LEGACY_DEFAULT_PROJECT_PREFIX}${suffix}` as ProjectId
|
|
251
|
+
|
|
252
|
+
const legacyRunsDir = join(threadsDir, legacyThreadId, 'runs')
|
|
253
|
+
const newProjectDir = join(projectsDir, newProjectId)
|
|
254
|
+
const newSessionDir = join(newProjectDir, 'sessions', LEGACY_DEFAULT_SESSION_ID)
|
|
255
|
+
const newRunsDir = join(newSessionDir, 'runs')
|
|
256
|
+
|
|
257
|
+
// Ensure parent path exists for the atomic rename of `runs/`.
|
|
258
|
+
try {
|
|
259
|
+
await mkdir(newSessionDir, { recursive: true })
|
|
260
|
+
} catch (cause) {
|
|
261
|
+
throw new FilesystemMigrationError({
|
|
262
|
+
op: 'mkdir_session',
|
|
263
|
+
path: newSessionDir,
|
|
264
|
+
cause,
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Move the whole `runs/` subtree in a single rename — atomic on
|
|
269
|
+
// same-filesystem, EXDEV on cross-mount (documented limitation).
|
|
270
|
+
const legacyRunsExists = await directoryExists(legacyRunsDir)
|
|
271
|
+
if (legacyRunsExists) {
|
|
272
|
+
try {
|
|
273
|
+
await rename(legacyRunsDir, newRunsDir)
|
|
274
|
+
} catch (cause) {
|
|
275
|
+
throw new FilesystemMigrationError({
|
|
276
|
+
op: 'rename_runs',
|
|
277
|
+
path: legacyRunsDir,
|
|
278
|
+
cause,
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Step 4b: synthesize project.json via write-tmp-rename.
|
|
284
|
+
const projectJson: SyntheticProject = {
|
|
285
|
+
id: newProjectId,
|
|
286
|
+
tenantId: UNKNOWN_TENANT_ID,
|
|
287
|
+
name: `legacy ${legacyThreadId}`,
|
|
288
|
+
config: {
|
|
289
|
+
maxDelegationDepth: 4,
|
|
290
|
+
maxDelegationWidth: 8,
|
|
291
|
+
maxInterventionDepth: 10,
|
|
292
|
+
},
|
|
293
|
+
createdAt: now.toISOString(),
|
|
294
|
+
updatedAt: now.toISOString(),
|
|
295
|
+
_legacy: true,
|
|
296
|
+
}
|
|
297
|
+
const projectJsonPath = join(newProjectDir, 'project.json')
|
|
298
|
+
try {
|
|
299
|
+
await atomicWriteJson(projectJsonPath, projectJson)
|
|
300
|
+
} catch (cause) {
|
|
301
|
+
throw new FilesystemMigrationError({
|
|
302
|
+
op: 'write_project_json',
|
|
303
|
+
path: projectJsonPath,
|
|
304
|
+
cause,
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Step 4c: synthesize session.json for the legacy-default session.
|
|
309
|
+
const sessionJson: SyntheticSession = {
|
|
310
|
+
id: LEGACY_DEFAULT_SESSION_ID,
|
|
311
|
+
projectId: newProjectId,
|
|
312
|
+
tenantId: UNKNOWN_TENANT_ID,
|
|
313
|
+
status: 'idle',
|
|
314
|
+
currentActor: null,
|
|
315
|
+
previousActors: [],
|
|
316
|
+
workspaceId: null,
|
|
317
|
+
ownerVersion: 0,
|
|
318
|
+
createdAt: now.toISOString(),
|
|
319
|
+
updatedAt: now.toISOString(),
|
|
320
|
+
_legacy: true,
|
|
321
|
+
}
|
|
322
|
+
const sessionJsonPath = join(newSessionDir, 'session.json')
|
|
323
|
+
try {
|
|
324
|
+
await atomicWriteJson(sessionJsonPath, sessionJson)
|
|
325
|
+
} catch (cause) {
|
|
326
|
+
throw new FilesystemMigrationError({
|
|
327
|
+
op: 'write_session_json',
|
|
328
|
+
path: sessionJsonPath,
|
|
329
|
+
cause,
|
|
330
|
+
})
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
migrated.push({ legacyThreadId, newProjectId })
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Step 5: write the completion marker last. Presence = done.
|
|
337
|
+
try {
|
|
338
|
+
await writeMarker(markerPath, {
|
|
339
|
+
version: MIGRATION_VERSION,
|
|
340
|
+
at: now,
|
|
341
|
+
migratedThreads: migrated,
|
|
342
|
+
})
|
|
343
|
+
} catch (cause) {
|
|
344
|
+
throw new FilesystemMigrationError({
|
|
345
|
+
op: 'write_marker',
|
|
346
|
+
path: markerPath,
|
|
347
|
+
cause,
|
|
348
|
+
})
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const result: FilesystemMigrationResult = {
|
|
352
|
+
kind: 'migrated',
|
|
353
|
+
migratedThreads: migrated,
|
|
354
|
+
markerPath,
|
|
355
|
+
at: now,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Step 6: emit event.
|
|
359
|
+
this.sink.emit({ type: 'filesystem.migrated', result })
|
|
360
|
+
|
|
361
|
+
return result
|
|
362
|
+
} finally {
|
|
363
|
+
// Always release the lock — even on failure, a crashed run with the
|
|
364
|
+
// main marker absent will retry on the next boot; the stale `.tmp`
|
|
365
|
+
// would otherwise wedge that retry.
|
|
366
|
+
await releaseMigrationLock(lockPath).catch(() => undefined)
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Shared atomic-write helper. Mirrors `store/session/disk.ts:atomicWriteJson`
|
|
373
|
+
* — intentionally duplicated so `session/migration/` has no inbound
|
|
374
|
+
* dependency on the store layer (Convention #4 dependency direction).
|
|
375
|
+
*/
|
|
376
|
+
async function atomicWriteJson(filePath: string, value: unknown): Promise<void> {
|
|
377
|
+
const { writeFile, rename: renameFile, unlink } = await import('node:fs/promises')
|
|
378
|
+
const tmp = `${filePath}.tmp`
|
|
379
|
+
try {
|
|
380
|
+
await writeFile(tmp, JSON.stringify(value, null, 2), 'utf-8')
|
|
381
|
+
await renameFile(tmp, filePath)
|
|
382
|
+
} catch (err) {
|
|
383
|
+
await unlink(tmp).catch(() => undefined)
|
|
384
|
+
throw err
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
async function directoryExists(path: string): Promise<boolean> {
|
|
389
|
+
try {
|
|
390
|
+
const s = await stat(path)
|
|
391
|
+
return s.isDirectory()
|
|
392
|
+
} catch (err) {
|
|
393
|
+
const code = (err as NodeJS.ErrnoException).code
|
|
394
|
+
if (code === 'ENOENT') return false
|
|
395
|
+
throw err
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function sleep(ms: number): Promise<void> {
|
|
400
|
+
return new Promise((resolve) => setTimeout(resolve, ms))
|
|
401
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ID-prefix migration window — read-side compat for legacy `thd_*` IDs.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 already ships {@link parseThreadId} in `utils/id.ts` that accepts
|
|
5
|
+
* either `thd_*` or `prj_*` silently. This module formalises the warning
|
|
6
|
+
* emission path called out in session-hierarchy.md §13.3.1:
|
|
7
|
+
*
|
|
8
|
+
* | Version | Reader accepts | Writer emits | Legacy read behaviour |
|
|
9
|
+
* |---------|---------------------|--------------|-------------------------------|
|
|
10
|
+
* | 0.2.x | `thd_*` AND `prj_*` | `prj_*` only | emits `MigrationWarning` once |
|
|
11
|
+
* | 0.3.x | `prj_*` only | `prj_*` only | rejects `StalePrefixError` |
|
|
12
|
+
*
|
|
13
|
+
* Consumers that touch raw legacy IDs (filesystem migrator, wire decoders,
|
|
14
|
+
* CLI imports) route through {@link acceptLegacyThreadId} so the warning
|
|
15
|
+
* signal is structured rather than ad-hoc console output (Convention #18).
|
|
16
|
+
*
|
|
17
|
+
* The `WINDOW_OPEN` constant is the single switch that flips this module
|
|
18
|
+
* from soft-accept to hard-reject when 0.3.0 cuts. Convention #0: no silent
|
|
19
|
+
* long-lived compat — the window is explicit, dated, and fails closed when
|
|
20
|
+
* the clock runs out.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import type { ProjectId } from '../../types/session/ids.js'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Structured event emitted when the reader accepts a legacy `thd_*` ID.
|
|
27
|
+
*
|
|
28
|
+
* Shape is stable across the 0.2.x window — platform consumers can wire
|
|
29
|
+
* this into their observability pipeline (metrics, audit log) without
|
|
30
|
+
* string parsing (Convention #18).
|
|
31
|
+
*/
|
|
32
|
+
export interface MigrationWarning {
|
|
33
|
+
kind: 'id_prefix_legacy_read'
|
|
34
|
+
legacyId: string
|
|
35
|
+
normalizedId: ProjectId
|
|
36
|
+
at: Date
|
|
37
|
+
emittedOncePerProcess: true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Sink contract — one `emit` method so callers can swap implementations. */
|
|
41
|
+
export interface MigrationWarningSink {
|
|
42
|
+
emit(warning: MigrationWarning): void
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Default sink used when consumers do not inject one. Drops warnings on the
|
|
47
|
+
* floor — migration still runs; observers just lose the signal. Convention
|
|
48
|
+
* #5 deny-by-default applies to behaviour, not telemetry; missing a warning
|
|
49
|
+
* sink is not a failure mode.
|
|
50
|
+
*/
|
|
51
|
+
export const NOOP_MIGRATION_WARNING_SINK: MigrationWarningSink = {
|
|
52
|
+
emit() {},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Raised when the reader encounters a string that is neither a valid
|
|
57
|
+
* `prj_*` nor `thd_*` prefix. In the 0.3.x window the legacy branch will
|
|
58
|
+
* also throw this error — flip {@link WINDOW_OPEN} to `false` to cut over.
|
|
59
|
+
*/
|
|
60
|
+
export class StalePrefixError extends Error {
|
|
61
|
+
readonly details: { rawId: string; kind: 'thd_rejected' | 'unknown_prefix' }
|
|
62
|
+
|
|
63
|
+
constructor(details: { rawId: string; kind: 'thd_rejected' | 'unknown_prefix' }) {
|
|
64
|
+
const reason =
|
|
65
|
+
details.kind === 'thd_rejected'
|
|
66
|
+
? `Stale ThreadId prefix '${details.rawId.slice(0, 4)}…' — run 'namzu sdk migrate-ids' before 0.3.0`
|
|
67
|
+
: `Unknown ID prefix '${details.rawId.slice(0, 4)}…' — expected 'prj_' or 'thd_'`
|
|
68
|
+
super(reason)
|
|
69
|
+
this.name = 'StalePrefixError'
|
|
70
|
+
this.details = details
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 0.2.x: compat window OPEN — `thd_*` coerces to `prj_*` with a warning.
|
|
76
|
+
* 0.3.x: flip to `false` — legacy branch becomes throw-only.
|
|
77
|
+
*/
|
|
78
|
+
export const WINDOW_OPEN = true
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Process-lifetime dedup map. Keyed by raw legacy ID so each distinct legacy
|
|
82
|
+
* string emits exactly one warning — spamming observability on a hot loop
|
|
83
|
+
* of reads is the anti-goal.
|
|
84
|
+
*/
|
|
85
|
+
const seenLegacy = new Set<string>()
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Accept-on-read for legacy `thd_*` IDs during the 0.2.x window.
|
|
89
|
+
*
|
|
90
|
+
* Contract:
|
|
91
|
+
* - `prj_*` inputs return as-is; no warning emitted.
|
|
92
|
+
* - `thd_*` inputs normalize to `prj_<suffix>` and emit a single
|
|
93
|
+
* {@link MigrationWarning} per distinct input string per process.
|
|
94
|
+
* - Everything else throws {@link StalePrefixError}.
|
|
95
|
+
* - When {@link WINDOW_OPEN} flips to `false`, the `thd_*` branch throws
|
|
96
|
+
* too — single knob, single commit.
|
|
97
|
+
*
|
|
98
|
+
* Testing hook: {@link __resetSeenLegacyForTests} clears the dedup Set so
|
|
99
|
+
* each test starts with a clean emission history.
|
|
100
|
+
*/
|
|
101
|
+
export function acceptLegacyThreadId(raw: string, sink: MigrationWarningSink): ProjectId {
|
|
102
|
+
if (raw.startsWith('prj_')) {
|
|
103
|
+
return raw as ProjectId
|
|
104
|
+
}
|
|
105
|
+
if (raw.startsWith('thd_')) {
|
|
106
|
+
if (!WINDOW_OPEN) {
|
|
107
|
+
throw new StalePrefixError({ rawId: raw, kind: 'thd_rejected' })
|
|
108
|
+
}
|
|
109
|
+
const normalized = `prj_${raw.slice('thd_'.length)}` as ProjectId
|
|
110
|
+
if (!seenLegacy.has(raw)) {
|
|
111
|
+
seenLegacy.add(raw)
|
|
112
|
+
sink.emit({
|
|
113
|
+
kind: 'id_prefix_legacy_read',
|
|
114
|
+
legacyId: raw,
|
|
115
|
+
normalizedId: normalized,
|
|
116
|
+
at: new Date(),
|
|
117
|
+
emittedOncePerProcess: true,
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
return normalized
|
|
121
|
+
}
|
|
122
|
+
throw new StalePrefixError({ rawId: raw, kind: 'unknown_prefix' })
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Writer guard: reject emission of `thd_*` at encode time. Phase 1's
|
|
127
|
+
* {@link generateProjectId} already emits `prj_*` only; this helper exists
|
|
128
|
+
* so write paths that handle raw strings (e.g. synthesis during filesystem
|
|
129
|
+
* migration) can fail fast on accidental legacy re-emission. Convention #0:
|
|
130
|
+
* no silent back-sliding to the old prefix.
|
|
131
|
+
*/
|
|
132
|
+
export function rejectLegacyPrefix(id: string): void {
|
|
133
|
+
if (id.startsWith('thd_')) {
|
|
134
|
+
throw new StalePrefixError({ rawId: id, kind: 'thd_rejected' })
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Test-only: clear the process-level dedup Set so subsequent
|
|
140
|
+
* {@link acceptLegacyThreadId} calls emit warnings again. Production code
|
|
141
|
+
* must never call this — the whole point is one warning per distinct
|
|
142
|
+
* legacy id per process.
|
|
143
|
+
*/
|
|
144
|
+
export function __resetSeenLegacyForTests(): void {
|
|
145
|
+
seenLegacy.clear()
|
|
146
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Sub-barrel for the migration module (Convention #4).
|
|
2
|
+
// Public surface for boot-time FS re-layout + ID-prefix read-accept.
|
|
3
|
+
// See session-hierarchy.md §13.3.1 (ID prefix) + §13.4.1 (filesystem).
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
acceptLegacyThreadId,
|
|
7
|
+
rejectLegacyPrefix,
|
|
8
|
+
NOOP_MIGRATION_WARNING_SINK,
|
|
9
|
+
StalePrefixError,
|
|
10
|
+
WINDOW_OPEN,
|
|
11
|
+
} from './id-prefix.js'
|
|
12
|
+
export type { MigrationWarning, MigrationWarningSink } from './id-prefix.js'
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
DefaultFilesystemMigrator,
|
|
16
|
+
NOOP_FILESYSTEM_MIGRATION_SINK,
|
|
17
|
+
LEGACY_DEFAULT_SESSION_ID,
|
|
18
|
+
LEGACY_DEFAULT_PROJECT_PREFIX,
|
|
19
|
+
MIGRATION_VERSION,
|
|
20
|
+
MARKER_REL_PATH,
|
|
21
|
+
LOCK_REL_PATH,
|
|
22
|
+
} from './filesystem.js'
|
|
23
|
+
export type {
|
|
24
|
+
FilesystemMigrator,
|
|
25
|
+
FilesystemMigrationResult,
|
|
26
|
+
FilesystemMigrationEvent,
|
|
27
|
+
FilesystemMigrationSink,
|
|
28
|
+
} from './filesystem.js'
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
readMarker,
|
|
32
|
+
writeMarker,
|
|
33
|
+
acquireMigrationLock,
|
|
34
|
+
releaseMigrationLock,
|
|
35
|
+
} from './marker.js'
|
|
36
|
+
export type { MigrationMarker } from './marker.js'
|
|
37
|
+
|
|
38
|
+
export { FilesystemMigrationError } from './errors.js'
|