@sandbox-agent/persist-rivet 0.3.1 → 0.3.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/dist/index.js +1 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -11,10 +11,7 @@ var RivetSessionPersistDriver = class {
|
|
|
11
11
|
constructor(ctx, options = {}) {
|
|
12
12
|
this.ctx = ctx;
|
|
13
13
|
this.maxSessions = normalizeCap(options.maxSessions, DEFAULT_MAX_SESSIONS);
|
|
14
|
-
this.maxEventsPerSession = normalizeCap(
|
|
15
|
-
options.maxEventsPerSession,
|
|
16
|
-
DEFAULT_MAX_EVENTS_PER_SESSION
|
|
17
|
-
);
|
|
14
|
+
this.maxEventsPerSession = normalizeCap(options.maxEventsPerSession, DEFAULT_MAX_EVENTS_PER_SESSION);
|
|
18
15
|
this.stateKey = options.stateKey ?? DEFAULT_STATE_KEY;
|
|
19
16
|
if (!this.ctx.state[this.stateKey]) {
|
|
20
17
|
this.ctx.state[this.stateKey] = { sessions: {}, events: {} };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { ListEventsRequest, ListPage, ListPageRequest, SessionEvent, SessionPersistDriver, SessionRecord } from \"sandbox-agent\";\n\n/** Structural type compatible with rivetkit's ActorContext without importing it. */\nexport interface ActorContextLike {\n state: Record<string, unknown>;\n}\n\nexport interface RivetPersistData {\n sessions: Record<string, SessionRecord>;\n events: Record<string, SessionEvent[]>;\n}\n\nexport type RivetPersistState = {\n _sandboxAgentPersist: RivetPersistData;\n};\n\nexport interface RivetSessionPersistDriverOptions {\n /** Maximum number of sessions to retain. Oldest are evicted first. Default: 1024. */\n maxSessions?: number;\n /** Maximum events per session. Oldest are trimmed first. Default: 500. */\n maxEventsPerSession?: number;\n /** Key on `c.state` where persist data is stored. Default: `\"_sandboxAgentPersist\"`. */\n stateKey?: string;\n}\n\nconst DEFAULT_MAX_SESSIONS = 1024;\nconst DEFAULT_MAX_EVENTS_PER_SESSION = 500;\nconst DEFAULT_LIST_LIMIT = 100;\nconst DEFAULT_STATE_KEY = \"_sandboxAgentPersist\";\n\nexport class RivetSessionPersistDriver implements SessionPersistDriver {\n private readonly maxSessions: number;\n private readonly maxEventsPerSession: number;\n private readonly stateKey: string;\n private readonly ctx: ActorContextLike;\n\n constructor(ctx: ActorContextLike, options: RivetSessionPersistDriverOptions = {}) {\n this.ctx = ctx;\n this.maxSessions = normalizeCap(options.maxSessions, DEFAULT_MAX_SESSIONS);\n this.maxEventsPerSession = normalizeCap(options.maxEventsPerSession, DEFAULT_MAX_EVENTS_PER_SESSION);\n this.stateKey = options.stateKey ?? DEFAULT_STATE_KEY;\n\n // Auto-initialize if absent; preserve existing data on actor wake.\n if (!this.ctx.state[this.stateKey]) {\n this.ctx.state[this.stateKey] = { sessions: {}, events: {} } satisfies RivetPersistData;\n }\n }\n\n private get data(): RivetPersistData {\n return this.ctx.state[this.stateKey] as RivetPersistData;\n }\n\n async getSession(id: string): Promise<SessionRecord | null> {\n const session = this.data.sessions[id];\n return session ? cloneSessionRecord(session) : null;\n }\n\n async listSessions(request: ListPageRequest = {}): Promise<ListPage<SessionRecord>> {\n const sorted = Object.values(this.data.sessions).sort((a, b) => {\n if (a.createdAt !== b.createdAt) {\n return a.createdAt - b.createdAt;\n }\n return a.id.localeCompare(b.id);\n });\n const page = paginate(sorted, request);\n return {\n items: page.items.map(cloneSessionRecord),\n nextCursor: page.nextCursor,\n };\n }\n\n async updateSession(session: SessionRecord): Promise<void> {\n this.data.sessions[session.id] = { ...session };\n\n if (!this.data.events[session.id]) {\n this.data.events[session.id] = [];\n }\n\n const ids = Object.keys(this.data.sessions);\n if (ids.length <= this.maxSessions) {\n return;\n }\n\n const overflow = ids.length - this.maxSessions;\n const removable = Object.values(this.data.sessions)\n .sort((a, b) => {\n if (a.createdAt !== b.createdAt) {\n return a.createdAt - b.createdAt;\n }\n return a.id.localeCompare(b.id);\n })\n .slice(0, overflow)\n .map((s) => s.id);\n\n for (const sessionId of removable) {\n delete this.data.sessions[sessionId];\n delete this.data.events[sessionId];\n }\n }\n\n async listEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>> {\n const all = [...(this.data.events[request.sessionId] ?? [])].sort((a, b) => {\n if (a.eventIndex !== b.eventIndex) {\n return a.eventIndex - b.eventIndex;\n }\n return a.id.localeCompare(b.id);\n });\n const page = paginate(all, request);\n return {\n items: page.items.map(cloneSessionEvent),\n nextCursor: page.nextCursor,\n };\n }\n\n async insertEvent(event: SessionEvent): Promise<void> {\n const events = this.data.events[event.sessionId] ?? [];\n events.push(cloneSessionEvent(event));\n\n if (events.length > this.maxEventsPerSession) {\n events.splice(0, events.length - this.maxEventsPerSession);\n }\n\n this.data.events[event.sessionId] = events;\n }\n}\n\nfunction cloneSessionRecord(session: SessionRecord): SessionRecord {\n return {\n ...session,\n sessionInit: session.sessionInit ? (JSON.parse(JSON.stringify(session.sessionInit)) as SessionRecord[\"sessionInit\"]) : undefined,\n };\n}\n\nfunction cloneSessionEvent(event: SessionEvent): SessionEvent {\n return {\n ...event,\n payload: JSON.parse(JSON.stringify(event.payload)) as SessionEvent[\"payload\"],\n };\n}\n\nfunction normalizeCap(value: number | undefined, fallback: number): number {\n if (!Number.isFinite(value) || (value ?? 0) < 1) {\n return fallback;\n }\n return Math.floor(value as number);\n}\n\nfunction paginate<T>(items: T[], request: ListPageRequest): ListPage<T> {\n const offset = parseCursor(request.cursor);\n const limit = normalizeCap(request.limit, DEFAULT_LIST_LIMIT);\n const slice = items.slice(offset, offset + limit);\n const nextOffset = offset + slice.length;\n return {\n items: slice,\n nextCursor: nextOffset < items.length ? String(nextOffset) : undefined,\n };\n}\n\nfunction parseCursor(cursor: string | undefined): number {\n if (!cursor) {\n return 0;\n }\n const parsed = Number.parseInt(cursor, 10);\n if (!Number.isFinite(parsed) || parsed < 0) {\n return 0;\n }\n return parsed;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sandbox-agent/persist-rivet",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Rivet Actor persistence driver for the Sandbox Agent TypeScript SDK",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"sandbox-agent": "0.3.
|
|
20
|
+
"sandbox-agent": "0.3.2"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
23
|
"rivetkit": ">=0.5.0"
|