@linxin666/dsh-remote-web-ui 0.3.6 → 0.3.9
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.i18n.yaml +2 -2
- package/README.md +77 -468
- package/README.zh.md +83 -113
- package/lib/client.js +955 -203
- package/lib/client.js.map +1 -1
- package/lib/index.js +1136 -1466
- package/lib/types/client/FooterRemoteEntry.d.ts +6 -7
- package/lib/types/client/FooterRemoteEntry.d.ts.map +1 -1
- package/lib/types/client/FooterRemoteEntry.js +1 -1
- package/lib/types/client/RemoteEntry.d.ts +7 -4
- package/lib/types/client/RemoteEntry.d.ts.map +1 -1
- package/lib/types/client/RemoteEntry.js +7 -10
- package/lib/types/client/RemotePanel.d.ts +2 -2
- package/lib/types/client/RemotePanel.d.ts.map +1 -1
- package/lib/types/client/RemotePanel.js +2 -2
- package/lib/types/client/RemoteSettingsCard.d.ts +9 -5
- package/lib/types/client/RemoteSettingsCard.d.ts.map +1 -1
- package/lib/types/client/RemoteSettingsCard.js +56 -3
- package/lib/types/client/deep-link.d.ts +10 -13
- package/lib/types/client/deep-link.d.ts.map +1 -1
- package/lib/types/client/deep-link.js +14 -74
- package/lib/types/client/index.d.ts +2 -6
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +73 -39
- package/lib/types/client/locales.d.ts +26 -12
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +36 -22
- package/lib/types/client/mobile-adapt.d.ts +40 -0
- package/lib/types/client/mobile-adapt.d.ts.map +1 -0
- package/lib/types/client/mobile-adapt.js +967 -0
- package/lib/types/client/pair-api.d.ts +24 -6
- package/lib/types/client/pair-api.d.ts.map +1 -1
- package/lib/types/client/pair-api.js +9 -14
- package/lib/types/client/remote-channel.d.ts +3 -0
- package/lib/types/client/remote-channel.d.ts.map +1 -1
- package/lib/types/client/remote-channel.js +35 -3
- package/lib/types/client/settings-form.d.ts +35 -43
- package/lib/types/client/settings-form.d.ts.map +1 -1
- package/lib/types/client/settings-form.js +60 -53
- package/lib/types/firewall.d.ts +75 -0
- package/lib/types/firewall.d.ts.map +1 -0
- package/lib/types/firewall.js +184 -0
- package/lib/types/gate.d.ts +11 -5
- package/lib/types/gate.d.ts.map +1 -1
- package/lib/types/gate.js +11 -5
- package/lib/types/index.d.ts +39 -10
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +206 -58
- package/lib/types/inner-auth.d.ts +32 -0
- package/lib/types/inner-auth.d.ts.map +1 -0
- package/lib/types/inner-auth.js +72 -0
- package/lib/types/lan-bind-plan.d.ts +55 -0
- package/lib/types/lan-bind-plan.d.ts.map +1 -0
- package/lib/types/lan-bind-plan.js +60 -0
- package/lib/types/lan-bind.d.ts +69 -0
- package/lib/types/lan-bind.d.ts.map +1 -0
- package/lib/types/lan-bind.js +128 -0
- package/lib/types/loopback-proxy.d.ts +9 -2
- package/lib/types/loopback-proxy.d.ts.map +1 -1
- package/lib/types/loopback-proxy.js +24 -2
- package/lib/types/pairing.d.ts +15 -3
- package/lib/types/pairing.d.ts.map +1 -1
- package/lib/types/pairing.js +20 -6
- package/lib/types/remote-api.d.ts +30 -13
- package/lib/types/remote-api.d.ts.map +1 -1
- package/lib/types/remote-api.js +55 -42
- package/lib/types/remote-channel-boot.d.ts +21 -2
- package/lib/types/remote-channel-boot.d.ts.map +1 -1
- package/lib/types/remote-channel-boot.js +65 -3
- package/lib/types/remote-channel-rules.d.ts +8 -0
- package/lib/types/remote-channel-rules.d.ts.map +1 -1
- package/lib/types/remote-channel-rules.js +9 -2
- package/lib/types/remote-methods.d.ts +45 -11
- package/lib/types/remote-methods.d.ts.map +1 -1
- package/lib/types/remote-methods.js +56 -27
- package/lib/types/remote-presence-pet.d.ts +51 -0
- package/lib/types/remote-presence-pet.d.ts.map +1 -0
- package/lib/types/remote-presence-pet.js +101 -0
- package/lib/types/routes.d.ts +76 -4
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +336 -19
- package/lib/types/tunnel.d.ts.map +1 -1
- package/lib/types/tunnel.js +7 -1
- package/package.json +20 -18
- package/src/client/FooterRemoteEntry.tsx +9 -10
- package/src/client/RemoteEntry.tsx +13 -14
- package/src/client/RemotePanel.tsx +5 -16
- package/src/client/RemoteSettingsCard.tsx +72 -13
- package/src/client/deep-link.ts +14 -75
- package/src/client/index.ts +77 -39
- package/src/client/locales.ts +36 -22
- package/src/client/mobile-adapt.ts +913 -0
- package/src/client/pair-api.ts +26 -15
- package/src/client/remote-channel.ts +31 -3
- package/src/client/settings-form.ts +78 -92
- package/src/dsh-home.ts +1 -1
- package/src/firewall.ts +230 -0
- package/src/gate.ts +11 -5
- package/src/index.ts +235 -65
- package/src/inner-auth.ts +85 -0
- package/src/lan-bind-plan.ts +81 -0
- package/src/lan-bind.ts +145 -0
- package/src/loopback-proxy.ts +34 -0
- package/src/pairing.persist.test.ts +1 -1
- package/src/pairing.ts +20 -6
- package/src/remote-api.ts +67 -45
- package/src/remote-channel-boot.ts +70 -3
- package/src/remote-channel-rules.ts +17 -2
- package/src/remote-methods.ts +58 -27
- package/src/remote-presence-pet.ts +129 -0
- package/src/routes.ts +358 -19
- package/src/tunnel.ts +7 -1
- package/assets/apple-touch-icon.png +0 -0
- package/assets/mobile-icon-192.png +0 -0
- package/assets/mobile-icon-512.png +0 -0
- package/assets/mobile-service-worker.js +0 -63
- package/lib/mobile.js +0 -17658
- package/lib/mobile.js.map +0 -1
- package/lib/types/mobile/PairRequiredView.d.ts +0 -7
- package/lib/types/mobile/PairRequiredView.d.ts.map +0 -1
- package/lib/types/mobile/PairRequiredView.js +0 -28
- package/lib/types/mobile/PairRequiredView.test.d.ts +0 -2
- package/lib/types/mobile/PairRequiredView.test.d.ts.map +0 -1
- package/lib/types/mobile/PairRequiredView.test.js +0 -24
- package/lib/types/mobile/api.d.ts +0 -145
- package/lib/types/mobile/api.d.ts.map +0 -1
- package/lib/types/mobile/api.js +0 -103
- package/lib/types/mobile/index.d.ts +0 -10
- package/lib/types/mobile/index.d.ts.map +0 -1
- package/lib/types/mobile/index.js +0 -38
- package/lib/types/mobile/markdown.d.ts +0 -34
- package/lib/types/mobile/markdown.d.ts.map +0 -1
- package/lib/types/mobile/markdown.js +0 -285
- package/lib/types/mobile/markdown.test.d.ts +0 -2
- package/lib/types/mobile/markdown.test.d.ts.map +0 -1
- package/lib/types/mobile/markdown.test.js +0 -79
- package/lib/types/mobile/messages.d.ts +0 -149
- package/lib/types/mobile/messages.d.ts.map +0 -1
- package/lib/types/mobile/messages.js +0 -561
- package/lib/types/mobile/messages.test.d.ts +0 -2
- package/lib/types/mobile/messages.test.d.ts.map +0 -1
- package/lib/types/mobile/messages.test.js +0 -356
- package/lib/types/mobile/mobile-styles.d.ts +0 -6
- package/lib/types/mobile/mobile-styles.d.ts.map +0 -1
- package/lib/types/mobile/mobile-styles.js +0 -1438
- package/lib/types/mobile/mobile-theme.d.ts +0 -22
- package/lib/types/mobile/mobile-theme.d.ts.map +0 -1
- package/lib/types/mobile/mobile-theme.js +0 -70
- package/lib/types/mobile/mobile-theme.test.d.ts +0 -2
- package/lib/types/mobile/mobile-theme.test.d.ts.map +0 -1
- package/lib/types/mobile/mobile-theme.test.js +0 -71
- package/lib/types/mobile/mux.d.ts +0 -128
- package/lib/types/mobile/mux.d.ts.map +0 -1
- package/lib/types/mobile/mux.js +0 -305
- package/lib/types/mobile/mux.test.d.ts +0 -2
- package/lib/types/mobile/mux.test.d.ts.map +0 -1
- package/lib/types/mobile/mux.test.js +0 -267
- package/lib/types/mobile/pairing.d.ts +0 -31
- package/lib/types/mobile/pairing.d.ts.map +0 -1
- package/lib/types/mobile/pairing.js +0 -62
- package/lib/types/mobile/rpc.d.ts +0 -38
- package/lib/types/mobile/rpc.d.ts.map +0 -1
- package/lib/types/mobile/rpc.js +0 -83
- package/lib/types/mobile/theme-toggle.d.ts +0 -12
- package/lib/types/mobile/theme-toggle.d.ts.map +0 -1
- package/lib/types/mobile/theme-toggle.js +0 -26
- package/lib/types/mobile/views/App.d.ts +0 -57
- package/lib/types/mobile/views/App.d.ts.map +0 -1
- package/lib/types/mobile/views/App.js +0 -150
- package/lib/types/mobile/views/App.test.d.ts +0 -2
- package/lib/types/mobile/views/App.test.d.ts.map +0 -1
- package/lib/types/mobile/views/App.test.js +0 -52
- package/lib/types/mobile/views/ChatView.d.ts +0 -63
- package/lib/types/mobile/views/ChatView.d.ts.map +0 -1
- package/lib/types/mobile/views/ChatView.js +0 -821
- package/lib/types/mobile/views/ChatView.stream.test.d.ts +0 -2
- package/lib/types/mobile/views/ChatView.stream.test.d.ts.map +0 -1
- package/lib/types/mobile/views/ChatView.stream.test.js +0 -236
- package/lib/types/mobile/views/ChatView.test.d.ts +0 -2
- package/lib/types/mobile/views/ChatView.test.d.ts.map +0 -1
- package/lib/types/mobile/views/ChatView.test.js +0 -718
- package/lib/types/mobile/views/SessionListView.d.ts +0 -27
- package/lib/types/mobile/views/SessionListView.d.ts.map +0 -1
- package/lib/types/mobile/views/SessionListView.js +0 -139
- package/lib/types/mobile/views/SessionListView.test.d.ts +0 -2
- package/lib/types/mobile/views/SessionListView.test.d.ts.map +0 -1
- package/lib/types/mobile/views/SessionListView.test.js +0 -167
- package/lib/types/mobile/views/WorkspaceView.d.ts +0 -21
- package/lib/types/mobile/views/WorkspaceView.d.ts.map +0 -1
- package/lib/types/mobile/views/WorkspaceView.js +0 -93
- package/lib/types/mobile/views/WorkspaceView.test.d.ts +0 -2
- package/lib/types/mobile/views/WorkspaceView.test.d.ts.map +0 -1
- package/lib/types/mobile/views/WorkspaceView.test.js +0 -183
- package/lib/types/mobile-api.d.ts +0 -65
- package/lib/types/mobile-api.d.ts.map +0 -1
- package/lib/types/mobile-api.js +0 -404
- package/lib/types/mobile-pending.d.ts +0 -38
- package/lib/types/mobile-pending.d.ts.map +0 -1
- package/lib/types/mobile-pending.js +0 -59
- package/lib/types/mobile-pwa.d.ts +0 -6
- package/lib/types/mobile-pwa.d.ts.map +0 -1
- package/lib/types/mobile-pwa.js +0 -17
- package/lib/types/mobile-routes.d.ts +0 -13
- package/lib/types/mobile-routes.d.ts.map +0 -1
- package/lib/types/mobile-routes.js +0 -217
- package/lib/types/paired-model-catalog.d.ts +0 -17
- package/lib/types/paired-model-catalog.d.ts.map +0 -1
- package/lib/types/paired-model-catalog.js +0 -311
- package/src/mobile/PairRequiredView.test.tsx +0 -28
- package/src/mobile/PairRequiredView.tsx +0 -58
- package/src/mobile/api.ts +0 -229
- package/src/mobile/index.tsx +0 -41
- package/src/mobile/markdown.test.ts +0 -91
- package/src/mobile/markdown.ts +0 -291
- package/src/mobile/messages.test.ts +0 -402
- package/src/mobile/messages.ts +0 -685
- package/src/mobile/mobile-styles.ts +0 -1439
- package/src/mobile/mobile-theme.test.ts +0 -84
- package/src/mobile/mobile-theme.ts +0 -76
- package/src/mobile/mux.test.ts +0 -314
- package/src/mobile/mux.ts +0 -336
- package/src/mobile/pairing.ts +0 -77
- package/src/mobile/rpc.ts +0 -90
- package/src/mobile/theme-toggle.tsx +0 -47
- package/src/mobile/views/App.test.tsx +0 -62
- package/src/mobile/views/App.tsx +0 -213
- package/src/mobile/views/ChatView.stream.test.tsx +0 -268
- package/src/mobile/views/ChatView.test.tsx +0 -816
- package/src/mobile/views/ChatView.tsx +0 -1342
- package/src/mobile/views/SessionListView.test.tsx +0 -207
- package/src/mobile/views/SessionListView.tsx +0 -244
- package/src/mobile/views/WorkspaceView.test.tsx +0 -227
- package/src/mobile/views/WorkspaceView.tsx +0 -245
- package/src/mobile-api.ts +0 -418
- package/src/mobile-pending.ts +0 -88
- package/src/mobile-pwa.ts +0 -19
- package/src/mobile-routes.ts +0 -231
- package/src/paired-model-catalog.ts +0 -272
|
@@ -82,7 +82,6 @@ export interface DeviceFrame {
|
|
|
82
82
|
/**
|
|
83
83
|
* Mint a fresh pairing token (one active token at a time — this invalidates
|
|
84
84
|
* any previous link).
|
|
85
|
-
* @param workspaceId - optional current workspace to deep-link the phone into.
|
|
86
85
|
* @param address - optional LAN IP literal the QR must be built from (the
|
|
87
86
|
* default is the first interface); unknown literals refuse with
|
|
88
87
|
* 'unknown-address'.
|
|
@@ -90,7 +89,7 @@ export interface DeviceFrame {
|
|
|
90
89
|
* 0.0.0.0), or the forbidden refusal (the loopback-only fence rejected this
|
|
91
90
|
* origin — the panel is a desktop control endpoint).
|
|
92
91
|
*/
|
|
93
|
-
export declare function issuePair(
|
|
92
|
+
export declare function issuePair(address?: string): Promise<IssueResponse>;
|
|
94
93
|
/**
|
|
95
94
|
* Accept a pairing token (the phone's first open of the QR link). Success
|
|
96
95
|
* sets the device cookie; the page then reloads to boot with it.
|
|
@@ -109,10 +108,9 @@ export declare function stopPair(): Promise<void>;
|
|
|
109
108
|
export declare function revokePair(deviceId: string): Promise<void>;
|
|
110
109
|
/** Presence heartbeat from a paired phone (unpaired heartbeats 401 harmlessly). */
|
|
111
110
|
export declare function sendHeartbeat(): Promise<void>;
|
|
112
|
-
/** Whether the current page URL carries a pairing token
|
|
111
|
+
/** Whether the current page URL carries a pairing token. */
|
|
113
112
|
export declare function readPairParams(search: string): {
|
|
114
113
|
pair?: string;
|
|
115
|
-
workspace?: string;
|
|
116
114
|
};
|
|
117
115
|
/**
|
|
118
116
|
* Strip one query parameter from the current URL without reloading.
|
|
@@ -120,8 +118,28 @@ export declare function readPairParams(search: string): {
|
|
|
120
118
|
* @returns the new search string ('' when empty).
|
|
121
119
|
*/
|
|
122
120
|
export declare function stripParam(name: string): string;
|
|
123
|
-
/**
|
|
124
|
-
export
|
|
121
|
+
/** LAN-bind status frame from the loopback-only card endpoint. */
|
|
122
|
+
export interface LanBindFrame {
|
|
123
|
+
profile: string;
|
|
124
|
+
/** The config toggle: true/false once flipped, null while untouched. */
|
|
125
|
+
setting: boolean | null;
|
|
126
|
+
/** The bind default the managed patch block currently pins. */
|
|
127
|
+
blockHost: string | null;
|
|
128
|
+
/** The live bind of the running web server. */
|
|
129
|
+
bindHost: string;
|
|
130
|
+
port: number;
|
|
131
|
+
lanUrls: string[];
|
|
132
|
+
firewall: {
|
|
133
|
+
ok: boolean;
|
|
134
|
+
managed: boolean;
|
|
135
|
+
note?: string;
|
|
136
|
+
};
|
|
137
|
+
platform: string;
|
|
138
|
+
/** true when the running bind has not caught up with the toggle yet. */
|
|
139
|
+
pendingRestart?: boolean;
|
|
140
|
+
}
|
|
141
|
+
/** Read the LAN-bind facts (loopback-only endpoint). */
|
|
142
|
+
export declare function readLanBindStatus(): Promise<LanBindFrame>;
|
|
125
143
|
/** Human-readable expiry clock, e.g. "10:35". */
|
|
126
144
|
export declare function formatClock(epochMs: number): string;
|
|
127
145
|
/** Calendar + clock for last-seen timestamps, e.g. "2026-08-19 10:35". */
|
|
@@ -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,oEAAoE;AACpE,MAAM,WAAW,cAAc;IAC7B,oBAAoB,EAAE,OAAO,CAAA;CAC9B;AAED,0DAA0D;AAC1D,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC,CAQlE;AAED,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,oEAAoE;AACpE,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;CAC5C;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,gDAAgD;IAChD,OAAO,CAAC,EAAE,WAAW,EAAE,CAAA;IACvB,mEAAmE;IACnE,MAAM,CAAC,EAAE,iBAAiB,CAAA;IAC1B,mEAAmE;IACnE,OAAO,CAAC,EAAE,YAAY,CAAA;CACvB;AAED,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"pair-api.d.ts","sourceRoot":"","sources":["../../../src/client/pair-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,7 +17,6 @@ export async function readPairGatePolicy() {
|
|
|
17
17
|
/**
|
|
18
18
|
* Mint a fresh pairing token (one active token at a time — this invalidates
|
|
19
19
|
* any previous link).
|
|
20
|
-
* @param workspaceId - optional current workspace to deep-link the phone into.
|
|
21
20
|
* @param address - optional LAN IP literal the QR must be built from (the
|
|
22
21
|
* default is the first interface); unknown literals refuse with
|
|
23
22
|
* 'unknown-address'.
|
|
@@ -25,12 +24,11 @@ export async function readPairGatePolicy() {
|
|
|
25
24
|
* 0.0.0.0), or the forbidden refusal (the loopback-only fence rejected this
|
|
26
25
|
* origin — the panel is a desktop control endpoint).
|
|
27
26
|
*/
|
|
28
|
-
export async function issuePair(
|
|
27
|
+
export async function issuePair(address) {
|
|
29
28
|
const response = await fetch('/api/pair/issue', {
|
|
30
29
|
method: 'POST',
|
|
31
30
|
headers: { 'content-type': 'application/json' },
|
|
32
31
|
body: JSON.stringify({
|
|
33
|
-
...(workspaceId !== undefined ? { workspaceId } : {}),
|
|
34
32
|
...(address !== undefined ? { address } : {}),
|
|
35
33
|
}),
|
|
36
34
|
});
|
|
@@ -90,15 +88,11 @@ export async function revokePair(deviceId) {
|
|
|
90
88
|
export async function sendHeartbeat() {
|
|
91
89
|
await fetch('/api/pair/heartbeat', { method: 'POST' });
|
|
92
90
|
}
|
|
93
|
-
/** Whether the current page URL carries a pairing token
|
|
91
|
+
/** Whether the current page URL carries a pairing token. */
|
|
94
92
|
export function readPairParams(search) {
|
|
95
93
|
const params = new URLSearchParams(search);
|
|
96
94
|
const pair = params.get('pair');
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
...(pair !== null && pair !== '' ? { pair } : {}),
|
|
100
|
-
...(workspace !== null && workspace !== '' ? { workspace } : {}),
|
|
101
|
-
};
|
|
95
|
+
return pair !== null && pair !== '' ? { pair } : {};
|
|
102
96
|
}
|
|
103
97
|
/**
|
|
104
98
|
* Strip one query parameter from the current URL without reloading.
|
|
@@ -110,11 +104,12 @@ export function stripParam(name) {
|
|
|
110
104
|
url.searchParams.delete(name);
|
|
111
105
|
return url.search;
|
|
112
106
|
}
|
|
113
|
-
/**
|
|
114
|
-
export function
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
107
|
+
/** Read the LAN-bind facts (loopback-only endpoint). */
|
|
108
|
+
export async function readLanBindStatus() {
|
|
109
|
+
const response = await fetch('/api/pair/lan-bind');
|
|
110
|
+
if (!response.ok)
|
|
111
|
+
throw new Error(`remote-web-ui: lan-bind status failed with ${String(response.status)}`);
|
|
112
|
+
return await response.json();
|
|
118
113
|
}
|
|
119
114
|
/** Human-readable expiry clock, e.g. "10:35". */
|
|
120
115
|
export function formatClock(epochMs) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-channel.d.ts","sourceRoot":"","sources":["../../../src/client/remote-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EACL,iBAAiB,EAEjB,aAAa,EACd,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAA;AAC3C,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;AAIvE,qEAAqE;AACrE,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,CAAA;IACpD,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAC9D;AAED,qFAAqF;AACrF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,6BAA6B,EACvC,iBAAiB,EAAE,OAAO,GAAG,SAAS,GACrC,OAAO,CAQT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI5D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUhE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAcnF;AAED,wEAAwE;AACxE,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAA;IAC3B,WAAW,CAAC,EAAE,OAAO,WAAW,CAAA;IAChC,gBAAgB,CAAC,EAAE,cAAc,CAAA;IACjC,iBAAiB,CAAC,EAAE,cAAc,CAAA;IAClC,iBAAiB,CAAC,EAAE,cAAc,CAAA;IAClC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"remote-channel.d.ts","sourceRoot":"","sources":["../../../src/client/remote-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EACL,iBAAiB,EAEjB,aAAa,EACd,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAA;AAC3C,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;AAIvE,qEAAqE;AACrE,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,CAAA;IACpD,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAC9D;AAED,qFAAqF;AACrF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,6BAA6B,EACvC,iBAAiB,EAAE,OAAO,GAAG,SAAS,GACrC,OAAO,CAQT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI5D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUhE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAcnF;AAED,wEAAwE;AACxE,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAA;IAC3B,WAAW,CAAC,EAAE,OAAO,WAAW,CAAA;IAChC,gBAAgB,CAAC,EAAE,cAAc,CAAA;IACjC,iBAAiB,CAAC,EAAE,cAAc,CAAA;IAClC,iBAAiB,CAAC,EAAE,cAAc,CAAA;IAClC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,cAAc,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACzD;AAED,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAoBD;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E;AA0BD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,IAAI,CAmG1G;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE7D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,iBAAiB,CAIxF"}
|
|
@@ -178,6 +178,38 @@ export function installRemoteChannel(window, options = {}) {
|
|
|
178
178
|
const OriginalEventSource = window.EventSource;
|
|
179
179
|
const sameOrigin = (url) => url.origin === window.location.origin;
|
|
180
180
|
const rewrite = (raw) => rewriteRawUrl(raw, window.location.href, window.location.origin);
|
|
181
|
+
// The cookieless device credential (set by the /pair-app capture script):
|
|
182
|
+
// attaches as a header on gated fetches and as the device query on WS and
|
|
183
|
+
// EventSource handshakes, mirroring the boot patch exactly.
|
|
184
|
+
const device = (() => {
|
|
185
|
+
try {
|
|
186
|
+
return window.sessionStorage?.getItem(RULES.deviceKey) ?? null;
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
})();
|
|
192
|
+
const attach = (init) => {
|
|
193
|
+
if (device === null)
|
|
194
|
+
return init;
|
|
195
|
+
const headers = init?.headers;
|
|
196
|
+
if (typeof Headers !== 'undefined' && headers instanceof Headers) {
|
|
197
|
+
try {
|
|
198
|
+
headers.set(RULES.deviceHeader, device);
|
|
199
|
+
}
|
|
200
|
+
catch { /* ignore */ }
|
|
201
|
+
return init;
|
|
202
|
+
}
|
|
203
|
+
if (typeof headers === 'object' && headers !== null) {
|
|
204
|
+
return { ...init, headers: { ...headers, [RULES.deviceHeader]: device } };
|
|
205
|
+
}
|
|
206
|
+
return init;
|
|
207
|
+
};
|
|
208
|
+
const withDeviceQuery = (url) => {
|
|
209
|
+
if (device !== null)
|
|
210
|
+
url.searchParams.set(RULES.deviceQuery, device);
|
|
211
|
+
return url;
|
|
212
|
+
};
|
|
181
213
|
const patchedFetch = (input, init) => {
|
|
182
214
|
const url = new URL(typeof input === 'string' || input instanceof URL ? input.toString() : input.url, window.location.href);
|
|
183
215
|
if (sameOrigin(url) && shouldRewriteFetchPath(url.pathname)) {
|
|
@@ -186,7 +218,7 @@ export function installRemoteChannel(window, options = {}) {
|
|
|
186
218
|
const next = typeof input === 'string' || input instanceof URL
|
|
187
219
|
? rewritten.toString()
|
|
188
220
|
: new Request(rewritten, input);
|
|
189
|
-
return Promise.resolve(originalFetch.call(window, next, init)).then(async (response) => {
|
|
221
|
+
return Promise.resolve(originalFetch.call(window, next, attach(init))).then(async (response) => {
|
|
190
222
|
if (await isUnpairedDenied(response.clone()))
|
|
191
223
|
options.onUnpaired?.();
|
|
192
224
|
else
|
|
@@ -203,7 +235,7 @@ export function installRemoteChannel(window, options = {}) {
|
|
|
203
235
|
if (wsOrigin !== '' && wsOrigin === window.location.origin && shouldRewriteWsPath(parsed.pathname)) {
|
|
204
236
|
const rewritten = new URL(parsed);
|
|
205
237
|
rewritten.pathname = rewritePath(parsed.pathname);
|
|
206
|
-
super(rewritten, protocols);
|
|
238
|
+
super(withDeviceQuery(rewritten), protocols);
|
|
207
239
|
return;
|
|
208
240
|
}
|
|
209
241
|
super(url, protocols);
|
|
@@ -223,7 +255,7 @@ export function installRemoteChannel(window, options = {}) {
|
|
|
223
255
|
if (sameOrigin(parsed) && shouldRewriteFetchPath(parsed.pathname)) {
|
|
224
256
|
const rewritten = new URL(parsed);
|
|
225
257
|
rewritten.pathname = rewritePath(parsed.pathname);
|
|
226
|
-
super(rewritten, eventSourceInitDict);
|
|
258
|
+
super(withDeviceQuery(rewritten), eventSourceInitDict);
|
|
227
259
|
return;
|
|
228
260
|
}
|
|
229
261
|
super(url, eventSourceInitDict);
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* each plugin's client bundle; mirrors the official ui-plugin-config
|
|
7
7
|
* card-store pattern.
|
|
8
8
|
*/
|
|
9
|
-
import type { SettingsScope
|
|
9
|
+
import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
10
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
10
11
|
/** The write one field's staged text performs when the card is saved. */
|
|
11
12
|
export type FieldWrite = {
|
|
12
13
|
kind: 'set';
|
|
@@ -21,9 +22,11 @@ export interface FieldSpec {
|
|
|
21
22
|
/**
|
|
22
23
|
* Whether the Host treats this field as a secret and redacts its value from
|
|
23
24
|
* the read-back (role('secret') in the section schema). Redacted secrets are
|
|
24
|
-
* never compared against the draft on save
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* never compared against the draft on save: the Host strips them from every
|
|
26
|
+
* wire view layer, so the settled snapshot carries nothing to read back. A
|
|
27
|
+
* staged secret set is judged by the mutation settling; the rest of its
|
|
28
|
+
* batch, when one exists, is still judged by read-back, and the atomic
|
|
29
|
+
* mutation lands every write or none.
|
|
27
30
|
*/
|
|
28
31
|
secret?: boolean;
|
|
29
32
|
/** Render a stored value as draft text; the empty string when the section carries none. */
|
|
@@ -49,8 +52,8 @@ export interface CardShell {
|
|
|
49
52
|
available: boolean;
|
|
50
53
|
/**
|
|
51
54
|
* Whether the namespace is actually served to this client. False when the
|
|
52
|
-
* Host deployment does not expose it (e.g. the
|
|
53
|
-
*
|
|
55
|
+
* Host deployment does not expose it (e.g. the owning plugin's settings
|
|
56
|
+
* domain is not mounted): the card renders an explanation
|
|
54
57
|
* instead of its form, so a missing namespace never looks like a missing
|
|
55
58
|
* plugin.
|
|
56
59
|
*/
|
|
@@ -83,7 +86,7 @@ export interface CardActions {
|
|
|
83
86
|
/** Drop every staged edit. */
|
|
84
87
|
discard: () => void;
|
|
85
88
|
}
|
|
86
|
-
/** One durable write
|
|
89
|
+
/** One durable write inside the save's atomic scope mutation. */
|
|
87
90
|
export interface BatchedWrite {
|
|
88
91
|
/** Field this entry writes. */
|
|
89
92
|
field: string;
|
|
@@ -92,28 +95,6 @@ export interface BatchedWrite {
|
|
|
92
95
|
/** Value for op set (absent for unset). */
|
|
93
96
|
value?: unknown;
|
|
94
97
|
}
|
|
95
|
-
/** Per-field outcome of one batched scope write. */
|
|
96
|
-
export interface BatchedFieldResult {
|
|
97
|
-
/** Field this entry writes. */
|
|
98
|
-
field: string;
|
|
99
|
-
/** Whether the Host accepted this field's write (per the read-back view). */
|
|
100
|
-
landed: boolean;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Result of a batched scope write. The bridge scope posts every planned write
|
|
104
|
-
* in one /mutate so the Host validate hook judges baseURL+model together; a
|
|
105
|
-
* batched refusal fails the whole save rather than per-field.
|
|
106
|
-
*/
|
|
107
|
-
export interface BatchResult {
|
|
108
|
-
/** Whether the whole mutate was accepted. */
|
|
109
|
-
ok: boolean;
|
|
110
|
-
/** Per-field success, in the request order (always present when ok). */
|
|
111
|
-
fields: BatchedFieldResult[];
|
|
112
|
-
/** Host rejection code (mutate refused). */
|
|
113
|
-
code?: string;
|
|
114
|
-
/** Host rejection message (mutate refused). */
|
|
115
|
-
message?: string;
|
|
116
|
-
}
|
|
117
98
|
/** Constraints a numeric field's accepted drafts must satisfy, mirroring the host schema. */
|
|
118
99
|
export interface NumberConstraints {
|
|
119
100
|
/** The accepted value must be a whole number. */
|
|
@@ -128,8 +109,8 @@ export declare function textField(field: string): FieldSpec;
|
|
|
128
109
|
/**
|
|
129
110
|
* A free-text field the Host treats as a secret and redacts from the read-back
|
|
130
111
|
* (role('secret') in the section schema). The card still edits it like text,
|
|
131
|
-
* but a save never compares the redacted value back
|
|
132
|
-
*
|
|
112
|
+
* but a save never compares the redacted value back: the staged set is judged
|
|
113
|
+
* by the mutation settling (see {@link FieldSpec.secret}).
|
|
133
114
|
*/
|
|
134
115
|
export declare function secretField(field: string): FieldSpec;
|
|
135
116
|
/** A boolean field, edited through true/false draft text. */
|
|
@@ -171,19 +152,22 @@ export declare class CardForm<T> {
|
|
|
171
152
|
/** The actions the card's slot registration injects. */
|
|
172
153
|
actions(): CardActions;
|
|
173
154
|
/**
|
|
174
|
-
* Write every staged edit, then re-seed from
|
|
155
|
+
* Write every staged edit in one atomic scope mutation, then re-seed from
|
|
156
|
+
* what the Host accepted.
|
|
175
157
|
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
158
|
+
* The whole batch rides one mutate, so cross-field validate hooks
|
|
159
|
+
* (baseURL+model) judge it as a unit: the Host either applies every write
|
|
160
|
+
* or refuses the batch. The 0.1.2 scope contract never rejects a refused
|
|
161
|
+
* mutation — the scope recovers with a fresh Host view and resolves — so
|
|
162
|
+
* resolution alone proves nothing: the outcome is judged by reading the
|
|
163
|
+
* settled snapshot back, one planned write at a time, and one missed write
|
|
164
|
+
* fails the whole save. A scope that still rejects on refusal (the dsh-web
|
|
165
|
+
* bridge scope) reports through the same failure path with its rejection
|
|
166
|
+
* message. A save that did not land keeps its drafts, so the user can
|
|
167
|
+
* correct them instead of retyping.
|
|
168
|
+
* @returns settlement after the mutation and the read-back.
|
|
183
169
|
*/
|
|
184
170
|
save(): Promise<void>;
|
|
185
|
-
/** The scope's batch surface when it supports one; undefined conservatively otherwise. */
|
|
186
|
-
private batchedScope;
|
|
187
171
|
/**
|
|
188
172
|
* Every staged edit a save would write. An entry whose draft is not a value
|
|
189
173
|
* its field accepts carries no write: the form is still dirty, and the save
|
|
@@ -192,8 +176,16 @@ export declare class CardForm<T> {
|
|
|
192
176
|
* @returns the planned writes, in the order the fields were staged.
|
|
193
177
|
*/
|
|
194
178
|
private plan;
|
|
195
|
-
|
|
196
|
-
|
|
179
|
+
/**
|
|
180
|
+
* Read-back judgment for a planned set: the user layer must hold the
|
|
181
|
+
* intended value once the mutation has settled.
|
|
182
|
+
*/
|
|
183
|
+
private landedSet;
|
|
184
|
+
/**
|
|
185
|
+
* Read-back judgment for a planned unset: the field must be gone from the
|
|
186
|
+
* user layer once the mutation has settled.
|
|
187
|
+
*/
|
|
188
|
+
private landedUnset;
|
|
197
189
|
private stage;
|
|
198
190
|
private specOf;
|
|
199
191
|
private snapshotOf;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-form.d.ts","sourceRoot":"","sources":["../../../src/client/settings-form.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAyB,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"settings-form.d.ts","sourceRoot":"","sources":["../../../src/client/settings-form.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* each plugin's client bundle; mirrors the official ui-plugin-config
|
|
8
8
|
* card-store pattern.
|
|
9
9
|
*/
|
|
10
|
-
import { createSnapshotStore } from '@deepseek-ai/dsh-client-
|
|
10
|
+
import { createSnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
11
11
|
/** A whole- or decimal-number field. An empty draft clears the field; any other draft that is not a finite number within the constraints blocks the save. */
|
|
12
12
|
export function numberField(field, constraints = {}) {
|
|
13
13
|
const { integer = false, min } = constraints;
|
|
@@ -43,8 +43,8 @@ export function textField(field) {
|
|
|
43
43
|
/**
|
|
44
44
|
* A free-text field the Host treats as a secret and redacts from the read-back
|
|
45
45
|
* (role('secret') in the section schema). The card still edits it like text,
|
|
46
|
-
* but a save never compares the redacted value back
|
|
47
|
-
*
|
|
46
|
+
* but a save never compares the redacted value back: the staged set is judged
|
|
47
|
+
* by the mutation settling (see {@link FieldSpec.secret}).
|
|
48
48
|
*/
|
|
49
49
|
export function secretField(field) {
|
|
50
50
|
return { ...textField(field), secret: true };
|
|
@@ -129,7 +129,7 @@ export class CardForm {
|
|
|
129
129
|
exposed: snapshot.status === 'ready',
|
|
130
130
|
writable: snapshot.writable,
|
|
131
131
|
dirty: plan.length > 0,
|
|
132
|
-
invalid: plan.some(item => item.
|
|
132
|
+
invalid: plan.some(item => item.judge === undefined),
|
|
133
133
|
saving: this.saving,
|
|
134
134
|
failed: this.failed,
|
|
135
135
|
...this.failedReason === undefined ? {} : { failedReason: this.failedReason },
|
|
@@ -168,22 +168,26 @@ export class CardForm {
|
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
170
|
/**
|
|
171
|
-
* Write every staged edit, then re-seed from
|
|
171
|
+
* Write every staged edit in one atomic scope mutation, then re-seed from
|
|
172
|
+
* what the Host accepted.
|
|
172
173
|
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
174
|
+
* The whole batch rides one mutate, so cross-field validate hooks
|
|
175
|
+
* (baseURL+model) judge it as a unit: the Host either applies every write
|
|
176
|
+
* or refuses the batch. The 0.1.2 scope contract never rejects a refused
|
|
177
|
+
* mutation — the scope recovers with a fresh Host view and resolves — so
|
|
178
|
+
* resolution alone proves nothing: the outcome is judged by reading the
|
|
179
|
+
* settled snapshot back, one planned write at a time, and one missed write
|
|
180
|
+
* fails the whole save. A scope that still rejects on refusal (the dsh-web
|
|
181
|
+
* bridge scope) reports through the same failure path with its rejection
|
|
182
|
+
* message. A save that did not land keeps its drafts, so the user can
|
|
183
|
+
* correct them instead of retyping.
|
|
184
|
+
* @returns settlement after the mutation and the read-back.
|
|
180
185
|
*/
|
|
181
186
|
async save() {
|
|
182
187
|
const plan = this.plan();
|
|
183
|
-
const valid = plan.filter(item => item.
|
|
188
|
+
const valid = plan.filter((item) => item.judge !== undefined);
|
|
184
189
|
if (plan.length === 0 || this.saving || valid.length !== plan.length)
|
|
185
190
|
return;
|
|
186
|
-
const plannedWrites = valid.map(item => item.op);
|
|
187
191
|
// Snapshot the staged entries this save writes, so an edit staged while it
|
|
188
192
|
// is in flight (which replaces the same key) survives: only delete the key
|
|
189
193
|
// when the entry is still the one this save started from.
|
|
@@ -194,39 +198,35 @@ export class CardForm {
|
|
|
194
198
|
this.failed = false;
|
|
195
199
|
this.failedReason = undefined;
|
|
196
200
|
this.publish();
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
this.failedReason = result.message;
|
|
209
|
-
}
|
|
201
|
+
// One atomic namespace mutation: the 0.1.2 scope contract takes ordered
|
|
202
|
+
// path operations, so the whole staged batch is validated, persisted, and
|
|
203
|
+
// recovered together — either every write lands or none does.
|
|
204
|
+
const ops = valid.map(item => item.op.op === 'set'
|
|
205
|
+
? { op: 'set', path: [item.field], value: item.op.value }
|
|
206
|
+
: { op: 'unset', path: [item.field] });
|
|
207
|
+
let failedReason;
|
|
208
|
+
try {
|
|
209
|
+
await this.scope.mutate(ops);
|
|
210
210
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (await item.run())
|
|
214
|
-
landed.add(item.field);
|
|
215
|
-
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
failedReason = error instanceof Error ? error.message : String(error);
|
|
216
213
|
}
|
|
214
|
+
// The 0.1.2 scope resolves even a refused mutation (it recovers with a
|
|
215
|
+
// fresh view instead of throwing), so resolution alone proves nothing:
|
|
216
|
+
// judge every planned write against the settled snapshot. The mutation is
|
|
217
|
+
// atomic, so one missed write fails the whole save and keeps the drafts.
|
|
218
|
+
const landed = failedReason === undefined && valid.every(item => item.judge());
|
|
217
219
|
for (const [field, before] of pending) {
|
|
218
|
-
if (landed
|
|
220
|
+
if (landed && this.staged.get(field) === before)
|
|
219
221
|
this.staged.delete(field);
|
|
220
222
|
}
|
|
221
223
|
this.saving = false;
|
|
222
|
-
this.failed = landed
|
|
224
|
+
this.failed = !landed;
|
|
225
|
+
// A read-back failure carries no server reason: the card surfaces its
|
|
226
|
+
// generic failure copy; a rejecting scope (the bridge) adds its message.
|
|
227
|
+
this.failedReason = failedReason;
|
|
223
228
|
this.publish();
|
|
224
229
|
}
|
|
225
|
-
/** The scope's batch surface when it supports one; undefined conservatively otherwise. */
|
|
226
|
-
batchedScope() {
|
|
227
|
-
const candidate = this.scope;
|
|
228
|
-
return typeof candidate?.mutate === 'function' ? candidate : undefined;
|
|
229
|
-
}
|
|
230
230
|
/**
|
|
231
231
|
* Every staged edit a save would write. An entry whose draft is not a value
|
|
232
232
|
* its field accepts carries no write: the form is still dirty, and the save
|
|
@@ -240,35 +240,42 @@ export class CardForm {
|
|
|
240
240
|
const spec = this.specOf(field);
|
|
241
241
|
if (staged.clear) {
|
|
242
242
|
if (this.stored(field))
|
|
243
|
-
plan.push({ field, op: { field, op: 'unset' },
|
|
243
|
+
plan.push({ field, op: { field, op: 'unset' }, judge: () => this.landedUnset(field) });
|
|
244
244
|
continue;
|
|
245
245
|
}
|
|
246
246
|
if (staged.text === spec.format(this.sectionValue(field)))
|
|
247
247
|
continue;
|
|
248
248
|
const write = spec.parse(staged.text);
|
|
249
249
|
if (write === undefined)
|
|
250
|
-
plan.push({ field, op: { field, op: 'unset' },
|
|
250
|
+
plan.push({ field, op: { field, op: 'unset' }, judge: undefined });
|
|
251
251
|
else if (write.kind === 'clear')
|
|
252
|
-
plan.push({ field, op: { field, op: 'unset' },
|
|
252
|
+
plan.push({ field, op: { field, op: 'unset' }, judge: () => this.landedUnset(field) });
|
|
253
253
|
else
|
|
254
|
-
plan.push({ field, op: { field, op: 'set', value: write.value },
|
|
254
|
+
plan.push({ field, op: { field, op: 'set', value: write.value }, judge: () => this.landedSet(field, write.value) });
|
|
255
255
|
}
|
|
256
256
|
return plan;
|
|
257
257
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
//
|
|
258
|
+
/**
|
|
259
|
+
* Read-back judgment for a planned set: the user layer must hold the
|
|
260
|
+
* intended value once the mutation has settled.
|
|
261
|
+
*/
|
|
262
|
+
landedSet(field, value) {
|
|
263
|
+
// A redacted secret never appears in any wire view layer: the Host strips
|
|
264
|
+
// role('secret') fields and reports them through a sidecar the scope
|
|
265
|
+
// snapshot does not expose, so there is nothing to compare the draft
|
|
266
|
+
// against. Settling is the only signal the form has; the rest of the
|
|
267
|
+
// batch, when one exists, still carries the atomic verdict by read-back.
|
|
268
268
|
if (this.specOf(field).secret)
|
|
269
269
|
return true;
|
|
270
270
|
return this.userLayer()?.[field] === value;
|
|
271
271
|
}
|
|
272
|
+
/**
|
|
273
|
+
* Read-back judgment for a planned unset: the field must be gone from the
|
|
274
|
+
* user layer once the mutation has settled.
|
|
275
|
+
*/
|
|
276
|
+
landedUnset(field) {
|
|
277
|
+
return !this.stored(field);
|
|
278
|
+
}
|
|
272
279
|
stage(field, edit) {
|
|
273
280
|
this.staged.set(field, edit);
|
|
274
281
|
this.failed = false;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host firewall management for the LAN bind toggle: while LAN access is on,
|
|
3
|
+
* keep one inbound allow rule for the bound port; when it turns off, remove
|
|
4
|
+
* the rule. Windows manages the Windows Defender Firewall rule via netsh;
|
|
5
|
+
* Linux uses the first available manager among firewalld / ufw / iptables.
|
|
6
|
+
* On every other platform (macOS included) the plugin reports the firewall
|
|
7
|
+
* as unmanaged: the port usually needs no rule there, and managing pf or the
|
|
8
|
+
* application firewall is out of scope for a distributable plugin.
|
|
9
|
+
*
|
|
10
|
+
* Ported from the dsh-LAN reference implementation (MIT), adapted to this
|
|
11
|
+
* package's structure and test seams.
|
|
12
|
+
*/
|
|
13
|
+
/** Rule name shared by every backend so re-runs recreate the same rule. */
|
|
14
|
+
export declare const FIREWALL_RULE_NAME = "remote-web-ui (auto)";
|
|
15
|
+
/** One command execution result (test seam replaces the runner). */
|
|
16
|
+
export interface ToolResult {
|
|
17
|
+
ok: boolean;
|
|
18
|
+
out: string;
|
|
19
|
+
err: string;
|
|
20
|
+
/** true when the binary could not be spawned at all (ENOENT et al). */
|
|
21
|
+
missing?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** The command runner seam: spawnSync in production, a stub in tests. */
|
|
24
|
+
export type CommandRunner = (cmd: string, args: readonly string[]) => ToolResult;
|
|
25
|
+
/** Production runner: spawn without a shell, capture text, 20s timeout. */
|
|
26
|
+
export declare const spawnRunner: CommandRunner;
|
|
27
|
+
/** A firewall backend manages one allow rule for a TCP port. */
|
|
28
|
+
export interface FirewallBackend {
|
|
29
|
+
/** Short label surfaced in the settings card (netsh, firewalld, ...). */
|
|
30
|
+
readonly label: string;
|
|
31
|
+
ruleExists(port: number): boolean;
|
|
32
|
+
addRule(port: number): boolean;
|
|
33
|
+
removeRule(port: number): boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Detect the platform firewall manager. Returns undefined when the platform
|
|
37
|
+
* has no supported manager (macOS, unknown Linux without tools): the port
|
|
38
|
+
* then usually needs no rule and the UI reports "unmanaged".
|
|
39
|
+
*/
|
|
40
|
+
export declare function detectFirewallBackend(platform: NodeJS.Platform, run?: CommandRunner): FirewallBackend | undefined;
|
|
41
|
+
/** Cached detection for the running platform (per process). */
|
|
42
|
+
export declare function firewallBackend(): FirewallBackend | undefined;
|
|
43
|
+
/** Firewall state reported to the settings card. */
|
|
44
|
+
export interface FirewallSummary {
|
|
45
|
+
/** true when the rule state matches the LAN toggle (or nothing to manage). */
|
|
46
|
+
ok: boolean;
|
|
47
|
+
/** false when no supported firewall manager exists on this platform. */
|
|
48
|
+
managed: boolean;
|
|
49
|
+
/** Backend label or an explanation for unmanaged platforms. */
|
|
50
|
+
note?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Delete-and-add: recreating the rule is idempotent and locale-proof (netsh
|
|
54
|
+
* output is localized, so parsing the live rule's port is fragile; the Linux
|
|
55
|
+
* backends follow the same recreate pattern).
|
|
56
|
+
*/
|
|
57
|
+
export declare function ensureFirewallRule(port: number): boolean;
|
|
58
|
+
export declare function removeFirewallRule(port: number): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Human-readable firewall state for the status endpoint. A missing backend
|
|
61
|
+
* means the platform has nothing to manage; detection stays at the call site
|
|
62
|
+
* so an explicit undefined cannot silently re-probe the real OS mid-test.
|
|
63
|
+
*/
|
|
64
|
+
export declare function computeFirewallSummary(port: number, lanEnabled: boolean, backend: FirewallBackend | undefined): FirewallSummary;
|
|
65
|
+
/** How long a firewallSummary answer is reused before the backend is probed again. */
|
|
66
|
+
export declare const FIREWALL_SUMMARY_TTL_MS = 30000;
|
|
67
|
+
/** Forget the cached summary (rule mutations call this). */
|
|
68
|
+
export declare function invalidateFirewallSummary(): void;
|
|
69
|
+
/**
|
|
70
|
+
* The settings card polls this every ten seconds; the probes are blocking
|
|
71
|
+
* spawnSync subprocesses on managed platforms, so short-TTL memoization
|
|
72
|
+
* keeps one poll from freezing the host event loop per request.
|
|
73
|
+
*/
|
|
74
|
+
export declare function firewallSummary(port: number, lanEnabled: boolean): FirewallSummary;
|
|
75
|
+
//# sourceMappingURL=firewall.d.ts.map
|