@sandbox-agent/persist-rivet 0.3.1 → 0.4.0-rc.1

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/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # @sandbox-agent/persist-rivet
2
+
3
+ > **Deprecated:** This package has been deprecated and removed.
4
+
5
+ Copy the driver source into your project. See the [multiplayer docs](https://github.com/rivet-dev/sandbox-agent/tree/main/docs/multiplayer.mdx) and the [session persistence docs](https://sandboxagent.dev/session-persistence) for guidance.
package/dist/index.d.ts CHANGED
@@ -1,36 +1,2 @@
1
- import { SessionRecord, SessionEvent, SessionPersistDriver, ListPageRequest, ListPage, ListEventsRequest } from 'sandbox-agent';
2
1
 
3
- /** Structural type compatible with rivetkit's ActorContext without importing it. */
4
- interface ActorContextLike {
5
- state: Record<string, unknown>;
6
- }
7
- interface RivetPersistData {
8
- sessions: Record<string, SessionRecord>;
9
- events: Record<string, SessionEvent[]>;
10
- }
11
- type RivetPersistState = {
12
- _sandboxAgentPersist: RivetPersistData;
13
- };
14
- interface RivetSessionPersistDriverOptions {
15
- /** Maximum number of sessions to retain. Oldest are evicted first. Default: 1024. */
16
- maxSessions?: number;
17
- /** Maximum events per session. Oldest are trimmed first. Default: 500. */
18
- maxEventsPerSession?: number;
19
- /** Key on `c.state` where persist data is stored. Default: `"_sandboxAgentPersist"`. */
20
- stateKey?: string;
21
- }
22
- declare class RivetSessionPersistDriver implements SessionPersistDriver {
23
- private readonly maxSessions;
24
- private readonly maxEventsPerSession;
25
- private readonly stateKey;
26
- private readonly ctx;
27
- constructor(ctx: ActorContextLike, options?: RivetSessionPersistDriverOptions);
28
- private get data();
29
- getSession(id: string): Promise<SessionRecord | null>;
30
- listSessions(request?: ListPageRequest): Promise<ListPage<SessionRecord>>;
31
- updateSession(session: SessionRecord): Promise<void>;
32
- listEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>>;
33
- insertEvent(event: SessionEvent): Promise<void>;
34
- }
35
-
36
- export { type ActorContextLike, type RivetPersistData, type RivetPersistState, RivetSessionPersistDriver, type RivetSessionPersistDriverOptions };
2
+ export { }
package/dist/index.js CHANGED
@@ -1,127 +1,5 @@
1
1
  // src/index.ts
2
- var DEFAULT_MAX_SESSIONS = 1024;
3
- var DEFAULT_MAX_EVENTS_PER_SESSION = 500;
4
- var DEFAULT_LIST_LIMIT = 100;
5
- var DEFAULT_STATE_KEY = "_sandboxAgentPersist";
6
- var RivetSessionPersistDriver = class {
7
- maxSessions;
8
- maxEventsPerSession;
9
- stateKey;
10
- ctx;
11
- constructor(ctx, options = {}) {
12
- this.ctx = ctx;
13
- this.maxSessions = normalizeCap(options.maxSessions, DEFAULT_MAX_SESSIONS);
14
- this.maxEventsPerSession = normalizeCap(
15
- options.maxEventsPerSession,
16
- DEFAULT_MAX_EVENTS_PER_SESSION
17
- );
18
- this.stateKey = options.stateKey ?? DEFAULT_STATE_KEY;
19
- if (!this.ctx.state[this.stateKey]) {
20
- this.ctx.state[this.stateKey] = { sessions: {}, events: {} };
21
- }
22
- }
23
- get data() {
24
- return this.ctx.state[this.stateKey];
25
- }
26
- async getSession(id) {
27
- const session = this.data.sessions[id];
28
- return session ? cloneSessionRecord(session) : null;
29
- }
30
- async listSessions(request = {}) {
31
- const sorted = Object.values(this.data.sessions).sort((a, b) => {
32
- if (a.createdAt !== b.createdAt) {
33
- return a.createdAt - b.createdAt;
34
- }
35
- return a.id.localeCompare(b.id);
36
- });
37
- const page = paginate(sorted, request);
38
- return {
39
- items: page.items.map(cloneSessionRecord),
40
- nextCursor: page.nextCursor
41
- };
42
- }
43
- async updateSession(session) {
44
- this.data.sessions[session.id] = { ...session };
45
- if (!this.data.events[session.id]) {
46
- this.data.events[session.id] = [];
47
- }
48
- const ids = Object.keys(this.data.sessions);
49
- if (ids.length <= this.maxSessions) {
50
- return;
51
- }
52
- const overflow = ids.length - this.maxSessions;
53
- const removable = Object.values(this.data.sessions).sort((a, b) => {
54
- if (a.createdAt !== b.createdAt) {
55
- return a.createdAt - b.createdAt;
56
- }
57
- return a.id.localeCompare(b.id);
58
- }).slice(0, overflow).map((s) => s.id);
59
- for (const sessionId of removable) {
60
- delete this.data.sessions[sessionId];
61
- delete this.data.events[sessionId];
62
- }
63
- }
64
- async listEvents(request) {
65
- const all = [...this.data.events[request.sessionId] ?? []].sort((a, b) => {
66
- if (a.eventIndex !== b.eventIndex) {
67
- return a.eventIndex - b.eventIndex;
68
- }
69
- return a.id.localeCompare(b.id);
70
- });
71
- const page = paginate(all, request);
72
- return {
73
- items: page.items.map(cloneSessionEvent),
74
- nextCursor: page.nextCursor
75
- };
76
- }
77
- async insertEvent(event) {
78
- const events = this.data.events[event.sessionId] ?? [];
79
- events.push(cloneSessionEvent(event));
80
- if (events.length > this.maxEventsPerSession) {
81
- events.splice(0, events.length - this.maxEventsPerSession);
82
- }
83
- this.data.events[event.sessionId] = events;
84
- }
85
- };
86
- function cloneSessionRecord(session) {
87
- return {
88
- ...session,
89
- sessionInit: session.sessionInit ? JSON.parse(JSON.stringify(session.sessionInit)) : void 0
90
- };
91
- }
92
- function cloneSessionEvent(event) {
93
- return {
94
- ...event,
95
- payload: JSON.parse(JSON.stringify(event.payload))
96
- };
97
- }
98
- function normalizeCap(value, fallback) {
99
- if (!Number.isFinite(value) || (value ?? 0) < 1) {
100
- return fallback;
101
- }
102
- return Math.floor(value);
103
- }
104
- function paginate(items, request) {
105
- const offset = parseCursor(request.cursor);
106
- const limit = normalizeCap(request.limit, DEFAULT_LIST_LIMIT);
107
- const slice = items.slice(offset, offset + limit);
108
- const nextOffset = offset + slice.length;
109
- return {
110
- items: slice,
111
- nextCursor: nextOffset < items.length ? String(nextOffset) : void 0
112
- };
113
- }
114
- function parseCursor(cursor) {
115
- if (!cursor) {
116
- return 0;
117
- }
118
- const parsed = Number.parseInt(cursor, 10);
119
- if (!Number.isFinite(parsed) || parsed < 0) {
120
- return 0;
121
- }
122
- return parsed;
123
- }
124
- export {
125
- RivetSessionPersistDriver
126
- };
2
+ throw new Error(
3
+ "@sandbox-agent/persist-rivet has been deprecated and removed. Copy the reference implementation from docs/multiplayer.mdx into your project instead. See https://github.com/rivet-dev/sandbox-agent/tree/main/docs/multiplayer.mdx"
4
+ );
127
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n ListEventsRequest,\n ListPage,\n ListPageRequest,\n SessionEvent,\n SessionPersistDriver,\n SessionRecord,\n} 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(\n options.maxEventsPerSession,\n DEFAULT_MAX_EVENTS_PER_SESSION,\n );\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\n ? (JSON.parse(JSON.stringify(session.sessionInit)) as SessionRecord[\"sessionInit\"])\n : 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":";AAgCA,IAAM,uBAAuB;AAC7B,IAAM,iCAAiC;AACvC,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB;AAEnB,IAAM,4BAAN,MAAgE;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,KAAuB,UAA4C,CAAC,GAAG;AACjF,SAAK,MAAM;AACX,SAAK,cAAc,aAAa,QAAQ,aAAa,oBAAoB;AACzE,SAAK,sBAAsB;AAAA,MACzB,QAAQ;AAAA,MACR;AAAA,IACF;AACA,SAAK,WAAW,QAAQ,YAAY;AAGpC,QAAI,CAAC,KAAK,IAAI,MAAM,KAAK,QAAQ,GAAG;AAClC,WAAK,IAAI,MAAM,KAAK,QAAQ,IAAI,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,IAAY,OAAyB;AACnC,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ;AAAA,EACrC;AAAA,EAEA,MAAM,WAAW,IAA2C;AAC1D,UAAM,UAAU,KAAK,KAAK,SAAS,EAAE;AACrC,WAAO,UAAU,mBAAmB,OAAO,IAAI;AAAA,EACjD;AAAA,EAEA,MAAM,aAAa,UAA2B,CAAC,GAAqC;AAClF,UAAM,SAAS,OAAO,OAAO,KAAK,KAAK,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9D,UAAI,EAAE,cAAc,EAAE,WAAW;AAC/B,eAAO,EAAE,YAAY,EAAE;AAAA,MACzB;AACA,aAAO,EAAE,GAAG,cAAc,EAAE,EAAE;AAAA,IAChC,CAAC;AACD,UAAM,OAAO,SAAS,QAAQ,OAAO;AACrC,WAAO;AAAA,MACL,OAAO,KAAK,MAAM,IAAI,kBAAkB;AAAA,MACxC,YAAY,KAAK;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,SAAuC;AACzD,SAAK,KAAK,SAAS,QAAQ,EAAE,IAAI,EAAE,GAAG,QAAQ;AAE9C,QAAI,CAAC,KAAK,KAAK,OAAO,QAAQ,EAAE,GAAG;AACjC,WAAK,KAAK,OAAO,QAAQ,EAAE,IAAI,CAAC;AAAA,IAClC;AAEA,UAAM,MAAM,OAAO,KAAK,KAAK,KAAK,QAAQ;AAC1C,QAAI,IAAI,UAAU,KAAK,aAAa;AAClC;AAAA,IACF;AAEA,UAAM,WAAW,IAAI,SAAS,KAAK;AACnC,UAAM,YAAY,OAAO,OAAO,KAAK,KAAK,QAAQ,EAC/C,KAAK,CAAC,GAAG,MAAM;AACd,UAAI,EAAE,cAAc,EAAE,WAAW;AAC/B,eAAO,EAAE,YAAY,EAAE;AAAA,MACzB;AACA,aAAO,EAAE,GAAG,cAAc,EAAE,EAAE;AAAA,IAChC,CAAC,EACA,MAAM,GAAG,QAAQ,EACjB,IAAI,CAAC,MAAM,EAAE,EAAE;AAElB,eAAW,aAAa,WAAW;AACjC,aAAO,KAAK,KAAK,SAAS,SAAS;AACnC,aAAO,KAAK,KAAK,OAAO,SAAS;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,SAA6D;AAC5E,UAAM,MAAM,CAAC,GAAI,KAAK,KAAK,OAAO,QAAQ,SAAS,KAAK,CAAC,CAAE,EAAE,KAAK,CAAC,GAAG,MAAM;AAC1E,UAAI,EAAE,eAAe,EAAE,YAAY;AACjC,eAAO,EAAE,aAAa,EAAE;AAAA,MAC1B;AACA,aAAO,EAAE,GAAG,cAAc,EAAE,EAAE;AAAA,IAChC,CAAC;AACD,UAAM,OAAO,SAAS,KAAK,OAAO;AAClC,WAAO;AAAA,MACL,OAAO,KAAK,MAAM,IAAI,iBAAiB;AAAA,MACvC,YAAY,KAAK;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,OAAoC;AACpD,UAAM,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS,KAAK,CAAC;AACrD,WAAO,KAAK,kBAAkB,KAAK,CAAC;AAEpC,QAAI,OAAO,SAAS,KAAK,qBAAqB;AAC5C,aAAO,OAAO,GAAG,OAAO,SAAS,KAAK,mBAAmB;AAAA,IAC3D;AAEA,SAAK,KAAK,OAAO,MAAM,SAAS,IAAI;AAAA,EACtC;AACF;AAEA,SAAS,mBAAmB,SAAuC;AACjE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,aAAa,QAAQ,cAChB,KAAK,MAAM,KAAK,UAAU,QAAQ,WAAW,CAAC,IAC/C;AAAA,EACN;AACF;AAEA,SAAS,kBAAkB,OAAmC;AAC5D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,KAAK,MAAM,KAAK,UAAU,MAAM,OAAO,CAAC;AAAA,EACnD;AACF;AAEA,SAAS,aAAa,OAA2B,UAA0B;AACzE,MAAI,CAAC,OAAO,SAAS,KAAK,MAAM,SAAS,KAAK,GAAG;AAC/C,WAAO;AAAA,EACT;AACA,SAAO,KAAK,MAAM,KAAe;AACnC;AAEA,SAAS,SAAY,OAAY,SAAuC;AACtE,QAAM,SAAS,YAAY,QAAQ,MAAM;AACzC,QAAM,QAAQ,aAAa,QAAQ,OAAO,kBAAkB;AAC5D,QAAM,QAAQ,MAAM,MAAM,QAAQ,SAAS,KAAK;AAChD,QAAM,aAAa,SAAS,MAAM;AAClC,SAAO;AAAA,IACL,OAAO;AAAA,IACP,YAAY,aAAa,MAAM,SAAS,OAAO,UAAU,IAAI;AAAA,EAC/D;AACF;AAEA,SAAS,YAAY,QAAoC;AACvD,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,SAAS,QAAQ,EAAE;AACzC,MAAI,CAAC,OAAO,SAAS,MAAM,KAAK,SAAS,GAAG;AAC1C,WAAO;AAAA,EACT;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["throw new Error(\n \"@sandbox-agent/persist-rivet has been deprecated and removed. \" +\n \"Copy the reference implementation from docs/multiplayer.mdx into your project instead. \" +\n \"See https://github.com/rivet-dev/sandbox-agent/tree/main/docs/multiplayer.mdx\",\n);\n"],"mappings":";AAAA,MAAM,IAAI;AAAA,EACR;AAGF;","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sandbox-agent/persist-rivet",
3
- "version": "0.3.1",
4
- "description": "Rivet Actor persistence driver for the Sandbox Agent TypeScript SDK",
3
+ "version": "0.4.0-rc.1",
4
+ "description": "Rivet Actor persistence driver for the Sandbox Agent TypeScript SDK (DEPRECATED)",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -16,30 +16,16 @@
16
16
  "import": "./dist/index.js"
17
17
  }
18
18
  },
19
- "dependencies": {
20
- "sandbox-agent": "0.3.1"
21
- },
22
- "peerDependencies": {
23
- "rivetkit": ">=0.5.0"
24
- },
25
- "peerDependenciesMeta": {
26
- "rivetkit": {
27
- "optional": true
28
- }
29
- },
30
19
  "files": [
31
20
  "dist"
32
21
  ],
33
22
  "devDependencies": {
34
23
  "@types/node": "^22.0.0",
35
24
  "tsup": "^8.0.0",
36
- "typescript": "^5.7.0",
37
- "vitest": "^3.0.0"
25
+ "typescript": "^5.7.0"
38
26
  },
39
27
  "scripts": {
40
28
  "build": "tsup",
41
- "typecheck": "tsc --noEmit",
42
- "test": "vitest run",
43
- "test:watch": "vitest"
29
+ "typecheck": "tsc --noEmit"
44
30
  }
45
31
  }