[R2] Export KVStore from a /kv subpath and add fileStore(dir) - #292
Merged
Merged
Conversation
- New subpath @lousho/build-ai-agent/kv (src/deploy/kv.ts): KVStore,
KVCheckpointStore, CHECKPOINT_KV_BINDING and the KVStoreOptions, KVBinding,
KVPutOptions types. Its import graph is Node-free: assertSessionId moved to
src/session/sessionId.ts (re-exported from sessionStore.ts), and the
type-only imports in kvStore.ts and checkpoint.ts are now `import type`.
kv.test.ts bundles the barrel with esbuild for the browser platform and
fails on any node: import.
- fileStore(dir, { historyLimit }) (root export): sessions, checkpoints,
checkpoint history and approvals as JSON files, written atomically, no lock
files. Approvals are claimed with an exclusive create so two resolvers get
the record once (a rename claim is not atomic on Windows).
- Docs: sessions, deployment, durable-execution, api-overview; CHANGELOG.
Closes #189
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aits for its killed child The guardrails timeout test kills its slow child with a taskkill it does not wait for; on Windows the scratch directory stays locked (EPERM) until the child exits, and with the new kv.test.ts in the suite the afterEach rm hit that window in 5 of 6 local full runs. The cleanup now retries on EPERM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md
…g; longer timeout for the file-backed history contract Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md
…v-file-store # Conflicts: # CHANGELOG.md # package.json # tsup.config.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md
# Conflicts: # CHANGELOG.md
This was referenced Oct 2, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #189
What
@lousho/build-ai-agent/kv(new subpath, additive):KVStore,KVCheckpointStore,CHECKPOINT_KV_BINDINGand the typesKVStoreOptions,KVBinding,KVPutOptions(src/deploy/kv.ts, tsup entrydeploy/kv, one addedexportsblock). The barrel is Node-free:assertSessionIdmoved tosrc/session/sessionId.ts(re-exported fromsessionStore.ts, so existing imports are unchanged),kvStore.tsimportsSessionStoreas a type, andcheckpoint.tsimportsMessage/StorageServiceas types.src/deploy/kv.test.tsbundles the barrel with esbuild (platform: 'browser',metafile) and asserts no input imports anode:path.fileStore(dir, { historyLimit? })(root export,src/storage/fileStore.ts):sessions/<id>.json(FileSessionStore),checkpoints/<id>.json,checkpoint-history/<id>.json,approvals/<id>.json. Atomic temp-file + rename writes, no lock files, noStorageService; directories are created on first write; a corrupt history file reads as empty; session/checkpoint and approval ids are validated (approval ids against/^[A-Za-z0-9_-]{1,128}$/).docs/deployment.md(Worker example importingKVStorefrom/kv, key table kept),docs/sessions.md(store table rows and thefileStore('./.lousho')snippet),docs/durable-execution.md(history table),docs/api-overview.md.llms.txt/llms-full.txtregenerated. CHANGELOG entry under Unreleased. README unchanged.Deviation from the ticket
FileApprovalStore.resolveclaims the record with an exclusive create of<id>.json.claim(flag: 'wx') instead of renaming the record: on Windows two concurrent renames of the same file could both succeed in testing, so the rename was not a safe claim. A resolver that crashes after claiming leaves the claim file and the approval resolves tonulluntil it is saved again (tested). The concurrency test runs 10 rounds of two store instances resolving one id and gets exactly one record each round.Also included:
src/execution/guardrails.test.tsafterEachretriesrmSynconEPERM(Windows keeps the killed timeout child's working directory locked briefly); test-only, needed for the suite to pass locally.Docs site
No page was added and no
##/###/####heading was added, renamed or removed. Edited pages:deployment.md,sessions.md,durable-execution.md,api-overview.md. The docs site needs only a content sync, no navigation change.Verification (on the branch, synced with origin/main)
npx tsc --noEmit: oknpm run lint: ok (0 warnings)npm run build/npm run build --workspace=packages/create-lousho-agent: oknpm run test:types: no type errorsnpm run docs:verify-snippets -- --skip-build: all 207 snippets type-check, 8 also runnpm run docs:llms:check: oknpm run pack-smoke: all checks passed (esm 16/16 and cjs 16/16 entries loaded, including./kv);dist/deploy/kv.d.tsexports all six names;dist/deploy/kv.mjscontains nonode:npm run test:coverage: final run after merging the latest origin/main ([M10a] Slack and Discord: a pending ask_question survives a restart #285 and [N13a] web_fetch built-in with pinned-DNS SSRF checks; http_request no longer open to DNS rebinding #277; CHANGELOG conflicts kept both sides, llms regenerated), viavitest run --coverage --config vitest.coverage.config.ts --coverage.reportOnFailure: 225 of 226 files passed, 3220 tests passed, 2 skipped; the one failure wasNodeWorkspace.test.ts"returns stdout, stderr and the exit code" timing out at 5 s under load from other agents, and that file alone passed (26 passed, 1 skipped). An earlier run failed only in the Docker integration ofSubprocessSandbox.test.ts("no such container"; shared daemon), which passed 13/13 alone.npx vitest run src/session src/deploy src/storage: 23 files, 244 tests passednpx vitest run src/session src/deploy src/storage src/execution/checkpointHistory.contract.test.ts: 24 files, 296 tests passednpm run fallow: exit 0, dead code: no issues, maintainability 89.7typecheckok,typecheck:serverok,test13 files / 112 tests passed,test:server14 files / 122 tests passedLive test spend: none (the ticket makes no live calls).
🤖 Generated with Claude Code