@kaged/storage
SQLite adapter via bun:sqlite with schema migrations, CRUD for sessions/messages/providers/compactions/task instances, and transcript persistence
5
source files
5
test files
~8.2k
lines
✓ 253 pass
tests
pass
typecheck
clean
lint
Test results 253
sqlite storage compactions > createCompaction + getCompaction round-trip
[4.39ms]
sqlite storage compactions > getCompaction returns null for nonexistent id
[2.59ms]
sqlite storage compactions > createCompaction duplicate id throws ConstraintError
[2.78ms]
sqlite storage compactions > round-trips all trigger types
[2.99ms]
sqlite storage compactions > round-trips all strategy types
[3.08ms]
sqlite storage compactions > round-trips supersededMessageIds as JSON array
[2.70ms]
sqlite storage compactions > round-trips empty supersededMessageIds
[2.65ms]
sqlite storage compactions > round-trips pluginsFired with entries
[2.62ms]
sqlite storage compactions > round-trips pluginCost when present
[2.63ms]
sqlite storage compactions > round-trips pluginCost as null
[2.58ms]
sqlite storage compactions > round-trips fallbackOccurred boolean
[2.62ms]
sqlite storage compactions > round-trips summary fields
[2.61ms]
sqlite storage compactions > round-trips checkpoint linkage
[2.60ms]
sqlite storage compactions > round-trips operator feedback fields
[2.88ms]
sqlite storage compactions — listCompactions > lists compactions for a session ordered by created_at
[3.09ms]
sqlite storage compactions — listCompactions > returns empty list for session with no compactions
[2.67ms]
sqlite storage compactions — listCompactions > paginates with cursor
[3.04ms]
sqlite storage compactions — listCompactions > does not return compactions from other sessions
[2.79ms]
sqlite storage compactions — updateCompaction > updates afterEstimate
[2.75ms]
sqlite storage compactions — updateCompaction > updates operator feedback
[2.64ms]
sqlite storage compactions — updateCompaction > updates fallback fields
[2.67ms]
sqlite storage compactions — updateCompaction > updates supersededMessageIds
[2.55ms]
sqlite storage compactions — updateCompaction > updates summary fields
[2.63ms]
sqlite storage compactions — updateCompaction > updates checkpointId
[2.71ms]
sqlite storage compactions — updateCompaction > no-op update does nothing
[2.61ms]
sqlite storage compactions — updateCompaction > throws NotFoundError for nonexistent id
[2.62ms]
sqlite storage compactions — updateCompaction > preserves unchanged fields on partial update
[2.86ms]
sqlite storage compactions — migration v9 > schema version is 9
[2.68ms]
sqlite storage issues > createIssue + getIssue round-trip
[3.06ms]
sqlite storage issues > getIssue returns null for nonexistent id
[1.77ms]
sqlite storage issues > getIssueByNumber round-trip
[1.82ms]
sqlite storage issues > getIssueByNumber returns null when absent
[1.75ms]
sqlite storage issues > createIssue duplicate id throws ConstraintError
[1.82ms]
sqlite storage issues > createIssue duplicate project/number throws ConstraintError
[1.91ms]
sqlite storage issues > listIssues by projectId
[2.05ms]
sqlite storage issues > listIssues filtered by status
[2.06ms]
sqlite storage issues > listIssues filtered by createdBy
[1.89ms]
sqlite storage issues > listIssues orders by updatedAt descending
[1.88ms]
sqlite storage issues > listIssues paginates with cursor + limit
[2.05ms]
sqlite storage issues > updateIssue updates title
[1.85ms]
sqlite storage issues > updateIssue updates body
[1.78ms]
sqlite storage issues > updateIssue updates status assignment resolution fields
[1.79ms]
sqlite storage issues > updateIssue preserves originalBody on first edit
[1.79ms]
sqlite storage issues > updateIssue does not overwrite originalBody when omitted later
[1.73ms]
sqlite storage issues > updateIssue can clear assignment
[1.75ms]
sqlite storage issues > updateIssue nonexistent throws NotFoundError
[1.74ms]
sqlite storage issues > deleteIssue success
[1.95ms]
sqlite storage issues > deleteIssue nonexistent throws NotFoundError
[2.94ms]
sqlite storage issues > deleteIssue cascades to issue_updates
[2.16ms]
sqlite storage issues > nextIssueNumber starts at 1
[1.90ms]
sqlite storage issues > nextIssueNumber increments per project
[2.12ms]
sqlite storage issues > countIssues counts by project
[2.12ms]
sqlite storage issues > createIssueUpdate + getIssueUpdate round-trip
[2.09ms]
sqlite storage issues > getIssueUpdate returns null for nonexistent id
[2.02ms]
sqlite storage issues > createIssueUpdate duplicate id throws ConstraintError
[2.43ms]
sqlite storage issues > createIssueUpdate missing issue throws ConstraintError
[1.82ms]
sqlite storage issues > listIssueUpdates ordered by created_at ASC
[1.97ms]
sqlite storage issues > listIssueUpdates paginates
[2.07ms]
sqlite storage issues > listIssueUpdates only returns rows for requested issue
[1.91ms]
sqlite storage issues > deleteIssueUpdate success
[1.81ms]
sqlite storage issues > deleteIssueUpdate nonexistent throws NotFoundError
[1.73ms]
sqlite storage issues > metadata round-trip JSON
[1.85ms]
sqlite storage issues > visibility values persist for all and operator_only
[2.13ms]
initialization > sqlite storage > creates database with WAL mode
[5.21ms]
initialization > sqlite storage > creates schema_version table with current version
[4.23ms]
initialization > sqlite storage > creates all 24 tables
[4.32ms]
initialization > sqlite storage > idempotent — opening same DB twice does not fail
[4.29ms]
initialization > sqlite storage > foreign keys are enforced
[3.90ms]
sessions > sqlite storage > create and get session
[3.99ms]
sessions > sqlite storage > get non-existent session returns null
[3.81ms]
sessions > sqlite storage > duplicate session id throws ConstraintError
[19.92ms]
sessions > sqlite storage > update session state
[4.03ms]
sessions > sqlite storage > update session endedAt
[3.96ms]
sessions > sqlite storage > update session name
[3.90ms]
sessions > sqlite storage > clear session name with null
[3.92ms]
sessions > sqlite storage > create session with name
[3.78ms]
sessions > sqlite storage > update non-existent session throws NotFoundError
[3.81ms]
sessions > sqlite storage > list sessions returns all
[3.99ms]
sessions > sqlite storage > list sessions filters by projectId
[4.03ms]
sessions > sqlite storage > list sessions filters by createdBy
[4.00ms]
sessions > sqlite storage > list sessions filters by state
[3.98ms]
sessions > sqlite storage > list sessions paginates with cursor
[4.26ms]
sessions > sqlite storage > count sessions by project excludes ended sessions
[4.19ms]
sessions > sqlite storage > count sessions by operator excludes ended sessions
[4.00ms]
sessions > sqlite storage > forkedFrom is persisted
[3.93ms]
runs > sqlite storage > create and get run
[3.99ms]
runs > sqlite storage > get non-existent run returns null
[3.94ms]
runs > sqlite storage > duplicate run id throws ConstraintError
[3.95ms]
runs > sqlite storage > update run state and completion
[4.81ms]
runs > sqlite storage > update run with error
[3.97ms]
runs > sqlite storage > update non-existent run throws NotFoundError
[3.90ms]
runs > sqlite storage > list runs for session
[4.07ms]
runs > sqlite storage > list runs paginates
[25.68ms]
runs > sqlite storage > count runs for session
[3.93ms]
runs > sqlite storage > run error round-trips through JSON
[3.95ms]
runs > sqlite storage > getProjectStats returns session aggregates, 24h activity, and recent runs
[5.60ms]
messages > sqlite storage > create and list messages
[4.29ms]
messages > sqlite storage > supersede messages after cursor
[4.46ms]
messages > sqlite storage > messages paginate with cursor
[4.32ms]
messages > sqlite storage > message metadata round-trips through JSON
[4.18ms]
messages > sqlite storage > message with runId
[4.09ms]
checkpoints > sqlite storage > create and get checkpoint
[4.10ms]
checkpoints > sqlite storage > get non-existent checkpoint returns null
[3.93ms]
checkpoints > sqlite storage > update checkpoint resumed
[4.40ms]
checkpoints > sqlite storage > update checkpoint rolled back
[4.08ms]
checkpoints > sqlite storage > update checkpoint superseded
[4.31ms]
checkpoints > sqlite storage > update non-existent checkpoint throws NotFoundError
[4.26ms]
checkpoints > sqlite storage > list checkpoints for session
[4.49ms]
checkpoints > sqlite storage > count checkpoints
[4.27ms]
checkpoints > sqlite storage > rolledBack round-trips as boolean
[4.26ms]
checkpoints > sqlite storage > createdBy values persist correctly
[4.26ms]
subagent invocations > sqlite storage > create and get subagent invocation
[4.35ms]
subagent invocations > sqlite storage > get non-existent returns null
[4.18ms]
subagent invocations > sqlite storage > update subagent invocation state
[4.36ms]
subagent invocations > sqlite storage > update non-existent throws NotFoundError
[4.29ms]
subagent invocations > sqlite storage > list subagent invocations for run
[4.43ms]
subagent invocations > sqlite storage > cageId null when uncaged
[4.20ms]
tool calls > sqlite storage > create and get tool call
[4.35ms]
tool calls > sqlite storage > get non-existent returns null
[4.13ms]
tool calls > sqlite storage > update tool call completion
[4.35ms]
tool calls > sqlite storage > update non-existent throws NotFoundError
[4.19ms]
tool calls > sqlite storage > list tool calls for run
[4.54ms]
tool calls > sqlite storage > tool calls paginate
[4.56ms]
pty transcripts > sqlite storage > create and list pty transcripts
[4.49ms]
pty transcripts > sqlite storage > empty list for unknown run
[4.20ms]
pty transcripts > sqlite storage > multiple transcripts per run
[4.36ms]
prompt edits > sqlite storage > create and list prompt edits
[4.49ms]
prompt edits > sqlite storage > empty list for unknown checkpoint
[4.24ms]
prompt edits > sqlite storage > multiple edits per checkpoint
[4.36ms]
edge cases > sqlite storage > empty updates are no-ops (runs)
[4.18ms]
edge cases > sqlite storage > empty updates are no-ops (checkpoints)
[4.23ms]
edge cases > sqlite storage > page limit clamped to max 200
[4.26ms]
edge cases > sqlite storage > page limit minimum 1
[4.21ms]
edge cases > sqlite storage > close is idempotent
[4.06ms]
edge cases > sqlite storage > supersedeMessagesAfter returns 0 when no messages match
[22.07ms]
errors module > sqlite storage > StorageError has correct name
[4.06ms]
errors module > sqlite storage > NotFoundError includes entity info
[4.07ms]
errors module > sqlite storage > ConstraintError preserves cause
[4.77ms]
task instances > sqlite storage > create and get task instance
[4.50ms]
task instances > sqlite storage > get returns null for missing instance
[4.15ms]
task instances > sqlite storage > duplicate create throws ConstraintError
[4.20ms]
task instances > sqlite storage > update task instance state and exit
[4.38ms]
task instances > sqlite storage > update nonexistent instance throws NotFoundError
[4.10ms]
task instances > sqlite storage > update with empty changes is no-op
[4.14ms]
task instances > sqlite storage > update tmux fields
[4.24ms]
task instances > sqlite storage > delete task instance
[4.28ms]
task instances > sqlite storage > delete nonexistent instance throws NotFoundError
[4.13ms]
task instances > sqlite storage > list task instances by project
[4.53ms]
task instances > sqlite storage > list task instances by state
[4.31ms]
task instances > sqlite storage > list task instances respects pagination limit
[4.40ms]
task instances > sqlite storage > count task instances by project
[4.25ms]
task instances > sqlite storage > stores and retrieves all fields including nulls
[4.18ms]
task instances > sqlite storage > stores and retrieves instance with all null optional fields
[4.36ms]
task transcripts > sqlite storage > create and list task transcript
[4.46ms]
task transcripts > sqlite storage > empty list for unknown task instance
[4.19ms]
task transcripts > sqlite storage > multiple transcripts per task instance
[4.31ms]
task transcripts > sqlite storage > duplicate id throws ConstraintError
[4.23ms]
task transcripts > sqlite storage > foreign key to nonexistent task instance fails
[4.24ms]
task transcripts > sqlite storage > large transcript blob round-trips correctly
[6.39ms]
guests > sqlite storage > createGuest + getGuest round-trip
[4.32ms]
guests > sqlite storage > getGuestByHandle
[4.19ms]
guests > sqlite storage > listGuests with status filter and pagination
[4.56ms]
guests > sqlite storage > updateGuest handle, displayName, passwordHash, status changes
[4.36ms]
guests > sqlite storage > updateGuest throws ConstraintError on duplicate handle
[4.37ms]
guests > sqlite storage > deleteGuest + cascade to invites, sessions, grants
[5.01ms]
guests > sqlite storage > createGuest throws ConstraintError on duplicate userId
[4.26ms]
guests > sqlite storage > createGuest throws ConstraintError on duplicate handle
[4.56ms]
guests > sqlite storage > getGuest returns null for missing
[4.09ms]
guest invites > sqlite storage > createGuestInvite + getGuestInvite round-trip
[4.26ms]
guest invites > sqlite storage > deleteGuestInvite
[4.24ms]
guest invites > sqlite storage > deleteGuestInvitesByUser
[4.46ms]
guest invites > sqlite storage > deleteExpiredGuestInvites returns count of deleted
[4.40ms]
guest invites > sqlite storage > getGuestInvite returns null for missing
[4.06ms]
guest sessions > sqlite storage > createGuestSession + getGuestSession round-trip
[4.22ms]
guest sessions > sqlite storage > updateGuestSession lastActiveAt
[4.29ms]
guest sessions > sqlite storage > deleteGuestSession
[4.20ms]
guest sessions > sqlite storage > deleteGuestSessionsByUser
[4.42ms]
guest sessions > sqlite storage > updateGuestSession throws NotFoundError for missing
[4.08ms]
guest sessions > sqlite storage > getGuestSession returns null for missing
[4.07ms]
project guest grants > sqlite storage > createProjectGuestGrant + getProjectGuestGrant round-trip
[4.28ms]
project guest grants > sqlite storage > JSON round-trip for permissionSet
[4.24ms]
project guest grants > sqlite storage > listProjectGuestGrants by project
[4.43ms]
project guest grants > sqlite storage > listGuestGrants by user
[4.32ms]
project guest grants > sqlite storage > updateProjectGuestGrant new permissionSet, notes
[4.47ms]
project guest grants > sqlite storage > deleteProjectGuestGrant
[4.35ms]
project guest grants > sqlite storage > deleteProjectGuestGrant throws NotFoundError for missing
[4.08ms]
project guest grants > sqlite storage > getProjectGuestGrant returns null for missing
[4.06ms]
model overrides > sqlite storage > getModelOverrides returns empty for no overrides
[4.15ms]
model overrides > sqlite storage > upsert and get single override
[4.24ms]
model overrides > sqlite storage > upsert multiple overrides for same model
[4.22ms]
model overrides > sqlite storage > upsert replaces existing override (idempotent)
[4.19ms]
model overrides > sqlite storage > overrides are isolated per provider
[4.23ms]
model overrides > sqlite storage > overrides are isolated per model
[4.27ms]
model overrides > sqlite storage > deleteModelOverride removes single field
[4.33ms]
model overrides > sqlite storage > deleteModelOverride throws NotFoundError for missing
[4.16ms]
model overrides > sqlite storage > deleteAllModelOverrides removes all fields for a model
[4.26ms]
model overrides > sqlite storage > deleteAllModelOverrides returns 0 when none exist
[4.13ms]
provider spend limits > sqlite storage > getSpendLimit returns null when not set
[4.14ms]
provider spend limits > sqlite storage > upsert and get spend limit
[4.19ms]
provider spend limits > sqlite storage > upsert replaces existing spend limit
[4.22ms]
provider spend limits > sqlite storage > spend limit with percentage-based windows
[4.14ms]
provider spend limits > sqlite storage > deleteSpendLimit removes the limit
[4.16ms]
provider spend limits > sqlite storage > deleteSpendLimit throws NotFoundError for missing
[4.13ms]
provider spend limits > sqlite storage > limits are isolated per provider
[4.25ms]
provider spend events > sqlite storage > createSpendEvent and sumSpendByWindow
[4.42ms]
provider spend events > sqlite storage > sumSpendByWindow returns null when no events
[4.16ms]
provider spend events > sqlite storage > sumSpendByWindow isolates by provider
[4.29ms]
provider spend events > sqlite storage > sumSpendByWindow isolates by window key
[4.28ms]
provider spend events > sqlite storage > sumSpendByWindow7d with 7-day window
[4.24ms]
provider spend events > sqlite storage > sumSpendByWindow7d returns null when no events
[4.05ms]
provider usage cache > sqlite storage > getUsageCache returns null when not cached
[4.11ms]
provider usage cache > sqlite storage > setUsageCache and getUsageCache
[4.19ms]
provider usage cache > sqlite storage > setUsageCache replaces existing cache
[4.12ms]
provider usage cache > sqlite storage > deleteUsageCache removes the cache
[4.14ms]
provider usage cache > sqlite storage > deleteUsageCache is idempotent for missing provider
[4.08ms]
provider usage cache > sqlite storage > usage cache is isolated per provider
[4.15ms]
session boundIssue > sqlite storage issue todos and links > create session with boundIssue and getSession returns it
[9.54ms]
session boundIssue > sqlite storage issue todos and links > update session boundIssue persists new issue id
[4.10ms]
session boundIssue > sqlite storage issue todos and links > update session boundIssue can clear to null
[4.00ms]
issue_todos > sqlite storage issue todos and links > create and get issue todo
[4.38ms]
issue_todos > sqlite storage issue todos and links > get non-existent issue todo returns null
[3.93ms]
issue_todos > sqlite storage issue todos and links > duplicate issue todo id throws ConstraintError
[4.08ms]
issue_todos > sqlite storage issue todos and links > list issue todos returns position order ascending
[4.34ms]
issue_todos > sqlite storage issue todos and links > list issue todos breaks position ties by id
[4.16ms]
issue_todos > sqlite storage issue todos and links > list issue todos filters by status
[4.10ms]
issue_todos > sqlite storage issue todos and links > list issue todos filters by kind
[4.10ms]
issue_todos > sqlite storage issue todos and links > list issue todos filters by phase
[4.08ms]
issue_todos > sqlite storage issue todos and links > list issue todos combines status kind and phase filters
[4.24ms]
issue_todos > sqlite storage issue todos and links > update issue todo persists mutable fields
[4.19ms]
issue_todos > sqlite storage issue todos and links > update non-existent issue todo throws NotFoundError
[3.97ms]
issue_todos > sqlite storage issue todos and links > delete issue todo removes it
[4.06ms]
issue_todos > sqlite storage issue todos and links > delete non-existent issue todo throws NotFoundError
[3.94ms]
issue_todos > sqlite storage issue todos and links > count issue todos counts only matching issue
[4.12ms]
issue_todos > sqlite storage issue todos and links > nextIssueTodoPosition starts at one for empty issue
[3.90ms]
issue_todos > sqlite storage issue todos and links > nextIssueTodoPosition uses max position plus one
[7.30ms]
issue_todos > sqlite storage issue todos and links > storage allows multiple in_progress (handler enforces single-in_progress)
[4.15ms]
issue_todos > sqlite storage issue todos and links > another todo can become in_progress after current one completes
[4.16ms]
issue_links > sqlite storage issue todos and links > create and get issue link
[5.62ms]
issue_links > sqlite storage issue todos and links > get non-existent issue link returns null
[4.37ms]
issue_links > sqlite storage issue todos and links > duplicate issue link id throws ConstraintError
[4.50ms]
issue_links > sqlite storage issue todos and links > listIssueLinksFrom returns links ordered by createdAt
[4.47ms]
issue_links > sqlite storage issue todos and links > listIssueLinksTo returns links ordered by createdAt
[4.48ms]
issue_links > sqlite storage issue todos and links > listIssueLinksForProject returns only matching project links
[4.51ms]
issue_links > sqlite storage issue todos and links > listIssueLinksForProject paginates by cursor
[4.74ms]
issue_links > sqlite storage issue todos and links > delete issue link removes it
[4.49ms]
issue_links > sqlite storage issue todos and links > delete non-existent issue link throws NotFoundError
[4.33ms]
cascade delete > sqlite storage issue todos and links > deleting an issue cascades to issue_todos
[7.94ms]
cascade delete > sqlite storage issue todos and links > deleting an issue cascades to outgoing and incoming issue_links
[4.61ms]
sqlite storage guest activity > listGuestActivity returns issues opened by the guest
[6.52ms]
sqlite storage guest activity > listGuestActivity returns comments made by the guest
[2.56ms]
sqlite storage guest activity > listGuestActivity returns grant events for the guest
[2.57ms]
sqlite storage guest activity > listGuestActivity filters by projectId
[2.55ms]
sqlite storage guest activity > listGuestActivity paginates with cursor + limit
[3.25ms]