@zhihand/mcp 0.32.1 → 0.32.3
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/bin/zhihand +1 -1
- package/dist/core/device.js +1 -0
- package/dist/core/ws.d.ts +2 -0
- package/dist/core/ws.js +16 -6
- package/dist/daemon/prompt-listener.js +22 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/bin/zhihand
CHANGED
|
@@ -30,7 +30,7 @@ import { fetchUserCredentials } from "../dist/core/ws.js";
|
|
|
30
30
|
import { configureMCP, displayName } from "../dist/cli/mcp-config.js";
|
|
31
31
|
|
|
32
32
|
const DEFAULT_ENDPOINT = "https://api.zhihand.com";
|
|
33
|
-
const VERSION = "0.32.
|
|
33
|
+
const VERSION = "0.32.3";
|
|
34
34
|
|
|
35
35
|
const CLI_TOOL_MAP = {
|
|
36
36
|
claude: "claudecode",
|
package/dist/core/device.js
CHANGED
|
@@ -176,6 +176,7 @@ const RAW_ATTRIBUTE_ALLOWLIST = [
|
|
|
176
176
|
"brand", "manufacturer", "model", "rom_family", "rom_version",
|
|
177
177
|
"system_release", "api_level", "app_version", "app_build",
|
|
178
178
|
"display_width_px", "display_height_px", "density", "density_dpi",
|
|
179
|
+
"display_width_pixels", "display_height_pixels", "display_scale",
|
|
179
180
|
"screen_width_dp", "screen_height_dp", "smallest_width_dp",
|
|
180
181
|
"form_factor", "orientation", "touchscreen", "navigation_mode",
|
|
181
182
|
"locale", "language", "timezone", "rtl", "dark_mode", "font_scale",
|
package/dist/core/ws.d.ts
CHANGED
|
@@ -46,6 +46,7 @@ export interface WSEvent {
|
|
|
46
46
|
command?: QueuedCommandRecord;
|
|
47
47
|
device_profile?: Record<string, unknown>;
|
|
48
48
|
credential?: Record<string, unknown>;
|
|
49
|
+
payload?: Record<string, unknown>;
|
|
49
50
|
sequence: number;
|
|
50
51
|
}
|
|
51
52
|
export declare function handleWSEvent(event: WSEvent): void;
|
|
@@ -61,6 +62,7 @@ export interface UserEventStreamHandlers {
|
|
|
61
62
|
onDisconnected: () => void;
|
|
62
63
|
}
|
|
63
64
|
export declare class UserEventWebSocket {
|
|
65
|
+
private controllerToken;
|
|
64
66
|
private handlers;
|
|
65
67
|
private rws;
|
|
66
68
|
private lastProcessedSeq;
|
package/dist/core/ws.js
CHANGED
|
@@ -163,18 +163,26 @@ export function subscribeToCommandAck(commandId, callback) {
|
|
|
163
163
|
return () => { ackCallbacks.delete(commandId); };
|
|
164
164
|
}
|
|
165
165
|
export class UserEventWebSocket {
|
|
166
|
+
controllerToken;
|
|
166
167
|
handlers;
|
|
167
168
|
rws;
|
|
168
169
|
lastProcessedSeq = new Map();
|
|
169
170
|
constructor(userId, controllerToken, endpoint, handlers) {
|
|
171
|
+
this.controllerToken = controllerToken;
|
|
170
172
|
this.handlers = handlers;
|
|
171
|
-
const topics = "commands,device_profile,device.online,device.offline,credential.added,credential.removed";
|
|
172
|
-
const wsUrl = `${endpoint.replace(/^http/, "ws")}/v1/users/${encodeURIComponent(userId)}/ws
|
|
173
|
+
const topics = ["commands", "device_profile", "device.online", "device.offline", "credential.added", "credential.removed"];
|
|
174
|
+
const wsUrl = `${endpoint.replace(/^http/, "ws")}/v1/users/${encodeURIComponent(userId)}/ws`;
|
|
173
175
|
this.rws = new ReconnectingWebSocket({
|
|
174
176
|
url: wsUrl,
|
|
175
177
|
headers: { "Authorization": `Bearer ${controllerToken}` },
|
|
176
178
|
onOpen: () => {
|
|
177
|
-
|
|
179
|
+
// Send auth message as the server requires it as the first frame.
|
|
180
|
+
this.rws.send(JSON.stringify({
|
|
181
|
+
type: "auth",
|
|
182
|
+
bearer: this.controllerToken,
|
|
183
|
+
topics,
|
|
184
|
+
}));
|
|
185
|
+
// onConnected is called after auth_ok is received (see handleMessage)
|
|
178
186
|
},
|
|
179
187
|
onClose: (_code, _reason) => {
|
|
180
188
|
this.handlers.onDisconnected();
|
|
@@ -203,9 +211,11 @@ export class UserEventWebSocket {
|
|
|
203
211
|
this.rws.send(JSON.stringify({ type: "pong" }));
|
|
204
212
|
return;
|
|
205
213
|
}
|
|
206
|
-
// Auth responses
|
|
207
|
-
if (msg.type === "auth_ok")
|
|
214
|
+
// Auth responses
|
|
215
|
+
if (msg.type === "auth_ok") {
|
|
216
|
+
this.handlers.onConnected();
|
|
208
217
|
return;
|
|
218
|
+
}
|
|
209
219
|
if (msg.type === "auth_error") {
|
|
210
220
|
log.error(`[ws] Auth failed: ${msg.error}`);
|
|
211
221
|
this.rws.stop(); // Don't retry with invalid credentials
|
|
@@ -244,7 +254,7 @@ export class UserEventWebSocket {
|
|
|
244
254
|
this.handlers.onCommandAcked(ev);
|
|
245
255
|
break;
|
|
246
256
|
case "credential.added":
|
|
247
|
-
this.handlers.onCredentialAdded(ev.credential ?? { credential_id: ev.credential_id });
|
|
257
|
+
this.handlers.onCredentialAdded(ev.credential ?? ev.payload ?? { credential_id: ev.credential_id });
|
|
248
258
|
break;
|
|
249
259
|
case "credential.removed":
|
|
250
260
|
this.handlers.onCredentialRemoved(ev.credential_id);
|
|
@@ -51,9 +51,13 @@ export class PromptListener {
|
|
|
51
51
|
"Authorization": `Bearer ${this.config.controllerToken}`,
|
|
52
52
|
},
|
|
53
53
|
onOpen: () => {
|
|
54
|
-
|
|
55
|
-
this.
|
|
56
|
-
|
|
54
|
+
// Send auth message as first frame (required by server).
|
|
55
|
+
this.rws.send(JSON.stringify({
|
|
56
|
+
type: "auth",
|
|
57
|
+
controller_token: this.config.controllerToken,
|
|
58
|
+
topics: ["prompts"],
|
|
59
|
+
}));
|
|
60
|
+
// onConnected deferred until auth_ok is received (see handleWSMessage)
|
|
57
61
|
},
|
|
58
62
|
onClose: (_code, _reason) => {
|
|
59
63
|
if (this.wsConnected) {
|
|
@@ -73,6 +77,21 @@ export class PromptListener {
|
|
|
73
77
|
}
|
|
74
78
|
handleWSMessage(data) {
|
|
75
79
|
const msg = data;
|
|
80
|
+
// Auth responses
|
|
81
|
+
if (msg.type === "auth_ok") {
|
|
82
|
+
this.wsConnected = true;
|
|
83
|
+
this.stopPolling();
|
|
84
|
+
this.log("[ws] Connected to prompt stream.");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (msg.type === "auth_error") {
|
|
88
|
+
this.log(`[ws] Auth failed: ${msg.error}`);
|
|
89
|
+
this.rws?.stop();
|
|
90
|
+
this.rws = null;
|
|
91
|
+
this.wsConnected = false;
|
|
92
|
+
this.startPolling();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
76
95
|
// Application-level ping (if server sends these alongside protocol pings)
|
|
77
96
|
if (msg.type === "ping") {
|
|
78
97
|
this.rws?.send(JSON.stringify({ type: "pong" }));
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
export declare const PACKAGE_VERSION = "0.
|
|
2
|
+
export declare const PACKAGE_VERSION = "0.32.3";
|
|
3
3
|
export declare function createServer(): McpServer;
|
|
4
4
|
export declare function startStdioServer(): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { handlePair } from "./tools/pair.js";
|
|
|
8
8
|
import { resolveTargetDevice } from "./tools/resolve.js";
|
|
9
9
|
import { buildControlToolDescription, buildSystemToolDescription, buildScreenshotToolDescription, formatDeviceStatus, extractDynamic, } from "./core/device.js";
|
|
10
10
|
import { registry } from "./core/registry.js";
|
|
11
|
-
export const PACKAGE_VERSION = "0.
|
|
11
|
+
export const PACKAGE_VERSION = "0.32.3";
|
|
12
12
|
function errorResult(message) {
|
|
13
13
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
14
14
|
}
|