@belonguniverseai/react-sdk 0.6.28 → 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.
Files changed (101) hide show
  1. package/README.md +14 -4
  2. package/dist/api/artifact-actions.d.ts +0 -1
  3. package/dist/api/auth-errors.d.ts +21 -0
  4. package/dist/api/client.d.ts +800 -64
  5. package/dist/api/goals.d.ts +19 -2
  6. package/dist/api/task-schedule-sharing.d.ts +18 -3
  7. package/dist/api/task-schedules.d.ts +74 -10
  8. package/dist/app/VoiceOverlay.d.ts +4 -3
  9. package/dist/app/dock-story-data.d.ts +15 -0
  10. package/dist/browser/control-channel.d.ts +9 -0
  11. package/dist/browser/dom-bridge.d.ts +2 -0
  12. package/dist/component/BelongWidget.d.ts +13 -3
  13. package/dist/component/{abnfDiagram-N423BO3Z-BGC_KU0K.js → abnfDiagram-N423BO3Z-BvL7baZ-.js} +4 -4
  14. package/dist/component/{arc-BpIEtZvJ.js → arc-DVUroP2Z.js} +2 -2
  15. package/dist/component/{architectureDiagram-T3A2C74G-DYlEVfnh.js → architectureDiagram-T3A2C74G-CYt93mxs.js} +3 -3
  16. package/dist/component/{blockDiagram-VBNYF7ZC-BWDnhAW1.js → blockDiagram-VBNYF7ZC-yST7U8Pb.js} +4 -4
  17. package/dist/component/{c4Diagram-5PPSVZJV-VKL0Shn2.js → c4Diagram-5PPSVZJV-BHz6Efx3.js} +3 -3
  18. package/dist/component/{channel-gGd0pNDR.js → channel-CKTqNdN4.js} +2 -2
  19. package/dist/component/{chunk-2GRJ4B5K-CEt4y1jX.js → chunk-2GRJ4B5K-Bw2zHHAm.js} +2 -2
  20. package/dist/component/{chunk-2Q5K7J3B-Dj2wrNzr.js → chunk-2Q5K7J3B-DpBuF73m.js} +2 -2
  21. package/dist/component/{chunk-5RXB4S5H-oJQEn1bH.js → chunk-5RXB4S5H-dxBtwi1p.js} +5 -5
  22. package/dist/component/{chunk-5VM5RSS4-DddP8MPP.js → chunk-5VM5RSS4-BOTqM1Rc.js} +2 -2
  23. package/dist/component/{chunk-6Q2QTUOP-CppUJwrF.js → chunk-6Q2QTUOP-DjMXJhRD.js} +2 -2
  24. package/dist/component/{chunk-GF5L2VYU--hyUlO9v.js → chunk-GF5L2VYU-CGpnSfXM.js} +6 -6
  25. package/dist/component/{chunk-JWPE2WC7-CN0Ieqel.js → chunk-JWPE2WC7-L5aYKPho.js} +2 -2
  26. package/dist/component/{chunk-KBJHAD2P-BWhCQoHz.js → chunk-KBJHAD2P-DH2RFBaF.js} +2 -2
  27. package/dist/component/{chunk-RYQCIY6F-BgNewpQe.js → chunk-RYQCIY6F-QPgRO0s7.js} +2 -2
  28. package/dist/component/{chunk-XXDRQBXY-mNH171OF.js → chunk-XXDRQBXY-C1ezaFpA.js} +2 -2
  29. package/dist/component/{classDiagram-JCYQIIEL-UjZbWotD.js → classDiagram-JCYQIIEL-Dx7Qx836.js} +3 -3
  30. package/dist/component/{classDiagram-v2-OCEON4UE-UjZbWotD.js → classDiagram-v2-OCEON4UE-Dx7Qx836.js} +3 -3
  31. package/dist/component/{cose-bilkent-JH36ORCC-lsVWGlMj.js → cose-bilkent-JH36ORCC-Bem1eaLJ.js} +2 -2
  32. package/dist/component/{cynefinDiagram-MW4NZA55-B5Ss0zoy.js → cynefinDiagram-MW4NZA55-DF15EWOu.js} +3 -3
  33. package/dist/component/{dagre-VZM6K2ZE-DisWRVfU.js → dagre-VZM6K2ZE-BVzwev7l.js} +3 -3
  34. package/dist/component/{diagram-7IWD3JNH-B2QrdsOh.js → diagram-7IWD3JNH-DzQhKX_v.js} +4 -4
  35. package/dist/component/{diagram-B4RE2ZJO-Bs8l4THz.js → diagram-B4RE2ZJO-DnHINfhE.js} +3 -3
  36. package/dist/component/{diagram-LBJQPF4R-JTadtYMW.js → diagram-LBJQPF4R-CPqE_GwY.js} +3 -3
  37. package/dist/component/{diagram-Q27KOJAE-BQC33flc.js → diagram-Q27KOJAE-BjpvfqhL.js} +4 -4
  38. package/dist/component/{diagram-UB23O5K3-ujC22dQx.js → diagram-UB23O5K3-BcYqFjqI.js} +3 -3
  39. package/dist/component/{ebnfDiagram-BXEA7PRR-0WnF2wzt.js → ebnfDiagram-BXEA7PRR-DoqGcWGx.js} +4 -4
  40. package/dist/component/{erDiagram-JOGREHBK-CqgMsd5R.js → erDiagram-JOGREHBK-DGrj5tIK.js} +5 -5
  41. package/dist/component/{flowDiagram-UKHOOZJN-BOM0P8Mk.js → flowDiagram-UKHOOZJN-B8OuOrVY.js} +7 -7
  42. package/dist/component/{ganttDiagram-PKOTCBZU-WeRFC1th.js → ganttDiagram-PKOTCBZU-BaxSqTVY.js} +3 -3
  43. package/dist/component/{gitGraphDiagram-DS77QQ5N-CS8L-BA8.js → gitGraphDiagram-DS77QQ5N-W1Sqa3Hc.js} +4 -4
  44. package/dist/component/{highlighted-body-OFNGDK62-CGejnMyq.js → highlighted-body-OFNGDK62-Cf1UqcGe.js} +2 -2
  45. package/dist/component/index.d.ts +1 -0
  46. package/dist/component/index.js +2 -2
  47. package/dist/component/{infoDiagram-6WML65LV-CQQhytkd.js → infoDiagram-6WML65LV-BS0JlYPr.js} +2 -2
  48. package/dist/component/{ishikawaDiagram-WSZJBQD7-CjDo3-zt.js → ishikawaDiagram-WSZJBQD7-Df_NzOQV.js} +2 -2
  49. package/dist/component/{journeyDiagram-NVQOT4AX-BCCoblta.js → journeyDiagram-NVQOT4AX-JWKvZ6rc.js} +5 -5
  50. package/dist/component/{kanban-definition-27J2QSJJ-DgTIrgvB.js → kanban-definition-27J2QSJJ-DMvICKAB.js} +3 -3
  51. package/dist/component/{linear-BOaza_dp.js → linear-D02U2fTS.js} +2 -2
  52. package/dist/component/{mermaid-GHXKKRXX-BAq5-Vj8.js → mermaid-GHXKKRXX-B7CJJdoE.js} +37650 -36676
  53. package/dist/component/{mindmap-definition-FAOFIHXS-D1oolR3A.js → mindmap-definition-FAOFIHXS-AzTh8oju.js} +4 -4
  54. package/dist/component/{pegDiagram-VL7TDLO6-C9UxqvBP.js → pegDiagram-VL7TDLO6-DSCzZs_w.js} +4 -4
  55. package/dist/component/{pieDiagram-7S7Q4E2Y-I5IXzOZM.js → pieDiagram-7S7Q4E2Y-CEByr6BB.js} +4 -4
  56. package/dist/component/{quadrantDiagram-CIZ2JOQS-DPDFBhEd.js → quadrantDiagram-CIZ2JOQS-BrWOf-GT.js} +3 -3
  57. package/dist/component/{railroadDiagram-AXF67PYL-DIAkhVTf.js → railroadDiagram-AXF67PYL-DRtsV2gM.js} +4 -4
  58. package/dist/component/{requirementDiagram-LRYGKXZP-DBEmV-Qy.js → requirementDiagram-LRYGKXZP-_WwAo7AE.js} +4 -4
  59. package/dist/component/{sankeyDiagram-W5VNT64P-BEeDyDj7.js → sankeyDiagram-W5VNT64P-DBxP3yyK.js} +2 -2
  60. package/dist/component/{sequenceDiagram-SI44F4Z6-WYcXWUHF.js → sequenceDiagram-SI44F4Z6-B3SNXrpC.js} +4 -4
  61. package/dist/component/{sizeCapture-X5ZJPWSS-BqDBRpiS.js → sizeCapture-X5ZJPWSS-D5G8pyPC.js} +2 -2
  62. package/dist/component/{stateDiagram-OKZ733FA-CfYfR0OH.js → stateDiagram-OKZ733FA-C4UZwsoc.js} +3 -3
  63. package/dist/component/{stateDiagram-v2-UEYNNEHI-BSa2VwcQ.js → stateDiagram-v2-UEYNNEHI-DIYB5q15.js} +3 -3
  64. package/dist/component/{swimlanes-SLNWSIFB-C-7mrC4X.js → swimlanes-SLNWSIFB-Cc9yJXTh.js} +4 -4
  65. package/dist/component/{swimlanesDiagram-ULZ7WXOC-DXcMd7U4.js → swimlanesDiagram-ULZ7WXOC-DsGPiJ-s.js} +3 -3
  66. package/dist/component/{timeline-definition-Z64GVDOM-Dp65E80E.js → timeline-definition-Z64GVDOM-Dr4-iAeD.js} +3 -3
  67. package/dist/component/{vennDiagram-T6HMQDX7-CRpZ12TH.js → vennDiagram-T6HMQDX7-ZiaZ9jYw.js} +2 -2
  68. package/dist/component/{wardleyDiagram-T6FBY63Y-BupsM8K3.js → wardleyDiagram-T6FBY63Y-KdF37MT-.js} +3 -3
  69. package/dist/component/{xychartDiagram-ELKLHX3M-CUnr8Qbu.js → xychartDiagram-ELKLHX3M-NH_bOKPL.js} +3 -3
  70. package/dist/components/embed/ComposerContext.d.ts +11 -7
  71. package/dist/components/embed/EmbedComposer.d.ts +3 -1
  72. package/dist/components/embed/GoalRefusalCard.d.ts +5 -1
  73. package/dist/components/scheduled/ConfirmRunPausedScheduleDialog.d.ts +18 -0
  74. package/dist/components/scheduled/EmailCopiesFields.d.ts +19 -0
  75. package/dist/components/scheduled/ScheduledDetailSurface.d.ts +2 -1
  76. package/dist/components/scheduled/use-run-now-with-confirmation.d.ts +17 -0
  77. package/dist/embed/artifact-action-bridge.d.ts +11 -3
  78. package/dist/embed/artifact-remint-budget.d.ts +5 -0
  79. package/dist/embed/copy.d.ts +13 -18
  80. package/dist/embed/goal-edit-command.d.ts +6 -5
  81. package/dist/embed/plan-decision-text.d.ts +1 -0
  82. package/dist/embed/voice-config.d.ts +22 -31
  83. package/dist/embed/voice-prefs.d.ts +18 -34
  84. package/dist/i18n/messages/en.d.ts +28 -2
  85. package/dist/i18n/messages/surfaces/feedback.d.ts +12 -0
  86. package/dist/i18n/messages/surfaces/plan.d.ts +4 -0
  87. package/dist/i18n/messages/surfaces/scheduled.d.ts +53 -1
  88. package/dist/i18n/messages/surfaces/usage.d.ts +1 -1
  89. package/dist/lib/tab-control-store.d.ts +14 -0
  90. package/dist/lib/tab-leadership.d.ts +9 -24
  91. package/dist/lib/use-tab-leadership.d.ts +5 -7
  92. package/dist/routes/chat/history-merge.d.ts +53 -0
  93. package/dist/routes/chat/history-paging.d.ts +25 -6
  94. package/dist/routes/chat/use-catch-up-on-return.d.ts +70 -0
  95. package/dist/routes/chat/use-return-to-page.d.ts +7 -0
  96. package/dist/stream/belong-chat-transport.d.ts +8 -6
  97. package/dist/stream/dispatch-once.d.ts +1 -1
  98. package/dist/stream/queued-message-outbox.d.ts +1 -0
  99. package/dist/stream/session-control-context.d.ts +7 -0
  100. package/dist/types/public.d.ts +12 -5
  101. package/package.json +1 -1
@@ -1,32 +1,20 @@
1
+ import { PushToTalkKey } from './voice-config.ts';
2
+ /** What the user picked in Settings: a key to hold, or push-to-talk off. */
3
+ export type PushToTalkChoice = PushToTalkKey | "off";
4
+ /** `useSyncExternalStore` subscribe — fires whenever the user's choice changes, in any tab. */
5
+ export declare const subscribePushToTalkKey: (listener: () => void) => (() => void);
6
+ /** The user's own choice, or `null` when they never chose (host default applies). */
7
+ export declare const peekUserPushToTalkChoice: () => PushToTalkChoice | null;
8
+ /** The key the dock actually binds — the user's choice over the host default — or `null` for none. */
9
+ export declare const getEffectivePushToTalkKey: () => PushToTalkKey | null;
10
+ /** `useSyncExternalStore` snapshot — the effective key (a primitive, so stable). */
11
+ export declare const peekPushToTalkKey: () => PushToTalkKey | null;
1
12
  /**
2
- * User voice preferences — the per-browser push-to-talk key override and the
3
- * first-conversation voice hint flag.
4
- *
5
- * Host default (voice-config `pushToTalkKey`) ◀ user pref (localStorage)
6
- *
7
- * `voice-config.ts` carries the HOST's deployment-wide knobs (set once via
8
- * `configureVoice`); this module layers the END USER's own choice on top, the
9
- * same way `theme.ts` layers user prefs over the host theme. Components read
10
- * the EFFECTIVE key (user pref if set, else host default) through a tiny
11
- * external store (`subscribePushToTalkKey` / `peekPushToTalkKey`) so the
12
- * settings UI, the composer tooltip, and the dock's key handler all rebind
13
- * live when the user picks a new key.
14
- *
15
- * localStorage is a perimeter: the prefs bag is zod-validated on read and any
16
- * junk (corrupted JSON, wrong shape, storage disabled) degrades to "no pref".
13
+ * Persist the user's choice and notify subscribers. The value comes from a
14
+ * form control, so it is parsed here: anything outside the key list and "off"
15
+ * is ignored.
17
16
  */
18
- /** `useSyncExternalStore` subscribe — fires on set/clear of the user key. */
19
- export declare const subscribePushToTalkKey: (listener: () => void) => (() => void);
20
- /** The user's own override, or `null` when the host default applies. */
21
- export declare const peekUserPushToTalkKey: () => string | null;
22
- /** The key the dock actually binds: user pref if set, else the host default. */
23
- export declare const getEffectivePushToTalkKey: () => string;
24
- /** `useSyncExternalStore` snapshot — the effective key (string, so stable). */
25
- export declare const peekPushToTalkKey: () => string;
26
- /** Persist a user-chosen `KeyboardEvent.code` and notify subscribers. */
27
- export declare const setUserPushToTalkKey: (code: string) => void;
28
- /** Drop the user override (back to the host default) and notify subscribers. */
29
- export declare const clearUserPushToTalkKey: () => void;
17
+ export declare const setUserPushToTalkChoice: (choice: string) => void;
30
18
  /** True once the push-to-talk hint chip was dismissed (X or first capture). */
31
19
  export declare const readVoiceHintDismissed: () => boolean;
32
20
  /** Persist the hint dismissal so it never shows again in this browser. */
@@ -46,14 +34,10 @@ export type VoiceClosedSendMode = "confirm" | "auto";
46
34
  export declare const subscribeVoiceClosedSendMode: (listener: () => void) => (() => void);
47
35
  export declare const peekVoiceClosedSendMode: () => VoiceClosedSendMode;
48
36
  export declare const setVoiceClosedSendMode: (mode: VoiceClosedSendMode) => void;
37
+ /** Human label for a push-to-talk key: "ControlLeft" → "Left Ctrl". */
38
+ export declare const formatKeyCode: (code: PushToTalkKey) => string;
49
39
  /**
50
- * Human label for a `KeyboardEvent.code`: "ControlLeft" → "Left Ctrl",
51
- * "KeyA" → "A", "Digit7" → "7". Codes with no friendlier reading ("Space",
52
- * "F1", unknown codes) pass through unchanged.
53
- */
54
- export declare const formatKeyCode: (code: string) => string;
55
- /**
56
- * Test-only: clear listeners and re-seed the user key from localStorage. The
40
+ * Test-only: clear listeners and re-seed the user's choice from localStorage. The
57
41
  * store is a module singleton, so unit tests reset it in `beforeEach`.
58
42
  */
59
43
  export declare const __resetVoicePrefsForTest: () => void;
@@ -16,7 +16,7 @@ export declare const en: {
16
16
  readonly expandComposer: "Expand message input";
17
17
  readonly collapseComposer: "Compact message input";
18
18
  readonly contextTitle: "Context for this message";
19
- readonly pageNote: "Page label only; this control does not attach page contents.";
19
+ readonly pageNote: "The agent receives this page name with your message, not the page contents.";
20
20
  readonly removeFile: "Remove {{name}}";
21
21
  readonly closeContext: "Close context";
22
22
  readonly currentPage: "Current page";
@@ -500,6 +500,7 @@ export declare const en: {
500
500
  readonly sharedConflict: "Someone updated this task while you were editing. Your text is still here. Copy any changes you want to keep, then reopen the editor to load the latest version.";
501
501
  readonly sharedReadOnly: "You no longer have edit access. Your unsaved changes are still here.";
502
502
  readonly templateUnavailable: "The linked HTML template could not be read. Ask the owner to restore it, then resume this task.";
503
+ readonly cliReconnectRequired: "Simetrik couldn't be reached during this run. It reconnects on its own the next time you open Simetrik.";
503
504
  readonly viewTitle: "Scheduled";
504
505
  readonly subtitle: "Run work automatically, even when you're away";
505
506
  readonly newTask: "New task";
@@ -523,7 +524,7 @@ export declare const en: {
523
524
  readonly nextRunIn: "Next run {{when}}";
524
525
  readonly lastRun: "Last run {{time}}";
525
526
  readonly dayAtTime: "{{day}} at {{time}}";
526
- readonly pausedNotice: "Paused — runs won't start until you resume.";
527
+ readonly pausedNotice: "Paused — scheduled runs won't start until you resume. Run now still runs it once.";
527
528
  readonly scheduleIdLabel: "Schedule ID";
528
529
  readonly copyScheduleId: "Copy ID";
529
530
  readonly customEmailLabel: "Custom email enabled";
@@ -534,6 +535,15 @@ export declare const en: {
534
535
  readonly sharedRecipients: "Shared recipients";
535
536
  readonly sharedRecipientsHelp: "Sent only from the owner’s original task. Shared delivery pauses when that task is paused.";
536
537
  readonly errorRecipientsInvalid: "Enter valid, unique email addresses.";
538
+ readonly errorEmailAddressingInvalid: "This combination of shared and local email settings is invalid. Combined CC and BCC lists allow 50 addresses each; Reply-To allows 10. Extra local CC/BCC recipients need a To address that is not already covered by shared delivery.";
539
+ readonly emailCopiesToggle: "Add CC, BCC or Reply-To";
540
+ readonly emailCopiesLabel: "CC, BCC and Reply-To";
541
+ readonly emailCc: "CC";
542
+ readonly emailBcc: "BCC";
543
+ readonly emailReplyTo: "Reply-To";
544
+ readonly emailCopiesHelp: "Everyone sees the CC addresses, BCC stays hidden, and replies go to Reply-To. Separate addresses with commas.";
545
+ readonly sharedEmailCopies: "Shared CC, BCC and Reply-To";
546
+ readonly sharedEmailCopiesHelp: "Added only to the owner’s original task email, like shared recipients. Each person can also add their own.";
537
547
  readonly emailAccountRecipient: "Schedule owner's account email";
538
548
  readonly teamsDeliveryLabel: "Microsoft Teams delivery approved";
539
549
  readonly teamsStatusActive: "Active";
@@ -590,6 +600,8 @@ export declare const en: {
590
600
  readonly resumedCompleted: "Its time already passed, so this one-time task is now completed.";
591
601
  readonly runNow: "Run now";
592
602
  readonly runNowStarted: "Run started — it will appear below.";
603
+ readonly runPausedConfirmTitle: "Run this paused task now?";
604
+ readonly runPausedConfirmBody: "This task is paused. It will run once now, including its emails, and stay paused.";
593
605
  readonly edit: "Edit";
594
606
  readonly delete: "Delete";
595
607
  readonly deleteConfirmTitle: "Delete this scheduled task?";
@@ -608,6 +620,7 @@ export declare const en: {
608
620
  readonly runStatusFailed: "Failed";
609
621
  readonly runNeedsAttentionHint: "Waiting for your input.";
610
622
  readonly manualRun: "Manual run";
623
+ readonly manualRunPaused: "Manual run while paused";
611
624
  readonly openRun: "Open this run's conversation";
612
625
  readonly detailLoadError: "Couldn't load this scheduled task.";
613
626
  readonly detailGone: "This scheduled task no longer exists.";
@@ -624,6 +637,7 @@ export declare const en: {
624
637
  readonly progressDone: "done";
625
638
  readonly failedPrefix: "Failed:";
626
639
  readonly failedHelp: "Tell me what to do";
640
+ readonly runThisPlan: "Run this plan";
627
641
  readonly approveAndRun: "Approve & run";
628
642
  readonly reject: "Reject";
629
643
  };
@@ -799,6 +813,9 @@ export declare const en: {
799
813
  readonly issueReport: {
800
814
  readonly open: "Send feedback";
801
815
  readonly title: "Send feedback";
816
+ readonly sdkVersion: "SDK version";
817
+ readonly sessionId: "Session ID";
818
+ readonly copyDetails: "Copy report details";
802
819
  readonly placeholder: "Describe the issue";
803
820
  readonly includesWithShot: "This report includes a screenshot of the current screen and technical details of your session.";
804
821
  readonly includesNoShot: "This report includes technical details of your session.";
@@ -1278,6 +1295,7 @@ export declare const en: {
1278
1295
  readonly conversation: {
1279
1296
  readonly thinking: "Thinking…";
1280
1297
  readonly followerBanner: "This conversation is open in another tab";
1298
+ readonly useThisTab: "Use this tab";
1281
1299
  readonly historyUnavailable: "Couldn't load this conversation — try reopening it.";
1282
1300
  readonly showEarlierMessages: "Show earlier messages";
1283
1301
  };
@@ -1326,6 +1344,7 @@ export declare const en: {
1326
1344
  readonly refusal: {
1327
1345
  readonly existsTitle: "This chat already has a goal.";
1328
1346
  readonly existsBody: "One goal at a time — this one is still running.";
1347
+ readonly existsBodyUnfinished: "One goal at a time — this one isn't finished yet.";
1329
1348
  readonly existsOpen: "Open it";
1330
1349
  readonly existsReplace: "Clear it and set this one";
1331
1350
  readonly disabledTitle: "Goals aren't turned on here yet.";
@@ -1343,6 +1362,13 @@ export declare const en: {
1343
1362
  };
1344
1363
  readonly edited: "Goal updated.";
1345
1364
  readonly revived: "Goal updated and resumed — the assistant will pick it up now.";
1365
+ readonly stillStopped: {
1366
+ readonly budget: "Goal updated, but it's still stopped: its budget is {{cap}} and it has already used {{used}}. To restart it, send /goal budget with a number above {{used}}.";
1367
+ readonly turns: "Goal updated, but it's still stopped: its turn limit is {{cap}} and it has already used {{used}}. To restart it, send /goal turns with a number above {{used}}.";
1368
+ readonly budgetAndTurns: "Goal updated, but it's still stopped: its budget is {{tokenBudget}} and it has already used {{tokensUsed}}; its turn limit is {{maxTurns}} and it has already used {{turnsUsed}}. To restart it, send /goal budget with a number above {{tokensUsed}} and /goal turns with a number above {{turnsUsed}}.";
1369
+ readonly time: "Goal updated, but it's still stopped: it ran for as long as it was allowed, and that limit can't be raised. To keep chatting here, clear it with /goal clear — you can start a new goal after that.";
1370
+ readonly generic: "Goal updated, but it's still stopped: every limit it reached has to go above what it has already used before it can restart.";
1371
+ };
1346
1372
  readonly notEditable: "The goal can no longer be edited.";
1347
1373
  readonly editUsage: "Use /goal edit <objective>, /goal turns <number> or /goal budget <tokens>.";
1348
1374
  readonly status: "Goal · {{status}} · turn {{turnsUsed}} of {{maxTurns}} — {{objective}}";
@@ -9,6 +9,9 @@ export declare const feedbackEn: {
9
9
  readonly issueReport: {
10
10
  readonly open: "Send feedback";
11
11
  readonly title: "Send feedback";
12
+ readonly sdkVersion: "SDK version";
13
+ readonly sessionId: "Session ID";
14
+ readonly copyDetails: "Copy report details";
12
15
  readonly placeholder: "Describe the issue";
13
16
  readonly includesWithShot: "This report includes a screenshot of the current screen and technical details of your session.";
14
17
  readonly includesNoShot: "This report includes technical details of your session.";
@@ -39,6 +42,9 @@ export declare const feedbackEs: {
39
42
  issueReport: {
40
43
  open: string;
41
44
  title: string;
45
+ sdkVersion: string;
46
+ sessionId: string;
47
+ copyDetails: string;
42
48
  placeholder: string;
43
49
  includesWithShot: string;
44
50
  includesNoShot: string;
@@ -69,6 +75,9 @@ export declare const feedbackPt: {
69
75
  issueReport: {
70
76
  open: string;
71
77
  title: string;
78
+ sdkVersion: string;
79
+ sessionId: string;
80
+ copyDetails: string;
72
81
  placeholder: string;
73
82
  includesWithShot: string;
74
83
  includesNoShot: string;
@@ -99,6 +108,9 @@ export declare const feedbackIt: {
99
108
  issueReport: {
100
109
  open: string;
101
110
  title: string;
111
+ sdkVersion: string;
112
+ sessionId: string;
113
+ copyDetails: string;
102
114
  placeholder: string;
103
115
  includesWithShot: string;
104
116
  includesNoShot: string;
@@ -12,6 +12,7 @@ export declare const planEn: {
12
12
  readonly progressDone: "done";
13
13
  readonly failedPrefix: "Failed:";
14
14
  readonly failedHelp: "Tell me what to do";
15
+ readonly runThisPlan: "Run this plan";
15
16
  readonly approveAndRun: "Approve & run";
16
17
  readonly reject: "Reject";
17
18
  };
@@ -30,6 +31,7 @@ export declare const planEs: {
30
31
  failedPrefix: string;
31
32
  failedHelp: string;
32
33
  approveAndRun: string;
34
+ runThisPlan: string;
33
35
  reject: string;
34
36
  };
35
37
  };
@@ -47,6 +49,7 @@ export declare const planPt: {
47
49
  failedPrefix: string;
48
50
  failedHelp: string;
49
51
  approveAndRun: string;
52
+ runThisPlan: string;
50
53
  reject: string;
51
54
  };
52
55
  };
@@ -64,6 +67,7 @@ export declare const planIt: {
64
67
  failedPrefix: string;
65
68
  failedHelp: string;
66
69
  approveAndRun: string;
70
+ runThisPlan: string;
67
71
  reject: string;
68
72
  };
69
73
  };
@@ -57,6 +57,7 @@ export declare const scheduledEn: {
57
57
  readonly sharedConflict: "Someone updated this task while you were editing. Your text is still here. Copy any changes you want to keep, then reopen the editor to load the latest version.";
58
58
  readonly sharedReadOnly: "You no longer have edit access. Your unsaved changes are still here.";
59
59
  readonly templateUnavailable: "The linked HTML template could not be read. Ask the owner to restore it, then resume this task.";
60
+ readonly cliReconnectRequired: "Simetrik couldn't be reached during this run. It reconnects on its own the next time you open Simetrik.";
60
61
  readonly viewTitle: "Scheduled";
61
62
  readonly subtitle: "Run work automatically, even when you're away";
62
63
  readonly newTask: "New task";
@@ -80,7 +81,7 @@ export declare const scheduledEn: {
80
81
  readonly nextRunIn: "Next run {{when}}";
81
82
  readonly lastRun: "Last run {{time}}";
82
83
  readonly dayAtTime: "{{day}} at {{time}}";
83
- readonly pausedNotice: "Paused — runs won't start until you resume.";
84
+ readonly pausedNotice: "Paused — scheduled runs won't start until you resume. Run now still runs it once.";
84
85
  readonly scheduleIdLabel: "Schedule ID";
85
86
  readonly copyScheduleId: "Copy ID";
86
87
  readonly customEmailLabel: "Custom email enabled";
@@ -91,6 +92,15 @@ export declare const scheduledEn: {
91
92
  readonly sharedRecipients: "Shared recipients";
92
93
  readonly sharedRecipientsHelp: "Sent only from the owner’s original task. Shared delivery pauses when that task is paused.";
93
94
  readonly errorRecipientsInvalid: "Enter valid, unique email addresses.";
95
+ readonly errorEmailAddressingInvalid: "This combination of shared and local email settings is invalid. Combined CC and BCC lists allow 50 addresses each; Reply-To allows 10. Extra local CC/BCC recipients need a To address that is not already covered by shared delivery.";
96
+ readonly emailCopiesToggle: "Add CC, BCC or Reply-To";
97
+ readonly emailCopiesLabel: "CC, BCC and Reply-To";
98
+ readonly emailCc: "CC";
99
+ readonly emailBcc: "BCC";
100
+ readonly emailReplyTo: "Reply-To";
101
+ readonly emailCopiesHelp: "Everyone sees the CC addresses, BCC stays hidden, and replies go to Reply-To. Separate addresses with commas.";
102
+ readonly sharedEmailCopies: "Shared CC, BCC and Reply-To";
103
+ readonly sharedEmailCopiesHelp: "Added only to the owner’s original task email, like shared recipients. Each person can also add their own.";
94
104
  readonly emailAccountRecipient: "Schedule owner's account email";
95
105
  readonly teamsDeliveryLabel: "Microsoft Teams delivery approved";
96
106
  readonly teamsStatusActive: "Active";
@@ -147,6 +157,8 @@ export declare const scheduledEn: {
147
157
  readonly resumedCompleted: "Its time already passed, so this one-time task is now completed.";
148
158
  readonly runNow: "Run now";
149
159
  readonly runNowStarted: "Run started — it will appear below.";
160
+ readonly runPausedConfirmTitle: "Run this paused task now?";
161
+ readonly runPausedConfirmBody: "This task is paused. It will run once now, including its emails, and stay paused.";
150
162
  readonly edit: "Edit";
151
163
  readonly delete: "Delete";
152
164
  readonly deleteConfirmTitle: "Delete this scheduled task?";
@@ -165,6 +177,7 @@ export declare const scheduledEn: {
165
177
  readonly runStatusFailed: "Failed";
166
178
  readonly runNeedsAttentionHint: "Waiting for your input.";
167
179
  readonly manualRun: "Manual run";
180
+ readonly manualRunPaused: "Manual run while paused";
168
181
  readonly openRun: "Open this run's conversation";
169
182
  readonly detailLoadError: "Couldn't load this scheduled task.";
170
183
  readonly detailGone: "This scheduled task no longer exists.";
@@ -228,6 +241,7 @@ export declare const scheduledEs: {
228
241
  sharedConflict: string;
229
242
  sharedReadOnly: string;
230
243
  templateUnavailable: string;
244
+ cliReconnectRequired: string;
231
245
  viewTitle: string;
232
246
  subtitle: string;
233
247
  newTask: string;
@@ -262,6 +276,15 @@ export declare const scheduledEs: {
262
276
  sharedRecipients: string;
263
277
  sharedRecipientsHelp: string;
264
278
  errorRecipientsInvalid: string;
279
+ errorEmailAddressingInvalid: string;
280
+ emailCopiesToggle: string;
281
+ emailCopiesLabel: string;
282
+ emailCc: string;
283
+ emailBcc: string;
284
+ emailReplyTo: string;
285
+ emailCopiesHelp: string;
286
+ sharedEmailCopies: string;
287
+ sharedEmailCopiesHelp: string;
265
288
  emailAccountRecipient: string;
266
289
  teamsDeliveryLabel: string;
267
290
  teamsStatusActive: string;
@@ -318,6 +341,8 @@ export declare const scheduledEs: {
318
341
  resumedCompleted: string;
319
342
  runNow: string;
320
343
  runNowStarted: string;
344
+ runPausedConfirmTitle: string;
345
+ runPausedConfirmBody: string;
321
346
  edit: string;
322
347
  delete: string;
323
348
  deleteConfirmTitle: string;
@@ -336,6 +361,7 @@ export declare const scheduledEs: {
336
361
  runStatusFailed: string;
337
362
  runNeedsAttentionHint: string;
338
363
  manualRun: string;
364
+ manualRunPaused: string;
339
365
  openRun: string;
340
366
  detailLoadError: string;
341
367
  detailGone: string;
@@ -399,6 +425,7 @@ export declare const scheduledPt: {
399
425
  sharedConflict: string;
400
426
  sharedReadOnly: string;
401
427
  templateUnavailable: string;
428
+ cliReconnectRequired: string;
402
429
  viewTitle: string;
403
430
  subtitle: string;
404
431
  newTask: string;
@@ -433,6 +460,15 @@ export declare const scheduledPt: {
433
460
  sharedRecipients: string;
434
461
  sharedRecipientsHelp: string;
435
462
  errorRecipientsInvalid: string;
463
+ errorEmailAddressingInvalid: string;
464
+ emailCopiesToggle: string;
465
+ emailCopiesLabel: string;
466
+ emailCc: string;
467
+ emailBcc: string;
468
+ emailReplyTo: string;
469
+ emailCopiesHelp: string;
470
+ sharedEmailCopies: string;
471
+ sharedEmailCopiesHelp: string;
436
472
  emailAccountRecipient: string;
437
473
  teamsDeliveryLabel: string;
438
474
  teamsStatusActive: string;
@@ -489,6 +525,8 @@ export declare const scheduledPt: {
489
525
  resumedCompleted: string;
490
526
  runNow: string;
491
527
  runNowStarted: string;
528
+ runPausedConfirmTitle: string;
529
+ runPausedConfirmBody: string;
492
530
  edit: string;
493
531
  delete: string;
494
532
  deleteConfirmTitle: string;
@@ -507,6 +545,7 @@ export declare const scheduledPt: {
507
545
  runStatusFailed: string;
508
546
  runNeedsAttentionHint: string;
509
547
  manualRun: string;
548
+ manualRunPaused: string;
510
549
  openRun: string;
511
550
  detailLoadError: string;
512
551
  detailGone: string;
@@ -570,6 +609,7 @@ export declare const scheduledIt: {
570
609
  sharedConflict: string;
571
610
  sharedReadOnly: string;
572
611
  templateUnavailable: string;
612
+ cliReconnectRequired: string;
573
613
  viewTitle: string;
574
614
  subtitle: string;
575
615
  newTask: string;
@@ -604,6 +644,15 @@ export declare const scheduledIt: {
604
644
  sharedRecipients: string;
605
645
  sharedRecipientsHelp: string;
606
646
  errorRecipientsInvalid: string;
647
+ errorEmailAddressingInvalid: string;
648
+ emailCopiesToggle: string;
649
+ emailCopiesLabel: string;
650
+ emailCc: string;
651
+ emailBcc: string;
652
+ emailReplyTo: string;
653
+ emailCopiesHelp: string;
654
+ sharedEmailCopies: string;
655
+ sharedEmailCopiesHelp: string;
607
656
  emailAccountRecipient: string;
608
657
  teamsDeliveryLabel: string;
609
658
  teamsStatusActive: string;
@@ -660,6 +709,8 @@ export declare const scheduledIt: {
660
709
  resumedCompleted: string;
661
710
  runNow: string;
662
711
  runNowStarted: string;
712
+ runPausedConfirmTitle: string;
713
+ runPausedConfirmBody: string;
663
714
  edit: string;
664
715
  delete: string;
665
716
  deleteConfirmTitle: string;
@@ -678,6 +729,7 @@ export declare const scheduledIt: {
678
729
  runStatusFailed: string;
679
730
  runNeedsAttentionHint: string;
680
731
  manualRun: string;
732
+ manualRunPaused: string;
681
733
  openRun: string;
682
734
  detailLoadError: string;
683
735
  detailGone: string;
@@ -4,7 +4,7 @@ export declare const usageEn: {
4
4
  readonly expandComposer: "Expand message input";
5
5
  readonly collapseComposer: "Compact message input";
6
6
  readonly contextTitle: "Context for this message";
7
- readonly pageNote: "Page label only; this control does not attach page contents.";
7
+ readonly pageNote: "The agent receives this page name with your message, not the page contents.";
8
8
  readonly removeFile: "Remove {{name}}";
9
9
  readonly closeContext: "Close context";
10
10
  readonly currentPage: "Current page";
@@ -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
- /** The narrow `BroadcastChannel` surface the guard uses (injectable for tests). */
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
- /** Fired on every role CHANGE (the caller assumes "leader" until told). */
34
- readonly onRoleChange: (role: TabRole) => void;
16
+ readonly onChange: (snapshot: TabControlSnapshot) => void;
35
17
  readonly heartbeatIntervalMs?: number;
36
18
  readonly takeoverTimeoutMs?: number;
37
- /** Channel seam; return `null` for "unsupported" (guard disabled). */
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;
@@ -1,8 +1,6 @@
1
1
  import { TabRole } from './tab-leadership.ts';
2
- /**
3
- * @param chatId The mount-time chat id — the persisted server session if one
4
- * was already known at mount, else a per-tab `belong-chat-<nanoid>`
5
- * placeholder. Used only as the channel key until the real server session id
6
- * is persisted.
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: the older pages the reader
43
- * scrolled in ABOVE it. Found by the page's first row id; nothing when the
44
- * page does not line up with the screen (then it is merged as a whole).
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: <T extends {
65
+ export declare const splitOlderPrefix: <R extends {
47
66
  readonly id: string;
48
- }>(loaded: readonly {
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
  };