@tyvm/knowhow 0.0.104 → 0.0.106

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 (233) hide show
  1. package/CONFIG.md +8 -5
  2. package/package.json +3 -2
  3. package/scripts/check-model-pricing.ts +509 -0
  4. package/scripts/compare-openrouter-coverage.ts +576 -0
  5. package/src/agents/base/base.ts +127 -2
  6. package/src/agents/tools/execCommand.ts +4 -0
  7. package/src/agents/tools/executeScript/definition.ts +1 -1
  8. package/src/agents/tools/index.ts +0 -1
  9. package/src/agents/tools/list.ts +3 -43
  10. package/src/agents/tools/writeFile.ts +1 -1
  11. package/src/auth/browserLogin.ts +9 -4
  12. package/src/chat/modules/RemoteSyncModule.ts +3 -0
  13. package/src/cli.ts +31 -1
  14. package/src/clients/cerebras.ts +10 -0
  15. package/src/clients/contextLimits.ts +7 -2
  16. package/src/clients/copilot.ts +23 -0
  17. package/src/clients/deepseek.ts +16 -0
  18. package/src/clients/fireworks.ts +15 -0
  19. package/src/clients/gemini.ts +45 -2
  20. package/src/clients/github.ts +16 -0
  21. package/src/clients/groq.ts +15 -0
  22. package/src/clients/http.ts +190 -6
  23. package/src/clients/index.ts +215 -9
  24. package/src/clients/llama.ts +16 -0
  25. package/src/clients/mistral.ts +16 -0
  26. package/src/clients/nvidia.ts +16 -0
  27. package/src/clients/openai.ts +41 -11
  28. package/src/clients/openrouter.ts +17 -0
  29. package/src/clients/pricing/anthropic.ts +105 -78
  30. package/src/clients/pricing/cerebras.ts +11 -0
  31. package/src/clients/pricing/copilot.ts +60 -0
  32. package/src/clients/pricing/deepseek.ts +15 -0
  33. package/src/clients/pricing/fireworks.ts +32 -0
  34. package/src/clients/pricing/github.ts +69 -0
  35. package/src/clients/pricing/google.ts +245 -206
  36. package/src/clients/pricing/groq.ts +56 -0
  37. package/src/clients/pricing/index.ts +43 -6
  38. package/src/clients/pricing/llama.ts +18 -0
  39. package/src/clients/pricing/mistral.ts +34 -0
  40. package/src/clients/pricing/models.ts +23 -0
  41. package/src/clients/pricing/nvidia.ts +102 -0
  42. package/src/clients/pricing/openai.ts +347 -171
  43. package/src/clients/pricing/openrouter.ts +36 -0
  44. package/src/clients/pricing/types.ts +110 -0
  45. package/src/clients/pricing/xai.ts +123 -66
  46. package/src/clients/types.ts +4 -0
  47. package/src/clients/xai.ts +152 -2
  48. package/src/fileSync.ts +8 -2
  49. package/src/login.ts +11 -3
  50. package/src/services/AgentSyncFs.ts +36 -12
  51. package/src/services/KnowhowClient.ts +11 -0
  52. package/src/services/LazyToolsService.ts +6 -0
  53. package/src/services/S3.ts +0 -7
  54. package/src/services/SyncedAgentWatcher.ts +13 -298
  55. package/src/services/index.ts +1 -0
  56. package/src/services/modules/index.ts +11 -2
  57. package/src/services/watchers/FsSyncer.ts +155 -0
  58. package/src/services/watchers/RemoteSyncer.ts +153 -0
  59. package/src/services/watchers/index.ts +2 -0
  60. package/src/types.ts +56 -279
  61. package/src/worker.ts +174 -0
  62. package/tests/clients/pricing.test.ts +37 -0
  63. package/tests/manual/clients/completions.json +838 -226
  64. package/tests/manual/clients/completions.test.ts +46 -31
  65. package/ts_build/package.json +3 -2
  66. package/ts_build/src/agents/base/base.d.ts +17 -1
  67. package/ts_build/src/agents/base/base.js +82 -1
  68. package/ts_build/src/agents/base/base.js.map +1 -1
  69. package/ts_build/src/agents/tools/execCommand.js +3 -0
  70. package/ts_build/src/agents/tools/execCommand.js.map +1 -1
  71. package/ts_build/src/agents/tools/executeScript/definition.js +1 -1
  72. package/ts_build/src/agents/tools/executeScript/definition.js.map +1 -1
  73. package/ts_build/src/agents/tools/index.d.ts +0 -1
  74. package/ts_build/src/agents/tools/index.js +0 -1
  75. package/ts_build/src/agents/tools/index.js.map +1 -1
  76. package/ts_build/src/agents/tools/list.js +3 -38
  77. package/ts_build/src/agents/tools/list.js.map +1 -1
  78. package/ts_build/src/agents/tools/visionTool.d.ts +1 -1
  79. package/ts_build/src/agents/tools/writeFile.js +1 -1
  80. package/ts_build/src/agents/tools/writeFile.js.map +1 -1
  81. package/ts_build/src/ai.d.ts +1 -1
  82. package/ts_build/src/auth/browserLogin.d.ts +2 -1
  83. package/ts_build/src/auth/browserLogin.js +10 -3
  84. package/ts_build/src/auth/browserLogin.js.map +1 -1
  85. package/ts_build/src/chat/modules/RemoteSyncModule.js +1 -0
  86. package/ts_build/src/chat/modules/RemoteSyncModule.js.map +1 -1
  87. package/ts_build/src/cli.js +19 -0
  88. package/ts_build/src/cli.js.map +1 -1
  89. package/ts_build/src/clients/anthropic.d.ts +1 -82
  90. package/ts_build/src/clients/cerebras.d.ts +4 -0
  91. package/ts_build/src/clients/cerebras.js +14 -0
  92. package/ts_build/src/clients/cerebras.js.map +1 -0
  93. package/ts_build/src/clients/contextLimits.js +7 -2
  94. package/ts_build/src/clients/contextLimits.js.map +1 -1
  95. package/ts_build/src/clients/copilot.d.ts +4 -0
  96. package/ts_build/src/clients/copilot.js +15 -0
  97. package/ts_build/src/clients/copilot.js.map +1 -0
  98. package/ts_build/src/clients/deepseek.d.ts +4 -0
  99. package/ts_build/src/clients/deepseek.js +15 -0
  100. package/ts_build/src/clients/deepseek.js.map +1 -0
  101. package/ts_build/src/clients/fireworks.d.ts +4 -0
  102. package/ts_build/src/clients/fireworks.js +15 -0
  103. package/ts_build/src/clients/fireworks.js.map +1 -0
  104. package/ts_build/src/clients/gemini.d.ts +1 -0
  105. package/ts_build/src/clients/gemini.js +28 -1
  106. package/ts_build/src/clients/gemini.js.map +1 -1
  107. package/ts_build/src/clients/github.d.ts +4 -0
  108. package/ts_build/src/clients/github.js +15 -0
  109. package/ts_build/src/clients/github.js.map +1 -0
  110. package/ts_build/src/clients/groq.d.ts +4 -0
  111. package/ts_build/src/clients/groq.js +15 -0
  112. package/ts_build/src/clients/groq.js.map +1 -0
  113. package/ts_build/src/clients/http.d.ts +22 -1
  114. package/ts_build/src/clients/http.js +132 -7
  115. package/ts_build/src/clients/http.js.map +1 -1
  116. package/ts_build/src/clients/index.d.ts +22 -0
  117. package/ts_build/src/clients/index.js +150 -5
  118. package/ts_build/src/clients/index.js.map +1 -1
  119. package/ts_build/src/clients/llama.d.ts +4 -0
  120. package/ts_build/src/clients/llama.js +15 -0
  121. package/ts_build/src/clients/llama.js.map +1 -0
  122. package/ts_build/src/clients/mistral.d.ts +4 -0
  123. package/ts_build/src/clients/mistral.js +15 -0
  124. package/ts_build/src/clients/mistral.js.map +1 -0
  125. package/ts_build/src/clients/nvidia.d.ts +4 -0
  126. package/ts_build/src/clients/nvidia.js +15 -0
  127. package/ts_build/src/clients/nvidia.js.map +1 -0
  128. package/ts_build/src/clients/openai.d.ts +4 -206
  129. package/ts_build/src/clients/openai.js +27 -9
  130. package/ts_build/src/clients/openai.js.map +1 -1
  131. package/ts_build/src/clients/openrouter.d.ts +4 -0
  132. package/ts_build/src/clients/openrouter.js +15 -0
  133. package/ts_build/src/clients/openrouter.js.map +1 -0
  134. package/ts_build/src/clients/pricing/anthropic.d.ts +26 -78
  135. package/ts_build/src/clients/pricing/anthropic.js +75 -78
  136. package/ts_build/src/clients/pricing/anthropic.js.map +1 -1
  137. package/ts_build/src/clients/pricing/cerebras.d.ts +4 -0
  138. package/ts_build/src/clients/pricing/cerebras.js +11 -0
  139. package/ts_build/src/clients/pricing/cerebras.js.map +1 -0
  140. package/ts_build/src/clients/pricing/copilot.d.ts +5 -0
  141. package/ts_build/src/clients/pricing/copilot.js +35 -0
  142. package/ts_build/src/clients/pricing/copilot.js.map +1 -0
  143. package/ts_build/src/clients/pricing/deepseek.d.ts +5 -0
  144. package/ts_build/src/clients/pricing/deepseek.js +10 -0
  145. package/ts_build/src/clients/pricing/deepseek.js.map +1 -0
  146. package/ts_build/src/clients/pricing/fireworks.d.ts +5 -0
  147. package/ts_build/src/clients/pricing/fireworks.js +21 -0
  148. package/ts_build/src/clients/pricing/fireworks.js.map +1 -0
  149. package/ts_build/src/clients/pricing/github.d.ts +4 -0
  150. package/ts_build/src/clients/pricing/github.js +58 -0
  151. package/ts_build/src/clients/pricing/github.js.map +1 -0
  152. package/ts_build/src/clients/pricing/google.d.ts +59 -6
  153. package/ts_build/src/clients/pricing/google.js +214 -167
  154. package/ts_build/src/clients/pricing/google.js.map +1 -1
  155. package/ts_build/src/clients/pricing/groq.d.ts +5 -0
  156. package/ts_build/src/clients/pricing/groq.js +41 -0
  157. package/ts_build/src/clients/pricing/groq.js.map +1 -0
  158. package/ts_build/src/clients/pricing/index.d.ts +17 -6
  159. package/ts_build/src/clients/pricing/index.js +65 -10
  160. package/ts_build/src/clients/pricing/index.js.map +1 -1
  161. package/ts_build/src/clients/pricing/llama.d.ts +4 -0
  162. package/ts_build/src/clients/pricing/llama.js +14 -0
  163. package/ts_build/src/clients/pricing/llama.js.map +1 -0
  164. package/ts_build/src/clients/pricing/mistral.d.ts +5 -0
  165. package/ts_build/src/clients/pricing/mistral.js +23 -0
  166. package/ts_build/src/clients/pricing/mistral.js.map +1 -0
  167. package/ts_build/src/clients/pricing/models.d.ts +9 -0
  168. package/ts_build/src/clients/pricing/models.js +19 -0
  169. package/ts_build/src/clients/pricing/models.js.map +1 -0
  170. package/ts_build/src/clients/pricing/nvidia.d.ts +8 -0
  171. package/ts_build/src/clients/pricing/nvidia.js +96 -0
  172. package/ts_build/src/clients/pricing/nvidia.js.map +1 -0
  173. package/ts_build/src/clients/pricing/openai.d.ts +86 -197
  174. package/ts_build/src/clients/pricing/openai.js +294 -168
  175. package/ts_build/src/clients/pricing/openai.js.map +1 -1
  176. package/ts_build/src/clients/pricing/openrouter.d.ts +4 -0
  177. package/ts_build/src/clients/pricing/openrouter.js +29 -0
  178. package/ts_build/src/clients/pricing/openrouter.js.map +1 -0
  179. package/ts_build/src/clients/pricing/types.d.ts +46 -0
  180. package/ts_build/src/clients/pricing/types.js +49 -0
  181. package/ts_build/src/clients/pricing/types.js.map +1 -0
  182. package/ts_build/src/clients/pricing/xai.d.ts +39 -64
  183. package/ts_build/src/clients/pricing/xai.js +93 -60
  184. package/ts_build/src/clients/pricing/xai.js.map +1 -1
  185. package/ts_build/src/clients/types.d.ts +1 -0
  186. package/ts_build/src/clients/xai.d.ts +2 -58
  187. package/ts_build/src/clients/xai.js +123 -2
  188. package/ts_build/src/clients/xai.js.map +1 -1
  189. package/ts_build/src/fileSync.js +7 -2
  190. package/ts_build/src/fileSync.js.map +1 -1
  191. package/ts_build/src/login.js +8 -2
  192. package/ts_build/src/login.js.map +1 -1
  193. package/ts_build/src/services/AgentSyncFs.js +1 -0
  194. package/ts_build/src/services/AgentSyncFs.js.map +1 -1
  195. package/ts_build/src/services/KnowhowClient.d.ts +1 -0
  196. package/ts_build/src/services/KnowhowClient.js +7 -0
  197. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  198. package/ts_build/src/services/LazyToolsService.d.ts +1 -0
  199. package/ts_build/src/services/LazyToolsService.js +3 -0
  200. package/ts_build/src/services/LazyToolsService.js.map +1 -1
  201. package/ts_build/src/services/S3.js +0 -7
  202. package/ts_build/src/services/S3.js.map +1 -1
  203. package/ts_build/src/services/SyncedAgentWatcher.d.ts +0 -51
  204. package/ts_build/src/services/SyncedAgentWatcher.js +1 -282
  205. package/ts_build/src/services/SyncedAgentWatcher.js.map +1 -1
  206. package/ts_build/src/services/index.d.ts +1 -0
  207. package/ts_build/src/services/index.js +1 -0
  208. package/ts_build/src/services/index.js.map +1 -1
  209. package/ts_build/src/services/modules/index.js +41 -1
  210. package/ts_build/src/services/modules/index.js.map +1 -1
  211. package/ts_build/src/services/watchers/FsSyncer.d.ts +27 -0
  212. package/ts_build/src/services/watchers/FsSyncer.js +135 -0
  213. package/ts_build/src/services/watchers/FsSyncer.js.map +1 -0
  214. package/ts_build/src/services/watchers/RemoteSyncer.d.ts +28 -0
  215. package/ts_build/src/services/watchers/RemoteSyncer.js +126 -0
  216. package/ts_build/src/services/watchers/RemoteSyncer.js.map +1 -0
  217. package/ts_build/src/services/watchers/index.d.ts +2 -0
  218. package/ts_build/src/services/watchers/index.js +19 -0
  219. package/ts_build/src/services/watchers/index.js.map +1 -0
  220. package/ts_build/src/types.d.ts +163 -124
  221. package/ts_build/src/types.js +33 -213
  222. package/ts_build/src/types.js.map +1 -1
  223. package/ts_build/src/worker.d.ts +4 -0
  224. package/ts_build/src/worker.js +140 -0
  225. package/ts_build/src/worker.js.map +1 -1
  226. package/ts_build/tests/clients/pricing.test.js +21 -0
  227. package/ts_build/tests/clients/pricing.test.js.map +1 -1
  228. package/ts_build/tests/manual/clients/completions.test.js +27 -24
  229. package/ts_build/tests/manual/clients/completions.test.js.map +1 -1
  230. package/src/clients/pricing/catalog.ts +0 -287
  231. package/ts_build/src/clients/pricing/catalog.d.ts +0 -28
  232. package/ts_build/src/clients/pricing/catalog.js +0 -179
  233. package/ts_build/src/clients/pricing/catalog.js.map +0 -1
@@ -0,0 +1,155 @@
1
+ import fs from "fs";
2
+ import fsPromises from "fs/promises";
3
+ import path from "path";
4
+
5
+ import { SyncedAgentWatcher } from "../SyncedAgentWatcher";
6
+ import { messagesToRenderEvents } from "../../chat/renderer/messagesToRenderEvents";
7
+ import { EventService } from "../EventService";
8
+
9
+ /**
10
+ * Watches an agent running in another process via the filesystem.
11
+ * Reads .knowhow/processes/agents/<taskId>/metadata.json for changes.
12
+ * Sends messages by writing to .knowhow/processes/agents/<taskId>/input.txt
13
+ */
14
+ export class FsSyncedAgentWatcher implements SyncedAgentWatcher {
15
+ public taskId: string = "";
16
+ private taskPath: string = "";
17
+ private watcher: fs.FSWatcher | null = null;
18
+ private lastThreadLength: number = 0;
19
+ public agentName: string = "unknown";
20
+ private debounceTimer: NodeJS.Timeout | null = null;
21
+ public agentEvents = new EventService();
22
+ public eventTypes = {
23
+ done: "done",
24
+ toolCall: "tool:pre_call",
25
+ toolUsed: "tool:post_call",
26
+ agentSay: "agent:say",
27
+ threadUpdate: "thread_update",
28
+ };
29
+
30
+ async startWatching(taskId: string): Promise<void> {
31
+ this.taskId = taskId;
32
+ this.taskPath = path.join(".knowhow/processes/agents", taskId);
33
+
34
+ // Load initial state to track current thread length (for delta rendering)
35
+ const metadata = await this.readMetadata();
36
+ if (metadata) {
37
+ const threads: any[][] = metadata.threads || [];
38
+ const lastThread = threads[threads.length - 1] || [];
39
+ this.agentName = metadata.agentName || taskId;
40
+ this.lastThreadLength = lastThread.length;
41
+ }
42
+
43
+ // Watch the directory for metadata.json changes
44
+ try {
45
+ this.watcher = fs.watch(this.taskPath, (event, filename) => {
46
+ if (filename === "metadata.json" || filename === null) {
47
+ // Debounce rapid file writes
48
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
49
+ this.debounceTimer = setTimeout(() => {
50
+ this.onMetadataChanged().catch(() => {});
51
+ }, 200);
52
+ }
53
+ });
54
+ } catch (err: any) {
55
+ console.warn(`⚠️ Could not watch ${this.taskPath}: ${err.message}`);
56
+ }
57
+
58
+ console.log(`👁️ Watching fs-synced agent: ${taskId} (${this.agentName})`);
59
+ console.log(
60
+ ` Type /logs 20 to see recent messages, or type to send a message`
61
+ );
62
+ }
63
+
64
+ private async onMetadataChanged(): Promise<void> {
65
+ const metadata = await this.readMetadata();
66
+ if (!metadata?.threads) return;
67
+
68
+ const threads: any[][] = metadata.threads;
69
+ const lastThread = threads[threads.length - 1] || [];
70
+
71
+ // Only render NEW messages since last check
72
+ const newMessages = lastThread.slice(this.lastThreadLength);
73
+ if (newMessages.length > 0) {
74
+ const renderEvents = messagesToRenderEvents(
75
+ newMessages,
76
+ this.taskId,
77
+ this.agentName
78
+ );
79
+ for (const event of renderEvents) {
80
+ if (event.type === "toolCall") {
81
+ this.agentEvents.emit(this.eventTypes.toolCall, {
82
+ toolCall: (event as any).toolCall,
83
+ });
84
+ } else if (event.type === "toolResult") {
85
+ this.agentEvents.emit(this.eventTypes.toolUsed, {
86
+ toolCall: (event as any).toolCall,
87
+ functionResp: (event as any).result,
88
+ });
89
+ } else if (event.type === "agentMessage") {
90
+ this.agentEvents.emit(this.eventTypes.agentSay, {
91
+ message: (event as any).message,
92
+ });
93
+ }
94
+ }
95
+ this.agentEvents.emit(this.eventTypes.threadUpdate, lastThread);
96
+ this.lastThreadLength = lastThread.length;
97
+ }
98
+
99
+ // Emit done if the agent has completed and has a result
100
+ const status = metadata.status;
101
+ const result = metadata.result;
102
+ if ((status === "completed" || status === "killed") && result != null) {
103
+ this.stopWatching();
104
+ this.agentEvents.emit(this.eventTypes.done, result);
105
+ }
106
+ }
107
+
108
+ async sendMessage(message: string): Promise<void> {
109
+ const inputPath = path.join(this.taskPath, "input.txt");
110
+ await fsPromises.writeFile(inputPath, message, "utf8");
111
+ }
112
+
113
+ async getThreads(): Promise<any[][]> {
114
+ const metadata = await this.readMetadata();
115
+ return metadata?.threads || [];
116
+ }
117
+
118
+ stopWatching(): void {
119
+ if (this.debounceTimer) {
120
+ clearTimeout(this.debounceTimer);
121
+ this.debounceTimer = null;
122
+ }
123
+ this.watcher?.close();
124
+ this.watcher = null;
125
+ console.log(`🔌 Stopped watching agent: ${this.taskId}`);
126
+ }
127
+
128
+ async pause(): Promise<void> {
129
+ const statusPath = path.join(this.taskPath, "status.txt");
130
+ await fsPromises.writeFile(statusPath, "paused", "utf8");
131
+ console.log(`⏸️ Paused remote agent: ${this.taskId}`);
132
+ }
133
+
134
+ async unpause(): Promise<void> {
135
+ const statusPath = path.join(this.taskPath, "status.txt");
136
+ await fsPromises.writeFile(statusPath, "running", "utf8");
137
+ console.log(`▶️ Unpaused remote agent: ${this.taskId}`);
138
+ }
139
+
140
+ async kill(): Promise<void> {
141
+ const statusPath = path.join(this.taskPath, "status.txt");
142
+ await fsPromises.writeFile(statusPath, "killed", "utf8");
143
+ console.log(`🛑 Killed remote agent: ${this.taskId}`);
144
+ }
145
+
146
+ private async readMetadata(): Promise<any> {
147
+ try {
148
+ const metaPath = path.join(this.taskPath, "metadata.json");
149
+ const content = await fsPromises.readFile(metaPath, "utf8");
150
+ return JSON.parse(content);
151
+ } catch {
152
+ return null;
153
+ }
154
+ }
155
+ }
@@ -0,0 +1,153 @@
1
+ import { Message } from "../../clients/types";
2
+ import { EventService } from "../EventService";
3
+ import * as fs from "fs";
4
+ import * as fsPromises from "fs/promises";
5
+ import * as path from "path";
6
+ import { messagesToRenderEvents } from "../../chat/renderer/messagesToRenderEvents";
7
+ import { KnowhowSimpleClient } from "../KnowhowClient";
8
+ import { SyncedAgentWatcher } from "../SyncedAgentWatcher";
9
+
10
+ /**
11
+ * Watches an agent running on Knowhow Web via polling the API.
12
+ * Polls GET /tasks/<taskId> every 3 seconds for thread updates.
13
+ * Sends messages via the client's sendMessageToAgent method.
14
+ */
15
+ export class WebSyncedAgentWatcher implements SyncedAgentWatcher {
16
+ public taskId: string = "";
17
+ private client: KnowhowSimpleClient;
18
+ private pollInterval: NodeJS.Timeout | null = null;
19
+ private lastThreadLength: number = 0;
20
+ public agentName: string = "remote-agent";
21
+ private stopped: boolean = false;
22
+ public agentEvents = new EventService();
23
+ public eventTypes = {
24
+ done: "done",
25
+ toolCall: "tool:pre_call",
26
+ toolUsed: "tool:post_call",
27
+ agentSay: "agent:say",
28
+ threadUpdate: "thread_update",
29
+ };
30
+
31
+ constructor(client?: KnowhowSimpleClient) {
32
+ this.client = client || new KnowhowSimpleClient();
33
+ }
34
+
35
+ async startWatching(taskId: string): Promise<void> {
36
+ this.taskId = taskId;
37
+ this.stopped = false;
38
+
39
+ // Load initial state to track current thread length
40
+ try {
41
+ const details = await this.client.getTaskDetails(taskId);
42
+ const threads: any[][] = details?.data?.threads || [];
43
+ const lastThread = threads[threads.length - 1] || [];
44
+ this.agentName = "remote-agent";
45
+ this.lastThreadLength = lastThread.length;
46
+ } catch (err: any) {
47
+ console.warn(
48
+ `⚠️ Could not load initial state for task ${taskId}: ${err.message}`
49
+ );
50
+ }
51
+
52
+ // Poll every 3 seconds for updates
53
+ this.pollInterval = setInterval(async () => {
54
+ if (!this.stopped) {
55
+ await this.onPoll().catch(() => {});
56
+ }
57
+ }, 3000);
58
+
59
+ console.log(`🌐 Watching web-synced agent: ${taskId} (${this.agentName})`);
60
+ console.log(
61
+ ` Type /logs 20 to see recent messages, or type to send a message`
62
+ );
63
+ }
64
+
65
+ private async onPoll(): Promise<void> {
66
+ if (this.stopped) return;
67
+ try {
68
+ const details = await this.client.getTaskDetails(this.taskId);
69
+ const threads: any[][] = details?.data?.threads || [];
70
+ const lastThread = threads[threads.length - 1] || [];
71
+
72
+ const newMessages = lastThread.slice(this.lastThreadLength);
73
+ if (newMessages.length > 0) {
74
+ const renderEvents = messagesToRenderEvents(
75
+ newMessages,
76
+ this.taskId,
77
+ this.agentName
78
+ );
79
+ for (const event of renderEvents) {
80
+ if (event.type === "toolCall") {
81
+ this.agentEvents.emit(this.eventTypes.toolCall, {
82
+ toolCall: (event as any).toolCall,
83
+ });
84
+ } else if (event.type === "toolResult") {
85
+ this.agentEvents.emit(this.eventTypes.toolUsed, {
86
+ toolCall: (event as any).toolCall,
87
+ functionResp: (event as any).result,
88
+ });
89
+ } else if (event.type === "agentMessage") {
90
+ this.agentEvents.emit(this.eventTypes.agentSay, {
91
+ message: (event as any).message,
92
+ });
93
+ }
94
+ }
95
+ this.agentEvents.emit(this.eventTypes.threadUpdate, lastThread);
96
+ this.lastThreadLength = lastThread.length;
97
+ }
98
+
99
+ // Stop polling and emit done if task is complete with a result
100
+ const status = details?.data?.status;
101
+ const result = details?.data?.result;
102
+ if (status === "completed" || status === "killed") {
103
+ this.stopWatching();
104
+ if (result != null) {
105
+ this.agentEvents.emit(this.eventTypes.done, result);
106
+ } else {
107
+ console.log(
108
+ `\n✅ Remote agent ${this.taskId} status: ${status} (no result)`
109
+ );
110
+ }
111
+ }
112
+ } catch {
113
+ // Silently continue on poll errors
114
+ }
115
+ }
116
+
117
+ async sendMessage(message: string): Promise<void> {
118
+ await this.client.sendMessageToAgent(this.taskId, message);
119
+ }
120
+
121
+ async getThreads(): Promise<any[][]> {
122
+ try {
123
+ const details = await this.client.getTaskDetails(this.taskId);
124
+ return details?.data?.threads || [];
125
+ } catch {
126
+ return [];
127
+ }
128
+ }
129
+
130
+ stopWatching(): void {
131
+ this.stopped = true;
132
+ if (this.pollInterval) {
133
+ clearInterval(this.pollInterval);
134
+ this.pollInterval = null;
135
+ }
136
+ console.log(`🔌 Stopped watching web agent: ${this.taskId}`);
137
+ }
138
+
139
+ async pause(): Promise<void> {
140
+ await this.client.pauseAgent(this.taskId);
141
+ console.log(`⏸️ Paused remote web agent: ${this.taskId}`);
142
+ }
143
+
144
+ async unpause(): Promise<void> {
145
+ await this.client.resumeAgent(this.taskId);
146
+ console.log(`▶️ Unpaused remote web agent: ${this.taskId}`);
147
+ }
148
+
149
+ async kill(): Promise<void> {
150
+ await this.client.killAgent(this.taskId);
151
+ console.log(`🛑 Killed remote web agent: ${this.taskId}`);
152
+ }
153
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./FsSyncer";
2
+ export * from "./RemoteSyncer";