dsh-multi-chat 0.6.7 → 1.0.0
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.
- package/README.md +20 -21
- package/README.zh.md +20 -21
- package/bin/dsh-multi-chat.mjs +5 -9
- package/lib/client.js +778 -0
- package/lib/client.js.map +1 -0
- package/{plugin/dsh-client-ui-multi-wall/lib → lib}/index.js +57 -69
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/WallToggle.d.ts +1 -1
- package/lib/types/client/WallToggle.d.ts.map +1 -0
- package/lib/types/client/WallToggle.js +36 -0
- package/lib/types/client/WallToggle.js.map +1 -0
- package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/WallView.d.ts +1 -1
- package/lib/types/client/WallView.d.ts.map +1 -0
- package/lib/types/client/WallView.js +218 -0
- package/lib/types/client/WallView.js.map +1 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/index.js +59 -0
- package/lib/types/client/index.js.map +1 -0
- package/lib/types/client/locales.d.ts.map +1 -0
- package/lib/types/client/locales.js +96 -0
- package/lib/types/client/locales.js.map +1 -0
- package/lib/types/client/store.d.ts.map +1 -0
- package/lib/types/client/store.js +27 -0
- package/lib/types/client/store.js.map +1 -0
- package/lib/types/client/wall-injected.d.ts.map +1 -0
- package/lib/types/client/wall-injected.js +76 -0
- package/lib/types/client/wall-injected.js.map +1 -0
- package/lib/types/gateway.d.ts +57 -0
- package/lib/types/gateway.d.ts.map +1 -0
- package/lib/types/gateway.js +566 -0
- package/lib/types/gateway.js.map +1 -0
- package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/index.d.ts +1 -16
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +550 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/invariant.d.ts.map +1 -0
- package/lib/types/invariant.js +26 -0
- package/lib/types/invariant.js.map +1 -0
- package/package.json +31 -17
- package/scripts/install-plugin.ps1 +6 -9
- package/src/client/WallToggle.module.css +26 -0
- package/src/client/WallToggle.tsx +52 -0
- package/src/client/WallView.module.css +190 -0
- package/src/client/WallView.tsx +406 -0
- package/src/client/index.ts +103 -0
- package/src/client/locales.ts +100 -0
- package/src/client/store.ts +40 -0
- package/src/client/wall-injected.ts +123 -0
- package/src/css-modules.d.ts +5 -0
- package/src/gateway.ts +627 -0
- package/src/index.ts +618 -0
- package/src/invariant.ts +34 -0
- package/plugin/dsh-client-ui-multi-wall/README.md +0 -26
- package/plugin/dsh-client-ui-multi-wall/README.zh.md +0 -26
- package/plugin/dsh-client-ui-multi-wall/cordis.patch.yml +0 -7
- package/plugin/dsh-client-ui-multi-wall/lib/client.js +0 -781
- package/plugin/dsh-client-ui-multi-wall/lib/invariant.js +0 -27
- package/plugin/dsh-client-ui-multi-wall/package.json +0 -88
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/index.d.ts +0 -0
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/locales.d.ts +0 -0
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/store.d.ts +0 -0
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/client/wall-injected.d.ts +0 -0
- /package/{plugin/dsh-client-ui-multi-wall/lib → lib}/types/invariant.d.ts +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/** `multiWall` namespace dictionaries. */
|
|
2
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
3
|
+
export const zh = {
|
|
4
|
+
'toggle': '多窗口',
|
|
5
|
+
'toggle.aria': '打开或关闭多窗口',
|
|
6
|
+
'view.multiWall': '多窗口',
|
|
7
|
+
'overlay.title': '多窗口',
|
|
8
|
+
'overlay.close': '关闭',
|
|
9
|
+
'scan': '发现实例',
|
|
10
|
+
'scan.from': '起始端口',
|
|
11
|
+
'scan.to': '结束端口',
|
|
12
|
+
'create': '新建窗口',
|
|
13
|
+
'create.pending': '启动中…',
|
|
14
|
+
'create.done': '已创建窗口 :{port}',
|
|
15
|
+
'create.failed': '创建失败:{error}',
|
|
16
|
+
'create.unknown': '未知原因',
|
|
17
|
+
'exit': '退出',
|
|
18
|
+
'exit.aria': '退出多窗口,返回对话',
|
|
19
|
+
'link': '手机访问',
|
|
20
|
+
'link.aria': '获取手机访问链接',
|
|
21
|
+
'link.fetching': '正在获取链接…',
|
|
22
|
+
'link.none': '未检测到局域网地址',
|
|
23
|
+
'link.copy': '复制链接',
|
|
24
|
+
'link.copied': '已复制',
|
|
25
|
+
'link.hint': '提示:{hint}',
|
|
26
|
+
'link.reachable': '手机在同一网络时可用:{urls}',
|
|
27
|
+
'link.unreachable': '当前实例仅绑定本机,手机无法访问。{hint}',
|
|
28
|
+
'link.token': '口令:{token}',
|
|
29
|
+
'columns': '列数',
|
|
30
|
+
'columns.auto': '自动',
|
|
31
|
+
'refresh': '全部刷新',
|
|
32
|
+
'openTab': '新标签页打开',
|
|
33
|
+
'reload': '重新加载',
|
|
34
|
+
'remove': '从视图移除',
|
|
35
|
+
'stop': '关闭实例',
|
|
36
|
+
'stop.confirm': '确定关闭?',
|
|
37
|
+
'stop.self': '即将关闭当前实例(本页面将断开)',
|
|
38
|
+
'stop.done': '已关闭 :{port}',
|
|
39
|
+
'stop.failed': '关闭 :{port} 失败:{error}',
|
|
40
|
+
'zoom': '放大',
|
|
41
|
+
'loading': '加载中',
|
|
42
|
+
'empty': '没有检测到 DSH 实例',
|
|
43
|
+
'empty.hint': '先启动若干 dsh web --port <n> 实例,再点击「发现实例」或手动添加端口。',
|
|
44
|
+
'status.scanning': '扫描 {from}–{to} …',
|
|
45
|
+
'status.found': '发现 {count} 个实例:{ports}',
|
|
46
|
+
'status.none': '区间 {from}–{to} 未发现 DSH 实例',
|
|
47
|
+
'status.refreshed': '已刷新全部窗口',
|
|
48
|
+
};
|
|
49
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
50
|
+
export const en = {
|
|
51
|
+
'toggle': 'Multi-Window',
|
|
52
|
+
'toggle.aria': 'Toggle multi-window',
|
|
53
|
+
'view.multiWall': 'Multi-Window',
|
|
54
|
+
'overlay.title': 'Multi-Window',
|
|
55
|
+
'overlay.close': 'Close',
|
|
56
|
+
'scan': 'Discover',
|
|
57
|
+
'scan.from': 'Start port',
|
|
58
|
+
'scan.to': 'End port',
|
|
59
|
+
'create': 'New window',
|
|
60
|
+
'create.pending': 'Starting…',
|
|
61
|
+
'create.done': 'Created window :{port}',
|
|
62
|
+
'create.failed': 'Create failed: {error}',
|
|
63
|
+
'create.unknown': 'unknown reason',
|
|
64
|
+
'exit': 'Exit',
|
|
65
|
+
'exit.aria': 'Exit multi-window and return to chat',
|
|
66
|
+
'link': 'Phone access',
|
|
67
|
+
'link.aria': 'Get phone access link',
|
|
68
|
+
'link.fetching': 'Fetching link…',
|
|
69
|
+
'link.none': 'No LAN address detected',
|
|
70
|
+
'link.copy': 'Copy link',
|
|
71
|
+
'link.copied': 'Copied',
|
|
72
|
+
'link.hint': 'Hint: {hint}',
|
|
73
|
+
'link.reachable': 'Reachable on the same network: {urls}',
|
|
74
|
+
'link.unreachable': 'This instance binds loopback only; phones cannot reach it. {hint}',
|
|
75
|
+
'link.token': 'Token: {token}',
|
|
76
|
+
'columns': 'Columns',
|
|
77
|
+
'columns.auto': 'Auto',
|
|
78
|
+
'refresh': 'Refresh all',
|
|
79
|
+
'openTab': 'Open in new tab',
|
|
80
|
+
'reload': 'Reload',
|
|
81
|
+
'remove': 'Remove from view',
|
|
82
|
+
'stop': 'Stop instance',
|
|
83
|
+
'stop.confirm': 'Confirm stop?',
|
|
84
|
+
'stop.self': 'Stopping the current instance (this page will disconnect)',
|
|
85
|
+
'stop.done': 'Stopped :{port}',
|
|
86
|
+
'stop.failed': 'Failed to stop :{port}: {error}',
|
|
87
|
+
'zoom': 'Zoom',
|
|
88
|
+
'loading': 'Loading',
|
|
89
|
+
'empty': 'No DSH instances found',
|
|
90
|
+
'empty.hint': 'Start a few `dsh web --port <n>` instances first, then click "Discover" or add a port manually.',
|
|
91
|
+
'status.scanning': 'Scanning {from}–{to} …',
|
|
92
|
+
'status.found': 'Found {count} instance(s): {ports}',
|
|
93
|
+
'status.none': 'No DSH instances in {from}–{to}',
|
|
94
|
+
'status.refreshed': 'Refreshed all windows',
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=locales.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locales.js","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/client/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAE5F,4DAA4D;AAC5D,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,2CAA2C;AAC3C,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACrD,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACjD,UAAU,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACpD,UAAU,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACxD,CAAA;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,iBAAiB,CAAC,SAAS,EAAE,WAAW,CAAC,CAW3E"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wall store: which instances are shown and the grid columns. The ports list
|
|
3
|
+
* is the wall's whole business state — discovery writes it, removal filters
|
|
4
|
+
* it, and the grid renders from it. Open/closed is NOT stored here: the wall
|
|
5
|
+
* is a `conversation.view` ring entry, so the active view (chat store's
|
|
6
|
+
* `view` field) decides whether it renders.
|
|
7
|
+
*/
|
|
8
|
+
import { defineStore } from '@deepseek-ai/dsh-client-runtime/client';
|
|
9
|
+
/**
|
|
10
|
+
* Create the wall store handle. Persisted under `dsh.multi-wall` so the port
|
|
11
|
+
* set and column choice survive view switches and reloads.
|
|
12
|
+
* @returns the store handle (spec + type + identity + factory in one).
|
|
13
|
+
*/
|
|
14
|
+
export function createWallStore() {
|
|
15
|
+
return defineStore({
|
|
16
|
+
init: () => ({ ports: [], columns: 'auto' }),
|
|
17
|
+
persist: 'dsh.multi-wall',
|
|
18
|
+
actions: {
|
|
19
|
+
setPorts: (d, ports) => { d.ports = ports; },
|
|
20
|
+
addPort: (d, port) => { if (!d.ports.includes(port))
|
|
21
|
+
d.ports = [...d.ports, port]; },
|
|
22
|
+
removePort: (d, port) => { d.ports = d.ports.filter(p => p !== port); },
|
|
23
|
+
setColumns: (d, columns) => { d.columns = columns; },
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/client/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,WAAW,EAA0B,MAAM,wCAAwC,CAAA;AAgB5F;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,WAAW,CAAC;QACjB,IAAI,EAAE,GAAc,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACvD,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE;YACP,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAe,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,KAAK,CAAA,CAAC,CAAC;YACrD,OAAO,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA,CAAC,CAAC;YAC3F,UAAU,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA,CAAC,CAAC;YAC9E,UAAU,EAAE,CAAC,CAAC,EAAE,OAAe,EAAE,EAAE,GAAG,CAAC,CAAC,OAAO,GAAG,OAAO,CAAA,CAAC,CAAC;SAC5D;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wall-injected.d.ts","sourceRoot":"","sources":["../../../src/client/wall-injected.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,gDAAgD;AAChD,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,OAAO,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,oDAAoD;AACpD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,OAAO,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,0DAA0D;AAC1D,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,oEAAoE;IACpE,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAA;IAClB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACjC,wEAAwE;IACxE,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC/C,4EAA4E;IAC5E,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC,oFAAoF;IACpF,MAAM,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAA;IAChC,gFAAgF;IAChF,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,SAAK,GAAG,YAAY,CA6D3D"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injected probe face for the wall view: same-origin fetches to the node
|
|
3
|
+
* half's /multi/api routes. Callbacks only — components never see ctx.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Build the probe face bound to this origin's /multi/api routes.
|
|
7
|
+
* @param mount - the API base path ('' at the root, '/multi' when mounted).
|
|
8
|
+
* @returns the injected callbacks.
|
|
9
|
+
*/
|
|
10
|
+
export function createWallInjected(mount = '') {
|
|
11
|
+
const base = mount.replace(/\/+$/, '');
|
|
12
|
+
return {
|
|
13
|
+
discover: async () => {
|
|
14
|
+
const res = await fetch(`${base}/multi/api/ports`);
|
|
15
|
+
if (!res.ok)
|
|
16
|
+
return [];
|
|
17
|
+
const data = (await res.json());
|
|
18
|
+
return (data.ports ?? []).filter(p => p.alive).map(p => p.port);
|
|
19
|
+
},
|
|
20
|
+
probe: async (ports) => {
|
|
21
|
+
const res = await fetch(`${base}/multi/api/status?ports=${ports.join(',')}`);
|
|
22
|
+
if (!res.ok)
|
|
23
|
+
return [];
|
|
24
|
+
const data = (await res.json());
|
|
25
|
+
return data.ports ?? [];
|
|
26
|
+
},
|
|
27
|
+
stop: async (port) => {
|
|
28
|
+
const res = await fetch(`${base}/multi/api/stop?port=${port}`, { method: 'POST' });
|
|
29
|
+
if (!res.ok)
|
|
30
|
+
return { port, ok: false, error: `HTTP ${res.status}` };
|
|
31
|
+
const data = (await res.json());
|
|
32
|
+
return data.ports?.[0] ?? { port, ok: false, error: 'no result' };
|
|
33
|
+
},
|
|
34
|
+
create: async () => {
|
|
35
|
+
// Harden the failure surface: a non-2xx answer, an HTML fallback page
|
|
36
|
+
// (route missing) or a truncated body must never degrade into the bare
|
|
37
|
+
// "unknown" the UI shows for a missing error field.
|
|
38
|
+
const res = await fetch(`${base}/multi/api/create`, { method: 'POST' });
|
|
39
|
+
if (!res.ok) {
|
|
40
|
+
return { ok: false, error: `HTTP ${res.status}` };
|
|
41
|
+
}
|
|
42
|
+
const text = await res.text();
|
|
43
|
+
let data;
|
|
44
|
+
try {
|
|
45
|
+
data = JSON.parse(text);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
const snippet = text.trim().slice(0, 120);
|
|
49
|
+
return { ok: false, error: `invalid response: ${snippet === '' ? '<empty body>' : snippet}` };
|
|
50
|
+
}
|
|
51
|
+
if (data.ok === true) {
|
|
52
|
+
return data.port !== undefined
|
|
53
|
+
? { ok: true, port: data.port }
|
|
54
|
+
: { ok: false, error: 'no port in response' };
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
ok: false,
|
|
58
|
+
...(typeof data.error === 'string' ? { error: data.error } : { error: 'server returned no reason' }),
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
link: async () => {
|
|
62
|
+
const res = await fetch(`${base}/multi/api/link`);
|
|
63
|
+
const data = (await res.json().catch(() => ({})));
|
|
64
|
+
return {
|
|
65
|
+
port: data.port ?? 0,
|
|
66
|
+
host: data.host ?? 'unknown',
|
|
67
|
+
lan: data.lan ?? [],
|
|
68
|
+
reachable: data.reachable === true,
|
|
69
|
+
...(typeof data.gatewayPort === 'number' ? { gatewayPort: data.gatewayPort } : {}),
|
|
70
|
+
...(typeof data.token === 'string' ? { token: data.token } : {}),
|
|
71
|
+
...(typeof data.hint === 'string' ? { hint: data.hint } : {}),
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=wall-injected.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wall-injected.js","sourceRoot":"","sources":["../../../src/client/wall-injected.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline authenticated gateway for the multi-wall plugin's node half.
|
|
3
|
+
*
|
|
4
|
+
* The official `dsh web` CLI forbids `--host 0.0.0.0` (it would expose remote
|
|
5
|
+
* code execution to the network), so reaching a loopback-only DSH instance
|
|
6
|
+
* from a phone/another machine needs an auth-gated gateway in front of it.
|
|
7
|
+
*
|
|
8
|
+
* This module embeds that gateway directly in the plugin (no external
|
|
9
|
+
* `gateway.mjs` file needed at runtime): a raw TCP listener that authenticates
|
|
10
|
+
* a token (HMAC-signed session cookie), then transparently proxies to
|
|
11
|
+
* `127.0.0.1:<target-port>`, rewriting Host/Origin so the official `/api`
|
|
12
|
+
* browser-trust fence treats it as a local request. WebSocket upgrades pass
|
|
13
|
+
* through untouched because the socket is piped byte-for-byte after the head.
|
|
14
|
+
* The HTML document response is buffered once so a `crypto.randomUUID`
|
|
15
|
+
* polyfill can be injected for phones (insecure-origin HTTP); all other
|
|
16
|
+
* responses stream through unchanged.
|
|
17
|
+
*
|
|
18
|
+
* Zero dependencies: node:net + node:crypto only.
|
|
19
|
+
* @module @deepseek-ai/dsh-client-ui-multi-wall/gateway
|
|
20
|
+
*/
|
|
21
|
+
/** Options for {@link startGateway}. */
|
|
22
|
+
export interface GatewayOptions {
|
|
23
|
+
/** Loopback target port (the DSH instance to proxy by default). */
|
|
24
|
+
targetPort: number;
|
|
25
|
+
/** Listen port; pass 0 to let the OS pick one. */
|
|
26
|
+
port: number;
|
|
27
|
+
/** Login token (secret). */
|
|
28
|
+
token: string;
|
|
29
|
+
/** Instance label shown on the login page. */
|
|
30
|
+
name: string;
|
|
31
|
+
/** Session cookie lifetime in hours. */
|
|
32
|
+
maxAgeHours?: number;
|
|
33
|
+
/**
|
|
34
|
+
* When set, the gateway routes `/gw/<port>/<path>` to `127.0.0.1:<port>`
|
|
35
|
+
* for any port in this list (the wall's phone panes). Other ports are
|
|
36
|
+
* rejected, so the phone cannot reach arbitrary loopback services.
|
|
37
|
+
*/
|
|
38
|
+
routedPorts?: number[];
|
|
39
|
+
/** Log lines (startup, login events). */
|
|
40
|
+
log?: (message: string) => void;
|
|
41
|
+
}
|
|
42
|
+
/** Handle returned by {@link startGateway}. */
|
|
43
|
+
export interface GatewayHandle {
|
|
44
|
+
/** The OS-assigned listen port (equals `port` unless it was 0). */
|
|
45
|
+
port: number;
|
|
46
|
+
/** The login token. */
|
|
47
|
+
token: string;
|
|
48
|
+
/** Close the gateway listener. */
|
|
49
|
+
close: () => void;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Start an in-process authenticated gateway for one loopback DSH instance.
|
|
53
|
+
* @param options - target, listen port, token, label, and lifetime.
|
|
54
|
+
* @returns a handle with the assigned port and token, and a close().
|
|
55
|
+
*/
|
|
56
|
+
export declare function startGateway(options: GatewayOptions): Promise<GatewayHandle>;
|
|
57
|
+
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/gateway.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAiBH,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAA;IAClB,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAA;IACZ,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,yCAAyC;IACzC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAED,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,kCAAkC;IAClC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAgMD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA2W5E"}
|