opc-agent 3.0.1 → 4.0.1

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 (216) hide show
  1. package/README.md +404 -74
  2. package/README.zh-CN.md +82 -0
  3. package/dist/channels/dingtalk.d.ts +17 -0
  4. package/dist/channels/dingtalk.js +38 -0
  5. package/dist/channels/googlechat.d.ts +14 -0
  6. package/dist/channels/googlechat.js +37 -0
  7. package/dist/channels/imessage.d.ts +13 -0
  8. package/dist/channels/imessage.js +28 -0
  9. package/dist/channels/irc.d.ts +20 -0
  10. package/dist/channels/irc.js +71 -0
  11. package/dist/channels/line.d.ts +14 -0
  12. package/dist/channels/line.js +28 -0
  13. package/dist/channels/matrix.d.ts +15 -0
  14. package/dist/channels/matrix.js +28 -0
  15. package/dist/channels/mattermost.d.ts +18 -0
  16. package/dist/channels/mattermost.js +49 -0
  17. package/dist/channels/msteams.d.ts +14 -0
  18. package/dist/channels/msteams.js +28 -0
  19. package/dist/channels/nostr.d.ts +14 -0
  20. package/dist/channels/nostr.js +28 -0
  21. package/dist/channels/qq.d.ts +15 -0
  22. package/dist/channels/qq.js +28 -0
  23. package/dist/channels/signal.d.ts +14 -0
  24. package/dist/channels/signal.js +28 -0
  25. package/dist/channels/sms.d.ts +15 -0
  26. package/dist/channels/sms.js +28 -0
  27. package/dist/channels/twitch.d.ts +17 -0
  28. package/dist/channels/twitch.js +59 -0
  29. package/dist/channels/voice-call.d.ts +27 -0
  30. package/dist/channels/voice-call.js +82 -0
  31. package/dist/channels/whatsapp.d.ts +14 -0
  32. package/dist/channels/whatsapp.js +28 -0
  33. package/dist/cli/chat.d.ts +2 -0
  34. package/dist/cli/chat.js +134 -0
  35. package/dist/cli/setup.d.ts +4 -0
  36. package/dist/cli/setup.js +303 -0
  37. package/dist/cli.js +142 -6
  38. package/dist/core/api-server.d.ts +25 -0
  39. package/dist/core/api-server.js +286 -0
  40. package/dist/core/audio.d.ts +50 -0
  41. package/dist/core/audio.js +68 -0
  42. package/dist/core/context-discovery.d.ts +16 -0
  43. package/dist/core/context-discovery.js +107 -0
  44. package/dist/core/context-refs.d.ts +29 -0
  45. package/dist/core/context-refs.js +162 -0
  46. package/dist/core/gateway.d.ts +53 -0
  47. package/dist/core/gateway.js +80 -0
  48. package/dist/core/heartbeat.d.ts +19 -0
  49. package/dist/core/heartbeat.js +50 -0
  50. package/dist/core/hooks.d.ts +28 -0
  51. package/dist/core/hooks.js +82 -0
  52. package/dist/core/ide-bridge.d.ts +53 -0
  53. package/dist/core/ide-bridge.js +97 -0
  54. package/dist/core/node-network.d.ts +23 -0
  55. package/dist/core/node-network.js +77 -0
  56. package/dist/core/profiles.d.ts +27 -0
  57. package/dist/core/profiles.js +131 -0
  58. package/dist/core/sandbox.d.ts +25 -0
  59. package/dist/core/sandbox.js +84 -1
  60. package/dist/core/session-manager.d.ts +33 -0
  61. package/dist/core/session-manager.js +157 -0
  62. package/dist/core/vision.d.ts +45 -0
  63. package/dist/core/vision.js +177 -0
  64. package/dist/hub/brain-seed.d.ts +14 -0
  65. package/dist/hub/brain-seed.js +77 -0
  66. package/dist/hub/client.d.ts +25 -0
  67. package/dist/hub/client.js +44 -0
  68. package/dist/index.d.ts +66 -1
  69. package/dist/index.js +95 -3
  70. package/dist/memory/context-compressor.d.ts +43 -0
  71. package/dist/memory/context-compressor.js +167 -0
  72. package/dist/memory/index.d.ts +4 -0
  73. package/dist/memory/index.js +5 -1
  74. package/dist/memory/user-profiler.d.ts +50 -0
  75. package/dist/memory/user-profiler.js +201 -0
  76. package/dist/providers/index.d.ts +1 -1
  77. package/dist/providers/index.js +54 -1
  78. package/dist/scheduler/cron-engine.d.ts +41 -0
  79. package/dist/scheduler/cron-engine.js +200 -0
  80. package/dist/scheduler/index.d.ts +3 -0
  81. package/dist/scheduler/index.js +7 -0
  82. package/dist/schema/oad.d.ts +12 -12
  83. package/dist/security/approvals.d.ts +53 -0
  84. package/dist/security/approvals.js +115 -0
  85. package/dist/security/elevated.d.ts +41 -0
  86. package/dist/security/elevated.js +89 -0
  87. package/dist/security/index.d.ts +6 -0
  88. package/dist/security/index.js +7 -1
  89. package/dist/security/secrets.d.ts +34 -0
  90. package/dist/security/secrets.js +115 -0
  91. package/dist/skills/builtin/index.d.ts +6 -0
  92. package/dist/skills/builtin/index.js +402 -0
  93. package/dist/skills/marketplace.d.ts +30 -0
  94. package/dist/skills/marketplace.js +142 -0
  95. package/dist/skills/types.d.ts +34 -0
  96. package/dist/skills/types.js +16 -0
  97. package/dist/studio/server.d.ts +25 -0
  98. package/dist/studio/server.js +780 -0
  99. package/dist/studio/templates-data.d.ts +21 -0
  100. package/dist/studio/templates-data.js +148 -0
  101. package/dist/studio-ui/index.html +2502 -1073
  102. package/dist/tools/builtin/browser.d.ts +47 -0
  103. package/dist/tools/builtin/browser.js +284 -0
  104. package/dist/tools/builtin/home-assistant.d.ts +12 -0
  105. package/dist/tools/builtin/home-assistant.js +126 -0
  106. package/dist/tools/builtin/index.d.ts +7 -1
  107. package/dist/tools/builtin/index.js +23 -2
  108. package/dist/tools/builtin/rl-tools.d.ts +13 -0
  109. package/dist/tools/builtin/rl-tools.js +228 -0
  110. package/dist/tools/builtin/vision.d.ts +6 -0
  111. package/dist/tools/builtin/vision.js +61 -0
  112. package/dist/tools/builtin/web-search.d.ts +9 -0
  113. package/dist/tools/builtin/web-search.js +150 -0
  114. package/dist/tools/document-processor.d.ts +39 -0
  115. package/dist/tools/document-processor.js +188 -0
  116. package/dist/tools/image-generator.d.ts +42 -0
  117. package/dist/tools/image-generator.js +136 -0
  118. package/dist/tools/web-scraper.d.ts +20 -0
  119. package/dist/tools/web-scraper.js +148 -0
  120. package/dist/tools/web-search.d.ts +51 -0
  121. package/dist/tools/web-search.js +152 -0
  122. package/install.ps1 +154 -0
  123. package/install.sh +164 -0
  124. package/package.json +63 -52
  125. package/src/channels/dingtalk.ts +46 -0
  126. package/src/channels/googlechat.ts +42 -0
  127. package/src/channels/imessage.ts +32 -0
  128. package/src/channels/irc.ts +82 -0
  129. package/src/channels/line.ts +33 -0
  130. package/src/channels/matrix.ts +34 -0
  131. package/src/channels/mattermost.ts +57 -0
  132. package/src/channels/msteams.ts +33 -0
  133. package/src/channels/nostr.ts +33 -0
  134. package/src/channels/qq.ts +34 -0
  135. package/src/channels/signal.ts +33 -0
  136. package/src/channels/sms.ts +34 -0
  137. package/src/channels/twitch.ts +65 -0
  138. package/src/channels/voice-call.ts +100 -0
  139. package/src/channels/whatsapp.ts +33 -0
  140. package/src/cli/chat.ts +99 -0
  141. package/src/cli/setup.ts +314 -0
  142. package/src/cli.ts +148 -6
  143. package/src/core/api-server.ts +277 -0
  144. package/src/core/audio.ts +98 -0
  145. package/src/core/context-discovery.ts +85 -0
  146. package/src/core/context-refs.ts +140 -0
  147. package/src/core/gateway.ts +106 -0
  148. package/src/core/heartbeat.ts +51 -0
  149. package/src/core/hooks.ts +105 -0
  150. package/src/core/ide-bridge.ts +133 -0
  151. package/src/core/node-network.ts +86 -0
  152. package/src/core/profiles.ts +122 -0
  153. package/src/core/sandbox.ts +100 -0
  154. package/src/core/session-manager.ts +137 -0
  155. package/src/core/vision.ts +180 -0
  156. package/src/hub/brain-seed.ts +54 -0
  157. package/src/hub/client.ts +60 -0
  158. package/src/index.ts +86 -1
  159. package/src/memory/context-compressor.ts +189 -0
  160. package/src/memory/index.ts +4 -0
  161. package/src/memory/user-profiler.ts +215 -0
  162. package/src/providers/index.ts +64 -1
  163. package/src/scheduler/cron-engine.ts +191 -0
  164. package/src/scheduler/index.ts +2 -0
  165. package/src/security/approvals.ts +143 -0
  166. package/src/security/elevated.ts +105 -0
  167. package/src/security/index.ts +6 -0
  168. package/src/security/secrets.ts +129 -0
  169. package/src/skills/builtin/index.ts +408 -0
  170. package/src/skills/marketplace.ts +113 -0
  171. package/src/skills/types.ts +42 -0
  172. package/src/studio/server.ts +1591 -791
  173. package/src/studio/templates-data.ts +178 -0
  174. package/src/studio-ui/index.html +2502 -1073
  175. package/src/tools/builtin/browser.ts +299 -0
  176. package/src/tools/builtin/home-assistant.ts +116 -0
  177. package/src/tools/builtin/index.ts +37 -28
  178. package/src/tools/builtin/rl-tools.ts +243 -0
  179. package/src/tools/builtin/vision.ts +64 -0
  180. package/src/tools/builtin/web-search.ts +126 -0
  181. package/src/tools/document-processor.ts +213 -0
  182. package/src/tools/image-generator.ts +150 -0
  183. package/src/tools/web-scraper.ts +179 -0
  184. package/src/tools/web-search.ts +180 -0
  185. package/tests/api-server.test.ts +148 -0
  186. package/tests/approvals.test.ts +89 -0
  187. package/tests/audio.test.ts +40 -0
  188. package/tests/browser.test.ts +179 -0
  189. package/tests/builtin-tools.test.ts +83 -83
  190. package/tests/channels-extra.test.ts +45 -0
  191. package/tests/context-compressor.test.ts +172 -0
  192. package/tests/context-refs.test.ts +121 -0
  193. package/tests/cron-engine.test.ts +101 -0
  194. package/tests/document-processor.test.ts +69 -0
  195. package/tests/e2e-nocode.test.ts +442 -0
  196. package/tests/elevated.test.ts +69 -0
  197. package/tests/gateway.test.ts +63 -71
  198. package/tests/home-assistant.test.ts +40 -0
  199. package/tests/hooks.test.ts +79 -0
  200. package/tests/ide-bridge.test.ts +38 -0
  201. package/tests/image-generator.test.ts +84 -0
  202. package/tests/node-network.test.ts +74 -0
  203. package/tests/profiles.test.ts +61 -0
  204. package/tests/rl-tools.test.ts +93 -0
  205. package/tests/sandbox-manager.test.ts +46 -0
  206. package/tests/secrets.test.ts +107 -0
  207. package/tests/settings-api.test.ts +148 -0
  208. package/tests/setup.test.ts +73 -0
  209. package/tests/studio.test.ts +402 -229
  210. package/tests/tools/builtin-extended.test.ts +138 -138
  211. package/tests/user-profiler.test.ts +169 -0
  212. package/tests/v090-features.test.ts +254 -0
  213. package/tests/vision.test.ts +61 -0
  214. package/tests/voice-call.test.ts +47 -0
  215. package/tests/voice-interaction.test.ts +38 -0
  216. package/tests/web-search.test.ts +155 -0
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ContextRefResolver = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const child_process_1 = require("child_process");
40
+ const MAX_CONTENT_LENGTH = 5000;
41
+ function truncate(text, max = MAX_CONTENT_LENGTH) {
42
+ if (text.length <= max)
43
+ return text;
44
+ return text.slice(0, max) + `\n...[truncated, ${text.length - max} chars omitted]`;
45
+ }
46
+ class ContextRefResolver {
47
+ /**
48
+ * Parse @-references from text without resolving content.
49
+ */
50
+ parseRefs(text) {
51
+ const refs = [];
52
+ const patterns = [
53
+ [/@file:(\S+)/g, 'file', (m) => m[1]],
54
+ [/@folder:(\S+)/g, 'folder', (m) => m[1]],
55
+ [/@url:(https?:\/\/\S+)/g, 'url', (m) => m[1]],
56
+ [/@git-diff\b/g, 'git-diff', () => 'git-diff'],
57
+ [/@git-log:(\d+)/g, 'git-log', (m) => m[1]],
58
+ [/@git-log\b(?!:)/g, 'git-log', () => '10'],
59
+ ];
60
+ for (const [regex, type, extract] of patterns) {
61
+ let match;
62
+ while ((match = regex.exec(text)) !== null) {
63
+ refs.push({ type, path: extract(match) });
64
+ }
65
+ }
66
+ return refs;
67
+ }
68
+ /**
69
+ * Resolve content for each ref. Returns new array with content filled in.
70
+ */
71
+ async resolveRefs(refs) {
72
+ return Promise.all(refs.map(async (ref) => {
73
+ try {
74
+ const content = await this.resolveOne(ref);
75
+ return { ...ref, content: truncate(content) };
76
+ }
77
+ catch (err) {
78
+ const msg = err instanceof Error ? err.message : String(err);
79
+ return { ...ref, content: `[Error resolving @${ref.type}:${ref.path}]: ${msg}` };
80
+ }
81
+ }));
82
+ }
83
+ async resolveOne(ref) {
84
+ switch (ref.type) {
85
+ case 'file':
86
+ return fs.readFileSync(ref.path, 'utf-8');
87
+ case 'folder':
88
+ return this.listDir(ref.path);
89
+ case 'url':
90
+ return await this.fetchUrl(ref.path);
91
+ case 'git-diff':
92
+ return (0, child_process_1.execSync)('git diff', { encoding: 'utf-8', timeout: 10000 });
93
+ case 'git-log': {
94
+ const n = parseInt(ref.path) || 10;
95
+ return (0, child_process_1.execSync)(`git log --oneline -${n}`, { encoding: 'utf-8', timeout: 10000 });
96
+ }
97
+ default:
98
+ return `[Unknown ref type: ${ref.type}]`;
99
+ }
100
+ }
101
+ listDir(dirPath, prefix = '', depth = 0) {
102
+ if (depth > 5)
103
+ return prefix + '...(max depth)\n';
104
+ if (!fs.existsSync(dirPath))
105
+ throw new Error(`Directory not found: ${dirPath}`);
106
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
107
+ let result = '';
108
+ for (const entry of entries) {
109
+ if (entry.name.startsWith('.') || entry.name === 'node_modules')
110
+ continue;
111
+ result += `${prefix}${entry.isDirectory() ? '📁 ' : '📄 '}${entry.name}\n`;
112
+ if (entry.isDirectory()) {
113
+ result += this.listDir(path.join(dirPath, entry.name), prefix + ' ', depth + 1);
114
+ }
115
+ }
116
+ return result;
117
+ }
118
+ async fetchUrl(url) {
119
+ const controller = new AbortController();
120
+ const timeout = setTimeout(() => controller.abort(), 10000);
121
+ try {
122
+ const res = await fetch(url, { signal: controller.signal });
123
+ const text = await res.text();
124
+ return text;
125
+ }
126
+ finally {
127
+ clearTimeout(timeout);
128
+ }
129
+ }
130
+ /**
131
+ * Inject resolved refs as system messages before the user's last message.
132
+ */
133
+ injectRefs(messages, refs) {
134
+ if (refs.length === 0)
135
+ return messages;
136
+ const resolvedRefs = refs.filter(r => r.content);
137
+ if (resolvedRefs.length === 0)
138
+ return messages;
139
+ const contextMessages = resolvedRefs.map(ref => ({
140
+ role: 'system',
141
+ content: `[Context from @${ref.type}:${ref.path}]\n\`\`\`\n${ref.content}\n\`\`\``,
142
+ }));
143
+ // Insert before the last user message
144
+ const result = [...messages];
145
+ let lastUserIdx = -1;
146
+ for (let i = result.length - 1; i >= 0; i--) {
147
+ if (result[i].role === 'user') {
148
+ lastUserIdx = i;
149
+ break;
150
+ }
151
+ }
152
+ if (lastUserIdx >= 0) {
153
+ result.splice(lastUserIdx, 0, ...contextMessages);
154
+ }
155
+ else {
156
+ result.push(...contextMessages);
157
+ }
158
+ return result;
159
+ }
160
+ }
161
+ exports.ContextRefResolver = ContextRefResolver;
162
+ //# sourceMappingURL=context-refs.js.map
@@ -0,0 +1,53 @@
1
+ import { EventEmitter } from 'events';
2
+ export interface AgentConfig {
3
+ id: string;
4
+ name: string;
5
+ model?: string;
6
+ skills?: string[];
7
+ }
8
+ export interface ChannelConfig {
9
+ id: string;
10
+ type: string;
11
+ config?: Record<string, unknown>;
12
+ }
13
+ export interface GatewayConfig {
14
+ port: number;
15
+ agents: AgentConfig[];
16
+ channels: ChannelConfig[];
17
+ }
18
+ interface GatewayMessage {
19
+ id: string;
20
+ content: string;
21
+ channel: string;
22
+ timestamp: number;
23
+ }
24
+ export declare class Gateway extends EventEmitter {
25
+ private config;
26
+ private agents;
27
+ private channels;
28
+ private running;
29
+ private startTime;
30
+ private messagesProcessed;
31
+ private latencies;
32
+ private errors;
33
+ constructor(config: GatewayConfig);
34
+ start(): Promise<void>;
35
+ stop(): Promise<void>;
36
+ routeMessage(message: GatewayMessage, channel: string): Promise<string>;
37
+ addAgent(config: AgentConfig): void;
38
+ removeAgent(id: string): void;
39
+ addChannel(config: ChannelConfig): void;
40
+ getStatus(): {
41
+ uptime: number;
42
+ agents: number;
43
+ channels: number;
44
+ messagesProcessed: number;
45
+ };
46
+ getMetrics(): {
47
+ messagesPerMinute: number;
48
+ avgLatency: number;
49
+ errorRate: number;
50
+ };
51
+ }
52
+ export {};
53
+ //# sourceMappingURL=gateway.d.ts.map
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Gateway = void 0;
4
+ const events_1 = require("events");
5
+ class Gateway extends events_1.EventEmitter {
6
+ config;
7
+ agents = new Map();
8
+ channels = new Map();
9
+ running = false;
10
+ startTime = 0;
11
+ messagesProcessed = 0;
12
+ latencies = [];
13
+ errors = 0;
14
+ constructor(config) {
15
+ super();
16
+ this.config = config;
17
+ for (const a of config.agents)
18
+ this.agents.set(a.id, a);
19
+ for (const c of config.channels)
20
+ this.channels.set(c.id, c);
21
+ }
22
+ async start() {
23
+ if (this.running)
24
+ throw new Error('Gateway already running');
25
+ this.running = true;
26
+ this.startTime = Date.now();
27
+ this.emit('started');
28
+ }
29
+ async stop() {
30
+ if (!this.running)
31
+ throw new Error('Gateway not running');
32
+ this.running = false;
33
+ this.emit('stopped');
34
+ }
35
+ async routeMessage(message, channel) {
36
+ if (!this.running)
37
+ throw new Error('Gateway not running');
38
+ const start = Date.now();
39
+ this.messagesProcessed++;
40
+ // Simple round-robin routing
41
+ const agentIds = Array.from(this.agents.keys());
42
+ if (agentIds.length === 0) {
43
+ this.errors++;
44
+ throw new Error('No agents available');
45
+ }
46
+ const agentId = agentIds[this.messagesProcessed % agentIds.length];
47
+ this.latencies.push(Date.now() - start);
48
+ return agentId;
49
+ }
50
+ addAgent(config) {
51
+ this.agents.set(config.id, config);
52
+ }
53
+ removeAgent(id) {
54
+ if (!this.agents.has(id))
55
+ throw new Error(`Agent ${id} not found`);
56
+ this.agents.delete(id);
57
+ }
58
+ addChannel(config) {
59
+ this.channels.set(config.id, config);
60
+ }
61
+ getStatus() {
62
+ return {
63
+ uptime: this.running ? Date.now() - this.startTime : 0,
64
+ agents: this.agents.size,
65
+ channels: this.channels.size,
66
+ messagesProcessed: this.messagesProcessed,
67
+ };
68
+ }
69
+ getMetrics() {
70
+ const upMinutes = this.running ? (Date.now() - this.startTime) / 60000 : 1;
71
+ const avgLatency = this.latencies.length ? this.latencies.reduce((a, b) => a + b, 0) / this.latencies.length : 0;
72
+ return {
73
+ messagesPerMinute: this.messagesProcessed / Math.max(upMinutes, 0.001),
74
+ avgLatency,
75
+ errorRate: this.messagesProcessed ? this.errors / this.messagesProcessed : 0,
76
+ };
77
+ }
78
+ }
79
+ exports.Gateway = Gateway;
80
+ //# sourceMappingURL=gateway.js.map
@@ -0,0 +1,19 @@
1
+ export interface HeartbeatConfig {
2
+ interval: number;
3
+ checkFn: () => Promise<string>;
4
+ }
5
+ export declare class HeartbeatManager {
6
+ private config;
7
+ private timer;
8
+ private callbacks;
9
+ private lastBeat;
10
+ constructor(config: HeartbeatConfig);
11
+ start(): void;
12
+ stop(): void;
13
+ onBeat(callback: (status: string) => void): void;
14
+ getLastBeat(): {
15
+ timestamp: number;
16
+ status: string;
17
+ } | null;
18
+ }
19
+ //# sourceMappingURL=heartbeat.d.ts.map
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HeartbeatManager = void 0;
4
+ class HeartbeatManager {
5
+ config;
6
+ timer = null;
7
+ callbacks = [];
8
+ lastBeat = null;
9
+ constructor(config) {
10
+ if (!config.interval || config.interval < 100) {
11
+ throw new Error('HeartbeatManager requires interval >= 100ms');
12
+ }
13
+ if (typeof config.checkFn !== 'function') {
14
+ throw new Error('HeartbeatManager requires checkFn');
15
+ }
16
+ this.config = config;
17
+ }
18
+ start() {
19
+ if (this.timer)
20
+ return;
21
+ this.timer = setInterval(async () => {
22
+ try {
23
+ const status = await this.config.checkFn();
24
+ this.lastBeat = { timestamp: Date.now(), status };
25
+ for (const cb of this.callbacks)
26
+ cb(status);
27
+ }
28
+ catch (err) {
29
+ const status = `error: ${err.message}`;
30
+ this.lastBeat = { timestamp: Date.now(), status };
31
+ for (const cb of this.callbacks)
32
+ cb(status);
33
+ }
34
+ }, this.config.interval);
35
+ }
36
+ stop() {
37
+ if (this.timer) {
38
+ clearInterval(this.timer);
39
+ this.timer = null;
40
+ }
41
+ }
42
+ onBeat(callback) {
43
+ this.callbacks.push(callback);
44
+ }
45
+ getLastBeat() {
46
+ return this.lastBeat;
47
+ }
48
+ }
49
+ exports.HeartbeatManager = HeartbeatManager;
50
+ //# sourceMappingURL=heartbeat.js.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Hooks Module - v1.0.0
3
+ * Event hook system with priority ordering and context modification.
4
+ */
5
+ export type HookEvent = 'before:message' | 'after:message' | 'before:tool' | 'after:tool' | 'before:llm' | 'after:llm' | 'before:send' | 'after:send' | 'before:learn' | 'after:learn' | 'before:recall' | 'after:recall' | 'on:error' | 'on:start' | 'on:stop';
6
+ export declare const ALL_HOOK_EVENTS: HookEvent[];
7
+ export interface HookContext {
8
+ [key: string]: unknown;
9
+ }
10
+ export type HookHandler = (ctx: HookContext) => HookContext | void | Promise<HookContext | void>;
11
+ export declare class HookManager {
12
+ private hooks;
13
+ register(event: HookEvent, handler: HookHandler, options?: {
14
+ priority?: number;
15
+ name?: string;
16
+ }): string;
17
+ unregister(id: string): boolean;
18
+ run(event: HookEvent, ctx?: HookContext): Promise<HookContext>;
19
+ getRegistered(event?: HookEvent): {
20
+ id: string;
21
+ event: HookEvent;
22
+ priority: number;
23
+ name?: string;
24
+ }[];
25
+ clear(event?: HookEvent): void;
26
+ hasHooks(event: HookEvent): boolean;
27
+ }
28
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * Hooks Module - v1.0.0
4
+ * Event hook system with priority ordering and context modification.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.HookManager = exports.ALL_HOOK_EVENTS = void 0;
8
+ exports.ALL_HOOK_EVENTS = [
9
+ 'before:message', 'after:message',
10
+ 'before:tool', 'after:tool',
11
+ 'before:llm', 'after:llm',
12
+ 'before:send', 'after:send',
13
+ 'before:learn', 'after:learn',
14
+ 'before:recall', 'after:recall',
15
+ 'on:error', 'on:start', 'on:stop',
16
+ ];
17
+ let hookIdCounter = 0;
18
+ class HookManager {
19
+ hooks = new Map();
20
+ register(event, handler, options) {
21
+ const id = `hook_${++hookIdCounter}`;
22
+ const entry = {
23
+ id,
24
+ event,
25
+ handler,
26
+ priority: options?.priority ?? 100,
27
+ name: options?.name,
28
+ };
29
+ if (!this.hooks.has(event))
30
+ this.hooks.set(event, []);
31
+ const list = this.hooks.get(event);
32
+ list.push(entry);
33
+ list.sort((a, b) => a.priority - b.priority);
34
+ return id;
35
+ }
36
+ unregister(id) {
37
+ for (const [event, list] of this.hooks) {
38
+ const idx = list.findIndex(h => h.id === id);
39
+ if (idx !== -1) {
40
+ list.splice(idx, 1);
41
+ return true;
42
+ }
43
+ }
44
+ return false;
45
+ }
46
+ async run(event, ctx = {}) {
47
+ const list = this.hooks.get(event);
48
+ if (!list || list.length === 0)
49
+ return ctx;
50
+ let current = { ...ctx };
51
+ for (const hook of list) {
52
+ const result = await hook.handler(current);
53
+ if (result)
54
+ current = { ...current, ...result };
55
+ }
56
+ return current;
57
+ }
58
+ getRegistered(event) {
59
+ const results = [];
60
+ const events = event ? [event] : exports.ALL_HOOK_EVENTS;
61
+ for (const e of events) {
62
+ const list = this.hooks.get(e) ?? [];
63
+ for (const h of list) {
64
+ results.push({ id: h.id, event: h.event, priority: h.priority, name: h.name });
65
+ }
66
+ }
67
+ return results;
68
+ }
69
+ clear(event) {
70
+ if (event) {
71
+ this.hooks.delete(event);
72
+ }
73
+ else {
74
+ this.hooks.clear();
75
+ }
76
+ }
77
+ hasHooks(event) {
78
+ return (this.hooks.get(event)?.length ?? 0) > 0;
79
+ }
80
+ }
81
+ exports.HookManager = HookManager;
82
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1,53 @@
1
+ export interface IDEConfig {
2
+ editor: 'vscode' | 'jetbrains' | 'zed' | 'cursor';
3
+ workspacePath?: string;
4
+ }
5
+ export interface Diagnostic {
6
+ path: string;
7
+ line: number;
8
+ column: number;
9
+ severity: 'error' | 'warning' | 'info';
10
+ message: string;
11
+ }
12
+ export interface TextEdit {
13
+ range: Range;
14
+ newText: string;
15
+ }
16
+ export interface Range {
17
+ startLine: number;
18
+ startColumn: number;
19
+ endLine: number;
20
+ endColumn: number;
21
+ }
22
+ export interface SearchOptions {
23
+ caseSensitive?: boolean;
24
+ regex?: boolean;
25
+ include?: string;
26
+ exclude?: string;
27
+ maxResults?: number;
28
+ }
29
+ export interface SearchResult {
30
+ path: string;
31
+ line: number;
32
+ column: number;
33
+ text: string;
34
+ }
35
+ export declare class IDEBridge {
36
+ private config;
37
+ constructor(config: IDEConfig);
38
+ private getCliCommand;
39
+ private exec;
40
+ openFile(path: string, line?: number): Promise<void>;
41
+ getDiagnostics(path?: string): Promise<Diagnostic[]>;
42
+ runCommand(command: string): Promise<string>;
43
+ getOpenFiles(): Promise<string[]>;
44
+ applyEdit(path: string, edits: TextEdit[]): Promise<void>;
45
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
46
+ getSelection(): Promise<{
47
+ path: string;
48
+ text: string;
49
+ range: Range;
50
+ } | null>;
51
+ installExtension(extensionId: string): Promise<void>;
52
+ }
53
+ //# sourceMappingURL=ide-bridge.d.ts.map
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IDEBridge = void 0;
4
+ const child_process_1 = require("child_process");
5
+ class IDEBridge {
6
+ config;
7
+ constructor(config) {
8
+ this.config = config;
9
+ }
10
+ getCliCommand() {
11
+ switch (this.config.editor) {
12
+ case 'vscode':
13
+ case 'cursor': return this.config.editor === 'cursor' ? 'cursor' : 'code';
14
+ case 'jetbrains': return 'idea';
15
+ case 'zed': return 'zed';
16
+ }
17
+ }
18
+ exec(cmd) {
19
+ try {
20
+ return (0, child_process_1.execSync)(cmd, { encoding: 'utf-8', timeout: 10000, cwd: this.config.workspacePath }).trim();
21
+ }
22
+ catch (e) {
23
+ throw new Error(`IDE command failed: ${e.message}`);
24
+ }
25
+ }
26
+ async openFile(path, line) {
27
+ const cli = this.getCliCommand();
28
+ const target = line ? `${path}:${line}` : path;
29
+ if (this.config.editor === 'vscode' || this.config.editor === 'cursor') {
30
+ this.exec(`${cli} --goto "${target}"`);
31
+ }
32
+ else if (this.config.editor === 'zed') {
33
+ this.exec(`zed "${target}"`);
34
+ }
35
+ else {
36
+ this.exec(`${cli} --line ${line || 1} "${path}"`);
37
+ }
38
+ }
39
+ async getDiagnostics(path) {
40
+ // VS Code doesn't expose diagnostics via CLI; return empty as stub
41
+ return [];
42
+ }
43
+ async runCommand(command) {
44
+ const cli = this.getCliCommand();
45
+ if (this.config.editor === 'vscode' || this.config.editor === 'cursor') {
46
+ return this.exec(`${cli} --command "${command}"`);
47
+ }
48
+ throw new Error(`runCommand not supported for ${this.config.editor}`);
49
+ }
50
+ async getOpenFiles() {
51
+ // Stub — no standard CLI to get open files
52
+ return [];
53
+ }
54
+ async applyEdit(path, edits) {
55
+ // Stub — would use editor's API/extension
56
+ if (edits.length === 0)
57
+ return;
58
+ throw new Error('applyEdit requires an IDE extension to be installed. Use file system edits as fallback.');
59
+ }
60
+ async search(query, options) {
61
+ const cli = this.getCliCommand();
62
+ if (this.config.editor === 'vscode' || this.config.editor === 'cursor') {
63
+ try {
64
+ const args = [`--search "${query}"`];
65
+ if (options?.include)
66
+ args.push(`--include "${options.include}"`);
67
+ const output = this.exec(`${cli} ${args.join(' ')}`);
68
+ // Parse output lines
69
+ return output.split('\n').filter(Boolean).map(line => {
70
+ const match = line.match(/^(.+):(\d+):(\d+):(.*)$/);
71
+ if (!match)
72
+ return { path: '', line: 0, column: 0, text: line };
73
+ return { path: match[1], line: parseInt(match[2]), column: parseInt(match[3]), text: match[4] };
74
+ });
75
+ }
76
+ catch {
77
+ return [];
78
+ }
79
+ }
80
+ return [];
81
+ }
82
+ async getSelection() {
83
+ // Stub — requires editor extension
84
+ return null;
85
+ }
86
+ async installExtension(extensionId) {
87
+ const cli = this.getCliCommand();
88
+ if (this.config.editor === 'vscode' || this.config.editor === 'cursor') {
89
+ this.exec(`${cli} --install-extension ${extensionId}`);
90
+ }
91
+ else {
92
+ throw new Error(`installExtension not supported for ${this.config.editor}`);
93
+ }
94
+ }
95
+ }
96
+ exports.IDEBridge = IDEBridge;
97
+ //# sourceMappingURL=ide-bridge.js.map
@@ -0,0 +1,23 @@
1
+ import { EventEmitter } from 'events';
2
+ export interface RemoteNode {
3
+ id: string;
4
+ name: string;
5
+ host: string;
6
+ port: number;
7
+ type: 'vps' | 'pi' | 'phone' | 'desktop';
8
+ status: 'online' | 'offline' | 'pairing';
9
+ capabilities: string[];
10
+ lastSeen: number;
11
+ }
12
+ export declare class NodeNetwork extends EventEmitter {
13
+ private nodes;
14
+ addNode(config: Partial<RemoteNode>): RemoteNode;
15
+ removeNode(id: string): void;
16
+ listNodes(): RemoteNode[];
17
+ getNode(id: string): RemoteNode | null;
18
+ pair(nodeId: string, pairingCode: string): Promise<boolean>;
19
+ sendCommand(nodeId: string, command: string): Promise<any>;
20
+ broadcast(command: string): Promise<Map<string, any>>;
21
+ healthCheck(): Promise<Map<string, boolean>>;
22
+ }
23
+ //# sourceMappingURL=node-network.d.ts.map