@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.
- package/CONFIG.md +8 -5
- package/package.json +3 -2
- package/scripts/check-model-pricing.ts +509 -0
- package/scripts/compare-openrouter-coverage.ts +576 -0
- package/src/agents/base/base.ts +127 -2
- package/src/agents/tools/execCommand.ts +4 -0
- package/src/agents/tools/executeScript/definition.ts +1 -1
- package/src/agents/tools/index.ts +0 -1
- package/src/agents/tools/list.ts +3 -43
- package/src/agents/tools/writeFile.ts +1 -1
- package/src/auth/browserLogin.ts +9 -4
- package/src/chat/modules/RemoteSyncModule.ts +3 -0
- package/src/cli.ts +31 -1
- package/src/clients/cerebras.ts +10 -0
- package/src/clients/contextLimits.ts +7 -2
- package/src/clients/copilot.ts +23 -0
- package/src/clients/deepseek.ts +16 -0
- package/src/clients/fireworks.ts +15 -0
- package/src/clients/gemini.ts +45 -2
- package/src/clients/github.ts +16 -0
- package/src/clients/groq.ts +15 -0
- package/src/clients/http.ts +190 -6
- package/src/clients/index.ts +215 -9
- package/src/clients/llama.ts +16 -0
- package/src/clients/mistral.ts +16 -0
- package/src/clients/nvidia.ts +16 -0
- package/src/clients/openai.ts +41 -11
- package/src/clients/openrouter.ts +17 -0
- package/src/clients/pricing/anthropic.ts +105 -78
- package/src/clients/pricing/cerebras.ts +11 -0
- package/src/clients/pricing/copilot.ts +60 -0
- package/src/clients/pricing/deepseek.ts +15 -0
- package/src/clients/pricing/fireworks.ts +32 -0
- package/src/clients/pricing/github.ts +69 -0
- package/src/clients/pricing/google.ts +245 -206
- package/src/clients/pricing/groq.ts +56 -0
- package/src/clients/pricing/index.ts +43 -6
- package/src/clients/pricing/llama.ts +18 -0
- package/src/clients/pricing/mistral.ts +34 -0
- package/src/clients/pricing/models.ts +23 -0
- package/src/clients/pricing/nvidia.ts +102 -0
- package/src/clients/pricing/openai.ts +347 -171
- package/src/clients/pricing/openrouter.ts +36 -0
- package/src/clients/pricing/types.ts +110 -0
- package/src/clients/pricing/xai.ts +123 -66
- package/src/clients/types.ts +4 -0
- package/src/clients/xai.ts +152 -2
- package/src/fileSync.ts +8 -2
- package/src/login.ts +11 -3
- package/src/services/AgentSyncFs.ts +36 -12
- package/src/services/KnowhowClient.ts +11 -0
- package/src/services/LazyToolsService.ts +6 -0
- package/src/services/S3.ts +0 -7
- package/src/services/SyncedAgentWatcher.ts +13 -298
- package/src/services/index.ts +1 -0
- package/src/services/modules/index.ts +11 -2
- package/src/services/watchers/FsSyncer.ts +155 -0
- package/src/services/watchers/RemoteSyncer.ts +153 -0
- package/src/services/watchers/index.ts +2 -0
- package/src/types.ts +56 -279
- package/src/worker.ts +174 -0
- package/tests/clients/pricing.test.ts +37 -0
- package/tests/manual/clients/completions.json +838 -226
- package/tests/manual/clients/completions.test.ts +46 -31
- package/ts_build/package.json +3 -2
- package/ts_build/src/agents/base/base.d.ts +17 -1
- package/ts_build/src/agents/base/base.js +82 -1
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/tools/execCommand.js +3 -0
- package/ts_build/src/agents/tools/execCommand.js.map +1 -1
- package/ts_build/src/agents/tools/executeScript/definition.js +1 -1
- package/ts_build/src/agents/tools/executeScript/definition.js.map +1 -1
- package/ts_build/src/agents/tools/index.d.ts +0 -1
- package/ts_build/src/agents/tools/index.js +0 -1
- package/ts_build/src/agents/tools/index.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +3 -38
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/agents/tools/visionTool.d.ts +1 -1
- package/ts_build/src/agents/tools/writeFile.js +1 -1
- package/ts_build/src/agents/tools/writeFile.js.map +1 -1
- package/ts_build/src/ai.d.ts +1 -1
- package/ts_build/src/auth/browserLogin.d.ts +2 -1
- package/ts_build/src/auth/browserLogin.js +10 -3
- package/ts_build/src/auth/browserLogin.js.map +1 -1
- package/ts_build/src/chat/modules/RemoteSyncModule.js +1 -0
- package/ts_build/src/chat/modules/RemoteSyncModule.js.map +1 -1
- package/ts_build/src/cli.js +19 -0
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +1 -82
- package/ts_build/src/clients/cerebras.d.ts +4 -0
- package/ts_build/src/clients/cerebras.js +14 -0
- package/ts_build/src/clients/cerebras.js.map +1 -0
- package/ts_build/src/clients/contextLimits.js +7 -2
- package/ts_build/src/clients/contextLimits.js.map +1 -1
- package/ts_build/src/clients/copilot.d.ts +4 -0
- package/ts_build/src/clients/copilot.js +15 -0
- package/ts_build/src/clients/copilot.js.map +1 -0
- package/ts_build/src/clients/deepseek.d.ts +4 -0
- package/ts_build/src/clients/deepseek.js +15 -0
- package/ts_build/src/clients/deepseek.js.map +1 -0
- package/ts_build/src/clients/fireworks.d.ts +4 -0
- package/ts_build/src/clients/fireworks.js +15 -0
- package/ts_build/src/clients/fireworks.js.map +1 -0
- package/ts_build/src/clients/gemini.d.ts +1 -0
- package/ts_build/src/clients/gemini.js +28 -1
- package/ts_build/src/clients/gemini.js.map +1 -1
- package/ts_build/src/clients/github.d.ts +4 -0
- package/ts_build/src/clients/github.js +15 -0
- package/ts_build/src/clients/github.js.map +1 -0
- package/ts_build/src/clients/groq.d.ts +4 -0
- package/ts_build/src/clients/groq.js +15 -0
- package/ts_build/src/clients/groq.js.map +1 -0
- package/ts_build/src/clients/http.d.ts +22 -1
- package/ts_build/src/clients/http.js +132 -7
- package/ts_build/src/clients/http.js.map +1 -1
- package/ts_build/src/clients/index.d.ts +22 -0
- package/ts_build/src/clients/index.js +150 -5
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/clients/llama.d.ts +4 -0
- package/ts_build/src/clients/llama.js +15 -0
- package/ts_build/src/clients/llama.js.map +1 -0
- package/ts_build/src/clients/mistral.d.ts +4 -0
- package/ts_build/src/clients/mistral.js +15 -0
- package/ts_build/src/clients/mistral.js.map +1 -0
- package/ts_build/src/clients/nvidia.d.ts +4 -0
- package/ts_build/src/clients/nvidia.js +15 -0
- package/ts_build/src/clients/nvidia.js.map +1 -0
- package/ts_build/src/clients/openai.d.ts +4 -206
- package/ts_build/src/clients/openai.js +27 -9
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/openrouter.d.ts +4 -0
- package/ts_build/src/clients/openrouter.js +15 -0
- package/ts_build/src/clients/openrouter.js.map +1 -0
- package/ts_build/src/clients/pricing/anthropic.d.ts +26 -78
- package/ts_build/src/clients/pricing/anthropic.js +75 -78
- package/ts_build/src/clients/pricing/anthropic.js.map +1 -1
- package/ts_build/src/clients/pricing/cerebras.d.ts +4 -0
- package/ts_build/src/clients/pricing/cerebras.js +11 -0
- package/ts_build/src/clients/pricing/cerebras.js.map +1 -0
- package/ts_build/src/clients/pricing/copilot.d.ts +5 -0
- package/ts_build/src/clients/pricing/copilot.js +35 -0
- package/ts_build/src/clients/pricing/copilot.js.map +1 -0
- package/ts_build/src/clients/pricing/deepseek.d.ts +5 -0
- package/ts_build/src/clients/pricing/deepseek.js +10 -0
- package/ts_build/src/clients/pricing/deepseek.js.map +1 -0
- package/ts_build/src/clients/pricing/fireworks.d.ts +5 -0
- package/ts_build/src/clients/pricing/fireworks.js +21 -0
- package/ts_build/src/clients/pricing/fireworks.js.map +1 -0
- package/ts_build/src/clients/pricing/github.d.ts +4 -0
- package/ts_build/src/clients/pricing/github.js +58 -0
- package/ts_build/src/clients/pricing/github.js.map +1 -0
- package/ts_build/src/clients/pricing/google.d.ts +59 -6
- package/ts_build/src/clients/pricing/google.js +214 -167
- package/ts_build/src/clients/pricing/google.js.map +1 -1
- package/ts_build/src/clients/pricing/groq.d.ts +5 -0
- package/ts_build/src/clients/pricing/groq.js +41 -0
- package/ts_build/src/clients/pricing/groq.js.map +1 -0
- package/ts_build/src/clients/pricing/index.d.ts +17 -6
- package/ts_build/src/clients/pricing/index.js +65 -10
- package/ts_build/src/clients/pricing/index.js.map +1 -1
- package/ts_build/src/clients/pricing/llama.d.ts +4 -0
- package/ts_build/src/clients/pricing/llama.js +14 -0
- package/ts_build/src/clients/pricing/llama.js.map +1 -0
- package/ts_build/src/clients/pricing/mistral.d.ts +5 -0
- package/ts_build/src/clients/pricing/mistral.js +23 -0
- package/ts_build/src/clients/pricing/mistral.js.map +1 -0
- package/ts_build/src/clients/pricing/models.d.ts +9 -0
- package/ts_build/src/clients/pricing/models.js +19 -0
- package/ts_build/src/clients/pricing/models.js.map +1 -0
- package/ts_build/src/clients/pricing/nvidia.d.ts +8 -0
- package/ts_build/src/clients/pricing/nvidia.js +96 -0
- package/ts_build/src/clients/pricing/nvidia.js.map +1 -0
- package/ts_build/src/clients/pricing/openai.d.ts +86 -197
- package/ts_build/src/clients/pricing/openai.js +294 -168
- package/ts_build/src/clients/pricing/openai.js.map +1 -1
- package/ts_build/src/clients/pricing/openrouter.d.ts +4 -0
- package/ts_build/src/clients/pricing/openrouter.js +29 -0
- package/ts_build/src/clients/pricing/openrouter.js.map +1 -0
- package/ts_build/src/clients/pricing/types.d.ts +46 -0
- package/ts_build/src/clients/pricing/types.js +49 -0
- package/ts_build/src/clients/pricing/types.js.map +1 -0
- package/ts_build/src/clients/pricing/xai.d.ts +39 -64
- package/ts_build/src/clients/pricing/xai.js +93 -60
- package/ts_build/src/clients/pricing/xai.js.map +1 -1
- package/ts_build/src/clients/types.d.ts +1 -0
- package/ts_build/src/clients/xai.d.ts +2 -58
- package/ts_build/src/clients/xai.js +123 -2
- package/ts_build/src/clients/xai.js.map +1 -1
- package/ts_build/src/fileSync.js +7 -2
- package/ts_build/src/fileSync.js.map +1 -1
- package/ts_build/src/login.js +8 -2
- package/ts_build/src/login.js.map +1 -1
- package/ts_build/src/services/AgentSyncFs.js +1 -0
- package/ts_build/src/services/AgentSyncFs.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.d.ts +1 -0
- package/ts_build/src/services/KnowhowClient.js +7 -0
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/LazyToolsService.d.ts +1 -0
- package/ts_build/src/services/LazyToolsService.js +3 -0
- package/ts_build/src/services/LazyToolsService.js.map +1 -1
- package/ts_build/src/services/S3.js +0 -7
- package/ts_build/src/services/S3.js.map +1 -1
- package/ts_build/src/services/SyncedAgentWatcher.d.ts +0 -51
- package/ts_build/src/services/SyncedAgentWatcher.js +1 -282
- package/ts_build/src/services/SyncedAgentWatcher.js.map +1 -1
- package/ts_build/src/services/index.d.ts +1 -0
- package/ts_build/src/services/index.js +1 -0
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/src/services/modules/index.js +41 -1
- package/ts_build/src/services/modules/index.js.map +1 -1
- package/ts_build/src/services/watchers/FsSyncer.d.ts +27 -0
- package/ts_build/src/services/watchers/FsSyncer.js +135 -0
- package/ts_build/src/services/watchers/FsSyncer.js.map +1 -0
- package/ts_build/src/services/watchers/RemoteSyncer.d.ts +28 -0
- package/ts_build/src/services/watchers/RemoteSyncer.js +126 -0
- package/ts_build/src/services/watchers/RemoteSyncer.js.map +1 -0
- package/ts_build/src/services/watchers/index.d.ts +2 -0
- package/ts_build/src/services/watchers/index.js +19 -0
- package/ts_build/src/services/watchers/index.js.map +1 -0
- package/ts_build/src/types.d.ts +163 -124
- package/ts_build/src/types.js +33 -213
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/worker.d.ts +4 -0
- package/ts_build/src/worker.js +140 -0
- package/ts_build/src/worker.js.map +1 -1
- package/ts_build/tests/clients/pricing.test.js +21 -0
- package/ts_build/tests/clients/pricing.test.js.map +1 -1
- package/ts_build/tests/manual/clients/completions.test.js +27 -24
- package/ts_build/tests/manual/clients/completions.test.js.map +1 -1
- package/src/clients/pricing/catalog.ts +0 -287
- package/ts_build/src/clients/pricing/catalog.d.ts +0 -28
- package/ts_build/src/clients/pricing/catalog.js +0 -179
- 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
|
+
}
|