@haikit/server 0.3.1 → 0.5.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 +33 -1
- package/dist/routes.d.ts +4 -2
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +17 -4
- package/dist/routes.js.map +1 -1
- package/dist/runtime.d.ts +51 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +249 -4
- package/dist/runtime.js.map +1 -1
- package/dist/store.js +1 -1
- package/dist/store.js.map +1 -1
- package/package.json +2 -2
- package/src/routes.ts +17 -4
- package/src/runtime.ts +278 -3
- package/src/store.ts +1 -1
package/README.md
CHANGED
|
@@ -17,5 +17,37 @@ action *means* is resolved server-side from the surface's declared contract. If
|
|
|
17
17
|
the client could name a tool, a prompt injection inside any tool result would
|
|
18
18
|
become a button wired to it.
|
|
19
19
|
|
|
20
|
+
**`init` runs a tool at the start of every conversation**, before the user
|
|
21
|
+
types anything. The runtime makes the call, not the model, so it can't be
|
|
22
|
+
skipped: the call and its result go into the history as if the model had made
|
|
23
|
+
them.
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
const hai = createHai({ model, store, tools, surfaces, system, init: loadProfile });
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
A third route, `POST /hai/start`, opens the conversation and runs `init`
|
|
30
|
+
without calling the model. The client's `start()` calls it, and `mountChat`
|
|
31
|
+
does so when it opens and after *Start a new conversation*. The Messages API
|
|
32
|
+
requires the history to begin with a user message, so it opens with
|
|
33
|
+
`[conversation started]`, followed by init's call and result. Without an
|
|
34
|
+
`init`, `/start` returns an empty stream and creates no conversation. A client
|
|
35
|
+
that never calls `start()` still gets `init`, run with the first message.
|
|
36
|
+
|
|
37
|
+
It gets `{}` as input and can render surfaces. An elicit surface ("which
|
|
38
|
+
account?") parks the conversation before anyone has typed; the answer becomes
|
|
39
|
+
init's result, and the model replies. If it throws, the request is refused and
|
|
40
|
+
nothing is recorded, so the next start or message tries again. It stays in the model's tool list, because changing that list
|
|
41
|
+
mid-conversation invalidates newer models' earlier reasoning. But a later call
|
|
42
|
+
from the model gets "already ran" instead of running it twice. Its result stays
|
|
43
|
+
in context for every turn, so keep it digest-sized.
|
|
44
|
+
|
|
45
|
+
**A conversation closes once any of its surfaces passes its `staleAfterMs`.**
|
|
46
|
+
From then on both routes answer with an `expired` event and the model is not
|
|
47
|
+
called, so a picker left open over a weekend cannot resolve against last week's
|
|
48
|
+
data. The user starts a new conversation. A surface that declares no window
|
|
49
|
+
never goes stale, so set one wherever the data can change.
|
|
50
|
+
|
|
20
51
|
`memoryStore()` is for development. A parked elicit turn is durable state —
|
|
21
|
-
lose `pending` and that conversation can never be sent again.
|
|
52
|
+
lose `pending` and that conversation can never be sent again. Ship with
|
|
53
|
+
[`@haikit/postgres`](https://www.npmjs.com/package/@haikit/postgres).
|
package/dist/routes.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
2
|
import type { Hai } from "./runtime.js";
|
|
3
3
|
/**
|
|
4
|
-
* Node http handler for the
|
|
4
|
+
* Node http handler for the three routes. Returns true if it handled the
|
|
5
|
+
* request.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
+
* All three stream SSE: chat and interact because both can resume the agent
|
|
8
|
+
* loop, start because the init tool it runs can render surfaces. Note what the
|
|
7
9
|
* interact route accepts: {handle, action, value} and nothing else. The client
|
|
8
10
|
* cannot name a tool, a handler, or an action target.
|
|
9
11
|
*/
|
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAExC
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAExC;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,SAAS,IACxB,KAAK,eAAe,EAAE,KAAK,cAAc,KAAG,OAAO,CAAC,OAAO,CAAC,CA4E1F"}
|
package/dist/routes.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { isConversationBusy, isStaleLease } from "@haikit/core";
|
|
2
2
|
/**
|
|
3
|
-
* Node http handler for the
|
|
3
|
+
* Node http handler for the three routes. Returns true if it handled the
|
|
4
|
+
* request.
|
|
4
5
|
*
|
|
5
|
-
*
|
|
6
|
+
* All three stream SSE: chat and interact because both can resume the agent
|
|
7
|
+
* loop, start because the init tool it runs can render surfaces. Note what the
|
|
6
8
|
* interact route accepts: {handle, action, value} and nothing else. The client
|
|
7
9
|
* cannot name a tool, a handler, or an action target.
|
|
8
10
|
*/
|
|
@@ -12,9 +14,17 @@ export function nodeHandler(hai, basePath = "/hai") {
|
|
|
12
14
|
if (req.method !== "POST" || !url.pathname.startsWith(basePath))
|
|
13
15
|
return false;
|
|
14
16
|
const route = url.pathname.slice(basePath.length);
|
|
15
|
-
if (route !== "/chat" && route !== "/interact")
|
|
17
|
+
if (route !== "/chat" && route !== "/interact" && route !== "/start")
|
|
16
18
|
return false;
|
|
17
19
|
const body = await readJson(req);
|
|
20
|
+
// Nothing to run before the first message: answer with an empty stream and
|
|
21
|
+
// create no conversation, so an app without init doesn't get one for every
|
|
22
|
+
// page view. Its first message starts the conversation, as it always has.
|
|
23
|
+
if (route === "/start" && !hai.config.init) {
|
|
24
|
+
openSSE(res);
|
|
25
|
+
res.end();
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
18
28
|
// Before the SSE stream opens, because a rejected load has no stream to
|
|
19
29
|
// report into — and an uncaught throw here would take down the request.
|
|
20
30
|
let conversation;
|
|
@@ -29,7 +39,7 @@ export function nodeHandler(hai, basePath = "/hai") {
|
|
|
29
39
|
return true;
|
|
30
40
|
}
|
|
31
41
|
const emit = openSSE(res);
|
|
32
|
-
if (route === "/chat") {
|
|
42
|
+
if (route === "/chat" || route === "/start") {
|
|
33
43
|
emit({ type: "hello", conversationId: conversation.id, model: hai.config.model.id });
|
|
34
44
|
}
|
|
35
45
|
let superseded = false;
|
|
@@ -37,6 +47,9 @@ export function nodeHandler(hai, basePath = "/hai") {
|
|
|
37
47
|
if (route === "/chat") {
|
|
38
48
|
await hai.send(conversation, String(body.message ?? ""), emit);
|
|
39
49
|
}
|
|
50
|
+
else if (route === "/start") {
|
|
51
|
+
await hai.start(conversation, emit);
|
|
52
|
+
}
|
|
40
53
|
else {
|
|
41
54
|
await hai.interact(conversation, { handle: body.handle, action: body.action, value: body.value }, emit);
|
|
42
55
|
}
|
package/dist/routes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIhE
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime.d.ts
CHANGED
|
@@ -7,6 +7,22 @@ export interface HaiConfig {
|
|
|
7
7
|
surfaces: AnySurfaceImpl[];
|
|
8
8
|
/** Guard against runaway tool loops. */
|
|
9
9
|
maxHops?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Runs at the start of every conversation, before the user's first message
|
|
12
|
+
* when the client calls `start()` (the default UI does, on open), otherwise
|
|
13
|
+
* with that first message. Either way it runs before the model's first turn.
|
|
14
|
+
* The runtime makes the call, not the model, so it cannot be skipped: the
|
|
15
|
+
* call and its result are recorded as if the model had made them. It
|
|
16
|
+
* receives `{}` as input and may render surfaces — an elicit surface parks
|
|
17
|
+
* the conversation before the model runs at all.
|
|
18
|
+
*
|
|
19
|
+
* If it throws, the request is refused and nothing is recorded, so the next
|
|
20
|
+
* message tries again. It stays in the model's tool list for the whole
|
|
21
|
+
* conversation — changing that list mid-conversation invalidates the
|
|
22
|
+
* model's earlier reasoning on newer models — but a later call from the
|
|
23
|
+
* model gets "already ran" back instead of running it again.
|
|
24
|
+
*/
|
|
25
|
+
init?: Tool;
|
|
10
26
|
}
|
|
11
27
|
export declare class Hai {
|
|
12
28
|
readonly config: HaiConfig;
|
|
@@ -17,11 +33,46 @@ export declare class Hai {
|
|
|
17
33
|
private nid;
|
|
18
34
|
private buildQueryUiTool;
|
|
19
35
|
send(conversation: Conversation, text: string, emit: Emit): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Start a conversation before the user has typed anything, so init's result
|
|
38
|
+
* — and any surface it shows — is already there when the first message
|
|
39
|
+
* arrives. The model does not run. Does nothing without an init tool, or
|
|
40
|
+
* once the conversation has begun.
|
|
41
|
+
*/
|
|
42
|
+
start(conversation: Conversation, emit: Emit): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Run the init tool as the conversation's first tool call, after `text` —
|
|
45
|
+
* the user's first message, or STARTED when it runs before one. Returns
|
|
46
|
+
* true when it parked the conversation on an elicit surface.
|
|
47
|
+
*
|
|
48
|
+
* Nothing reaches the history until the tool has succeeded — not even the
|
|
49
|
+
* user's message — so a refused start leaves the conversation exactly as
|
|
50
|
+
* the route found it, and the next message starts it again.
|
|
51
|
+
*/
|
|
52
|
+
private runInit;
|
|
20
53
|
interact(conversation: Conversation, input: {
|
|
21
54
|
handle: string;
|
|
22
55
|
action: string;
|
|
23
56
|
value: unknown;
|
|
24
57
|
}, emit: Emit): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Refuse any request on a conversation that has outlived one of its surfaces.
|
|
60
|
+
*
|
|
61
|
+
* Runs first, before anything is changed, so a refused request records
|
|
62
|
+
* nothing and costs no model call — the save that follows only releases the
|
|
63
|
+
* lease. Every handle in the surviving history counts, answered ones
|
|
64
|
+
* included: what the user picked from a surface is still in the model's
|
|
65
|
+
* context at the price it was shown at.
|
|
66
|
+
*
|
|
67
|
+
* A payload held to a window whose age cannot be computed counts as expired.
|
|
68
|
+
* A store returning a bad `createdAt` has to fail closed, not quietly make
|
|
69
|
+
* every surface fresh forever. A `"never"` window needs no age, so its
|
|
70
|
+
* timestamp is not consulted — the conformance suite is what holds a store
|
|
71
|
+
* to returning good ones. A payload whose row is gone counts as expired too:
|
|
72
|
+
* nothing deletes a payload the history still references, so a missing one
|
|
73
|
+
* is lost data, and lost data proves nothing is fresh.
|
|
74
|
+
*/
|
|
75
|
+
private refuseIfExpired;
|
|
25
76
|
private runTurn;
|
|
26
77
|
private invokeTool;
|
|
27
78
|
private emitContext;
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,IAAI,EAIV,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAcD,qBAAa,GAAG;IACd,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,GAAG,CAAK;gBAEJ,MAAM,EAAE,SAAS;IAoB7B,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,gBAAgB;IAkFlB,IAAI,CAAC,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAqC/E;;;;;OAKG;IACG,KAAK,CAAC,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlE;;;;;;;;OAQG;YACW,OAAO;IA+Df,QAAQ,CACZ,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EACzD,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,IAAI,CAAC;IA8DhB;;;;;;;;;;;;;;;;OAgBG;YACW,eAAe;YA4Cf,OAAO;YAuEP,UAAU;YA0FV,WAAW;CAa1B"}
|
package/dist/runtime.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { estTokens, isStaleLease, makeCap, } from "@haikit/core";
|
|
2
|
+
/**
|
|
3
|
+
* Opens the history when init runs before the user has said anything: the
|
|
4
|
+
* Messages API requires the first message to be the user's. Bracketed like
|
|
5
|
+
* `[UI interaction]` — framework text, not something the user typed.
|
|
6
|
+
*/
|
|
7
|
+
const STARTED = "[conversation started]";
|
|
8
|
+
/** Appended to the init tool's description in what the model sees. */
|
|
9
|
+
const INIT_NOTE = "This ran automatically at the start of the conversation, and its result is already above. " +
|
|
10
|
+
"Calling it again does not run it.";
|
|
2
11
|
export class Hai {
|
|
3
12
|
config;
|
|
4
13
|
surfaces = new Map();
|
|
@@ -6,14 +15,22 @@ export class Hai {
|
|
|
6
15
|
seq = 0;
|
|
7
16
|
constructor(config) {
|
|
8
17
|
this.config = config;
|
|
9
|
-
for (const s of config.surfaces)
|
|
18
|
+
for (const s of config.surfaces) {
|
|
19
|
+
checkWindow(s);
|
|
10
20
|
this.surfaces.set(s.surface.name, s);
|
|
21
|
+
}
|
|
11
22
|
for (const t of config.tools)
|
|
12
23
|
this.tools.set(t.name, t);
|
|
13
24
|
// query_ui is DERIVED, never authored. It cannot drift from the surfaces
|
|
14
25
|
// that actually exist, and it always exists.
|
|
15
26
|
const queryUi = this.buildQueryUiTool();
|
|
16
27
|
this.tools.set(queryUi.name, queryUi);
|
|
28
|
+
if (config.init) {
|
|
29
|
+
if (this.tools.has(config.init.name)) {
|
|
30
|
+
throw new Error(`init tool "${config.init.name}" has the same name as another tool`);
|
|
31
|
+
}
|
|
32
|
+
this.tools.set(config.init.name, config.init);
|
|
33
|
+
}
|
|
17
34
|
}
|
|
18
35
|
nid(prefix) {
|
|
19
36
|
return `${prefix}_${++this.seq}`;
|
|
@@ -89,6 +106,10 @@ export class Hai {
|
|
|
89
106
|
}
|
|
90
107
|
// ─────────────────────────────────────────────────── public API
|
|
91
108
|
async send(conversation, text, emit) {
|
|
109
|
+
if (await this.refuseIfExpired(conversation, emit))
|
|
110
|
+
return;
|
|
111
|
+
// The first message is the one that starts the conversation.
|
|
112
|
+
const starting = conversation.messages.length === 0;
|
|
92
113
|
// The user typed while a tool was parked. Every tool_use in a turn must
|
|
93
114
|
// receive a tool_result, so close the pending one out honestly first.
|
|
94
115
|
if (conversation.status === "awaiting" && conversation.pending) {
|
|
@@ -111,10 +132,102 @@ export class Hai {
|
|
|
111
132
|
conversation.pending = null;
|
|
112
133
|
}
|
|
113
134
|
emit({ type: "block_start", block: { kind: "user", id: this.nid("b"), text } });
|
|
114
|
-
|
|
135
|
+
if (starting && this.config.init) {
|
|
136
|
+
if (await this.runInit(conversation, text, emit))
|
|
137
|
+
return; // parked on its surface
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
conversation.messages.push({ role: "user", content: text });
|
|
141
|
+
}
|
|
115
142
|
await this.runTurn(conversation, emit);
|
|
116
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Start a conversation before the user has typed anything, so init's result
|
|
146
|
+
* — and any surface it shows — is already there when the first message
|
|
147
|
+
* arrives. The model does not run. Does nothing without an init tool, or
|
|
148
|
+
* once the conversation has begun.
|
|
149
|
+
*/
|
|
150
|
+
async start(conversation, emit) {
|
|
151
|
+
if (!this.config.init || conversation.messages.length > 0)
|
|
152
|
+
return;
|
|
153
|
+
if (await this.runInit(conversation, STARTED, emit))
|
|
154
|
+
return; // parked on its surface
|
|
155
|
+
conversation.status = "idle";
|
|
156
|
+
emit({ type: "status", status: "idle" });
|
|
157
|
+
await this.emitContext(conversation, emit);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Run the init tool as the conversation's first tool call, after `text` —
|
|
161
|
+
* the user's first message, or STARTED when it runs before one. Returns
|
|
162
|
+
* true when it parked the conversation on an elicit surface.
|
|
163
|
+
*
|
|
164
|
+
* Nothing reaches the history until the tool has succeeded — not even the
|
|
165
|
+
* user's message — so a refused start leaves the conversation exactly as
|
|
166
|
+
* the route found it, and the next message starts it again.
|
|
167
|
+
*/
|
|
168
|
+
async runInit(conversation, text, emit) {
|
|
169
|
+
const init = this.config.init;
|
|
170
|
+
const call = { type: "tool_use", id: `toolu_init_${newId()}`, name: init.name, input: {} };
|
|
171
|
+
const toolBlockId = this.nid("b");
|
|
172
|
+
const before = { handles: conversation.handles.length, status: conversation.status };
|
|
173
|
+
conversation.status = "streaming";
|
|
174
|
+
emit({ type: "status", status: "streaming" });
|
|
175
|
+
emit({ type: "block_start", block: { kind: "tool", id: toolBlockId, name: init.name, input: {}, status: "running" } });
|
|
176
|
+
// Surfaces are held until init succeeds. One shown by a start that is then
|
|
177
|
+
// refused would look live in the browser, and every click on it would be
|
|
178
|
+
// rejected: its handle never reaches the history.
|
|
179
|
+
const held = [];
|
|
180
|
+
const hold = (e) => {
|
|
181
|
+
if (e.type === "ui_open" || e.type === "ui_props")
|
|
182
|
+
held.push(e);
|
|
183
|
+
else
|
|
184
|
+
emit(e);
|
|
185
|
+
};
|
|
186
|
+
const started = Date.now();
|
|
187
|
+
let outcome;
|
|
188
|
+
try {
|
|
189
|
+
outcome = await this.invokeTool(conversation, call, hold, toolBlockId, { init: true });
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
// undo what the tool's renders recorded; their payload rows are orphans
|
|
193
|
+
conversation.handles.length = before.handles;
|
|
194
|
+
conversation.status = before.status;
|
|
195
|
+
if (isStaleLease(err))
|
|
196
|
+
throw err;
|
|
197
|
+
const message = `initialisation failed: ${err.message}`;
|
|
198
|
+
emit({ type: "block_update", id: toolBlockId, status: "error", ms: Date.now() - started, result: message });
|
|
199
|
+
throw new Error(message);
|
|
200
|
+
}
|
|
201
|
+
const { ret, mode } = outcome;
|
|
202
|
+
const ms = Date.now() - started;
|
|
203
|
+
for (const e of held)
|
|
204
|
+
emit(e);
|
|
205
|
+
conversation.messages.push({ role: "user", content: text });
|
|
206
|
+
conversation.messages.push({ role: "assistant", content: [call] });
|
|
207
|
+
if (mode === "elicit" && ret.handle) {
|
|
208
|
+
emit({ type: "block_update", id: toolBlockId, status: "awaiting", ms, result: ret.model });
|
|
209
|
+
conversation.status = "awaiting";
|
|
210
|
+
conversation.pending = { toolUseId: call.id, handle: ret.handle, digest: ret.model, results: [] };
|
|
211
|
+
emit({ type: "status", status: "awaiting" });
|
|
212
|
+
await this.emitContext(conversation, emit);
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
emit({ type: "block_update", id: toolBlockId, status: "ok", ms, result: ret.model });
|
|
216
|
+
conversation.messages.push({
|
|
217
|
+
role: "user",
|
|
218
|
+
content: [{ type: "tool_result", tool_use_id: call.id, content: ret.model }],
|
|
219
|
+
});
|
|
220
|
+
// Commit before the model runs. An init that only returns text makes no
|
|
221
|
+
// fenced write of its own, so a request that outlived its lease while init
|
|
222
|
+
// ran would otherwise go on to call the model for a history its final save
|
|
223
|
+
// will lose. This save is fenced: it throws StaleLease if another request
|
|
224
|
+
// has taken the conversation over, and the model never runs here.
|
|
225
|
+
await this.config.store.saveConversation(conversation);
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
117
228
|
async interact(conversation, input, emit) {
|
|
229
|
+
if (await this.refuseIfExpired(conversation, emit))
|
|
230
|
+
return;
|
|
118
231
|
// The payload row carries a conversation id, but that alone is not enough.
|
|
119
232
|
// A turn that rendered a surface and was then overtaken leaves a row behind:
|
|
120
233
|
// its conversation save is rejected, so the winning history never records
|
|
@@ -171,13 +284,71 @@ export class Hai {
|
|
|
171
284
|
conversation.messages.push({ role: "user", content: `[UI interaction] ${label}` });
|
|
172
285
|
return this.runTurn(conversation, emit);
|
|
173
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Refuse any request on a conversation that has outlived one of its surfaces.
|
|
289
|
+
*
|
|
290
|
+
* Runs first, before anything is changed, so a refused request records
|
|
291
|
+
* nothing and costs no model call — the save that follows only releases the
|
|
292
|
+
* lease. Every handle in the surviving history counts, answered ones
|
|
293
|
+
* included: what the user picked from a surface is still in the model's
|
|
294
|
+
* context at the price it was shown at.
|
|
295
|
+
*
|
|
296
|
+
* A payload held to a window whose age cannot be computed counts as expired.
|
|
297
|
+
* A store returning a bad `createdAt` has to fail closed, not quietly make
|
|
298
|
+
* every surface fresh forever. A `"never"` window needs no age, so its
|
|
299
|
+
* timestamp is not consulted — the conformance suite is what holds a store
|
|
300
|
+
* to returning good ones. A payload whose row is gone counts as expired too:
|
|
301
|
+
* nothing deletes a payload the history still references, so a missing one
|
|
302
|
+
* is lost data, and lost data proves nothing is fresh.
|
|
303
|
+
*/
|
|
304
|
+
async refuseIfExpired(conversation, emit) {
|
|
305
|
+
if (!conversation.handles.length)
|
|
306
|
+
return false;
|
|
307
|
+
const now = Date.now();
|
|
308
|
+
const records = await this.config.store.getPayloads(conversation.handles, conversation.id);
|
|
309
|
+
// the surface that went out of date first is the one that closed it
|
|
310
|
+
let first = null;
|
|
311
|
+
// getPayloads omits handles it cannot find, and the loop below only sees
|
|
312
|
+
// what came back — so a missing row has to be caught here
|
|
313
|
+
const found = new Set(records.map((r) => r.handle));
|
|
314
|
+
if (conversation.handles.some((h) => !found.has(h))) {
|
|
315
|
+
first = { expiredAt: Number.NaN, age: Number.NaN, window: undefined };
|
|
316
|
+
}
|
|
317
|
+
for (const record of records) {
|
|
318
|
+
// a surface the code no longer registers has no current window at all,
|
|
319
|
+
// which is not the same as one registered without a window ("never")
|
|
320
|
+
const impl = this.surfaces.get(record.component);
|
|
321
|
+
const window = strictest(record.staleAfterMs, impl ? windowOf(impl) : undefined);
|
|
322
|
+
if (window === "never")
|
|
323
|
+
continue;
|
|
324
|
+
// A timestamp that is not a finite number cannot prove anything is fresh:
|
|
325
|
+
// Infinity would compare fresh forever, and a bigint would throw on the
|
|
326
|
+
// arithmetic. Replace it before doing any, so each counts as expired —
|
|
327
|
+
// and so does a payload whose window is known nowhere.
|
|
328
|
+
const createdAt = Number.isFinite(record.createdAt) ? record.createdAt : Number.NaN;
|
|
329
|
+
const expiredAt = createdAt + (window ?? Number.NaN);
|
|
330
|
+
if (expiredAt > now)
|
|
331
|
+
continue;
|
|
332
|
+
if (!first || expiredAt < first.expiredAt)
|
|
333
|
+
first = { expiredAt, age: now - createdAt, window };
|
|
334
|
+
}
|
|
335
|
+
if (!first)
|
|
336
|
+
return false;
|
|
337
|
+
const shown = Number.isFinite(first.age) ? `results shown ${duration(first.age)} ago` : "results shown here";
|
|
338
|
+
const verdict = first.window === undefined ? "can no longer be checked" : `were only valid for ${duration(first.window)}`;
|
|
339
|
+
emit({
|
|
340
|
+
type: "expired",
|
|
341
|
+
message: `This conversation is out of date — ${shown} ${verdict}. Start a new conversation for current results.`,
|
|
342
|
+
});
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
174
345
|
// ──────────────────────────────────────────────── the agent loop
|
|
175
346
|
async runTurn(conversation, emit) {
|
|
176
347
|
conversation.status = "streaming";
|
|
177
348
|
emit({ type: "status", status: "streaming" });
|
|
178
349
|
const toolDefs = [...this.tools.values()].map((t) => ({
|
|
179
350
|
name: t.name,
|
|
180
|
-
description: t.description,
|
|
351
|
+
description: t === this.config.init ? `${t.description}\n\n${INIT_NOTE}` : t.description,
|
|
181
352
|
input_schema: t.inputJsonSchema,
|
|
182
353
|
strict: t.strict,
|
|
183
354
|
}));
|
|
@@ -233,10 +404,20 @@ export class Hai {
|
|
|
233
404
|
emit({ type: "status", status: "idle" });
|
|
234
405
|
await this.emitContext(conversation, emit);
|
|
235
406
|
}
|
|
236
|
-
async invokeTool(conversation, call, emit, toolBlockId
|
|
407
|
+
async invokeTool(conversation, call, emit, toolBlockId,
|
|
408
|
+
// the runtime's own start-of-conversation call: failures throw instead of
|
|
409
|
+
// becoming a result for the model, because there is no model turn yet
|
|
410
|
+
options = {}) {
|
|
237
411
|
const tool = this.tools.get(call.name);
|
|
238
412
|
if (!tool)
|
|
239
413
|
return { ret: { model: `Unknown tool: ${call.name}` }, mode: null };
|
|
414
|
+
// the model calling init again: it ran at the start, and does not run twice
|
|
415
|
+
if (tool === this.config.init && !options.init) {
|
|
416
|
+
return {
|
|
417
|
+
ret: { model: `${tool.name} already ran at the start of this conversation; its result is above.` },
|
|
418
|
+
mode: null,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
240
421
|
let mode = null;
|
|
241
422
|
const ctx = {
|
|
242
423
|
conversationId: conversation.id,
|
|
@@ -246,12 +427,16 @@ export class Hai {
|
|
|
246
427
|
mode = surfaceMode;
|
|
247
428
|
// Validate before storing: props may originate outside this process.
|
|
248
429
|
const parsed = impl.surface.props.parse(props);
|
|
430
|
+
const window = windowOf(impl);
|
|
249
431
|
const handle = await this.config.store.putPayload({
|
|
250
432
|
conversationId: conversation.id,
|
|
251
433
|
component: impl.surface.name,
|
|
252
434
|
version: impl.surface.version,
|
|
253
435
|
props: parsed,
|
|
254
436
|
mode: surfaceMode,
|
|
437
|
+
// recorded now, so no later deploy can relax the window this data
|
|
438
|
+
// was shown under — see the stricter-of in refuseIfExpired
|
|
439
|
+
staleAfterMs: window,
|
|
255
440
|
}, conversation.leaseToken);
|
|
256
441
|
conversation.handles.push(handle);
|
|
257
442
|
// The split, in two lines. Digest -> model. Payload -> browser.
|
|
@@ -263,6 +448,9 @@ export class Hai {
|
|
|
263
448
|
component: impl.surface.name,
|
|
264
449
|
version: impl.surface.version,
|
|
265
450
|
mode: surfaceMode,
|
|
451
|
+
// so a browser left open can close the conversation on time, rather
|
|
452
|
+
// than only finding out when its next request is refused
|
|
453
|
+
...(window === "never" ? {} : { staleAfterMs: window }),
|
|
266
454
|
});
|
|
267
455
|
emit({ type: "ui_props", handle, props: parsed });
|
|
268
456
|
return { model: digest, handle };
|
|
@@ -273,6 +461,8 @@ export class Hai {
|
|
|
273
461
|
input = tool.input.parse(call.input);
|
|
274
462
|
}
|
|
275
463
|
catch (err) {
|
|
464
|
+
if (options.init)
|
|
465
|
+
throw err;
|
|
276
466
|
return { ret: { model: `Invalid input for ${call.name}: ${err.message}` }, mode: null };
|
|
277
467
|
}
|
|
278
468
|
try {
|
|
@@ -280,6 +470,8 @@ export class Hai {
|
|
|
280
470
|
return { ret, mode };
|
|
281
471
|
}
|
|
282
472
|
catch (err) {
|
|
473
|
+
if (options.init)
|
|
474
|
+
throw err;
|
|
283
475
|
// A tool error is information for the model; a lost lease is not. Fencing
|
|
284
476
|
// exists so a superseded turn stops — converting StaleLease into "tool
|
|
285
477
|
// failed" would hand it back to the model and keep paying for hops whose
|
|
@@ -304,6 +496,59 @@ export class Hai {
|
|
|
304
496
|
});
|
|
305
497
|
}
|
|
306
498
|
}
|
|
499
|
+
/**
|
|
500
|
+
* A surface's declared window; one that declares none never goes stale. Only a
|
|
501
|
+
* missing field defaults — `null` is not "no window" but an invalid one, and
|
|
502
|
+
* has to reach checkWindow to be refused like any other.
|
|
503
|
+
*/
|
|
504
|
+
const windowOf = (s) => s.impl.staleAfterMs === undefined ? "never" : s.impl.staleAfterMs;
|
|
505
|
+
/**
|
|
506
|
+
* The type checked again at runtime, because JavaScript callers never see it.
|
|
507
|
+
* Zero or less would expire every surface the moment it rendered; NaN never
|
|
508
|
+
* compares as expired, and Infinity means "never" without saying so. Leaving
|
|
509
|
+
* the window out is fine: that is "never".
|
|
510
|
+
*/
|
|
511
|
+
function checkWindow(s) {
|
|
512
|
+
const window = windowOf(s);
|
|
513
|
+
if (window === "never" || (typeof window === "number" && Number.isFinite(window) && window > 0))
|
|
514
|
+
return;
|
|
515
|
+
const got = typeof window === "string" ? JSON.stringify(window) : String(window);
|
|
516
|
+
throw new RangeError(`surface ${s.surface.name}: staleAfterMs must be a positive, finite number of milliseconds, ` +
|
|
517
|
+
`or "never" (got ${got})`);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* The window a payload is held to: the stricter of the one recorded when it
|
|
521
|
+
* rendered and the one the code declares now. Recorded is what the data was
|
|
522
|
+
* shown under, and survives the surface being renamed or removed; current
|
|
523
|
+
* catches a window tightened since. Neither may relax the other. Undefined
|
|
524
|
+
* when neither is known — an old payload whose surface is gone — which the
|
|
525
|
+
* caller counts as expired.
|
|
526
|
+
*/
|
|
527
|
+
function strictest(recorded, current) {
|
|
528
|
+
const valid = (w) => w === "never" || (typeof w === "number" && Number.isFinite(w) && w > 0);
|
|
529
|
+
const known = [recorded, current].filter(valid);
|
|
530
|
+
if (!known.length)
|
|
531
|
+
return undefined;
|
|
532
|
+
const finite = known.filter((w) => w !== "never");
|
|
533
|
+
return finite.length ? Math.min(...finite) : "never";
|
|
534
|
+
}
|
|
535
|
+
const newId = () => globalThis.crypto.randomUUID().replaceAll("-", "").slice(0, 16);
|
|
536
|
+
/** "2 hours", "15 minutes" — for a sentence a person reads. */
|
|
537
|
+
function duration(ms) {
|
|
538
|
+
const units = [
|
|
539
|
+
[86_400_000, "day"],
|
|
540
|
+
[3_600_000, "hour"],
|
|
541
|
+
[60_000, "minute"],
|
|
542
|
+
[1_000, "second"],
|
|
543
|
+
];
|
|
544
|
+
for (const [size, name] of units) {
|
|
545
|
+
if (ms >= size) {
|
|
546
|
+
const n = Math.floor(ms / size);
|
|
547
|
+
return `${n} ${name}${n === 1 ? "" : "s"}`;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return "under a second";
|
|
551
|
+
}
|
|
307
552
|
/** Find the array prop a surface's queries operate over (for cap totals). */
|
|
308
553
|
function primaryCollection(props) {
|
|
309
554
|
if (props && typeof props === "object") {
|
package/dist/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,OAAO,GASR,MAAM,cAAc,CAAC;AAYtB,MAAM,OAAO,GAAG;IACL,MAAM,CAAY;IACV,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC7C,KAAK,GAAG,IAAI,GAAG,EAAgB,CAAC;IACzC,GAAG,GAAG,CAAC,CAAC;IAEhB,YAAY,MAAiB;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ;YAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACtE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACxD,yEAAyE;QACzE,6CAA6C;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAEO,GAAG,CAAC,MAAc;QACxB,OAAO,GAAG,MAAM,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;IACnC,CAAC;IAED,iEAAiE;IAEzD,gBAAgB;QACtB,2EAA2E;QAC3E,wEAAwE;QACxE,uEAAuE;QACvE,mBAAmB;QACnB,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CACxD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;YACrD,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;YAC5C,IAAI,IAAI,CAAC,WAAW;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YAC1D,KAAK,CAAC,IAAI,CACR,IAAI,CAAC,cAAc;gBACjB,CAAC,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE;gBAChD,CAAC,CAAC,gCAAgC,CACrC,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACxE,CAAC,CAAC,CACH,CAAC;QAEF,uEAAuE;QACvE,oEAAoE;QACpE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACjE,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CACV,4CAA4C,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBACxG,mFAAmF;gBACnF,sFAAsF,CACzF,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/D,MAAM,IAAI,GAAG,IAAI,CAAC;QAClB,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,WAAW,EACT,yFAAyF;gBACzF,yFAAyF;gBACzF,CAAC,SAAS,CAAC,CAAC,CAAC,2BAA2B,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAQ,EAAE;YACjC,eAAe,EAAE;gBACf,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE;oBACrD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mDAAmD,EAAE;oBAC3F,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAQ;wBACd,WAAW,EACT,mFAAmF;4BACnF,sFAAsF;qBACzF;iBACF;gBACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;aAC9B;YACD,MAAM,EAAE,KAAK;YACb,KAAK,CAAC,GAAG,CAAC,KAAwD,EAAE,GAAG;gBACrE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;gBACpF,IAAI,CAAC,MAAM;oBAAE,OAAO,GAAG,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;gBAEhE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBACjD,MAAM,OAAO,GAAG,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAClD,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACtB,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;oBAC/E,OAAO,GAAG,CAAC,IAAI,CAAC,sBAAsB,KAAK,CAAC,KAAK,iBAAiB,SAAS,IAAI,MAAM,GAAG,CAAC,CAAC;gBAC5F,CAAC;gBAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC/C,IAAI,IAAa,CAAC;gBAClB,IAAI,CAAC;oBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBAC5C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,GAAG,CAAC,IAAI,CAAC,qBAAqB,KAAK,CAAC,KAAK,MAAO,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;gBAClF,CAAC;gBAED,MAAM,IAAI,GAAI,MAAM,CAAC,KAAa,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC5E,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACjF,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;SACF,CAAC;IACJ,CAAC;IAED,iEAAiE;IAEjE,KAAK,CAAC,IAAI,CAAC,YAA0B,EAAE,IAAY,EAAE,IAAU;QAC7D,wEAAwE;QACxE,sEAAsE;QACtE,IAAI,YAAY,CAAC,MAAM,KAAK,UAAU,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YAC/D,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC;YACpE,wEAAwE;YACxE,sDAAsD;YACtD,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpD,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACzB,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACP,GAAG,OAAO;oBACV;wBACE,IAAI,EAAE,aAAa;wBACnB,WAAW,EAAE,SAAS;wBACtB,OAAO,EAAE,GAAG,MAAM,sCAAsC,IAAI,GAAG;qBAChE;iBACF;aACF,CAAC,CAAC;YACH,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAChF,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,YAA0B,EAC1B,KAAyD,EACzD,IAAU;QAEV,2EAA2E;QAC3E,6EAA6E;QAC7E,0EAA0E;QAC1E,4EAA4E;QAC5E,2EAA2E;QAC3E,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAEpF,IAAI,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAEvF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;QACjF,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAE/C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QAErE,4EAA4E;QAC5E,sEAAsE;QACtE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAEzD,IAAI,KAAc,CAAC;QACnB,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,2BAA4B,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAE7E,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,KAAK,KAAK,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;YACnG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YACpF,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YAE9G,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACzB,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACP,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO;oBAC/B;wBACE,IAAI,EAAE,aAAa;wBACnB,WAAW,EAAE,YAAY,CAAC,OAAO,CAAC,SAAS;wBAC3C,oEAAoE;wBACpE,yDAAyD;wBACzD,OAAO,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE;qBACpD;iBACF;aACF,CAAC,CAAC;YACH,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;YAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAC1C,CAAC;QAED,8DAA8D;QAC9D,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC9G,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,KAAK,EAAE,EAAE,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED,kEAAkE;IAE1D,KAAK,CAAC,OAAO,CAAC,YAA0B,EAAE,IAAU;QAC1D,YAAY,CAAC,MAAM,GAAG,WAAW,CAAC;QAClC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QAE9C,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpD,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,YAAY,EAAE,CAAC,CAAC,eAAe;YAC/B,MAAM,EAAE,CAAC,CAAC,MAAM;SACjB,CAAC,CAAC,CAAC;QAEJ,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;YAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,MAAM,GAAG,KAAK,CAAC;YAEnB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;gBAC7C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;gBAC1B,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;oBACpB,IAAI,CAAC,MAAM,EAAE,CAAC;wBACZ,MAAM,GAAG,IAAI,CAAC;wBACd,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;oBACrF,CAAC;oBACD,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClD,CAAC;aACF,CAAC,CAAC;YAEH,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1E,IAAI,KAAK,CAAC,WAAW,KAAK,UAAU;gBAAE,MAAM;YAE5C,MAAM,OAAO,GAAc,EAAE,CAAC;YAC9B,IAAI,MAAM,GAAiE,IAAI,CAAC;YAEhF,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,UAAU,CAAC,EAAE,CAAC;gBAC5E,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAClC,IAAI,CAAC;oBACH,IAAI,EAAE,aAAa;oBACnB,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE;iBAChG,CAAC,CAAC;gBAEH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC3B,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;gBACnF,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;gBAEhC,IAAI,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;oBACpC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;oBAC3F,MAAM,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;gBACzE,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;oBACrF,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;gBAClF,CAAC;YACH,CAAC;YAED,IAAI,MAAM,EAAE,CAAC;gBACX,wEAAwE;gBACxE,YAAY,CAAC,MAAM,GAAG,UAAU,CAAC;gBACjC,YAAY,CAAC,OAAO,GAAG,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC;gBAC9C,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;gBAC7C,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;gBAC3C,OAAO;YACT,CAAC;YAED,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,YAAY,CAAC,MAAM,GAAG,MAAM,CAAC;QAC7B,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACzC,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAEO,KAAK,CAAC,UAAU,CACtB,YAA0B,EAC1B,IAAS,EACT,IAAU,EACV,WAAmB;QAEnB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,iBAAiB,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAE/E,IAAI,IAAI,GAAgC,IAAI,CAAC;QAE7C,MAAM,GAAG,GAAY;YACnB,cAAc,EAAE,YAAY,CAAC,EAAE;YAC/B,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;YAC5B,MAAM,EAAE,CAAC,KAAK,EAAE,IAAoB,EAAE,KAAc,EAAE,OAAyC,EAAE,EAAE;gBACjG,MAAM,WAAW,GAAG,OAAO,EAAE,IAAI,IAAI,SAAS,CAAC;gBAC/C,IAAI,GAAG,WAAW,CAAC;gBAEnB,qEAAqE;gBACrE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAE/C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAC/C;oBACE,cAAc,EAAE,YAAY,CAAC,EAAE;oBAC/B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;oBAC5B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;oBAC7B,KAAK,EAAE,MAAM;oBACb,IAAI,EAAE,WAAW;iBAClB,EACD,YAAY,CAAC,UAAU,CACxB,CAAC;gBAEF,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAElC,gEAAgE;gBAChE,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;gBACpD,IAAI,CAAC;oBACH,IAAI,EAAE,SAAS;oBACf,MAAM;oBACN,MAAM,EAAE,WAAW;oBACnB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;oBAC5B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;oBAC7B,IAAI,EAAE,WAAW;iBAClB,CAAC,CAAC;gBACH,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;gBAElD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YACnC,CAAC,CAAsB;SACxB,CAAC;QAEF,IAAI,KAAc,CAAC;QACnB,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,qBAAqB,IAAI,CAAC,IAAI,KAAM,GAAa,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACrG,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACvC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,0EAA0E;YAC1E,uEAAuE;YACvE,yEAAyE;YACzE,qDAAqD;YACrD,IAAI,YAAY,CAAC,GAAG,CAAC;gBAAE,MAAM,GAAG,CAAC;YACjC,OAAO,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,YAAa,GAAa,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC1F,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,YAA0B,EAAE,IAAU;QAC9D,uEAAuE;QACvE,4DAA4D;QAC5D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;QAC3F,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,MAAM,IAAI,OAAO;YAAE,QAAQ,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClE,IAAI,CAAC;YACH,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,YAAY,CAAC,QAAQ;YAC/B,WAAW,EAAE,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC;YAC7C,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;CACF;AAED,6EAA6E;AAC7E,SAAS,iBAAiB,CAAC,KAAc;IACvC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YAC5E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO,GAAG,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/store.js
CHANGED
|
@@ -87,7 +87,7 @@ export function memoryStore(options = {}) {
|
|
|
87
87
|
async putPayload(record, leaseToken) {
|
|
88
88
|
fence(record.conversationId, leaseToken);
|
|
89
89
|
const handle = `ui_${String(++handleSeq).padStart(2, "0")}`;
|
|
90
|
-
payloads.set(handle, copy({ ...record, handle, createdAt: Date.now() }));
|
|
90
|
+
payloads.set(handle, copy({ ...record, handle, createdAt: Date.now(), staleAfterMs: record.staleAfterMs ?? null }));
|
|
91
91
|
return handle;
|
|
92
92
|
},
|
|
93
93
|
/** Scoped: a handle from another conversation must not resolve. */
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haikit/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The haikit server runtime: agent loop, elicit state machine, derived query_ui, and the interaction security boundary.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"haikit",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"prepack": "npm --prefix ../.. run build"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@haikit/core": "0.
|
|
39
|
+
"@haikit/core": "0.5.0",
|
|
40
40
|
"@types/node": ">=22"
|
|
41
41
|
},
|
|
42
42
|
"publishConfig": {
|
package/src/routes.ts
CHANGED
|
@@ -4,9 +4,11 @@ import type { Emit, WireEvent } from "@haikit/core";
|
|
|
4
4
|
import type { Hai } from "./runtime.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Node http handler for the
|
|
7
|
+
* Node http handler for the three routes. Returns true if it handled the
|
|
8
|
+
* request.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
+
* All three stream SSE: chat and interact because both can resume the agent
|
|
11
|
+
* loop, start because the init tool it runs can render surfaces. Note what the
|
|
10
12
|
* interact route accepts: {handle, action, value} and nothing else. The client
|
|
11
13
|
* cannot name a tool, a handler, or an action target.
|
|
12
14
|
*/
|
|
@@ -16,10 +18,19 @@ export function nodeHandler(hai: Hai, basePath = "/hai") {
|
|
|
16
18
|
if (req.method !== "POST" || !url.pathname.startsWith(basePath)) return false;
|
|
17
19
|
|
|
18
20
|
const route = url.pathname.slice(basePath.length);
|
|
19
|
-
if (route !== "/chat" && route !== "/interact") return false;
|
|
21
|
+
if (route !== "/chat" && route !== "/interact" && route !== "/start") return false;
|
|
20
22
|
|
|
21
23
|
const body = await readJson(req);
|
|
22
24
|
|
|
25
|
+
// Nothing to run before the first message: answer with an empty stream and
|
|
26
|
+
// create no conversation, so an app without init doesn't get one for every
|
|
27
|
+
// page view. Its first message starts the conversation, as it always has.
|
|
28
|
+
if (route === "/start" && !hai.config.init) {
|
|
29
|
+
openSSE(res);
|
|
30
|
+
res.end();
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
23
34
|
// Before the SSE stream opens, because a rejected load has no stream to
|
|
24
35
|
// report into — and an uncaught throw here would take down the request.
|
|
25
36
|
let conversation;
|
|
@@ -33,7 +44,7 @@ export function nodeHandler(hai: Hai, basePath = "/hai") {
|
|
|
33
44
|
}
|
|
34
45
|
|
|
35
46
|
const emit = openSSE(res);
|
|
36
|
-
if (route === "/chat") {
|
|
47
|
+
if (route === "/chat" || route === "/start") {
|
|
37
48
|
emit({ type: "hello", conversationId: conversation.id, model: hai.config.model.id });
|
|
38
49
|
}
|
|
39
50
|
|
|
@@ -41,6 +52,8 @@ export function nodeHandler(hai: Hai, basePath = "/hai") {
|
|
|
41
52
|
try {
|
|
42
53
|
if (route === "/chat") {
|
|
43
54
|
await hai.send(conversation, String(body.message ?? ""), emit);
|
|
55
|
+
} else if (route === "/start") {
|
|
56
|
+
await hai.start(conversation, emit);
|
|
44
57
|
} else {
|
|
45
58
|
await hai.interact(
|
|
46
59
|
conversation,
|
package/src/runtime.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type Tool,
|
|
11
11
|
type ToolCtx,
|
|
12
12
|
type ToolReturn,
|
|
13
|
+
type WireEvent,
|
|
13
14
|
} from "@haikit/core";
|
|
14
15
|
|
|
15
16
|
export interface HaiConfig {
|
|
@@ -20,8 +21,36 @@ export interface HaiConfig {
|
|
|
20
21
|
surfaces: AnySurfaceImpl[];
|
|
21
22
|
/** Guard against runaway tool loops. */
|
|
22
23
|
maxHops?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Runs at the start of every conversation, before the user's first message
|
|
26
|
+
* when the client calls `start()` (the default UI does, on open), otherwise
|
|
27
|
+
* with that first message. Either way it runs before the model's first turn.
|
|
28
|
+
* The runtime makes the call, not the model, so it cannot be skipped: the
|
|
29
|
+
* call and its result are recorded as if the model had made them. It
|
|
30
|
+
* receives `{}` as input and may render surfaces — an elicit surface parks
|
|
31
|
+
* the conversation before the model runs at all.
|
|
32
|
+
*
|
|
33
|
+
* If it throws, the request is refused and nothing is recorded, so the next
|
|
34
|
+
* message tries again. It stays in the model's tool list for the whole
|
|
35
|
+
* conversation — changing that list mid-conversation invalidates the
|
|
36
|
+
* model's earlier reasoning on newer models — but a later call from the
|
|
37
|
+
* model gets "already ran" back instead of running it again.
|
|
38
|
+
*/
|
|
39
|
+
init?: Tool;
|
|
23
40
|
}
|
|
24
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Opens the history when init runs before the user has said anything: the
|
|
44
|
+
* Messages API requires the first message to be the user's. Bracketed like
|
|
45
|
+
* `[UI interaction]` — framework text, not something the user typed.
|
|
46
|
+
*/
|
|
47
|
+
const STARTED = "[conversation started]";
|
|
48
|
+
|
|
49
|
+
/** Appended to the init tool's description in what the model sees. */
|
|
50
|
+
const INIT_NOTE =
|
|
51
|
+
"This ran automatically at the start of the conversation, and its result is already above. " +
|
|
52
|
+
"Calling it again does not run it.";
|
|
53
|
+
|
|
25
54
|
export class Hai {
|
|
26
55
|
readonly config: HaiConfig;
|
|
27
56
|
private readonly surfaces = new Map<string, AnySurfaceImpl>();
|
|
@@ -30,12 +59,22 @@ export class Hai {
|
|
|
30
59
|
|
|
31
60
|
constructor(config: HaiConfig) {
|
|
32
61
|
this.config = config;
|
|
33
|
-
for (const s of config.surfaces)
|
|
62
|
+
for (const s of config.surfaces) {
|
|
63
|
+
checkWindow(s);
|
|
64
|
+
this.surfaces.set(s.surface.name, s);
|
|
65
|
+
}
|
|
34
66
|
for (const t of config.tools) this.tools.set(t.name, t);
|
|
35
67
|
// query_ui is DERIVED, never authored. It cannot drift from the surfaces
|
|
36
68
|
// that actually exist, and it always exists.
|
|
37
69
|
const queryUi = this.buildQueryUiTool();
|
|
38
70
|
this.tools.set(queryUi.name, queryUi);
|
|
71
|
+
|
|
72
|
+
if (config.init) {
|
|
73
|
+
if (this.tools.has(config.init.name)) {
|
|
74
|
+
throw new Error(`init tool "${config.init.name}" has the same name as another tool`);
|
|
75
|
+
}
|
|
76
|
+
this.tools.set(config.init.name, config.init);
|
|
77
|
+
}
|
|
39
78
|
}
|
|
40
79
|
|
|
41
80
|
private nid(prefix: string) {
|
|
@@ -127,6 +166,11 @@ export class Hai {
|
|
|
127
166
|
// ─────────────────────────────────────────────────── public API
|
|
128
167
|
|
|
129
168
|
async send(conversation: Conversation, text: string, emit: Emit): Promise<void> {
|
|
169
|
+
if (await this.refuseIfExpired(conversation, emit)) return;
|
|
170
|
+
|
|
171
|
+
// The first message is the one that starts the conversation.
|
|
172
|
+
const starting = conversation.messages.length === 0;
|
|
173
|
+
|
|
130
174
|
// The user typed while a tool was parked. Every tool_use in a turn must
|
|
131
175
|
// receive a tool_result, so close the pending one out honestly first.
|
|
132
176
|
if (conversation.status === "awaiting" && conversation.pending) {
|
|
@@ -150,15 +194,107 @@ export class Hai {
|
|
|
150
194
|
}
|
|
151
195
|
|
|
152
196
|
emit({ type: "block_start", block: { kind: "user", id: this.nid("b"), text } });
|
|
153
|
-
|
|
197
|
+
if (starting && this.config.init) {
|
|
198
|
+
if (await this.runInit(conversation, text, emit)) return; // parked on its surface
|
|
199
|
+
} else {
|
|
200
|
+
conversation.messages.push({ role: "user", content: text });
|
|
201
|
+
}
|
|
154
202
|
await this.runTurn(conversation, emit);
|
|
155
203
|
}
|
|
156
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Start a conversation before the user has typed anything, so init's result
|
|
207
|
+
* — and any surface it shows — is already there when the first message
|
|
208
|
+
* arrives. The model does not run. Does nothing without an init tool, or
|
|
209
|
+
* once the conversation has begun.
|
|
210
|
+
*/
|
|
211
|
+
async start(conversation: Conversation, emit: Emit): Promise<void> {
|
|
212
|
+
if (!this.config.init || conversation.messages.length > 0) return;
|
|
213
|
+
if (await this.runInit(conversation, STARTED, emit)) return; // parked on its surface
|
|
214
|
+
conversation.status = "idle";
|
|
215
|
+
emit({ type: "status", status: "idle" });
|
|
216
|
+
await this.emitContext(conversation, emit);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Run the init tool as the conversation's first tool call, after `text` —
|
|
221
|
+
* the user's first message, or STARTED when it runs before one. Returns
|
|
222
|
+
* true when it parked the conversation on an elicit surface.
|
|
223
|
+
*
|
|
224
|
+
* Nothing reaches the history until the tool has succeeded — not even the
|
|
225
|
+
* user's message — so a refused start leaves the conversation exactly as
|
|
226
|
+
* the route found it, and the next message starts it again.
|
|
227
|
+
*/
|
|
228
|
+
private async runInit(conversation: Conversation, text: string, emit: Emit): Promise<boolean> {
|
|
229
|
+
const init = this.config.init!;
|
|
230
|
+
const call = { type: "tool_use", id: `toolu_init_${newId()}`, name: init.name, input: {} };
|
|
231
|
+
const toolBlockId = this.nid("b");
|
|
232
|
+
const before = { handles: conversation.handles.length, status: conversation.status };
|
|
233
|
+
|
|
234
|
+
conversation.status = "streaming";
|
|
235
|
+
emit({ type: "status", status: "streaming" });
|
|
236
|
+
emit({ type: "block_start", block: { kind: "tool", id: toolBlockId, name: init.name, input: {}, status: "running" } });
|
|
237
|
+
|
|
238
|
+
// Surfaces are held until init succeeds. One shown by a start that is then
|
|
239
|
+
// refused would look live in the browser, and every click on it would be
|
|
240
|
+
// rejected: its handle never reaches the history.
|
|
241
|
+
const held: WireEvent[] = [];
|
|
242
|
+
const hold: Emit = (e) => {
|
|
243
|
+
if (e.type === "ui_open" || e.type === "ui_props") held.push(e);
|
|
244
|
+
else emit(e);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const started = Date.now();
|
|
248
|
+
let outcome: { ret: ToolReturn; mode: "display" | "elicit" | null };
|
|
249
|
+
try {
|
|
250
|
+
outcome = await this.invokeTool(conversation, call, hold, toolBlockId, { init: true });
|
|
251
|
+
} catch (err) {
|
|
252
|
+
// undo what the tool's renders recorded; their payload rows are orphans
|
|
253
|
+
conversation.handles.length = before.handles;
|
|
254
|
+
conversation.status = before.status;
|
|
255
|
+
if (isStaleLease(err)) throw err;
|
|
256
|
+
const message = `initialisation failed: ${(err as Error).message}`;
|
|
257
|
+
emit({ type: "block_update", id: toolBlockId, status: "error", ms: Date.now() - started, result: message });
|
|
258
|
+
throw new Error(message);
|
|
259
|
+
}
|
|
260
|
+
const { ret, mode } = outcome;
|
|
261
|
+
const ms = Date.now() - started;
|
|
262
|
+
for (const e of held) emit(e);
|
|
263
|
+
|
|
264
|
+
conversation.messages.push({ role: "user", content: text });
|
|
265
|
+
conversation.messages.push({ role: "assistant", content: [call] });
|
|
266
|
+
|
|
267
|
+
if (mode === "elicit" && ret.handle) {
|
|
268
|
+
emit({ type: "block_update", id: toolBlockId, status: "awaiting", ms, result: ret.model });
|
|
269
|
+
conversation.status = "awaiting";
|
|
270
|
+
conversation.pending = { toolUseId: call.id, handle: ret.handle, digest: ret.model, results: [] };
|
|
271
|
+
emit({ type: "status", status: "awaiting" });
|
|
272
|
+
await this.emitContext(conversation, emit);
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
emit({ type: "block_update", id: toolBlockId, status: "ok", ms, result: ret.model });
|
|
277
|
+
conversation.messages.push({
|
|
278
|
+
role: "user",
|
|
279
|
+
content: [{ type: "tool_result", tool_use_id: call.id, content: ret.model }],
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Commit before the model runs. An init that only returns text makes no
|
|
283
|
+
// fenced write of its own, so a request that outlived its lease while init
|
|
284
|
+
// ran would otherwise go on to call the model for a history its final save
|
|
285
|
+
// will lose. This save is fenced: it throws StaleLease if another request
|
|
286
|
+
// has taken the conversation over, and the model never runs here.
|
|
287
|
+
await this.config.store.saveConversation(conversation);
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
|
|
157
291
|
async interact(
|
|
158
292
|
conversation: Conversation,
|
|
159
293
|
input: { handle: string; action: string; value: unknown },
|
|
160
294
|
emit: Emit,
|
|
161
295
|
): Promise<void> {
|
|
296
|
+
if (await this.refuseIfExpired(conversation, emit)) return;
|
|
297
|
+
|
|
162
298
|
// The payload row carries a conversation id, but that alone is not enough.
|
|
163
299
|
// A turn that rendered a surface and was then overtaken leaves a row behind:
|
|
164
300
|
// its conversation save is rejected, so the winning history never records
|
|
@@ -218,6 +354,65 @@ export class Hai {
|
|
|
218
354
|
return this.runTurn(conversation, emit);
|
|
219
355
|
}
|
|
220
356
|
|
|
357
|
+
/**
|
|
358
|
+
* Refuse any request on a conversation that has outlived one of its surfaces.
|
|
359
|
+
*
|
|
360
|
+
* Runs first, before anything is changed, so a refused request records
|
|
361
|
+
* nothing and costs no model call — the save that follows only releases the
|
|
362
|
+
* lease. Every handle in the surviving history counts, answered ones
|
|
363
|
+
* included: what the user picked from a surface is still in the model's
|
|
364
|
+
* context at the price it was shown at.
|
|
365
|
+
*
|
|
366
|
+
* A payload held to a window whose age cannot be computed counts as expired.
|
|
367
|
+
* A store returning a bad `createdAt` has to fail closed, not quietly make
|
|
368
|
+
* every surface fresh forever. A `"never"` window needs no age, so its
|
|
369
|
+
* timestamp is not consulted — the conformance suite is what holds a store
|
|
370
|
+
* to returning good ones. A payload whose row is gone counts as expired too:
|
|
371
|
+
* nothing deletes a payload the history still references, so a missing one
|
|
372
|
+
* is lost data, and lost data proves nothing is fresh.
|
|
373
|
+
*/
|
|
374
|
+
private async refuseIfExpired(conversation: Conversation, emit: Emit): Promise<boolean> {
|
|
375
|
+
if (!conversation.handles.length) return false;
|
|
376
|
+
const now = Date.now();
|
|
377
|
+
const records = await this.config.store.getPayloads(conversation.handles, conversation.id);
|
|
378
|
+
|
|
379
|
+
// the surface that went out of date first is the one that closed it
|
|
380
|
+
let first: { expiredAt: number; age: number; window: number | undefined } | null = null;
|
|
381
|
+
|
|
382
|
+
// getPayloads omits handles it cannot find, and the loop below only sees
|
|
383
|
+
// what came back — so a missing row has to be caught here
|
|
384
|
+
const found = new Set(records.map((r) => r.handle));
|
|
385
|
+
if (conversation.handles.some((h) => !found.has(h))) {
|
|
386
|
+
first = { expiredAt: Number.NaN, age: Number.NaN, window: undefined };
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
for (const record of records) {
|
|
390
|
+
// a surface the code no longer registers has no current window at all,
|
|
391
|
+
// which is not the same as one registered without a window ("never")
|
|
392
|
+
const impl = this.surfaces.get(record.component);
|
|
393
|
+
const window = strictest(record.staleAfterMs, impl ? windowOf(impl) : undefined);
|
|
394
|
+
if (window === "never") continue;
|
|
395
|
+
// A timestamp that is not a finite number cannot prove anything is fresh:
|
|
396
|
+
// Infinity would compare fresh forever, and a bigint would throw on the
|
|
397
|
+
// arithmetic. Replace it before doing any, so each counts as expired —
|
|
398
|
+
// and so does a payload whose window is known nowhere.
|
|
399
|
+
const createdAt = Number.isFinite(record.createdAt) ? record.createdAt : Number.NaN;
|
|
400
|
+
const expiredAt = createdAt + (window ?? Number.NaN);
|
|
401
|
+
if (expiredAt > now) continue;
|
|
402
|
+
if (!first || expiredAt < first.expiredAt) first = { expiredAt, age: now - createdAt, window };
|
|
403
|
+
}
|
|
404
|
+
if (!first) return false;
|
|
405
|
+
|
|
406
|
+
const shown = Number.isFinite(first.age) ? `results shown ${duration(first.age)} ago` : "results shown here";
|
|
407
|
+
const verdict =
|
|
408
|
+
first.window === undefined ? "can no longer be checked" : `were only valid for ${duration(first.window)}`;
|
|
409
|
+
emit({
|
|
410
|
+
type: "expired",
|
|
411
|
+
message: `This conversation is out of date — ${shown} ${verdict}. Start a new conversation for current results.`,
|
|
412
|
+
});
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
|
|
221
416
|
// ──────────────────────────────────────────────── the agent loop
|
|
222
417
|
|
|
223
418
|
private async runTurn(conversation: Conversation, emit: Emit): Promise<void> {
|
|
@@ -226,7 +421,7 @@ export class Hai {
|
|
|
226
421
|
|
|
227
422
|
const toolDefs = [...this.tools.values()].map((t) => ({
|
|
228
423
|
name: t.name,
|
|
229
|
-
description: t.description,
|
|
424
|
+
description: t === this.config.init ? `${t.description}\n\n${INIT_NOTE}` : t.description,
|
|
230
425
|
input_schema: t.inputJsonSchema,
|
|
231
426
|
strict: t.strict,
|
|
232
427
|
}));
|
|
@@ -296,10 +491,21 @@ export class Hai {
|
|
|
296
491
|
call: any,
|
|
297
492
|
emit: Emit,
|
|
298
493
|
toolBlockId: string,
|
|
494
|
+
// the runtime's own start-of-conversation call: failures throw instead of
|
|
495
|
+
// becoming a result for the model, because there is no model turn yet
|
|
496
|
+
options: { init?: boolean } = {},
|
|
299
497
|
): Promise<{ ret: ToolReturn; mode: "display" | "elicit" | null }> {
|
|
300
498
|
const tool = this.tools.get(call.name);
|
|
301
499
|
if (!tool) return { ret: { model: `Unknown tool: ${call.name}` }, mode: null };
|
|
302
500
|
|
|
501
|
+
// the model calling init again: it ran at the start, and does not run twice
|
|
502
|
+
if (tool === this.config.init && !options.init) {
|
|
503
|
+
return {
|
|
504
|
+
ret: { model: `${tool.name} already ran at the start of this conversation; its result is above.` },
|
|
505
|
+
mode: null,
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
|
|
303
509
|
let mode: "display" | "elicit" | null = null;
|
|
304
510
|
|
|
305
511
|
const ctx: ToolCtx = {
|
|
@@ -311,6 +517,7 @@ export class Hai {
|
|
|
311
517
|
|
|
312
518
|
// Validate before storing: props may originate outside this process.
|
|
313
519
|
const parsed = impl.surface.props.parse(props);
|
|
520
|
+
const window = windowOf(impl);
|
|
314
521
|
|
|
315
522
|
const handle = await this.config.store.putPayload(
|
|
316
523
|
{
|
|
@@ -319,6 +526,9 @@ export class Hai {
|
|
|
319
526
|
version: impl.surface.version,
|
|
320
527
|
props: parsed,
|
|
321
528
|
mode: surfaceMode,
|
|
529
|
+
// recorded now, so no later deploy can relax the window this data
|
|
530
|
+
// was shown under — see the stricter-of in refuseIfExpired
|
|
531
|
+
staleAfterMs: window,
|
|
322
532
|
},
|
|
323
533
|
conversation.leaseToken,
|
|
324
534
|
);
|
|
@@ -334,6 +544,9 @@ export class Hai {
|
|
|
334
544
|
component: impl.surface.name,
|
|
335
545
|
version: impl.surface.version,
|
|
336
546
|
mode: surfaceMode,
|
|
547
|
+
// so a browser left open can close the conversation on time, rather
|
|
548
|
+
// than only finding out when its next request is refused
|
|
549
|
+
...(window === "never" ? {} : { staleAfterMs: window }),
|
|
337
550
|
});
|
|
338
551
|
emit({ type: "ui_props", handle, props: parsed });
|
|
339
552
|
|
|
@@ -345,6 +558,7 @@ export class Hai {
|
|
|
345
558
|
try {
|
|
346
559
|
input = tool.input.parse(call.input);
|
|
347
560
|
} catch (err) {
|
|
561
|
+
if (options.init) throw err;
|
|
348
562
|
return { ret: { model: `Invalid input for ${call.name}: ${(err as Error).message}` }, mode: null };
|
|
349
563
|
}
|
|
350
564
|
|
|
@@ -352,6 +566,7 @@ export class Hai {
|
|
|
352
566
|
const ret = await tool.run(input, ctx);
|
|
353
567
|
return { ret, mode };
|
|
354
568
|
} catch (err) {
|
|
569
|
+
if (options.init) throw err;
|
|
355
570
|
// A tool error is information for the model; a lost lease is not. Fencing
|
|
356
571
|
// exists so a superseded turn stops — converting StaleLease into "tool
|
|
357
572
|
// failed" would hand it back to the model and keep paying for hops whose
|
|
@@ -376,6 +591,66 @@ export class Hai {
|
|
|
376
591
|
}
|
|
377
592
|
}
|
|
378
593
|
|
|
594
|
+
/**
|
|
595
|
+
* A surface's declared window; one that declares none never goes stale. Only a
|
|
596
|
+
* missing field defaults — `null` is not "no window" but an invalid one, and
|
|
597
|
+
* has to reach checkWindow to be refused like any other.
|
|
598
|
+
*/
|
|
599
|
+
const windowOf = (s: AnySurfaceImpl): number | "never" =>
|
|
600
|
+
s.impl.staleAfterMs === undefined ? "never" : s.impl.staleAfterMs;
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* The type checked again at runtime, because JavaScript callers never see it.
|
|
604
|
+
* Zero or less would expire every surface the moment it rendered; NaN never
|
|
605
|
+
* compares as expired, and Infinity means "never" without saying so. Leaving
|
|
606
|
+
* the window out is fine: that is "never".
|
|
607
|
+
*/
|
|
608
|
+
function checkWindow(s: AnySurfaceImpl) {
|
|
609
|
+
const window: unknown = windowOf(s);
|
|
610
|
+
if (window === "never" || (typeof window === "number" && Number.isFinite(window) && window > 0)) return;
|
|
611
|
+
const got = typeof window === "string" ? JSON.stringify(window) : String(window);
|
|
612
|
+
throw new RangeError(
|
|
613
|
+
`surface ${s.surface.name}: staleAfterMs must be a positive, finite number of milliseconds, ` +
|
|
614
|
+
`or "never" (got ${got})`,
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* The window a payload is held to: the stricter of the one recorded when it
|
|
620
|
+
* rendered and the one the code declares now. Recorded is what the data was
|
|
621
|
+
* shown under, and survives the surface being renamed or removed; current
|
|
622
|
+
* catches a window tightened since. Neither may relax the other. Undefined
|
|
623
|
+
* when neither is known — an old payload whose surface is gone — which the
|
|
624
|
+
* caller counts as expired.
|
|
625
|
+
*/
|
|
626
|
+
function strictest(recorded: unknown, current: unknown): number | "never" | undefined {
|
|
627
|
+
const valid = (w: unknown): w is number | "never" =>
|
|
628
|
+
w === "never" || (typeof w === "number" && Number.isFinite(w) && w > 0);
|
|
629
|
+
const known = [recorded, current].filter(valid);
|
|
630
|
+
if (!known.length) return undefined;
|
|
631
|
+
const finite = known.filter((w): w is number => w !== "never");
|
|
632
|
+
return finite.length ? Math.min(...finite) : "never";
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
const newId = () => globalThis.crypto.randomUUID().replaceAll("-", "").slice(0, 16);
|
|
636
|
+
|
|
637
|
+
/** "2 hours", "15 minutes" — for a sentence a person reads. */
|
|
638
|
+
function duration(ms: number): string {
|
|
639
|
+
const units: [number, string][] = [
|
|
640
|
+
[86_400_000, "day"],
|
|
641
|
+
[3_600_000, "hour"],
|
|
642
|
+
[60_000, "minute"],
|
|
643
|
+
[1_000, "second"],
|
|
644
|
+
];
|
|
645
|
+
for (const [size, name] of units) {
|
|
646
|
+
if (ms >= size) {
|
|
647
|
+
const n = Math.floor(ms / size);
|
|
648
|
+
return `${n} ${name}${n === 1 ? "" : "s"}`;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return "under a second";
|
|
652
|
+
}
|
|
653
|
+
|
|
379
654
|
/** Find the array prop a surface's queries operate over (for cap totals). */
|
|
380
655
|
function primaryCollection(props: unknown): string {
|
|
381
656
|
if (props && typeof props === "object") {
|
package/src/store.ts
CHANGED
|
@@ -110,7 +110,7 @@ export function memoryStore(options: MemoryStoreOptions = {}): StoreAdapter {
|
|
|
110
110
|
async putPayload(record, leaseToken) {
|
|
111
111
|
fence(record.conversationId, leaseToken);
|
|
112
112
|
const handle = `ui_${String(++handleSeq).padStart(2, "0")}`;
|
|
113
|
-
payloads.set(handle, copy({ ...record, handle, createdAt: Date.now() }));
|
|
113
|
+
payloads.set(handle, copy({ ...record, handle, createdAt: Date.now(), staleAfterMs: record.staleAfterMs ?? null }));
|
|
114
114
|
return handle;
|
|
115
115
|
},
|
|
116
116
|
|