@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 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 two routes. Returns true if it handled the request.
4
+ * Node http handler for the three routes. Returns true if it handled the
5
+ * request.
5
6
  *
6
- * Both routes stream SSE, because both can resume the agent loop. Note what the
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
  */
@@ -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;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,SAAS,IACxB,KAAK,eAAe,EAAE,KAAK,cAAc,KAAG,OAAO,CAAC,OAAO,CAAC,CAiE1F"}
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 two routes. Returns true if it handled the request.
3
+ * Node http handler for the three routes. Returns true if it handled the
4
+ * request.
4
5
  *
5
- * Both routes stream SSE, because both can resume the agent loop. Note what the
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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
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;
@@ -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,EAGV,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;CAClB;AAED,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;IAU7B,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;IA4BzE,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;YA8DF,OAAO;YAuEP,UAAU;YAsEV,WAAW;CAa1B"}
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
- conversation.messages.push({ role: "user", content: text });
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") {
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,OAAO,GAUR,MAAM,cAAc,CAAC;AA4BtB;;;;GAIG;AACH,MAAM,OAAO,GAAG,wBAAwB,CAAC;AAEzC,sEAAsE;AACtE,MAAM,SAAS,GACb,4FAA4F;IAC5F,mCAAmC,CAAC;AAEtC,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,EAAE,CAAC;YAChC,WAAW,CAAC,CAAC,CAAC,CAAC;YACf,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC;QACD,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;QAEtC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrC,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,CAAC,IAAI,CAAC,IAAI,qCAAqC,CAAC,CAAC;YACvF,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAChD,CAAC;IACH,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,IAAI,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,IAAI,CAAC;YAAE,OAAO;QAE3D,6DAA6D;QAC7D,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;QAEpD,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,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC;gBAAE,OAAO,CAAC,wBAAwB;QACpF,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK,CAAC,YAA0B,EAAE,IAAU;QAChD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO;QAClE,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC;YAAE,OAAO,CAAC,wBAAwB;QACrF,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;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,OAAO,CAAC,YAA0B,EAAE,IAAY,EAAE,IAAU;QACxE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAK,CAAC;QAC/B,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,cAAc,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC3F,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,CAAC;QAErF,YAAY,CAAC,MAAM,GAAG,WAAW,CAAC;QAClC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAEvH,2EAA2E;QAC3E,yEAAyE;QACzE,kDAAkD;QAClD,MAAM,IAAI,GAAgB,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAS,CAAC,CAAC,EAAE,EAAE;YACvB,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;gBAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;gBAC3D,IAAI,CAAC,CAAC,CAAC,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,IAAI,OAA+D,CAAC;QACpE,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACzF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,wEAAwE;YACxE,YAAY,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;YAC7C,YAAY,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YACpC,IAAI,YAAY,CAAC,GAAG,CAAC;gBAAE,MAAM,GAAG,CAAC;YACjC,MAAM,OAAO,GAAG,0BAA2B,GAAa,CAAC,OAAO,EAAE,CAAC;YACnE,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAC5G,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;QAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAE9B,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEnE,IAAI,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACpC,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;YAC3F,YAAY,CAAC,MAAM,GAAG,UAAU,CAAC;YACjC,YAAY,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YAClG,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YAC7C,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,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;QACrF,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;YACzB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;SAC7E,CAAC,CAAC;QAEH,wEAAwE;QACxE,2EAA2E;QAC3E,2EAA2E;QAC3E,0EAA0E;QAC1E,kEAAkE;QAClE,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,YAA0B,EAC1B,KAAyD,EACzD,IAAU;QAEV,IAAI,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,IAAI,CAAC;YAAE,OAAO;QAE3D,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;;;;;;;;;;;;;;;;OAgBG;IACK,KAAK,CAAC,eAAe,CAAC,YAA0B,EAAE,IAAU;QAClE,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;QAE3F,oEAAoE;QACpE,IAAI,KAAK,GAA0E,IAAI,CAAC;QAExF,yEAAyE;QACzE,0DAA0D;QAC1D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACpD,IAAI,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,KAAK,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QACxE,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,uEAAuE;YACvE,qEAAqE;YACrE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACjF,IAAI,MAAM,KAAK,OAAO;gBAAE,SAAS;YACjC,0EAA0E;YAC1E,wEAAwE;YACxE,uEAAuE;YACvE,uDAAuD;YACvD,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACpF,MAAM,SAAS,GAAG,SAAS,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;YACrD,IAAI,SAAS,GAAG,GAAG;gBAAE,SAAS;YAC9B,IAAI,CAAC,KAAK,IAAI,SAAS,GAAG,KAAK,CAAC,SAAS;gBAAE,KAAK,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,MAAM,EAAE,CAAC;QACjG,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QAEzB,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC;QAC7G,MAAM,OAAO,GACX,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,uBAAuB,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5G,IAAI,CAAC;YACH,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,sCAAsC,KAAK,IAAI,OAAO,iDAAiD;SACjH,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,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,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,OAAO,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW;YACxF,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;IACnB,0EAA0E;IAC1E,sEAAsE;IACtE,UAA8B,EAAE;QAEhC,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,4EAA4E;QAC5E,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/C,OAAO;gBACL,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,sEAAsE,EAAE;gBAClG,IAAI,EAAE,IAAI;aACX,CAAC;QACJ,CAAC;QAED,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;gBAC/C,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAE9B,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;oBACjB,kEAAkE;oBAClE,2DAA2D;oBAC3D,YAAY,EAAE,MAAM;iBACrB,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;oBACjB,oEAAoE;oBACpE,yDAAyD;oBACzD,GAAG,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;iBACxD,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,IAAI,OAAO,CAAC,IAAI;gBAAE,MAAM,GAAG,CAAC;YAC5B,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,IAAI,OAAO,CAAC,IAAI;gBAAE,MAAM,GAAG,CAAC;YAC5B,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;;;;GAIG;AACH,MAAM,QAAQ,GAAG,CAAC,CAAiB,EAAoB,EAAE,CACvD,CAAC,CAAC,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;AAEpE;;;;;GAKG;AACH,SAAS,WAAW,CAAC,CAAiB;IACpC,MAAM,MAAM,GAAY,QAAQ,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;QAAE,OAAO;IACxG,MAAM,GAAG,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjF,MAAM,IAAI,UAAU,CAClB,WAAW,CAAC,CAAC,OAAO,CAAC,IAAI,oEAAoE;QAC3F,mBAAmB,GAAG,GAAG,CAC5B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,SAAS,CAAC,QAAiB,EAAE,OAAgB;IACpD,MAAM,KAAK,GAAG,CAAC,CAAU,EAAyB,EAAE,CAClD,CAAC,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1E,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAC/D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACvD,CAAC;AAED,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAEpF,+DAA+D;AAC/D,SAAS,QAAQ,CAAC,EAAU;IAC1B,MAAM,KAAK,GAAuB;QAChC,CAAC,UAAU,EAAE,KAAK,CAAC;QACnB,CAAC,SAAS,EAAE,MAAM,CAAC;QACnB,CAAC,MAAM,EAAE,QAAQ,CAAC;QAClB,CAAC,KAAK,EAAE,QAAQ,CAAC;KAClB,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;YACf,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;YAChC,OAAO,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;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"}
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.1",
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.3.1",
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 two routes. Returns true if it handled the request.
7
+ * Node http handler for the three routes. Returns true if it handled the
8
+ * request.
8
9
  *
9
- * Both routes stream SSE, because both can resume the agent loop. Note what the
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) this.surfaces.set(s.surface.name, s);
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
- conversation.messages.push({ role: "user", content: text });
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