@burdenoff/fe-libs 2026.1009.1 → 2026.1009.2

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.
@@ -32,6 +32,7 @@ var i = (e) => e.map(t).join(", "), a = (e, t) => {
32
32
  function s(e, s) {
33
33
  switch (s.code) {
34
34
  case "opened": return r([a(e, s.what)], ([e]) => e ?? "");
35
+ case "closed": return r([[e("appControl.closed.preview", "Closed the AI preview."), "Closed the AI preview."]], ([e]) => e ?? "");
35
36
  case "search-opened": return s.query === null ? r([[e("appControl.searchOpened", "Opened search."), "Opened search."]], ([e]) => e ?? "") : r([[e("appControl.searchOpenedFor", "Opened search for “{{query}}”."), "Opened search for “{{query}}”."]], ([e]) => n(e ?? "", { query: t(s.query ?? "") }));
36
37
  case "sidebar": return r(s.already ? [s.collapsed ? [e("appControl.sidebarAlreadyCollapsed", "The sidebar is already collapsed."), "The sidebar is already collapsed."] : [e("appControl.sidebarAlreadyExpanded", "The sidebar is already expanded."), "The sidebar is already expanded."]] : [s.collapsed ? [e("appControl.sidebarCollapsed", "Collapsed the sidebar."), "Collapsed the sidebar."] : [e("appControl.sidebarExpanded", "Expanded the sidebar."), "Expanded the sidebar."]], ([e]) => e ?? "");
37
38
  case "sidebar-entry": return r([s.already ? s.expanded ? [e("appControl.entryAlreadyExpanded", "{{name}} is already expanded."), "{{name}} is already expanded."] : [e("appControl.entryAlreadyCollapsed", "{{name}} is already collapsed."), "{{name}} is already collapsed."] : s.expanded ? [e("appControl.entryExpanded", "Expanded {{name}}."), "Expanded {{name}}."] : [e("appControl.entryCollapsed", "Collapsed {{name}}."), "Collapsed {{name}}."]], ([e]) => n(e ?? "", { name: t(s.name) }));
@@ -55,6 +55,8 @@ export type AppControlRequest = {
55
55
  control: "assistant.transcript";
56
56
  } | {
57
57
  control: "assistant.preview";
58
+ } | {
59
+ control: "assistant.preview.close";
58
60
  } | {
59
61
  control: "assistant.conversation.new";
60
62
  } | {
@@ -24,29 +24,29 @@ var l = 60, u = /^(?:log ?out|sign ?out|(?:log|sign) (?:me )?out(?: of (?:the |m
24
24
  RegExp(`^(?:change|switch|set|update|turn|put|make)(?: over)? ${r}(?:(?:app|ui|user interface|interface|screen|display|site|system|menu|application) )?language (?:to|into|as|over to) (.+)$`),
25
25
  RegExp(`^(?:switch|change|set|put|turn) ${r}(?:app|ui|user interface|interface|screen|display|site|application|menus?) (?:language )?(?:to|into) (.+)$`),
26
26
  RegExp(`^(?:show|display|use|run) ${r}(?:app|ui|user interface|interface|screen|display|site|application)(?: menus?)? in (.+)$`)
27
- ], k = RegExp(`^${i} ${r}(?:(?:assistant|ai|conversation|conversations|chat) history|history of (?:my )?(?:conversations|chats)|(?:past|previous|old|earlier) conversations)$`), A = RegExp(`^${i} ${r}history$`), j = RegExp(`^${i} ${r}(?:voice|spoken|speech) transcript$`), M = RegExp(`^${i} ${r}transcript$`), N = RegExp(`^${i} ${r}(?:ai|assistant) preview(?: panel| pane| surface)?$`), P = RegExp(`^${i} ${r}preview(?: panel| pane)?$`), F = /^(?:(?:start|begin|open) (?:a |an |another )?(?:new |fresh |blank )?conversation|new conversation|(?:start|begin) (?:a )?(?:new|fresh) conversation with you)$/, I = [RegExp(`^(?:go to|open|show|show me|switch to|select|view|change to|move to|take me to|bring up) ${r}(.+) tab$`), /^(?:switch|change|move) tabs? to (.+)$/], L = "(?:filter|narrow|limit)(?: down)?", R = [RegExp(`^${L}(?: ${r}(?:page|list|table|results|items|rows|view))? (?:by|to|for|on) ${r}(.+)$`)], z = [/^(?:show|display|list|keep) only (.+)$/, /^only (?:show|display|list|keep) (.+)$/], B = [
27
+ ], k = RegExp(`^${i} ${r}(?:(?:assistant|ai|conversation|conversations|chat) history|history of (?:my )?(?:conversations|chats)|(?:past|previous|old|earlier) conversations)$`), A = RegExp(`^${i} ${r}history$`), j = RegExp(`^${i} ${r}(?:voice|spoken|speech) transcript$`), M = RegExp(`^${i} ${r}transcript$`), ee = RegExp(`^${i} ${r}(?:ai|assistant) preview(?: panel| pane| surface)?$`), N = RegExp(`^${i} ${r}preview(?: panel| pane)?$`), P = RegExp(`^(?:close|hide|dismiss) ${r}(?:ai|assistant) preview(?: panel| pane| surface)?$`), F = RegExp(`^(?:close|hide) ${r}preview(?: panel| pane)?$`), I = /^(?:(?:start|begin|open) (?:a |an |another )?(?:new |fresh |blank )?conversation|new conversation|(?:start|begin) (?:a )?(?:new|fresh) conversation with you)$/, L = [RegExp(`^(?:go to|open|show|show me|switch to|select|view|change to|move to|take me to|bring up) ${r}(.+) tab$`), /^(?:switch|change|move) tabs? to (.+)$/], R = "(?:filter|narrow|limit)(?: down)?", z = [RegExp(`^${R}(?: ${r}(?:page|list|table|results|items|rows|view))? (?:by|to|for|on) ${r}(.+)$`)], B = [/^(?:show|display|list|keep) only (.+)$/, /^only (?:show|display|list|keep) (.+)$/], V = [
28
28
  RegExp(`^(?:set|change|switch|put|make) ${r}(.+?) filter (?:to|as|on) (.+)$`),
29
- RegExp(`^${L} ${r}(.+?) (?:by|to|for|on) (.+)$`),
29
+ RegExp(`^${R} ${r}(.+?) (?:by|to|for|on) (.+)$`),
30
30
  RegExp(`^(?:use|apply) ${r}(.+?) filter (?:of|with|for|set to) (.+)$`)
31
- ], V = RegExp(`^(?:clear|remove|reset|drop|turn off) ${r}(?:(?:all|every) )?(?:(.+?) )?filters?$`), H = [
31
+ ], H = RegExp(`^(?:clear|remove|reset|drop|turn off) ${r}(?:(?:all|every) )?(?:(.+?) )?filters?$`), U = [
32
32
  [/(?: in)? (?:ascending|asc)(?: order)?$/, "asc"],
33
33
  [/(?: in)? (?:descending|desc)(?: order)?$/, "desc"],
34
34
  [/ (?:a to z|low to high|lowest first|smallest first|oldest first)$/, "asc"],
35
35
  [/ (?:z to a|high to low|highest first|largest first|biggest first|newest first|latest first)$/, "desc"]
36
- ], U = RegExp(`^(?:sort|order|arrange|rank)(?: ${r}(?:page|list|table|results|items|rows|view|it|them))? by (.+)$`), W = /^(?:sort|order)(?: it| them)? (ascending|descending|asc|desc)$/, G = [
36
+ ], W = RegExp(`^(?:sort|order|arrange|rank)(?: ${r}(?:page|list|table|results|items|rows|view|it|them))? by (.+)$`), G = /^(?:sort|order)(?: it| them)? (ascending|descending|asc|desc)$/, K = [
37
37
  /^(?:search|find|look)(?: (?:this page|the page|the list|the table|this list|this table|here|these|them))? for (.+)$/,
38
38
  /^(?:find|search for) (.+?) (?:on|in) (?:this|the) (?:page|list|table)$/,
39
39
  /^search (?:this page|the page|the list|the table|here) (?:for )?(.+)$/
40
- ], K = /^(?:clear|reset|empty|remove|stop) (?:the |my |this )?(?:page )?search(?:ing)?$/, q = [RegExp(`^(?:open|show|start|bring up|pull up) ${r}(.+?) (?:form|dialog|dialogue|modal)$`)], J = RegExp(`^(?:open|show|start|bring up|pull up) ${r}(.+)$`), Y = /\b(?:and then|then|and also|also|after that|afterwards|and open|and show|and go|and sort|and filter)\b/;
41
- function X(e, t) {
40
+ ], q = /^(?:clear|reset|empty|remove|stop) (?:the |my |this )?(?:page )?search(?:ing)?$/, J = [RegExp(`^(?:open|show|start|bring up|pull up) ${r}(.+?) (?:form|dialog|dialogue|modal)$`)], Y = RegExp(`^(?:open|show|start|bring up|pull up) ${r}(.+)$`), X = /\b(?:and then|then|and also|also|after that|afterwards|and open|and show|and go|and sort|and filter)\b/;
41
+ function Z(e, t) {
42
42
  for (let n of e) {
43
43
  let e = n.exec(t);
44
44
  if (e) return e;
45
45
  }
46
46
  return null;
47
47
  }
48
- function Z(e) {
49
- for (let [t, n] of H) {
48
+ function Q(e) {
49
+ for (let [t, n] of U) {
50
50
  let r = t.exec(e);
51
51
  if (r) return {
52
52
  field: e.slice(0, r.index).trim(),
@@ -58,13 +58,13 @@ function Z(e) {
58
58
  direction: null
59
59
  };
60
60
  }
61
- function Q(e) {
61
+ function $(e) {
62
62
  let t = e.replace(/\b(?:please|pls)$/, "").trim();
63
63
  return !t || t.length > l ? null : t;
64
64
  }
65
- function $(s, l, S) {
65
+ function te(s, l, S) {
66
66
  let T = S.registered;
67
- if (Y.test(s)) return null;
67
+ if (X.test(s)) return null;
68
68
  if (T["account.logout"] && u.test(s)) return a({ control: "account.logout" });
69
69
  if (T["header.workspace"] || T["header.context"]) {
70
70
  let e = RegExp(`^(?:switch|change|move|go|jump|hop)(?: over)? to ${r}(.+?) ${d}$`).exec(s) ?? RegExp(`^(?:switch|change|move) ${r}${d} (?:to|over to) ${r}(.+)$`).exec(s);
@@ -88,7 +88,7 @@ function $(s, l, S) {
88
88
  }
89
89
  if (T["header.search"]) {
90
90
  for (let e of x) {
91
- let t = e.exec(s), n = t ? Q(t[1] ?? "") : null;
91
+ let t = e.exec(s), n = t ? $(t[1] ?? "") : null;
92
92
  if (n) return a({
93
93
  control: "header.search",
94
94
  query: c(l, n)
@@ -143,16 +143,18 @@ function $(s, l, S) {
143
143
  if (M.test(s)) return o({ control: "assistant.transcript" });
144
144
  }
145
145
  if (T["assistant.preview"]) {
146
- if (N.test(s)) return a({ control: "assistant.preview" });
147
- if (P.test(s)) return o({ control: "assistant.preview" });
148
- }
149
- if (T["assistant.conversation.new"] && F.test(s)) return a({ control: "assistant.conversation.new" });
150
- let L = S.page;
151
- if (!L) return null;
152
- if (L.tabs.length > 0) {
153
- let e = X(I, s), t = e ? (e[1] ?? "").trim() : "";
146
+ if (ee.test(s)) return a({ control: "assistant.preview" });
147
+ if (N.test(s)) return o({ control: "assistant.preview" });
148
+ if (P.test(s)) return a({ control: "assistant.preview.close" });
149
+ if (F.test(s)) return o({ control: "assistant.preview.close" });
150
+ }
151
+ if (T["assistant.conversation.new"] && I.test(s)) return a({ control: "assistant.conversation.new" });
152
+ let R = S.page;
153
+ if (!R) return null;
154
+ if (R.tabs.length > 0) {
155
+ let e = Z(L, s), t = e ? (e[1] ?? "").trim() : "";
154
156
  if (t) {
155
- let e = n(t, L.tabs).kind !== "none";
157
+ let e = n(t, R.tabs).kind !== "none";
156
158
  return {
157
159
  request: {
158
160
  control: "page.tab",
@@ -162,30 +164,30 @@ function $(s, l, S) {
162
164
  };
163
165
  }
164
166
  }
165
- if (L.filters.length > 0) {
166
- let e = V.exec(s);
167
+ if (R.filters.length > 0) {
168
+ let e = H.exec(s);
167
169
  if (e) return a({
168
170
  control: "page.filter.clear",
169
171
  filter: (e[1] ?? "").trim() || null
170
172
  });
171
- let t = X(B, s);
173
+ let t = Z(V, s);
172
174
  if (t) {
173
175
  let e = (t[1] ?? "").trim(), r = (t[2] ?? "").trim();
174
- if (e && r && n(e, L.filters).kind !== "none") return a({
176
+ if (e && r && n(e, R.filters).kind !== "none") return a({
175
177
  control: "page.filter",
176
178
  filter: e,
177
179
  option: r
178
180
  });
179
181
  }
180
- let r = X(R, s);
182
+ let r = Z(z, s);
181
183
  if (r && (r[1] ?? "").trim()) return a({
182
184
  control: "page.filter",
183
185
  filter: null,
184
186
  option: (r[1] ?? "").trim()
185
187
  });
186
- let i = X(z, s);
188
+ let i = Z(B, s);
187
189
  if (i) {
188
- let e = (i[1] ?? "").trim(), t = L.filters.some((t) => n(e, t.options).kind !== "none");
190
+ let e = (i[1] ?? "").trim(), t = R.filters.some((t) => n(e, t.options).kind !== "none");
189
191
  if (e && t) return a({
190
192
  control: "page.filter",
191
193
  filter: null,
@@ -193,16 +195,16 @@ function $(s, l, S) {
193
195
  });
194
196
  }
195
197
  }
196
- if (L.sorts.length > 0) {
197
- let e = W.exec(s);
198
+ if (R.sorts.length > 0) {
199
+ let e = G.exec(s);
198
200
  if (e) return a({
199
201
  control: "page.sort",
200
202
  field: null,
201
203
  direction: /^asc/.test(e[1] ?? "") ? "asc" : "desc"
202
204
  });
203
- let t = U.exec(s);
205
+ let t = W.exec(s);
204
206
  if (t) {
205
- let { field: e, direction: n } = Z((t[1] ?? "").trim());
207
+ let { field: e, direction: n } = Q((t[1] ?? "").trim());
206
208
  if (e) return a({
207
209
  control: "page.sort",
208
210
  field: e,
@@ -210,22 +212,22 @@ function $(s, l, S) {
210
212
  });
211
213
  }
212
214
  }
213
- if (L.searchable) {
214
- if (K.test(s)) return a({ control: "page.search.clear" });
215
- let e = X(G, s), t = e ? Q(e[1] ?? "") : null;
215
+ if (R.searchable) {
216
+ if (q.test(s)) return a({ control: "page.search.clear" });
217
+ let e = Z(K, s), t = e ? $(e[1] ?? "") : null;
216
218
  if (t) return a({
217
219
  control: "page.search",
218
220
  query: c(l, t)
219
221
  });
220
222
  }
221
- if (L.openers.length > 0) {
222
- let t = X(q, s), r = t ? (t[1] ?? "").trim() : "";
223
- if (r && n(r, L.openers).kind !== "none") return a({
223
+ if (R.openers.length > 0) {
224
+ let t = Z(J, s), r = t ? (t[1] ?? "").trim() : "";
225
+ if (r && n(r, R.openers).kind !== "none") return a({
224
226
  control: "page.open",
225
227
  name: r
226
228
  });
227
- let i = J.exec(s), c = i ? (i[1] ?? "").trim() : "";
228
- if (c && L.openers.filter((t) => e(t.label) === c).length > 0) return o({
229
+ let i = Y.exec(s), c = i ? (i[1] ?? "").trim() : "";
230
+ if (c && R.openers.filter((t) => e(t.label) === c).length > 0) return o({
229
231
  control: "page.open",
230
232
  name: c
231
233
  });
@@ -233,4 +235,4 @@ function $(s, l, S) {
233
235
  return null;
234
236
  }
235
237
  //#endregion
236
- export { $ as matchAppControl, c as queryAsSaid };
238
+ export { te as matchAppControl, c as queryAsSaid };
@@ -9,6 +9,9 @@ import { ControlBlock, ControlKey, SortDirection } from './types';
9
9
  export type ControlReply = {
10
10
  code: "opened";
11
11
  what: OpenedWhat;
12
+ } | {
13
+ code: "closed";
14
+ what: ClosedWhat;
12
15
  } | {
13
16
  code: "search-opened";
14
17
  query: string | null;
@@ -95,6 +98,7 @@ export type ControlReply = {
95
98
  reason: ControlBlock;
96
99
  };
97
100
  export type OpenedWhat = "notifications" | "help" | "context" | "history" | "transcript" | "preview" | "conversation";
101
+ export type ClosedWhat = "preview";
98
102
  export type NotFoundKind = "tab" | "filter" | "filter-option" | "sort" | "form" | "workspace";
99
103
  export type AmbiguousKind = "tab" | "filter" | "menu" | "workspace" | "column" | "form";
100
104
  /** What is recorded on the exchange (`AssistantLocalAction`). */
@@ -18,15 +18,18 @@ function a(e) {
18
18
  }
19
19
  }
20
20
  var o = (e, t) => e.status === "failed" ? i({ code: "failed" }, "failed") : i(t(e.status === "already"), e.status);
21
- function s(e, t, n) {
22
- if (n.voiceLive && r.has(e)) return "voice-session";
21
+ function s(e, t) {
22
+ return r.has(e) ? !(e === "assistant.preview" && "surface" in t && t.surface === "page") : !1;
23
+ }
24
+ function c(e, t, n, r = !0) {
25
+ if (r && n.voiceLive && s(e, t)) return "voice-session";
23
26
  try {
24
27
  return t.blockedBy?.() ?? null;
25
28
  } catch {
26
29
  return "permission";
27
30
  }
28
31
  }
29
- var c = (e, t) => ({
32
+ var l = (e, t) => ({
30
33
  kind: "reply",
31
34
  control: e,
32
35
  run: i({
@@ -34,26 +37,39 @@ var c = (e, t) => ({
34
37
  reason: t
35
38
  }, "blocked")
36
39
  });
37
- function l(t, n) {
38
- let { control: r, what: i } = t, l = e(r);
39
- if (!l) return null;
40
- let u = s(r, l, n);
41
- return u ? c(r, u) : {
40
+ function u(t, n) {
41
+ let { control: r, what: i } = t, s = e(r);
42
+ if (!s) return null;
43
+ let u = c(r, s, n);
44
+ return u ? l(r, u) : {
42
45
  kind: "run",
43
46
  control: r,
44
- run: () => o(a(() => l.run()), () => ({
47
+ run: () => o(a(() => s.run()), () => ({
45
48
  code: "opened",
46
49
  what: i
47
50
  }))
48
51
  };
49
52
  }
50
- var u = (e) => e.map((e) => e.label);
51
- function d(t, r) {
52
- let l = e("page");
53
- if (!l) return null;
54
- let d = s("page", l, r);
55
- if (d) return c("page", d);
56
- let m = l.page, h = (e) => ({
53
+ function d(t) {
54
+ let n = e("assistant.preview");
55
+ if (!n?.close) return null;
56
+ let r = n.close, i = c("assistant.preview", n, t, !1);
57
+ return i ? l("assistant.preview", i) : {
58
+ kind: "run",
59
+ control: "assistant.preview",
60
+ run: () => o(a(r), () => ({
61
+ code: "closed",
62
+ what: "preview"
63
+ }))
64
+ };
65
+ }
66
+ var f = (e) => e.map((e) => e.label);
67
+ function p(t, r) {
68
+ let s = e("page");
69
+ if (!s) return null;
70
+ let u = c("page", s, r);
71
+ if (u) return l("page", u);
72
+ let d = s.page, p = (e) => ({
57
73
  kind: "reply",
58
74
  control: "page",
59
75
  run: e
@@ -64,36 +80,36 @@ function d(t, r) {
64
80
  });
65
81
  switch (t.control) {
66
82
  case "page.tab": {
67
- let e = l.tabs;
83
+ let e = s.tabs;
68
84
  if (!e) return null;
69
- let r = e.items(), s = n(t.name, r);
70
- if (s.kind === "none") return h(i({
85
+ let r = e.items(), c = n(t.name, r);
86
+ if (c.kind === "none") return p(i({
71
87
  code: "not-found",
72
88
  what: "tab",
73
- page: m,
89
+ page: d,
74
90
  name: t.name,
75
- options: u(r)
91
+ options: f(r)
76
92
  }, "not-found"));
77
- if (s.kind === "many") return h(i({
93
+ if (c.kind === "many") return p(i({
78
94
  code: "ambiguous",
79
95
  what: "tab",
80
96
  name: t.name,
81
- options: u(s.items)
97
+ options: f(c.items)
82
98
  }, "ambiguous"));
83
- let c = s.item;
84
- return e.current?.() === c.id ? h(i({
99
+ let l = c.item;
100
+ return e.current?.() === l.id ? p(i({
85
101
  code: "tab",
86
- name: c.label,
102
+ name: l.label,
87
103
  already: !0
88
- }, "already")) : g(() => o(a(() => e.select(c.id)), (e) => ({
104
+ }, "already")) : g(() => o(a(() => e.select(l.id)), (e) => ({
89
105
  code: "tab",
90
- name: c.label,
106
+ name: l.label,
91
107
  already: e
92
108
  })));
93
109
  }
94
- case "page.filter": return p(l, t.filter, t.option, h, g);
110
+ case "page.filter": return h(s, t.filter, t.option, p, g);
95
111
  case "page.filter.clear": {
96
- let e = l.filters;
112
+ let e = s.filters;
97
113
  if (!e) return null;
98
114
  let r = e.items();
99
115
  if (t.filter === null) return g(() => o(a(() => {
@@ -104,85 +120,85 @@ function d(t, r) {
104
120
  code: "filter-cleared",
105
121
  filter: null
106
122
  })));
107
- let s = n(t.filter, r);
108
- if (s.kind === "none") return h(i({
123
+ let c = n(t.filter, r);
124
+ if (c.kind === "none") return p(i({
109
125
  code: "not-found",
110
126
  what: "filter",
111
- page: m,
127
+ page: d,
112
128
  name: t.filter,
113
- options: u(r)
129
+ options: f(r)
114
130
  }, "not-found"));
115
- if (s.kind === "many") return h(i({
131
+ if (c.kind === "many") return p(i({
116
132
  code: "ambiguous",
117
133
  what: "filter",
118
134
  name: t.filter,
119
- options: u(s.items)
135
+ options: f(c.items)
120
136
  }, "ambiguous"));
121
- let c = s.item;
122
- return g(() => o(a(() => e.set(c.id, null)), () => ({
137
+ let l = c.item;
138
+ return g(() => o(a(() => e.set(l.id, null)), () => ({
123
139
  code: "filter-cleared",
124
- filter: c.label
140
+ filter: l.label
125
141
  })));
126
142
  }
127
143
  case "page.sort": {
128
- let e = l.sort;
144
+ let e = s.sort;
129
145
  if (!e) return null;
130
- let n = e.fields(), r = f(m, t.field, n, e.current?.() ?? null);
131
- if ("reply" in r) return h(r.reply);
132
- let { id: s, label: c } = r, u = t.direction ?? "asc", d = e.current?.() ?? null;
133
- return d && d.field === s && d.direction === u ? h(i({
146
+ let n = e.fields(), r = m(d, t.field, n, e.current?.() ?? null);
147
+ if ("reply" in r) return p(r.reply);
148
+ let { id: c, label: l } = r, u = t.direction ?? "asc", f = e.current?.() ?? null;
149
+ return f && f.field === c && f.direction === u ? p(i({
134
150
  code: "sorted",
135
- page: m,
136
- field: c,
151
+ page: d,
152
+ field: l,
137
153
  direction: u,
138
154
  already: !0
139
- }, "already")) : g(() => o(a(() => e.set(s, u)), () => ({
155
+ }, "already")) : g(() => o(a(() => e.set(c, u)), () => ({
140
156
  code: "sorted",
141
- page: m,
142
- field: c,
157
+ page: d,
158
+ field: l,
143
159
  direction: u,
144
160
  already: !1
145
161
  })));
146
162
  }
147
163
  case "page.search": {
148
- let e = l.search;
164
+ let e = s.search;
149
165
  return e ? g(() => o(a(() => e.set(t.query)), () => ({
150
166
  code: "searched",
151
- page: m,
167
+ page: d,
152
168
  query: t.query
153
169
  }))) : null;
154
170
  }
155
171
  case "page.search.clear": {
156
- let e = l.search;
172
+ let e = s.search;
157
173
  return e ? g(() => o(a(() => e.clear ? e.clear() : e.set("")), () => ({ code: "search-cleared" }))) : null;
158
174
  }
159
175
  case "page.open": {
160
- let e = l.openers;
176
+ let e = s.openers;
161
177
  if (!e) return null;
162
- let r = e.items(), s = n(t.name, r);
163
- if (s.kind === "none") return h(i({
178
+ let r = e.items(), c = n(t.name, r);
179
+ if (c.kind === "none") return p(i({
164
180
  code: "not-found",
165
181
  what: "form",
166
- page: m,
182
+ page: d,
167
183
  name: t.name,
168
- options: u(r)
184
+ options: f(r)
169
185
  }, "not-found"));
170
- if (s.kind === "many") return h(i({
186
+ if (c.kind === "many") return p(i({
171
187
  code: "ambiguous",
172
188
  what: "form",
173
189
  name: t.name,
174
- options: u(s.items)
190
+ options: f(c.items)
175
191
  }, "ambiguous"));
176
- let c = s.item;
177
- return g(() => o(a(() => e.open(c.id)), () => ({
192
+ let l = c.item;
193
+ return g(() => o(a(() => e.open(l.id)), () => ({
178
194
  code: "form-opened",
179
- name: c.label
195
+ name: l.label
180
196
  })));
181
197
  }
182
198
  default: return null;
183
199
  }
184
200
  }
185
- function f(e, t, r, a) {
201
+ function m(e, t, r, a) {
186
202
  if (t === null) return (a ? r.find((e) => e.id === a.field) : void 0) ?? { reply: i({ code: "sort-needs-field" }, "not-found") };
187
203
  let o = n(t, r);
188
204
  return o.kind === "one" ? o.item : { reply: o.kind === "none" ? i({
@@ -190,54 +206,54 @@ function f(e, t, r, a) {
190
206
  what: "sort",
191
207
  page: e,
192
208
  name: t,
193
- options: u(r)
209
+ options: f(r)
194
210
  }, "not-found") : i({
195
211
  code: "ambiguous",
196
212
  what: "column",
197
213
  name: t,
198
- options: u(o.items)
214
+ options: f(o.items)
199
215
  }, "ambiguous") };
200
216
  }
201
- function p(e, t, r, s, c) {
217
+ function h(e, t, r, s, c) {
202
218
  let l = e.filters;
203
219
  if (!l) return null;
204
- let d = e.page, f = l.items(), p = [];
220
+ let u = e.page, d = l.items(), p = [];
205
221
  if (t !== null) {
206
- let e = n(t, f);
222
+ let e = n(t, d);
207
223
  if (e.kind === "none") return s(i({
208
224
  code: "not-found",
209
225
  what: "filter",
210
- page: d,
226
+ page: u,
211
227
  name: t,
212
- options: u(f)
228
+ options: f(d)
213
229
  }, "not-found"));
214
230
  if (e.kind === "many") return s(i({
215
231
  code: "ambiguous",
216
232
  what: "filter",
217
233
  name: t,
218
- options: u(e.items)
234
+ options: f(e.items)
219
235
  }, "ambiguous"));
220
236
  let a = e.item, o = a.options(), c = n(r, o, { sayingMayContainLabel: !0 });
221
237
  if (c.kind === "none") return s(i({
222
238
  code: "not-found",
223
239
  what: "filter-option",
224
- page: d,
240
+ page: u,
225
241
  name: r,
226
- options: u(o),
242
+ options: f(o),
227
243
  filter: a.label
228
244
  }, "not-found"));
229
245
  if (c.kind === "many") return s(i({
230
246
  code: "ambiguous",
231
247
  what: "filter",
232
248
  name: r,
233
- options: u(c.items)
249
+ options: f(c.items)
234
250
  }, "ambiguous"));
235
251
  p.push({
236
252
  filter: a,
237
253
  option: c.item
238
254
  });
239
255
  } else {
240
- for (let e of f) {
256
+ for (let e of d) {
241
257
  let t = n(r, e.options(), { sayingMayContainLabel: !0 });
242
258
  if (t.kind === "one") p.push({
243
259
  filter: e,
@@ -249,17 +265,17 @@ function p(e, t, r, s, c) {
249
265
  });
250
266
  }
251
267
  if (p.length === 0) {
252
- let e = n(r, f);
268
+ let e = n(r, d);
253
269
  return e.kind === "one" ? s(i({
254
270
  code: "filter-choose",
255
271
  filter: e.item.label,
256
- options: u(e.item.options())
272
+ options: f(e.item.options())
257
273
  }, "not-found")) : s(i({
258
274
  code: "not-found",
259
275
  what: "filter",
260
- page: d,
276
+ page: u,
261
277
  name: r,
262
- options: u(f)
278
+ options: f(d)
263
279
  }, "not-found"));
264
280
  }
265
281
  if (p.length > 1) return s(i({
@@ -284,37 +300,38 @@ function p(e, t, r, s, c) {
284
300
  already: e
285
301
  })));
286
302
  }
287
- function m(r, f) {
303
+ function g(r, s) {
288
304
  switch (r.control) {
289
- case "header.notifications": return l({
305
+ case "header.notifications": return u({
290
306
  control: "header.notifications",
291
307
  what: "notifications"
292
- }, f);
293
- case "header.help": return l({
308
+ }, s);
309
+ case "header.help": return u({
294
310
  control: "header.help",
295
311
  what: "help"
296
- }, f);
297
- case "header.context": return l({
312
+ }, s);
313
+ case "header.context": return u({
298
314
  control: "header.context",
299
315
  what: "context"
300
- }, f);
301
- case "assistant.history": return l({
316
+ }, s);
317
+ case "assistant.history": return u({
302
318
  control: "assistant.history",
303
319
  what: "history"
304
- }, f);
305
- case "assistant.transcript": return l({
320
+ }, s);
321
+ case "assistant.transcript": return u({
306
322
  control: "assistant.transcript",
307
323
  what: "transcript"
308
- }, f);
309
- case "assistant.preview": return l({
324
+ }, s);
325
+ case "assistant.preview": return u({
310
326
  control: "assistant.preview",
311
327
  what: "preview"
312
- }, f);
328
+ }, s);
329
+ case "assistant.preview.close": return d(s);
313
330
  case "assistant.conversation.new": {
314
331
  let t = e("assistant.conversation.new");
315
332
  if (!t) return null;
316
- let n = s("assistant.conversation.new", t, f);
317
- return n ? c("assistant.conversation.new", n) : {
333
+ let n = c("assistant.conversation.new", t, s);
334
+ return n ? l("assistant.conversation.new", n) : {
318
335
  kind: "run",
319
336
  control: "assistant.conversation.new",
320
337
  silent: !0,
@@ -327,8 +344,8 @@ function m(r, f) {
327
344
  case "header.search": {
328
345
  let t = e("header.search");
329
346
  if (!t) return null;
330
- let n = s("header.search", t, f);
331
- return n ? c("header.search", n) : {
347
+ let n = c("header.search", t, s);
348
+ return n ? l("header.search", n) : {
332
349
  kind: "run",
333
350
  control: "header.search",
334
351
  run: () => o(a(() => t.run({ query: r.query })), () => ({
@@ -340,8 +357,8 @@ function m(r, f) {
340
357
  case "sidebar": {
341
358
  let t = e("sidebar");
342
359
  if (!t) return null;
343
- let n = s("sidebar", t, f);
344
- return n ? c("sidebar", n) : t.collapsed() === r.collapsed ? {
360
+ let n = c("sidebar", t, s);
361
+ return n ? l("sidebar", n) : t.collapsed() === r.collapsed ? {
345
362
  kind: "reply",
346
363
  control: "sidebar",
347
364
  run: i({
@@ -362,8 +379,8 @@ function m(r, f) {
362
379
  case "sidebar.entry": {
363
380
  let t = e("sidebar");
364
381
  if (!t) return null;
365
- let l = s("sidebar", t, f);
366
- if (l) return c("sidebar", l);
382
+ let u = c("sidebar", t, s);
383
+ if (u) return l("sidebar", u);
367
384
  let d = t.entries(), p = n(r.name, d);
368
385
  if (p.kind === "none") return null;
369
386
  if (p.kind === "many") return {
@@ -373,7 +390,7 @@ function m(r, f) {
373
390
  code: "ambiguous",
374
391
  what: "menu",
375
392
  name: r.name,
376
- options: u(p.items)
393
+ options: f(p.items)
377
394
  }, "ambiguous")
378
395
  };
379
396
  let m = p.item;
@@ -400,23 +417,23 @@ function m(r, f) {
400
417
  case "language": {
401
418
  let n = e("language");
402
419
  if (!n) return null;
403
- let l = s("language", n, f);
404
- if (l) return c("language", l);
405
- let u = n.languages().find((e) => e.code.toLowerCase() === r.code);
406
- return u ? n.current().toLowerCase() === u.code.toLowerCase() ? {
420
+ let u = c("language", n, s);
421
+ if (u) return l("language", u);
422
+ let d = n.languages().find((e) => e.code.toLowerCase() === r.code);
423
+ return d ? n.current().toLowerCase() === d.code.toLowerCase() ? {
407
424
  kind: "reply",
408
425
  control: "language",
409
426
  run: i({
410
427
  code: "language",
411
- label: u.label,
428
+ label: d.label,
412
429
  already: !0
413
430
  }, "already")
414
431
  } : {
415
432
  kind: "run",
416
433
  control: "language",
417
- run: () => o(a(() => n.set(u.code)), (e) => ({
434
+ run: () => o(a(() => n.set(d.code)), (e) => ({
418
435
  code: "language",
419
- label: u.label,
436
+ label: d.label,
420
437
  already: e
421
438
  }))
422
439
  } : {
@@ -431,8 +448,8 @@ function m(r, f) {
431
448
  case "header.workspace": {
432
449
  let t = e("header.workspace");
433
450
  if (!t) return null;
434
- let l = s("header.workspace", t, f);
435
- if (l) return c("header.workspace", l);
451
+ let u = c("header.workspace", t, s);
452
+ if (u) return l("header.workspace", u);
436
453
  let d = t.targets(), p = d.filter((e) => e.current !== !0);
437
454
  if (p.length === 0) return {
438
455
  kind: "reply",
@@ -448,7 +465,7 @@ function m(r, f) {
448
465
  what: "workspace",
449
466
  page: "",
450
467
  name: r.target,
451
- options: u(p)
468
+ options: f(p)
452
469
  }, "not-found")
453
470
  };
454
471
  if (m.kind === "many") return {
@@ -458,7 +475,7 @@ function m(r, f) {
458
475
  code: "ambiguous",
459
476
  what: "workspace",
460
477
  name: r.target,
461
- options: u(m.items)
478
+ options: f(m.items)
462
479
  }, "ambiguous")
463
480
  };
464
481
  let h = m.item;
@@ -482,7 +499,7 @@ function m(r, f) {
482
499
  }, "confirm"),
483
500
  confirmed: () => {
484
501
  let t = e("header.workspace"), n = t?.targets().find((e) => e.id === h.id);
485
- return !t || !n || n.current === !0 || s("header.workspace", t, f) ? i({ code: "failed" }, "failed") : o(a(() => t.switchTo(h.id)), () => ({
502
+ return !t || !n || n.current === !0 || c("header.workspace", t, s) ? i({ code: "failed" }, "failed") : o(a(() => t.switchTo(h.id)), () => ({
486
503
  code: "workspace-switched",
487
504
  name: h.label
488
505
  }));
@@ -492,20 +509,20 @@ function m(r, f) {
492
509
  case "account.logout": {
493
510
  let t = e("account.logout");
494
511
  if (!t) return null;
495
- let n = s("account.logout", t, f);
496
- return n ? c("account.logout", n) : {
512
+ let n = c("account.logout", t, s);
513
+ return n ? l("account.logout", n) : {
497
514
  kind: "confirm",
498
515
  control: "account.logout",
499
516
  prompt: { kind: "logout" },
500
517
  ask: i({ code: "logout-confirm" }, "confirm"),
501
518
  confirmed: () => {
502
519
  let t = e("account.logout");
503
- return !t || s("account.logout", t, f) ? i({ code: "failed" }, "failed") : o(a(() => t.run()), () => ({ code: "logout-done" }));
520
+ return !t || c("account.logout", t, s) ? i({ code: "failed" }, "failed") : o(a(() => t.run()), () => ({ code: "logout-done" }));
504
521
  }
505
522
  };
506
523
  }
507
- default: return d(r, f);
524
+ default: return p(r, s);
508
525
  }
509
526
  }
510
527
  //#endregion
511
- export { m as planAppControl };
528
+ export { g as planAppControl };
@@ -160,6 +160,28 @@ export interface PageControlsAdapter extends ControlBase {
160
160
  open: (id: string) => ControlResult;
161
161
  };
162
162
  }
163
+ /**
164
+ * The AI Preview, a product's own surface showing what the assistant just
165
+ * built or ran. Open and close are SET operations (`already` when it is in the
166
+ * state asked for), never toggles.
167
+ *
168
+ * Extensible per product: a product registers its own `assistant.preview` with
169
+ * the same shape, and a product without a preview registers nothing, so for it
170
+ * the sentence goes to the model as before ("not applicable").
171
+ */
172
+ export interface PreviewControl extends OpenControl {
173
+ /**
174
+ * Hide it. SET: `already` when it is hidden. Absent: "close the AI preview"
175
+ * is not a command for this product and goes to the model.
176
+ */
177
+ close?: () => ControlResult;
178
+ /**
179
+ * Where the preview is drawn. "panel" (the default): an overlay inside the
180
+ * assistant panel, which the live voice screen covers. "page": drawn on the
181
+ * product's own page beside the assistant, so Voice may open it.
182
+ */
183
+ surface?: "panel" | "page";
184
+ }
163
185
  /** Every control key, and the handler shape it takes. */
164
186
  export interface ControlMap {
165
187
  "header.notifications": OpenControl;
@@ -172,7 +194,7 @@ export interface ControlMap {
172
194
  language: LanguageControl;
173
195
  "assistant.history": OpenControl;
174
196
  "assistant.transcript": OpenControl;
175
- "assistant.preview": OpenControl;
197
+ "assistant.preview": PreviewControl;
176
198
  "assistant.conversation.new": OpenControl;
177
199
  page: PageControlsAdapter;
178
200
  }
@@ -126,6 +126,7 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
126
126
  readonly "appControl.ambiguous": "More than one {{what}} matches “{{name}}”: {{options}}. Say which one.";
127
127
  readonly "appControl.blockedPermission": "That isn't available to you here.";
128
128
  readonly "appControl.blockedVoice": "I can't open that while the voice screen is up. End the voice session, or use the button in the assistant's header.";
129
+ readonly "appControl.closed.preview": "Closed the AI preview.";
129
130
  readonly "appControl.dialog.cancel": "Cancel";
130
131
  readonly "appControl.dialog.logoutBody": "You'll be signed out of this account on this device.";
131
132
  readonly "appControl.dialog.logoutConfirm": "Log out";
@@ -20,6 +20,7 @@ var m = {
20
20
  "appControl.ambiguous": "More than one {{what}} matches “{{name}}”: {{options}}. Say which one.",
21
21
  "appControl.blockedPermission": "That isn't available to you here.",
22
22
  "appControl.blockedVoice": "I can't open that while the voice screen is up. End the voice session, or use the button in the assistant's header.",
23
+ "appControl.closed.preview": "Closed the AI preview.",
23
24
  "appControl.dialog.cancel": "Cancel",
24
25
  "appControl.dialog.logoutBody": "You'll be signed out of this account on this device.",
25
26
  "appControl.dialog.logoutConfirm": "Log out",
@@ -43,7 +43,11 @@ var k = ({ onClose: k, visible: A, docked: j, onToggleDock: M, writeAccess: N, o
43
43
  }, e);
44
44
  J(t.historyOpen), V(t.previewOpen);
45
45
  };
46
- t("assistant.history", w(() => ({ run: () => q ? { status: "already" } : (J(!0), V(!1), { status: "done" }) }), [q, J])), t("assistant.preview", w(() => H ? { run: () => U ? { status: "already" } : (J(!1), V(!0), { status: "done" }) } : null, [
46
+ t("assistant.history", w(() => ({ run: () => q ? { status: "already" } : (J(!0), V(!1), { status: "done" }) }), [q, J])), t("assistant.preview", w(() => H ? {
47
+ surface: "panel",
48
+ run: () => U ? { status: "already" } : (J(!1), V(!0), { status: "done" }),
49
+ close: () => U ? (V(!1), { status: "done" }) : { status: "already" }
50
+ } : null, [
47
51
  H,
48
52
  U,
49
53
  J
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fe-libs",
3
- "version": "2026.1009.1",
3
+ "version": "2026.1009.2",
4
4
  "description": "Burdenoff frontend primitives and domain libraries",
5
5
  "type": "module",
6
6
  "bin": {