@data-club/ai-hub 0.0.9 → 0.0.10

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.
Files changed (48) hide show
  1. package/dist/auth/locales/cs.d.ts +1 -1
  2. package/dist/auth/locales/cs.d.ts.map +1 -1
  3. package/dist/auth/locales/cs.js +1 -12
  4. package/dist/auth/locales/cs.js.map +1 -1
  5. package/dist/auth/locales/sk.d.ts +1 -1
  6. package/dist/auth/locales/sk.d.ts.map +1 -1
  7. package/dist/auth/locales/sk.js +1 -12
  8. package/dist/auth/locales/sk.js.map +1 -1
  9. package/dist/auth/texts.d.ts +0 -17
  10. package/dist/auth/texts.d.ts.map +1 -1
  11. package/dist/auth/texts.js +0 -11
  12. package/dist/auth/texts.js.map +1 -1
  13. package/dist/client/AIHubClient.d.ts +2 -39
  14. package/dist/client/AIHubClient.d.ts.map +1 -1
  15. package/dist/client/AIHubClient.js +2 -13
  16. package/dist/client/AIHubClient.js.map +1 -1
  17. package/dist/components/DataClubAIHubAdmin/SettingsPage.d.ts +7 -8
  18. package/dist/components/DataClubAIHubAdmin/SettingsPage.d.ts.map +1 -1
  19. package/dist/components/DataClubAIHubAdmin/SettingsPage.js +8 -83
  20. package/dist/components/DataClubAIHubAdmin/SettingsPage.js.map +1 -1
  21. package/dist/components/MessageList/index.d.ts.map +1 -1
  22. package/dist/components/MessageList/index.js +1 -2
  23. package/dist/components/MessageList/index.js.map +1 -1
  24. package/dist/context/AIHubProvider.d.ts.map +1 -1
  25. package/dist/context/AIHubProvider.js +1 -31
  26. package/dist/context/AIHubProvider.js.map +1 -1
  27. package/dist/index.d.ts +1 -3
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +0 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/state/stateReducer.d.ts.map +1 -1
  32. package/dist/state/stateReducer.js +0 -1
  33. package/dist/state/stateReducer.js.map +1 -1
  34. package/dist/types.d.ts +1 -73
  35. package/dist/types.d.ts.map +1 -1
  36. package/package.json +2 -1
  37. package/src/auth/locales/cs.ts +1 -17
  38. package/src/auth/locales/sk.ts +1 -17
  39. package/src/auth/texts.ts +0 -34
  40. package/src/client/AIHubClient.ts +2 -42
  41. package/src/components/DataClubAIHubAdmin/SettingsPage.tsx +8 -177
  42. package/src/components/MessageList/index.tsx +0 -4
  43. package/src/context/AIHubProvider.tsx +1 -32
  44. package/src/index.ts +0 -8
  45. package/src/state/stateReducer.ts +0 -1
  46. package/src/styles/default.css +0 -63
  47. package/src/types.ts +0 -75
  48. package/src/components/CacheBadge/index.tsx +0 -245
@@ -2,20 +2,19 @@
2
2
  * `<AdminSettingsPage />` — the super_admin-only Settings sub-page mounted
3
3
  * inside `<DataClubAIHubAdmin />` ([08-admin-settings.md]).
4
4
  *
5
- * Five independent sections, each with its own Save button — per the spec,
6
- * "Don't make the user save all five sections together":
5
+ * Independent sections, each with its own Save button — per the spec,
6
+ * "Don't make the user save all sections together":
7
7
  *
8
- * 1. **Letta connection** — base URL, ADE URL, API key (masked + replaceable).
9
- * 2. **Theme** — default theme + switcher-enabled checkbox.
10
- * 3. **UI feature toggles** — the §8.4 toggle blob.
11
- * 4. **Signing key** — rotate with `ROTATE`-typing friction. Rotating
8
+ * 1. **Theme** — default theme + switcher-enabled checkbox.
9
+ * 2. **UI feature toggles** — the §8.4 toggle blob.
10
+ * 3. **Signing key** — rotate with `ROTATE`-typing friction. Rotating
12
11
  * invalidates every JWT, including the calling super-admin's.
13
- * 5. **Metrics scrape token** — rotate with the same friction. The new token
12
+ * 4. **Metrics scrape token** — rotate with the same friction. The new token
14
13
  * is shown ONCE via a reveal modal; subsequent settings reads no longer
15
14
  * expose it. Does NOT invalidate the calling JWT.
16
15
  *
17
16
  * Each section owns its own dirty-state and save handler; sibling sections
18
- * never share state. This means a half-typed Letta URL won't be pushed when
17
+ * never share state. This means a half-typed value won't be pushed when
19
18
  * the admin clicks `Save toggles` in a different section.
20
19
  *
21
20
  * Visible to `super_admin` only — the parent shell hides the nav item for
@@ -176,11 +175,6 @@ export function AdminSettingsPage(props: AdminSettingsPageProps): ReactNode {
176
175
  ) : null}
177
176
  {settings !== null ? (
178
177
  <>
179
- <LettaConnectionSection
180
- settings={settings}
181
- texts={props.texts}
182
- onSaved={handleSectionSaved}
183
- />
184
178
  <ThemeSection
185
179
  settings={settings}
186
180
  texts={props.texts}
@@ -230,7 +224,7 @@ export function AdminSettingsPage(props: AdminSettingsPageProps): ReactNode {
230
224
  }
231
225
 
232
226
  /* ────────────────────────────────────────────────────────────────────────── */
233
- /* Section: Letta connection */
227
+ /* Section: Theme */
234
228
  /* ────────────────────────────────────────────────────────────────────────── */
235
229
 
236
230
  interface SectionProps {
@@ -238,169 +232,6 @@ interface SectionProps {
238
232
  texts: AIHubAdminTexts;
239
233
  }
240
234
 
241
- interface LettaConnectionSectionProps extends SectionProps {
242
- onSaved: (next: AdminSettingsView) => void;
243
- }
244
-
245
- function LettaConnectionSection(props: LettaConnectionSectionProps): ReactNode {
246
- const { client } = useAIHub();
247
- const [baseUrl, setBaseUrl] = useState(props.settings.letta_base_url ?? "");
248
- // Empty string = leave-as-is; non-empty = replace.
249
- const [apiKey, setApiKey] = useState("");
250
- const [saving, setSaving] = useState(false);
251
- const [flash, setFlash] = useState<{ tone: "success" | "error"; text: string } | null>(
252
- null,
253
- );
254
-
255
- async function handleSave(event: React.FormEvent): Promise<void> {
256
- event.preventDefault();
257
- setSaving(true);
258
- setFlash(null);
259
- try {
260
- const body: Parameters<typeof client.patchAdminSettings>[0] = {};
261
- // Compare against current to avoid stomping the existing value with the
262
- // identical one. The server treats null + value identically, but the
263
- // schema forbids `null + ""` so we coerce explicitly.
264
- if (baseUrl !== (props.settings.letta_base_url ?? "")) {
265
- body.lettaBaseUrl = baseUrl === "" ? null : baseUrl;
266
- }
267
- if (apiKey !== "") body.lettaApiKey = apiKey;
268
- const next = await client.patchAdminSettings(body);
269
- props.onSaved(next);
270
- setApiKey("");
271
- setFlash({ tone: "success", text: props.texts.settingsSaveSuccessFlash });
272
- } catch (err) {
273
- setFlash({
274
- tone: "error",
275
- text:
276
- err instanceof Error && err.message.length > 0
277
- ? err.message
278
- : props.texts.settingsSaveGenericError,
279
- });
280
- } finally {
281
- setSaving(false);
282
- }
283
- }
284
-
285
- // Clears the DB column (sends `letta_api_key: ""`), which makes the
286
- // server fall back to env.LETTA_API_KEY at runtime per the
287
- // resolveApiKey precedence in letta/client.ts. Same code path as the
288
- // base URL nulling — only it targets the API-key column.
289
- async function handleClearApiKeyOverride(): Promise<void> {
290
- setSaving(true);
291
- setFlash(null);
292
- try {
293
- const next = await client.patchAdminSettings({ lettaApiKey: "" });
294
- props.onSaved(next);
295
- setFlash({ tone: "success", text: props.texts.settingsSaveSuccessFlash });
296
- } catch (err) {
297
- setFlash({
298
- tone: "error",
299
- text:
300
- err instanceof Error && err.message.length > 0
301
- ? err.message
302
- : props.texts.settingsSaveGenericError,
303
- });
304
- } finally {
305
- setSaving(false);
306
- }
307
- }
308
-
309
- return (
310
- <section
311
- className="data-club-ai-hub-admin__settings-section"
312
- data-testid="admin-settings-letta-section"
313
- >
314
- <h2 className="data-club-ai-hub-admin__settings-section-heading">
315
- {props.texts.settingsLettaSectionHeading}
316
- </h2>
317
- <form onSubmit={(event) => void handleSave(event)} noValidate>
318
- <label className="data-club-ai-hub-admin__form-field">
319
- <span className="data-club-ai-hub-admin__form-label">
320
- {props.texts.settingsLettaBaseUrlLabel}
321
- </span>
322
- <input
323
- type="url"
324
- className="data-club-ai-hub-admin__form-input"
325
- data-testid="admin-settings-letta-base-url"
326
- value={baseUrl}
327
- onChange={(event) => setBaseUrl(event.target.value)}
328
- disabled={saving}
329
- />
330
- </label>
331
- <label className="data-club-ai-hub-admin__form-field">
332
- <span className="data-club-ai-hub-admin__form-label">
333
- {props.texts.settingsLettaApiKeyLabel}
334
- </span>
335
- <input
336
- type="password"
337
- className="data-club-ai-hub-admin__form-input"
338
- data-testid="admin-settings-letta-api-key"
339
- value={apiKey}
340
- placeholder={
341
- props.settings.letta_api_key_source === "db"
342
- ? props.texts.settingsLettaApiKeyPlaceholder
343
- : ""
344
- }
345
- onChange={(event) => setApiKey(event.target.value)}
346
- disabled={saving}
347
- autoComplete="new-password"
348
- />
349
- <span
350
- className="data-club-ai-hub-admin__form-helper"
351
- data-testid="admin-settings-letta-api-key-helper"
352
- data-source={props.settings.letta_api_key_source}
353
- >
354
- {props.settings.letta_api_key_source === "db"
355
- ? props.texts.settingsLettaApiKeyDbHelper
356
- : props.settings.letta_api_key_source === "env"
357
- ? props.texts.settingsLettaApiKeyEnvHelper
358
- : props.texts.settingsLettaApiKeyNoneHelper}
359
- </span>
360
- {props.settings.letta_api_key_source === "db" ? (
361
- <button
362
- type="button"
363
- className="data-club-ai-hub-admin__button"
364
- data-testid="admin-settings-letta-api-key-clear"
365
- onClick={() => void handleClearApiKeyOverride()}
366
- disabled={saving}
367
- >
368
- {props.texts.settingsLettaApiKeyClearOverrideButton}
369
- </button>
370
- ) : null}
371
- </label>
372
- {flash !== null ? (
373
- <div
374
- className={
375
- flash.tone === "success"
376
- ? "data-club-ai-hub-admin__flash data-club-ai-hub-admin__flash--success"
377
- : "data-club-ai-hub-admin__flash data-club-ai-hub-admin__flash--error"
378
- }
379
- data-testid="admin-settings-letta-flash"
380
- role={flash.tone === "error" ? "alert" : "status"}
381
- >
382
- {flash.text}
383
- </div>
384
- ) : null}
385
- <button
386
- type="submit"
387
- className="data-club-ai-hub-admin__button data-club-ai-hub-admin__button--primary"
388
- data-testid="admin-settings-letta-save"
389
- disabled={saving}
390
- >
391
- {saving
392
- ? props.texts.settingsSaveSavingButton
393
- : props.texts.settingsSaveLettaButton}
394
- </button>
395
- </form>
396
- </section>
397
- );
398
- }
399
-
400
- /* ────────────────────────────────────────────────────────────────────────── */
401
- /* Section: Theme */
402
- /* ────────────────────────────────────────────────────────────────────────── */
403
-
404
235
  interface ThemeSectionProps extends SectionProps {
405
236
  onSaved: (next: AdminSettingsView) => void;
406
237
  }
@@ -54,7 +54,6 @@ import type {
54
54
  AIHubMessageBubbleRenderer,
55
55
  } from "../../types.js";
56
56
 
57
- import { CacheBadge } from "../CacheBadge/index.js";
58
57
  import { MarkdownRenderer } from "../MarkdownRenderer/index.js";
59
58
  import { ReasoningView } from "../ReasoningView/index.js";
60
59
  import { ScrollToPresentButton } from "../ScrollToPresentButton/index.js";
@@ -713,9 +712,6 @@ function MessageBubble(props: {
713
712
  message.content.trim()
714
713
  )}
715
714
  </span>
716
- {isAssistant && message.usage ? (
717
- <CacheBadge usage={message.usage} />
718
- ) : null}
719
715
  {props.isFailedAssistant ? (
720
716
  <div className={cls.bubbleActions}>
721
717
  <span>{props.failedLabel}</span>
@@ -108,7 +108,7 @@ function mergeOptimisticAffordances(
108
108
  ): AIHubMessage[] {
109
109
  const optimisticById = new Map<string, AIHubMessage>();
110
110
  for (const m of optimistic) {
111
- if (m.role === "assistant" && (m.reasoning || m.tool_calls?.length || m.usage)) {
111
+ if (m.role === "assistant" && (m.reasoning || m.tool_calls?.length)) {
112
112
  optimisticById.set(m.id, m);
113
113
  }
114
114
  }
@@ -123,13 +123,6 @@ function mergeOptimisticAffordances(
123
123
  if ((!next.tool_calls || next.tool_calls.length === 0) && o.tool_calls?.length) {
124
124
  next.tool_calls = o.tool_calls;
125
125
  }
126
- // Usage rides through too — if the canonical refetch happens
127
- // before the server stamped `message_usage` (small race window),
128
- // the live `usage` event we already handled keeps the badge
129
- // rendered until the next refresh confirms it.
130
- if (!next.usage && o.usage) {
131
- next.usage = o.usage;
132
- }
133
126
  return next;
134
127
  });
135
128
  }
@@ -828,30 +821,6 @@ export function AIHubProvider(props: AIHubProviderProps): ReactNode {
828
821
  setStreamingReasoning(null);
829
822
  setStreamingToolCalls([]);
830
823
  sawAssistantOutput = true;
831
- } else if (event.event === "usage") {
832
- // Live usage stamp — the runner emits this right before
833
- // `stream_end{done}` carrying the cache-hit/write counts for
834
- // the turn. We attach it to the matching assistant bubble so
835
- // `<CacheBadge />` appears immediately (without waiting for
836
- // the post-stream `/messages` refetch). The refetch path
837
- // also stamps the same `usage` from the persisted
838
- // `message_usage` row, so refresh + history retrieval show
839
- // the badge too.
840
- const targetId = event.data.letta_message_id;
841
- if (typeof targetId === "string") {
842
- const usage = {
843
- input: event.data.input ?? null,
844
- output: event.data.output ?? null,
845
- cache_read: event.data.cache_read ?? null,
846
- cache_write: event.data.cache_write ?? null,
847
- reasoning: event.data.reasoning ?? null,
848
- context: event.data.context ?? null,
849
- total: event.data.total ?? null,
850
- };
851
- setMessages((prev) =>
852
- prev.map((m) => (m.id === targetId ? { ...m, usage } : m)),
853
- );
854
- }
855
824
  } else if (event.event === "error") {
856
825
  setLastTurnError(event.data.message);
857
826
  sawError = true;
package/src/index.ts CHANGED
@@ -26,7 +26,6 @@ export type {
26
26
  Session,
27
27
  AIHubMessage,
28
28
  AIHubMessageOverride,
29
- AIHubMessageUsage,
30
29
  AIHubToolCallRecord,
31
30
  TurnStatus,
32
31
  RunningPhase,
@@ -232,13 +231,6 @@ export type {
232
231
  } from "./components/ToolCallView/index.js";
233
232
  export { formatToolContentForDisplay } from "./components/ToolCallView/formatContent.js";
234
233
 
235
- export { CacheBadge, computeCacheHitRatio } from "./components/CacheBadge/index.js";
236
- export type {
237
- CacheBadgeProps,
238
- CacheBadgeClassNames,
239
- CacheBadgeTexts,
240
- } from "./components/CacheBadge/index.js";
241
-
242
234
  export { ScrollToPresentButton } from "./components/ScrollToPresentButton/index.js";
243
235
  export type {
244
236
  ScrollToPresentButtonProps,
@@ -125,7 +125,6 @@ export function reduceAIHubState(
125
125
  case "tool_call_dispatched":
126
126
  case "tool_call_progress":
127
127
  case "tool_call_result":
128
- case "usage":
129
128
  return next;
130
129
  }
131
130
  }
@@ -2260,69 +2260,6 @@
2260
2260
  letter-spacing: 0.04em;
2261
2261
  }
2262
2262
 
2263
- /* ─────────────────────────────────────────────────────────────────── */
2264
- /* Cache badge — per-assistant-message prompt-cache hit indicator */
2265
- /* */
2266
- /* Renders as a small chip in the bottom-right corner of the assistant */
2267
- /* bubble, showing the cache-hit % over the prompt-side tokens. The */
2268
- /* `data-cache-state` attribute (none|cold|warm|hot) drives the color */
2269
- /* so skinners can override per-state via the CSS-vars without */
2270
- /* duplicating the layout rules. */
2271
- /* ─────────────────────────────────────────────────────────────────── */
2272
- .data-club-ai-hub__cache-badge {
2273
- display: inline-flex;
2274
- align-items: center;
2275
- gap: 0.25em;
2276
- margin-top: 0.4em;
2277
- margin-left: auto;
2278
- align-self: flex-end;
2279
- padding: 0.1em 0.5em;
2280
- font-size: 0.75em;
2281
- line-height: 1.2;
2282
- border-radius: 999px;
2283
- background: var(--dc-aih-cache-badge-bg, rgba(127, 127, 127, 0.12));
2284
- color: var(--dc-aih-cache-badge-fg, var(--dc-aih-text-muted, #888));
2285
- border: 1px solid var(--dc-aih-cache-badge-border, transparent);
2286
- cursor: help; /* signals the title-attribute tooltip */
2287
- user-select: none;
2288
- transition: background 0.15s ease, border-color 0.15s ease;
2289
- }
2290
- .data-club-ai-hub__cache-badge[data-cache-state="hot"] {
2291
- background: var(--dc-aih-cache-badge-hot-bg, rgba(40, 180, 99, 0.14));
2292
- color: var(--dc-aih-cache-badge-hot-fg, #28b463);
2293
- }
2294
- .data-club-ai-hub__cache-badge[data-cache-state="warm"] {
2295
- background: var(--dc-aih-cache-badge-warm-bg, rgba(255, 142, 78, 0.14));
2296
- color: var(--dc-aih-cache-badge-warm-fg, #ff8e4e);
2297
- }
2298
- .data-club-ai-hub__cache-badge[data-cache-state="cold"] {
2299
- background: var(--dc-aih-cache-badge-cold-bg, rgba(160, 160, 160, 0.14));
2300
- color: var(--dc-aih-cache-badge-cold-fg, #888);
2301
- }
2302
- .data-club-ai-hub__cache-badge[data-cache-state="miss"] {
2303
- /* Full cache miss — provider had to reinitialize the whole prompt.
2304
- Red-tinted to signal "nothing cached this turn". */
2305
- background: var(--dc-aih-cache-badge-miss-bg, rgba(216, 44, 246, 0.12));
2306
- color: var(--dc-aih-cache-badge-miss-fg, #d82cf6);
2307
- }
2308
- .data-club-ai-hub__cache-badge[data-cache-state="priming"] {
2309
- /* This turn WROTE to the provider's cache. Next turn benefits.
2310
- Blue-tinted to distinguish from cold miss. */
2311
- background: var(--dc-aih-cache-badge-priming-bg, rgba(41, 189, 239, 0.14));
2312
- color: var(--dc-aih-cache-badge-priming-fg, #29bdef);
2313
- }
2314
- .data-club-ai-hub__cache-badge[data-cache-state="none"] {
2315
- font-style: italic;
2316
- opacity: 0.7;
2317
- }
2318
- .data-club-ai-hub__cache-badge__icon {
2319
- font-size: 0.9em;
2320
- }
2321
- .data-club-ai-hub__cache-badge__label {
2322
- font-variant-numeric: tabular-nums;
2323
- font-weight: 600;
2324
- }
2325
-
2326
2263
  /* ────────────────────────────────────────────────────────────────────────── */
2327
2264
  /* Step 12 — admin Agents / Sessions overview / Settings sub-pages */
2328
2265
  /* ────────────────────────────────────────────────────────────────────────── */
package/src/types.ts CHANGED
@@ -81,10 +81,6 @@ export interface AIHubUser {
81
81
  * `user.theme_preference + deployment.{theme_default, theme_switcher_enabled}`
82
82
  * per §7.6 (two lines in the React provider).
83
83
  *
84
- * `letta_ade_url` is included only when the caller's role is `power_user`
85
- * or higher; for `user`-role callers the field is absent — by design
86
- * (§6.3.4: the URL is an admin-surface concern).
87
- *
88
84
  * @see SPECIFICATIONS.md §6.3.4 — `GET /auth/me`
89
85
  * @see SPECIFICATIONS.md §7.6 — theme resolution
90
86
  */
@@ -123,11 +119,6 @@ export interface AIHubDeployment {
123
119
  * hidden. (Also hidden whenever only one agent exists, regardless of this.)
124
120
  */
125
121
  agent_switcher_enabled: boolean;
126
- /**
127
- * Browser-facing URL of the self-hosted Letta ADE — only present when the
128
- * caller's role is `power_user` or higher. Absent for `user`-role callers.
129
- */
130
- letta_ade_url?: string;
131
122
  }
132
123
 
133
124
  /**
@@ -261,16 +252,6 @@ export interface AIHubMessage {
261
252
  * @see ui-sketches/03-chat.md — tool_call_card
262
253
  */
263
254
  tool_calls?: AIHubToolCallRecord[] | null;
264
- /**
265
- * Provider-reported token usage for the turn that produced this
266
- * message. Set on the LAST assistant message of each turn (the
267
- * `usage_statistics` event is per-run, not per-message; we stamp it
268
- * on the visible final bubble). Renders as a small cache-status
269
- * badge in the chat UI; hover for the full breakdown.
270
- *
271
- * @see AIHubMessageUsage
272
- */
273
- usage?: AIHubMessageUsage | null;
274
255
  }
275
256
 
276
257
  /**
@@ -638,61 +619,6 @@ export interface AIHubSystemNoticeEvent extends AIHubEventBase {
638
619
  };
639
620
  }
640
621
 
641
- /**
642
- * System: per-turn token-usage counters propagated from Letta. Stamped
643
- * on the LAST assistant message of the turn — the React reducer uses
644
- * `letta_message_id` to attach the badge to the right bubble. Also
645
- * persisted server-side so a refresh keeps the badge.
646
- *
647
- * @see SPECIFICATIONS.md §9.4
648
- * @see docs/server/chat-sse.md
649
- */
650
- export interface AIHubSystemUsageEvent extends AIHubEventBase {
651
- event: "usage";
652
- data: {
653
- /**
654
- * Letta message id this usage attaches to (the turn's last assistant
655
- * message). The reducer joins this against the chat history to put
656
- * the cache badge on the right bubble. Optional for forward
657
- * compatibility with future per-message usage events.
658
- */
659
- letta_message_id?: string;
660
- /** Non-cached input-token count (prompt_tokens). */
661
- input?: number;
662
- /** Output-token count (completion_tokens). */
663
- output?: number;
664
- /** Cache-read-token count — Anthropic / OpenAI / Gemini all report. */
665
- cache_read?: number;
666
- /** Cache-write-token count — Anthropic only; null elsewhere. */
667
- cache_write?: number;
668
- /** Reasoning / thinking tokens for models that produce them. */
669
- reasoning?: number;
670
- /** Letta's rolling context-window-size estimate post-turn. */
671
- context?: number;
672
- /** Sum reported by provider (may differ from input+output when reasoning is counted separately). */
673
- total?: number;
674
- };
675
- }
676
-
677
- /**
678
- * Per-assistant-message cache + token usage, attached to the
679
- * historical chat record. Returned from `GET /sessions/{id}/messages`
680
- * via `AIHubMessage.usage`. Same shape as the live wire event's
681
- * `data` minus the `letta_message_id` (which is already the message
682
- * itself).
683
- *
684
- * @see AIHubSystemUsageEvent
685
- */
686
- export interface AIHubMessageUsage {
687
- input?: number | null;
688
- output?: number | null;
689
- cache_read?: number | null;
690
- cache_write?: number | null;
691
- reasoning?: number | null;
692
- context?: number | null;
693
- total?: number | null;
694
- }
695
-
696
622
  /**
697
623
  * System: non-recoverable error. Followed by `stream_end {reason: "error"}`.
698
624
  * The turn transitions to `failed`; the session remains usable.
@@ -734,7 +660,6 @@ export type AIHubEvent =
734
660
  | AIHubToolCallProgressEvent
735
661
  | AIHubToolCallResultEvent
736
662
  | AIHubSystemNoticeEvent
737
- | AIHubSystemUsageEvent
738
663
  | AIHubSystemErrorEvent;
739
664
 
740
665
  /* ────────────────────────────────────────────────────────────────────────── */