@workerdeck/server 0.15.0 → 0.17.0
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 +10 -0
- package/build/index.d.mts +200 -77
- package/build/index.mjs +3190 -2526
- package/build/index.mjs.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -208,6 +208,16 @@ OAuth, never reads or forwards tokens — see the repo README's
|
|
|
208
208
|
VFS only when *not* restoring, and dispose per-session resources via `onClose`. Every one is a
|
|
209
209
|
runtime-only failure. `createProviderRunner()` does all four; reach for the raw hook only when it
|
|
210
210
|
genuinely doesn't fit.
|
|
211
|
+
- **`parking.persistLive` is how a *provider* session survives a restart, and it needs a durable
|
|
212
|
+
store to mean anything.** Claude and codex go dormant — remembered by engine session id and
|
|
213
|
+
resumed from the engine's own store — which a provider session cannot do, so its record carries
|
|
214
|
+
the state itself, written through after every turn. With the default in-memory store the option
|
|
215
|
+
does nothing and says nothing. It is off by default: a library must not start writing sessions'
|
|
216
|
+
transcripts to disk because someone upgraded, and the record holds the whole transcript in
|
|
217
|
+
plaintext.
|
|
218
|
+
- **A restored session is refreshed in place, not consumed.** A park's record *is* the session and
|
|
219
|
+
is deleted on wake; a live or dormant one is a way back the session still needs next time. If you
|
|
220
|
+
implement a `SessionStore`, do not "tidy up" a record on read.
|
|
211
221
|
- **One origin is not a convenience.** A browser cannot put an `Authorization` header on a
|
|
212
222
|
WebSocket upgrade, so a cookie is the only credential a tab can present on an attach, and a
|
|
213
223
|
cookie is per-origin. That is what `fallback` is for — an app served from the gateway's own port.
|
package/build/index.d.mts
CHANGED
|
@@ -1,40 +1,45 @@
|
|
|
1
1
|
import { IncomingMessage, Server, ServerResponse } from "node:http";
|
|
2
2
|
import { AttachmentInput, BridgeAnswer, BrowserBridgeExecutor, ClaudeAuthProbe, EngineAdapter, EngineSessionOptions, HostToolDefinition, LanguageModel, McpConnection, ParkedExecution, Runner, RunnerSnapshot, SessionRunnerConfig, ToolExecutionResult, ToolExecutor, ToolSet } from "@workerdeck/core";
|
|
3
3
|
import { JobQueue, QueueAdapter } from "@workerdeck/queue";
|
|
4
|
-
import { CreateSessionRequest, JobEvent, MessageAttachment, ProfileEngine, ProfileInfo, ProviderConfig, SdkSessionSummary, ServerFrame, SessionCapability, SessionInfo, SessionNotification, SessionWebhookConfig } from "@workerdeck/protocol";
|
|
4
|
+
import { CreateSessionRequest, JobEvent, MessageAttachment, ProfileEngine, ProfileInfo, ProfileUsage, ProviderConfig, SdkSessionSummary, ServerFrame, SessionCapability, SessionInfo, SessionNotification, SessionWebhookConfig } from "@workerdeck/protocol";
|
|
5
5
|
|
|
6
|
-
//#region src/
|
|
7
|
-
type
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
*/
|
|
13
|
-
onRegister?: (runner: Runner) => void;
|
|
6
|
+
//#region src/services/bridge.d.ts
|
|
7
|
+
type BridgeHubOptions = {
|
|
8
|
+
/** How long a bridged call may stay unanswered before it fails. Default 60000. */timeoutMs?: number;
|
|
9
|
+
/** Called when a bridged execution reaches a terminal result — the host feeds
|
|
10
|
+
* it back into the runner's loop. */
|
|
11
|
+
onResult?: (sessionId: string, executionId: string, result: ToolExecutionResult) => void;
|
|
14
12
|
};
|
|
15
|
-
/**
|
|
16
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Routes tool executions between a session and the browser tabs attached to it.
|
|
15
|
+
*
|
|
16
|
+
* A session may have several clients attached (dashboard plus embedded panel);
|
|
17
|
+
* the bridge asks the **first attached** one, which is the closest thing to "the
|
|
18
|
+
* client driving this session". If none is attached, dispatch fails fast rather
|
|
19
|
+
* than hanging — an autonomous job simply never bridges, it uses the server
|
|
20
|
+
* executor instead.
|
|
21
|
+
*/
|
|
22
|
+
declare class BridgeHub {
|
|
17
23
|
#private;
|
|
18
|
-
constructor(options?:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
closeAll(): void;
|
|
24
|
+
constructor(options?: BridgeHubOptions);
|
|
25
|
+
/** The executor to hand a runner for this session. Created on first use and
|
|
26
|
+
* reused, so results routed back always reach the same pending table. */
|
|
27
|
+
executorFor(sessionId: string): BrowserBridgeExecutor;
|
|
28
|
+
/** How many clients are watching this session. Parking consults it: a session
|
|
29
|
+
* someone is watching stays live. */
|
|
30
|
+
attachedCount(sessionId: string): number;
|
|
31
|
+
/** Register an attached client. Returns a detach function. */
|
|
32
|
+
attach(sessionId: string, send: (frame: ServerFrame) => void): () => void;
|
|
33
|
+
/**
|
|
34
|
+
* Deliver a client's answer to a bridged call. Returns false when the id is
|
|
35
|
+
* unknown or already settled — late and duplicate answers are ignored.
|
|
36
|
+
*/
|
|
37
|
+
resolve(sessionId: string, executionId: string, answer: BridgeAnswer): boolean;
|
|
38
|
+
/** Drop a session's bridge, failing anything still in flight. */
|
|
39
|
+
remove(sessionId: string): void;
|
|
35
40
|
}
|
|
36
41
|
//#endregion
|
|
37
|
-
//#region src/notifications.d.ts
|
|
42
|
+
//#region src/services/notifications.d.ts
|
|
38
43
|
type SessionNotificationOptions = {
|
|
39
44
|
/** POST target for every notification. */webhook?: SessionWebhookConfig;
|
|
40
45
|
/** Local observer, invoked for every notification whether or not a webhook is
|
|
@@ -43,6 +48,11 @@ type SessionNotificationOptions = {
|
|
|
43
48
|
onNotification?: (notification: SessionNotification) => void; /** Delivery attempts per notification (exponential backoff). Default 3. */
|
|
44
49
|
attempts?: number; /** Initial backoff between attempts. Default 500ms. */
|
|
45
50
|
retryDelayMs?: number;
|
|
51
|
+
/** Gateway wiring, not a host option: the serve-time `SessionInfo` decoration
|
|
52
|
+
* (project identity today), so a webhook or push consumer reads the same
|
|
53
|
+
* record every REST caller does. The assembly supplies it; identity when
|
|
54
|
+
* absent. */
|
|
55
|
+
decorateInfo?: (info: SessionInfo) => SessionInfo;
|
|
46
56
|
};
|
|
47
57
|
/**
|
|
48
58
|
* Turns session events into the handful of notifications a human away from the
|
|
@@ -73,58 +83,74 @@ declare class SessionNotifier {
|
|
|
73
83
|
watch(runner: Runner, afterSeq?: number): void;
|
|
74
84
|
}
|
|
75
85
|
//#endregion
|
|
76
|
-
//#region src/
|
|
77
|
-
type
|
|
78
|
-
/** How long a bridged call may stay unanswered before it fails. Default 60000. */timeoutMs?: number;
|
|
79
|
-
/** Called when a bridged execution reaches a terminal result — the host feeds
|
|
80
|
-
* it back into the runner's loop. */
|
|
81
|
-
onResult?: (sessionId: string, executionId: string, result: ToolExecutionResult) => void;
|
|
82
|
-
};
|
|
83
|
-
/**
|
|
84
|
-
* Routes tool executions between a session and the browser tabs attached to it.
|
|
85
|
-
*
|
|
86
|
-
* A session may have several clients attached (dashboard plus embedded panel);
|
|
87
|
-
* the bridge asks the **first attached** one, which is the closest thing to "the
|
|
88
|
-
* client driving this session". If none is attached, dispatch fails fast rather
|
|
89
|
-
* than hanging — an autonomous job simply never bridges, it uses the server
|
|
90
|
-
* executor instead.
|
|
91
|
-
*/
|
|
92
|
-
declare class BridgeHub {
|
|
93
|
-
#private;
|
|
94
|
-
constructor(options?: BridgeHubOptions);
|
|
95
|
-
/** The executor to hand a runner for this session. Created on first use and
|
|
96
|
-
* reused, so results routed back always reach the same pending table. */
|
|
97
|
-
executorFor(sessionId: string): BrowserBridgeExecutor;
|
|
98
|
-
/** How many clients are watching this session. Parking consults it: a session
|
|
99
|
-
* someone is watching stays live. */
|
|
100
|
-
attachedCount(sessionId: string): number;
|
|
101
|
-
/** Register an attached client. Returns a detach function. */
|
|
102
|
-
attach(sessionId: string, send: (frame: ServerFrame) => void): () => void;
|
|
86
|
+
//#region src/services/registry.d.ts
|
|
87
|
+
type SessionRegistryOptions = {
|
|
103
88
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
89
|
+
* Called once per runner as it enters the table, before it starts — the one
|
|
90
|
+
* seam every path goes through (create, prepare, adopt, and the rebuild of a
|
|
91
|
+
* parked session), which is what a watcher that must not miss a session needs.
|
|
106
92
|
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
93
|
+
onRegister?: (runner: Runner) => void;
|
|
94
|
+
};
|
|
95
|
+
/** In-memory session table. Terminal sessions stay listed until removed or the process exits. */
|
|
96
|
+
declare class SessionRegistry {
|
|
97
|
+
#private;
|
|
98
|
+
constructor(options?: SessionRegistryOptions);
|
|
99
|
+
create(config: SessionRunnerConfig): Runner;
|
|
100
|
+
/** Build and list a Claude-engine runner without starting it, so watchers can
|
|
101
|
+
* subscribe first. Call `start()` once they have. */
|
|
102
|
+
prepare(config: SessionRunnerConfig): Runner;
|
|
103
|
+
/** Register an already-built runner (a non-Claude engine) and start it. */
|
|
104
|
+
adopt(runner: Runner): Runner;
|
|
105
|
+
/** List a runner without starting it — for a rehydrated session, whose watchers
|
|
106
|
+
* must be subscribed before it comes back up. */
|
|
107
|
+
register(runner: Runner): Runner;
|
|
108
|
+
get(id: string): Runner | undefined;
|
|
109
|
+
list(): SessionInfo[];
|
|
110
|
+
remove(id: string): boolean;
|
|
111
|
+
/** Drop a runner WITHOUT closing it: the session isn't ending, it parked and
|
|
112
|
+
* lives on in its snapshot. Closing here would tell every client it was over. */
|
|
113
|
+
evict(id: string): boolean;
|
|
114
|
+
closeAll(): void;
|
|
110
115
|
}
|
|
111
116
|
//#endregion
|
|
112
|
-
//#region src/session-store.d.ts
|
|
117
|
+
//#region src/services/session-store.d.ts
|
|
113
118
|
/**
|
|
114
|
-
* A session
|
|
119
|
+
* A session captured whole: its wire-visible info, the config to rebuild the
|
|
120
|
+
* runner, the engine's snapshot, and what it is waiting for.
|
|
115
121
|
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
122
|
+
* Two things are stored in this one shape, and the discriminator is `kind`:
|
|
123
|
+
*
|
|
124
|
+
* - **`parked`** — the live runner is torn down and the session is waiting on
|
|
125
|
+
* deferred executions. The record *is* the session, so waking consumes it.
|
|
126
|
+
* - **`live`** — the runner is up and this is a copy taken after a turn, so the
|
|
127
|
+
* session survives a restart (`persistLive`). It is a way back that the
|
|
128
|
+
* session still needs the *next* time the process dies, so waking **refreshes
|
|
129
|
+
* it in place** and only `session_closed` removes it.
|
|
130
|
+
*
|
|
131
|
+
* That difference is the whole reason these are two kinds rather than one, and
|
|
132
|
+
* it is a correctness difference, not bookkeeping: consuming a live record on
|
|
133
|
+
* wake opens a window from the attach to the next turn in which the session
|
|
134
|
+
* exists nowhere durable. A user who opens a session, reads it and types nothing
|
|
135
|
+
* would lose it to a redeploy — silently, which is the failure class worth
|
|
136
|
+
* spending a discriminator on.
|
|
137
|
+
*
|
|
138
|
+
* They share the shape so a store, and an older server, need no new code: every
|
|
139
|
+
* other branch (rebuild from `config` + `snapshot`, serve `snapshot.vfs`, arm
|
|
140
|
+
* `executions`, subscribe past `snapshot.seq`) is already right for both.
|
|
119
141
|
*/
|
|
120
142
|
type ParkedSessionRecord = {
|
|
121
|
-
/** Absent on records written before dormant sessions existed — those are all parked. */kind?: 'parked';
|
|
122
|
-
id: string;
|
|
143
|
+
/** Absent on records written before dormant sessions existed — those are all parked. */kind?: 'parked' | 'live';
|
|
144
|
+
id: string;
|
|
145
|
+
/** Session info as of the write: `parked` for a park, `idle` for a live copy —
|
|
146
|
+
* never `running`, which would come back as a spinner over no process. */
|
|
123
147
|
info: SessionInfo;
|
|
124
148
|
profile?: string; /** The config the session was created with (profile defaults already applied). */
|
|
125
149
|
config: SessionRunnerConfig;
|
|
126
150
|
snapshot: RunnerSnapshot;
|
|
127
|
-
|
|
151
|
+
/** Empty for a live record: an idle session is waiting on nothing, so there is
|
|
152
|
+
* nothing for `hydrate` to arm a watchdog for. */
|
|
153
|
+
executions: ParkedExecution[]; /** When it was written. Named for the park that came first. */
|
|
128
154
|
parkedAt: number;
|
|
129
155
|
};
|
|
130
156
|
/**
|
|
@@ -228,7 +254,7 @@ type FileSessionStoreOptions = {
|
|
|
228
254
|
*/
|
|
229
255
|
declare function createFileSessionStore(options?: FileSessionStoreOptions): SessionStore;
|
|
230
256
|
//#endregion
|
|
231
|
-
//#region src/parking.d.ts
|
|
257
|
+
//#region src/services/parking.d.ts
|
|
232
258
|
type SessionParkOptions = {
|
|
233
259
|
registry: SessionRegistry;
|
|
234
260
|
store: SessionStore;
|
|
@@ -246,6 +272,24 @@ type SessionParkOptions = {
|
|
|
246
272
|
/** Wait this long after the last client detaches before parking, so a reconnect
|
|
247
273
|
* (a wifi blip, a page reload) doesn't cost a teardown. Default 2000. */
|
|
248
274
|
parkDelayMs?: number;
|
|
275
|
+
/**
|
|
276
|
+
* Keep a live session's snapshot written through to the store, so it survives
|
|
277
|
+
* a gateway restart. **Off by default**: a library must not start writing a
|
|
278
|
+
* session's whole transcript to disk because someone upgraded.
|
|
279
|
+
*
|
|
280
|
+
* This is the restart story for the engine that cannot go dormant. Dormancy
|
|
281
|
+
* works by remembering an *engine* session id to resume from, which the
|
|
282
|
+
* provider engine does not have — there is no store behind it, the history
|
|
283
|
+
* lives in the runner. What it has instead is `snapshot()`, so the record
|
|
284
|
+
* carries the state itself and rehydration is the ordinary `restore` path.
|
|
285
|
+
* Between the two, every engine survives a restart.
|
|
286
|
+
*
|
|
287
|
+
* Written at the end of a turn, never on a shutdown hook — a `kill -9`, an OOM
|
|
288
|
+
* or a pulled power cable run no hook, and that is precisely the case this
|
|
289
|
+
* exists for. Turn-end is also a natural rate limit: one write per turn, not
|
|
290
|
+
* one per token.
|
|
291
|
+
*/
|
|
292
|
+
persistLive?: boolean;
|
|
249
293
|
/** Grace given at {@link SessionParkManager.hydrate} to an execution whose
|
|
250
294
|
* deadline passed while the server was down. Its result could not have been
|
|
251
295
|
* delivered during the outage, so failing it the instant the process is back
|
|
@@ -290,6 +334,18 @@ declare class SessionParkManager {
|
|
|
290
334
|
/** Record the config a session was created with. Only sessions the host
|
|
291
335
|
* remembers can be parked — there is no way to rebuild the others. */
|
|
292
336
|
remember(sessionId: string, config: SessionRunnerConfig): void;
|
|
337
|
+
/**
|
|
338
|
+
* Re-save a live session's dormant record because something outside the event
|
|
339
|
+
* stream changed it.
|
|
340
|
+
*
|
|
341
|
+
* `#rememberDormant` is otherwise driven by `status_changed` and `system_init`
|
|
342
|
+
* alone, and a rename (`PATCH /sessions/:id`) fires neither — so without this
|
|
343
|
+
* a renamed session that is never touched again keeps its old title on disk
|
|
344
|
+
* and comes back under it. Safe to call for anything: every gate in
|
|
345
|
+
* `#rememberDormant` still applies, so a session that cannot be resumed, has
|
|
346
|
+
* no engine session yet, or is no longer the registry's writes nothing.
|
|
347
|
+
*/
|
|
348
|
+
touch(runner: Runner): void;
|
|
293
349
|
/**
|
|
294
350
|
* Adopt the store's contents (a durable store after a restart): re-index the
|
|
295
351
|
* executions and re-arm their watchdogs, no deadline sooner than the grace
|
|
@@ -335,7 +391,7 @@ declare class SessionParkManager {
|
|
|
335
391
|
close(): void;
|
|
336
392
|
}
|
|
337
393
|
//#endregion
|
|
338
|
-
//#region src/profile-store.d.ts
|
|
394
|
+
//#region src/services/profile-store.d.ts
|
|
339
395
|
/**
|
|
340
396
|
* Where dashboard-managed profiles live. The seam exists for the same reason
|
|
341
397
|
* `QueueAdapter` does: a single-host deployment wants the bundled file store and
|
|
@@ -367,7 +423,7 @@ declare function createMemoryProfileStore(seed?: ProfileInfo[]): ProfileStore;
|
|
|
367
423
|
*/
|
|
368
424
|
declare function createFileProfileStore(path?: string): ProfileStore;
|
|
369
425
|
//#endregion
|
|
370
|
-
//#region src/
|
|
426
|
+
//#region src/options.d.ts
|
|
371
427
|
type SdkSessionLister = (options: {
|
|
372
428
|
dir?: string;
|
|
373
429
|
limit?: number;
|
|
@@ -664,6 +720,22 @@ type WorkerServerOptions = {
|
|
|
664
720
|
/** Grace given on boot to an execution whose deadline passed while the server
|
|
665
721
|
* was down (durable stores only — nothing else survives a restart). Default 60000. */
|
|
666
722
|
expiredGraceMs?: number;
|
|
723
|
+
/**
|
|
724
|
+
* Keep live `provider` sessions written through to the store after each
|
|
725
|
+
* turn, so they survive a gateway restart. **Off by default** — this writes
|
|
726
|
+
* a session's whole transcript to `store` and a library must not start doing
|
|
727
|
+
* that because someone upgraded.
|
|
728
|
+
*
|
|
729
|
+
* It is the restart story for the one engine dormancy cannot cover: claude
|
|
730
|
+
* and codex are remembered by *engine session id* and resumed from their own
|
|
731
|
+
* on-disk store, which a provider session does not have. Pair it with a
|
|
732
|
+
* durable `store` — with the default in-memory one it does nothing a park
|
|
733
|
+
* did not already do.
|
|
734
|
+
*
|
|
735
|
+
* The record is rebuilt lazily, on first attach, exactly like a dormant one;
|
|
736
|
+
* a boot with fifty remembered sessions spawns nothing.
|
|
737
|
+
*/
|
|
738
|
+
persistLive?: boolean;
|
|
667
739
|
/** Park/remember/resume failures — storage or engine-assembly problems, not
|
|
668
740
|
* session errors. 'remember' is the write that lets a live session survive a
|
|
669
741
|
* restart; losing one costs that session its way back and nothing else. */
|
|
@@ -753,9 +825,11 @@ type WorkerServer = {
|
|
|
753
825
|
}>;
|
|
754
826
|
close: () => Promise<void>;
|
|
755
827
|
};
|
|
828
|
+
//#endregion
|
|
829
|
+
//#region src/server.d.ts
|
|
756
830
|
declare function createWorkerServer(options?: WorkerServerOptions): WorkerServer;
|
|
757
831
|
//#endregion
|
|
758
|
-
//#region src/sandboxed-profile.d.ts
|
|
832
|
+
//#region src/lib/sandboxed-profile.d.ts
|
|
759
833
|
/**
|
|
760
834
|
* A `provider` profile that grants a session nothing but the sandbox: the
|
|
761
835
|
* QuickJS guest, the in-memory VFS, and the model.
|
|
@@ -812,7 +886,7 @@ declare function sandboxedProviderProfile(name: string, provider: ProviderConfig
|
|
|
812
886
|
mcpServers?: string[];
|
|
813
887
|
}): ProfileInfo;
|
|
814
888
|
//#endregion
|
|
815
|
-
//#region src/provider-runner.d.ts
|
|
889
|
+
//#region src/lib/provider-runner.d.ts
|
|
816
890
|
type ProviderRunnerOptions = {
|
|
817
891
|
/**
|
|
818
892
|
* The model to run. A function is called per turn with the session's
|
|
@@ -882,7 +956,7 @@ type ProviderRunnerOptions = {
|
|
|
882
956
|
*/
|
|
883
957
|
declare function createProviderRunner(ctx: EngineRunnerContext, options: ProviderRunnerOptions): Promise<Runner>;
|
|
884
958
|
//#endregion
|
|
885
|
-
//#region src/attachments.d.ts
|
|
959
|
+
//#region src/services/attachments.d.ts
|
|
886
960
|
type AttachmentStoreOptions = {
|
|
887
961
|
/** Largest single upload. Default 10 MiB. */maxFileBytes?: number; /** Ceiling on everything one session is holding. Default 64 MiB. */
|
|
888
962
|
maxSessionBytes?: number;
|
|
@@ -946,7 +1020,7 @@ declare class AttachmentStore {
|
|
|
946
1020
|
drop(sessionId: string): void;
|
|
947
1021
|
}
|
|
948
1022
|
//#endregion
|
|
949
|
-
//#region src/produced-files.d.ts
|
|
1023
|
+
//#region src/services/produced-files.d.ts
|
|
950
1024
|
/** One host file an engine reported writing, as the store holds it. */
|
|
951
1025
|
type ProducedFile = {
|
|
952
1026
|
fileId: string; /** Absolute host path, exactly as the runner reported it. */
|
|
@@ -996,5 +1070,54 @@ declare class ProducedFileStore {
|
|
|
996
1070
|
drop(sessionId: string): void;
|
|
997
1071
|
}
|
|
998
1072
|
//#endregion
|
|
999
|
-
|
|
1073
|
+
//#region src/services/profile-usage.d.ts
|
|
1074
|
+
/**
|
|
1075
|
+
* The gateway's single plan-usage state per profile, fed from every session's
|
|
1076
|
+
* `rate_limit` events and served on `GET /profiles` (`ProfileInfo.usage`).
|
|
1077
|
+
*
|
|
1078
|
+
* Why this exists at all: usage had only ever lived in session transcripts, so
|
|
1079
|
+
* a client attaching to a session that idled since yesterday replayed
|
|
1080
|
+
* yesterday's reading as if current — and a session opened today knew nothing
|
|
1081
|
+
* of what a sibling session on the same account spent an hour ago. The profile
|
|
1082
|
+
* is the account boundary (one config dir / codex home / provider key = one
|
|
1083
|
+
* plan), so the newest reading across all of a profile's sessions is the one
|
|
1084
|
+
* usage state that is ever worth showing. No history: last-write-wins per
|
|
1085
|
+
* window, exactly the reducer's rule on the client side.
|
|
1086
|
+
*
|
|
1087
|
+
* Last-write-wins goes by the **event's own clock**, not arrival order:
|
|
1088
|
+
* `watch()` subscribes from seq 0 (a replayed log is how a rebuilt session's
|
|
1089
|
+
* readings arrive at all), and a replayed yesterday-reading must not clobber
|
|
1090
|
+
* the fresher one another session on the same profile reported live. All
|
|
1091
|
+
* events are stamped by this gateway's clock at emit time, so the comparison
|
|
1092
|
+
* is sound across sessions.
|
|
1093
|
+
*
|
|
1094
|
+
* In-memory on purpose, like the learned default models and the availability
|
|
1095
|
+
* cache: display-only state may start empty after a restart (absent = unknown,
|
|
1096
|
+
* never 0%), and the first session to report refills it.
|
|
1097
|
+
*/
|
|
1098
|
+
declare class ProfileUsageTracker {
|
|
1099
|
+
#private;
|
|
1100
|
+
/** Follow a runner's `rate_limit` events for its lifetime. Sessions without a
|
|
1101
|
+
* profile have no account to attribute usage to and are skipped. */
|
|
1102
|
+
watch(runner: Runner): void;
|
|
1103
|
+
/**
|
|
1104
|
+
* The profile's windows as they should be served *now*. Undefined until any
|
|
1105
|
+
* session on the profile has reported (unknown, never 0%).
|
|
1106
|
+
*
|
|
1107
|
+
* The 0%-after-reset inference lives here — at serve time — and nowhere
|
|
1108
|
+
* else, because it is a function of the wall clock: a window whose own
|
|
1109
|
+
* `resetsAt` has passed with no newer reading has provably rolled, so the
|
|
1110
|
+
* pre-reset utilization is no longer merely stale but *wrong*. It cannot be
|
|
1111
|
+
* a producer's job (the producers only relay what the engine said, and the
|
|
1112
|
+
* whole problem is the engine's silence; a fabricated 0% event would be
|
|
1113
|
+
* replayed from transcripts forever as if reported) and must not be every
|
|
1114
|
+
* renderer's (N clients would each reimplement the clock math). The held
|
|
1115
|
+
* reading stays untouched, so a late fresh report still lands by ts, and the
|
|
1116
|
+
* served zero is labeled `inferredReset` — it is a floor, not a report: the
|
|
1117
|
+
* account may have been used outside this gateway since the reset.
|
|
1118
|
+
*/
|
|
1119
|
+
usage(profile: string, now?: number): ProfileUsage | undefined;
|
|
1120
|
+
}
|
|
1121
|
+
//#endregion
|
|
1122
|
+
export { AttachmentStore, type AttachmentStoreOptions, type Authenticator, BridgeHub, type BridgeHubOptions, type EngineRunnerContext, type FileSessionStoreOptions, MemorySessionStore, type ParkedSessionRecord, type ProducedFile, ProducedFileStore, type ProfileStore, ProfileUsageTracker, type ProviderRunnerOptions, type QueueServerOptions, type SdkSessionLister, type SessionNotificationOptions, SessionNotifier, SessionParkManager, type SessionParkOptions, SessionRegistry, type SessionRegistryOptions, type SessionStore, type WorkerServer, type WorkerServerOptions, createFileProfileStore, createFileSessionStore, createMemoryProfileStore, createProviderRunner, createWorkerServer, sandboxedProviderProfile, toDurableRecord };
|
|
1000
1123
|
//# sourceMappingURL=index.d.mts.map
|