@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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/bin/remote-cli-router.js +2 -0
  4. package/dist/binding/BindingManager.d.ts +62 -0
  5. package/dist/binding/BindingManager.d.ts.map +1 -0
  6. package/dist/binding/BindingManager.js +119 -0
  7. package/dist/binding/BindingManager.js.map +1 -0
  8. package/dist/cli.d.ts +3 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +32 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/config.d.ts +19 -0
  13. package/dist/commands/config.d.ts.map +1 -0
  14. package/dist/commands/config.js +206 -0
  15. package/dist/commands/config.js.map +1 -0
  16. package/dist/commands/start.d.ts +5 -0
  17. package/dist/commands/start.d.ts.map +1 -0
  18. package/dist/commands/start.js +65 -0
  19. package/dist/commands/start.js.map +1 -0
  20. package/dist/commands/status.d.ts +5 -0
  21. package/dist/commands/status.d.ts.map +1 -0
  22. package/dist/commands/status.js +103 -0
  23. package/dist/commands/status.js.map +1 -0
  24. package/dist/commands/stop.d.ts +5 -0
  25. package/dist/commands/stop.d.ts.map +1 -0
  26. package/dist/commands/stop.js +56 -0
  27. package/dist/commands/stop.js.map +1 -0
  28. package/dist/config/ConfigManager.d.ts +46 -0
  29. package/dist/config/ConfigManager.d.ts.map +1 -0
  30. package/dist/config/ConfigManager.js +101 -0
  31. package/dist/config/ConfigManager.js.map +1 -0
  32. package/dist/feishu/FeishuClient.d.ts +46 -0
  33. package/dist/feishu/FeishuClient.d.ts.map +1 -0
  34. package/dist/feishu/FeishuClient.js +130 -0
  35. package/dist/feishu/FeishuClient.js.map +1 -0
  36. package/dist/feishu/FeishuLongConnHandler.d.ts +149 -0
  37. package/dist/feishu/FeishuLongConnHandler.d.ts.map +1 -0
  38. package/dist/feishu/FeishuLongConnHandler.js +632 -0
  39. package/dist/feishu/FeishuLongConnHandler.js.map +1 -0
  40. package/dist/server.d.ts +80 -0
  41. package/dist/server.d.ts.map +1 -0
  42. package/dist/server.js +533 -0
  43. package/dist/server.js.map +1 -0
  44. package/dist/storage/JsonStore.d.ts +90 -0
  45. package/dist/storage/JsonStore.d.ts.map +1 -0
  46. package/dist/storage/JsonStore.js +215 -0
  47. package/dist/storage/JsonStore.js.map +1 -0
  48. package/dist/storage/MemoryStore.d.ts +69 -0
  49. package/dist/storage/MemoryStore.d.ts.map +1 -0
  50. package/dist/storage/MemoryStore.js +117 -0
  51. package/dist/storage/MemoryStore.js.map +1 -0
  52. package/dist/types/config.d.ts +53 -0
  53. package/dist/types/config.d.ts.map +1 -0
  54. package/dist/types/config.js +31 -0
  55. package/dist/types/config.js.map +1 -0
  56. package/dist/types/index.d.ts +93 -0
  57. package/dist/types/index.d.ts.map +1 -0
  58. package/dist/types/index.js +18 -0
  59. package/dist/types/index.js.map +1 -0
  60. package/dist/utils/PidManager.d.ts +28 -0
  61. package/dist/utils/PidManager.d.ts.map +1 -0
  62. package/dist/utils/PidManager.js +90 -0
  63. package/dist/utils/PidManager.js.map +1 -0
  64. package/dist/utils/ToolFormatter.d.ts +41 -0
  65. package/dist/utils/ToolFormatter.d.ts.map +1 -0
  66. package/dist/utils/ToolFormatter.js +273 -0
  67. package/dist/utils/ToolFormatter.js.map +1 -0
  68. package/dist/websocket/ConnectionHub.d.ts +73 -0
  69. package/dist/websocket/ConnectionHub.d.ts.map +1 -0
  70. package/dist/websocket/ConnectionHub.js +177 -0
  71. package/dist/websocket/ConnectionHub.js.map +1 -0
  72. 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"}