@burdenoff/fe-libs 2026.1007.4 → 2026.1007.6

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 (166) hide show
  1. package/dist/chrome/AutoBreadcrumbs.d.ts.map +1 -1
  2. package/dist/chrome/AutoBreadcrumbs.js +65 -76
  3. package/dist/chrome/Breadcrumb.d.ts.map +1 -1
  4. package/dist/chrome/Breadcrumbs.d.ts.map +1 -1
  5. package/dist/chrome/Breadcrumbs.js +47 -46
  6. package/dist/chrome/ContextSwitcher.js +86 -86
  7. package/dist/chrome/HeaderBar.d.ts.map +1 -1
  8. package/dist/chrome/HeaderBar.js +111 -107
  9. package/dist/chrome/HeaderThemeSwitcher.d.ts.map +1 -1
  10. package/dist/chrome/HeaderThemeSwitcher.js +46 -45
  11. package/dist/chrome/LanguageSwitcher.js +4 -4
  12. package/dist/chrome/MobileTabBar.js +4 -4
  13. package/dist/chrome/PageHeader.d.ts.map +1 -1
  14. package/dist/chrome/PageHeader.js +32 -30
  15. package/dist/chrome/PersonaSurfaceControls.js +8 -8
  16. package/dist/chrome/ProductSideNav.js +6 -6
  17. package/dist/chrome/ProfileSwitcher.d.ts.map +1 -1
  18. package/dist/chrome/ProfileSwitcher.js +89 -88
  19. package/dist/chrome/SideNavigation.js +4 -4
  20. package/dist/chrome/Tabs.d.ts.map +1 -1
  21. package/dist/chrome/Tabs.js +30 -29
  22. package/dist/chrome/breadcrumbLabel.d.ts +10 -0
  23. package/dist/chrome/breadcrumbLabel.d.ts.map +1 -0
  24. package/dist/chrome/breadcrumbLabel.js +31 -0
  25. package/dist/chrome/contextSwitcher/TriggerButton.d.ts.map +1 -1
  26. package/dist/chrome/contextSwitcher/TriggerButton.js +40 -36
  27. package/dist/chrome/notificationCenter/BellButton.d.ts.map +1 -1
  28. package/dist/chrome/notificationCenter/BellButton.js +29 -25
  29. package/dist/chrome/shellLabelManifest.d.ts +27 -0
  30. package/dist/chrome/shellLabelManifest.d.ts.map +1 -0
  31. package/dist/chrome/sideNavigation/SidebarHeader.d.ts.map +1 -1
  32. package/dist/chrome/sideNavigation/SidebarHeader.js +23 -22
  33. package/dist/shared/assistant/api.d.ts +11 -0
  34. package/dist/shared/assistant/api.d.ts.map +1 -1
  35. package/dist/shared/assistant/api.js +6 -2
  36. package/dist/shared/assistant/appControls/languageReply.d.ts +6 -1
  37. package/dist/shared/assistant/appControls/languageReply.d.ts.map +1 -1
  38. package/dist/shared/assistant/conversation.d.ts +14 -0
  39. package/dist/shared/assistant/conversation.d.ts.map +1 -1
  40. package/dist/shared/assistant/createSandboxAssistantTransport.d.ts +8 -1
  41. package/dist/shared/assistant/createSandboxAssistantTransport.d.ts.map +1 -1
  42. package/dist/shared/assistant/createSandboxAssistantTransport.js +70 -51
  43. package/dist/shared/assistant/history/historyMapping.d.ts.map +1 -1
  44. package/dist/shared/assistant/history/historyMapping.js +19 -12
  45. package/dist/shared/assistant/i18nManifest.d.ts +26 -5
  46. package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
  47. package/dist/shared/assistant/i18nManifest.js +36 -22
  48. package/dist/shared/assistant/index.d.ts +7 -0
  49. package/dist/shared/assistant/index.d.ts.map +1 -1
  50. package/dist/shared/assistant/localUiCommandCopy.d.ts +23 -0
  51. package/dist/shared/assistant/localUiCommandCopy.d.ts.map +1 -1
  52. package/dist/shared/assistant/localUiCommandCopy.js +60 -23
  53. package/dist/shared/assistant/localUiCommands.d.ts +29 -0
  54. package/dist/shared/assistant/localUiCommands.d.ts.map +1 -1
  55. package/dist/shared/assistant/localUiCommands.js +18 -7
  56. package/dist/shared/assistant/productCopy.d.ts +78 -0
  57. package/dist/shared/assistant/productCopy.d.ts.map +1 -0
  58. package/dist/shared/assistant/productCopy.js +45 -0
  59. package/dist/shared/assistant/types.d.ts +19 -8
  60. package/dist/shared/assistant/types.d.ts.map +1 -1
  61. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  62. package/dist/shared/assistant/ui/AssistantChatArea.js +1479 -1140
  63. package/dist/shared/assistant/ui/AssistantEmptyState.d.ts.map +1 -1
  64. package/dist/shared/assistant/ui/AssistantEmptyState.js +30 -22
  65. package/dist/shared/assistant/ui/AssistantHeader.d.ts.map +1 -1
  66. package/dist/shared/assistant/ui/AssistantHeader.js +46 -45
  67. package/dist/shared/assistant/ui/AssistantMarkdownRenderer.d.ts +18 -3
  68. package/dist/shared/assistant/ui/AssistantMarkdownRenderer.d.ts.map +1 -1
  69. package/dist/shared/assistant/ui/AssistantMarkdownRenderer.js +1 -1
  70. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts +5 -0
  71. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts.map +1 -1
  72. package/dist/shared/assistant/ui/AssistantMessageItem.js +89 -84
  73. package/dist/shared/assistant/ui/AssistantMessageList.d.ts +5 -0
  74. package/dist/shared/assistant/ui/AssistantMessageList.d.ts.map +1 -1
  75. package/dist/shared/assistant/ui/AssistantMessageList.js +26 -25
  76. package/dist/shared/assistant/ui/AssistantUiOfferLink.d.ts +45 -0
  77. package/dist/shared/assistant/ui/AssistantUiOfferLink.d.ts.map +1 -0
  78. package/dist/shared/assistant/ui/AssistantUiOfferLink.js +56 -0
  79. package/dist/shared/assistant/ui/assistantOverlayState.d.ts +9 -0
  80. package/dist/shared/assistant/ui/assistantOverlayState.d.ts.map +1 -1
  81. package/dist/shared/assistant/ui/assistantOverlayState.js +37 -28
  82. package/dist/shared/assistant/ui/composer/AssistantConnectSourceItem.d.ts.map +1 -1
  83. package/dist/shared/assistant/ui/composer/AssistantConnectSourceItem.js +1 -1
  84. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +5 -0
  85. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
  86. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +12 -11
  87. package/dist/shared/assistant/ui/voice/VoiceConversationView.d.ts +6 -1
  88. package/dist/shared/assistant/ui/voice/VoiceConversationView.d.ts.map +1 -1
  89. package/dist/shared/assistant/ui/voice/VoiceConversationView.js +7 -7
  90. package/dist/shared/assistant/ui/voice/VoiceTranscriptDrawer.d.ts +6 -1
  91. package/dist/shared/assistant/ui/voice/VoiceTranscriptDrawer.d.ts.map +1 -1
  92. package/dist/shared/assistant/ui/voice/VoiceTranscriptDrawer.js +15 -12
  93. package/dist/shared/assistant/uiActions/actOnResolve.d.ts +108 -0
  94. package/dist/shared/assistant/uiActions/actOnResolve.d.ts.map +1 -0
  95. package/dist/shared/assistant/uiActions/actOnResolve.js +51 -0
  96. package/dist/shared/assistant/uiActions/linkContext.d.ts +29 -0
  97. package/dist/shared/assistant/uiActions/linkContext.d.ts.map +1 -1
  98. package/dist/shared/assistant/uiActions/linkContext.js +37 -10
  99. package/dist/shared/assistant/uiActions/navIntent.d.ts +58 -0
  100. package/dist/shared/assistant/uiActions/navIntent.d.ts.map +1 -0
  101. package/dist/shared/assistant/uiActions/navIntent.js +79 -0
  102. package/dist/shared/assistant/uiActions/navigateAction.d.ts +6 -1
  103. package/dist/shared/assistant/uiActions/navigateAction.d.ts.map +1 -1
  104. package/dist/shared/assistant/uiActions/navigateAction.js +18 -14
  105. package/dist/shared/assistant/uiActions/navigationOutcome.d.ts +16 -2
  106. package/dist/shared/assistant/uiActions/navigationOutcome.d.ts.map +1 -1
  107. package/dist/shared/assistant/uiActions/navigationOutcome.js +6 -2
  108. package/dist/shared/assistant/uiActions/offerYesOnSurface.d.ts +39 -0
  109. package/dist/shared/assistant/uiActions/offerYesOnSurface.d.ts.map +1 -0
  110. package/dist/shared/assistant/uiActions/offerYesOnSurface.js +34 -0
  111. package/dist/shared/assistant/uiActions/uiCatalogue.d.ts +14 -0
  112. package/dist/shared/assistant/uiActions/uiCatalogue.d.ts.map +1 -1
  113. package/dist/shared/assistant/uiActions/uiCatalogue.js +23 -3
  114. package/dist/shared/assistant/uiActions/uiOffers.d.ts +249 -0
  115. package/dist/shared/assistant/uiActions/uiOffers.d.ts.map +1 -0
  116. package/dist/shared/assistant/uiActions/uiOffers.js +195 -0
  117. package/dist/shared/assistant/writeProposals.d.ts +6 -0
  118. package/dist/shared/assistant/writeProposals.d.ts.map +1 -1
  119. package/dist/shared/assistant/writeReplyBinder.d.ts +40 -0
  120. package/dist/shared/assistant/writeReplyBinder.d.ts.map +1 -1
  121. package/dist/shared/assistant/writeReplyBinder.js +100 -83
  122. package/dist/shared/assistant/writeReplySend.d.ts +14 -0
  123. package/dist/shared/assistant/writeReplySend.d.ts.map +1 -1
  124. package/dist/shared/assistant/writeReplySend.js +32 -29
  125. package/dist/shared/components/ContextConversationWidget.js +1 -1
  126. package/dist/shared/events/sinks/RybbitSink.d.ts.map +1 -1
  127. package/dist/shared/events/sinks/RybbitSink.js +66 -69
  128. package/dist/shared/hooks/index.d.ts +2 -0
  129. package/dist/shared/hooks/index.d.ts.map +1 -1
  130. package/dist/shared/navigation/unsavedChanges.d.ts +83 -0
  131. package/dist/shared/navigation/unsavedChanges.d.ts.map +1 -0
  132. package/dist/shared/navigation/unsavedChanges.js +46 -0
  133. package/dist/shared/providers/AppShellProvider.d.ts +17 -0
  134. package/dist/shared/providers/AppShellProvider.d.ts.map +1 -1
  135. package/dist/shared/providers/AppShellProvider.js +188 -180
  136. package/dist/shared/providers/shell/I18nProvider.d.ts +92 -4
  137. package/dist/shared/providers/shell/I18nProvider.d.ts.map +1 -1
  138. package/dist/shared/providers/shell/I18nProvider.js +187 -79
  139. package/dist/shared/providers/shell/ProfileI18nBridge.d.ts +18 -2
  140. package/dist/shared/providers/shell/ProfileI18nBridge.d.ts.map +1 -1
  141. package/dist/shared/providers/shell/ProfileI18nBridge.js +55 -41
  142. package/dist/shared/providers/shell/directionMode.d.ts +25 -0
  143. package/dist/shared/providers/shell/directionMode.d.ts.map +1 -0
  144. package/dist/shared/providers/shell/directionMode.js +34 -0
  145. package/dist/shared/providers/shell/index.d.ts +4 -2
  146. package/dist/shared/providers/shell/index.d.ts.map +1 -1
  147. package/dist/shared/providers/shell/translationLayers.d.ts +30 -0
  148. package/dist/shared/providers/shell/translationLayers.d.ts.map +1 -0
  149. package/dist/shared/providers/shell/translationLayers.js +35 -0
  150. package/dist/shared/providers/shell/translationStore.d.ts +55 -0
  151. package/dist/shared/providers/shell/translationStore.d.ts.map +1 -0
  152. package/dist/shared/providers/shell/translationStore.js +100 -0
  153. package/dist/shared/providers/shell/useShellLabel.d.ts +13 -1
  154. package/dist/shared/providers/shell/useShellLabel.d.ts.map +1 -1
  155. package/dist/shared/providers/shell/useShellLabel.js +10 -9
  156. package/dist/shared-assistant.js +244 -237
  157. package/dist/shared-hooks.js +10 -9
  158. package/dist/shared-providers-shell.js +20 -19
  159. package/dist/shared.js +20 -19
  160. package/dist/ui/boff-ui2.d.ts.map +1 -1
  161. package/dist/ui/cta-overflow-menu.d.ts.map +1 -1
  162. package/dist/ui/cta-overflow-menu.js +20 -18
  163. package/dist/ui/guidance.d.ts +1 -1
  164. package/dist/ui/guidance.d.ts.map +1 -1
  165. package/dist/ui/guidance.js +53 -52
  166. package/package.json +3 -2
@@ -7,21 +7,21 @@ import { useEffect as o, useRef as s } from "react";
7
7
  import { ArrowRight as c, Download as l, X as u } from "lucide-react";
8
8
  import { jsx as d, jsxs as f } from "react/jsx-runtime";
9
9
  //#region src/shared/assistant/ui/voice/VoiceTranscriptDrawer.tsx
10
- var p = ({ turns: p, onClose: m, onSave: h, onContinueInChat: g, closeOnEscape: _ = !1, onShowEarlier: v, showEarlierDisabled: y = !1 }) => {
11
- let b = t(), x = s(null);
12
- return e(x, { fallbackSelector: `[${n}]` }), o(() => {
10
+ var p = ({ turns: p, onClose: m, onSave: h, onContinueInChat: g, closeOnEscape: _ = !1, onShowEarlier: v, showEarlierDisabled: y = !1, renderAfterTurn: b }) => {
11
+ let x = t(), S = s(null);
12
+ return e(S, { fallbackSelector: `[${n}]` }), o(() => {
13
13
  if (!_) return;
14
14
  let e = (e) => {
15
15
  if (e.key !== "Escape" || document.querySelector("[role=\"alertdialog\"]")) return;
16
- let t = x.current?.closest(`[${n}]`), i = document.activeElement;
16
+ let t = S.current?.closest(`[${n}]`), i = document.activeElement;
17
17
  r(t ?? null, i) && (e.preventDefault(), e.stopPropagation(), m());
18
18
  };
19
19
  return document.addEventListener("keydown", e, !0), () => document.removeEventListener("keydown", e, !0);
20
20
  }, [_, m]), /* @__PURE__ */ f("div", {
21
- ref: x,
21
+ ref: S,
22
22
  className: "absolute inset-0 z-30 flex flex-col bg-bg-sunken/95 backdrop-blur-sm",
23
23
  role: "dialog",
24
- "aria-label": b("voiceSession.transcriptTitle", "Voice transcript"),
24
+ "aria-label": x("voiceSession.transcriptTitle", "Voice transcript"),
25
25
  "data-testid": "assistant-voice-transcript",
26
26
  children: [
27
27
  /* @__PURE__ */ f("div", {
@@ -30,16 +30,16 @@ var p = ({ turns: p, onClose: m, onSave: h, onContinueInChat: g, closeOnEscape:
30
30
  className: "min-w-0",
31
31
  children: [/* @__PURE__ */ d("h2", {
32
32
  className: "text-sm font-semibold text-text-primary",
33
- children: b("voiceSession.transcript", "Voice conversation")
33
+ children: x("voiceSession.transcript", "Voice conversation")
34
34
  }), /* @__PURE__ */ d("p", {
35
35
  className: "truncate text-xs text-text-muted",
36
- children: b("voiceSession.transcriptHint", "Spoken turns in this conversation — kept out of your typed chat.")
36
+ children: x("voiceSession.transcriptHint", "Spoken turns in this conversation — kept out of your typed chat.")
37
37
  })]
38
38
  }), /* @__PURE__ */ d("button", {
39
39
  type: "button",
40
40
  onClick: m,
41
41
  className: "flex size-8 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
42
- "aria-label": b("voiceSession.transcriptClose", "Close the transcript"),
42
+ "aria-label": x("voiceSession.transcriptClose", "Close the transcript"),
43
43
  "data-testid": "assistant-voice-transcript-close",
44
44
  children: /* @__PURE__ */ d(u, { className: "size-4" })
45
45
  })]
@@ -48,7 +48,10 @@ var p = ({ turns: p, onClose: m, onSave: h, onContinueInChat: g, closeOnEscape:
48
48
  onShowEarlier: v,
49
49
  disabled: y
50
50
  }) : null,
51
- /* @__PURE__ */ d(i, { turns: p }),
51
+ /* @__PURE__ */ d(i, {
52
+ turns: p,
53
+ renderAfterTurn: b
54
+ }),
52
55
  (h || g) && p.length > 0 ? /* @__PURE__ */ f("div", {
53
56
  className: "flex items-center justify-end gap-2 border-t border-border-subtle px-4 py-3",
54
57
  children: [h ? /* @__PURE__ */ f("button", {
@@ -59,13 +62,13 @@ var p = ({ turns: p, onClose: m, onSave: h, onContinueInChat: g, closeOnEscape:
59
62
  children: [/* @__PURE__ */ d(l, {
60
63
  className: "size-3.5",
61
64
  "aria-hidden": "true"
62
- }), b("voiceSession.save", "Save transcript")]
65
+ }), x("voiceSession.save", "Save transcript")]
63
66
  }) : null, g ? /* @__PURE__ */ f("button", {
64
67
  type: "button",
65
68
  onClick: g,
66
69
  className: "flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-fg transition-opacity hover:opacity-90 focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
67
70
  "data-testid": "assistant-voice-continue-in-chat",
68
- children: [b("voiceSession.continueInChat", "Continue in chat"), /* @__PURE__ */ d(c, {
71
+ children: [x("voiceSession.continueInChat", "Continue in chat"), /* @__PURE__ */ d(c, {
69
72
  className: "size-3.5",
70
73
  "aria-hidden": "true"
71
74
  })]
@@ -0,0 +1,108 @@
1
+ import { UnsavedChange } from '../../navigation/unsavedChanges';
2
+ import { LocalUiCommandOptions } from '../localUiCommands';
3
+ import { NavIntent } from './navIntent';
4
+ import { LiveUiOffer } from './uiOffers';
5
+ /**
6
+ * ★ BOFF-8060 (N3, design §8): act-on-resolve — the person asked explicitly to
7
+ * be taken somewhere, the model answered with exactly one offered page, and
8
+ * the panel opens it without asking a second time.
9
+ *
10
+ * Decided ONCE, when the turn poller has seen the turn complete and made its
11
+ * final read; never on a later poll, a reopen or a resume. ALL guards must
12
+ * hold; any one failing keeps the page an ordinary OFFER ("Open {page}"), so a
13
+ * wrong "no" costs one tap and a wrong "yes" is what the guards exist to stop.
14
+ *
15
+ * - R1 explicit intent: the person's own sentence THIS turn matched the frozen
16
+ * grammar (`parseNavIntent`) — never a chip, host-queued prompt, retry or
17
+ * redirect remainder (the caller passes null for those).
18
+ * - R2 exactly one offer bound to the turn, live and resolvable now.
19
+ * - R2b relevance: a content word the person named is among the page's own
20
+ * registry words — an offer steered elsewhere stays an offer.
21
+ * - R3 nothing pending: no write proposal waits in the conversation, AND the
22
+ * turn could not have raised one (sent in a read mode, served by a read
23
+ * sandbox). Proposal discovery runs AFTER a turn settles, so at
24
+ * completion only a read transport proves "this turn raised none".
25
+ * - R4 nothing moved: the location, the open conversation, the workspace and
26
+ * the signed-in actor are what they were at send; the panel is mounted
27
+ * and the tab visible.
28
+ * - R5 nothing unsaved: the N4 leave-page guard (`listUnsavedChanges`)
29
+ * reports an empty list. ★★ It FAILS CLOSED: without a guard (null —
30
+ * which is also what a product WITHOUT the `leaveGuard` attestation
31
+ * gets, see `n4LeaveGuard`), or
32
+ * when the guard throws or answers anything but a well-formed list, the
33
+ * panel never acts — and nothing may call such a turn act-on-resolve.
34
+ * A non-empty list keeps the offer and names what is unsaved.
35
+ * - R6 not already there: then the panel says so (N1a copy) and stays.
36
+ *
37
+ * Pure: the caller reads every live value at the decision point.
38
+ */
39
+ /** N4's `listUnsavedChanges()`: the unsaved changes on the page right now. */
40
+ export type UnsavedChangesProbe = () => readonly UnsavedChange[];
41
+ /**
42
+ * ★★ The N4 leave-page guard R5 reads (design §8 R5; `ui-navigation.md` §7):
43
+ * `listUnsavedChanges`, the page's live registry (`useUnsavedChanges`) — but
44
+ * ONLY when the product attests that its editors register there
45
+ * (`LocalUiCommandOptions.leaveGuard === true`).
46
+ *
47
+ * The registry cannot tell "nothing is unsaved" from "this product's editors
48
+ * never call `useUnsavedChanges`": both read `[]`. Without the attestation an
49
+ * empty list proves nothing, so the guard is ABSENT (null) and R5 fails closed
50
+ * (`R5-absent`) — the panel never acts on its own, and the page stays an
51
+ * offer. A product sets `leaveGuard: true` only in the same release as its
52
+ * editors' `useUnsavedChanges` adoption, with a seam test that pins both.
53
+ */
54
+ export declare function n4LeaveGuard(options: Pick<LocalUiCommandOptions, "leaveGuard"> | null | undefined): UnsavedChangesProbe | null;
55
+ /** Where the person was, and as whom, at one moment (R4). */
56
+ export interface ActOnResolveSnapshot {
57
+ /** `pathname + search`. */
58
+ location: string;
59
+ conversationId: string | null;
60
+ workspaceId: string | null;
61
+ actorId: string | null;
62
+ }
63
+ export interface ActOnResolveInput {
64
+ /** R1: the turn's explicit request, captured at send; null when there was none. */
65
+ intent: NavIntent | null;
66
+ /** R2: the turn's live, resolvable offers (`liveOffersFor`). */
67
+ live: readonly LiveUiOffer[];
68
+ /** R2: the turn's offers not used yet, live or not. */
69
+ unusedCount: number;
70
+ /** R3: write proposals pending in the conversation now. */
71
+ pendingProposals: number;
72
+ /** R3: the mode the turn was SENT in could write. */
73
+ turnWriteCapable: boolean;
74
+ /** R4. */
75
+ atSend: ActOnResolveSnapshot;
76
+ now: ActOnResolveSnapshot;
77
+ mounted: boolean;
78
+ visible: boolean;
79
+ /** R5: N4's guard (`n4LeaveGuard(options)`); null fails closed. */
80
+ unsavedChanges: UnsavedChangesProbe | null;
81
+ /** R6: the person is already on the offered page (or one of its aliases). */
82
+ alreadyThere: (offer: LiveUiOffer) => boolean;
83
+ }
84
+ /** Which guard kept the page an offer. */
85
+ export type ActOnResolveHold = "R1" | "R2" | "R2b" | "R3" | "R4" | "R5-absent" | "R5-unsaved";
86
+ export type ActOnResolveDecision =
87
+ /** Open it (`runNavigation`, `via: 'offer'`, `trigger: 'resolve'`). */
88
+ {
89
+ act: "navigate";
90
+ offer: LiveUiOffer;
91
+ }
92
+ /** R6: say "You're already on {page}", record it, and stay. */
93
+ | {
94
+ act: "already-here";
95
+ offer: LiveUiOffer;
96
+ }
97
+ /**
98
+ * The page stays an offer. `unsaved` is set for `R5-unsaved` only: the
99
+ * changes N4 named, for the "you have unsaved changes" line.
100
+ */
101
+ | {
102
+ act: "keep-offer";
103
+ hold: ActOnResolveHold;
104
+ unsaved?: readonly UnsavedChange[];
105
+ };
106
+ /** The act-on-resolve decision (design §8). Every guard, in order; the first that fails holds. */
107
+ export declare function decideActOnResolve(input: ActOnResolveInput): ActOnResolveDecision;
108
+ //# sourceMappingURL=actOnResolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actOnResolve.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/uiActions/actOnResolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,mBAAmB,GAAG,MAAM,SAAS,aAAa,EAAE,CAAC;AAEjE;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,YAAY,CAAC,GAAG,IAAI,GAAG,SAAS,GACpE,mBAAmB,GAAG,IAAI,CAE5B;AAED,6DAA6D;AAC7D,MAAM,WAAW,oBAAoB;IACnC,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,gEAAgE;IAChE,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAC7B,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,gBAAgB,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU;IACV,MAAM,EAAE,oBAAoB,CAAC;IAC7B,GAAG,EAAE,oBAAoB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,mEAAmE;IACnE,cAAc,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC3C,6EAA6E;IAC7E,YAAY,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC;CAC/C;AAED,0CAA0C;AAC1C,MAAM,MAAM,gBAAgB,GACxB,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,WAAW,GACX,YAAY,CAAC;AAEjB,MAAM,MAAM,oBAAoB;AAC9B,uEAAuE;AACrE;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE;AACzC,+DAA+D;GAC7D;IAAE,GAAG,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE;AAC7C;;;GAGG;GACD;IACE,GAAG,EAAE,YAAY,CAAC;IAClB,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CACpC,CAAC;AAkCN,kGAAkG;AAClG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,oBAAoB,CA2BjF"}
@@ -0,0 +1,51 @@
1
+ import { listUnsavedChanges as e } from "../../navigation/unsavedChanges.js";
2
+ import { navIntentRelevant as t } from "./navIntent.js";
3
+ //#region src/shared/assistant/uiActions/actOnResolve.ts
4
+ function n(t) {
5
+ return t?.leaveGuard === !0 ? e : null;
6
+ }
7
+ var r = (e) => ({
8
+ act: "keep-offer",
9
+ hold: e
10
+ }), i = (e, t) => e.location === t.location && e.conversationId !== null && e.conversationId === t.conversationId && e.workspaceId === t.workspaceId && e.actorId !== null && e.actorId === t.actorId;
11
+ function a(e) {
12
+ try {
13
+ let t = e();
14
+ if (!Array.isArray(t)) return null;
15
+ let n = [];
16
+ for (let e of t) {
17
+ if (typeof e != "object" || !e || !("id" in e) || !("label" in e) || typeof e.id != "string" || typeof e.label != "string") return null;
18
+ n.push({
19
+ id: e.id,
20
+ label: e.label
21
+ });
22
+ }
23
+ return n;
24
+ } catch {
25
+ return null;
26
+ }
27
+ }
28
+ function o(e) {
29
+ let { intent: n } = e;
30
+ if (!n) return r("R1");
31
+ let [o] = e.live;
32
+ if (!o || e.live.length !== 1 || e.unusedCount !== 1) return r("R2");
33
+ if (!t(n, o.target)) return r("R2b");
34
+ if (e.pendingProposals !== 0 || e.turnWriteCapable || o.offer.transport !== "read") return r("R3");
35
+ if (!e.mounted || !e.visible || !i(e.atSend, e.now)) return r("R4");
36
+ if (!e.unsavedChanges) return r("R5-absent");
37
+ let s = a(e.unsavedChanges);
38
+ return s === null ? r("R5-absent") : s.length > 0 ? {
39
+ act: "keep-offer",
40
+ hold: "R5-unsaved",
41
+ unsaved: s
42
+ } : e.alreadyThere(o) ? {
43
+ act: "already-here",
44
+ offer: o
45
+ } : {
46
+ act: "navigate",
47
+ offer: o
48
+ };
49
+ }
50
+ //#endregion
51
+ export { o as decideActOnResolve, n as n4LeaveGuard };
@@ -36,10 +36,37 @@ export interface PendingChoice {
36
36
  */
37
37
  candidateIds: readonly string[];
38
38
  }
39
+ /** ★ BOFF-8060 (N3): an offered page among the reply's targets, by its registry path. */
40
+ export interface OfferedTarget {
41
+ offerId: string;
42
+ /** The registry entry, re-validated against the live registry by the caller. */
43
+ target: LocalDestination;
44
+ }
39
45
  export interface NavigationContext {
40
46
  links: ResolvedLinks;
41
47
  pendingChoice: PendingChoice | null;
48
+ /**
49
+ * ★ BOFF-8060 (N3): which of `links.targets` are offered pages (by path).
50
+ * Absent or empty: no offer, and "take me there" is N1b's.
51
+ */
52
+ offers?: ReadonlyArray<{
53
+ path: string;
54
+ offerId: string;
55
+ }>;
42
56
  }
57
+ /**
58
+ * ★ BOFF-8060 (N3, design §3.3): the reply's live, resolvable offers join its
59
+ * targets. De-duplicated by path against the inline links — an inline link to
60
+ * the same page BECOMES the offer target (the registry entry, `via: 'offer'`
61
+ * wins) — and appended after them otherwise. One offer per page: the first.
62
+ */
63
+ export declare function withOfferedTargets(links: ResolvedLinks, offers: readonly OfferedTarget[]): {
64
+ links: ResolvedLinks;
65
+ offers: Array<{
66
+ path: string;
67
+ offerId: string;
68
+ }>;
69
+ };
43
70
  /**
44
71
  * @param text what the person SEES of the message (`spokenTurnText`), never raw
45
72
  * content: a link inside a tool-step description is not a link they saw.
@@ -48,5 +75,7 @@ export declare function buildNavigationContext(input: {
48
75
  reply: SurfaceMessage | null;
49
76
  text: string;
50
77
  resolve: ResolveContext;
78
+ /** ★ N3: the reply's live offers, already re-validated (`liveOffersFor`). */
79
+ offers?: readonly OfferedTarget[];
51
80
  }): NavigationContext | null;
52
81
  //# sourceMappingURL=linkContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"linkContext.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/uiActions/linkContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;GAUG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EACL,CAAC;QACC,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC5B,SAAS,CAAC;CACf;AAYD,gGAAgG;AAChG,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,cAAc,EAC3D,QAAQ,EAAE,SAAS,CAAC,EAAE,EACtB,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,CAAC,GAAG,IAAI,CAQV;AAaD,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,SAAS,gBAAgB,EAAE,GACtC,IAAI,CAWN;AAED,eAAO,MAAM,gBAAgB,GAC3B,WAAW,MAAM,KAChB,gBAAgB,EAAE,GAAG,SAAqC,CAAC;AAE9D,0BAA0B;AAC1B,eAAO,MAAM,mBAAmB,QAAO,IAAyB,CAAC;AAIjE,MAAM,WAAW,aAAa;IAC5B,wIAAwI;IACxI,UAAU,EAAE,aAAa,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D;;;;OAIG;IACH,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;CACrC;AAiDD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,CAAC;CACzB,GAAG,iBAAiB,GAAG,IAAI,CAI3B"}
1
+ {"version":3,"file":"linkContext.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/uiActions/linkContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;GAUG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EACL,CAAC;QACC,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC5B,SAAS,CAAC;CACf;AAYD,gGAAgG;AAChG,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,cAAc,EAC3D,QAAQ,EAAE,SAAS,CAAC,EAAE,EACtB,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,CAAC,GAAG,IAAI,CAQV;AAaD,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,SAAS,gBAAgB,EAAE,GACtC,IAAI,CAWN;AAED,eAAO,MAAM,gBAAgB,GAC3B,WAAW,MAAM,KAChB,gBAAgB,EAAE,GAAG,SAAqC,CAAC;AAE9D,0BAA0B;AAC1B,eAAO,MAAM,mBAAmB,QAAO,IAAyB,CAAC;AAIjE,MAAM,WAAW,aAAa;IAC5B,wIAAwI;IACxI,UAAU,EAAE,aAAa,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D;;;;OAIG;IACH,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,yFAAyF;AACzF,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,SAAS,aAAa,EAAE,GAC/B;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAW5E;AAiDD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,CAAC;IACxB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CACnC,GAAG,iBAAiB,GAAG,IAAI,CAO3B"}
@@ -23,15 +23,34 @@ function c(e, t) {
23
23
  s.delete(e.value);
24
24
  }
25
25
  }
26
- var l = (e) => s.get(e), u = () => s.clear(), d = null, f = (e) => {
27
- if (d?.text === e) return d.links;
26
+ var l = (e) => s.get(e), u = () => s.clear();
27
+ function d(e, t) {
28
+ let n = [...e.targets], r = [];
29
+ for (let { offerId: e, target: i } of t) {
30
+ if (r.some((e) => e.path === i.path)) continue;
31
+ let t = n.findIndex((e) => e.path === i.path);
32
+ t >= 0 ? n[t] = i : n.push(i), r.push({
33
+ path: i.path,
34
+ offerId: e
35
+ });
36
+ }
37
+ return {
38
+ links: {
39
+ targets: n,
40
+ unresolved: e.unresolved
41
+ },
42
+ offers: r
43
+ };
44
+ }
45
+ var f = null, p = (e) => {
46
+ if (f?.text === e) return f.links;
28
47
  let t = r(e);
29
- return d = {
48
+ return f = {
30
49
  text: e,
31
50
  links: t
32
51
  }, t;
33
52
  };
34
- function p(t, r) {
53
+ function m(t, r) {
35
54
  let i = t.metadata?.localAction;
36
55
  if (typeof i != "object" || !i) return null;
37
56
  let a = i;
@@ -50,11 +69,19 @@ function p(t, r) {
50
69
  candidateIds: c
51
70
  };
52
71
  }
53
- function m(e) {
54
- return e.reply ? {
55
- links: t(f(e.text), e.resolve),
56
- pendingChoice: p(e.reply, e.resolve)
57
- } : null;
72
+ function h(e) {
73
+ if (!e.reply) return null;
74
+ let n = t(p(e.text), e.resolve), r = m(e.reply, e.resolve);
75
+ if (!e.offers || e.offers.length === 0) return {
76
+ links: n,
77
+ pendingChoice: r
78
+ };
79
+ let i = d(n, e.offers);
80
+ return {
81
+ links: i.links,
82
+ pendingChoice: r,
83
+ offers: i.offers
84
+ };
58
85
  }
59
86
  //#endregion
60
- export { m as buildNavigationContext, u as clearPresentedLists, a as latestReplyOnSurface, l as presentedListFor, c as rememberPresentedList };
87
+ export { h as buildNavigationContext, u as clearPresentedLists, a as latestReplyOnSurface, l as presentedListFor, c as rememberPresentedList, d as withOfferedTargets };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * ★ BOFF-8060 (N3, design §8 R1): is what the person said THIS turn an
3
+ * explicit, imperative request to be taken somewhere?
4
+ *
5
+ * A FROZEN grammar with 0 false matches as its target: it is the first guard of
6
+ * act-on-resolve, the one case where the panel navigates after a model turn
7
+ * without a second question. Every doubt answers null, and a null only means
8
+ * the page stays an OFFER ("Open {page}") — nothing is lost.
9
+ *
10
+ * Imperative only, as a WHOLE utterance, in English:
11
+ *
12
+ * - `(please |can you |could you )?(take|bring|get) me (to|into) <x>( please)?`
13
+ * - `(please )?(go|navigate|jump|head) to <x>( please)?`
14
+ * - `(please )?open (the )?<x> (page|screen|section|settings)( please)?`
15
+ * - `(please )?show me (the )?<x> (page|screen|section)( please)?`
16
+ *
17
+ * Never: a question (a trailing `?` is allowed only on the `can you` /
18
+ * `could you` forms; any other question mark anywhere is refused); a negation;
19
+ * a conjunction or a clause break anywhere ("…and delete the old one",
20
+ * "…, rename it"), or `then` / `also`; an idiom that goes nowhere ("go to
21
+ * sleep", "head to head", "get me to understand…"); `<x>` longer than 12
22
+ * words; a newline. "where is…?" and "is there a page…" are never explicit.
23
+ *
24
+ * Pure: no React, no DOM, no registry. Relevance (R2b) is `navIntentRelevant`.
25
+ */
26
+ /** What the person asked to be taken to, as they named it. */
27
+ export interface NavIntent {
28
+ /** `<x>`, lower-cased, spaces collapsed. */
29
+ object: string;
30
+ /** Its content words, stop words removed and plurals folded (R2b). */
31
+ contentWords: string[];
32
+ }
33
+ /** The longest `<x>` the grammar accepts, in words. */
34
+ export declare const NAV_INTENT_OBJECT_MAX_WORDS = 12;
35
+ /** Simple plural folding: "templates" → "template", "policies" → "policy". */
36
+ export declare function foldNavIntentPlural(word: string): string;
37
+ /** Lower-case word tokens of a registry string, camelCase and ids split. */
38
+ export declare function navIntentWords(value: string): string[];
39
+ /**
40
+ * The person's sentence as one explicit "take me to <x>", or null.
41
+ *
42
+ * @param locale what it was typed or said in — English only (Hindi and Tamil
43
+ * wait for N7 and their own blind sets).
44
+ */
45
+ export declare function parseNavIntent(text: string, locale: string | null | undefined): NavIntent | null;
46
+ /** The registry's own words for a page (R2b): label, context and id. */
47
+ export interface NavIntentTarget {
48
+ id: string;
49
+ label: string;
50
+ context?: string;
51
+ }
52
+ /**
53
+ * R2b: at least one content word of what the person named appears among the
54
+ * target's registry label, context or id words (plurals folded). An offer for a
55
+ * page the person did not name is never acted on — it stays an offer.
56
+ */
57
+ export declare function navIntentRelevant(intent: NavIntent, target: NavIntentTarget): boolean;
58
+ //# sourceMappingURL=navIntent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navIntent.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/uiActions/navIntent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,uDAAuD;AACvD,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAoI9C,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAOtD;AAOD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAChC,SAAS,GAAG,IAAI,CA+ClB;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAKrF"}
@@ -0,0 +1,79 @@
1
+ //#region src/shared/assistant/uiActions/navIntent.ts
2
+ var e = 12, t = (e) => e == null || /^en(?:[-_]|$)/i.test(e.trim()), n = /\b(?:not|never|no|don't|dont|do not|doesn't|doesnt|didn't|didnt|can't|cant|cannot|won't|wont|shouldn't|shouldnt|stop)\b/, r = /\b(?:then|also|afterwards|after that|before that)\b/, i = /\b(?:and|or|but|nor|plus)\b|[&+]/, a = /[,;:\u2013\u2014]|\s-+\s/, o = new Set([
3
+ "bed",
4
+ "breakfast",
5
+ "brunch",
6
+ "dinner",
7
+ "extremes",
8
+ "hell",
9
+ "lunch",
10
+ "pieces",
11
+ "sleep",
12
+ "town",
13
+ "trouble",
14
+ "war",
15
+ "waste"
16
+ ]), s = new Set([
17
+ "accept",
18
+ "agree",
19
+ "appreciate",
20
+ "believe",
21
+ "care",
22
+ "consider",
23
+ "decide",
24
+ "feel",
25
+ "focus",
26
+ "imagine",
27
+ "know",
28
+ "learn",
29
+ "realise",
30
+ "realize",
31
+ "remember",
32
+ "think",
33
+ "trust",
34
+ "understand",
35
+ "wonder"
36
+ ]), c = /^(?:please )?head to head\b/, l = /^(?:(please|can you|could you) )?(?:please )?(?:take|bring|get) me (?:to|into) (.+)$/, u = /^(?:please )?(?:go|navigate|jump|head) to (.+)$/, d = /^(?:please )?open (?:the )?(.+) (?:page|screen|section|settings)$/, f = /^(?:please )?show me (?:the )?(.+) (?:page|screen|section)$/, p = new Set(/* @__PURE__ */ "a.about.all.an.any.area.at.by.can.do.find.for.from.i.in.is.it.its.me.my.of.on.one.our.page.part.place.please.screen.section.see.some.that.the.their.there.these.this.those.to.view.we.where.which.with.you.your".split("."));
37
+ function m(e) {
38
+ return e.length > 4 && e.endsWith("ies") ? `${e.slice(0, -3)}y` : e.length > 4 && /(?:ss|sh|ch|x|z)es$/.test(e) ? e.slice(0, -2) : e.length > 3 && e.endsWith("s") && !e.endsWith("ss") ? e.slice(0, -1) : e;
39
+ }
40
+ function h(e) {
41
+ return e.replace(/([a-z0-9])([A-Z])/g, "$1 $2").normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((e) => e.length > 0);
42
+ }
43
+ var g = (e) => h(e).filter((e) => !p.has(e)).map(m);
44
+ function _(e, p) {
45
+ if (typeof e != "string" || !t(p) || /[\r\n\u2028\u2029]/.test(e)) return null;
46
+ let m = e.normalize("NFKC").toLowerCase().replace(/[\u2018\u2019\u02bc]/g, "'").replace(/\s+/g, " ").trim();
47
+ m = m.replace(/[.!]+$/, "").trim();
48
+ let h = m.endsWith("?");
49
+ if (h && (m = m.slice(0, -1).trim()), /[?¿؟?]/.test(m) || (m = m.replace(/,?\s*please$/, "").trim(), m = m.replace(/^please,\s*/, "please "), m.length === 0) || n.test(m) || r.test(m) || i.test(m) || a.test(m) || c.test(m)) return null;
50
+ let _, v = l.exec(m);
51
+ if (v) {
52
+ if (h && v[1] !== "can you" && v[1] !== "could you") return null;
53
+ _ = v[2];
54
+ } else {
55
+ if (h) return null;
56
+ _ = (u.exec(m) ?? d.exec(m) ?? f.exec(m))?.[1];
57
+ }
58
+ if (_ === void 0) return null;
59
+ _ = _.trim();
60
+ let y = _.split(" ").filter((e) => e.length > 0);
61
+ if (y.length === 0 || y.length > 12) return null;
62
+ let b = y[0] === "the" || y[0] === "a" || y[0] === "an" ? y[1] : y[0];
63
+ if (b !== void 0 && (o.has(b) || s.has(b))) return null;
64
+ let x = g(_);
65
+ return x.length === 0 ? null : {
66
+ object: y.join(" "),
67
+ contentWords: x
68
+ };
69
+ }
70
+ function v(e, t) {
71
+ let n = new Set([
72
+ t.label,
73
+ t.context ?? "",
74
+ t.id
75
+ ].flatMap(h).map(m));
76
+ return e.contentWords.some((e) => n.has(e));
77
+ }
78
+ //#endregion
79
+ export { e as NAV_INTENT_OBJECT_MAX_WORDS, m as foldNavIntentPlural, v as navIntentRelevant, h as navIntentWords, _ as parseNavIntent };
@@ -1,4 +1,4 @@
1
- import { AssistantNavigateAction, AssistantNavigateOutcome, AssistantNavigateVia } from '../conversation';
1
+ import { AssistantNavigateAction, AssistantNavigateOfferTrigger, AssistantNavigateOutcome, AssistantNavigateVia } from '../conversation';
2
2
  import { LocalDestination } from '../localUiCommands';
3
3
  import { NavigationOutcome } from './navigationOutcome';
4
4
  /** The server keeps a `localAction` of at most 1024 bytes; stay well inside it. */
@@ -17,6 +17,11 @@ export declare function buildNavigateAction(input: {
17
17
  alreadyHere: boolean;
18
18
  via: AssistantNavigateVia;
19
19
  outcome?: NavigationOutcome;
20
+ /** ★ BOFF-8060 (N3): how an offer was accepted. Kept only with `via: "offer"`. */
21
+ offer?: {
22
+ trigger: AssistantNavigateOfferTrigger;
23
+ offerId: string;
24
+ };
20
25
  }): AssistantNavigateAction;
21
26
  /** The registry label of the page at `path` (its target or its own path), or null. */
22
27
  export declare function labelForPath(destinations: readonly LocalDestination[], path: string): string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"navigateAction.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/uiActions/navigateAction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEzE,mFAAmF;AACnF,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAQhD,wBAAgB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,wBAAwB,CAElF;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,GAAG,EAAE,oBAAoB,CAAC;IAC1B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B,GAAG,uBAAuB,CAgB1B;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAC1B,YAAY,EAAE,SAAS,gBAAgB,EAAE,EACzC,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAOf;AAED,6CAA6C;AAC7C,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,SAAS,gBAAgB,EAAE,EACzC,IAAI,EAAE,MAAM,GACX,gBAAgB,GAAG,IAAI,CAQzB;AAED,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,CAAC;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;CACjG;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,SAAS,cAAc,EAAE,EACnC,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,MAAM,GAAG,IAAI,CAYf"}
1
+ {"version":3,"file":"navigateAction.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/uiActions/navigateAction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,6BAA6B,EAC7B,wBAAwB,EACxB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEzE,mFAAmF;AACnF,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAUhD,wBAAgB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,wBAAwB,CAElF;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,GAAG,EAAE,oBAAoB,CAAC;IAC1B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,kFAAkF;IAClF,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,6BAA6B,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE,GAAG,uBAAuB,CAuB1B;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAC1B,YAAY,EAAE,SAAS,gBAAgB,EAAE,EACzC,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAOf;AAED,6CAA6C;AAC7C,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,SAAS,gBAAgB,EAAE,EACzC,IAAI,EAAE,MAAM,GACX,gBAAgB,GAAG,IAAI,CAQzB;AAED,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,CAAC;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;CACjG;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,SAAS,cAAc,EAAE,EACnC,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,MAAM,GAAG,IAAI,CAYf"}
@@ -1,31 +1,35 @@
1
1
  import { isCurrentPath as e } from "../localUiCommands.js";
2
2
  import { pathnameOf as t } from "./navigationOutcome.js";
3
3
  //#region src/shared/assistant/uiActions/navigateAction.ts
4
- var n = 900, r = 256, i = 128, a = (e) => new TextEncoder().encode(JSON.stringify(e)).length, o = (e) => e.length <= r ? e : t(e).slice(0, r);
5
- function s(e) {
4
+ var n = 900, r = 256, i = 128, a = /^uo_[0-9a-f]{32}$/, o = (e) => new TextEncoder().encode(JSON.stringify(e)).length, s = (e) => e.length <= r ? e : t(e).slice(0, r);
5
+ function c(e) {
6
6
  return e.status;
7
7
  }
8
- function c(e) {
9
- let n = e.outcome && "landedPath" in e.outcome ? t(e.outcome.landedPath) : void 0, c = {
8
+ function l(e) {
9
+ let n = e.outcome && "landedPath" in e.outcome ? t(e.outcome.landedPath) : void 0, l = e.via === "offer" && e.offer && a.test(e.offer.offerId) ? {
10
+ trigger: e.offer.trigger,
11
+ offerId: e.offer.offerId
12
+ } : {}, u = {
10
13
  kind: "navigate",
11
14
  destinationId: e.destinationId.length <= i ? e.destinationId : "",
12
- path: o(e.path),
15
+ path: s(e.path),
13
16
  alreadyHere: e.alreadyHere,
14
17
  via: e.via,
15
- ...e.outcome ? { outcome: s(e.outcome) } : {}
16
- }, l = n !== void 0 && n.length <= r ? {
17
- ...c,
18
+ ...e.outcome ? { outcome: c(e.outcome) } : {},
19
+ ...l
20
+ }, d = n !== void 0 && n.length <= r ? {
21
+ ...u,
18
22
  landedPath: n
19
- } : c;
20
- return a(l) <= 900 ? l : c;
23
+ } : u;
24
+ return o(d) <= 900 ? d : u;
21
25
  }
22
- function l(t, n) {
26
+ function u(t, n) {
23
27
  return t.find((t) => [t.path, ...t.aliases ?? []].some((t) => e(t, n)))?.label ?? null;
24
28
  }
25
- function u(t, n) {
29
+ function d(t, n) {
26
30
  return t.find((t) => [t.path, ...t.aliases ?? []].some((t) => e(t, n))) ?? null;
27
31
  }
28
- function d(e, t) {
32
+ function f(e, t) {
29
33
  for (let n = e.length - 1; n >= 0; --n) {
30
34
  let r = e[n];
31
35
  if (!r || r.role !== "assistant") continue;
@@ -37,4 +41,4 @@ function d(e, t) {
37
41
  return null;
38
42
  }
39
43
  //#endregion
40
- export { n as NAVIGATE_RECORD_BUDGET_BYTES, c as buildNavigateAction, u as destinationForPath, l as labelForPath, d as newestAssistantOnSurface, s as outcomeStatus };
44
+ export { n as NAVIGATE_RECORD_BUDGET_BYTES, l as buildNavigateAction, d as destinationForPath, u as labelForPath, f as newestAssistantOnSurface, c as outcomeStatus };
@@ -1,4 +1,5 @@
1
- import { AssistantNavigate } from '../ui/AssistantMarkdownRenderer';
1
+ import { AssistantNavigate, AssistantNavigateInitiator } from '../ui/AssistantMarkdownRenderer';
2
+ import { UnsavedChange } from '../../navigation/unsavedChanges';
2
3
  /**
3
4
  * ★ BOFF-8060 (N1a, C7): never claim success before the landing is checked.
4
5
  *
@@ -19,9 +20,16 @@ export type NavigationOutcome = {
19
20
  landedPath: string;
20
21
  } | {
21
22
  status: "new-tab";
22
- } | {
23
+ }
24
+ /**
25
+ * Not routed. ★ BOFF-8060 (N4): `unsaved` names the unsaved changes that
26
+ * refused it (`reason: "unsaved-changes"`), for the reply only — it is never
27
+ * written into the navigate record.
28
+ */
29
+ | {
23
30
  status: "refused";
24
31
  reason: NavigationRefusal;
32
+ unsaved?: readonly UnsavedChange[];
25
33
  } | {
26
34
  status: "unconfirmed";
27
35
  };
@@ -34,6 +42,12 @@ export interface NavigationDeps {
34
42
  schedule: (fn: () => void, ms: number) => void;
35
43
  /** Is this path rendered WITHOUT the shell that hosts the panel? */
36
44
  isShellLess: (path: string) => boolean;
45
+ /**
46
+ * ★ BOFF-8060 (N4): who started it. Absent means the assistant, which the
47
+ * navigator refuses while the page holds unsaved changes; only a tap the
48
+ * person made on an "Open {page}" link passes `"person"`.
49
+ */
50
+ initiator?: AssistantNavigateInitiator;
37
51
  }
38
52
  /** Poll interval, quiet window and ceiling (ms). */
39
53
  export declare const NAVIGATION_POLL_MS = 50;
@@ -1 +1 @@
1
- {"version":3,"file":"navigationOutcome.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/uiActions/navigationOutcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAA2B,MAAM,iCAAiC,CAAC;AAGlG;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,GAAG,cAAc,GAAG,WAAW,CAAC;AAEjF,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAA;CAAE,GAChD;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC;AAE9B,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,0DAA0D;IAC1D,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,qGAAqG;IACrG,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,oEAAoE;IACpE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACxC;AAED,oDAAoD;AACpD,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AA2BD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,iBAAiB,GAAG,IAAI,EAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAwC5B"}
1
+ {"version":3,"file":"navigationOutcome.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/uiActions/navigationOutcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAE3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAGrE;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,GAAG,cAAc,GAAG,WAAW,CAAC;AAEjF,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE;AACvB;;;;GAIG;GACD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,GACpF;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC;AAE9B,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,0DAA0D;IAC1D,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,qGAAqG;IACrG,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,oEAAoE;IACpE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC;;;;OAIG;IACH,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACxC;AAED,oDAAoD;AACpD,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AA2BD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,iBAAiB,GAAG,IAAI,EAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,iBAAiB,CAAC,CA4C5B"}