@belonguniverseai/react-sdk 0.6.27 → 0.6.29
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 +43 -4
- package/dist/api/account-scope.d.ts +75 -0
- package/dist/api/artifact-actions.d.ts +0 -1
- package/dist/api/auth-errors.d.ts +21 -0
- package/dist/api/client-identity.d.ts +3 -1
- package/dist/api/client.d.ts +1394 -162
- package/dist/api/goals.d.ts +19 -2
- package/dist/api/live-artifacts.d.ts +197 -0
- package/dist/api/my-usage.d.ts +28 -0
- package/dist/api/queries.d.ts +6 -4
- package/dist/api/query-keys.d.ts +44 -3
- package/dist/api/task-schedule-sharing.d.ts +18 -3
- package/dist/api/task-schedules.d.ts +76 -12
- package/dist/app/VoiceOverlay.d.ts +4 -3
- package/dist/app/dock-story-data.d.ts +19 -1
- package/dist/browser/control-channel.d.ts +9 -0
- package/dist/browser/dom-bridge.d.ts +2 -0
- package/dist/component/BelongWidget.d.ts +17 -4
- package/dist/component/{abnfDiagram-N423BO3Z-DrnjkZwk.js → abnfDiagram-N423BO3Z-BvL7baZ-.js} +4 -4
- package/dist/component/{arc-CLchGzOM.js → arc-DVUroP2Z.js} +2 -2
- package/dist/component/{architectureDiagram-T3A2C74G-Du8PLen3.js → architectureDiagram-T3A2C74G-CYt93mxs.js} +3 -3
- package/dist/component/{blockDiagram-VBNYF7ZC-BxmYbrlL.js → blockDiagram-VBNYF7ZC-yST7U8Pb.js} +4 -4
- package/dist/component/{c4Diagram-5PPSVZJV-DHiwlK7l.js → c4Diagram-5PPSVZJV-BHz6Efx3.js} +3 -3
- package/dist/component/{channel-C2eeNEMi.js → channel-CKTqNdN4.js} +2 -2
- package/dist/component/{chunk-2GRJ4B5K-D6I_U4nB.js → chunk-2GRJ4B5K-Bw2zHHAm.js} +2 -2
- package/dist/component/{chunk-2Q5K7J3B-BR3JSmNI.js → chunk-2Q5K7J3B-DpBuF73m.js} +2 -2
- package/dist/component/{chunk-5RXB4S5H-DcmzyncC.js → chunk-5RXB4S5H-dxBtwi1p.js} +5 -5
- package/dist/component/{chunk-5VM5RSS4-8ww1xEAz.js → chunk-5VM5RSS4-BOTqM1Rc.js} +2 -2
- package/dist/component/{chunk-6Q2QTUOP-Chlg3gnC.js → chunk-6Q2QTUOP-DjMXJhRD.js} +2 -2
- package/dist/component/{chunk-GF5L2VYU-CgKydjVC.js → chunk-GF5L2VYU-CGpnSfXM.js} +6 -6
- package/dist/component/{chunk-JWPE2WC7-13zVpFYT.js → chunk-JWPE2WC7-L5aYKPho.js} +2 -2
- package/dist/component/{chunk-KBJHAD2P-CP28c_dJ.js → chunk-KBJHAD2P-DH2RFBaF.js} +2 -2
- package/dist/component/{chunk-RYQCIY6F-CaHaa77d.js → chunk-RYQCIY6F-QPgRO0s7.js} +2 -2
- package/dist/component/{chunk-XXDRQBXY-Cd0yVkqx.js → chunk-XXDRQBXY-C1ezaFpA.js} +2 -2
- package/dist/component/{classDiagram-JCYQIIEL-Bn0740dK.js → classDiagram-JCYQIIEL-Dx7Qx836.js} +3 -3
- package/dist/component/{classDiagram-v2-OCEON4UE-Bn0740dK.js → classDiagram-v2-OCEON4UE-Dx7Qx836.js} +3 -3
- package/dist/component/{cose-bilkent-JH36ORCC-Y6CvxIe4.js → cose-bilkent-JH36ORCC-Bem1eaLJ.js} +2 -2
- package/dist/component/{cynefinDiagram-MW4NZA55-BJ_o5gyM.js → cynefinDiagram-MW4NZA55-DF15EWOu.js} +3 -3
- package/dist/component/{dagre-VZM6K2ZE-Ce_ZLKlj.js → dagre-VZM6K2ZE-BVzwev7l.js} +3 -3
- package/dist/component/{diagram-7IWD3JNH-K8E_XdII.js → diagram-7IWD3JNH-DzQhKX_v.js} +4 -4
- package/dist/component/{diagram-B4RE2ZJO-DZGs1RuF.js → diagram-B4RE2ZJO-DnHINfhE.js} +3 -3
- package/dist/component/{diagram-LBJQPF4R-CzKPOqJK.js → diagram-LBJQPF4R-CPqE_GwY.js} +3 -3
- package/dist/component/{diagram-Q27KOJAE-UItKj-dk.js → diagram-Q27KOJAE-BjpvfqhL.js} +4 -4
- package/dist/component/{diagram-UB23O5K3-ZxBLx0B9.js → diagram-UB23O5K3-BcYqFjqI.js} +3 -3
- package/dist/component/{ebnfDiagram-BXEA7PRR-BIS2pIB5.js → ebnfDiagram-BXEA7PRR-DoqGcWGx.js} +4 -4
- package/dist/component/{erDiagram-JOGREHBK-BNZB6-ZZ.js → erDiagram-JOGREHBK-DGrj5tIK.js} +5 -5
- package/dist/component/{flowDiagram-UKHOOZJN-B8H3ZNjd.js → flowDiagram-UKHOOZJN-B8OuOrVY.js} +7 -7
- package/dist/component/{ganttDiagram-PKOTCBZU-2JJJVAY-.js → ganttDiagram-PKOTCBZU-BaxSqTVY.js} +3 -3
- package/dist/component/{gitGraphDiagram-DS77QQ5N-BVWxsX1D.js → gitGraphDiagram-DS77QQ5N-W1Sqa3Hc.js} +4 -4
- package/dist/component/{highlighted-body-OFNGDK62-CmQzAJHd.js → highlighted-body-OFNGDK62-Cf1UqcGe.js} +2 -2
- package/dist/component/index.d.ts +1 -0
- package/dist/component/index.js +2 -2
- package/dist/component/{infoDiagram-6WML65LV-B-7B2PTM.js → infoDiagram-6WML65LV-BS0JlYPr.js} +2 -2
- package/dist/component/{ishikawaDiagram-WSZJBQD7-DgjY91jV.js → ishikawaDiagram-WSZJBQD7-Df_NzOQV.js} +2 -2
- package/dist/component/{journeyDiagram-NVQOT4AX-fkb_5H2H.js → journeyDiagram-NVQOT4AX-JWKvZ6rc.js} +5 -5
- package/dist/component/{kanban-definition-27J2QSJJ-ZRQERkli.js → kanban-definition-27J2QSJJ-DMvICKAB.js} +3 -3
- package/dist/component/{linear-DX0_iAiu.js → linear-D02U2fTS.js} +2 -2
- package/dist/component/{mermaid-GHXKKRXX-BhURR8Q_.js → mermaid-GHXKKRXX-B7CJJdoE.js} +51487 -47044
- package/dist/component/{mindmap-definition-FAOFIHXS-Duc36TEr.js → mindmap-definition-FAOFIHXS-AzTh8oju.js} +4 -4
- package/dist/component/{pegDiagram-VL7TDLO6-Egcz9GLB.js → pegDiagram-VL7TDLO6-DSCzZs_w.js} +4 -4
- package/dist/component/{pieDiagram-7S7Q4E2Y-DEe2GHp7.js → pieDiagram-7S7Q4E2Y-CEByr6BB.js} +4 -4
- package/dist/component/{quadrantDiagram-CIZ2JOQS-DNfio-6s.js → quadrantDiagram-CIZ2JOQS-BrWOf-GT.js} +3 -3
- package/dist/component/{railroadDiagram-AXF67PYL-B3lRYedY.js → railroadDiagram-AXF67PYL-DRtsV2gM.js} +4 -4
- package/dist/component/{requirementDiagram-LRYGKXZP-DYYxC0Cg.js → requirementDiagram-LRYGKXZP-_WwAo7AE.js} +4 -4
- package/dist/component/{sankeyDiagram-W5VNT64P-CKQNueMs.js → sankeyDiagram-W5VNT64P-DBxP3yyK.js} +2 -2
- package/dist/component/{sequenceDiagram-SI44F4Z6-ChF8pgI7.js → sequenceDiagram-SI44F4Z6-B3SNXrpC.js} +4 -4
- package/dist/component/{sizeCapture-X5ZJPWSS-BQyVznxb.js → sizeCapture-X5ZJPWSS-D5G8pyPC.js} +2 -2
- package/dist/component/{stateDiagram-OKZ733FA-CAVOTaJQ.js → stateDiagram-OKZ733FA-C4UZwsoc.js} +3 -3
- package/dist/component/{stateDiagram-v2-UEYNNEHI-rGNqHCbu.js → stateDiagram-v2-UEYNNEHI-DIYB5q15.js} +3 -3
- package/dist/component/{swimlanes-SLNWSIFB-j8tXsaid.js → swimlanes-SLNWSIFB-Cc9yJXTh.js} +4 -4
- package/dist/component/{swimlanesDiagram-ULZ7WXOC-CsbepRMA.js → swimlanesDiagram-ULZ7WXOC-DsGPiJ-s.js} +3 -3
- package/dist/component/{timeline-definition-Z64GVDOM-nCRE1AQh.js → timeline-definition-Z64GVDOM-Dr4-iAeD.js} +3 -3
- package/dist/component/{vennDiagram-T6HMQDX7-C3ubGm9c.js → vennDiagram-T6HMQDX7-ZiaZ9jYw.js} +2 -2
- package/dist/component/{wardleyDiagram-T6FBY63Y-mKT8yN1z.js → wardleyDiagram-T6FBY63Y-KdF37MT-.js} +3 -3
- package/dist/component/{xychartDiagram-ELKLHX3M-D5AF8jgv.js → xychartDiagram-ELKLHX3M-NH_bOKPL.js} +3 -3
- package/dist/components/artifacts/ArtifactDetailSurface.d.ts +37 -0
- package/dist/components/artifacts/ArtifactMeta.d.ts +10 -0
- package/dist/components/artifacts/ArtifactsListSurface.d.ts +11 -0
- package/dist/components/artifacts/BindScheduleDialog.d.ts +39 -0
- package/dist/components/artifacts/ConfirmDeleteArtifactDialog.d.ts +9 -0
- package/dist/components/artifacts/ConfirmReshareDialog.d.ts +24 -0
- package/dist/components/artifacts/artifact-format.d.ts +38 -0
- package/dist/components/artifacts/open-artifact-version.d.ts +16 -0
- package/dist/components/artifacts/use-artifact-actions.d.ts +32 -0
- package/dist/components/embed/ComposerContext.d.ts +11 -7
- package/dist/components/embed/EmbedComposer.d.ts +7 -1
- package/dist/components/embed/EmbedRail.d.ts +9 -2
- package/dist/components/embed/GoalRefusalCard.d.ts +5 -1
- package/dist/components/embed/MobileNavBar.d.ts +2 -1
- package/dist/components/embed/ResponseModeDial.d.ts +11 -0
- package/dist/components/embed/SessionStatsPanel.d.ts +3 -0
- package/dist/components/embed/UsageSettings.d.ts +11 -0
- package/dist/components/embed/format-compact-number.d.ts +8 -0
- package/dist/components/embed/use-artifact-operation-notices.d.ts +1 -0
- package/dist/components/scheduled/ConfirmRunPausedScheduleDialog.d.ts +18 -0
- package/dist/components/scheduled/EmailCopiesFields.d.ts +19 -0
- package/dist/components/scheduled/ScheduledDetailSurface.d.ts +2 -1
- package/dist/components/scheduled/use-run-now-with-confirmation.d.ts +17 -0
- package/dist/embed/artifact-action-bridge.d.ts +13 -3
- package/dist/embed/artifact-remint-budget.d.ts +5 -0
- package/dist/embed/copy.d.ts +13 -18
- package/dist/embed/dock-state.d.ts +1 -1
- package/dist/embed/global.d.ts +2 -0
- package/dist/embed/goal-edit-command.d.ts +6 -5
- package/dist/embed/plan-decision-text.d.ts +1 -0
- package/dist/embed/presets.d.ts +1 -0
- package/dist/embed/response-mode.d.ts +48 -0
- package/dist/embed/theme.d.ts +5 -0
- package/dist/embed/voice-config.d.ts +22 -31
- package/dist/embed/voice-prefs.d.ts +18 -34
- package/dist/i18n/messages/en.d.ts +146 -7
- package/dist/i18n/messages/surfaces/artifacts.d.ts +304 -0
- package/dist/i18n/messages/surfaces/feedback.d.ts +12 -0
- package/dist/i18n/messages/surfaces/header.d.ts +4 -0
- package/dist/i18n/messages/surfaces/myUsage.d.ts +75 -0
- package/dist/i18n/messages/surfaces/plan.d.ts +4 -0
- package/dist/i18n/messages/surfaces/scheduled.d.ts +53 -1
- package/dist/i18n/messages/surfaces/settings.d.ts +12 -0
- package/dist/i18n/messages/surfaces/stats.d.ts +4 -12
- package/dist/i18n/messages/surfaces/stream.d.ts +88 -0
- package/dist/i18n/messages/surfaces/usage.d.ts +1 -9
- package/dist/infrastructure/telemetry/first-response-timing.d.ts +51 -0
- package/dist/lib/tab-control-store.d.ts +14 -0
- package/dist/lib/tab-leadership.d.ts +9 -24
- package/dist/lib/use-now.d.ts +32 -0
- package/dist/lib/use-tab-leadership.d.ts +5 -7
- package/dist/routes/artifact-detail.d.ts +2 -0
- package/dist/routes/artifacts.d.ts +2 -0
- package/dist/routes/chat/history-merge.d.ts +53 -0
- package/dist/routes/chat/history-paging.d.ts +25 -6
- package/dist/routes/chat/transcript-row.d.ts +1 -0
- package/dist/routes/chat/use-catch-up-on-return.d.ts +70 -0
- package/dist/routes/chat/use-return-to-page.d.ts +7 -0
- package/dist/stream/belong-chat-transport.d.ts +38 -8
- package/dist/stream/belong-data-parts.d.ts +10 -0
- package/dist/stream/dispatch-once.d.ts +1 -1
- package/dist/stream/message-parts.d.ts +3 -1
- package/dist/stream/queued-message-outbox.d.ts +6 -0
- package/dist/stream/select-session-usage.d.ts +9 -0
- package/dist/stream/session-control-context.d.ts +7 -0
- package/dist/stream/session-stats-csv.d.ts +7 -9
- package/dist/types/public.d.ts +16 -9
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Live ownership shared by the composer and the browser-control channel. */
|
|
2
|
+
export type TabOwnership = {
|
|
3
|
+
readonly term: number;
|
|
4
|
+
readonly tabId: string;
|
|
5
|
+
};
|
|
6
|
+
export type TabControlSnapshot = {
|
|
7
|
+
readonly role: "pending" | "leader" | "follower";
|
|
8
|
+
readonly owner: TabOwnership | null;
|
|
9
|
+
};
|
|
10
|
+
export declare const peekTabControl: (sessionId: string) => TabControlSnapshot;
|
|
11
|
+
export declare const subscribeTabControl: (listener: () => void) => (() => void);
|
|
12
|
+
export declare const publishTabControl: (sessionId: string, snapshot: TabControlSnapshot) => void;
|
|
13
|
+
/** A departing controller must not clear a newer controller's snapshot. */
|
|
14
|
+
export declare const clearTabControl: (sessionId: string, snapshot: TabControlSnapshot) => void;
|
|
@@ -1,26 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
* Multi-tab same-session guard (plan 007 §C5).
|
|
3
|
-
*
|
|
4
|
-
* Two dock tabs open on ONE session can double-send and clobber the persisted
|
|
5
|
-
* `{ runId, lastEventId }` stream state. This module elects a single LEADER
|
|
6
|
-
* tab per session over a `BroadcastChannel` (`belong:session:<sessionId>`);
|
|
7
|
-
* follower tabs banner "open in another tab" and disable the composer.
|
|
8
|
-
*
|
|
9
|
-
* Protocol (all messages Zod-parsed at the perimeter — §4):
|
|
10
|
-
* - on start every tab broadcasts a `claim` carrying `{ tabId, claimedAtMs }`
|
|
11
|
-
* - seniority = the EARLIER claim; equal timestamps tie-break on tabId
|
|
12
|
-
* - the leader heartbeats every ~5 s and re-asserts when a junior claims
|
|
13
|
-
* - a tab that hears a senior claim/heartbeat becomes follower
|
|
14
|
-
* - a follower takes over when no senior beat lands for ~12 s, or
|
|
15
|
-
* immediately on the leader's `release` (stop / pagehide)
|
|
16
|
-
*
|
|
17
|
-
* Feature detection: no `BroadcastChannel` (older WebKit, jsdom) → guard
|
|
18
|
-
* disabled, the tab stays leader, zero behavior change.
|
|
19
|
-
*/
|
|
1
|
+
import { TabControlSnapshot } from './tab-control-store.ts';
|
|
20
2
|
export type TabRole = "leader" | "follower";
|
|
21
3
|
export declare const HEARTBEAT_INTERVAL_MS = 5000;
|
|
22
4
|
export declare const TAKEOVER_TIMEOUT_MS = 12000;
|
|
23
|
-
/**
|
|
5
|
+
/** Allow the channel's asynchronous discovery replies to arrive before claiming. */
|
|
6
|
+
export declare const DISCOVERY_INTERVAL_MS = 150;
|
|
24
7
|
export type LeadershipChannel = {
|
|
25
8
|
postMessage: (message: unknown) => void;
|
|
26
9
|
close: () => void;
|
|
@@ -30,17 +13,19 @@ export type LeadershipChannel = {
|
|
|
30
13
|
};
|
|
31
14
|
export type TabLeadershipOptions = {
|
|
32
15
|
readonly sessionId: string;
|
|
33
|
-
|
|
34
|
-
readonly onRoleChange: (role: TabRole) => void;
|
|
16
|
+
readonly onChange: (snapshot: TabControlSnapshot) => void;
|
|
35
17
|
readonly heartbeatIntervalMs?: number;
|
|
36
18
|
readonly takeoverTimeoutMs?: number;
|
|
37
|
-
|
|
19
|
+
readonly discoveryIntervalMs?: number;
|
|
38
20
|
readonly createChannel?: (name: string) => LeadershipChannel | null;
|
|
39
|
-
/** Clock seam (§25). */
|
|
40
21
|
readonly nowMs?: () => number;
|
|
22
|
+
/** Separate browser realms have separate page identities; injectable in tests. */
|
|
23
|
+
readonly tabId?: string;
|
|
41
24
|
};
|
|
42
25
|
export type TabLeadershipHandle = {
|
|
43
26
|
readonly stop: () => void;
|
|
27
|
+
readonly requestControl: () => void;
|
|
28
|
+
readonly getSnapshot: () => TabControlSnapshot;
|
|
44
29
|
};
|
|
45
30
|
export declare const tabLeadershipChannelName: (sessionId: string) => string;
|
|
46
31
|
export declare const startTabLeadership: (options: TabLeadershipOptions) => TabLeadershipHandle;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dock's clock, as one moving value every surface can read.
|
|
3
|
+
*
|
|
4
|
+
* Surfaces that say something about time — "Link works until…", "refreshed 2h
|
|
5
|
+
* ago", "hasn't refreshed since…" — used to capture `new Date()` in a
|
|
6
|
+
* `useState` initializer. That freezes the comparison at MOUNT: a link that
|
|
7
|
+
* expired four minutes ago was still offered as live, and an overdue warning
|
|
8
|
+
* never appeared, even after a refetch brought fresh rows (P2, 2026-09-27
|
|
9
|
+
* PR #614 deep audit finding 8). Server-side expiry is enforced, so the damage
|
|
10
|
+
* was a screen that lied, not access — which is exactly the kind of thing a
|
|
11
|
+
* reader stops trusting the rest of the surface over.
|
|
12
|
+
*
|
|
13
|
+
* ONE STORE, not a hook-local interval, and that is the point: every consumer
|
|
14
|
+
* in a render reads the SAME `Date` object. Two independent clocks a few
|
|
15
|
+
* milliseconds apart can straddle an expiry and render "live" beside "expired"
|
|
16
|
+
* in the same paint (§25), which is the bug the frozen `useState` was
|
|
17
|
+
* originally protecting against — this keeps that guarantee and adds movement.
|
|
18
|
+
*
|
|
19
|
+
* One interval for the whole SDK, started by the first subscriber and cleared
|
|
20
|
+
* by the last: nothing ticks while no surface is on screen, and a store that
|
|
21
|
+
* has been idle re-reads the wall clock when it starts again rather than
|
|
22
|
+
* handing out the instant it stopped at.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* How often the shared instant advances. Half a minute: everything the dock
|
|
26
|
+
* says about time is minute-scale or coarser ("works until 10:00", "2h ago"),
|
|
27
|
+
* so this is fine enough that no reader sees a stale answer, and coarse enough
|
|
28
|
+
* that an idle dock is not re-rendering its surfaces every second.
|
|
29
|
+
*/
|
|
30
|
+
export declare const NOW_TICK_MS = 30000;
|
|
31
|
+
/** The current instant, shared with every other consumer of this render. */
|
|
32
|
+
export declare const useNow: () => Date;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { TabRole } from './tab-leadership.ts';
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*/
|
|
8
|
-
export declare const useTabLeadership: (chatId: string) => TabRole;
|
|
2
|
+
/** The persisted server id replaces a new Session's per-tab placeholder. */
|
|
3
|
+
export declare const useTabLeadership: (chatId: string) => {
|
|
4
|
+
readonly role: TabRole;
|
|
5
|
+
readonly requestControl: () => void;
|
|
6
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { BelongUIMessage } from '../../stream/belong-data-parts.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Merge freshly-fetched server history with whatever is CURRENTLY on screen
|
|
4
|
+
* (§41 — a history load must never make a message the user is looking at
|
|
5
|
+
* disappear). Server order is authoritative; any LOCAL-ONLY message — most
|
|
6
|
+
* often the optimistic turn a concurrent send appended after this fetch
|
|
7
|
+
* started — survives, appended AFTER the server-ordered messages rather than
|
|
8
|
+
* lost to the replace.
|
|
9
|
+
*
|
|
10
|
+
* What is on screen above the page stays above it: the page lines up on the
|
|
11
|
+
* first of its rows found on screen (`isRowOf`, so a turn this tab streamed
|
|
12
|
+
* live lines up too), then back over the earlier rows of the page.
|
|
13
|
+
*
|
|
14
|
+
* Dedupe prefers the row id, then the client id the row was sent with. A
|
|
15
|
+
* message with no id match yet falls back to `(role, flattened text)`. Only
|
|
16
|
+
* the suffix AFTER the last server-known on-screen message can be local-only.
|
|
17
|
+
* Within that suffix, an assistant at the same next position as a durable
|
|
18
|
+
* assistant is the same historical turn with stream-vs-folded whitespace/part
|
|
19
|
+
* drift, not a new reply. A genuinely live assistant is preserved when
|
|
20
|
+
* durable history has no assistant at that position yet.
|
|
21
|
+
*/
|
|
22
|
+
export declare const mergeRestoredHistory: (loaded: readonly BelongUIMessage[], onScreen: readonly BelongUIMessage[]) => BelongUIMessage[];
|
|
23
|
+
/**
|
|
24
|
+
* A kept chat shows every turn it streamed. The server's newest page holds
|
|
25
|
+
* something it never saw only when it has a user turn that is not on screen:
|
|
26
|
+
* one sent from another tab or device (the reply to it comes with it).
|
|
27
|
+
*
|
|
28
|
+
* Turns are matched one to one, by their row id or the client id they were
|
|
29
|
+
* sent with, so a prompt repeated elsewhere ("continue", or two files-only
|
|
30
|
+
* turns with no text) is still a new turn. Text is only a fallback for a row
|
|
31
|
+
* that carries no client id, matched in order against the turns on screen
|
|
32
|
+
* that no id accounted for.
|
|
33
|
+
*/
|
|
34
|
+
export declare const hasUnseenTurns: (loaded: readonly BelongUIMessage[], onScreen: readonly BelongUIMessage[]) => boolean;
|
|
35
|
+
/**
|
|
36
|
+
* #839 — what an IDLE chat shows once the reader comes back to it, given the
|
|
37
|
+
* newest page read just now: the conversation a reload would show (§41),
|
|
38
|
+
* without the reload. Null when the page brings nothing the screen lacks, so
|
|
39
|
+
* a return with nothing new leaves every message — and every card — as it is.
|
|
40
|
+
*
|
|
41
|
+
* - The page lines up with the screen (some message on screen is one of its
|
|
42
|
+
* rows): the turns added elsewhere are merged in after what is on screen,
|
|
43
|
+
* exactly as a mount merges its read (`mergeRestoredHistory`) — no
|
|
44
|
+
* duplicates, server order, older pages above it and anything only this
|
|
45
|
+
* tab holds kept.
|
|
46
|
+
* - Nothing on screen is on the page: the conversation moved past a whole
|
|
47
|
+
* page while this tab was away, or was cleared elsewhere and went on. What
|
|
48
|
+
* is on screen is from before the page, so the page replaces it, as a
|
|
49
|
+
* reload would; scrolling up loads what came before it.
|
|
50
|
+
* - An empty page never empties the screen: a chat cleared in another tab
|
|
51
|
+
* reads empty after the next reload, but a return alone wipes nothing.
|
|
52
|
+
*/
|
|
53
|
+
export declare const catchUpTranscript: (page: readonly BelongUIMessage[], onScreen: readonly BelongUIMessage[]) => BelongUIMessage[] | null;
|
|
@@ -38,16 +38,35 @@ export declare const withoutOlderPages: <T extends {
|
|
|
38
38
|
export declare const olderHistoryCursor: (paging: HistoryPaging, messages: readonly {
|
|
39
39
|
readonly id: string;
|
|
40
40
|
}[]) => string | undefined;
|
|
41
|
+
/** Where a walk back over a page stands: page row and on-screen message. */
|
|
42
|
+
export type PageRowPlace = {
|
|
43
|
+
readonly pageIndex: number;
|
|
44
|
+
readonly screenIndex: number;
|
|
45
|
+
};
|
|
46
|
+
/** How a page's rows are told apart on screen (see {@link splitOlderPrefix}). */
|
|
47
|
+
export type PageRowMatch<R, T> = {
|
|
48
|
+
/** `message` IS `row`. Anchors the page on screen. */
|
|
49
|
+
readonly isRow: (row: R, message: T) => boolean;
|
|
50
|
+
/** `message`, on screen right above where the page lines up so far, stands
|
|
51
|
+
* for `row`, an earlier page row; `at` says where both are. */
|
|
52
|
+
readonly isSameTurn: (row: R, message: T, at: PageRowPlace) => boolean;
|
|
53
|
+
};
|
|
41
54
|
/**
|
|
42
|
-
* What a newest-page re-read must leave alone:
|
|
43
|
-
*
|
|
44
|
-
* page
|
|
55
|
+
* What a newest-page re-read must leave alone: whatever is on screen ABOVE
|
|
56
|
+
* the page (older pages the reader scrolled in, turns from before it). The
|
|
57
|
+
* page's first row found on screen anchors it; walking back from there, each
|
|
58
|
+
* earlier page row takes the message right above while that message stands
|
|
59
|
+
* for it, and the first one that does not ends the walk: what is above it
|
|
60
|
+
* stays where it is, even if that shows a message the page also holds. An
|
|
61
|
+
* extra message reads better than a wrong pairing. Nothing when no row of the
|
|
62
|
+
* page is on screen (it is merged as a whole). By default rows match by id
|
|
63
|
+
* only; the chat's merge passes its own rules.
|
|
45
64
|
*/
|
|
46
|
-
export declare const splitOlderPrefix: <
|
|
65
|
+
export declare const splitOlderPrefix: <R extends {
|
|
47
66
|
readonly id: string;
|
|
48
|
-
}
|
|
67
|
+
}, T extends {
|
|
49
68
|
readonly id: string;
|
|
50
|
-
}[], current: readonly T[]) => {
|
|
69
|
+
}>(loaded: readonly R[], current: readonly T[], match?: PageRowMatch<R, T>) => {
|
|
51
70
|
readonly older: readonly T[];
|
|
52
71
|
readonly rest: readonly T[];
|
|
53
72
|
};
|
|
@@ -29,6 +29,7 @@ export type TranscriptRowWiring = {
|
|
|
29
29
|
readonly onGoalStartAnother: () => void;
|
|
30
30
|
};
|
|
31
31
|
export type TranscriptRowProps = {
|
|
32
|
+
readonly onFirstResponseRendered?: ComponentProps<typeof MessageParts>["onFirstResponseRendered"];
|
|
32
33
|
readonly message: BelongUIMessage;
|
|
33
34
|
/** This message's index in the FULL conversation (not the render window). */
|
|
34
35
|
readonly index: number;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { BelongUIMessage } from '../../stream/belong-data-parts.ts';
|
|
2
|
+
import { HistoryPageResult, LoadedHistoryPage } from './history-cache.ts';
|
|
3
|
+
import { useReturnToPage } from './use-return-to-page.ts';
|
|
4
|
+
/** The chat as the catch-up reads it: `@ai-sdk/react`'s `Chat`, live. Its
|
|
5
|
+
* `messages` array is replaced on every change, so identity says "changed". */
|
|
6
|
+
export type CatchUpChat = {
|
|
7
|
+
readonly status: "submitted" | "streaming" | "ready" | "error";
|
|
8
|
+
readonly messages: readonly BelongUIMessage[];
|
|
9
|
+
};
|
|
10
|
+
/** The server's answer about the session's active run. `failed` (network,
|
|
11
|
+
* non-2xx, a drifted body) is not `none`: only a confirmed `none` is
|
|
12
|
+
* remembered. */
|
|
13
|
+
export type ActiveRunLookup = {
|
|
14
|
+
readonly kind: "none";
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: "run";
|
|
17
|
+
readonly runId: string;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: "failed";
|
|
20
|
+
};
|
|
21
|
+
/** The transport as the catch-up reads it. */
|
|
22
|
+
export type CatchUpTransport = {
|
|
23
|
+
readonly sessionId: string | null;
|
|
24
|
+
/** A stream, its handshake or its retry loop owns this session. */
|
|
25
|
+
readonly hasLiveStream: boolean;
|
|
26
|
+
};
|
|
27
|
+
/** What else may own the transcript right now; any of them blocks a step. */
|
|
28
|
+
export type CatchUpBlockers = {
|
|
29
|
+
/** The workspace does not resolve. */
|
|
30
|
+
readonly workspaceMissing: boolean;
|
|
31
|
+
/** The mount's first history read is out. */
|
|
32
|
+
readonly historyLoading: boolean;
|
|
33
|
+
/** A resume handshake is under way. */
|
|
34
|
+
readonly restoringLiveRun: boolean;
|
|
35
|
+
/** A queued-reply reconciliation is pending. It starts without a render,
|
|
36
|
+
* so it is asked for when needed rather than passed as a value. */
|
|
37
|
+
readonly queuedReconciliationPending: () => boolean;
|
|
38
|
+
};
|
|
39
|
+
export declare const useCatchUpOnReturn: (input: {
|
|
40
|
+
readonly chat: CatchUpChat;
|
|
41
|
+
readonly transport: CatchUpTransport;
|
|
42
|
+
/** Checked when a step starts and again after every await, against the
|
|
43
|
+
* latest render's values, never those of the render that started it. */
|
|
44
|
+
readonly blockers: CatchUpBlockers;
|
|
45
|
+
/** Read the newest page from the server now. */
|
|
46
|
+
readonly readNewestPage: (sessionId: string) => Promise<HistoryPageResult>;
|
|
47
|
+
/** The read landed after the transcript changed: the page it cached may
|
|
48
|
+
* predate the change (a clear), so no chat may be painted from it. */
|
|
49
|
+
readonly onReadOutdated: (sessionId: string) => void;
|
|
50
|
+
/** Show `caughtUp`, the conversation `page` brought the screen up to. */
|
|
51
|
+
readonly onCaughtUp: (caughtUp: BelongUIMessage[], page: LoadedHistoryPage) => void;
|
|
52
|
+
/** Ask the server for the session's active run. */
|
|
53
|
+
readonly findActiveRun: (sessionId: string) => Promise<ActiveRunLookup>;
|
|
54
|
+
/** Follow `runId`, the reply to the turn `page` ends on, from its first event. */
|
|
55
|
+
readonly onFollowRun: (sessionId: string, runId: string, page: LoadedHistoryPage) => void;
|
|
56
|
+
/** The session this tab has selected now (the stream-state pointer). */
|
|
57
|
+
readonly selectedSessionId: () => string | null;
|
|
58
|
+
/** Bumped when the transcript's work loses its owner (leaving the chat, a
|
|
59
|
+
* clear, a stop): a step started under an older value drops itself. A
|
|
60
|
+
* clear's POST runs before it empties the screen, so the transcript alone
|
|
61
|
+
* cannot tell a lookup that the clear is under way. */
|
|
62
|
+
readonly ownerGeneration: () => number;
|
|
63
|
+
/** A newly controlling tab catches up even when the page stayed visible. */
|
|
64
|
+
readonly controlRole?: "leader" | "follower";
|
|
65
|
+
/** Explicit retries of a control request, including a failed catch-up. */
|
|
66
|
+
readonly controlRequestId?: number;
|
|
67
|
+
readonly prepareControl?: (sessionId: string) => Promise<void>;
|
|
68
|
+
readonly onControlReady?: (ready: boolean) => void;
|
|
69
|
+
readonly returnOptions?: Parameters<typeof useReturnToPage>[1];
|
|
70
|
+
}) => void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Two return signals closer together than this are one return. */
|
|
2
|
+
export declare const RETURN_MIN_GAP_MS = 2000;
|
|
3
|
+
export declare const useReturnToPage: (onReturn: () => void, options?: {
|
|
4
|
+
readonly minGapMs?: number;
|
|
5
|
+
/** Clock seam (§25). */
|
|
6
|
+
readonly nowMs?: () => number;
|
|
7
|
+
}) => void;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { ChatTransport, UIMessageChunk } from 'ai';
|
|
3
|
+
import { FirstResponseObservation, FirstResponseSample } from '../infrastructure/telemetry/first-response-timing.ts';
|
|
4
|
+
import { AUTH_EXPIRED_ERROR_PREFIX } from '../api/auth-errors.ts';
|
|
3
5
|
import { BelongUIMessage, WireStreamPart } from './belong-data-parts.ts';
|
|
4
6
|
declare const cancelRunResponseSchema: z.ZodObject<{
|
|
5
7
|
recalledMessages: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
@@ -22,9 +24,9 @@ export declare const choiceAnswerSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
22
24
|
export declare const choiceStateSchema: z.ZodEnum<{
|
|
23
25
|
cancelled: "cancelled";
|
|
24
26
|
pending: "pending";
|
|
25
|
-
detached: "detached";
|
|
26
27
|
dismissed: "dismissed";
|
|
27
28
|
answered: "answered";
|
|
29
|
+
detached: "detached";
|
|
28
30
|
}>;
|
|
29
31
|
/**
|
|
30
32
|
* The wire/stored part union. Exported so the history loader (chat.tsx) can
|
|
@@ -37,6 +39,14 @@ export declare const wireStreamPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
37
39
|
type: z.ZodLiteral<"text">;
|
|
38
40
|
id: z.ZodString;
|
|
39
41
|
text: z.ZodString;
|
|
42
|
+
responsePhase: z.ZodCatch<z.ZodOptional<z.ZodObject<{
|
|
43
|
+
phase: z.ZodEnum<{
|
|
44
|
+
acknowledgment: "acknowledgment";
|
|
45
|
+
main: "main";
|
|
46
|
+
}>;
|
|
47
|
+
sourceMessageIds: z.ZodArray<z.ZodString>;
|
|
48
|
+
replyKey: z.ZodOptional<z.ZodString>;
|
|
49
|
+
}, z.core.$strip>>>;
|
|
40
50
|
}, z.core.$strip>, z.ZodObject<{
|
|
41
51
|
type: z.ZodLiteral<"data-reasoning">;
|
|
42
52
|
id: z.ZodString;
|
|
@@ -250,6 +260,7 @@ export declare const wireStreamPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
250
260
|
count: z.ZodOptional<z.ZodNumber>;
|
|
251
261
|
}, z.core.$strip>>;
|
|
252
262
|
}, z.core.$strip>>;
|
|
263
|
+
weightedHundredths: z.ZodOptional<z.ZodNumber>;
|
|
253
264
|
}, z.core.$strip>;
|
|
254
265
|
}, z.core.$strip>, z.ZodObject<{
|
|
255
266
|
type: z.ZodLiteral<"data-choice-request">;
|
|
@@ -259,9 +270,9 @@ export declare const wireStreamPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
259
270
|
state: z.ZodEnum<{
|
|
260
271
|
cancelled: "cancelled";
|
|
261
272
|
pending: "pending";
|
|
262
|
-
detached: "detached";
|
|
263
273
|
dismissed: "dismissed";
|
|
264
274
|
answered: "answered";
|
|
275
|
+
detached: "detached";
|
|
265
276
|
}>;
|
|
266
277
|
questions: z.ZodArray<z.ZodObject<{
|
|
267
278
|
id: z.ZodString;
|
|
@@ -354,9 +365,9 @@ export declare const wireStreamPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
354
365
|
at: z.ZodString;
|
|
355
366
|
}, z.core.$strip>>>;
|
|
356
367
|
runway: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
368
|
+
long: "long";
|
|
357
369
|
quick: "quick";
|
|
358
370
|
normal: "normal";
|
|
359
|
-
long: "long";
|
|
360
371
|
}>>>;
|
|
361
372
|
}, z.core.$strip>;
|
|
362
373
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -367,15 +378,17 @@ export declare const wireStreamPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
367
378
|
why: z.ZodString;
|
|
368
379
|
criteria: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
369
380
|
runway: z.ZodOptional<z.ZodEnum<{
|
|
381
|
+
long: "long";
|
|
370
382
|
quick: "quick";
|
|
371
383
|
normal: "normal";
|
|
372
|
-
long: "long";
|
|
373
384
|
}>>;
|
|
374
385
|
}, z.core.$strip>;
|
|
375
386
|
}, z.core.$strip>], "type">;
|
|
376
|
-
/** A request was 401'd twice (once with a freshly re-read token)
|
|
377
|
-
*
|
|
378
|
-
|
|
387
|
+
/** A request was 401'd twice (once with a freshly re-read token), or no usable
|
|
388
|
+
* token could be had at all (`BelongAuthUnavailableError`): the host session is
|
|
389
|
+
* expired — the dock must surface re-auth, not retry forever. Defined by the
|
|
390
|
+
* request layer, which raises it too; re-exported here for chat.tsx. */
|
|
391
|
+
export { AUTH_EXPIRED_ERROR_PREFIX };
|
|
379
392
|
/** The SSE reconnect loop exhausted its attempt budget without the backend
|
|
380
393
|
* delivering a single event — the service is unreachable. */
|
|
381
394
|
export declare const BACKEND_UNAVAILABLE_ERROR_PREFIX = "backend_unavailable:";
|
|
@@ -434,6 +447,10 @@ export declare const RESUME_GRACE_MS = 120000;
|
|
|
434
447
|
* across tests in the same file otherwise). */
|
|
435
448
|
export declare const __resetLiveStreamRegistryForTest: () => void;
|
|
436
449
|
export type BelongChatTransportOptions = {
|
|
450
|
+
readonly firstResponseTiming?: {
|
|
451
|
+
readonly nowMs: () => number;
|
|
452
|
+
readonly report: (sample: FirstResponseSample) => void;
|
|
453
|
+
};
|
|
437
454
|
/** Belong cloud base URL, e.g. `http://localhost:8787`. */
|
|
438
455
|
readonly apiBaseUrl: string;
|
|
439
456
|
/**
|
|
@@ -469,6 +486,10 @@ export type BelongChatTransportOptions = {
|
|
|
469
486
|
readonly foregroundGeneration?: number;
|
|
470
487
|
};
|
|
471
488
|
export type StreamContext = {
|
|
489
|
+
textPhaseKey?: string;
|
|
490
|
+
firstResponseObservations?: (phase: NonNullable<Extract<WireStreamPart, {
|
|
491
|
+
type: "text";
|
|
492
|
+
}>["responsePhase"]>) => readonly FirstResponseObservation[];
|
|
472
493
|
modelActivity?: {
|
|
473
494
|
id: string;
|
|
474
495
|
stepIndex: number;
|
|
@@ -572,8 +593,17 @@ export declare class BelongChatTransport implements ChatTransport<BelongUIMessag
|
|
|
572
593
|
* unaccepted stop.
|
|
573
594
|
*/
|
|
574
595
|
stopSubagent: (runId: string, subagentId: string) => Promise<void>;
|
|
596
|
+
beginFirstResponse: (clientMessageId: string) => void;
|
|
597
|
+
cancelFirstResponse: (clientMessageId: string) => void;
|
|
598
|
+
acceptFirstResponse: (input: {
|
|
599
|
+
sessionId: string;
|
|
600
|
+
runId: string;
|
|
601
|
+
clientMessageId: string;
|
|
602
|
+
messageId: string;
|
|
603
|
+
idempotent: boolean;
|
|
604
|
+
}) => void;
|
|
605
|
+
observeFirstResponseRendered: (observation: FirstResponseObservation) => void;
|
|
575
606
|
sendMessages: ChatTransport<BelongUIMessage>["sendMessages"];
|
|
576
607
|
reconnectToStream: ChatTransport<BelongUIMessage>["reconnectToStream"];
|
|
577
608
|
}
|
|
578
609
|
export declare const wireToUiChunks: (part: WireStreamPart, ctx: StreamContext) => readonly UIMessageChunk[];
|
|
579
|
-
export {};
|
|
@@ -310,6 +310,11 @@ export type UsageData = {
|
|
|
310
310
|
readonly autoCompactThresholdChars: number;
|
|
311
311
|
/** The detailed context-window breakdown (own-loop runtimes only). */
|
|
312
312
|
readonly contextWindow?: ContextWindowData | undefined;
|
|
313
|
+
/**
|
|
314
|
+
* Plan 018 — the turn in WEIGHTED tokens, in hundredths: the one unit the
|
|
315
|
+
* dock shows users. Absent on a turn from a cloud that predates it.
|
|
316
|
+
*/
|
|
317
|
+
readonly weightedHundredths?: number | undefined;
|
|
313
318
|
};
|
|
314
319
|
/**
|
|
315
320
|
* Goal Mode M6 — a goal the agent OFFERED. Nothing exists on the backend
|
|
@@ -367,6 +372,11 @@ export type BelongUIMessage = UIMessage<BelongMessageMetadata, BelongDataParts>;
|
|
|
367
372
|
* chunks yet — the transport translates this into `UIMessageChunk`.
|
|
368
373
|
*/
|
|
369
374
|
export type WireTextPart = {
|
|
375
|
+
readonly responsePhase?: {
|
|
376
|
+
readonly phase: "acknowledgment" | "main";
|
|
377
|
+
readonly sourceMessageIds: readonly string[];
|
|
378
|
+
readonly replyKey?: string | undefined;
|
|
379
|
+
} | undefined;
|
|
370
380
|
readonly type: "text";
|
|
371
381
|
readonly id: string;
|
|
372
382
|
readonly text: string;
|
|
@@ -4,7 +4,7 @@ export declare const claimDispatch: (key: string) => boolean;
|
|
|
4
4
|
* Run `effect` once for `key` on this page — or, without a key, once for the
|
|
5
5
|
* component's lifetime (React 19 StrictMode double-invokes included).
|
|
6
6
|
*/
|
|
7
|
-
export declare const useDispatchOnce: (key: string | undefined, effect: () => void, deps: readonly unknown[]) => void;
|
|
7
|
+
export declare const useDispatchOnce: (key: string | undefined, effect: () => void, deps: readonly unknown[], canDispatch?: () => boolean) => void;
|
|
8
8
|
/** Where a dispatch card's one-shot call stands. */
|
|
9
9
|
export type DispatchStatus = "dispatching" | "running" | "ok" | "no_handler" | "failed" | "done";
|
|
10
10
|
/** What a dispatch card shows, remembered by the same key as its guard. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BelongMessagePart, PartRendererProps } from './ai-sdk-part-renderers.tsx';
|
|
2
|
+
import { FirstResponseObservation } from '../infrastructure/telemetry/first-response-timing.ts';
|
|
2
3
|
/**
|
|
3
4
|
* The parts a message is INDEXED from (spec deviation 16). File parts render as
|
|
4
5
|
* chips above the message and never reach a render group, and dropping one
|
|
@@ -10,7 +11,7 @@ import { BelongMessagePart, PartRendererProps } from './ai-sdk-part-renderers.ts
|
|
|
10
11
|
* is the same list.
|
|
11
12
|
*/
|
|
12
13
|
export declare const indexableMessageParts: (parts: readonly BelongMessagePart[]) => readonly BelongMessagePart[];
|
|
13
|
-
export declare const MessageParts: ({ parts, streaming, historical, onContinueConnector, onExecutePlan, onFollowContinuation, partProps, }: {
|
|
14
|
+
export declare const MessageParts: ({ parts, streaming, historical, onContinueConnector, onExecutePlan, onFollowContinuation, partProps, onFirstResponseRendered, }: {
|
|
14
15
|
/** The message's parts, file parts already removed (they render as chips). */
|
|
15
16
|
readonly parts: readonly BelongMessagePart[];
|
|
16
17
|
/** This message is the one a run is streaming into right now. */
|
|
@@ -39,4 +40,5 @@ export declare const MessageParts: ({ parts, streaming, historical, onContinueCo
|
|
|
39
40
|
* the named props still wins. Absent = no goal wiring (stories, tests).
|
|
40
41
|
*/
|
|
41
42
|
readonly partProps?: ((part: BelongMessagePart) => Partial<PartRendererProps>) | undefined;
|
|
43
|
+
readonly onFirstResponseRendered?: ((observation: FirstResponseObservation) => void) | undefined;
|
|
42
44
|
}) => import("react").JSX.Element;
|
|
@@ -15,6 +15,12 @@ declare const queuedMessageOutboxEntrySchema: z.ZodObject<{
|
|
|
15
15
|
runtime: z.ZodOptional<z.ZodString>;
|
|
16
16
|
llmProvider: z.ZodOptional<z.ZodString>;
|
|
17
17
|
llmModel: z.ZodOptional<z.ZodString>;
|
|
18
|
+
responseMode: z.ZodOptional<z.ZodEnum<{
|
|
19
|
+
balanced: "balanced";
|
|
20
|
+
fast: "fast";
|
|
21
|
+
smart: "smart";
|
|
22
|
+
}>>;
|
|
23
|
+
pageLabel: z.ZodOptional<z.ZodString>;
|
|
18
24
|
workspaceExternalId: z.ZodOptional<z.ZodString>;
|
|
19
25
|
}, z.core.$strip>;
|
|
20
26
|
export type QueuedMessageOutboxEntry = Readonly<z.infer<typeof queuedMessageOutboxEntrySchema>>;
|
|
@@ -30,6 +30,13 @@ export type SessionUsageSummary = {
|
|
|
30
30
|
* panel then falls back to the session-usage view.
|
|
31
31
|
*/
|
|
32
32
|
readonly contextWindow: ContextWindowData | null;
|
|
33
|
+
/**
|
|
34
|
+
* Plan 018 — the chat in WEIGHTED tokens, in hundredths: the one figure the
|
|
35
|
+
* panel shows users (round once with `Math.round(x / 100)`). `null` when any
|
|
36
|
+
* turn folded here, or the history baseline, predates the field — an honest
|
|
37
|
+
* "unknown" rather than a total that silently skips turns.
|
|
38
|
+
*/
|
|
39
|
+
readonly totalWeightedHundredths: number | null;
|
|
33
40
|
};
|
|
34
41
|
/** The chat's usage total as of a history read (the ledger's sums). */
|
|
35
42
|
export type SessionUsageBaseline = {
|
|
@@ -39,6 +46,8 @@ export type SessionUsageBaseline = {
|
|
|
39
46
|
readonly totalCacheReadInputTokens: number;
|
|
40
47
|
readonly totalCacheWriteInputTokens: number;
|
|
41
48
|
readonly turns: number;
|
|
49
|
+
/** Plan 018 — absent from a cloud that predates weighted tokens. */
|
|
50
|
+
readonly totalWeightedHundredths?: number | undefined;
|
|
42
51
|
};
|
|
43
52
|
export declare const selectSessionUsage: (messages: readonly BelongUIMessage[],
|
|
44
53
|
/**
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type SessionControl = {
|
|
2
|
+
readonly readOnly: boolean;
|
|
3
|
+
/** Read live ownership again at the moment a side effect starts. */
|
|
4
|
+
readonly canControl: () => boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare const SessionControlContext: import('react').Context<SessionControl>;
|
|
7
|
+
export declare const useSessionControl: () => SessionControl;
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
* DTOs. Kept as an explicit local mirror (not inferred from AppType) so the CSV
|
|
7
7
|
* column contract is readable in one place.
|
|
8
8
|
*
|
|
9
|
+
* Plan 018 — tokens appear in WEIGHTED tokens only, the one unit users see; the
|
|
10
|
+
* raw input / output split is no longer exported. The weighted fields are
|
|
11
|
+
* optional here because an older cloud does not send them (an empty cell).
|
|
12
|
+
*
|
|
9
13
|
* RFC-4180: CRLF line breaks, header first, a field is quoted when it contains
|
|
10
14
|
* `"`, `,`, CR or LF; interior quotes are doubled. CSV-injection guard: a text
|
|
11
15
|
* field starting with = + - @ is prefixed with a single quote before quoting.
|
|
@@ -13,14 +17,10 @@
|
|
|
13
17
|
export type SessionStatsTurn = {
|
|
14
18
|
readonly turn: number;
|
|
15
19
|
readonly at: string;
|
|
16
|
-
readonly
|
|
17
|
-
readonly outputTokens: number;
|
|
18
|
-
readonly totalTokens: number;
|
|
20
|
+
readonly weightedTokens?: number;
|
|
19
21
|
};
|
|
20
22
|
export type SessionStatsDetail = {
|
|
21
|
-
readonly
|
|
22
|
-
readonly totalOutputTokens: number;
|
|
23
|
-
readonly totalTokens: number;
|
|
23
|
+
readonly totalWeightedTokens?: number;
|
|
24
24
|
readonly turns: number;
|
|
25
25
|
readonly runningMs: number;
|
|
26
26
|
readonly toolCalls: number;
|
|
@@ -32,9 +32,7 @@ export type SessionStatsSummaryRow = {
|
|
|
32
32
|
readonly title: string | null;
|
|
33
33
|
readonly createdAt: string;
|
|
34
34
|
readonly updatedAt: string;
|
|
35
|
-
readonly
|
|
36
|
-
readonly totalOutputTokens: number;
|
|
37
|
-
readonly totalTokens: number;
|
|
35
|
+
readonly totalWeightedTokens?: number;
|
|
38
36
|
readonly turns: number;
|
|
39
37
|
readonly runningMs: number;
|
|
40
38
|
readonly toolCalls: number;
|
package/dist/types/public.d.ts
CHANGED
|
@@ -114,17 +114,17 @@ export type PartialBelongTheme = {
|
|
|
114
114
|
/** Per-locale welcome-copy override (BEL-135). */
|
|
115
115
|
readonly copy?: DockCopyOverride;
|
|
116
116
|
};
|
|
117
|
-
/**
|
|
118
|
-
export type PresetName = "belong" | "simetrik" | "custom";
|
|
117
|
+
/** Theme styles. `tenant` restores the latest published tenant default. */
|
|
118
|
+
export type PresetName = "tenant" | "belong" | "simetrik" | "custom";
|
|
119
119
|
/** UI languages the dock ships. `setLocale` / `init({ locale })` accept these. */
|
|
120
120
|
export type BelongLocale = "en" | "es" | "pt" | "it";
|
|
121
121
|
export type BelongInitInput = {
|
|
122
122
|
/** Belong cloud base URL, e.g. `https://api.belong.host` or `http://localhost:8787`. */
|
|
123
123
|
readonly apiBaseUrl: string;
|
|
124
124
|
/**
|
|
125
|
-
* Public tenant slug (
|
|
125
|
+
* Public tenant ID or slug (multi-tenant deployments). Used for
|
|
126
126
|
* boot-time, unauthenticated surfaces only — the theme fetch adds
|
|
127
|
-
* `?tenant=<slug>` and every request carries it as `X-Belong-Tenant`
|
|
127
|
+
* `?tenant=<id-or-slug>` and every request carries it as `X-Belong-Tenant`
|
|
128
128
|
* (observability). Authenticated routes derive the tenant from the JWT;
|
|
129
129
|
* this value can never escalate. Omit on single-tenant deployments.
|
|
130
130
|
*/
|
|
@@ -166,9 +166,11 @@ export type BelongInitInput = {
|
|
|
166
166
|
};
|
|
167
167
|
/**
|
|
168
168
|
* What page the user is on, shown as "Looking at ‹label›" before the first
|
|
169
|
-
* message
|
|
169
|
+
* message and in the composer's page chip, and SENT with every message so
|
|
170
|
+
* the agent can resolve "this page" (the label only, never the page's
|
|
171
|
+
* contents). Omit `label` to use the browser tab title (`document.title`,
|
|
170
172
|
* tracked live so SPA navigation updates the line); pass
|
|
171
|
-
* `fromDocumentTitle: false` to show nothing unless a label is given.
|
|
173
|
+
* `fromDocumentTitle: false` to show and send nothing unless a label is given.
|
|
172
174
|
* A re-`init` replaces this config wholesale: omitting `pageContext` clears
|
|
173
175
|
* a previously seeded `label` and restores the tab-title fallback.
|
|
174
176
|
* `belong.setPageContext` overrides both at runtime and SURVIVES a later
|
|
@@ -182,7 +184,12 @@ export type BelongInitInput = {
|
|
|
182
184
|
readonly theme?: PartialBelongTheme;
|
|
183
185
|
/** Optional voice config (push-to-talk + read-aloud). */
|
|
184
186
|
readonly voice?: {
|
|
185
|
-
/**
|
|
187
|
+
/**
|
|
188
|
+
* Default hold-to-talk key as a `KeyboardEvent.code`: one of
|
|
189
|
+
* `"ControlRight"`, `"ControlLeft"`, `"AltRight"`, `"AltLeft"`, `"F2"`,
|
|
190
|
+
* `"F8"`, `"F9"`; any other code is ignored. Default: none — each user
|
|
191
|
+
* picks a key (or keeps it off) in Settings → Voice, and their choice wins.
|
|
192
|
+
*/
|
|
186
193
|
readonly pushToTalkKey?: string;
|
|
187
194
|
/** Auto-read assistant replies aloud (ElevenLabs TTS). Default `true`. */
|
|
188
195
|
readonly autoplayTts?: boolean;
|
|
@@ -324,8 +331,8 @@ export type BelongGlobal = {
|
|
|
324
331
|
readonly displayName?: string | null;
|
|
325
332
|
} | null) => void;
|
|
326
333
|
/**
|
|
327
|
-
* Set the page label shown
|
|
328
|
-
* `init({ pageContext })` and the tab title). `null` drops the override.
|
|
334
|
+
* Set the page label shown in the dock and sent with each message (wins
|
|
335
|
+
* over `init({ pageContext })` and the tab title). `null` drops the override.
|
|
329
336
|
*/
|
|
330
337
|
readonly setPageContext: (label: string | null) => void;
|
|
331
338
|
readonly setTheme: (theme: PartialBelongTheme) => void;
|