@linxin666/dsh-remote-web-ui 0.2.0 → 0.2.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.
Files changed (77) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +17 -8
  3. package/README.zh.md +5 -5
  4. package/lib/client.js +259 -43
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +26 -7
  7. package/lib/mobile.js +209 -39
  8. package/lib/mobile.js.map +1 -1
  9. package/lib/types/client/PluginSettingsCard.d.ts +22 -0
  10. package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
  11. package/lib/types/client/PluginSettingsCard.js +142 -3
  12. package/lib/types/client/RemoteEntry.d.ts.map +1 -1
  13. package/lib/types/client/RemoteEntry.js +11 -0
  14. package/lib/types/client/RemoteSettingsCard.d.ts +2 -2
  15. package/lib/types/client/UpdateEntry.d.ts.map +1 -1
  16. package/lib/types/client/UpdateEntry.js +8 -5
  17. package/lib/types/client/UpdatePanel.d.ts +3 -1
  18. package/lib/types/client/UpdatePanel.d.ts.map +1 -1
  19. package/lib/types/client/UpdatePanel.js +3 -3
  20. package/lib/types/client/locales.d.ts +4 -0
  21. package/lib/types/client/locales.d.ts.map +1 -1
  22. package/lib/types/client/locales.js +8 -4
  23. package/lib/types/client/pair-api.d.ts +1 -6
  24. package/lib/types/client/pair-api.d.ts.map +1 -1
  25. package/lib/types/client/pair-api.js +1 -10
  26. package/lib/types/gate.d.ts.map +1 -1
  27. package/lib/types/gate.js +2 -0
  28. package/lib/types/mobile/api.d.ts +10 -0
  29. package/lib/types/mobile/api.d.ts.map +1 -1
  30. package/lib/types/mobile/api.js +4 -0
  31. package/lib/types/mobile/messages.d.ts +24 -0
  32. package/lib/types/mobile/messages.d.ts.map +1 -1
  33. package/lib/types/mobile/messages.js +60 -23
  34. package/lib/types/mobile/messages.test.js +49 -1
  35. package/lib/types/mobile/mobile-styles.d.ts +1 -1
  36. package/lib/types/mobile/mobile-styles.d.ts.map +1 -1
  37. package/lib/types/mobile/mobile-styles.js +38 -0
  38. package/lib/types/mobile/views/ChatView.d.ts.map +1 -1
  39. package/lib/types/mobile/views/ChatView.js +34 -11
  40. package/lib/types/mobile/views/SessionListView.d.ts.map +1 -1
  41. package/lib/types/mobile/views/SessionListView.js +30 -4
  42. package/lib/types/mobile/views/SessionListView.test.js +58 -1
  43. package/lib/types/mobile/views/WorkspaceView.d.ts.map +1 -1
  44. package/lib/types/mobile/views/WorkspaceView.js +4 -2
  45. package/lib/types/mobile-api.d.ts.map +1 -1
  46. package/lib/types/mobile-api.js +10 -1
  47. package/lib/types/routes.d.ts.map +1 -1
  48. package/lib/types/routes.js +22 -2
  49. package/lib/types/tunnel.d.ts +1 -0
  50. package/lib/types/tunnel.d.ts.map +1 -1
  51. package/lib/types/tunnel.js +7 -2
  52. package/lib/types/update.d.ts +1 -1
  53. package/lib/types/update.d.ts.map +1 -1
  54. package/lib/types/update.js +1 -1
  55. package/package.json +1 -2
  56. package/src/client/PluginSettingsCard.tsx +219 -18
  57. package/src/client/RemoteEntry.tsx +10 -0
  58. package/src/client/RemoteSettingsCard.tsx +2 -2
  59. package/src/client/UpdateEntry.tsx +9 -5
  60. package/src/client/UpdatePanel.tsx +12 -1
  61. package/src/client/locales.ts +8 -4
  62. package/src/client/pair-api.ts +1 -10
  63. package/src/client/settings-card.module.css +90 -1
  64. package/src/gate.ts +2 -0
  65. package/src/mobile/api.ts +14 -1
  66. package/src/mobile/messages.test.ts +52 -1
  67. package/src/mobile/messages.ts +65 -22
  68. package/src/mobile/mobile-styles.ts +38 -0
  69. package/src/mobile/mobile-theme.test.ts +1 -1
  70. package/src/mobile/views/ChatView.tsx +33 -10
  71. package/src/mobile/views/SessionListView.test.tsx +69 -1
  72. package/src/mobile/views/SessionListView.tsx +58 -5
  73. package/src/mobile/views/WorkspaceView.tsx +4 -2
  74. package/src/mobile-api.ts +9 -1
  75. package/src/routes.ts +22 -2
  76. package/src/tunnel.ts +7 -2
  77. package/src/update.ts +2 -2
@@ -88,6 +88,27 @@ export declare function ValueField(props: FieldProps & {
88
88
  /** Placeholder shown while the draft is empty. */
89
89
  placeholder?: string;
90
90
  }): import("react").JSX.Element;
91
+ interface SelectOption {
92
+ value: string;
93
+ label: string;
94
+ }
95
+ /**
96
+ * The shared dual-mode select control. While an appearance skin is active it
97
+ * renders the legacy native `<select>` untouched, so element-level skin
98
+ * selectors keep working; under the default appearance it renders a
99
+ * self-drawn `role="listbox"` popup whose open/close is transition-animated.
100
+ * Staged cards reach it through BooleanField/ChoiceField; immediate-apply
101
+ * editors (the side-card prefs) bind it directly through onEdit.
102
+ * 双模式下拉框:皮肤激活时用原生 select,默认外观用自绘动画弹层。
103
+ */
104
+ export declare function SelectField(props: {
105
+ id: string;
106
+ options: ReadonlyArray<SelectOption>;
107
+ value: string;
108
+ disabled: boolean;
109
+ invalid: boolean;
110
+ onEdit: (text: string) => void;
111
+ }): import("react").JSX.Element;
91
112
  /** A staged boolean field: 继承 / 开 / 关. */
92
113
  export declare function BooleanField(props: FieldProps & {
93
114
  /** Copy for the inherit option. */
@@ -107,4 +128,5 @@ export declare function ChoiceField(props: FieldProps & {
107
128
  label: string;
108
129
  }>;
109
130
  }): import("react").JSX.Element;
131
+ export {};
110
132
  //# sourceMappingURL=PluginSettingsCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  * it. Inlined into each consumer's client bundle; mirrors the official
9
9
  * ui-plugin-config PluginCard in a self-contained slice.
10
10
  */
11
- import { useState } from 'react';
11
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
12
12
  import css from './settings-card.module.css';
13
13
  /** Copy keys the card chrome itself reads; every consumer locale carries this shared vocabulary. */
14
14
  export const CARD_COPY_KEYS = [
@@ -65,15 +65,154 @@ export function ValueField(props) {
65
65
  ? (_jsxs("span", { className: css.badges, children: [_jsx("span", { className: css.badge, children: props.overriddenLabel }), _jsx("button", { type: "button", className: css.reset, disabled: props.disabled, onClick: props.onReset, children: props.resetLabel })] }))
66
66
  : null] }), _jsx("input", { id: props.id, className: props.invalid ? css.inputInvalid : css.input, type: "text", ...props.numeric === true ? { inputMode: 'numeric' } : {}, ...props.invalid ? { 'aria-invalid': true } : {}, value: props.text, placeholder: props.placeholder ?? '', disabled: props.disabled, onChange: (event) => { props.onEdit(event.target.value); } }), _jsx("p", { className: props.invalid ? css.invalid : css.hint, children: props.invalid ? props.invalidLabel : props.hint })] }));
67
67
  }
68
+ const NON_SKIN_BODY_MARKERS = new Set(['dshSkinCenter', 'dshSidebarCollapsed']);
69
+ // 检测使用使用皮肤,用了皮肤退回原生select样式,防止样式冲突。默认外观下使用优化后的select样式。
70
+ function isSkinActive() {
71
+ const datasetList = Object.keys(document.body.dataset);
72
+ const isActive = datasetList.some(key => key.startsWith('dsh') && !NON_SKIN_BODY_MARKERS.has(key));
73
+ return isActive;
74
+ }
75
+ const SELECT_CLOSE_MS = 100;
76
+ /**
77
+ * The shared dual-mode select control. While an appearance skin is active it
78
+ * renders the legacy native `<select>` untouched, so element-level skin
79
+ * selectors keep working; under the default appearance it renders a
80
+ * self-drawn `role="listbox"` popup whose open/close is transition-animated.
81
+ * Staged cards reach it through BooleanField/ChoiceField; immediate-apply
82
+ * editors (the side-card prefs) bind it directly through onEdit.
83
+ * 双模式下拉框:皮肤激活时用原生 select,默认外观用自绘动画弹层。
84
+ */
85
+ export function SelectField(props) {
86
+ const { id, options, value } = props;
87
+ const [open, setOpen] = useState(false);
88
+ const [closing, setClosing] = useState(false);
89
+ const [phase, setPhase] = useState('initial');
90
+ const [activeIndex, setActiveIndex] = useState(0);
91
+ const closeTimer = useRef(undefined);
92
+ const wrapRef = useRef(null);
93
+ const popupRef = useRef(null);
94
+ const currentIndex = () => {
95
+ const index = options.findIndex(option => option.value === value);
96
+ return index >= 0 ? index : 0;
97
+ };
98
+ const close = useCallback(() => {
99
+ if (closeTimer.current !== undefined)
100
+ clearTimeout(closeTimer.current);
101
+ setClosing(true);
102
+ closeTimer.current = setTimeout(() => {
103
+ setClosing(false);
104
+ setOpen(false);
105
+ }, SELECT_CLOSE_MS);
106
+ }, []);
107
+ const openPopup = () => {
108
+ if (closeTimer.current !== undefined)
109
+ clearTimeout(closeTimer.current);
110
+ setActiveIndex(currentIndex());
111
+ setPhase('initial');
112
+ setClosing(false);
113
+ setOpen(true);
114
+ };
115
+ const commit = (index) => {
116
+ const option = options[index];
117
+ if (option)
118
+ props.onEdit(option.value);
119
+ close();
120
+ };
121
+ const onTriggerClick = () => {
122
+ if (props.disabled)
123
+ return;
124
+ if (open && !closing)
125
+ close();
126
+ else
127
+ openPopup();
128
+ };
129
+ const onKeyDown = (event) => {
130
+ if (props.disabled)
131
+ return;
132
+ const count = options.length;
133
+ switch (event.key) {
134
+ case 'ArrowDown':
135
+ case 'ArrowUp':
136
+ case 'Enter':
137
+ case ' ':
138
+ event.preventDefault();
139
+ if (!open) {
140
+ openPopup();
141
+ }
142
+ else if (!closing) {
143
+ if (event.key === 'ArrowDown')
144
+ setActiveIndex(index => (index + 1) % count);
145
+ else if (event.key === 'ArrowUp')
146
+ setActiveIndex(index => (index - 1 + count) % count);
147
+ else
148
+ commit(activeIndex);
149
+ }
150
+ break;
151
+ case 'Escape':
152
+ if (open) {
153
+ event.preventDefault();
154
+ event.stopPropagation();
155
+ close();
156
+ }
157
+ break;
158
+ case 'Tab':
159
+ if (open)
160
+ close();
161
+ break;
162
+ }
163
+ };
164
+ useEffect(() => () => {
165
+ if (closeTimer.current !== undefined)
166
+ clearTimeout(closeTimer.current);
167
+ }, []);
168
+ useLayoutEffect(() => {
169
+ if (open && !closing && phase === 'initial') {
170
+ void popupRef.current?.offsetHeight;
171
+ setPhase('open');
172
+ }
173
+ }, [open, closing, phase]);
174
+ useEffect(() => {
175
+ if (!open)
176
+ return;
177
+ const onPointerDown = (event) => {
178
+ const target = event.target;
179
+ if (target instanceof Node && !wrapRef.current?.contains(target))
180
+ close();
181
+ };
182
+ document.addEventListener('pointerdown', onPointerDown);
183
+ return () => document.removeEventListener('pointerdown', onPointerDown);
184
+ }, [open, close]);
185
+ useEffect(() => {
186
+ if (props.disabled && open)
187
+ close();
188
+ }, [props.disabled, open, close]);
189
+ // 使用了皮肤则退回原生select样式防止样式冲突。
190
+ if (isSkinActive()) {
191
+ return (_jsx("select", { id: id, className: css.select, value: value, disabled: props.disabled, onChange: (event) => { props.onEdit(event.target.value); }, children: options.map(option => (_jsx("option", { value: option.value, children: option.label }, option.value))) }));
192
+ }
193
+ const label = options.find(option => option.value === value)?.label ?? '';
194
+ const popupClass = closing
195
+ ? `${css.selectPopup} ${css.selectPopupClose}`
196
+ : phase === 'open'
197
+ ? `${css.selectPopup} ${css.selectPopupOpen}`
198
+ : css.selectPopup;
199
+ return (_jsxs("div", { className: css.selectWrap, ref: wrapRef, children: [_jsxs("button", { type: "button", id: id, className: `${css.select} ${css.selectButton}`, disabled: props.disabled, "aria-haspopup": "listbox", "aria-expanded": open, "aria-activedescendant": open ? `${id}-o${activeIndex}` : undefined, "aria-invalid": props.invalid || undefined, onClick: onTriggerClick, onKeyDown: onKeyDown, children: [_jsx("span", { className: css.selectLabel, children: label }), _jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: open ? `${css.selectChevron} ${css.selectChevronOpen}` : css.selectChevron, "aria-hidden": "true", children: _jsx("path", { d: "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z", fill: "currentColor" }) })] }), open
200
+ ? (_jsx("div", { className: popupClass, role: "listbox", ref: popupRef, children: options.map((option, index) => (_jsx("div", { id: `${id}-o${index}`, role: "option", "aria-selected": option.value === value, className: `${css.selectOption}${option.value === value ? ` ${css.selectOptionSelected}` : ''}${index === activeIndex && !closing ? ` ${css.selectOptionActive}` : ''}`, onClick: () => { commit(index); }, children: option.label }, option.value))) }))
201
+ : null] }));
202
+ }
68
203
  /** A staged boolean field: 继承 / 开 / 关. */
69
204
  export function BooleanField(props) {
70
205
  return (_jsxs("div", { className: css.field, children: [_jsxs("div", { className: css.head, children: [_jsx("label", { className: css.label, htmlFor: props.id, children: props.label }), props.overridden
71
206
  ? (_jsxs("span", { className: css.badges, children: [_jsx("span", { className: css.badge, children: props.overriddenLabel }), _jsx("button", { type: "button", className: css.reset, disabled: props.disabled, onClick: props.onReset, children: props.resetLabel })] }))
72
- : null] }), _jsxs("select", { id: props.id, className: css.select, value: props.text, disabled: props.disabled, onChange: (event) => { props.onEdit(event.target.value); }, children: [_jsx("option", { value: "", children: props.inheritLabel }), _jsx("option", { value: "true", children: props.onLabel }), _jsx("option", { value: "false", children: props.offLabel })] }), _jsx("p", { className: css.hint, children: props.hint })] }));
207
+ : null] }), _jsx(SelectField, { id: props.id, options: [
208
+ { value: '', label: props.inheritLabel },
209
+ { value: 'true', label: props.onLabel },
210
+ { value: 'false', label: props.offLabel },
211
+ ], value: props.text, disabled: props.disabled, invalid: props.invalid, onEdit: props.onEdit }), _jsx("p", { className: css.hint, children: props.hint })] }));
73
212
  }
74
213
  /** A staged enumerated field rendered as a select. */
75
214
  export function ChoiceField(props) {
76
215
  return (_jsxs("div", { className: css.field, children: [_jsxs("div", { className: css.head, children: [_jsx("label", { className: css.label, htmlFor: props.id, children: props.label }), props.overridden
77
216
  ? (_jsxs("span", { className: css.badges, children: [_jsx("span", { className: css.badge, children: props.overriddenLabel }), _jsx("button", { type: "button", className: css.reset, disabled: props.disabled, onClick: props.onReset, children: props.resetLabel })] }))
78
- : null] }), _jsxs("select", { id: props.id, className: css.select, value: props.text, disabled: props.disabled, onChange: (event) => { props.onEdit(event.target.value); }, children: [_jsx("option", { value: "", children: props.inheritLabel }), props.choices.map(choice => (_jsx("option", { value: choice.value, children: choice.label }, choice.value)))] }), _jsx("p", { className: props.invalid ? css.invalid : css.hint, children: props.invalid ? props.invalidLabel : props.hint })] }));
217
+ : null] }), _jsx(SelectField, { id: props.id, options: [{ value: '', label: props.inheritLabel }, ...props.choices], value: props.text, disabled: props.disabled, invalid: props.invalid, onEdit: props.onEdit }), _jsx("p", { className: props.invalid ? css.invalid : css.hint, children: props.invalid ? props.invalidLabel : props.hint })] }));
79
218
  }
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteEntry.d.ts","sourceRoot":"","sources":["../../../src/client/RemoteEntry.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAQjF,wEAAwE;AACxE,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,gBAAgB,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;AAwBrF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,gBAAgB,+BA6KvE"}
1
+ {"version":3,"file":"RemoteEntry.d.ts","sourceRoot":"","sources":["../../../src/client/RemoteEntry.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAQjF,wEAAwE;AACxE,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,gBAAgB,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;AAwBrF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,gBAAgB,+BAuLvE"}
@@ -52,6 +52,10 @@ export function RemoteEntry({ wide, useWorkspaces, t }) {
52
52
  useEffect(() => { stateRef.current = state; }, [state]);
53
53
  const [copied, setCopied] = useState(false);
54
54
  const eventSource = useRef(undefined);
55
+ // Generation counter for the open flow: closing (or re-opening) the panel
56
+ // bumps it, so an in-flight issue() that resolves after a close does not
57
+ // spawn a stray EventSource.
58
+ const openSeq = useRef(0);
55
59
  // The current workspace (the recent-workspace projection the shell's New
56
60
  // Session flow targets) — the deep-link target for the phone.
57
61
  const workspaceId = useWorkspaces(s => s.recentWorkspaceId);
@@ -98,8 +102,14 @@ export function RemoteEntry({ wide, useWorkspaces, t }) {
98
102
  };
99
103
  }, [workspaceId]);
100
104
  const openPanel = useCallback(async () => {
105
+ const seq = ++openSeq.current;
101
106
  setOpen(true);
102
107
  const next = await mint();
108
+ // A close (or re-open) during the await invalidates this issue: skip the
109
+ // state write and the stream so a panel closed mid-mint neither leaks an
110
+ // EventSource nor resurrects a stale QR.
111
+ if (seq !== openSeq.current)
112
+ return;
103
113
  setState(next);
104
114
  // Live status: the desktop panel mirrors the pairing service state. The
105
115
  // stream makes sense in the ready state and on the lan-required banner —
@@ -137,6 +147,7 @@ export function RemoteEntry({ wide, useWorkspaces, t }) {
137
147
  };
138
148
  }, [mint]);
139
149
  const closePanel = useCallback(() => {
150
+ openSeq.current += 1;
140
151
  closeEventSource();
141
152
  setOpen(false);
142
153
  }, [closeEventSource]);
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The remote-control settings card: pairing security and device limits.
3
- * Registers into the `settings.plugin.item` slot the plugin-configuration
4
- * section renders, bound to the `remote-web-ui` settings namespace.
3
+ * Registers into the `web-ui.plugin.item` child slot the Web UI plugin group
4
+ * renders, bound to the `remote-web-ui` settings namespace.
5
5
  */
6
6
  import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
7
7
  import type { SettingsScope, SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
@@ -1 +1 @@
1
- {"version":3,"file":"UpdateEntry.d.ts","sourceRoot":"","sources":["../../../src/client/UpdateEntry.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAOnE,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,IAAI,EAAE,OAAO,CAAA;IACb,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;CACzB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,gBAAgB,+BA2GxD"}
1
+ {"version":3,"file":"UpdateEntry.d.ts","sourceRoot":"","sources":["../../../src/client/UpdateEntry.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAOnE,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,IAAI,EAAE,OAAO,CAAA;IACb,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;CACzB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,gBAAgB,+BA8GxD"}
@@ -2,8 +2,9 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
2
2
  /**
3
3
  * The sidebar update seat: the download trigger beside the remote-control
4
4
  * trigger plus the update panel modal. Owns the flow — probe the registry
5
- * on open, auto-run the update when a newer release exists, report the
6
- * outcome (restart hint on success, translated failure on error).
5
+ * on open, show the result, and let the user start the update from the
6
+ * result view (#507), then report the outcome (restart hint on success,
7
+ * translated failure on error).
7
8
  * Component-local state per the client stack rules.
8
9
  */
9
10
  import { useCallback, useEffect, useRef, useState } from "react";
@@ -65,9 +66,11 @@ export function UpdateEntry({ wide, t }) {
65
66
  setView({ kind: "result", status });
66
67
  return;
67
68
  }
69
+ // Checking never starts an update by itself (#507): the result view
70
+ // carries the confirmation button that calls startUpdate.
68
71
  setView({ kind: "result", status });
69
- // Auto-update: an npm install with a newer release proceeds without a
70
- // second confirmation — clicking the update trigger is the intent.
72
+ }, [t]);
73
+ const startUpdate = useCallback(async (status) => {
71
74
  if (status.mode !== "npm" || !status.outdated)
72
75
  return;
73
76
  setView({ kind: "updating", status });
@@ -105,5 +108,5 @@ export function UpdateEntry({ wide, t }) {
105
108
  };
106
109
  }, [probeAvailability]);
107
110
  const updateLabel = updateAvailable ? t("update.availableLabel") : t("update.label");
108
- return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: css.trigger, "data-wide": wide ? undefined : "rail", "data-update-available": updateAvailable ? "true" : undefined, "aria-label": updateLabel, title: updateLabel, onClick: openPanel, children: _jsx(IconDownloadOutline16, { size: wide ? 16 : 18 }) }), open && createPortal((_jsxs("div", { className: css.overlay, role: "presentation", children: [_jsx("div", { className: css.mask, "aria-hidden": "true", onClick: closePanel }), _jsx(UpdatePanel, { t: t, view: view, onClose: closePanel, onRecheck: () => { void check(); } })] })), document.body)] }));
111
+ return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: css.trigger, "data-wide": wide ? undefined : "rail", "data-update-available": updateAvailable ? "true" : undefined, "aria-label": updateLabel, title: updateLabel, onClick: openPanel, children: _jsx(IconDownloadOutline16, { size: wide ? 16 : 18 }) }), open && createPortal((_jsxs("div", { className: css.overlay, role: "presentation", children: [_jsx("div", { className: css.mask, "aria-hidden": "true", onClick: closePanel }), _jsx(UpdatePanel, { t: t, view: view, onClose: closePanel, onRecheck: () => { void check(); }, onStartUpdate: (status) => { void startUpdate(status); } })] })), document.body)] }));
109
112
  }
@@ -30,11 +30,13 @@ export interface UpdatePanelProps {
30
30
  onClose(): void;
31
31
  /** Re-run the check from a terminal state. */
32
32
  onRecheck(): void;
33
+ /** Start the update from the result view (the confirmation step, #507). */
34
+ onStartUpdate(status: UpdateStatus): void;
33
35
  }
34
36
  /**
35
37
  * Render the update panel.
36
38
  * @param props - copy, view state, and actions.
37
39
  * @returns the panel element tree.
38
40
  */
39
- export declare function UpdatePanel({ t, view, onClose, onRecheck }: UpdatePanelProps): import("react").JSX.Element;
41
+ export declare function UpdatePanel({ t, view, onClose, onRecheck, onStartUpdate }: UpdatePanelProps): import("react").JSX.Element;
40
42
  //# sourceMappingURL=UpdatePanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UpdatePanel.d.ts","sourceRoot":"","sources":["../../../src/client/UpdatePanel.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAEnE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAGjE,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvD,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,IAAI,IAAI,CAAA;IACf,8CAA8C;IAC9C,SAAS,IAAI,IAAI,CAAA;CAClB;AAYD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,gBAAgB,+BAyC5E"}
1
+ {"version":3,"file":"UpdatePanel.d.ts","sourceRoot":"","sources":["../../../src/client/UpdatePanel.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAEnE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAGjE,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvD,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,IAAI,IAAI,CAAA;IACf,8CAA8C;IAC9C,SAAS,IAAI,IAAI,CAAA;IACjB,2EAA2E;IAC3E,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;CAC1C;AAYD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,gBAAgB,+BAiD3F"}
@@ -14,11 +14,11 @@ function anchorLatest(status) {
14
14
  * @param props - copy, view state, and actions.
15
15
  * @returns the panel element tree.
16
16
  */
17
- export function UpdatePanel({ t, view, onClose, onRecheck }) {
17
+ export function UpdatePanel({ t, view, onClose, onRecheck, onStartUpdate }) {
18
18
  const status = view.kind === "result" || view.kind === "updating" ? view.status : undefined;
19
19
  const title = view.kind === "done" && view.result.ok ? t("update.done") : t("update.title");
20
20
  const subtitle = subtitleOf(t, view);
21
- return (_jsxs("div", { className: css.panel, role: "dialog", "aria-modal": "true", "aria-label": title, children: [_jsxs("div", { className: css.header, children: [_jsxs("div", { className: css.heading, children: [_jsx("h2", { className: css.title, children: title }), subtitle !== undefined && _jsx("p", { className: css.subtitle, children: subtitle })] }), _jsx("button", { type: "button", className: css.close, "aria-label": t("update.close"), onClick: onClose, children: _jsx(IconCloseOutline16, {}) })] }), view.kind === "checking" && _jsx("p", { className: css.updateStatus, children: t("update.checking") }), view.kind === "result" && status !== undefined && _jsx(ResultBody, { t: t, status: status }), view.kind === "updating" && status !== undefined && (_jsxs("div", { children: [_jsx("p", { className: css.updateStatus, children: t("update.updating", { name: anchorName(status) ?? "", version: anchorLatest(status) ?? "" }) }), _jsx(PackageList, { status: status })] })), view.kind === "done" && _jsx(DoneBody, { t: t, result: view.result }), view.kind === "error" && (_jsxs("div", { children: [_jsx("p", { className: css.updateError, children: view.message }), view.detail !== undefined && _jsx("pre", { className: css.updateOutput, children: view.detail })] })), (view.kind === "done" || view.kind === "error") && (_jsx("div", { className: css.updateActions, children: _jsxs("button", { type: "button", className: css.updateRetry, onClick: onRecheck, children: [_jsx(IconRefreshOutline16, {}), " ", t("update.retry")] }) }))] }));
21
+ return (_jsxs("div", { className: css.panel, role: "dialog", "aria-modal": "true", "aria-label": title, children: [_jsxs("div", { className: css.header, children: [_jsxs("div", { className: css.heading, children: [_jsx("h2", { className: css.title, children: title }), subtitle !== undefined && _jsx("p", { className: css.subtitle, children: subtitle })] }), _jsx("button", { type: "button", className: css.close, "aria-label": t("update.close"), onClick: onClose, children: _jsx(IconCloseOutline16, {}) })] }), view.kind === "checking" && _jsx("p", { className: css.updateStatus, children: t("update.checking") }), view.kind === "result" && status !== undefined && _jsx(ResultBody, { t: t, status: status }), view.kind === "result" && status !== undefined && status.mode === "npm" && status.outdated && status.error === undefined && (_jsx("div", { className: css.updateActions, children: _jsx("button", { type: "button", className: css.updateRetry, onClick: () => onStartUpdate(status), children: t("update.start") }) })), view.kind === "updating" && status !== undefined && (_jsxs("div", { children: [_jsx("p", { className: css.updateStatus, children: t("update.updating", { name: anchorName(status) ?? "", version: anchorLatest(status) ?? "" }) }), _jsx("p", { className: css.updateDetail, children: t("update.cooldownNotice") }), _jsx(PackageList, { status: status })] })), view.kind === "done" && _jsx(DoneBody, { t: t, result: view.result }), view.kind === "error" && (_jsxs("div", { children: [_jsx("p", { className: css.updateError, children: view.message }), view.detail !== undefined && _jsx("pre", { className: css.updateOutput, children: view.detail })] })), (view.kind === "done" || view.kind === "error") && (_jsx("div", { className: css.updateActions, children: _jsxs("button", { type: "button", className: css.updateRetry, onClick: onRecheck, children: [_jsx(IconRefreshOutline16, {}), " ", t("update.retry")] }) }))] }));
22
22
  }
23
23
  /** The subtitle copy per view state (absent on plain results). */
24
24
  function subtitleOf(t, view) {
@@ -50,7 +50,7 @@ function ResultBody({ t, status }) {
50
50
  return (_jsxs("div", { children: [_jsx("p", { className: css.updateStatus, children: t("update.offline") }), _jsx("p", { className: css.updateDetail, children: t("update.offlineDetail") })] }));
51
51
  }
52
52
  if (status.outdated) {
53
- return (_jsxs("div", { children: [_jsx("p", { className: css.updateStatus, children: t("update.found") }), _jsx("p", { className: css.updateDetail, children: anchor !== undefined ? t("update.foundDetail", { name: anchor, version: latest ?? "" }) : "" })] }));
53
+ return (_jsxs("div", { children: [_jsx("p", { className: css.updateStatus, children: t("update.found") }), _jsx("p", { className: css.updateDetail, children: anchor !== undefined ? t("update.foundDetail", { name: anchor, version: latest ?? "" }) : "" }), _jsx("p", { className: css.updateDetail, children: t("update.cooldownNotice") })] }));
54
54
  }
55
55
  return (_jsxs("div", { children: [_jsx("p", { className: css.updateStatus, children: t("update.upToDate") }), anchor !== undefined && latest !== undefined && (_jsx("p", { className: css.updateDetail, children: t("update.upToDateDetail", { name: anchor, version: latest }) })), _jsx(PackageList, { status: status })] }));
56
56
  }
@@ -78,7 +78,9 @@ export declare const zh: {
78
78
  'update.upToDateDetail': string;
79
79
  'update.found': string;
80
80
  'update.foundDetail': string;
81
+ 'update.start': string;
81
82
  'update.updating': string;
83
+ 'update.cooldownNotice': string;
82
84
  'update.updatingTitle': string;
83
85
  'update.done': string;
84
86
  'update.doneDetail': string;
@@ -187,7 +189,9 @@ export declare const en: {
187
189
  'update.upToDateDetail': string;
188
190
  'update.found': string;
189
191
  'update.foundDetail': string;
192
+ 'update.start': string;
190
193
  'update.updating': string;
194
+ 'update.cooldownNotice': string;
191
195
  'update.updatingTitle': string;
192
196
  'update.done': string;
193
197
  'update.doneDetail': string;
@@ -1 +1 @@
1
- {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAE/E,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyGmB,CAAA;AAElC,sCAAsC;AACtC,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,EAAE,CAAA;AAEvC,wDAAwD;AACxD,MAAM,MAAM,eAAe,GAAG,SAAS,CAAA;AAEvC,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyGsB,CAAA"}
1
+ {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAE/E,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2GmB,CAAA;AAElC,sCAAsC;AACtC,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,EAAE,CAAA;AAEvC,wDAAwD;AACxD,MAAM,MAAM,eAAe,GAAG,SAAS,CAAA;AAEvC,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2GsB,CAAA"}
@@ -79,9 +79,11 @@ export const zh = {
79
79
  'update.upToDate': '当前已是最新版本',
80
80
  'update.upToDateDetail': '{name} 已是最新版本 v{version}。',
81
81
  'update.found': '发现新版本',
82
- 'update.foundDetail': '{name} 有新版本 v{version},正在自动更新…',
82
+ 'update.foundDetail': '{name} 有新版本 v{version}。确认后开始更新。',
83
+ 'update.start': '开始更新',
83
84
  'update.updating': '正在更新 {name} 至 v{version},可能需要 1-2 分钟…',
84
- 'update.updatingTitle': '正在自动更新…',
85
+ 'update.cooldownNotice': '本次更新由你主动触发,将跳过 pnpm 的 24 小时发布冷却期(供应链保护)直接安装所选版本。',
86
+ 'update.updatingTitle': '正在更新…',
85
87
  'update.done': '更新完成',
86
88
  'update.doneDetail': '所有组件已更新到最新版本。',
87
89
  'update.restartHint': '请重启 dsh web 使新版本生效:在终端按 Ctrl+C 停止后重新运行 dsh web。',
@@ -186,9 +188,11 @@ export const en = {
186
188
  'update.upToDate': 'Everything is up to date',
187
189
  'update.upToDateDetail': '{name} is at the latest version v{version}.',
188
190
  'update.found': 'A new version is available',
189
- 'update.foundDetail': '{name} has a newer release v{version}; updating automatically…',
191
+ 'update.foundDetail': '{name} has a newer release v{version}. Confirm to start the update.',
192
+ 'update.start': 'Update now',
190
193
  'update.updating': 'Updating {name} to v{version}; this may take 1-2 minutes…',
191
- 'update.updatingTitle': 'Updating automatically…',
194
+ 'update.cooldownNotice': 'This user-initiated update bypasses pnpm\'s 24-hour release cooldown (supply-chain protection) and installs the selected version immediately.',
195
+ 'update.updatingTitle': 'Updating…',
192
196
  'update.done': 'Update complete',
193
197
  'update.doneDetail': 'All components are up to date.',
194
198
  'update.restartHint': 'Restart dsh web for the new version to take effect: stop it with Ctrl+C in the terminal, then run dsh web again.',
@@ -83,12 +83,7 @@ export declare function readPairParams(search: string): {
83
83
  pair?: string;
84
84
  workspace?: string;
85
85
  };
86
- /**
87
- * Strip one query parameter from the current URL without reloading.
88
- * @param name - the parameter to remove.
89
- * @returns the new search string ('' when empty).
90
- */
91
- export declare function stripParam(name: string): string; /** Human-readable expiry clock, e.g. "10:35". */
86
+ /** Human-readable expiry clock, e.g. "10:35". */
92
87
  export declare function formatClock(epochMs: number): string;
93
88
  /**
94
89
  * Copy text to the clipboard with a fallback for insecure contexts
@@ -1 +1 @@
1
- {"version":3,"file":"pair-api.d.ts","sourceRoot":"","sources":["../../../src/client/pair-api.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAwB;AACxB,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,IAAI,CAAA;IACR,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,KAAK,CAAA;IACT,IAAI,EAAE,cAAc,CAAA;CACrB;AAED,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,KAAK,CAAA;IACT,IAAI,EAAE,iBAAiB,CAAA;CACxB;AAED,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,KAAK,CAAA;IACT,IAAI,EAAE,WAAW,CAAA;CAClB;AAED,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,qBAAqB,CAAA;AAExG,8BAA8B;AAC9B,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,WAAW,CAAA;CAAE,CAAA;AAEjF,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAA;IACxC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,kCAAkC;AAClC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,CAAA;IAC5E,YAAY,EAAE,OAAO,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAgB9F;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,aAAa,CAAC,CAUrF;AAED,iEAAiE;AACjE,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAG9C;AAED,mFAAmF;AACnF,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnD;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAQpF;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/C,CAAA,iDAAiD;AAClD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAsB7D"}
1
+ {"version":3,"file":"pair-api.d.ts","sourceRoot":"","sources":["../../../src/client/pair-api.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAwB;AACxB,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,IAAI,CAAA;IACR,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,KAAK,CAAA;IACT,IAAI,EAAE,cAAc,CAAA;CACrB;AAED,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,KAAK,CAAA;IACT,IAAI,EAAE,iBAAiB,CAAA;CACxB;AAED,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,KAAK,CAAA;IACT,IAAI,EAAE,WAAW,CAAA;CAClB;AAED,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,qBAAqB,CAAA;AAExG,8BAA8B;AAC9B,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,WAAW,CAAA;CAAE,CAAA;AAEjF,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAA;IACxC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,kCAAkC;AAClC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,CAAA;IAC5E,YAAY,EAAE,OAAO,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAgB9F;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,aAAa,CAAC,CAUrF;AAED,iEAAiE;AACjE,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAG9C;AAED,mFAAmF;AACnF,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnD;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAQpF;AAED,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAsB7D"}
@@ -74,16 +74,7 @@ export function readPairParams(search) {
74
74
  ...(workspace !== null && workspace !== '' ? { workspace } : {}),
75
75
  };
76
76
  }
77
- /**
78
- * Strip one query parameter from the current URL without reloading.
79
- * @param name - the parameter to remove.
80
- * @returns the new search string ('' when empty).
81
- */
82
- export function stripParam(name) {
83
- const url = new URL(window.location.href);
84
- url.searchParams.delete(name);
85
- return url.search;
86
- } /** Human-readable expiry clock, e.g. "10:35". */
77
+ /** Human-readable expiry clock, e.g. "10:35". */
87
78
  export function formatClock(epochMs) {
88
79
  const date = new Date(epochMs);
89
80
  const hours = String(date.getHours()).padStart(2, '0');
@@ -1 +1 @@
1
- {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAGlD;;;;;;;GAOG;AAEH;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASvF;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAQvE;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAKlE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,cAAc,EACvB,oBAAoB,GAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAQ,EACtD,OAAO,GAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAQ,GACxC,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAS9H;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAIhG"}
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAGlD;;;;;;;GAOG;AAEH;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASvF;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAQvE;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAKlE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,cAAc,EACvB,oBAAoB,GAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAQ,EACtD,OAAO,GAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAQ,GACxC,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAW9H;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAIhG"}
package/lib/types/gate.js CHANGED
@@ -86,6 +86,8 @@ export function makeGateListener(service, requirePairingForLan = true, enabled =
86
86
  const require = typeof requirePairingForLan === 'function' ? requirePairingForLan() : requirePairingForLan;
87
87
  if (!require)
88
88
  return next();
89
+ // The paired-device cookie is a full host-API credential: it passes this
90
+ // gate for the whole ApiProxy surface, not just the /m/api allowlist.
89
91
  return isPairedDeviceRequest(service, request) ? next() : false;
90
92
  };
91
93
  }
@@ -5,6 +5,7 @@
5
5
  * rpc/mux layers).
6
6
  */
7
7
  import type { WorkspaceView } from '@deepseek-ai/dsh-host-apiproxy/api/workspace';
8
+ import type { AgentPresetEntry } from '@deepseek-ai/dsh-host-apiproxy/api/agent-presets';
8
9
  import type { SessionSummary, SessionModels, SessionProjectionsBlock } from '@deepseek-ai/dsh-host-apiproxy/api/sessions';
9
10
  /** One session.list page. */
10
11
  export interface SessionPage {
@@ -19,6 +20,12 @@ export interface CreatedSession {
19
20
  /** The composition the new session runs (echoed so the caller can label it). */
20
21
  agentPreset?: string;
21
22
  }
23
+ /** Agent presets available when composing a new session. */
24
+ export interface AgentPresetRoster {
25
+ presets: readonly AgentPresetEntry[];
26
+ authorable: boolean;
27
+ hasDocument: boolean;
28
+ }
22
29
  /** One history page (already bounded to whole messages by the host). */
23
30
  export interface HistoryPage {
24
31
  events: import('@deepseek-ai/dsh-host-apiproxy/api/sessions').HistoryEntry[];
@@ -40,6 +47,8 @@ export declare function listWorkspaces(): Promise<WorkspaceView[]>;
40
47
  export declare function fetchMobilePreferences(): Promise<MobilePreferences>;
41
48
  /** One session.list page; omit the cursor for the first page. */
42
49
  export declare function listSessions(cursor?: string): Promise<SessionPage>;
50
+ /** Read the available agent compositions for a new session. */
51
+ export declare function listAgentPresets(): Promise<AgentPresetRoster>;
43
52
  /**
44
53
  * Create a blank session (entity birth precedes the first message). Name a
45
54
  * workspace to attach it there, or a cwd; omitting both uses the host cwd.
@@ -47,6 +56,7 @@ export declare function listSessions(cursor?: string): Promise<SessionPage>;
47
56
  export declare function createSession(options?: {
48
57
  workspaceId?: string;
49
58
  cwd?: string;
59
+ agentPreset?: string;
50
60
  }): Promise<CreatedSession>;
51
61
  /** One history window; omit beforeSeq for the tail page, pass a signal to abort. */
52
62
  export declare function history(sessionId: string, beforeSeq?: number, maxMessages?: number, signal?: AbortSignal): Promise<HistoryPage>;
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/mobile/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAA;AACjF,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,6CAA6C,CAAA;AAGzH,6BAA6B;AAC7B,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,6CAA6C,EAAE,YAAY,EAAE,CAAA;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,uBAAuB,CAAA;CACtC;AAED,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,kEAAkE;AAClE,wBAAsB,cAAc,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAG/D;AAED,yFAAyF;AACzF,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAEzE;AAED,iEAAiE;AACjE,wBAAsB,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAExE;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GACnD,OAAO,CAAC,cAAc,CAAC,CAEzB;AAED,oFAAoF;AACpF,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,WAAW,SAAK,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,WAAW,CAAC,CAMtB;AAED,qEAAqE;AACrE,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM3E;AAED,wEAAwE;AACxE,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMnF;AAED,oFAAoF;AACpF,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAEtE;AAED,2FAA2F;AAC3F,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GACvE,OAAO,CAAC;IAAE,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CAOtF"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/mobile/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAA;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAA;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,6CAA6C,CAAA;AAGzH,6BAA6B;AAC7B,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAA;IACpC,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,6CAA6C,EAAE,YAAY,EAAE,CAAA;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,uBAAuB,CAAA;CACtC;AAED,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,kEAAkE;AAClE,wBAAsB,cAAc,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAG/D;AAED,yFAAyF;AACzF,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAEzE;AAED,iEAAiE;AACjE,wBAAsB,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAExE;AAED,+DAA+D;AAC/D,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAEnE;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACzE,OAAO,CAAC,cAAc,CAAC,CAEzB;AAED,oFAAoF;AACpF,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,WAAW,SAAK,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,WAAW,CAAC,CAMtB;AAED,qEAAqE;AACrE,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM3E;AAED,wEAAwE;AACxE,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMnF;AAED,oFAAoF;AACpF,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAEtE;AAED,2FAA2F;AAC3F,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GACvE,OAAO,CAAC;IAAE,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CAOtF"}
@@ -18,6 +18,10 @@ export async function fetchMobilePreferences() {
18
18
  export async function listSessions(cursor) {
19
19
  return await callUnary('session.list', cursor === undefined ? {} : { cursor });
20
20
  }
21
+ /** Read the available agent compositions for a new session. */
22
+ export async function listAgentPresets() {
23
+ return await callUnary('agentPreset.list', {});
24
+ }
21
25
  /**
22
26
  * Create a blank session (entity birth precedes the first message). Name a
23
27
  * workspace to attach it there, or a cwd; omitting both uses the host cwd.
@@ -114,4 +114,28 @@ export interface WireEvent {
114
114
  * @returns messages sorted by seq.
115
115
  */
116
116
  export declare function foldEvents(events: readonly WireEvent[], existing?: readonly RenderMessage[]): RenderMessage[];
117
+ /**
118
+ * Incremental folder for one message stream. Live chat folds one event at a
119
+ * time; rebuilding the five index maps by scanning every message per event
120
+ * made that path O(n) per event (O(n * events) per turn). A folder keeps the
121
+ * indexes alive across folds, applies each event in O(1) map operations, and
122
+ * returns the previous snapshot identity unchanged when nothing applied, so
123
+ * React skips the re-render entirely. Replayed events are no-ops: the maxSeq
124
+ * watermark advanced by the first application skips them, which also makes a
125
+ * double-invoked React state updater harmless.
126
+ */
127
+ export declare class EventFolder {
128
+ private state;
129
+ private snapshotList;
130
+ /** @param initial - seed rows (history tail load); omit for an empty stream. */
131
+ constructor(initial?: readonly RenderMessage[]);
132
+ /** Fold one batch incrementally; returns the current snapshot list. */
133
+ fold(events: readonly WireEvent[]): RenderMessage[];
134
+ /** Replace the whole stream (history reload / session switch). */
135
+ seed(messages: readonly RenderMessage[]): void;
136
+ /** Prepend an older history page (exact seam; no overlapping seqs). */
137
+ prepend(older: readonly RenderMessage[]): void;
138
+ /** Current snapshot list; a fresh copy whenever the folder changed. */
139
+ snapshot(): RenderMessage[];
140
+ }
117
141
  //# sourceMappingURL=messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/mobile/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,EAAE,CAAA;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,kFAAkF;IAClF,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,sFAAsF;IACtF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE;QACf,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,MAAM,CAAA;QACpB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAC1B,CAAA;IACD,sFAAsF;IACtF,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,qDAAqD;IACrD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,IAAI,CAAA;CAC1B;AA6eD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,GAAG,aAAa,EAAE,CAsB7G"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/mobile/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,EAAE,CAAA;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,kFAAkF;IAClF,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,sFAAsF;IACtF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE;QACf,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,MAAM,CAAA;QACpB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAC1B,CAAA;IACD,sFAAsF;IACtF,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,qDAAqD;IACrD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,IAAI,CAAA;CAC1B;AAweD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,GAAG,aAAa,EAAE,CAE7G;AAED;;;;;;;;;GASG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,YAAY,CAA6B;IAEjD,gFAAgF;IAChF,YAAY,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,EAE7C;IAED,uEAAuE;IACvE,IAAI,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,aAAa,EAAE,CAWlD;IAED,kEAAkE;IAClE,IAAI,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAG7C;IAED,uEAAuE;IACvE,OAAO,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAG7C;IAED,uEAAuE;IACvE,QAAQ,IAAI,aAAa,EAAE,CAI1B;CACF"}