@tyvm/knowhow 0.0.82 → 0.0.84
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/package.json +4 -2
- package/src/agents/base/base.ts +72 -62
- package/src/agents/index.ts +30 -14
- package/src/agents/tools/startAgentTask.ts +3 -1
- package/src/chat/CliChatService.ts +20 -4
- package/src/chat/modules/AgentModule.ts +399 -357
- package/src/chat/modules/CustomCommandsModule.ts +0 -1
- package/src/chat/modules/InternalChatModule.ts +18 -2
- package/src/chat/modules/RendererModule.ts +109 -0
- package/src/chat/modules/SessionsModule.ts +854 -0
- package/src/chat/modules/SetupModule.ts +6 -8
- package/src/chat/modules/index.ts +1 -0
- package/src/chat/renderer/CompactRenderer.ts +209 -0
- package/src/chat/renderer/ConsoleRenderer.ts +141 -0
- package/src/chat/renderer/FancyRenderer.ts +421 -0
- package/src/chat/renderer/index.ts +5 -0
- package/src/chat/renderer/loadRenderer.ts +314 -0
- package/src/chat/renderer/messagesToRenderEvents.ts +96 -0
- package/src/chat/renderer/types.ts +88 -0
- package/src/chat/types.ts +5 -0
- package/src/chat.ts +69 -5
- package/src/cli.ts +24 -5
- package/src/config.ts +15 -0
- package/src/plugins/AgentsMdPlugin.ts +1 -1
- package/src/plugins/GitPlugin.ts +20 -20
- package/src/plugins/PluginBase.ts +11 -0
- package/src/plugins/SkillsPlugin.ts +150 -0
- package/src/plugins/asana.ts +4 -4
- package/src/plugins/embedding.ts +3 -5
- package/src/plugins/exec.ts +3 -3
- package/src/plugins/figma.ts +3 -7
- package/src/plugins/github.ts +18 -29
- package/src/plugins/jira.ts +2 -2
- package/src/plugins/language.ts +4 -4
- package/src/plugins/linear.ts +4 -4
- package/src/plugins/notion.ts +6 -8
- package/src/plugins/plugins.ts +30 -4
- package/src/plugins/url.ts +2 -2
- package/src/plugins/vim.ts +4 -3
- package/src/services/AgentService.ts +17 -0
- package/src/services/AgentSyncFs.ts +3 -0
- package/src/services/EventService.ts +168 -27
- package/src/services/KnowhowClient.ts +1 -0
- package/src/services/SessionManager.ts +51 -1
- package/src/services/SyncedAgentWatcher.ts +397 -0
- package/src/services/SyncerService.ts +147 -0
- package/src/services/index.ts +2 -0
- package/src/services/modules/index.ts +14 -3
- package/src/types.ts +25 -0
- package/src/worker.ts +80 -2
- package/src/workers/auth/PasskeySetup.ts +185 -0
- package/src/workers/auth/WorkerPasskeyAuth.ts +190 -0
- package/src/workers/auth/types.ts +58 -0
- package/src/workers/tools/getChallenge.ts +33 -0
- package/src/workers/tools/index.ts +8 -0
- package/src/workers/tools/lock.ts +31 -0
- package/src/workers/tools/unlock.ts +116 -0
- package/tests/unit/modules/moduleLoading.test.ts +226 -0
- package/tests/unit/plugins/pluginLoading.test.ts +151 -0
- package/ts_build/package.json +4 -2
- package/ts_build/src/agents/base/base.d.ts +4 -3
- package/ts_build/src/agents/base/base.js +54 -30
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/index.d.ts +3 -0
- package/ts_build/src/agents/index.js +21 -11
- package/ts_build/src/agents/index.js.map +1 -1
- package/ts_build/src/agents/tools/startAgentTask.js +2 -1
- package/ts_build/src/agents/tools/startAgentTask.js.map +1 -1
- package/ts_build/src/chat/CliChatService.js +16 -5
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +34 -17
- package/ts_build/src/chat/modules/AgentModule.js +248 -258
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/CustomCommandsModule.js.map +1 -1
- package/ts_build/src/chat/modules/InternalChatModule.d.ts +3 -0
- package/ts_build/src/chat/modules/InternalChatModule.js +16 -1
- package/ts_build/src/chat/modules/InternalChatModule.js.map +1 -1
- package/ts_build/src/chat/modules/RendererModule.d.ts +16 -0
- package/ts_build/src/chat/modules/RendererModule.js +76 -0
- package/ts_build/src/chat/modules/RendererModule.js.map +1 -0
- package/ts_build/src/chat/modules/SessionsModule.d.ts +33 -0
- package/ts_build/src/chat/modules/SessionsModule.js +582 -0
- package/ts_build/src/chat/modules/SessionsModule.js.map +1 -0
- package/ts_build/src/chat/modules/SetupModule.d.ts +3 -3
- package/ts_build/src/chat/modules/SetupModule.js +4 -6
- package/ts_build/src/chat/modules/SetupModule.js.map +1 -1
- package/ts_build/src/chat/modules/index.d.ts +1 -0
- package/ts_build/src/chat/modules/index.js +3 -1
- package/ts_build/src/chat/modules/index.js.map +1 -1
- package/ts_build/src/chat/renderer/CompactRenderer.d.ts +23 -0
- package/ts_build/src/chat/renderer/CompactRenderer.js +167 -0
- package/ts_build/src/chat/renderer/CompactRenderer.js.map +1 -0
- package/ts_build/src/chat/renderer/ConsoleRenderer.d.ts +22 -0
- package/ts_build/src/chat/renderer/ConsoleRenderer.js +110 -0
- package/ts_build/src/chat/renderer/ConsoleRenderer.js.map +1 -0
- package/ts_build/src/chat/renderer/FancyRenderer.d.ts +23 -0
- package/ts_build/src/chat/renderer/FancyRenderer.js +328 -0
- package/ts_build/src/chat/renderer/FancyRenderer.js.map +1 -0
- package/ts_build/src/chat/renderer/index.d.ts +5 -0
- package/ts_build/src/chat/renderer/index.js +29 -0
- package/ts_build/src/chat/renderer/index.js.map +1 -0
- package/ts_build/src/chat/renderer/loadRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/loadRenderer.js +246 -0
- package/ts_build/src/chat/renderer/loadRenderer.js.map +1 -0
- package/ts_build/src/chat/renderer/messagesToRenderEvents.d.ts +15 -0
- package/ts_build/src/chat/renderer/messagesToRenderEvents.js +72 -0
- package/ts_build/src/chat/renderer/messagesToRenderEvents.js.map +1 -0
- package/ts_build/src/chat/renderer/types.d.ts +75 -0
- package/ts_build/src/chat/renderer/types.js +3 -0
- package/ts_build/src/chat/renderer/types.js.map +1 -0
- package/ts_build/src/chat/types.d.ts +5 -0
- package/ts_build/src/chat.js +46 -4
- package/ts_build/src/chat.js.map +1 -1
- package/ts_build/src/cli.js +18 -5
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/config.d.ts +1 -0
- package/ts_build/src/config.js +17 -1
- package/ts_build/src/config.js.map +1 -1
- package/ts_build/src/plugins/AgentsMdPlugin.js +1 -1
- package/ts_build/src/plugins/AgentsMdPlugin.js.map +1 -1
- package/ts_build/src/plugins/GitPlugin.js +20 -20
- package/ts_build/src/plugins/GitPlugin.js.map +1 -1
- package/ts_build/src/plugins/PluginBase.d.ts +1 -0
- package/ts_build/src/plugins/PluginBase.js +13 -0
- package/ts_build/src/plugins/PluginBase.js.map +1 -1
- package/ts_build/src/plugins/SkillsPlugin.d.ts +13 -0
- package/ts_build/src/plugins/SkillsPlugin.js +149 -0
- package/ts_build/src/plugins/SkillsPlugin.js.map +1 -0
- package/ts_build/src/plugins/asana.js +4 -4
- package/ts_build/src/plugins/asana.js.map +1 -1
- package/ts_build/src/plugins/embedding.js +3 -3
- package/ts_build/src/plugins/embedding.js.map +1 -1
- package/ts_build/src/plugins/exec.js +3 -3
- package/ts_build/src/plugins/exec.js.map +1 -1
- package/ts_build/src/plugins/figma.js +3 -3
- package/ts_build/src/plugins/figma.js.map +1 -1
- package/ts_build/src/plugins/github.js +18 -18
- package/ts_build/src/plugins/github.js.map +1 -1
- package/ts_build/src/plugins/jira.js +2 -2
- package/ts_build/src/plugins/jira.js.map +1 -1
- package/ts_build/src/plugins/language.js +4 -4
- package/ts_build/src/plugins/language.js.map +1 -1
- package/ts_build/src/plugins/linear.js +4 -4
- package/ts_build/src/plugins/linear.js.map +1 -1
- package/ts_build/src/plugins/notion.js +6 -6
- package/ts_build/src/plugins/notion.js.map +1 -1
- package/ts_build/src/plugins/plugins.d.ts +3 -0
- package/ts_build/src/plugins/plugins.js +19 -4
- package/ts_build/src/plugins/plugins.js.map +1 -1
- package/ts_build/src/plugins/url.js +2 -2
- package/ts_build/src/plugins/url.js.map +1 -1
- package/ts_build/src/plugins/vim.js +2 -2
- package/ts_build/src/plugins/vim.js.map +1 -1
- package/ts_build/src/services/AgentService.d.ts +3 -0
- package/ts_build/src/services/AgentService.js +7 -0
- package/ts_build/src/services/AgentService.js.map +1 -1
- package/ts_build/src/services/AgentSyncFs.d.ts +1 -0
- package/ts_build/src/services/AgentSyncFs.js +2 -0
- package/ts_build/src/services/AgentSyncFs.js.map +1 -1
- package/ts_build/src/services/EventService.d.ts +25 -2
- package/ts_build/src/services/EventService.js +92 -14
- package/ts_build/src/services/EventService.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.d.ts +1 -0
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/SessionManager.d.ts +6 -0
- package/ts_build/src/services/SessionManager.js +39 -1
- package/ts_build/src/services/SessionManager.js.map +1 -1
- package/ts_build/src/services/SyncedAgentWatcher.d.ts +101 -0
- package/ts_build/src/services/SyncedAgentWatcher.js +312 -0
- package/ts_build/src/services/SyncedAgentWatcher.js.map +1 -0
- package/ts_build/src/services/SyncerService.d.ts +30 -0
- package/ts_build/src/services/SyncerService.js +72 -0
- package/ts_build/src/services/SyncerService.js.map +1 -0
- package/ts_build/src/services/index.d.ts +2 -0
- package/ts_build/src/services/index.js +2 -0
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/src/services/modules/index.js +10 -2
- package/ts_build/src/services/modules/index.js.map +1 -1
- package/ts_build/src/types.d.ts +19 -0
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/worker.d.ts +2 -0
- package/ts_build/src/worker.js +59 -4
- package/ts_build/src/worker.js.map +1 -1
- package/ts_build/src/workers/auth/PasskeySetup.d.ts +10 -0
- package/ts_build/src/workers/auth/PasskeySetup.js +131 -0
- package/ts_build/src/workers/auth/PasskeySetup.js.map +1 -0
- package/ts_build/src/workers/auth/WorkerPasskeyAuth.d.ts +35 -0
- package/ts_build/src/workers/auth/WorkerPasskeyAuth.js +129 -0
- package/ts_build/src/workers/auth/WorkerPasskeyAuth.js.map +1 -0
- package/ts_build/src/workers/auth/types.d.ts +36 -0
- package/ts_build/src/workers/auth/types.js +3 -0
- package/ts_build/src/workers/auth/types.js.map +1 -0
- package/ts_build/src/workers/tools/getChallenge.d.ts +9 -0
- package/ts_build/src/workers/tools/getChallenge.js +27 -0
- package/ts_build/src/workers/tools/getChallenge.js.map +1 -0
- package/ts_build/src/workers/tools/index.d.ts +6 -0
- package/ts_build/src/workers/tools/index.js +10 -0
- package/ts_build/src/workers/tools/index.js.map +1 -1
- package/ts_build/src/workers/tools/lock.d.ts +9 -0
- package/ts_build/src/workers/tools/lock.js +27 -0
- package/ts_build/src/workers/tools/lock.js.map +1 -0
- package/ts_build/src/workers/tools/unlock.d.ts +18 -0
- package/ts_build/src/workers/tools/unlock.js +78 -0
- package/ts_build/src/workers/tools/unlock.js.map +1 -0
- package/ts_build/tests/unit/modules/moduleLoading.test.d.ts +1 -0
- package/ts_build/tests/unit/modules/moduleLoading.test.js +187 -0
- package/ts_build/tests/unit/modules/moduleLoading.test.js.map +1 -0
- package/ts_build/tests/unit/plugins/pluginLoading.test.d.ts +1 -0
- package/ts_build/tests/unit/plugins/pluginLoading.test.js +123 -0
- package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent Chat Module - Handles agent interactions
|
|
3
3
|
*/
|
|
4
|
+
import { EventService } from "../../services/EventService";
|
|
5
|
+
import { ConsoleRenderer, AgentRenderer } from "../renderer";
|
|
4
6
|
import {
|
|
5
|
-
AgentSyncKnowhowWeb,
|
|
6
|
-
AgentSyncFs,
|
|
7
7
|
SessionManager,
|
|
8
8
|
TaskRegistry,
|
|
9
|
+
SyncedAgentWatcher,
|
|
10
|
+
SyncerService,
|
|
9
11
|
} from "../../services/index";
|
|
12
|
+
import { AttachableAgent } from "../../services/SyncedAgentWatcher";
|
|
10
13
|
import * as fs from "fs";
|
|
11
14
|
import * as fsPromises from "fs/promises";
|
|
12
15
|
import * as path from "path";
|
|
@@ -26,8 +29,13 @@ import {
|
|
|
26
29
|
HarmonyToolProcessor,
|
|
27
30
|
Base64ImageProcessor,
|
|
28
31
|
} from "../../processors/index";
|
|
29
|
-
import { TaskInfo
|
|
30
|
-
import {
|
|
32
|
+
import { TaskInfo } from "../types";
|
|
33
|
+
import {
|
|
34
|
+
createAgent,
|
|
35
|
+
agentConstructors,
|
|
36
|
+
AgentName,
|
|
37
|
+
agents,
|
|
38
|
+
} from "../../agents";
|
|
31
39
|
import { ToolCallEvent } from "../../agents/base/base";
|
|
32
40
|
import { $Command } from "@aws-sdk/client-s3";
|
|
33
41
|
import { KnowhowSimpleClient } from "../../services/KnowhowClient";
|
|
@@ -36,18 +44,33 @@ export class AgentModule extends BaseChatModule {
|
|
|
36
44
|
name = "agent";
|
|
37
45
|
description = "Agent interaction functionality";
|
|
38
46
|
|
|
47
|
+
/** Currently attached agent (for agent:attached mode commands) */
|
|
48
|
+
private attachedAgent: AttachableAgent | undefined;
|
|
49
|
+
|
|
39
50
|
// Service instances for task management, session management, and synchronization
|
|
40
51
|
private taskRegistry: TaskRegistry;
|
|
41
52
|
private sessionManager: SessionManager;
|
|
42
|
-
private
|
|
43
|
-
|
|
53
|
+
private syncer: SyncerService;
|
|
54
|
+
/** Timestamp when this process started - used to filter sessions */
|
|
55
|
+
private processStartTime: number = Date.now();
|
|
56
|
+
/** Currently attached agent task ID */
|
|
57
|
+
private activeAgentTaskId: string | undefined;
|
|
58
|
+
/** Currently active synced agent watcher (for FS or Web agents) */
|
|
59
|
+
private activeSyncedWatcher: SyncedAgentWatcher | undefined;
|
|
60
|
+
|
|
61
|
+
/** Stored wire params for rewireAgentRendering */
|
|
62
|
+
private _wireAgentEvents: EventService | undefined;
|
|
63
|
+
private _wireTaskId: string | undefined;
|
|
64
|
+
private _wireAgentName: string | undefined;
|
|
65
|
+
private _wireEventTypes:
|
|
66
|
+
| { toolCall?: string; toolUsed?: string; agentSay?: string; done: string }
|
|
67
|
+
| undefined;
|
|
44
68
|
|
|
45
69
|
constructor() {
|
|
46
70
|
super();
|
|
47
71
|
this.taskRegistry = new TaskRegistry();
|
|
48
72
|
this.sessionManager = new SessionManager();
|
|
49
|
-
this.
|
|
50
|
-
this.fsSync = new AgentSyncFs();
|
|
73
|
+
this.syncer = new SyncerService();
|
|
51
74
|
}
|
|
52
75
|
|
|
53
76
|
getCommands(): ChatCommand[] {
|
|
@@ -63,30 +86,137 @@ export class AgentModule extends BaseChatModule {
|
|
|
63
86
|
handler: this.handleAgentsCommand.bind(this),
|
|
64
87
|
},
|
|
65
88
|
{
|
|
66
|
-
name: "
|
|
67
|
-
description: "
|
|
68
|
-
|
|
89
|
+
name: "pause",
|
|
90
|
+
description: "Pause the currently attached agent",
|
|
91
|
+
modes: ["agent:attached"],
|
|
92
|
+
handler: async (_args: string[]): Promise<void> => {
|
|
93
|
+
if (this.attachedAgent) {
|
|
94
|
+
await this.attachedAgent.pause();
|
|
95
|
+
console.log("Agent paused.");
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "unpause",
|
|
101
|
+
description: "Unpause the currently attached agent",
|
|
102
|
+
modes: ["agent:attached"],
|
|
103
|
+
handler: async (_args: string[]): Promise<void> => {
|
|
104
|
+
if (this.attachedAgent) {
|
|
105
|
+
await this.attachedAgent.unpause();
|
|
106
|
+
console.log("Agent unpaused.");
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "kill",
|
|
112
|
+
description: "Kill the currently attached agent",
|
|
113
|
+
modes: ["agent:attached"],
|
|
114
|
+
handler: async (_args: string[]): Promise<void> => {
|
|
115
|
+
if (this.attachedAgent) {
|
|
116
|
+
await this.attachedAgent.kill();
|
|
117
|
+
console.log("Agent terminated.");
|
|
118
|
+
this.detachFromAgent();
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: "detach",
|
|
124
|
+
description: "Detach from the currently attached agent",
|
|
125
|
+
modes: ["agent:attached"],
|
|
126
|
+
handler: async (_args: string[]): Promise<void> => {
|
|
127
|
+
console.log("Detached from agent");
|
|
128
|
+
this.detachFromAgent();
|
|
129
|
+
},
|
|
69
130
|
},
|
|
70
131
|
{
|
|
71
|
-
name: "
|
|
72
|
-
description: "
|
|
73
|
-
|
|
132
|
+
name: "done",
|
|
133
|
+
description: "Exit the current agent interaction",
|
|
134
|
+
modes: ["agent:attached"],
|
|
135
|
+
handler: async (_args: string[]): Promise<void> => {
|
|
136
|
+
this.detachFromAgent();
|
|
137
|
+
},
|
|
74
138
|
},
|
|
75
139
|
];
|
|
76
140
|
}
|
|
77
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Clean up attached agent state and restore default mode/prompt.
|
|
144
|
+
*/
|
|
145
|
+
private detachFromAgent(): void {
|
|
146
|
+
this.attachedAgent = undefined;
|
|
147
|
+
|
|
148
|
+
// Unregister rendering event listeners
|
|
149
|
+
this.unwireAgentRendering();
|
|
150
|
+
|
|
151
|
+
if (this.chatService) {
|
|
152
|
+
this.chatService.setMode("default");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Stop any active synced watcher
|
|
156
|
+
if (this.activeSyncedWatcher) {
|
|
157
|
+
this.activeSyncedWatcher.stopWatching();
|
|
158
|
+
this.activeSyncedWatcher = undefined;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const context = this.chatService?.getContext();
|
|
162
|
+
if (context) context.activeAgentTaskId = undefined;
|
|
163
|
+
}
|
|
164
|
+
|
|
78
165
|
getModes(): ChatMode[] {
|
|
79
166
|
return [
|
|
80
167
|
{
|
|
81
168
|
name: "agent",
|
|
82
169
|
description: "Agent interaction mode",
|
|
83
170
|
active: true,
|
|
171
|
+
promptText: () => {
|
|
172
|
+
const ctx = this.chatService?.getContext();
|
|
173
|
+
return ctx?.currentAgent
|
|
174
|
+
? `\nAsk knowhow ${ctx.currentAgent}: `
|
|
175
|
+
: `\nAsk knowhow: `;
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
name: "agent:attached",
|
|
180
|
+
description: "Attached to a running agent",
|
|
181
|
+
active: false,
|
|
182
|
+
promptText: () =>
|
|
183
|
+
this.attachedAgent
|
|
184
|
+
? `Enter command or message for ${this.attachedAgent.name}: `
|
|
185
|
+
: `Enter command or message for agent: `,
|
|
84
186
|
},
|
|
85
187
|
];
|
|
86
188
|
}
|
|
87
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Get the current renderer from the chat context, falling back to a ConsoleRenderer.
|
|
192
|
+
*/
|
|
193
|
+
private get renderer(): AgentRenderer {
|
|
194
|
+
return (
|
|
195
|
+
(this.chatService?.getContext()?.renderer as AgentRenderer) ??
|
|
196
|
+
new ConsoleRenderer()
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
88
200
|
async initialize(service: ChatService): Promise<void> {
|
|
89
201
|
await super.initialize(service);
|
|
202
|
+
|
|
203
|
+
// Set up plugin log event handler - use setListener so re-init doesn't double-subscribe
|
|
204
|
+
const Events = services().Events;
|
|
205
|
+
Events.setListener(
|
|
206
|
+
{ key: "agentModule:pluginLog", event: Events.eventTypes.pluginLog },
|
|
207
|
+
(logEvent: any) => {
|
|
208
|
+
const activeTasks = this.taskRegistry.getAll();
|
|
209
|
+
this.renderer.render({
|
|
210
|
+
type: "log",
|
|
211
|
+
taskId: this.activeAgentTaskId,
|
|
212
|
+
agentName: logEvent.source,
|
|
213
|
+
message: logEvent.message,
|
|
214
|
+
level: logEvent.level || "info",
|
|
215
|
+
timestamp: logEvent.timestamp || new Date().toISOString(),
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
|
|
90
220
|
await this.handleAgentCommand(["Patcher"]);
|
|
91
221
|
}
|
|
92
222
|
|
|
@@ -145,51 +275,165 @@ export class AgentModule extends BaseChatModule {
|
|
|
145
275
|
}
|
|
146
276
|
}
|
|
147
277
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
278
|
+
/**
|
|
279
|
+
* Get the task registry for CLI access
|
|
280
|
+
*/
|
|
281
|
+
public getTaskRegistry(): TaskRegistry {
|
|
282
|
+
return this.taskRegistry;
|
|
283
|
+
}
|
|
153
284
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
285
|
+
/**
|
|
286
|
+
* Get the session manager
|
|
287
|
+
*/
|
|
288
|
+
public getSessionManager(): SessionManager {
|
|
289
|
+
return this.sessionManager;
|
|
290
|
+
}
|
|
158
291
|
|
|
159
|
-
|
|
292
|
+
/**
|
|
293
|
+
* Get the current renderer from the chat context, falling back to a ConsoleRenderer.
|
|
294
|
+
*/
|
|
295
|
+
public getRenderer(): AgentRenderer {
|
|
296
|
+
return this.renderer;
|
|
297
|
+
}
|
|
160
298
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
299
|
+
/**
|
|
300
|
+
* Get the currently active synced watcher
|
|
301
|
+
*/
|
|
302
|
+
public getActiveSyncedWatcher(): SyncedAgentWatcher | undefined {
|
|
303
|
+
return this.activeSyncedWatcher;
|
|
304
|
+
}
|
|
166
305
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
306
|
+
/**
|
|
307
|
+
* Set the currently active synced watcher
|
|
308
|
+
*/
|
|
309
|
+
public setActiveSyncedWatcher(w: SyncedAgentWatcher | undefined): void {
|
|
310
|
+
this.activeSyncedWatcher = w;
|
|
311
|
+
}
|
|
171
312
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
313
|
+
/**
|
|
314
|
+
* Get the currently active agent task ID
|
|
315
|
+
*/
|
|
316
|
+
public getActiveAgentTaskId(): string | undefined {
|
|
317
|
+
return this.activeAgentTaskId;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Set the currently active agent task ID
|
|
322
|
+
*/
|
|
323
|
+
public setActiveAgentTaskId(id: string | undefined): void {
|
|
324
|
+
this.activeAgentTaskId = id;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Wire up agentEvents to the renderer for a given task.
|
|
329
|
+
* Uses setListener with stable keys so re-calling automatically replaces old listeners.
|
|
330
|
+
*
|
|
331
|
+
* @param taskId The task ID to pass through to render events
|
|
332
|
+
* @param agentEvents An EventEmitter that emits toolCall / toolUsed / agentSay events
|
|
333
|
+
* @param eventTypes Object with event name constants (toolCall, toolUsed, agentSay, done)
|
|
334
|
+
* @param agentName Display name for the agent
|
|
335
|
+
*/
|
|
336
|
+
public wireAgentRendering(
|
|
337
|
+
taskId: string,
|
|
338
|
+
agentEvents: EventService,
|
|
339
|
+
eventTypes: {
|
|
340
|
+
toolCall?: string;
|
|
341
|
+
toolUsed?: string;
|
|
342
|
+
agentSay?: string;
|
|
343
|
+
done: string;
|
|
344
|
+
},
|
|
345
|
+
agentName: string
|
|
346
|
+
): void {
|
|
347
|
+
if (eventTypes.toolCall) {
|
|
348
|
+
agentEvents.setListener(
|
|
349
|
+
{ key: "agentModule:render:toolCall", event: eventTypes.toolCall },
|
|
350
|
+
(data: any) =>
|
|
351
|
+
this.renderer.render({
|
|
352
|
+
type: "toolCall",
|
|
353
|
+
taskId,
|
|
354
|
+
agentName,
|
|
355
|
+
toolCall: data.toolCall,
|
|
356
|
+
})
|
|
357
|
+
);
|
|
180
358
|
}
|
|
359
|
+
if (eventTypes.toolUsed) {
|
|
360
|
+
agentEvents.setListener(
|
|
361
|
+
{ key: "agentModule:render:toolUsed", event: eventTypes.toolUsed },
|
|
362
|
+
(data: any) =>
|
|
363
|
+
this.renderer.render({
|
|
364
|
+
type: "toolResult",
|
|
365
|
+
taskId,
|
|
366
|
+
agentName,
|
|
367
|
+
toolCall: data.toolCall,
|
|
368
|
+
result: data.functionResp,
|
|
369
|
+
})
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
if (eventTypes.agentSay) {
|
|
373
|
+
agentEvents.setListener(
|
|
374
|
+
{ key: "agentModule:render:agentSay", event: eventTypes.agentSay },
|
|
375
|
+
(data: any) =>
|
|
376
|
+
this.renderer.render({
|
|
377
|
+
type: "agentMessage",
|
|
378
|
+
taskId,
|
|
379
|
+
agentName,
|
|
380
|
+
message: data.message,
|
|
381
|
+
role: "assistant",
|
|
382
|
+
})
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Set active task on the renderer
|
|
387
|
+
this.activeAgentTaskId = taskId;
|
|
388
|
+
this.renderer.setActiveTaskId(taskId);
|
|
389
|
+
|
|
390
|
+
// Store agentEvents reference for unwire/rewire
|
|
391
|
+
this._wireAgentEvents = agentEvents;
|
|
392
|
+
this._wireAgentName = agentName;
|
|
393
|
+
this._wireEventTypes = eventTypes;
|
|
394
|
+
this._wireTaskId = taskId;
|
|
395
|
+
}
|
|
181
396
|
|
|
182
|
-
|
|
183
|
-
|
|
397
|
+
/**
|
|
398
|
+
* Unwire rendering event listeners that were set up by wireAgentRendering().
|
|
399
|
+
* Clears the active task on the renderer.
|
|
400
|
+
*/
|
|
401
|
+
public unwireAgentRendering(): void {
|
|
402
|
+
if (this._wireAgentEvents) {
|
|
403
|
+
this._wireAgentEvents.removeManagedListenersByPrefix(
|
|
404
|
+
"agentModule:render:"
|
|
405
|
+
);
|
|
406
|
+
this._wireAgentEvents = undefined;
|
|
407
|
+
}
|
|
408
|
+
this.activeAgentTaskId = undefined;
|
|
409
|
+
this.renderer.setActiveTaskId(undefined);
|
|
184
410
|
}
|
|
185
411
|
|
|
186
412
|
/**
|
|
187
|
-
*
|
|
413
|
+
* Rewire rendering event listeners to the current renderer.
|
|
414
|
+
* Call this after switching the active renderer (e.g. via /render) so that
|
|
415
|
+
* in-progress agents forward events to the new renderer.
|
|
416
|
+
* Since setListener auto-replaces, just re-call wireAgentRendering with stored params.
|
|
188
417
|
*/
|
|
189
|
-
|
|
190
|
-
|
|
418
|
+
public rewireAgentRendering(): void {
|
|
419
|
+
if (
|
|
420
|
+
!this._wireAgentEvents ||
|
|
421
|
+
!this._wireTaskId ||
|
|
422
|
+
!this._wireEventTypes ||
|
|
423
|
+
!this._wireAgentName
|
|
424
|
+
)
|
|
425
|
+
return;
|
|
426
|
+
this.wireAgentRendering(
|
|
427
|
+
this._wireTaskId,
|
|
428
|
+
this._wireAgentEvents,
|
|
429
|
+
this._wireEventTypes,
|
|
430
|
+
this._wireAgentName
|
|
431
|
+
);
|
|
191
432
|
}
|
|
192
433
|
|
|
434
|
+
/**
|
|
435
|
+
* List available agents and optionally select one interactively
|
|
436
|
+
*/
|
|
193
437
|
async handleAgentsCommand(args: string[]): Promise<void> {
|
|
194
438
|
try {
|
|
195
439
|
const allAgents = agents();
|
|
@@ -199,14 +443,15 @@ export class AgentModule extends BaseChatModule {
|
|
|
199
443
|
|
|
200
444
|
console.log("\nAvailable agents:");
|
|
201
445
|
Object.entries(allAgents).forEach(([name, agent]: [string, any]) => {
|
|
202
|
-
console.log(
|
|
446
|
+
console.log(
|
|
447
|
+
` - ${name}: ${(agent as any).description || "No description"}`
|
|
448
|
+
);
|
|
203
449
|
});
|
|
204
450
|
console.log("─".repeat(80), "\n");
|
|
205
451
|
|
|
206
|
-
// Interactive selection with autocomplete
|
|
207
452
|
const selectedAgent = await this.chatService?.getInput(
|
|
208
453
|
"Select an agent to start: ",
|
|
209
|
-
agentNames
|
|
454
|
+
agentNames
|
|
210
455
|
);
|
|
211
456
|
|
|
212
457
|
if (
|
|
@@ -214,7 +459,6 @@ export class AgentModule extends BaseChatModule {
|
|
|
214
459
|
selectedAgent.trim() &&
|
|
215
460
|
agentNames.includes(selectedAgent.trim())
|
|
216
461
|
) {
|
|
217
|
-
// Start the selected agent
|
|
218
462
|
await this.handleAgentCommand([selectedAgent.trim()]);
|
|
219
463
|
} else if (selectedAgent && selectedAgent.trim()) {
|
|
220
464
|
console.log(`Agent "${selectedAgent.trim()}" not found.`);
|
|
@@ -228,153 +472,17 @@ export class AgentModule extends BaseChatModule {
|
|
|
228
472
|
}
|
|
229
473
|
}
|
|
230
474
|
|
|
231
|
-
async logSessionTable() {
|
|
232
|
-
const runningTasks = this.taskRegistry.getAll();
|
|
233
|
-
const savedSessions = this.sessionManager.listAvailableSessions();
|
|
234
|
-
this.sessionManager.logSessionTable(runningTasks, savedSessions);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
async handleSessionsCommand(args: string[]): Promise<void> {
|
|
238
|
-
try {
|
|
239
|
-
// Get both running tasks and saved sessions
|
|
240
|
-
const runningTasks = this.taskRegistry.getAll();
|
|
241
|
-
const savedSessions = this.sessionManager.listAvailableSessions();
|
|
242
|
-
|
|
243
|
-
if (runningTasks.length === 0 && savedSessions.length === 0) {
|
|
244
|
-
console.log("No active tasks or saved sessions found.");
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
await this.logSessionTable();
|
|
249
|
-
|
|
250
|
-
// Interactive selection for both types
|
|
251
|
-
const allIds = [
|
|
252
|
-
...savedSessions.map((s) => s.sessionId),
|
|
253
|
-
...runningTasks.map((t) => t.taskId),
|
|
254
|
-
];
|
|
255
|
-
|
|
256
|
-
if (allIds.length > 0) {
|
|
257
|
-
const selectedId = await this.chatService?.getInput(
|
|
258
|
-
"Select a session/task to attach to (or press Enter to skip): ",
|
|
259
|
-
allIds
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
if (
|
|
263
|
-
selectedId &&
|
|
264
|
-
selectedId.trim() &&
|
|
265
|
-
allIds.includes(selectedId.trim())
|
|
266
|
-
) {
|
|
267
|
-
await this.handleAttachById(selectedId.trim());
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
} catch (error) {
|
|
271
|
-
console.error("Error listing sessions and tasks:", error);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Handle attachment by ID - works for both running tasks and saved sessions
|
|
277
|
-
*/
|
|
278
|
-
private async handleAttachById(id: string): Promise<void> {
|
|
279
|
-
// Check if it's a running task first
|
|
280
|
-
if (this.taskRegistry.has(id)) {
|
|
281
|
-
const taskInfo = this.taskRegistry.get(id);
|
|
282
|
-
if (taskInfo) {
|
|
283
|
-
// Switch to agent mode and set the selected agent
|
|
284
|
-
const context = this.chatService?.getContext();
|
|
285
|
-
const allAgents = agents();
|
|
286
|
-
const selectedAgent = allAgents[taskInfo.agentName];
|
|
287
|
-
|
|
288
|
-
if (context && selectedAgent) {
|
|
289
|
-
context.selectedAgent = selectedAgent;
|
|
290
|
-
context.agentMode = true;
|
|
291
|
-
context.currentAgent = taskInfo.agentName;
|
|
292
|
-
// Update context's model/provider to reflect the agent's settings
|
|
293
|
-
// so /model and /provider commands show accurate information
|
|
294
|
-
context.currentModel = selectedAgent.getModel();
|
|
295
|
-
context.currentProvider = selectedAgent.getProvider();
|
|
296
|
-
console.log(`🔄 Switched to agent mode with ${taskInfo.agentName}`);
|
|
297
|
-
console.log(`📋 Attached to running task: ${id}`);
|
|
298
|
-
console.log(`Task: ${taskInfo.initialInput}`);
|
|
299
|
-
console.log(`Status: ${taskInfo.status}`);
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
console.log(Marked.parse(`**Attached to running task: ${id}**`));
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Check if it's a saved session
|
|
308
|
-
try {
|
|
309
|
-
const session = this.sessionManager.loadSession(id);
|
|
310
|
-
if (session) {
|
|
311
|
-
console.log(Marked.parse(`**Resuming saved session: ${id}**`));
|
|
312
|
-
// Read session to get agent information
|
|
313
|
-
|
|
314
|
-
// Switch to agent mode and set the selected agent
|
|
315
|
-
const context = this.chatService?.getContext();
|
|
316
|
-
const allAgents = agents();
|
|
317
|
-
const selectedAgent = allAgents[session.agentName];
|
|
318
|
-
|
|
319
|
-
if (context && selectedAgent) {
|
|
320
|
-
context.selectedAgent = selectedAgent;
|
|
321
|
-
context.agentMode = true;
|
|
322
|
-
// Update context's model/provider to reflect the agent's settings
|
|
323
|
-
// so /model and /provider commands show accurate information
|
|
324
|
-
context.currentModel = selectedAgent.getModel();
|
|
325
|
-
context.currentProvider = selectedAgent.getProvider();
|
|
326
|
-
console.log(`🔄 Switched to agent mode with ${session.agentName}`);
|
|
327
|
-
console.log(`📋 Resuming saved session: ${id}`);
|
|
328
|
-
console.log(`Original task: ${session.initialInput}`);
|
|
329
|
-
console.log(`Status: ${session.status}`);
|
|
330
|
-
|
|
331
|
-
const addedContext = await this.chatService.getInput(
|
|
332
|
-
"Add any additional context for resuming this session (or press Enter to skip): "
|
|
333
|
-
);
|
|
334
|
-
await this.resumeSession(id);
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
} catch (error) {
|
|
339
|
-
// Session file doesn't exist or error reading it
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
console.log(Marked.parse(`**Session/Task ${id} not found.**`));
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* List available session files
|
|
347
|
-
*/
|
|
348
|
-
public async listAvailableSessions(): Promise<ChatSession[]> {
|
|
349
|
-
return this.sessionManager.listAvailableSessions();
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* List both active tasks and saved sessions for CLI usage
|
|
354
|
-
*/
|
|
355
|
-
public async listSessionsAndTasks(): Promise<{
|
|
356
|
-
runningTasks: TaskInfo[];
|
|
357
|
-
savedSessions: ChatSession[];
|
|
358
|
-
}> {
|
|
359
|
-
const runningTasks = this.taskRegistry.getAll();
|
|
360
|
-
const savedSessions = this.sessionManager.listAvailableSessions();
|
|
361
|
-
return {
|
|
362
|
-
runningTasks,
|
|
363
|
-
savedSessions,
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
|
|
367
475
|
/**
|
|
368
|
-
* Get the
|
|
476
|
+
* Get the process start time
|
|
369
477
|
*/
|
|
370
|
-
public
|
|
371
|
-
return this.
|
|
478
|
+
public getProcessStartTime(): number {
|
|
479
|
+
return this.processStartTime;
|
|
372
480
|
}
|
|
373
481
|
|
|
374
482
|
/**
|
|
375
483
|
* Resume a session from saved state
|
|
376
484
|
*/
|
|
377
|
-
|
|
485
|
+
public async resumeSession(
|
|
378
486
|
sessionId: string,
|
|
379
487
|
resumeReason?: string
|
|
380
488
|
): Promise<void> {
|
|
@@ -439,6 +547,16 @@ Please continue from where you left off and complete the original request.
|
|
|
439
547
|
async handleInput(input: string, context: ChatContext): Promise<boolean> {
|
|
440
548
|
// If in agent mode, start agent with the input as initial task (like original chat.ts)
|
|
441
549
|
if (context.agentMode && context.selectedAgent) {
|
|
550
|
+
// If we're attached to a running agent, forward input to it
|
|
551
|
+
if (this.attachedAgent) {
|
|
552
|
+
this.attachedAgent.addPendingUserMessage({
|
|
553
|
+
role: "user",
|
|
554
|
+
content: input,
|
|
555
|
+
});
|
|
556
|
+
return true;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Otherwise start a new agent task
|
|
442
560
|
// Create initial interaction for the chatHistory
|
|
443
561
|
const initialInteraction: ChatInteraction = {
|
|
444
562
|
input,
|
|
@@ -481,18 +599,22 @@ Please continue from where you left off and complete the original request.
|
|
|
481
599
|
run?: boolean; // whether to run immediately
|
|
482
600
|
taskId?: string; // optional pre-generated taskId
|
|
483
601
|
}) {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if (!allAgents[options.agentName]) {
|
|
602
|
+
if (!agentConstructors[options.agentName as AgentName]) {
|
|
487
603
|
throw new Error(
|
|
488
604
|
`Agent "${
|
|
489
605
|
options.agentName
|
|
490
|
-
}" not found. Available agents: ${Object.keys(
|
|
606
|
+
}" not found. Available agents: ${Object.keys(agentConstructors).join(
|
|
607
|
+
", "
|
|
608
|
+
)}`
|
|
491
609
|
);
|
|
492
610
|
}
|
|
493
611
|
|
|
494
612
|
const { input, chatHistory = [], agentName } = options;
|
|
495
|
-
const
|
|
613
|
+
const agentContext = services().Agents.getAgentContext();
|
|
614
|
+
const agent = createAgent(
|
|
615
|
+
options.agentName as AgentName,
|
|
616
|
+
agentContext
|
|
617
|
+
) as BaseAgent;
|
|
496
618
|
|
|
497
619
|
let done = false;
|
|
498
620
|
let output = "Done";
|
|
@@ -532,45 +654,26 @@ Please continue from where you left off and complete the original request.
|
|
|
532
654
|
this.saveSession(taskId, taskInfo, []);
|
|
533
655
|
|
|
534
656
|
// Reset sync services before setting up new task (removes old listeners)
|
|
535
|
-
this.
|
|
536
|
-
this.fsSync.reset();
|
|
537
|
-
|
|
538
|
-
// Create Knowhow chat task if messageId provided
|
|
539
|
-
if (
|
|
540
|
-
options.messageId &&
|
|
541
|
-
!options.existingKnowhowTaskId &&
|
|
542
|
-
!options.syncFs
|
|
543
|
-
) {
|
|
544
|
-
knowhowTaskId = await this.webSync.createChatTask({
|
|
545
|
-
messageId: options.messageId,
|
|
546
|
-
prompt: input,
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
if (knowhowTaskId) {
|
|
550
|
-
// Update TaskInfo with the created knowhowTaskId
|
|
551
|
-
taskInfo.knowhowTaskId = knowhowTaskId;
|
|
552
|
-
this.taskRegistry.register(taskId, taskInfo);
|
|
657
|
+
this.syncer.reset();
|
|
553
658
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
const fsTaskId = await this.fsSync.createTask({
|
|
564
|
-
taskId,
|
|
565
|
-
prompt: input,
|
|
566
|
-
});
|
|
659
|
+
// Create sync task (SyncerService decides web vs fs internally)
|
|
660
|
+
const syncTaskId = await this.syncer.createTask({
|
|
661
|
+
taskId,
|
|
662
|
+
prompt: input,
|
|
663
|
+
messageId: options.messageId,
|
|
664
|
+
syncFs: options.syncFs,
|
|
665
|
+
existingKnowhowTaskId: options.existingKnowhowTaskId,
|
|
666
|
+
agentName,
|
|
667
|
+
});
|
|
567
668
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
669
|
+
// Update TaskInfo with the sync task ID
|
|
670
|
+
const webTaskId = this.syncer.getCreatedWebTaskId();
|
|
671
|
+
knowhowTaskId = webTaskId;
|
|
672
|
+
taskInfo.knowhowTaskId = webTaskId || syncTaskId;
|
|
673
|
+
this.taskRegistry.register(taskId, taskInfo);
|
|
571
674
|
|
|
572
|
-
|
|
573
|
-
|
|
675
|
+
// Wire up event listeners on the agent
|
|
676
|
+
await this.syncer.setupAgentSync(agent, syncTaskId);
|
|
574
677
|
|
|
575
678
|
// Set up session update listener
|
|
576
679
|
const threadUpdateHandler = async (threadState: any) => {
|
|
@@ -641,29 +744,30 @@ Please continue from where you left off and complete the original request.
|
|
|
641
744
|
]);
|
|
642
745
|
|
|
643
746
|
// Set up event listeners
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
);
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
747
|
+
// Each task gets a fresh agent instance (via createAgent), so no stale listeners exist.
|
|
748
|
+
const agentLogHandler = (logData: any) => {
|
|
749
|
+
this.renderer.render({
|
|
750
|
+
type: "log",
|
|
751
|
+
taskId,
|
|
752
|
+
agentName: logData.agentName,
|
|
753
|
+
message: logData.message,
|
|
754
|
+
level: logData.level,
|
|
755
|
+
timestamp: logData.timestamp,
|
|
756
|
+
});
|
|
757
|
+
};
|
|
758
|
+
const agentStatusHandler = (statusData: any) => {
|
|
759
|
+
this.renderer.render({
|
|
760
|
+
type: "agentStatus",
|
|
761
|
+
taskId,
|
|
762
|
+
agentName: statusData.agentName,
|
|
763
|
+
statusMessage: statusData.statusMessage,
|
|
764
|
+
details: statusData.details,
|
|
765
|
+
timestamp: statusData.timestamp,
|
|
766
|
+
});
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
agent.agentEvents.on(agent.eventTypes.agentLog, agentLogHandler);
|
|
770
|
+
agent.agentEvents.on(agent.eventTypes.agentStatus, agentStatusHandler);
|
|
667
771
|
|
|
668
772
|
const taskCompleted = new Promise<string>((resolve) => {
|
|
669
773
|
agent.agentEvents.once(agent.eventTypes.done, async (doneMsg) => {
|
|
@@ -675,20 +779,20 @@ Please continue from where you left off and complete the original request.
|
|
|
675
779
|
agent.eventTypes.threadUpdate,
|
|
676
780
|
threadUpdateHandler
|
|
677
781
|
);
|
|
782
|
+
// Remove task-specific listeners so they don't fire for the next task
|
|
783
|
+
agent.agentEvents.removeListener(
|
|
784
|
+
agent.eventTypes.agentLog,
|
|
785
|
+
agentLogHandler
|
|
786
|
+
);
|
|
787
|
+
agent.agentEvents.removeListener(
|
|
788
|
+
agent.eventTypes.agentStatus,
|
|
789
|
+
agentStatusHandler
|
|
790
|
+
);
|
|
678
791
|
// Update task info
|
|
679
792
|
taskInfo = this.taskRegistry.get(taskId);
|
|
680
793
|
|
|
681
794
|
// Wait for AgentSync to finish before resolving
|
|
682
|
-
|
|
683
|
-
console.log(
|
|
684
|
-
"🎯 [AgentModule] Waiting for web sync finalization..."
|
|
685
|
-
);
|
|
686
|
-
await this.webSync.waitForFinalization();
|
|
687
|
-
console.log("🎯 [AgentModule] Web sync finalization complete");
|
|
688
|
-
}
|
|
689
|
-
console.log("🎯 [AgentModule] Waiting for fs sync finalization...");
|
|
690
|
-
await this.fsSync.waitForFinalization();
|
|
691
|
-
console.log("🎯 [AgentModule] Fs sync finalization complete");
|
|
795
|
+
await this.syncer.waitForFinalization();
|
|
692
796
|
|
|
693
797
|
if (taskInfo) {
|
|
694
798
|
taskInfo.status = "completed";
|
|
@@ -923,126 +1027,64 @@ Please continue from where you left off and complete the original request.
|
|
|
923
1027
|
|
|
924
1028
|
async attachedAgentChatLoop(
|
|
925
1029
|
taskId: string,
|
|
926
|
-
agent:
|
|
1030
|
+
agent: AttachableAgent,
|
|
927
1031
|
initialInput?: string
|
|
928
1032
|
): Promise<{ result: boolean; finalOutput?: string }> {
|
|
929
1033
|
try {
|
|
930
|
-
let done = false;
|
|
931
|
-
let output = "Done";
|
|
932
1034
|
let agentFinalOutput: string | undefined;
|
|
933
1035
|
|
|
934
|
-
//
|
|
935
|
-
// Set mode to agent:attached so custom commands are available
|
|
1036
|
+
// Set mode to agent:attached so mode-specific commands are available
|
|
936
1037
|
if (this.chatService) {
|
|
937
1038
|
this.chatService.setMode("agent:attached");
|
|
938
1039
|
}
|
|
939
1040
|
|
|
940
|
-
//
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
"/done",
|
|
953
|
-
];
|
|
954
|
-
const history: string[] = [];
|
|
1041
|
+
// Wire up rendering event listeners and track the active task
|
|
1042
|
+
this.wireAgentRendering(
|
|
1043
|
+
taskId,
|
|
1044
|
+
agent.agentEvents,
|
|
1045
|
+
agent.eventTypes,
|
|
1046
|
+
agent.name
|
|
1047
|
+
);
|
|
1048
|
+
const context = this.chatService?.getContext();
|
|
1049
|
+
if (context) context.activeAgentTaskId = taskId;
|
|
1050
|
+
|
|
1051
|
+
// Store the agent so the registered agent:attached commands can reference it
|
|
1052
|
+
this.attachedAgent = agent;
|
|
955
1053
|
|
|
956
1054
|
// Set up the event listener BEFORE starting the agent to avoid race condition
|
|
957
|
-
let finished = false;
|
|
958
1055
|
const donePromise = new Promise<string>((resolve) => {
|
|
959
1056
|
agent.agentEvents.once(agent.eventTypes.done, (doneMsg) => {
|
|
960
1057
|
// Capture the agent's final output
|
|
961
1058
|
agentFinalOutput = doneMsg || "No response from the AI";
|
|
962
1059
|
console.log("Finished", taskId, `$${agent.getTotalCostUsd()}`);
|
|
963
|
-
|
|
1060
|
+
|
|
1061
|
+
// Update final task status
|
|
1062
|
+
const finalTaskInfo = this.taskRegistry.get(taskId);
|
|
1063
|
+
if (finalTaskInfo) {
|
|
1064
|
+
if (finalTaskInfo.status === "running") {
|
|
1065
|
+
finalTaskInfo.status = "completed";
|
|
1066
|
+
finalTaskInfo.totalCost = agent.getTotalCostUsd();
|
|
1067
|
+
finalTaskInfo.endTime = Date.now();
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
|
|
964
1071
|
resolve("done");
|
|
1072
|
+
// Exit agent:attached mode so the prompt resets back to the default
|
|
1073
|
+
this.detachFromAgent();
|
|
965
1074
|
});
|
|
966
1075
|
});
|
|
967
1076
|
|
|
968
1077
|
// Now start the agent if we have an initial input (this means we're starting, not just attaching)
|
|
969
1078
|
if (initialInput) {
|
|
970
1079
|
const taskInfo = this.taskRegistry.get(taskId);
|
|
971
|
-
agent.call(
|
|
1080
|
+
(agent as BaseAgent).call(
|
|
972
1081
|
taskInfo?.formattedPrompt || taskInfo?.initialInput || initialInput
|
|
973
1082
|
);
|
|
974
1083
|
}
|
|
975
1084
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
commands
|
|
980
|
-
)) || "";
|
|
981
|
-
|
|
982
|
-
history.push(input);
|
|
983
|
-
|
|
984
|
-
while (!done) {
|
|
985
|
-
switch (input) {
|
|
986
|
-
case "":
|
|
987
|
-
if (finished) {
|
|
988
|
-
output = "Agent has completed the task.";
|
|
989
|
-
done = true;
|
|
990
|
-
}
|
|
991
|
-
break;
|
|
992
|
-
case "/done":
|
|
993
|
-
output = "Exited agent interaction.";
|
|
994
|
-
done = true;
|
|
995
|
-
break;
|
|
996
|
-
case "/pause":
|
|
997
|
-
await agent.pause();
|
|
998
|
-
console.log("Agent paused.");
|
|
999
|
-
break;
|
|
1000
|
-
case "/unpause":
|
|
1001
|
-
await agent.unpause();
|
|
1002
|
-
console.log("Agent unpaused.");
|
|
1003
|
-
break;
|
|
1004
|
-
case "/kill":
|
|
1005
|
-
await agent.kill();
|
|
1006
|
-
console.log("Agent terminated.");
|
|
1007
|
-
done = true;
|
|
1008
|
-
break;
|
|
1009
|
-
case "/detach":
|
|
1010
|
-
console.log("Detached from agent");
|
|
1011
|
-
// Reset mode back to default when detaching
|
|
1012
|
-
if (this.chatService) {
|
|
1013
|
-
this.chatService.setMode("default");
|
|
1014
|
-
}
|
|
1015
|
-
return { result: true, finalOutput: agentFinalOutput };
|
|
1016
|
-
default:
|
|
1017
|
-
agent.addPendingUserMessage({
|
|
1018
|
-
role: "user",
|
|
1019
|
-
content: input,
|
|
1020
|
-
});
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
if (!done) {
|
|
1024
|
-
input = await this.chatService?.getInput(
|
|
1025
|
-
`Enter command or message for ${agent.name}: `,
|
|
1026
|
-
commands
|
|
1027
|
-
);
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
// Reset mode back to default when exiting loop
|
|
1032
|
-
if (this.chatService) {
|
|
1033
|
-
this.chatService.setMode("default");
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
// Update final task status and save session
|
|
1037
|
-
const finalTaskInfo = this.taskRegistry.get(taskId);
|
|
1038
|
-
if (finalTaskInfo) {
|
|
1039
|
-
if (finalTaskInfo.status === "running") {
|
|
1040
|
-
finalTaskInfo.status = "completed";
|
|
1041
|
-
// Ensure final cost is captured
|
|
1042
|
-
finalTaskInfo.totalCost = agent.getTotalCostUsd();
|
|
1043
|
-
finalTaskInfo.endTime = Date.now();
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1085
|
+
// Return immediately — the main startChatLoop on CliChatService
|
|
1086
|
+
// now handles all user input via the registered agent:attached commands.
|
|
1087
|
+
// Any non-command input is forwarded to the agent via handleInput below.
|
|
1046
1088
|
return { result: true, finalOutput: agentFinalOutput };
|
|
1047
1089
|
} catch (error) {
|
|
1048
1090
|
console.error("Agent execution failed:", error);
|