kiokuko-dsh 0.1.19 → 0.1.20

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.
@@ -0,0 +1,228 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "kiokuko-dsh",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ const { createSnapshotStore } = require("@deepseek-ai/dsh-client-store");
7
+ const { jsx, jsxs, Fragment } = require("react/jsx-runtime");
8
+ const { Modal, Button, IconDownloadOutline16 } = require("@deepseek-ai/dsh-client-ui-primitives");
9
+ const SESSION_EXPORT_PATH = '/api/session.export';
10
+ const LOCALE_NAMESPACE = 'kiokuko-session-log-download';
11
+ const INITIAL_DOWNLOAD_STATE = { bySession: {} };
12
+ const en = {
13
+ 'header.action': 'Session log',
14
+ 'dialog.preparingTitle': 'Exporting Session',
15
+ 'dialog.preparingDescription': 'Streaming this Session, its sub-Sessions, and attachments to a ZIP file.',
16
+ 'dialog.successTitle': 'Session export complete',
17
+ 'dialog.successDescription': 'The Session ZIP has been saved or handed to the browser download manager.',
18
+ 'dialog.errorTitle': 'Session export failed',
19
+ 'dialog.close': 'Close',
20
+ 'dialog.commandFailed': 'Could not export the Session log.',
21
+ };
22
+ const ja = {
23
+ 'header.action': 'Session log',
24
+ 'dialog.preparingTitle': 'Sessionをエクスポート中',
25
+ 'dialog.preparingDescription': 'このSession、子Session、添付ファイルをZIPへストリーミングしています。',
26
+ 'dialog.successTitle': 'Sessionのエクスポート完了',
27
+ 'dialog.successDescription': 'Session ZIPを保存、またはブラウザのダウンロード処理へ渡しました。',
28
+ 'dialog.errorTitle': 'Sessionのエクスポートに失敗',
29
+ 'dialog.close': '閉じる',
30
+ 'dialog.commandFailed': 'Session logをエクスポートできませんでした。',
31
+ };
32
+ const zh = {
33
+ 'header.action': 'Session 日志',
34
+ 'dialog.preparingTitle': '正在导出 Session',
35
+ 'dialog.preparingDescription': '正在将当前 Session、子 Session 和附件流式写入 ZIP 文件。',
36
+ 'dialog.successTitle': 'Session 导出完成',
37
+ 'dialog.successDescription': 'Session ZIP 已保存或交给浏览器下载管理器。',
38
+ 'dialog.errorTitle': 'Session 导出失败',
39
+ 'dialog.close': '关闭',
40
+ 'dialog.commandFailed': '无法导出 Session 日志。',
41
+ };
42
+ function hostBase() {
43
+ const origin = globalThis.location?.origin;
44
+ return origin !== undefined && origin !== 'null' ? origin : 'http://dsh.internal';
45
+ }
46
+ function messageOf(error) {
47
+ return error instanceof Error ? error.message : String(error);
48
+ }
49
+ function isAbortError(error) {
50
+ return typeof DOMException !== 'undefined' && error instanceof DOMException && error.name === 'AbortError';
51
+ }
52
+ function sessionLogZipFilename(sessionId) {
53
+ return `dsh-session-${String(sessionId).replace(/[^A-Za-z0-9_-]/gu, '_')}.zip`;
54
+ }
55
+ async function responseFailure(response) {
56
+ const detail = await response.text().catch(() => '');
57
+ return new Error(`Session export failed: HTTP ${response.status}${detail === '' ? '' : ` ${detail}`}`);
58
+ }
59
+ /** Browser helper that never builds a whole-log Blob in application memory. */
60
+ async function downloadDshSessionLog(options) {
61
+ const url = new URL(options.endpoint);
62
+ url.searchParams.set('sessionId', options.sessionId);
63
+ url.searchParams.set('includeDescendants', 'true');
64
+ const browser = options.window ?? globalThis.window;
65
+ if (browser?.showSaveFilePicker === undefined) {
66
+ if (browser === undefined)
67
+ throw new Error('browser download surface is unavailable');
68
+ url.searchParams.set('download', '1');
69
+ browser.location.assign(url.toString());
70
+ return 'navigated';
71
+ }
72
+ const handle = await browser.showSaveFilePicker({
73
+ suggestedName: sessionLogZipFilename(options.sessionId),
74
+ types: [{ description: 'ZIP archive', accept: { 'application/zip': ['.zip'] } }],
75
+ });
76
+ const response = await (options.fetch ?? globalThis.fetch)(url, options.signal === undefined ? {} : { signal: options.signal });
77
+ if (!response.ok)
78
+ throw await responseFailure(response);
79
+ if (response.body === null)
80
+ throw new Error('Session export returned no response stream');
81
+ const writable = await handle.createWritable();
82
+ await response.body.pipeTo(writable);
83
+ return 'streamed';
84
+ }
85
+ class SessionLogDownloadController {
86
+ store = createSnapshotStore({ ...INITIAL_DOWNLOAD_STATE, bySession: {} });
87
+ active = new Map();
88
+ disposed = false;
89
+ download(sessionId) {
90
+ const existing = this.active.get(sessionId);
91
+ if (existing !== undefined)
92
+ return existing.done;
93
+ if (this.disposed)
94
+ return Promise.resolve();
95
+ const abort = new AbortController();
96
+ const done = this.run(sessionId, abort.signal).finally(() => this.active.delete(sessionId));
97
+ this.active.set(sessionId, { abort, done });
98
+ return done;
99
+ }
100
+ dismiss(sessionId) {
101
+ const current = this.store.getSnapshot().bySession[sessionId];
102
+ if (current === undefined || !current.open)
103
+ return;
104
+ this.publish(sessionId, { ...current, open: false });
105
+ }
106
+ async dispose() {
107
+ this.disposed = true;
108
+ const active = [...this.active.values()];
109
+ for (const operation of active)
110
+ operation.abort.abort();
111
+ await Promise.allSettled(active.map(operation => operation.done));
112
+ }
113
+ async run(sessionId, signal) {
114
+ this.publish(sessionId, { open: true, status: 'downloading', error: null });
115
+ try {
116
+ const endpoint = new URL(SESSION_EXPORT_PATH, hostBase()).toString();
117
+ const browser = globalThis.window;
118
+ if (browser?.showSaveFilePicker === undefined) {
119
+ const probe = await fetch(`${endpoint}?sessionId=${encodeURIComponent(sessionId)}&includeDescendants=true`, {
120
+ method: 'HEAD',
121
+ signal,
122
+ });
123
+ if (!probe.ok)
124
+ throw await responseFailure(probe);
125
+ }
126
+ await downloadDshSessionLog({
127
+ endpoint,
128
+ sessionId,
129
+ signal,
130
+ ...(browser === undefined ? {} : { window: browser }),
131
+ });
132
+ const open = this.store.getSnapshot().bySession[sessionId]?.open ?? true;
133
+ this.publish(sessionId, { open, status: 'success', error: null });
134
+ }
135
+ catch (error) {
136
+ if (signal.aborted || isAbortError(error))
137
+ return;
138
+ const open = this.store.getSnapshot().bySession[sessionId]?.open ?? true;
139
+ this.publish(sessionId, { open, status: 'error', error: messageOf(error) });
140
+ }
141
+ }
142
+ publish(sessionId, entry) {
143
+ this.store.update(state => {
144
+ state.bySession = { ...state.bySession, [sessionId]: entry };
145
+ });
146
+ }
147
+ }
148
+ function SessionLogDownloadDialog(props) {
149
+ const sessionId = String(props.sessionId);
150
+ const useSessionLogDownload = props.useSessionLogDownload;
151
+ const dismiss = props.dismiss;
152
+ const t = props.t;
153
+ const entry = useSessionLogDownload(state => state.bySession[sessionId]);
154
+ const status = entry?.status;
155
+ const error = status === 'error' ? entry?.error || t('dialog.commandFailed') : null;
156
+ return jsx(Modal, {
157
+ open: entry?.open === true,
158
+ onClose: () => dismiss(sessionId),
159
+ title: status === 'downloading'
160
+ ? t('dialog.preparingTitle')
161
+ : status === 'success' ? t('dialog.successTitle') : t('dialog.errorTitle'),
162
+ description: status === 'downloading'
163
+ ? t('dialog.preparingDescription')
164
+ : status === 'success' ? t('dialog.successDescription') : error ?? t('dialog.commandFailed'),
165
+ closeLabel: t('dialog.close'),
166
+ footer: jsx(Button, { variant: 'primary', onClick: () => dismiss(sessionId), children: t('dialog.close') }),
167
+ });
168
+ }
169
+ function SessionLogDownloadHeaderAction(props) {
170
+ const sessionId = String(props.sessionId);
171
+ const useSessionLogDownload = props.useSessionLogDownload;
172
+ const request = props.request;
173
+ const t = props.t;
174
+ const busy = useSessionLogDownload(state => state.bySession[sessionId])?.status === 'downloading';
175
+ return jsxs(Fragment, {
176
+ children: [
177
+ jsxs('button', {
178
+ type: 'button',
179
+ className: 'kiokuko-session-log-button',
180
+ disabled: busy,
181
+ 'aria-busy': busy,
182
+ onClick: () => request(sessionId),
183
+ children: [jsx('span', { children: t('header.action') }), jsx(IconDownloadOutline16, { size: 12 })],
184
+ }),
185
+ jsx(SessionLogDownloadDialog, props),
186
+ ],
187
+ });
188
+ }
189
+ function installStyle() {
190
+ const styleId = 'kiokuko-session-log-download-style';
191
+ const existing = document.querySelector(`style[data-plugin-css="${styleId}"]`);
192
+ if (existing !== null)
193
+ return () => undefined;
194
+ const style = document.createElement('style');
195
+ style.dataset.plugin = 'kiokuko-dsh';
196
+ style.dataset.pluginCss = styleId;
197
+ style.textContent = '.kiokuko-session-log-button{border:.5px solid var(--dsw-alias-border-l4);min-width:111px;height:32px;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family);cursor:pointer;background:transparent;border-radius:18px;justify-content:center;align-items:center;gap:4px;padding:6px 12px;font-size:13px;font-weight:400;line-height:20px;display:inline-flex}.kiokuko-session-log-button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.kiokuko-session-log-button:disabled{color:var(--dsw-alias-label-dimmed);cursor:wait}.kiokuko-session-log-button span,.kiokuko-session-log-button svg{flex:none}.kiokuko-session-log-button span{white-space:nowrap}';
198
+ document.head.appendChild(style);
199
+ return () => style.remove();
200
+ }
201
+ const inject = ['slots', 'locale'];
202
+ /** Register Kiokuko's streaming Session-export browser surface. */
203
+ function apply(ctx) {
204
+ const controller = new SessionLogDownloadController();
205
+ ctx.effect(() => async () => controller.dispose(), 'kiokuko-dsh: browser download lifecycle');
206
+ ctx.effect(installStyle, 'kiokuko-dsh: browser download style');
207
+ ctx.effect(() => ctx.locale.register(LOCALE_NAMESPACE, { en, ja, zh }), 'kiokuko-dsh: browser dictionaries');
208
+ ctx.on('command/executed', (sessionId, commandName, result) => {
209
+ if (commandName === 'export' && result.kind === 'success')
210
+ void controller.download(sessionId);
211
+ });
212
+ ctx.slots.inject('conversation.session.header.utilities', () => ctx.slots.register({
213
+ name: 'conversation.session.header.utilities',
214
+ id: 'kiokuko-session-log-download',
215
+ locale: LOCALE_NAMESPACE,
216
+ inject: () => ({
217
+ hooks: { sessionLogDownload: controller.store },
218
+ request: (sessionId) => controller.download(sessionId),
219
+ dismiss: (sessionId) => controller.dismiss(sessionId),
220
+ }),
221
+ }, SessionLogDownloadHeaderAction));
222
+ }
223
+ exports.apply = apply;
224
+ exports.downloadDshSessionLog = downloadDshSessionLog;
225
+ exports.inject = inject;
226
+ return module.exports;
227
+ }
228
+ });
package/dist/client.d.ts CHANGED
@@ -1,18 +1,40 @@
1
+ interface DshSessionDownloadWindow {
2
+ showSaveFilePicker?: (options: unknown) => Promise<{
3
+ createWritable(): Promise<WritableStream<Uint8Array>>;
4
+ }>;
5
+ location: {
6
+ assign(url: string): void;
7
+ };
8
+ }
1
9
  export interface DshSessionDownloadOptions {
2
10
  readonly endpoint: string;
3
11
  readonly sessionId: string;
4
12
  readonly fetch?: typeof globalThis.fetch;
5
- readonly window?: {
6
- showSaveFilePicker?: (options: unknown) => Promise<{
7
- createWritable(): Promise<WritableStream<Uint8Array>>;
8
- }>;
9
- location: {
10
- assign(url: string): void;
11
- };
13
+ readonly signal?: AbortSignal;
14
+ readonly window?: DshSessionDownloadWindow;
15
+ }
16
+ interface DshClientContext {
17
+ readonly locale: {
18
+ register(namespace: string, dictionaries: Record<string, Record<string, string>>): unknown;
12
19
  };
20
+ readonly slots: {
21
+ inject(name: string, register: () => unknown): unknown;
22
+ register(definition: {
23
+ readonly name: string;
24
+ readonly id: string;
25
+ readonly locale: string;
26
+ readonly inject: () => Record<string, unknown>;
27
+ }, component: (props: Record<string, unknown>) => unknown): unknown;
28
+ };
29
+ effect(setup: () => void | (() => void | Promise<void>), label: string): unknown;
30
+ on(event: 'command/executed', listener: (sessionId: string, commandName: string, result: {
31
+ readonly kind: string;
32
+ }) => void): unknown;
13
33
  }
14
- export declare const inject: readonly ["slots", "locale"];
15
- export declare function apply(ctx: import('@deepseek-ai/cordis').Context): Promise<void>;
16
34
  /** Browser helper that never builds a whole-log Blob in application memory. */
17
35
  export declare function downloadDshSessionLog(options: DshSessionDownloadOptions): Promise<'streamed' | 'navigated'>;
36
+ export declare const inject: readonly ["slots", "locale"];
37
+ /** Register Kiokuko's streaming Session-export browser surface. */
38
+ export declare function apply(ctx: DshClientContext): void;
39
+ export {};
18
40
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;YAAE,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAA;SAAE,CAAC,CAAA;QAC7G,QAAQ,EAAE;YAAE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,CAAA;KACxC,CAAA;CACF;AAID,eAAO,MAAM,MAAM,8BAA+B,CAAA;AAClD,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,qBAAqB,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrF;AAED,+EAA+E;AAC/E,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,UAAU,GAAG,WAAW,CAAC,CAiBjH"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,UAAU,wBAAwB;IAChC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;QAAE,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,CAAC,CAAA;IAC7G,QAAQ,EAAE;QAAE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACxC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAC3C;AAYD,UAAU,gBAAgB;IACxB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAA;KAC3F,CAAA;IACD,QAAQ,CAAC,KAAK,EAAE;QACd,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,GAAG,OAAO,CAAA;QACtD,QAAQ,CACN,UAAU,EAAE;YACV,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;YACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;YACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;YACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAC/C,EACD,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,GACrD,OAAO,CAAA;KACX,CAAA;IACD,MAAM,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IAChF,EAAE,CAAC,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAA;CACtI;AAuED,+EAA+E;AAC/E,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,UAAU,GAAG,WAAW,CAAC,CAqBjH;AAuHD,eAAO,MAAM,MAAM,8BAA+B,CAAA;AAElD,mEAAmE;AACnE,wBAAgB,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAkBjD"}
@@ -90,7 +90,7 @@ the path binding in its database and does not create `.git`, `.kiokuko.json`,
90
90
  or any other metadata file in the workspace.
91
91
 
92
92
  `kiokuko-dsh` disables the existing `session-log-download` Host row and inserts
93
- its own row under the stable `kiokuko-dsh` id. Its client delegates to the stock
93
+ its own row under the stable `kiokuko-dsh` id. Its DSH lazy-CJS client owns the
94
94
  Header modal and `/export` command UI while the Host route uses cursor-backed
95
95
  streaming export. Removing the bundle restores the stock row without rewriting
96
96
  unrelated plugins or settings. The plugin does not edit `AGENTS.md`.
@@ -34,12 +34,14 @@ packed-artifact integrity, and these outcomes without credentials:
34
34
 
35
35
  1. the reproducibility check proves that `prepare` emits the same `dist/` tree
36
36
  from the fixed source;
37
- 2. the package check builds a tarball containing the declared runtime closure
38
- and imports `kiokuko-dsh`, `kiokuko-dsh/client`, and `kiokuko-dsh/dsh` from an isolated consumer;
37
+ 2. the package check builds a tarball containing the declared runtime closure,
38
+ imports the Host entrypoints from an isolated consumer, and executes and
39
+ materializes `kiokuko-dsh/client` as a DSH lazy-CJS artifact;
39
40
  3. the disposable Profile installs that exact tarball;
40
41
  4. `dump-config` contains one active `kiokuko-dsh` row and the stock
41
42
  `session-log-download` row is disabled;
42
- 5. the DSH `web` profile cold-starts and reports the plugin loaded;
43
+ 5. the DSH `web` profile cold-starts, reports the plugin loaded, authenticates,
44
+ and executes and materializes Kiokuko from the composed application bundle;
43
45
  6. the profile stops cleanly;
44
46
  7. removing the plugin leaves no `kiokuko-dsh` row and restores the active
45
47
  stock `session-log-download` row.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiokuko-dsh",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Kiokuko plugin for DeepSeek Harness",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "./client": {
40
40
  "types": "./dist/client.d.ts",
41
- "default": "./dist/client.js"
41
+ "default": "./dist/client.cjs"
42
42
  },
43
43
  "./dsh": {
44
44
  "types": "./dist/dsh/index.d.ts",
@@ -104,7 +104,7 @@
104
104
  },
105
105
  "scripts": {
106
106
  "clean:dist": "node --input-type=module --eval \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true });\"",
107
- "build": "npm run clean:dist && tsc -p tsconfig.build.json",
107
+ "build": "npm run clean:dist && tsc -p tsconfig.build.json && node scripts/build-dsh-client.mjs",
108
108
  "typecheck": "tsc -p tsconfig.json --noEmit",
109
109
  "test": "node scripts/run-tests.mjs tests/dsh",
110
110
  "test:unit": "node scripts/run-tests.mjs tests/dsh/unit",
@@ -134,15 +134,11 @@
134
134
  },
135
135
  "peerDependencies": {
136
136
  "@deepseek-ai/cordis": "^4.0.2",
137
- "@deepseek-ai/dsh-session-log-export": "0.1.2-rc.1",
138
137
  "@huggingface/hub": "2.16.1",
139
138
  "@huggingface/transformers": "4.2.0",
140
139
  "sqlite-vec": "0.1.9"
141
140
  },
142
141
  "peerDependenciesMeta": {
143
- "@deepseek-ai/dsh-session-log-export": {
144
- "optional": true
145
- },
146
142
  "@huggingface/hub": {
147
143
  "optional": true
148
144
  },
package/dist/client.js DELETED
@@ -1,31 +0,0 @@
1
- /// <reference path="./dsh-session-log-export-client.d.ts" />
2
- // Keep DSH's native Header modal and `/export` command behavior. Loading is
3
- // deferred so non-Web consumers can import `./client` without the DSH bundle.
4
- export const inject = ['slots', 'locale'];
5
- export async function apply(ctx) {
6
- const official = await import('@deepseek-ai/dsh-session-log-export/client');
7
- official.apply(ctx);
8
- }
9
- /** Browser helper that never builds a whole-log Blob in application memory. */
10
- export async function downloadDshSessionLog(options) {
11
- const url = new URL(options.endpoint);
12
- url.searchParams.set('sessionId', options.sessionId);
13
- const browser = options.window ?? globalThis.window;
14
- if (browser?.showSaveFilePicker === undefined) {
15
- if (browser === undefined)
16
- throw new Error('browser download surface is unavailable');
17
- url.searchParams.set('download', '1');
18
- browser.location.assign(url.toString());
19
- return 'navigated';
20
- }
21
- const response = await (options.fetch ?? globalThis.fetch)(url);
22
- if (!response.ok)
23
- throw new Error(`Session export failed: HTTP ${response.status}`);
24
- if (response.body === null)
25
- throw new Error('Session export returned no response stream');
26
- const handle = await browser.showSaveFilePicker({ suggestedName: `dsh-session-${options.sessionId}.zip`, types: [{ description: 'ZIP archive', accept: { 'application/zip': ['.zip'] } }] });
27
- const writable = await handle.createWritable();
28
- await response.body.pipeTo(writable);
29
- return 'streamed';
30
- }
31
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAY7D,4EAA4E;AAC5E,8EAA8E;AAC9E,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAU,CAAA;AAClD,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,GAA0C;IACpE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,4CAA4C,CAAC,CAAA;IAC3E,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AACrB,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAkC;IAC5E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACrC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,IAAK,UAA0E,CAAC,MAAM,CAAA;IACpH,IAAI,OAAO,EAAE,kBAAkB,KAAK,SAAS,EAAE,CAAC;QAC9C,IAAI,OAAO,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;QACrF,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;QACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;QACvC,OAAO,WAAW,CAAA;IACpB,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAA;IAC/D,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IACnF,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IACzF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,kBAAkB,CAAC,EAAE,aAAa,EAAE,eAAe,OAAO,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,iBAAiB,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;IAC5L,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAA;IAC9C,MAAM,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACpC,OAAO,UAAU,CAAA;AACnB,CAAC"}