@yu_robotics/remote-cli-router 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/LICENSE +21 -0
- package/README.md +115 -0
- package/bin/remote-cli-router.js +2 -0
- package/dist/binding/BindingManager.d.ts +62 -0
- package/dist/binding/BindingManager.d.ts.map +1 -0
- package/dist/binding/BindingManager.js +119 -0
- package/dist/binding/BindingManager.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +32 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +19 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +206 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/start.d.ts +5 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +65 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +103 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +5 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +56 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/config/ConfigManager.d.ts +46 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +101 -0
- package/dist/config/ConfigManager.js.map +1 -0
- package/dist/feishu/FeishuClient.d.ts +46 -0
- package/dist/feishu/FeishuClient.d.ts.map +1 -0
- package/dist/feishu/FeishuClient.js +130 -0
- package/dist/feishu/FeishuClient.js.map +1 -0
- package/dist/feishu/FeishuLongConnHandler.d.ts +149 -0
- package/dist/feishu/FeishuLongConnHandler.d.ts.map +1 -0
- package/dist/feishu/FeishuLongConnHandler.js +632 -0
- package/dist/feishu/FeishuLongConnHandler.js.map +1 -0
- package/dist/server.d.ts +80 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +533 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/JsonStore.d.ts +90 -0
- package/dist/storage/JsonStore.d.ts.map +1 -0
- package/dist/storage/JsonStore.js +215 -0
- package/dist/storage/JsonStore.js.map +1 -0
- package/dist/storage/MemoryStore.d.ts +69 -0
- package/dist/storage/MemoryStore.d.ts.map +1 -0
- package/dist/storage/MemoryStore.js +117 -0
- package/dist/storage/MemoryStore.js.map +1 -0
- package/dist/types/config.d.ts +53 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +31 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +93 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +18 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/PidManager.d.ts +28 -0
- package/dist/utils/PidManager.d.ts.map +1 -0
- package/dist/utils/PidManager.js +90 -0
- package/dist/utils/PidManager.js.map +1 -0
- package/dist/utils/ToolFormatter.d.ts +41 -0
- package/dist/utils/ToolFormatter.d.ts.map +1 -0
- package/dist/utils/ToolFormatter.js +273 -0
- package/dist/utils/ToolFormatter.js.map +1 -0
- package/dist/websocket/ConnectionHub.d.ts +73 -0
- package/dist/websocket/ConnectionHub.d.ts.map +1 -0
- package/dist/websocket/ConnectionHub.js +177 -0
- package/dist/websocket/ConnectionHub.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common type definitions
|
|
3
|
+
*/
|
|
4
|
+
export interface BindingCode {
|
|
5
|
+
code: string;
|
|
6
|
+
deviceId: string;
|
|
7
|
+
createdAt: number;
|
|
8
|
+
expiresAt: number;
|
|
9
|
+
}
|
|
10
|
+
export interface UserBinding {
|
|
11
|
+
openId: string;
|
|
12
|
+
deviceId: string;
|
|
13
|
+
deviceName: string;
|
|
14
|
+
boundAt: number;
|
|
15
|
+
lastActiveAt: number;
|
|
16
|
+
}
|
|
17
|
+
export declare enum MessageType {
|
|
18
|
+
COMMAND = "command",// Command message
|
|
19
|
+
RESPONSE = "response",// Response message
|
|
20
|
+
BINDING_REQUEST = "binding_request",// Binding request
|
|
21
|
+
BINDING_CONFIRM = "binding_confirm",// Binding confirmation
|
|
22
|
+
HEARTBEAT = "heartbeat",// Heartbeat
|
|
23
|
+
ERROR = "error",// Error
|
|
24
|
+
NOTIFICATION = "notification"
|
|
25
|
+
}
|
|
26
|
+
export interface WSMessage {
|
|
27
|
+
type: MessageType;
|
|
28
|
+
messageId: string;
|
|
29
|
+
timestamp: number;
|
|
30
|
+
data: any;
|
|
31
|
+
}
|
|
32
|
+
export interface CommandMessage extends WSMessage {
|
|
33
|
+
type: MessageType.COMMAND;
|
|
34
|
+
data: {
|
|
35
|
+
openId: string;
|
|
36
|
+
content: string;
|
|
37
|
+
workingDir?: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export interface ResponseMessage extends WSMessage {
|
|
41
|
+
type: MessageType.RESPONSE;
|
|
42
|
+
data: {
|
|
43
|
+
success: boolean;
|
|
44
|
+
output?: string;
|
|
45
|
+
error?: string;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export type ContentBlockType = 'text' | 'tool_use' | 'tool_result' | 'divider';
|
|
49
|
+
export interface ContentBlock {
|
|
50
|
+
type: ContentBlockType;
|
|
51
|
+
}
|
|
52
|
+
export interface TextBlock extends ContentBlock {
|
|
53
|
+
type: 'text';
|
|
54
|
+
content: string;
|
|
55
|
+
}
|
|
56
|
+
export interface ToolUseInfo {
|
|
57
|
+
name: string;
|
|
58
|
+
id: string;
|
|
59
|
+
input: Record<string, any>;
|
|
60
|
+
}
|
|
61
|
+
export interface ToolResultInfo {
|
|
62
|
+
tool_use_id: string;
|
|
63
|
+
content: string;
|
|
64
|
+
is_error: boolean;
|
|
65
|
+
}
|
|
66
|
+
export interface ToolUseBlock extends ContentBlock {
|
|
67
|
+
type: 'tool_use';
|
|
68
|
+
tool: ToolUseInfo;
|
|
69
|
+
}
|
|
70
|
+
export interface ToolResultBlock extends ContentBlock {
|
|
71
|
+
type: 'tool_result';
|
|
72
|
+
result: ToolResultInfo;
|
|
73
|
+
}
|
|
74
|
+
export interface DividerBlock extends ContentBlock {
|
|
75
|
+
type: 'divider';
|
|
76
|
+
}
|
|
77
|
+
export type ContentBlockUnion = TextBlock | ToolUseBlock | ToolResultBlock | DividerBlock;
|
|
78
|
+
export interface StructuredContent {
|
|
79
|
+
blocks: ContentBlockUnion[];
|
|
80
|
+
sessionAbbr?: string;
|
|
81
|
+
}
|
|
82
|
+
export interface StructuredMessage extends WSMessage {
|
|
83
|
+
type: MessageType.RESPONSE;
|
|
84
|
+
data: {
|
|
85
|
+
success: boolean;
|
|
86
|
+
output?: string;
|
|
87
|
+
structuredContent?: StructuredContent;
|
|
88
|
+
error?: string;
|
|
89
|
+
sessionAbbr?: string;
|
|
90
|
+
openId?: string;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Common type definitions
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MessageType = void 0;
|
|
7
|
+
// WebSocket message type
|
|
8
|
+
var MessageType;
|
|
9
|
+
(function (MessageType) {
|
|
10
|
+
MessageType["COMMAND"] = "command";
|
|
11
|
+
MessageType["RESPONSE"] = "response";
|
|
12
|
+
MessageType["BINDING_REQUEST"] = "binding_request";
|
|
13
|
+
MessageType["BINDING_CONFIRM"] = "binding_confirm";
|
|
14
|
+
MessageType["HEARTBEAT"] = "heartbeat";
|
|
15
|
+
MessageType["ERROR"] = "error";
|
|
16
|
+
MessageType["NOTIFICATION"] = "notification"; // Notification message to Feishu
|
|
17
|
+
})(MessageType || (exports.MessageType = MessageType = {}));
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAmBH,yBAAyB;AACzB,IAAY,WAQX;AARD,WAAY,WAAW;IACrB,kCAAmB,CAAA;IACnB,oCAAqB,CAAA;IACrB,kDAAmC,CAAA;IACnC,kDAAmC,CAAA;IACnC,sCAAuB,CAAA;IACvB,8BAAe,CAAA;IACf,4CAA6B,CAAA,CAAI,iCAAiC;AACpE,CAAC,EARW,WAAW,2BAAX,WAAW,QAQtB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PID file manager for the router server
|
|
3
|
+
*/
|
|
4
|
+
export declare class PidManager {
|
|
5
|
+
private pidFilePath;
|
|
6
|
+
constructor(baseDir?: string);
|
|
7
|
+
/**
|
|
8
|
+
* Write the current process ID to the PID file
|
|
9
|
+
*/
|
|
10
|
+
writePid(pid: number): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Read the PID from the PID file
|
|
13
|
+
*/
|
|
14
|
+
readPid(): Promise<number | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Remove the PID file
|
|
17
|
+
*/
|
|
18
|
+
removePid(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a process with the given PID is running
|
|
21
|
+
*/
|
|
22
|
+
isProcessRunning(pid: number): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Get the PID of the running server, or null if not running
|
|
25
|
+
*/
|
|
26
|
+
getRunningPid(): Promise<number | null>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=PidManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PidManager.d.ts","sourceRoot":"","sources":["../../src/utils/PidManager.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,CAAC,EAAE,MAAM;IAK5B;;OAEG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAavC;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAUhC;;OAEG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAUtC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAa9C"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PidManager = void 0;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
/**
|
|
11
|
+
* PID file manager for the router server
|
|
12
|
+
*/
|
|
13
|
+
class PidManager {
|
|
14
|
+
pidFilePath;
|
|
15
|
+
constructor(baseDir) {
|
|
16
|
+
const configDir = baseDir || path_1.default.join(os_1.default.homedir(), '.remote-cli-router');
|
|
17
|
+
this.pidFilePath = path_1.default.join(configDir, 'server.pid');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Write the current process ID to the PID file
|
|
21
|
+
*/
|
|
22
|
+
async writePid(pid) {
|
|
23
|
+
try {
|
|
24
|
+
const dir = path_1.default.dirname(this.pidFilePath);
|
|
25
|
+
await promises_1.default.mkdir(dir, { recursive: true });
|
|
26
|
+
await promises_1.default.writeFile(this.pidFilePath, pid.toString(), 'utf-8');
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
throw new Error(`Failed to write PID file: ${error.message}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Read the PID from the PID file
|
|
34
|
+
*/
|
|
35
|
+
async readPid() {
|
|
36
|
+
try {
|
|
37
|
+
const content = await promises_1.default.readFile(this.pidFilePath, 'utf-8');
|
|
38
|
+
const pid = parseInt(content.trim(), 10);
|
|
39
|
+
return isNaN(pid) ? null : pid;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error.code === 'ENOENT') {
|
|
43
|
+
return null; // PID file doesn't exist
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`Failed to read PID file: ${error.message}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Remove the PID file
|
|
50
|
+
*/
|
|
51
|
+
async removePid() {
|
|
52
|
+
try {
|
|
53
|
+
await promises_1.default.unlink(this.pidFilePath);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (error.code !== 'ENOENT') {
|
|
57
|
+
throw new Error(`Failed to remove PID file: ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if a process with the given PID is running
|
|
63
|
+
*/
|
|
64
|
+
isProcessRunning(pid) {
|
|
65
|
+
try {
|
|
66
|
+
// Send signal 0 to check if process exists without killing it
|
|
67
|
+
process.kill(pid, 0);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get the PID of the running server, or null if not running
|
|
76
|
+
*/
|
|
77
|
+
async getRunningPid() {
|
|
78
|
+
const pid = await this.readPid();
|
|
79
|
+
if (pid && this.isProcessRunning(pid)) {
|
|
80
|
+
return pid;
|
|
81
|
+
}
|
|
82
|
+
// PID file exists but process is not running - clean up stale file
|
|
83
|
+
if (pid) {
|
|
84
|
+
await this.removePid();
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.PidManager = PidManager;
|
|
90
|
+
//# sourceMappingURL=PidManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PidManager.js","sourceRoot":"","sources":["../../src/utils/PidManager.ts"],"names":[],"mappings":";;;;;;AAAA,2DAA6B;AAC7B,gDAAwB;AACxB,4CAAoB;AAEpB;;GAEG;AACH,MAAa,UAAU;IACb,WAAW,CAAS;IAE5B,YAAY,OAAgB;QAC1B,MAAM,SAAS,GAAG,OAAO,IAAI,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,oBAAoB,CAAC,CAAC;QAC3E,IAAI,CAAC,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACxD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC3C,MAAM,kBAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,MAAM,kBAAE,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YAC7D,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YACzC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;QACjC,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5B,OAAO,IAAI,CAAC,CAAC,yBAAyB;YACxC,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS;QACb,IAAI,CAAC;YACH,MAAM,kBAAE,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,8BAA8B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,GAAW;QAC1B,IAAI,CAAC;YACH,8DAA8D;YAC9D,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,GAAG,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,OAAO,GAAG,CAAC;QACb,CAAC;QAED,mEAAmE;QACnE,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACzB,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA/ED,gCA+EC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ToolUseInfo, ToolResultInfo } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Feishu Card 2.0 element types
|
|
4
|
+
*/
|
|
5
|
+
export interface FeishuCardElement {
|
|
6
|
+
tag: string;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Get emoji for tool name
|
|
11
|
+
*/
|
|
12
|
+
export declare function getToolEmoji(toolName: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Extract context from tool input based on tool type
|
|
15
|
+
*/
|
|
16
|
+
export declare function extractToolContext(toolName: string, input: Record<string, unknown>): string;
|
|
17
|
+
/**
|
|
18
|
+
* Format file path for display (shorten home directory)
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatFilePath(filePath: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Truncate string to max length
|
|
23
|
+
*/
|
|
24
|
+
export declare function truncate(str: string, maxLength: number): string;
|
|
25
|
+
/**
|
|
26
|
+
* Create a Feishu Card 2.0 divider element
|
|
27
|
+
*/
|
|
28
|
+
export declare function createDividerElement(): FeishuCardElement;
|
|
29
|
+
/**
|
|
30
|
+
* Create a Feishu Card 2.0 markdown element
|
|
31
|
+
*/
|
|
32
|
+
export declare function createMarkdownElement(content: string): FeishuCardElement;
|
|
33
|
+
/**
|
|
34
|
+
* Create a Feishu Card 2.0 tool use element
|
|
35
|
+
*/
|
|
36
|
+
export declare function createToolUseElement(toolInfo: ToolUseInfo): FeishuCardElement[];
|
|
37
|
+
/**
|
|
38
|
+
* Create a Feishu Card 2.0 tool result element
|
|
39
|
+
*/
|
|
40
|
+
export declare function createToolResultElement(resultInfo: ToolResultInfo): FeishuCardElement[];
|
|
41
|
+
//# sourceMappingURL=ToolFormatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolFormatter.d.ts","sourceRoot":"","sources":["../../src/utils/ToolFormatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAuBD;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA2B3F;AA2KD;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMvD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAK/D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,CAExD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAKxE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,WAAW,GAAG,iBAAiB,EAAE,CAkB/E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,cAAc,GAAG,iBAAiB,EAAE,CA2BvF"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getToolEmoji = getToolEmoji;
|
|
4
|
+
exports.extractToolContext = extractToolContext;
|
|
5
|
+
exports.formatFilePath = formatFilePath;
|
|
6
|
+
exports.truncate = truncate;
|
|
7
|
+
exports.createDividerElement = createDividerElement;
|
|
8
|
+
exports.createMarkdownElement = createMarkdownElement;
|
|
9
|
+
exports.createToolUseElement = createToolUseElement;
|
|
10
|
+
exports.createToolResultElement = createToolResultElement;
|
|
11
|
+
/**
|
|
12
|
+
* Tool emoji mapping
|
|
13
|
+
*/
|
|
14
|
+
const TOOL_EMOJIS = {
|
|
15
|
+
Bash: '⚡',
|
|
16
|
+
Read: '📖',
|
|
17
|
+
Write: '✍️',
|
|
18
|
+
Edit: '✏️',
|
|
19
|
+
Grep: '🔍',
|
|
20
|
+
Glob: '📁',
|
|
21
|
+
Task: '🤖',
|
|
22
|
+
WebFetch: '🌐',
|
|
23
|
+
WebSearch: '🔎',
|
|
24
|
+
TodoWrite: '📝',
|
|
25
|
+
AskUserQuestion: '❓',
|
|
26
|
+
Skill: '🎯',
|
|
27
|
+
EnterPlanMode: '📋',
|
|
28
|
+
ExitPlanMode: '✅',
|
|
29
|
+
NotebookEdit: '📓',
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Get emoji for tool name
|
|
33
|
+
*/
|
|
34
|
+
function getToolEmoji(toolName) {
|
|
35
|
+
return TOOL_EMOJIS[toolName] || '🔧';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extract context from tool input based on tool type
|
|
39
|
+
*/
|
|
40
|
+
function extractToolContext(toolName, input) {
|
|
41
|
+
switch (toolName) {
|
|
42
|
+
case 'Bash':
|
|
43
|
+
return extractBashContext(input);
|
|
44
|
+
case 'Read':
|
|
45
|
+
return extractReadContext(input);
|
|
46
|
+
case 'Write':
|
|
47
|
+
return extractWriteContext(input);
|
|
48
|
+
case 'Edit':
|
|
49
|
+
return extractEditContext(input);
|
|
50
|
+
case 'Grep':
|
|
51
|
+
return extractGrepContext(input);
|
|
52
|
+
case 'Glob':
|
|
53
|
+
return extractGlobContext(input);
|
|
54
|
+
case 'Task':
|
|
55
|
+
return extractTaskContext(input);
|
|
56
|
+
case 'WebFetch':
|
|
57
|
+
return extractWebFetchContext(input);
|
|
58
|
+
case 'WebSearch':
|
|
59
|
+
return extractWebSearchContext(input);
|
|
60
|
+
case 'TodoWrite':
|
|
61
|
+
return extractTodoWriteContext(input);
|
|
62
|
+
case 'AskUserQuestion':
|
|
63
|
+
return extractAskUserQuestionContext(input);
|
|
64
|
+
default:
|
|
65
|
+
return formatGenericContext(input);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function extractBashContext(input) {
|
|
69
|
+
const command = input.command;
|
|
70
|
+
const description = input.description;
|
|
71
|
+
if (description && description.length > 0 && description.length < 100) {
|
|
72
|
+
return `**${description}**\n\`\`\`bash\n${truncate(command, 500)}\n\`\`\``;
|
|
73
|
+
}
|
|
74
|
+
return `\`\`\`bash\n${truncate(command, 500)}\n\`\`\``;
|
|
75
|
+
}
|
|
76
|
+
function extractReadContext(input) {
|
|
77
|
+
const filePath = input.file_path;
|
|
78
|
+
const offset = input.offset;
|
|
79
|
+
const limit = input.limit;
|
|
80
|
+
let context = `**File:** ${formatFilePath(filePath)}`;
|
|
81
|
+
if (offset !== undefined || limit !== undefined) {
|
|
82
|
+
const rangeInfo = [];
|
|
83
|
+
if (offset !== undefined)
|
|
84
|
+
rangeInfo.push(`offset: ${offset}`);
|
|
85
|
+
if (limit !== undefined)
|
|
86
|
+
rangeInfo.push(`limit: ${limit}`);
|
|
87
|
+
context += `\n**Range:** ${rangeInfo.join(', ')}`;
|
|
88
|
+
}
|
|
89
|
+
return context;
|
|
90
|
+
}
|
|
91
|
+
function extractWriteContext(input) {
|
|
92
|
+
const filePath = input.file_path;
|
|
93
|
+
const content = input.content;
|
|
94
|
+
const lines = content.split('\n').length;
|
|
95
|
+
const chars = content.length;
|
|
96
|
+
return `**File:** ${formatFilePath(filePath)}\n**Size:** ${lines} lines, ${chars} chars`;
|
|
97
|
+
}
|
|
98
|
+
function extractEditContext(input) {
|
|
99
|
+
const filePath = input.file_path;
|
|
100
|
+
const oldString = input.old_string;
|
|
101
|
+
const newString = input.new_string;
|
|
102
|
+
let context = `**File:** ${formatFilePath(filePath)}`;
|
|
103
|
+
if (oldString && newString) {
|
|
104
|
+
const oldLines = oldString.split('\n').length;
|
|
105
|
+
const newLines = newString.split('\n').length;
|
|
106
|
+
context += `\n**Change:** ${oldLines} → ${newLines} lines`;
|
|
107
|
+
}
|
|
108
|
+
return context;
|
|
109
|
+
}
|
|
110
|
+
function extractGrepContext(input) {
|
|
111
|
+
const pattern = input.pattern;
|
|
112
|
+
const path = input.path;
|
|
113
|
+
const glob = input.glob;
|
|
114
|
+
const type = input.type;
|
|
115
|
+
let context = `**Pattern:** \`${truncate(pattern, 100)}\``;
|
|
116
|
+
if (path) {
|
|
117
|
+
context += `\n**Path:** ${formatFilePath(path)}`;
|
|
118
|
+
}
|
|
119
|
+
if (glob) {
|
|
120
|
+
context += `\n**Glob:** \`${glob}\``;
|
|
121
|
+
}
|
|
122
|
+
if (type) {
|
|
123
|
+
context += `\n**Type:** ${type}`;
|
|
124
|
+
}
|
|
125
|
+
return context;
|
|
126
|
+
}
|
|
127
|
+
function extractGlobContext(input) {
|
|
128
|
+
const pattern = input.pattern;
|
|
129
|
+
const path = input.path;
|
|
130
|
+
let context = `**Pattern:** \`${pattern}\``;
|
|
131
|
+
if (path) {
|
|
132
|
+
context += `\n**Path:** ${formatFilePath(path)}`;
|
|
133
|
+
}
|
|
134
|
+
return context;
|
|
135
|
+
}
|
|
136
|
+
function extractTaskContext(input) {
|
|
137
|
+
const subagentType = input.subagent_type;
|
|
138
|
+
const description = input.description;
|
|
139
|
+
const prompt = input.prompt;
|
|
140
|
+
let context = `**Agent:** ${subagentType}`;
|
|
141
|
+
if (description) {
|
|
142
|
+
context += `\n**Task:** ${truncate(description, 100)}`;
|
|
143
|
+
}
|
|
144
|
+
if (prompt && prompt.length < 200) {
|
|
145
|
+
context += `\n**Prompt:** ${truncate(prompt, 150)}`;
|
|
146
|
+
}
|
|
147
|
+
return context;
|
|
148
|
+
}
|
|
149
|
+
function extractWebFetchContext(input) {
|
|
150
|
+
const url = input.url;
|
|
151
|
+
const prompt = input.prompt;
|
|
152
|
+
let context = `**URL:** ${url}`;
|
|
153
|
+
if (prompt && prompt.length < 150) {
|
|
154
|
+
context += `\n**Prompt:** ${truncate(prompt, 100)}`;
|
|
155
|
+
}
|
|
156
|
+
return context;
|
|
157
|
+
}
|
|
158
|
+
function extractWebSearchContext(input) {
|
|
159
|
+
const query = input.query;
|
|
160
|
+
return `**Query:** ${truncate(query, 150)}`;
|
|
161
|
+
}
|
|
162
|
+
function extractTodoWriteContext(input) {
|
|
163
|
+
const todos = input.todos;
|
|
164
|
+
if (!todos || todos.length === 0) {
|
|
165
|
+
return '**Updating todo list**';
|
|
166
|
+
}
|
|
167
|
+
return `**Todos:** ${todos.length} items`;
|
|
168
|
+
}
|
|
169
|
+
function extractAskUserQuestionContext(input) {
|
|
170
|
+
const questions = input.questions;
|
|
171
|
+
if (!questions || questions.length === 0) {
|
|
172
|
+
return '**Asking user question**';
|
|
173
|
+
}
|
|
174
|
+
if (questions.length === 1) {
|
|
175
|
+
return `**Question:** ${truncate(questions[0].question, 150)}`;
|
|
176
|
+
}
|
|
177
|
+
return `**Questions:** ${questions.length} items`;
|
|
178
|
+
}
|
|
179
|
+
function formatGenericContext(input) {
|
|
180
|
+
const keys = Object.keys(input);
|
|
181
|
+
if (keys.length === 0) {
|
|
182
|
+
return '_(no parameters)_';
|
|
183
|
+
}
|
|
184
|
+
const summary = keys.slice(0, 3).map(key => {
|
|
185
|
+
const value = input[key];
|
|
186
|
+
const valueStr = typeof value === 'string' ? truncate(value, 50) : JSON.stringify(value);
|
|
187
|
+
return `**${key}:** ${valueStr}`;
|
|
188
|
+
}).join('\n');
|
|
189
|
+
if (keys.length > 3) {
|
|
190
|
+
return `${summary}\n_...and ${keys.length - 3} more_`;
|
|
191
|
+
}
|
|
192
|
+
return summary;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Format file path for display (shorten home directory)
|
|
196
|
+
*/
|
|
197
|
+
function formatFilePath(filePath) {
|
|
198
|
+
const homeDir = process.env.HOME || '/Users';
|
|
199
|
+
if (filePath.startsWith(homeDir)) {
|
|
200
|
+
return `~${filePath.slice(homeDir.length)}`;
|
|
201
|
+
}
|
|
202
|
+
return filePath;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Truncate string to max length
|
|
206
|
+
*/
|
|
207
|
+
function truncate(str, maxLength) {
|
|
208
|
+
if (str.length <= maxLength) {
|
|
209
|
+
return str;
|
|
210
|
+
}
|
|
211
|
+
return str.slice(0, maxLength - 3) + '...';
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Create a Feishu Card 2.0 divider element
|
|
215
|
+
*/
|
|
216
|
+
function createDividerElement() {
|
|
217
|
+
return { tag: 'hr' };
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Create a Feishu Card 2.0 markdown element
|
|
221
|
+
*/
|
|
222
|
+
function createMarkdownElement(content) {
|
|
223
|
+
return {
|
|
224
|
+
tag: 'markdown',
|
|
225
|
+
content,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Create a Feishu Card 2.0 tool use element
|
|
230
|
+
*/
|
|
231
|
+
function createToolUseElement(toolInfo) {
|
|
232
|
+
const { name, input, id } = toolInfo;
|
|
233
|
+
const emoji = getToolEmoji(name);
|
|
234
|
+
const context = extractToolContext(name, input);
|
|
235
|
+
// Build markdown content
|
|
236
|
+
let content = `<text_tag color='blue'>${emoji} TOOL USE</text_tag> · **${name}**`;
|
|
237
|
+
if (id) {
|
|
238
|
+
content += ` · \`${id.slice(0, 8)}\``;
|
|
239
|
+
}
|
|
240
|
+
content += `\n\n${context}`;
|
|
241
|
+
return [
|
|
242
|
+
createDividerElement(),
|
|
243
|
+
createMarkdownElement(content),
|
|
244
|
+
];
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Create a Feishu Card 2.0 tool result element
|
|
248
|
+
*/
|
|
249
|
+
function createToolResultElement(resultInfo) {
|
|
250
|
+
const { tool_use_id, content, is_error } = resultInfo;
|
|
251
|
+
// Determine status
|
|
252
|
+
const statusColor = is_error ? 'red' : 'green';
|
|
253
|
+
const statusText = is_error ? 'ERROR' : 'SUCCESS';
|
|
254
|
+
// Build status text with color tag and tool_use_id
|
|
255
|
+
let statusDisplay = `<text_tag color='${statusColor}'>${statusText}</text_tag>`;
|
|
256
|
+
if (tool_use_id) {
|
|
257
|
+
statusDisplay += ` · \`${tool_use_id.slice(0, 8)}\``;
|
|
258
|
+
}
|
|
259
|
+
// Create status as markdown element
|
|
260
|
+
const elements = [createMarkdownElement(statusDisplay)];
|
|
261
|
+
if (content && !is_error) {
|
|
262
|
+
// For successful results, show the content in a code block
|
|
263
|
+
const truncated = truncate(content, 500);
|
|
264
|
+
elements.push(createMarkdownElement(`\`\`\`\n${truncated}\n\`\`\``));
|
|
265
|
+
}
|
|
266
|
+
else if (content && is_error) {
|
|
267
|
+
// For errors, show the error message
|
|
268
|
+
const truncated = truncate(content, 500);
|
|
269
|
+
elements.push(createMarkdownElement(truncated));
|
|
270
|
+
}
|
|
271
|
+
return elements;
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=ToolFormatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolFormatter.js","sourceRoot":"","sources":["../../src/utils/ToolFormatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { WebSocket } from 'ws';
|
|
2
|
+
/**
|
|
3
|
+
* WebSocket Connection Hub
|
|
4
|
+
* Manages all device WebSocket connections, responsible for message routing and connection management
|
|
5
|
+
*/
|
|
6
|
+
export declare class ConnectionHub {
|
|
7
|
+
private connections;
|
|
8
|
+
private lastActiveMap;
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Register device connection
|
|
12
|
+
* @param deviceId Device unique identifier
|
|
13
|
+
* @param ws WebSocket connection
|
|
14
|
+
*/
|
|
15
|
+
registerConnection(deviceId: string, ws: WebSocket): void;
|
|
16
|
+
/**
|
|
17
|
+
* Unregister device connection
|
|
18
|
+
* @param deviceId Device unique identifier
|
|
19
|
+
*/
|
|
20
|
+
unregisterConnection(deviceId: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Send message to specified device
|
|
23
|
+
* @param deviceId Device unique identifier
|
|
24
|
+
* @param message Message object
|
|
25
|
+
* @returns Whether sending was successful
|
|
26
|
+
*/
|
|
27
|
+
sendToDevice(deviceId: string, message: any): Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Check if device is online
|
|
30
|
+
* @param deviceId Device unique identifier
|
|
31
|
+
* @returns Whether it is online
|
|
32
|
+
*/
|
|
33
|
+
isDeviceOnline(deviceId: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Get device last active time
|
|
36
|
+
* @param deviceId Device unique identifier
|
|
37
|
+
* @returns Last active timestamp, returns undefined if device does not exist
|
|
38
|
+
*/
|
|
39
|
+
getLastActiveTime(deviceId: string): number | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Get list of all online device IDs
|
|
42
|
+
* @returns Device ID array
|
|
43
|
+
*/
|
|
44
|
+
getOnlineDevices(): string[];
|
|
45
|
+
/**
|
|
46
|
+
* Update device last active time
|
|
47
|
+
* @param deviceId Device unique identifier
|
|
48
|
+
*/
|
|
49
|
+
updateLastActive(deviceId: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get connection statistics
|
|
52
|
+
* @returns Connection statistics
|
|
53
|
+
*/
|
|
54
|
+
getConnectionStats(): {
|
|
55
|
+
totalConnections: number;
|
|
56
|
+
deviceIds: string[];
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Broadcast message to all devices
|
|
60
|
+
* @param message Message object
|
|
61
|
+
*/
|
|
62
|
+
broadcast(message: any): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Clean up stale connections
|
|
65
|
+
* @param timeoutMs Timeout duration (milliseconds)
|
|
66
|
+
*/
|
|
67
|
+
cleanupStaleConnections(timeoutMs: number): void;
|
|
68
|
+
/**
|
|
69
|
+
* Close all connections
|
|
70
|
+
*/
|
|
71
|
+
closeAllConnections(): void;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=ConnectionHub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConnectionHub.d.ts","sourceRoot":"","sources":["../../src/websocket/ConnectionHub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAE/B;;;GAGG;AACH,qBAAa,aAAa;IAExB,OAAO,CAAC,WAAW,CAAyB;IAE5C,OAAO,CAAC,aAAa,CAAsB;;IAO3C;;;;OAIG;IACH,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,GAAG,IAAI;IAgBzD;;;OAGG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK5C;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBpE;;;;OAIG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;OAIG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIvD;;;OAGG;IACH,gBAAgB,IAAI,MAAM,EAAE;IAI5B;;;OAGG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAMxC;;;OAGG;IACH,kBAAkB,IAAI;QACpB,gBAAgB,EAAE,MAAM,CAAC;QACzB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB;IAQD;;;OAGG;IACG,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB5C;;;OAGG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAuBhD;;OAEG;IACH,mBAAmB,IAAI,IAAI;CAY5B"}
|