@theoremjs/web 0.3.4-next.602.gb5a7fab → 0.3.4-next.604.ge4d5866

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 CHANGED
@@ -379,23 +379,23 @@ Each saved outcome records its absolute retention deadline. Changing a handler's
379
379
  Each issued gate records its absolute expiry. Changing `gateTtlMs` does not extend an issued gate.
380
380
  Ready, running, and uncertain operations do not expire.
381
381
 
382
- A session store declares its `capacity`: what it holds for one session, in bytes of UTF-8 JSON.
382
+ A session store with a real limit declares its `capacity`: what it holds for one session, in bytes of UTF-8 JSON.
383
383
 
384
- | Field | What it bounds | Memory store default |
385
- | --- | --- | --- |
386
- | `maxStateBytes` | One session's saved state | 16 MiB |
387
- | `maxOutcomeBytes` | One tool result | 1 MiB (`DEFAULT_MAX_OUTCOME_BYTES`) |
384
+ | Field | What it bounds |
385
+ | --- | --- |
386
+ | `maxStateBytes` | One session's saved state |
387
+ | `maxOutcomeBytes` | One tool result |
388
388
 
389
- Pass `capacity` to `createMemorySessionStore` to change them. A store you write declares the capacity of its own storage.
389
+ A store that declares no `capacity` holds any size. `createMemorySessionStore` declares none unless you pass `capacity`, with both fields. A store you write declares the capacity of its own storage, if it has one.
390
390
 
391
391
  Set `maxRequestBytes` to bound browser JSON before parsing. Its default is 16 MiB.
392
392
  The handler rejects oversized requests before provider access or tool preparation.
393
393
  Provider host options also accept `limits` for deadlines and upstream output.
394
- The handler keeps room for one `maxOutcomeBytes` result for each gate and each call that has not settled.
394
+ When the store declares a capacity, the handler keeps room for one `maxOutcomeBytes` result for each gate and each call that has not settled.
395
395
  When a session is full, the handler drops its oldest settled results, then its oldest provider checkpoints.
396
396
  It never drops gates, permissions, or calls that have not settled. When those alone do not fit, the new call is refused before it runs, and the user reads `session.full`.
397
397
  A result larger than `maxOutcomeBytes` settles as the call's `result_too_large` failure. The call is never left unresolved because of its size.
398
- The handler fits each state to the store's capacity before `compareAndSwap`.
398
+ The handler fits each state to the store's capacity, when it has one, before `compareAndSwap`.
399
399
 
400
400
  The default memory store coordinates handlers that share the same store object.
401
401
  It retains unexpired gates, unresolved operations, and unexpired outcomes during idle and capacity eviction.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theoremjs/web",
3
- "version": "0.3.4-next.602.gb5a7fab",
3
+ "version": "0.3.4-next.604.ge4d5866",
4
4
  "description": "Theorem on the web platform, with no UI framework: Web-standard server handlers that serve a profile, and the browser client that talks to them.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,6 +25,6 @@
25
25
  },
26
26
  "peerDependencies": {
27
27
  "zod": "^4.6.5",
28
- "@theoremjs/agents": "^0.3.4-next.602.gb5a7fab"
28
+ "@theoremjs/agents": "^0.3.4-next.604.ge4d5866"
29
29
  }
30
30
  }
package/server/mod.d.ts CHANGED
@@ -20,7 +20,6 @@ export { checkRequest, parseLiveClientMessage, parseLiveOpenMessage } from './re
20
20
  export { sessionStateStore } from './session-authority.ts';
21
21
  export { createTheoremSessionBoundary, type PreparedLiveOpen, type SessionBoundaryOptions, type TheoremSessionBoundary, } from './session-boundary.ts';
22
22
  export type { TheoremSessionCapacity } from './session-limits.ts';
23
- export { DEFAULT_SESSION_CAPACITY } from './session-limits.ts';
24
23
  export { createMemorySessionStore, DEFAULT_OPERATION_RETENTION_MS, type MemorySessionStoreOptions, type PendingToolGate, type SessionSnapshot, type SessionToolOperation, type SessionWriteResult, type TheoremSessionState, type TheoremSessionStore, theoremSessionStateSchema, } from './session-store.ts';
25
24
  export { createMemorySteerInbox, type SteerInbox, type SteerUnit, steerStage, steerUnitOf, stopOnRequest, } from './steer-inbox.ts';
26
25
  export { sessionToolCoordinator } from './tool-operations.ts';
package/server/mod.js CHANGED
@@ -18,7 +18,6 @@ export { createMemoryPageToolBroker, pageToolResultSchema, sessionPageDispatch,
18
18
  export { checkRequest, parseLiveClientMessage, parseLiveOpenMessage } from "./request-check.js";
19
19
  export { sessionStateStore } from "./session-authority.js";
20
20
  export { createTheoremSessionBoundary, } from "./session-boundary.js";
21
- export { DEFAULT_SESSION_CAPACITY } from "./session-limits.js";
22
21
  export { createMemorySessionStore, DEFAULT_OPERATION_RETENTION_MS, theoremSessionStateSchema, } from "./session-store.js";
23
22
  export { createMemorySteerInbox, steerStage, steerUnitOf, stopOnRequest, } from "./steer-inbox.js";
24
23
  export { sessionToolCoordinator } from "./tool-operations.js";
@@ -6,7 +6,7 @@ export type MutableStore<T> = {
6
6
  };
7
7
  /** Session state with the capacity its store declared. */
8
8
  export type SessionStateStore = MutableStore<TheoremSessionState> & {
9
- readonly capacity: TheoremSessionCapacity;
9
+ readonly capacity?: TheoremSessionCapacity;
10
10
  };
11
11
  /** Session state, with expired gates dropped as it loads so they can't be answered. */
12
12
  export declare function sessionStateStore(store: TheoremSessionStore, gateTtlMs: number, operationRetentionMs: number): SessionStateStore;
@@ -35,7 +35,7 @@ export function sessionStateStore(store, gateTtlMs, operationRetentionMs) {
35
35
  return { revision: snapshot?.revision ?? null, state };
36
36
  };
37
37
  return {
38
- capacity,
38
+ ...(capacity ? { capacity } : {}),
39
39
  async read(sessionId) {
40
40
  return (await load(sessionId, Date.now())).state;
41
41
  },
@@ -50,7 +50,8 @@ export function sessionStateStore(store, gateTtlMs, operationRetentionMs) {
50
50
  if (operation.status === 'settled')
51
51
  operation.retainUntil ??= operation.settledAt + operationRetentionMs;
52
52
  }
53
- fitSession(state, capacity);
53
+ if (capacity)
54
+ fitSession(state, capacity);
54
55
  const next = theoremSessionStateSchema.safeParse(state);
55
56
  if (!next.success) {
56
57
  throw new TheoremError('config', labelText('error.config'), {
@@ -1,15 +1,16 @@
1
1
  import type { TheoremSessionState } from './session-store.ts';
2
- /** What a session store holds for one session, in bytes of UTF-8 JSON. The store declares it. */
2
+ /** What a session store holds for one session, in bytes of UTF-8 JSON. A store with a real limit declares it. */
3
3
  export interface TheoremSessionCapacity {
4
4
  /** The most one session's saved state may take. */
5
5
  maxStateBytes: number;
6
6
  /** The most one tool result may take. Room for one is kept for each call that has not settled. */
7
7
  maxOutcomeBytes: number;
8
8
  }
9
- /** The memory store's default: room for sixteen full-size tool results in each session. */
10
- export declare const DEFAULT_SESSION_CAPACITY: TheoremSessionCapacity;
11
- /** The store's declared capacity, refused as `config` unless both are positive and one result fits. */
12
- export declare function checkedCapacity(capacity: unknown): TheoremSessionCapacity;
9
+ /**
10
+ * The store's declared capacity, refused as `config` unless both are positive and one result fits.
11
+ * Undefined when the store declares none: then it holds any size.
12
+ */
13
+ export declare function checkedCapacity(capacity: unknown): TheoremSessionCapacity | undefined;
13
14
  /**
14
15
  * Fits the state in the store's capacity: drops the oldest settled results, then the oldest
15
16
  * provider checkpoints, and refuses with `session.full` when open work alone does not fit.
@@ -1,11 +1,11 @@
1
- import { DEFAULT_MAX_OUTCOME_BYTES, labelText, TheoremError } from '@theoremjs/agents';
2
- /** The memory store's default: room for sixteen full-size tool results in each session. */
3
- export const DEFAULT_SESSION_CAPACITY = {
4
- maxStateBytes: 16 * DEFAULT_MAX_OUTCOME_BYTES,
5
- maxOutcomeBytes: DEFAULT_MAX_OUTCOME_BYTES,
6
- };
7
- /** The store's declared capacity, refused as `config` unless both are positive and one result fits. */
1
+ import { labelText, TheoremError } from '@theoremjs/agents';
2
+ /**
3
+ * The store's declared capacity, refused as `config` unless both are positive and one result fits.
4
+ * Undefined when the store declares none: then it holds any size.
5
+ */
8
6
  export function checkedCapacity(capacity) {
7
+ if (capacity === undefined)
8
+ return undefined;
9
9
  const { maxStateBytes, maxOutcomeBytes } = (capacity ?? {});
10
10
  if (!Number.isSafeInteger(maxStateBytes) ||
11
11
  !Number.isSafeInteger(maxOutcomeBytes) ||
@@ -88,8 +88,11 @@ export type SessionWriteResult = {
88
88
  * store (KV, Redis, a database row) when requests can reach different instances.
89
89
  */
90
90
  export interface TheoremSessionStore {
91
- /** What it holds for one session. The handler fits each write to it before `compareAndSwap`. */
92
- readonly capacity: TheoremSessionCapacity;
91
+ /**
92
+ * What it holds for one session, when it has a limit. The handler fits each write to it before
93
+ * `compareAndSwap`. Unset, the handler writes the state whole.
94
+ */
95
+ readonly capacity?: TheoremSessionCapacity;
93
96
  load(sessionId: string): Promise<SessionSnapshot | undefined>;
94
97
  /** Compare and replace atomically; null creates only an absent session. */
95
98
  compareAndSwap(sessionId: string, expectedRevision: string | null, next: TheoremSessionState): Promise<SessionWriteResult>;
@@ -101,8 +104,8 @@ export declare function pruneGates<Gate extends {
101
104
  expiresAt?: number;
102
105
  }>(gates: Record<string, Gate>, now: number, ttlMs: number): Record<string, Gate>;
103
106
  export type MemorySessionStoreOptions = {
104
- /** What it holds for one session. Default {@linkcode DEFAULT_SESSION_CAPACITY}. */
105
- capacity?: Partial<TheoremSessionCapacity>;
107
+ /** What it holds for one session. Unset, it holds any size. */
108
+ capacity?: TheoremSessionCapacity;
106
109
  /** invariant: Idle retention is in milliseconds. Protected authority remains. Default 24h. */
107
110
  ttlMs?: number;
108
111
  /** Oldest sessions are evicted past this count. Default 10 000. */
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import { jsonObjectSchema, jsonValueSchema, labelText, savedToolInvocationSchema, TheoremError, TOOL_AUTH_TYPES, TOOL_GATE_KINDS, TOOL_PERMISSION, toolOperationOutcomeSchema, turnHistoryMessageSchema, turnToolSnapshotSchema, z, } from '@theoremjs/agents';
12
12
  import { gateExpired } from '@theoremjs/agents/kernel';
13
- import { checkedCapacity, DEFAULT_SESSION_CAPACITY, } from "./session-limits.js";
13
+ import { checkedCapacity } from "./session-limits.js";
14
14
  export const DEFAULT_OPERATION_RETENTION_MS = 24 * 60 * 60 * 1000;
15
15
  const blobSchema = z.strictObject({
16
16
  data: z.string(),
@@ -219,7 +219,7 @@ export function createMemorySessionMap(options = {}) {
219
219
  }
220
220
  export function createMemorySessionStore(options = {}) {
221
221
  const { ttlMs, maxSessions } = memoryStoreLimits(options);
222
- const capacity = checkedCapacity({ ...DEFAULT_SESSION_CAPACITY, ...options.capacity });
222
+ const capacity = checkedCapacity(options.capacity);
223
223
  const sessions = new Map();
224
224
  const held = (entry) => Object.values(entry.snapshot.state.gates).some((gate) => gate.expiresAt === undefined || Date.now() < gate.expiresAt) ||
225
225
  Object.values(entry.snapshot.state.operations).some((operation) => operation.status !== 'settled' ||
@@ -234,7 +234,7 @@ export function createMemorySessionStore(options = {}) {
234
234
  return entry?.snapshot;
235
235
  };
236
236
  return {
237
- capacity,
237
+ ...(capacity ? { capacity } : {}),
238
238
  load(sessionId) {
239
239
  return Promise.resolve(structuredClone(current(sessionId)));
240
240
  },
@@ -1,7 +1,7 @@
1
1
  import { type ToolExecutionCoordinator } from '@theoremjs/agents';
2
2
  import type { TheoremSessionState } from './session-store.ts';
3
3
  export declare function sessionToolCoordinator(store: {
4
- readonly capacity: {
4
+ readonly capacity?: {
5
5
  maxOutcomeBytes: number;
6
6
  };
7
7
  mutate<T>(id: string, change: (state: TheoremSessionState) => T): Promise<T>;
@@ -69,7 +69,7 @@ function saveOutcome(state, identity, outcome) {
69
69
  }
70
70
  export function sessionToolCoordinator(store, sessionId) {
71
71
  return {
72
- maxOutcomeBytes: store.capacity.maxOutcomeBytes,
72
+ ...(store.capacity ? { maxOutcomeBytes: store.capacity.maxOutcomeBytes } : {}),
73
73
  lookup(identity) {
74
74
  return store.mutate(sessionId, (state) => {
75
75
  const record = checkedRecord(state, identity);