@belonguniverseai/react-sdk 0.6.21 → 0.6.22
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 +69 -0
- package/dist/api/client.d.ts +667 -4
- package/dist/api/goals.d.ts +179 -0
- package/dist/api/issue-reports.d.ts +13 -0
- package/dist/api/query-keys.d.ts +18 -0
- package/dist/api/report-client-error.d.ts +3 -0
- package/dist/api/retry-fetch.d.ts +19 -0
- package/dist/api/skill-library.d.ts +100 -0
- package/dist/api/skills.d.ts +3 -1
- package/dist/app/dock-outlet.d.ts +15 -5
- package/dist/browser/allowed-ops.d.ts +18 -0
- package/dist/browser/host-mcp.d.ts +31 -0
- package/dist/component/{abnfDiagram-N423BO3Z-DZRUOUZQ.js → abnfDiagram-N423BO3Z-D4mVRMw9.js} +4 -4
- package/dist/component/{arc-B4biduil.js → arc-GBp6w3tF.js} +2 -2
- package/dist/component/{architectureDiagram-T3A2C74G-q8voStNN.js → architectureDiagram-T3A2C74G-Cxm-USYQ.js} +3 -3
- package/dist/component/{blockDiagram-VBNYF7ZC-C0TDyTgw.js → blockDiagram-VBNYF7ZC-BAiLpxJf.js} +4 -4
- package/dist/component/{c4Diagram-5PPSVZJV-rxRyd6rh.js → c4Diagram-5PPSVZJV-Sy6sLJOj.js} +3 -3
- package/dist/component/{channel-CUruDJSx.js → channel-DPbaAkCI.js} +2 -2
- package/dist/component/{chunk-2GRJ4B5K-Kff5Fvbi.js → chunk-2GRJ4B5K-8r8YJzCc.js} +2 -2
- package/dist/component/{chunk-2Q5K7J3B-BT3ZD31a.js → chunk-2Q5K7J3B-RZqny7-R.js} +2 -2
- package/dist/component/{chunk-5RXB4S5H-CYZ36tQD.js → chunk-5RXB4S5H-QFCY9Dtl.js} +5 -5
- package/dist/component/{chunk-5VM5RSS4-BweQRk7u.js → chunk-5VM5RSS4-BG8q5ODa.js} +2 -2
- package/dist/component/{chunk-6Q2QTUOP-DHcoXRhe.js → chunk-6Q2QTUOP-D6ec2nI7.js} +2 -2
- package/dist/component/{chunk-GF5L2VYU-DtE5ljCc.js → chunk-GF5L2VYU-D7yROYf0.js} +6 -6
- package/dist/component/{chunk-JWPE2WC7-ClHq4gN2.js → chunk-JWPE2WC7-CmGlHqne.js} +2 -2
- package/dist/component/{chunk-KBJHAD2P-BeCfHf5W.js → chunk-KBJHAD2P-W03s7swc.js} +2 -2
- package/dist/component/{chunk-RYQCIY6F-CuAngwHt.js → chunk-RYQCIY6F-D0oyMUJ7.js} +2 -2
- package/dist/component/{chunk-XXDRQBXY-D9c0CJyR.js → chunk-XXDRQBXY-D4s0eyp4.js} +2 -2
- package/dist/component/{classDiagram-JCYQIIEL-DdzIbKj1.js → classDiagram-JCYQIIEL-DwNAC2XG.js} +3 -3
- package/dist/component/{classDiagram-v2-OCEON4UE-DdzIbKj1.js → classDiagram-v2-OCEON4UE-DwNAC2XG.js} +3 -3
- package/dist/component/{cose-bilkent-JH36ORCC-hME9BYGm.js → cose-bilkent-JH36ORCC-DhGvXDdi.js} +2 -2
- package/dist/component/{cynefinDiagram-MW4NZA55-BiceKBPh.js → cynefinDiagram-MW4NZA55-BCUeX7pB.js} +3 -3
- package/dist/component/{dagre-VZM6K2ZE-DiPOLAUX.js → dagre-VZM6K2ZE-DWofHoga.js} +3 -3
- package/dist/component/{diagram-7IWD3JNH-BSDWgxjs.js → diagram-7IWD3JNH-DjCFF_Dr.js} +4 -4
- package/dist/component/{diagram-B4RE2ZJO-BdpGOPaT.js → diagram-B4RE2ZJO-CSovrpFW.js} +3 -3
- package/dist/component/{diagram-LBJQPF4R-B0V6_5ih.js → diagram-LBJQPF4R-Cgpae-sR.js} +3 -3
- package/dist/component/{diagram-Q27KOJAE-CYDb40TJ.js → diagram-Q27KOJAE-DikMPfLU.js} +4 -4
- package/dist/component/{diagram-UB23O5K3-DgwjRdl5.js → diagram-UB23O5K3-sQU6rZbO.js} +3 -3
- package/dist/component/{ebnfDiagram-BXEA7PRR-D-C7SWec.js → ebnfDiagram-BXEA7PRR-B9t8-G8R.js} +4 -4
- package/dist/component/{erDiagram-JOGREHBK-DLJCjcXM.js → erDiagram-JOGREHBK-DKg1HhSl.js} +5 -5
- package/dist/component/{flowDiagram-UKHOOZJN-BZfBucKB.js → flowDiagram-UKHOOZJN-BO8jpT1D.js} +7 -7
- package/dist/component/{ganttDiagram-PKOTCBZU-CxTHmusv.js → ganttDiagram-PKOTCBZU-BPXYyB9Q.js} +3 -3
- package/dist/component/{gitGraphDiagram-DS77QQ5N-B_dWXxMf.js → gitGraphDiagram-DS77QQ5N-BjVLFBUS.js} +4 -4
- package/dist/component/{highlighted-body-OFNGDK62-CQ1ZdhQ-.js → highlighted-body-OFNGDK62-BKot66c3.js} +2 -2
- package/dist/component/index.js +2 -2
- package/dist/component/{infoDiagram-6WML65LV-P4GO-aVw.js → infoDiagram-6WML65LV-BkAC5Bwv.js} +2 -2
- package/dist/component/{ishikawaDiagram-WSZJBQD7-BMXMrxKI.js → ishikawaDiagram-WSZJBQD7-oplkIs_t.js} +2 -2
- package/dist/component/{journeyDiagram-NVQOT4AX-DPdTmxkF.js → journeyDiagram-NVQOT4AX-CuliMCSv.js} +5 -5
- package/dist/component/{kanban-definition-27J2QSJJ-sYw64NrE.js → kanban-definition-27J2QSJJ-DdzOdEiL.js} +3 -3
- package/dist/component/{linear-DYjDg3gl.js → linear-zZDwdGmK.js} +2 -2
- package/dist/component/{mermaid-GHXKKRXX-DfdCmrs3.js → mermaid-GHXKKRXX-aX5umm-y.js} +46587 -40943
- package/dist/component/{mindmap-definition-FAOFIHXS-UkAbrucA.js → mindmap-definition-FAOFIHXS-DD2HF9oE.js} +4 -4
- package/dist/component/{pegDiagram-VL7TDLO6-BGab1it6.js → pegDiagram-VL7TDLO6-DyiDl9bF.js} +4 -4
- package/dist/component/{pieDiagram-7S7Q4E2Y-BnY70Pr-.js → pieDiagram-7S7Q4E2Y-DflxKS_B.js} +4 -4
- package/dist/component/{quadrantDiagram-CIZ2JOQS-Cv1bjdQb.js → quadrantDiagram-CIZ2JOQS-nwwayVOP.js} +3 -3
- package/dist/component/{railroadDiagram-AXF67PYL-DJhLbGB_.js → railroadDiagram-AXF67PYL-BTtD2eN9.js} +4 -4
- package/dist/component/{requirementDiagram-LRYGKXZP-CLW3CgbU.js → requirementDiagram-LRYGKXZP-B37q1LKL.js} +4 -4
- package/dist/component/{sankeyDiagram-W5VNT64P-vnapx0yf.js → sankeyDiagram-W5VNT64P-zY0W9eje.js} +2 -2
- package/dist/component/{sequenceDiagram-SI44F4Z6-I43iQsY0.js → sequenceDiagram-SI44F4Z6-CmQiqB8F.js} +4 -4
- package/dist/component/{sizeCapture-X5ZJPWSS-D9LGwwwC.js → sizeCapture-X5ZJPWSS-dF3FvIT8.js} +2 -2
- package/dist/component/snapdom-DkzCA8S0.js +7061 -0
- package/dist/component/{stateDiagram-OKZ733FA-BXejMYGk.js → stateDiagram-OKZ733FA-CX61F3L0.js} +3 -3
- package/dist/component/{stateDiagram-v2-UEYNNEHI-BP05TJSl.js → stateDiagram-v2-UEYNNEHI-DnFZhhu3.js} +3 -3
- package/dist/component/{swimlanes-SLNWSIFB-CfmDVYhs.js → swimlanes-SLNWSIFB-CX9XGBvw.js} +4 -4
- package/dist/component/{swimlanesDiagram-ULZ7WXOC-DfjQBUfV.js → swimlanesDiagram-ULZ7WXOC-Bqkgx7qk.js} +3 -3
- package/dist/component/{timeline-definition-Z64GVDOM-C0BwzTs3.js → timeline-definition-Z64GVDOM-BUX4OSm1.js} +3 -3
- package/dist/component/{vennDiagram-T6HMQDX7-CRf8sGBL.js → vennDiagram-T6HMQDX7-BpVOq4Rh.js} +2 -2
- package/dist/component/{wardleyDiagram-T6FBY63Y-C2h7TQ4a.js → wardleyDiagram-T6FBY63Y-BUDGa8Mv.js} +3 -3
- package/dist/component/{xychartDiagram-ELKLHX3M-CBcAwmdF.js → xychartDiagram-ELKLHX3M-FIA_LnIu.js} +3 -3
- package/dist/components/embed/EmbedComposer.d.ts +11 -1
- package/dist/components/embed/EmbedHeader.d.ts +7 -1
- package/dist/components/embed/EmbedRail.d.ts +18 -2
- package/dist/components/embed/GoalActions.d.ts +15 -0
- package/dist/components/embed/GoalBadge.d.ts +17 -0
- package/dist/components/embed/GoalClearDialog.d.ts +6 -0
- package/dist/components/embed/GoalClearedLine.d.ts +3 -0
- package/dist/components/embed/GoalCompletionCard.d.ts +12 -0
- package/dist/components/embed/GoalComposeSheet.d.ts +19 -0
- package/dist/components/embed/GoalProposalCard.d.ts +29 -0
- package/dist/components/embed/GoalRailView.d.ts +15 -0
- package/dist/components/embed/GoalRefusalCard.d.ts +22 -0
- package/dist/components/embed/GoalSetCard.d.ts +5 -0
- package/dist/components/embed/GoalSnoozeMenu.d.ts +14 -0
- package/dist/components/embed/GoalStatusRow.d.ts +6 -0
- package/dist/components/embed/GoalTimeline.d.ts +6 -0
- package/dist/components/embed/MobileNavBar.d.ts +5 -1
- package/dist/components/embed/QuestionCard.d.ts +12 -1
- package/dist/components/embed/ScheduleNotices.d.ts +23 -0
- package/dist/components/embed/SentAsGoalTag.d.ts +1 -0
- package/dist/components/embed/SubagentsPaneBody.d.ts +3 -0
- package/dist/components/embed/rail-flags.d.ts +13 -0
- package/dist/components/feedback/IssueReportController.d.ts +1 -0
- package/dist/components/feedback/IssueReportDialog.d.ts +6 -0
- package/dist/components/skills/ConfirmDeleteSkillDialog.d.ts +9 -0
- package/dist/components/skills/SkillLibraryToolSync.d.ts +4 -0
- package/dist/components/skills/SkillsListSurface.d.ts +26 -0
- package/dist/components/skills/UploadSkillDialog.d.ts +32 -0
- package/dist/components/skills/skill-archive-file.d.ts +15 -0
- package/dist/embed/client-error-log.d.ts +72 -0
- package/dist/embed/dock-open-request.d.ts +32 -0
- package/dist/embed/dock-state.d.ts +1 -1
- package/dist/embed/goal-actions-model.d.ts +9 -0
- package/dist/embed/goal-cap-notice.d.ts +36 -0
- package/dist/embed/goal-deep-link.d.ts +24 -0
- package/dist/embed/goal-edit-command.d.ts +25 -0
- package/dist/embed/goal-journal.d.ts +53 -0
- package/dist/embed/goal-live-status.d.ts +2 -0
- package/dist/embed/goal-plain-units.d.ts +35 -0
- package/dist/embed/goal-progress.d.ts +15 -0
- package/dist/embed/goal-proposal-dismissal.d.ts +11 -0
- package/dist/embed/goal-resume-time.d.ts +22 -0
- package/dist/embed/goal-row-model.d.ts +27 -0
- package/dist/embed/goal-runway.d.ts +5 -0
- package/dist/embed/goal-schedule-handoff.d.ts +12 -0
- package/dist/embed/goal-status-label.d.ts +3 -0
- package/dist/embed/goal-time-usage.d.ts +19 -0
- package/dist/embed/issue-report-bus.d.ts +14 -0
- package/dist/embed/issue-report-open.d.ts +8 -0
- package/dist/embed/issue-report.d.ts +41 -0
- package/dist/embed/screen-capture.d.ts +74 -0
- package/dist/embed/slash-commands.d.ts +24 -0
- package/dist/embed/task-schedule-command.d.ts +7 -0
- package/dist/i18n/messages/en.d.ts +372 -8
- package/dist/i18n/messages/surfaces/feedback.d.ts +84 -0
- package/dist/i18n/messages/surfaces/header.d.ts +16 -0
- package/dist/i18n/messages/surfaces/skills.d.ts +216 -0
- package/dist/i18n/messages/surfaces/stream.d.ts +152 -29
- package/dist/i18n/messages/surfaces/workspace.d.ts +20 -0
- package/dist/public-api.d.ts +1 -1
- package/dist/routes/chat/part-renderer-extra-props.d.ts +43 -0
- package/dist/routes/chat/use-goal-receipt.d.ts +37 -0
- package/dist/routes/chat/use-host-draft-request.d.ts +2 -0
- package/dist/routes/chat/use-session-goal.d.ts +226 -0
- package/dist/routes/chat.d.ts +10 -1
- package/dist/routes/goal.d.ts +1 -0
- package/dist/routes/skills.d.ts +2 -0
- package/dist/stream/activity-items.d.ts +25 -0
- package/dist/stream/ai-sdk-part-renderers.d.ts +64 -25
- package/dist/stream/belong-chat-transport.d.ts +142 -2
- package/dist/stream/belong-data-parts.d.ts +48 -4
- package/dist/stream/goal-store.d.ts +43 -0
- package/dist/stream/message-metadata.d.ts +1 -0
- package/dist/stream/message-parts.d.ts +42 -0
- package/dist/stream/select-goal-set-part-id.d.ts +2 -0
- package/dist/stream/select-latest-goal.d.ts +13 -0
- package/dist/stream/subagent-controls-store.d.ts +20 -0
- package/dist/stream/subagent-lanes-model.d.ts +175 -0
- package/dist/stream/subagent-lanes.d.ts +89 -0
- package/dist/stream/use-publish-subagent-controls.d.ts +11 -0
- package/dist/stream/workspace-focus-store.d.ts +7 -1
- package/dist/test/render.d.ts +18 -1
- package/dist/test/subagent-fixtures.d.ts +24 -0
- package/dist/types/public.d.ts +54 -1
- package/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { UIMessage } from 'ai';
|
|
2
2
|
import { BelongMessageMetadata } from './message-metadata.ts';
|
|
3
|
+
import { GoalView } from '../api/goals.ts';
|
|
4
|
+
import { GoalRunwayPreset } from '../embed/goal-runway.ts';
|
|
3
5
|
/**
|
|
4
6
|
* F2 — per-step execution status. Optional: absent means `pending`
|
|
5
7
|
* (back-compat with plans proposed before F2 and the initial propose). The
|
|
@@ -137,8 +139,8 @@ export type ToolCallData = {
|
|
|
137
139
|
/**
|
|
138
140
|
* BEL-199 — the `data-subagent` part id this call ran INSIDE. Absent on every
|
|
139
141
|
* main-loop call (and on every part emitted before BEL-199). The expanded
|
|
140
|
-
* activity group
|
|
141
|
-
*
|
|
142
|
+
* activity group nests a matching item under that subagent's lane when the
|
|
143
|
+
* lane is in the same group; otherwise it stays a flat item (§41).
|
|
142
144
|
*/
|
|
143
145
|
readonly subagentId?: string | undefined;
|
|
144
146
|
};
|
|
@@ -153,8 +155,15 @@ export type ToolCallData = {
|
|
|
153
155
|
* surfacing it would read as breakage. Nothing about it is ever red.
|
|
154
156
|
*/
|
|
155
157
|
export type SubagentState = "running" | "finished" | "failed";
|
|
158
|
+
/**
|
|
159
|
+
* Spec 2026-09-16 §1.2 — how a subagent ended. An optional FIELD beside
|
|
160
|
+
* `state` (never new `state` values: older docks strict-parse that enum). The
|
|
161
|
+
* dock parses it leniently, so a future value degrades to "absent" and the
|
|
162
|
+
* outcome is derived from `state` / `timedOut` instead.
|
|
163
|
+
*/
|
|
164
|
+
export type SubagentOutcome = "ok" | "error" | "timeout" | "stopped" | "stalled" | "interrupted";
|
|
156
165
|
export type SubagentData = {
|
|
157
|
-
/** Registry name, e.g. "general-purpose"
|
|
166
|
+
/** Registry name, e.g. "general-purpose". Operator vocabulary: never rendered (§42). */
|
|
158
167
|
readonly name: string;
|
|
159
168
|
/** The model's own task label; this is what the line shows. */
|
|
160
169
|
readonly description: string;
|
|
@@ -169,6 +178,23 @@ export type SubagentData = {
|
|
|
169
178
|
* server prose.
|
|
170
179
|
*/
|
|
171
180
|
readonly timedOut?: boolean | undefined;
|
|
181
|
+
readonly outcome?: SubagentOutcome | undefined;
|
|
182
|
+
/** Waiting for a concurrency slot; re-emitted without it (same id) once started. */
|
|
183
|
+
readonly queued?: boolean | undefined;
|
|
184
|
+
/** ISO instant the subagent actually started; the elapsed timer's origin (§41). */
|
|
185
|
+
readonly startedAt?: string | undefined;
|
|
186
|
+
/** Integer ms from `startedAt` to finish; 0 when it never left the queue. */
|
|
187
|
+
readonly durationMs?: number | undefined;
|
|
188
|
+
/** Operator-only (insights). The dock never renders token counts (§42). */
|
|
189
|
+
readonly tokensCount?: number | undefined;
|
|
190
|
+
/** Subagents launched together share one wave id. */
|
|
191
|
+
readonly waveId?: string | undefined;
|
|
192
|
+
/** Model-provided name for the wave's work, e.g. "Auditing datasets". */
|
|
193
|
+
readonly groupLabel?: string | undefined;
|
|
194
|
+
/** The single plan step in progress at launch — a wave-label fallback. */
|
|
195
|
+
readonly planStepId?: string | undefined;
|
|
196
|
+
/** Only the own loop can stop a subagent; gates the dock's Stop. Never set once finished. */
|
|
197
|
+
readonly stoppable?: boolean | undefined;
|
|
172
198
|
};
|
|
173
199
|
export type SandboxCommandData = {
|
|
174
200
|
readonly state: SandboxCommandState;
|
|
@@ -267,6 +293,20 @@ export type UsageData = {
|
|
|
267
293
|
/** The detailed context-window breakdown (own-loop runtimes only). */
|
|
268
294
|
readonly contextWindow?: ContextWindowData | undefined;
|
|
269
295
|
};
|
|
296
|
+
/**
|
|
297
|
+
* Goal Mode M6 — a goal the agent OFFERED. Nothing exists on the backend
|
|
298
|
+
* until the user confirms; this part is the offer itself.
|
|
299
|
+
*
|
|
300
|
+
* Task 17 — `criteria`/`runway` are optional so a pre-Task-17 stored part
|
|
301
|
+
* still parses (§4): when present, Start skips the interview the same way
|
|
302
|
+
* the compose sheet's "Done when…" field does.
|
|
303
|
+
*/
|
|
304
|
+
export type GoalProposalData = {
|
|
305
|
+
readonly objective: string;
|
|
306
|
+
readonly why: string;
|
|
307
|
+
readonly criteria?: readonly string[] | undefined;
|
|
308
|
+
readonly runway?: GoalRunwayPreset | undefined;
|
|
309
|
+
};
|
|
270
310
|
/**
|
|
271
311
|
* Single source of truth for Belong's custom data parts. The record
|
|
272
312
|
* keys (`reasoning`, `plan`, …) become the part-type suffix:
|
|
@@ -289,6 +329,10 @@ export type BelongDataParts = {
|
|
|
289
329
|
status: StatusData;
|
|
290
330
|
/** F3 — context/cost meter. Additive; absent on old sessions. */
|
|
291
331
|
usage: UsageData;
|
|
332
|
+
/** Goal Mode M1 — the session's live long-running-goal snapshot. */
|
|
333
|
+
goal: GoalView;
|
|
334
|
+
/** Goal Mode M6 — a goal the agent offered via `propose_goal`. */
|
|
335
|
+
"goal-proposal": GoalProposalData;
|
|
292
336
|
};
|
|
293
337
|
/**
|
|
294
338
|
* The concrete `UIMessage` shape the chat surface and transport speak.
|
|
@@ -313,5 +357,5 @@ export type WireDataPart<NAME extends keyof BelongDataParts> = {
|
|
|
313
357
|
readonly id: string;
|
|
314
358
|
readonly data: BelongDataParts[NAME];
|
|
315
359
|
};
|
|
316
|
-
export type WireStreamPart = WireTextPart | WireDataPart<"reasoning"> | WireDataPart<"plan"> | WireDataPart<"approval-request"> | WireDataPart<"choice-request"> | WireDataPart<"tool-call"> | WireDataPart<"subagent"> | WireDataPart<"sandbox-command"> | WireDataPart<"ui-action"> | WireDataPart<"cli-reconnect"> | WireDataPart<"navigation"> | WireDataPart<"artifact"> | WireDataPart<"status"> | WireDataPart<"usage">;
|
|
360
|
+
export type WireStreamPart = WireTextPart | WireDataPart<"reasoning"> | WireDataPart<"plan"> | WireDataPart<"approval-request"> | WireDataPart<"choice-request"> | WireDataPart<"tool-call"> | WireDataPart<"subagent"> | WireDataPart<"sandbox-command"> | WireDataPart<"ui-action"> | WireDataPart<"cli-reconnect"> | WireDataPart<"navigation"> | WireDataPart<"artifact"> | WireDataPart<"status"> | WireDataPart<"usage"> | WireDataPart<"goal"> | WireDataPart<"goal-proposal">;
|
|
317
361
|
export type WireStreamPartType = WireStreamPart["type"];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { GoalView } from '../api/goals.ts';
|
|
2
|
+
export type GoalState = {
|
|
3
|
+
readonly sessionId: string;
|
|
4
|
+
readonly goal: GoalView;
|
|
5
|
+
} | null;
|
|
6
|
+
/**
|
|
7
|
+
* Whether `next` should replace `current` in the store. Accepts when: the
|
|
8
|
+
* store is empty; `next` is `null` (an explicit clear always wins); the
|
|
9
|
+
* session changed; or `next`'s goal is strictly newer by `updatedAt`.
|
|
10
|
+
*
|
|
11
|
+
* On an EQUAL `updatedAt` several tie-breaks still accept: a higher
|
|
12
|
+
* `turnsUsed`, a different `status`, a different `objective`/`maxTurns`/
|
|
13
|
+
* `tokenBudget`, or a different `tokensUsed`/`activeSeconds`. Postgres stamps
|
|
14
|
+
* `updated_at` per write and the dock's two writers can observe two different
|
|
15
|
+
* rows carrying the same timestamp (a goal turn and its status flip inside
|
|
16
|
+
* one drain iteration, or a timestamp truncated to the same millisecond on
|
|
17
|
+
* the wire); rejecting those pinned the pill to the older of two genuinely
|
|
18
|
+
* different states. The objective/turns/budget tie-break covers `/goal edit`:
|
|
19
|
+
* an edit bumps `updatedAt` but leaves `status` and `turnsUsed` untouched, so
|
|
20
|
+
* without it a same-millisecond edit would be indistinguishable from a no-op
|
|
21
|
+
* and get dropped. The tokensUsed/activeSeconds tie-break covers M3
|
|
22
|
+
* accounting (`recordTurnOutcome`): it writes counters on every turn without
|
|
23
|
+
* necessarily changing `status` or `turnsUsed` (a mid-drain accounting write
|
|
24
|
+
* followed by a same-millisecond read). Only a view equal on all nine —
|
|
25
|
+
* timestamp, turns, status, objective, maxTurns, tokenBudget, tokensUsed,
|
|
26
|
+
* activeSeconds and resumeAt — is rejected as a no-op.
|
|
27
|
+
*
|
|
28
|
+
* The resumeAt tie-break covers M5: a goal deferred again to a NEW time
|
|
29
|
+
* (the backoff doubling) changes neither `status` nor `turnsUsed`, so a
|
|
30
|
+
* same-millisecond republish would otherwise pin the pill to the old time.
|
|
31
|
+
*
|
|
32
|
+
* The journal-length tie-break covers M6: a repo-backed view that appended a
|
|
33
|
+
* History entry (a progress note, a status transition already covered
|
|
34
|
+
* above) without otherwise changing any of the other tie-break fields would
|
|
35
|
+
* be a no-op by the old rule, dropping the fresher History off the panel.
|
|
36
|
+
*/
|
|
37
|
+
export declare const isNewerGoalState: (current: GoalState, next: GoalState) => boolean;
|
|
38
|
+
export declare const publishGoalState: (next: GoalState) => void;
|
|
39
|
+
export declare const peekGoalState: () => GoalState;
|
|
40
|
+
export declare const subscribeGoalState: (listener: () => void) => (() => void);
|
|
41
|
+
export declare const useGoalState: () => GoalState;
|
|
42
|
+
export declare const publishGoalFetchSettled: (next: boolean) => void;
|
|
43
|
+
export declare const useGoalFetchSettled: () => boolean;
|
|
@@ -11,5 +11,6 @@ export declare const belongMessageMetadataSchema: z.ZodObject<{
|
|
|
11
11
|
createdAt: z.ZodOptional<z.ZodString>;
|
|
12
12
|
skill: z.ZodOptional<z.ZodString>;
|
|
13
13
|
fromHistory: z.ZodOptional<z.ZodBoolean>;
|
|
14
|
+
clientMessageId: z.ZodOptional<z.ZodString>;
|
|
14
15
|
}, z.core.$strip>;
|
|
15
16
|
export type BelongMessageMetadata = z.infer<typeof belongMessageMetadataSchema>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BelongMessagePart, PartRendererProps } from './ai-sdk-part-renderers.tsx';
|
|
2
|
+
/**
|
|
3
|
+
* The parts a message is INDEXED from (spec deviation 16). File parts render as
|
|
4
|
+
* chips above the message and never reach a render group, and dropping one
|
|
5
|
+
* shifts every later group's key — so the chat here and the fullscreen pane
|
|
6
|
+
* (`collectSubagentWaves`) must drop them the same way, or the two would draw
|
|
7
|
+
* the same message's lanes with different step keys.
|
|
8
|
+
*
|
|
9
|
+
* Idempotent: ChatRoute already filters before it renders, and filtering twice
|
|
10
|
+
* is the same list.
|
|
11
|
+
*/
|
|
12
|
+
export declare const indexableMessageParts: (parts: readonly BelongMessagePart[]) => readonly BelongMessagePart[];
|
|
13
|
+
export declare const MessageParts: ({ parts, streaming, historical, onContinueConnector, onExecutePlan, onFollowContinuation, partProps, }: {
|
|
14
|
+
/** The message's parts, file parts already removed (they render as chips). */
|
|
15
|
+
readonly parts: readonly BelongMessagePart[];
|
|
16
|
+
/** This message is the one a run is streaming into right now. */
|
|
17
|
+
readonly streaming: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Restored history must render settled, never re-fire the dispatch
|
|
20
|
+
* renderers' one-shot side effects (reconnect grant mint, host navigation,
|
|
21
|
+
* ui-action result POST).
|
|
22
|
+
*/
|
|
23
|
+
readonly historical: boolean;
|
|
24
|
+
readonly onContinueConnector?: PartRendererProps["onContinueConnector"];
|
|
25
|
+
/** The plan card's "Run this plan" CTA — omitted while a run streams. */
|
|
26
|
+
readonly onExecutePlan?: PartRendererProps["onExecutePlan"];
|
|
27
|
+
/**
|
|
28
|
+
* An agent-raised plan card's decision: the server posts it as the user's
|
|
29
|
+
* message and names the turn it started, which the chat must then follow
|
|
30
|
+
* live. Without it the card settles and the run it began never appears.
|
|
31
|
+
*/
|
|
32
|
+
readonly onFollowContinuation?: PartRendererProps["onFollowContinuation"];
|
|
33
|
+
/**
|
|
34
|
+
* Extra `PartRenderer` props computed PER PART — the goal surfaces' wiring
|
|
35
|
+
* (`routes/chat/part-renderer-extra-props.ts`), whose `renderGoalSetCard`
|
|
36
|
+
* gate depends on the specific part's id, so it cannot be hoisted to one
|
|
37
|
+
* value per message. Spread AFTER the props above, so a caller that routes
|
|
38
|
+
* `onContinueConnector` / `onExecutePlan` through here rather than through
|
|
39
|
+
* the named props still wins. Absent = no goal wiring (stories, tests).
|
|
40
|
+
*/
|
|
41
|
+
readonly partProps?: ((part: BelongMessagePart) => Partial<PartRendererProps>) | undefined;
|
|
42
|
+
}) => import("react").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BelongUIMessage } from './belong-data-parts.ts';
|
|
2
|
+
import { GoalView } from '../api/goals.ts';
|
|
3
|
+
export declare const selectLatestGoal: (messages: readonly BelongUIMessage[]) => GoalView | null;
|
|
4
|
+
/**
|
|
5
|
+
* Task 13 — the completion card's cue for whether "Get the files" has
|
|
6
|
+
* anything to show: every `file` (user attachment) or `data-artifact`
|
|
7
|
+
* (agent-published) part across the WHOLE session, not just the goal's own
|
|
8
|
+
* turns — the objective can reference something attached earlier in the same
|
|
9
|
+
* conversation. Counts part instances rather than deduping by id, so a
|
|
10
|
+
* re-emitted historical part only ever makes the button MORE likely to show,
|
|
11
|
+
* never hides files that were actually produced.
|
|
12
|
+
*/
|
|
13
|
+
export declare const countSessionFiles: (messages: readonly BelongUIMessage[]) => number;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SubagentLane } from './subagent-lanes-model.ts';
|
|
2
|
+
export type PublishedSubagentWave = {
|
|
3
|
+
readonly waveId: string;
|
|
4
|
+
/** Arrival order; readers sort with `orderLanes`. */
|
|
5
|
+
readonly lanes: readonly SubagentLane[];
|
|
6
|
+
/** In the last message while a run is active — the only time Stop applies. */
|
|
7
|
+
readonly live: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type SubagentControlsState = {
|
|
10
|
+
/** The active run of this chat, or null when none (Stop hides). */
|
|
11
|
+
readonly runId: string | null;
|
|
12
|
+
readonly stop: (subagentId: string) => Promise<void>;
|
|
13
|
+
/** Stops every stoppable running or queued lane of the wave, in parallel (§15). */
|
|
14
|
+
readonly stopAll: (waveId: string) => Promise<void>;
|
|
15
|
+
readonly waves: readonly PublishedSubagentWave[];
|
|
16
|
+
};
|
|
17
|
+
export declare const publishSubagentControls: (next: SubagentControlsState | null) => void;
|
|
18
|
+
export declare const peekSubagentControls: () => SubagentControlsState | null;
|
|
19
|
+
export declare const useSubagentControls: () => SubagentControlsState | null;
|
|
20
|
+
export declare const findPublishedWave: (controls: SubagentControlsState | null, waveId: string) => PublishedSubagentWave | undefined;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { ActivityItem, ToolActivityItem } from './activity-items.ts';
|
|
2
|
+
import { ApprovalState, BelongUIMessage, PlanData, SubagentData } from './belong-data-parts.ts';
|
|
3
|
+
/** A lane's state: the two in-flight states plus every §1.2 outcome. */
|
|
4
|
+
export type SubagentLaneStatus = "queued" | "running" | "ok" | "error" | "timeout" | "stalled" | "stopped" | "interrupted";
|
|
5
|
+
/** §3.3 colour column: accent while running, orange when it ended badly, else neutral. */
|
|
6
|
+
export type SubagentLaneTone = "active" | "notice" | "quiet";
|
|
7
|
+
/** §3.3 + §4a — what a lane's subline says; running and ok lanes say nothing of their own. */
|
|
8
|
+
export type SubagentLaneSubline = "waiting" | Exclude<SubagentLaneStatus, "running" | "ok">;
|
|
9
|
+
type SubagentLaneStep = {
|
|
10
|
+
/**
|
|
11
|
+
* `<group key>:item-<index in that group>` — unique across the message (a
|
|
12
|
+
* lane's steps can come from several groups) and stable as the stream
|
|
13
|
+
* appends, so a step never remounts.
|
|
14
|
+
*/
|
|
15
|
+
readonly key: string;
|
|
16
|
+
readonly item: ToolActivityItem;
|
|
17
|
+
};
|
|
18
|
+
export type SubagentLane = {
|
|
19
|
+
readonly subagentId: string;
|
|
20
|
+
readonly data: SubagentData;
|
|
21
|
+
readonly status: SubagentLaneStatus;
|
|
22
|
+
/** §4a — an approval this subagent raised is still pending in its message. */
|
|
23
|
+
readonly waiting: boolean;
|
|
24
|
+
readonly steps: readonly SubagentLaneStep[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* One render group of a message, the shape `groupMessageParts` returns —
|
|
28
|
+
* restated structurally so this model never imports the renderers file
|
|
29
|
+
* (depcruise counts type-only imports, and the renderers import this file).
|
|
30
|
+
*/
|
|
31
|
+
export type SubagentIndexGroup = {
|
|
32
|
+
readonly kind: "activity";
|
|
33
|
+
readonly key: string;
|
|
34
|
+
readonly items: readonly ActivityItem[];
|
|
35
|
+
} | {
|
|
36
|
+
readonly kind: "part";
|
|
37
|
+
readonly key: string;
|
|
38
|
+
readonly part: BelongUIMessage["parts"][number];
|
|
39
|
+
};
|
|
40
|
+
/** §4a — what every lane needs to know about ITS message, computed once per message. */
|
|
41
|
+
export type SubagentMessageIndex = {
|
|
42
|
+
/** subagentId → its lane: steps from every group, `waiting` from every approval card. */
|
|
43
|
+
readonly lanesById: ReadonlyMap<string, SubagentLane>;
|
|
44
|
+
/** waveId → its lanes, in arrival order across every group. */
|
|
45
|
+
readonly lanesByWaveId: ReadonlyMap<string, readonly SubagentLane[]>;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* What a group's lanes read from the message around them. `live` is the
|
|
49
|
+
* MESSAGE's liveness (it is the one a run streams into), not the group's: an
|
|
50
|
+
* approval or question card after the lanes makes their group non-last while
|
|
51
|
+
* the subagents still run, and their timers and Stop must not vanish then.
|
|
52
|
+
*/
|
|
53
|
+
export type SubagentLanesContext = {
|
|
54
|
+
readonly index: SubagentMessageIndex;
|
|
55
|
+
readonly live: boolean;
|
|
56
|
+
};
|
|
57
|
+
export type SubagentActivityEntry = {
|
|
58
|
+
readonly kind: "tool";
|
|
59
|
+
readonly key: string;
|
|
60
|
+
readonly item: ToolActivityItem;
|
|
61
|
+
} | {
|
|
62
|
+
readonly kind: "lane";
|
|
63
|
+
readonly key: string;
|
|
64
|
+
readonly lane: SubagentLane;
|
|
65
|
+
} | {
|
|
66
|
+
readonly kind: "wave";
|
|
67
|
+
readonly key: string;
|
|
68
|
+
readonly waveId: string;
|
|
69
|
+
/** Arrival order across the message. `orderLanes` sorts for display. */
|
|
70
|
+
readonly lanes: readonly SubagentLane[];
|
|
71
|
+
};
|
|
72
|
+
export type SubagentWaveCounts = {
|
|
73
|
+
readonly total: number;
|
|
74
|
+
/** `ok` */
|
|
75
|
+
readonly done: number;
|
|
76
|
+
readonly running: number;
|
|
77
|
+
readonly queued: number;
|
|
78
|
+
/** `error`, `timeout`, `stalled` */
|
|
79
|
+
readonly needsLook: number;
|
|
80
|
+
readonly stopped: number;
|
|
81
|
+
/** Every lane no longer running or queued (the meter's numerator). */
|
|
82
|
+
readonly ended: number;
|
|
83
|
+
};
|
|
84
|
+
export type SubagentWaveLabel = {
|
|
85
|
+
readonly kind: "text";
|
|
86
|
+
readonly text: string;
|
|
87
|
+
} | {
|
|
88
|
+
/**
|
|
89
|
+
* No label anywhere: the renderer words the wave itself. It needs both
|
|
90
|
+
* numbers, because "{{count}} running" is a STATE CLAIM — an unlabelled
|
|
91
|
+
* wave whose lanes have all ended must read its progress instead (§42).
|
|
92
|
+
*/
|
|
93
|
+
readonly kind: "count";
|
|
94
|
+
readonly count: number;
|
|
95
|
+
/** `ok` lanes. */
|
|
96
|
+
readonly done: number;
|
|
97
|
+
readonly running: number;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* §3.3 — the lane's state. `outcome` wins when present; an OLD part without it
|
|
101
|
+
* derives one: `finished` → ok, `failed` + `timedOut` → timeout, `failed` → error.
|
|
102
|
+
*/
|
|
103
|
+
export declare const subagentLaneStatus: (data: SubagentData) => SubagentLaneStatus;
|
|
104
|
+
export declare const subagentLaneTone: (status: SubagentLaneStatus) => SubagentLaneTone;
|
|
105
|
+
/**
|
|
106
|
+
* §4a — an approval card still waiting for a decision. The WIRE half of
|
|
107
|
+
* `ApprovalRenderer`'s own reading: `approved`, `rejected`, `amend_requested`
|
|
108
|
+
* and `expired` settle the card; only `pending` keeps it armed. (The card also
|
|
109
|
+
* settles on the viewer's own click before the wire catches up; a lane follows
|
|
110
|
+
* the wire, so the two agree once `approval_state_changed` lands, and after any
|
|
111
|
+
* reload.)
|
|
112
|
+
*/
|
|
113
|
+
export declare const isApprovalPending: (state: ApprovalState) => boolean;
|
|
114
|
+
/**
|
|
115
|
+
* §3.3 + §4a — a running lane is silent unless an approval it raised is pending
|
|
116
|
+
* ("Waiting for you"); an ok lane is silent; every other state names itself. An
|
|
117
|
+
* ENDED lane never reads "waiting": its approval settled or went with it.
|
|
118
|
+
*/
|
|
119
|
+
export declare const laneSubline: (status: SubagentLaneStatus, waiting: boolean) => SubagentLaneSubline | null;
|
|
120
|
+
/**
|
|
121
|
+
* §4a — read ONE message's groups once: every lane with its steps and wait, every wave.
|
|
122
|
+
*
|
|
123
|
+
* Known gap (spec deviation 15, a BACKEND defect the dock must not work around):
|
|
124
|
+
* when the executor's approval dedupe join binds two sibling subagents to one
|
|
125
|
+
* approval row, the joining seat re-emits the card under ITS OWN `subagentId`.
|
|
126
|
+
* The earlier sibling — still blocked on the same human — therefore loses its
|
|
127
|
+
* "Waiting for you" here, because the dock has no wire signal for the join.
|
|
128
|
+
*/
|
|
129
|
+
export declare const indexMessageSubagents: (groups: readonly SubagentIndexGroup[]) => SubagentMessageIndex;
|
|
130
|
+
/**
|
|
131
|
+
* Lay ONE group out against its message's index. Without an `index` the items
|
|
132
|
+
* are treated as a whole message of their own (a story, a unit test, a pane).
|
|
133
|
+
*/
|
|
134
|
+
export declare const partitionActivityItems: (items: readonly ActivityItem[], index?: SubagentMessageIndex) => readonly SubagentActivityEntry[];
|
|
135
|
+
/**
|
|
136
|
+
* §3.2 — running (earliest `startedAt` first), then queued, then ended badly,
|
|
137
|
+
* then interrupted, then ok. Ties keep first appearance.
|
|
138
|
+
*/
|
|
139
|
+
export declare const orderLanes: (lanes: readonly SubagentLane[]) => readonly SubagentLane[];
|
|
140
|
+
export declare const capLanes: (lanes: readonly SubagentLane[], showAll: boolean) => {
|
|
141
|
+
readonly visible: readonly SubagentLane[];
|
|
142
|
+
readonly hiddenCount: number;
|
|
143
|
+
};
|
|
144
|
+
export declare const waveCounts: (lanes: readonly SubagentLane[]) => SubagentWaveCounts;
|
|
145
|
+
/** Integer percent for the wave meter: ended / total. */
|
|
146
|
+
export declare const waveMeterPercent: (counts: SubagentWaveCounts) => number;
|
|
147
|
+
/**
|
|
148
|
+
* §3.2 — the first non-blank `groupLabel` (arrival order), else the title of
|
|
149
|
+
* the plan step a lane names, else the counts the renderer words (how many
|
|
150
|
+
* still run decides WHICH wording it may honestly use).
|
|
151
|
+
*/
|
|
152
|
+
export declare const waveLabel: (lanes: readonly SubagentLane[], plan: PlanData | null) => SubagentWaveLabel;
|
|
153
|
+
/** §3.3 — the collapsed line's progress: how many subagents, how many are `ok`. */
|
|
154
|
+
export declare const subagentProgress: (items: readonly ActivityItem[]) => {
|
|
155
|
+
readonly count: number;
|
|
156
|
+
readonly done: number;
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* §3.4 — `m:ss` (`h:mm:ss` from one hour). Running: `nowMs − startedAt`, and
|
|
160
|
+
* only while live (a crashed run's reloaded `running` part must not count up
|
|
161
|
+
* forever). Ended: `durationMs`. No `startedAt` → no timer.
|
|
162
|
+
*/
|
|
163
|
+
export declare const laneElapsedLabel: (input: {
|
|
164
|
+
readonly data: SubagentData;
|
|
165
|
+
readonly status: SubagentLaneStatus;
|
|
166
|
+
readonly live: boolean;
|
|
167
|
+
readonly nowMs: number;
|
|
168
|
+
}) => string | null;
|
|
169
|
+
/** Still in flight — the only states Stop applies to. */
|
|
170
|
+
export declare const isLaneInFlight: (status: SubagentLaneStatus) => boolean;
|
|
171
|
+
/** §3.6 — the fullscreen pane's filters. "running" includes queued lanes (still in flight). */
|
|
172
|
+
export type SubagentPaneFilter = "all" | "running" | "attention" | "done";
|
|
173
|
+
export declare const SUBAGENT_PANE_FILTERS: readonly SubagentPaneFilter[];
|
|
174
|
+
export declare const laneMatchesFilter: (status: SubagentLaneStatus, filter: SubagentPaneFilter) => boolean;
|
|
175
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { TFunction } from 'i18next';
|
|
3
|
+
import { ActivityItem, ToolActivityItem } from './activity-items.ts';
|
|
4
|
+
import { SubagentData } from './belong-data-parts.ts';
|
|
5
|
+
import { SubagentControlsState } from './subagent-controls-store.ts';
|
|
6
|
+
import { SubagentLane, SubagentLaneStatus, SubagentMessageIndex, SubagentWaveCounts, SubagentWaveLabel } from './subagent-lanes-model.ts';
|
|
7
|
+
type RenderToolItem = (item: ToolActivityItem) => ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* §3.6 — the wave label, worded. An unlabelled wave says how many are running
|
|
10
|
+
* only while any lane still is: "3 running" beside counts of "3 done" would be
|
|
11
|
+
* a false state claim on the surface §42 exists to keep honest. Once none runs,
|
|
12
|
+
* it reads the progress the collapsed line already words. BY NAME: that key is
|
|
13
|
+
* "{{done}} of {{count}} done" — a swapped pass renders "3 of 2 done".
|
|
14
|
+
*/
|
|
15
|
+
export declare const waveLabelText: (t: TFunction, label: SubagentWaveLabel) => string;
|
|
16
|
+
/** §3.6 — non-zero counts, in order: done, running, waiting, need a look, stopped. */
|
|
17
|
+
export declare const waveCountsText: (t: TFunction, counts: SubagentWaveCounts) => string;
|
|
18
|
+
/**
|
|
19
|
+
* The elapsed-time LEAF (§3.4). It owns the only interval, so a tick re-renders
|
|
20
|
+
* this span and nothing else, and it runs only while the group is live and the
|
|
21
|
+
* lane is running — the group's content is force-mounted while collapsed, so an
|
|
22
|
+
* unconditional interval would tick for every group in the transcript. This
|
|
23
|
+
* leaf is the wall-clock adapter; the model takes `nowMs` (§25).
|
|
24
|
+
*/
|
|
25
|
+
export declare const SubagentElapsed: ({ data, status, live, }: {
|
|
26
|
+
readonly data: SubagentData;
|
|
27
|
+
readonly status: SubagentLaneStatus;
|
|
28
|
+
readonly live: boolean;
|
|
29
|
+
}) => import("react").JSX.Element | null;
|
|
30
|
+
/** Accent spinner only while live (a reloaded crashed run must not spin), tick when ok, dot when orange. */
|
|
31
|
+
export declare const SubagentGlyph: ({ status, live, }: {
|
|
32
|
+
readonly status: SubagentLaneStatus;
|
|
33
|
+
readonly live: boolean;
|
|
34
|
+
}) => import("react").JSX.Element;
|
|
35
|
+
/**
|
|
36
|
+
* §3.3 subline: orange for the ended-badly outcomes, muted otherwise — including
|
|
37
|
+
* §4a's "Waiting for you" on a running lane whose approval is pending (waiting
|
|
38
|
+
* on a person is not a failure).
|
|
39
|
+
*/
|
|
40
|
+
export declare const SubagentOutcomeLine: ({ status, waiting, }: {
|
|
41
|
+
readonly status: SubagentLaneStatus;
|
|
42
|
+
readonly waiting: boolean;
|
|
43
|
+
}) => import("react").JSX.Element | null;
|
|
44
|
+
/** §3.5 — the subagent's own written report, as PLAIN text (never HTML). */
|
|
45
|
+
export declare const SubagentReport: ({ summary }: {
|
|
46
|
+
readonly summary: string;
|
|
47
|
+
}) => import("react").JSX.Element;
|
|
48
|
+
/**
|
|
49
|
+
* §3.5 — the Stop handler for a lane, or null when Stop must not render: the
|
|
50
|
+
* lane is stoppable (own loop only) and still running or queued, its group is
|
|
51
|
+
* live, and the chat has an active run.
|
|
52
|
+
*/
|
|
53
|
+
export declare const stopHandlerFor: (controls: SubagentControlsState | null, live: boolean, lane: SubagentLane) => SubagentControlsState["stop"] | null;
|
|
54
|
+
/**
|
|
55
|
+
* Stop ONE subagent. Disables after the click and shows nothing optimistic:
|
|
56
|
+
* the lane changes only when its `subagent_finished` part arrives (§3.5).
|
|
57
|
+
* `outline`, never `destructive` (§42) — a stop is an ordinary thing to ask
|
|
58
|
+
* for, and it is best-effort besides.
|
|
59
|
+
*/
|
|
60
|
+
export declare const SubagentStopButton: ({ subagentId, onStop, }: {
|
|
61
|
+
readonly subagentId: string;
|
|
62
|
+
readonly onStop: SubagentControlsState["stop"];
|
|
63
|
+
}) => import("react").JSX.Element;
|
|
64
|
+
/**
|
|
65
|
+
* Decision 9 — Stop all confirms INLINE, in two steps: the first click turns
|
|
66
|
+
* the button into "Stop N?" for 4 s; a second click inside that window stops.
|
|
67
|
+
* No modal. Once it stops, it stays disabled until the lanes finish and the
|
|
68
|
+
* button unmounts (nothing optimistic).
|
|
69
|
+
*/
|
|
70
|
+
export declare const SubagentStopAll: ({ count, onStopAll, }: {
|
|
71
|
+
readonly count: number;
|
|
72
|
+
readonly onStopAll: () => Promise<void>;
|
|
73
|
+
}) => import("react").JSX.Element;
|
|
74
|
+
/** A report worth a toggle: present and not blank. */
|
|
75
|
+
export declare const reportOf: (data: SubagentData) => string | null;
|
|
76
|
+
/**
|
|
77
|
+
* The expanded group's body: main-loop items in place, lanes with their nested
|
|
78
|
+
* steps, and waves. Keys are the model's (`item-<i>`, `lane-<id>`,
|
|
79
|
+
* `wave-<id>`), never a render index, so a re-sort never remounts a lane.
|
|
80
|
+
* `index` is the group's MESSAGE (§4a): a lane nests its calls, and a wave its
|
|
81
|
+
* lanes, from every group of it. Absent, the items are their own message.
|
|
82
|
+
*/
|
|
83
|
+
export declare const SubagentLanes: ({ items, live, renderToolItem, index, }: {
|
|
84
|
+
readonly items: readonly ActivityItem[];
|
|
85
|
+
readonly live: boolean;
|
|
86
|
+
readonly renderToolItem: RenderToolItem;
|
|
87
|
+
readonly index?: SubagentMessageIndex | undefined;
|
|
88
|
+
}) => import("react").JSX.Element;
|
|
89
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BelongChatTransport } from './belong-chat-transport.ts';
|
|
2
|
+
import { BelongUIMessage } from './belong-data-parts.ts';
|
|
3
|
+
import { PublishedSubagentWave } from './subagent-controls-store.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Every wave in the conversation, in message order — each message grouped and
|
|
6
|
+
* indexed exactly as `MessageParts` draws it (§4a, deviation 16: the same
|
|
7
|
+
* `indexableMessageParts` filter, so the pane's lanes and the chat's lanes are
|
|
8
|
+
* the same lanes down to their step keys), `waiting` included.
|
|
9
|
+
*/
|
|
10
|
+
export declare const collectSubagentWaves: (messages: readonly BelongUIMessage[], runActive: boolean) => readonly PublishedSubagentWave[];
|
|
11
|
+
export declare const usePublishSubagentControls: (transport: Pick<BelongChatTransport, "stopSubagent">, messages: readonly BelongUIMessage[]) => void;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { PreviewTarget } from './preview-panel-store.ts';
|
|
2
2
|
export type WorkspaceFocusTarget = PreviewTarget | {
|
|
3
3
|
readonly kind: "plan";
|
|
4
|
+
}
|
|
5
|
+
/** Spec 2026-09-16 §3.5 — one wave's full subagent list ("Show all" in fullscreen). */
|
|
6
|
+
| {
|
|
7
|
+
readonly kind: "subagents";
|
|
8
|
+
readonly waveId: string;
|
|
4
9
|
};
|
|
5
10
|
export type WorkspaceFocusState = {
|
|
6
11
|
readonly target: WorkspaceFocusTarget | null;
|
|
@@ -9,7 +14,8 @@ export type WorkspaceFocusState = {
|
|
|
9
14
|
/** The agent wants this shown, but the user holds the pane. */
|
|
10
15
|
readonly pending: WorkspaceFocusTarget | null;
|
|
11
16
|
};
|
|
12
|
-
/** Same thing on screen? Artifacts by id, workspace files by pinned scope + path,
|
|
17
|
+
/** Same thing on screen? Artifacts by id, workspace files by pinned scope + path,
|
|
18
|
+
* plans by kind, subagent views by wave. */
|
|
13
19
|
export declare const isSameFocusTarget: (a: WorkspaceFocusTarget, b: WorkspaceFocusTarget) => boolean;
|
|
14
20
|
export declare const peekWorkspaceFocus: () => WorkspaceFocusState;
|
|
15
21
|
export declare const subscribeWorkspaceFocus: (listener: () => void) => (() => void);
|
package/dist/test/render.d.ts
CHANGED
|
@@ -16,8 +16,25 @@ export declare function setValue(el: HTMLInputElement | HTMLTextAreaElement, val
|
|
|
16
16
|
* it holds or `timeoutMs` elapses. The repo's render harness serves React's
|
|
17
17
|
* prod build (no `React.act`), so async state — react-query settling, a $post
|
|
18
18
|
* resolving — is observed by polling rather than awaiting `act`.
|
|
19
|
+
*
|
|
20
|
+
* `predicate` keeps its ORIGINAL truthy contract — a falsy return (`false`,
|
|
21
|
+
* `null`, `0`, `""`, a `querySelector` miss, …) means "not yet, keep
|
|
22
|
+
* polling" — with exactly two additions, both needed for the
|
|
23
|
+
* `waitFor(() => expect(x).toBe(y))` idiom: `undefined` counts as
|
|
24
|
+
* "satisfied" (a PASSING `expect(...)` call returns nothing, so treating
|
|
25
|
+
* `undefined` as falsy would spin every such predicate to the timeout), and
|
|
26
|
+
* a THROW (a FAILING `expect(...)` call) means "not yet, keep polling"
|
|
27
|
+
* rather than an immediate hard stop. Without the second part, the very
|
|
28
|
+
* FIRST call to a throwing predicate always races an async continuation
|
|
29
|
+
* that hasn't had a microtask turn yet, so it would fail on that first race
|
|
30
|
+
* almost every time, no matter how the component under test is implemented
|
|
31
|
+
* — see IssueReportDialog.test.tsx's failed-send case for a concrete
|
|
32
|
+
* instance. Every existing boolean/element-returning predicate in this repo
|
|
33
|
+
* is unaffected: `true`/a found element still short-circuits immediately,
|
|
34
|
+
* `false`/`null` still retries. On timeout the LAST assertion error (if any)
|
|
35
|
+
* is re-thrown, which is more actionable than the generic message below.
|
|
19
36
|
*/
|
|
20
|
-
export declare function waitFor(predicate: () =>
|
|
37
|
+
export declare function waitFor(predicate: () => unknown, { timeoutMs, stepMs }?: {
|
|
21
38
|
timeoutMs?: number;
|
|
22
39
|
stepMs?: number;
|
|
23
40
|
}): Promise<void>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ActivityItem, ToolActivityItem } from '../stream/activity-items.ts';
|
|
2
|
+
import { SubagentLane } from '../stream/subagent-lanes-model.ts';
|
|
3
|
+
import { ApprovalState, BelongUIMessage, SubagentData, ToolCallData } from '../stream/belong-data-parts.ts';
|
|
4
|
+
/** A subagent activity item; `data` overrides the running defaults. */
|
|
5
|
+
export declare const subagentItem: (subagentId: string, data?: Partial<SubagentData>) => ActivityItem;
|
|
6
|
+
/**
|
|
7
|
+
* A tool activity item, completed unless `state` says otherwise; `subagentId`
|
|
8
|
+
* nests it under that lane.
|
|
9
|
+
*/
|
|
10
|
+
export declare const toolItem: (toolName: string, subagentId?: string, state?: ToolCallData["state"]) => ToolActivityItem;
|
|
11
|
+
/** An approval card part; `subagentId` undefined = the main agent raised it. */
|
|
12
|
+
export declare const approvalPart: (subagentId: string | undefined, state?: ApprovalState) => BelongUIMessage["parts"][number];
|
|
13
|
+
/**
|
|
14
|
+
* A `data-subagent` message part; `data` overrides the running defaults. Lives
|
|
15
|
+
* here (not in one suite) because the whole-message suite and the controls
|
|
16
|
+
* suite must build the SAME part — they assert the two index it identically.
|
|
17
|
+
*/
|
|
18
|
+
export declare const subagentPart: (id: string, data?: Partial<SubagentData>) => BelongUIMessage["parts"][number];
|
|
19
|
+
/**
|
|
20
|
+
* A resolved lane with no steps and no pending approval — what the pure model
|
|
21
|
+
* and the fullscreen pane both start from. `status` is derived, never passed,
|
|
22
|
+
* so a fixture can never claim a state its data does not imply.
|
|
23
|
+
*/
|
|
24
|
+
export declare const subagentLane: (subagentId: string, data?: Partial<SubagentData>) => SubagentLane;
|