@theoremjs/web 0.3.4-next.753.g176c472 → 0.3.4-next.757.gde44a4d
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 +1 -1
- package/package.json +2 -2
- package/server/handler.d.ts +2 -2
- package/server/handler.js +12 -5
package/README.md
CHANGED
|
@@ -273,7 +273,7 @@ const transport = withPageToolDispatch(
|
|
|
273
273
|
| `notifier`, `notifyRetryMs` | Tell an open page that a background call ended, and how long the page waits to reopen a cut stream. Unset, the page reads the end on its next turn or reload. See [the background section](#share-session-authority). |
|
|
274
274
|
| `credentialStore` | Where tool credentials are kept, by session. Default: process memory. |
|
|
275
275
|
| `authorizationUrl` | Returns the sign-in URL for an OAuth gate. Without it, an OAuth gate has no URL. |
|
|
276
|
-
| `gateTtlMs` | How long a gate waits for an answer. A later answer fails with `session.gate_expired
|
|
276
|
+
| `gateTtlMs` | How long a gate waits for an answer. A later answer fails with `session.gate_expired`, and the next message cancels the call. Unset, a gate waits until it is answered. |
|
|
277
277
|
| `maxRequestBytes` | The largest browser request body, in bytes. Unset, a body of any size is read. |
|
|
278
278
|
| `pageToolTimeoutMs` | How long the page has to answer a tool call it runs. A call it has not answered by then settles as timed out. Unset, the call waits until the page answers or the turn stops. The browser clients answer every call they get, so only a page function that never returns holds a turn. |
|
|
279
279
|
| `operationRetentionMs` | How long a settled tool result is kept. Default: 24 hours. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theoremjs/web",
|
|
3
|
-
"version": "0.3.4-next.
|
|
3
|
+
"version": "0.3.4-next.757.gde44a4d",
|
|
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.
|
|
28
|
+
"@theoremjs/agents": "^0.3.4-next.757.gde44a4d"
|
|
29
29
|
}
|
|
30
30
|
}
|
package/server/handler.d.ts
CHANGED
|
@@ -107,8 +107,8 @@ export type TheoremHandlerOptions = {
|
|
|
107
107
|
conversationStore?: TheoremConversationStore;
|
|
108
108
|
/**
|
|
109
109
|
* How long a gate (permission, confirmation, sign-in) waits for its answer, in
|
|
110
|
-
* milliseconds. An answer after that is refused with `session.gate_expired
|
|
111
|
-
* Unset, a gate waits until it is answered.
|
|
110
|
+
* milliseconds. An answer after that is refused with `session.gate_expired`,
|
|
111
|
+
* and the next message cancels the call. Unset, a gate waits until it is answered.
|
|
112
112
|
*/
|
|
113
113
|
gateTtlMs?: number;
|
|
114
114
|
/** Retain settled tool results in milliseconds. Default: 24 hours. */
|
package/server/handler.js
CHANGED
|
@@ -331,10 +331,16 @@ function answerPendingGate(state, request, profileId) {
|
|
|
331
331
|
state.permissions = answer.sessionPermissions;
|
|
332
332
|
return { callId: request.callId, pending, answer };
|
|
333
333
|
}
|
|
334
|
-
function walkedCallOf(state, reference, profileId) {
|
|
334
|
+
function walkedCallOf(state, reference, profileId, paused) {
|
|
335
335
|
const settled = Object.hasOwn(state.operations, reference.operationId)
|
|
336
336
|
? state.operations[reference.operationId]
|
|
337
337
|
: undefined;
|
|
338
|
+
// why: A gate that lapsed is gone from the session while the reply still waits on its call. The call is only ever cancelled here, so the next message is never refused for it.
|
|
339
|
+
if (!settled && !Object.hasOwn(state.gates, reference.operationId)) {
|
|
340
|
+
const lapsed = pendingGatesFrom(paused, { profileId, turnInput: {} }).find(({ callId }) => callId === reference.callId);
|
|
341
|
+
if (lapsed)
|
|
342
|
+
state.gates[reference.operationId] = lapsed.gate;
|
|
343
|
+
}
|
|
338
344
|
return settled?.status === 'settled' &&
|
|
339
345
|
settled.callId === reference.callId &&
|
|
340
346
|
settled.profileId === profileId
|
|
@@ -346,11 +352,12 @@ function walkedCallOf(state, reference, profileId) {
|
|
|
346
352
|
* answered `abandon`: every one of them, or none when one is neither waiting
|
|
347
353
|
* nor settled. Each comes back with the run that settles it.
|
|
348
354
|
*/
|
|
349
|
-
async function takeWalkedAway(ctx, request, session, abandon) {
|
|
355
|
+
async function takeWalkedAway(ctx, request, session, abandon, conversation) {
|
|
356
|
+
const paused = conversation.paused?.events ?? [];
|
|
350
357
|
// why: A throw leaves the session unsaved, so no call is taken unless all are.
|
|
351
358
|
const calls = await ctx.sessions.mutate(session.id, (state) => abandon.map((reference) => ({
|
|
352
359
|
reference,
|
|
353
|
-
call: walkedCallOf(state, reference, ctx.profile.id),
|
|
360
|
+
call: walkedCallOf(state, reference, ctx.profile.id, paused),
|
|
354
361
|
})));
|
|
355
362
|
return calls.map(({ reference, call }) => ({
|
|
356
363
|
...reference,
|
|
@@ -530,7 +537,7 @@ async function turn(ctx, chat, request, session) {
|
|
|
530
537
|
});
|
|
531
538
|
// why: Take the walked-away calls before streaming, so a stale one is a reply status, not a stream error.
|
|
532
539
|
const walkAway = body.abandon
|
|
533
|
-
? await takeWalkedAway(ctx, request, session, body.abandon)
|
|
540
|
+
? await takeWalkedAway(ctx, request, session, body.abandon, opened.conversation)
|
|
534
541
|
: undefined;
|
|
535
542
|
return eventStream(ctx, request, () => messageReply({ host, opened, message, ...(walkAway ? { walkAway } : {}), runner }));
|
|
536
543
|
}
|
|
@@ -664,7 +671,7 @@ async function rewind(ctx, request, session) {
|
|
|
664
671
|
const opened = await openConversation(host, body.conversation, { kind: 'rewind', at: body.at });
|
|
665
672
|
const waiting = waitingCalls(opened.conversation);
|
|
666
673
|
const walkAway = waiting.length
|
|
667
|
-
? await takeWalkedAway(ctx, request, session, waiting)
|
|
674
|
+
? await takeWalkedAway(ctx, request, session, waiting, opened.conversation)
|
|
668
675
|
: undefined;
|
|
669
676
|
const next = await rewindConversation({
|
|
670
677
|
host,
|