@tyvm/knowhow 0.0.145 → 0.0.147
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/autodoc/cli-reference.md +36 -7
- package/bin/knowhow.js +8 -6
- package/package.json +1 -1
- package/src/agents/base/base.ts +24 -0
- package/src/agents/historyRollback.ts +36 -0
- package/src/agents/tools/startAgentTask.ts +41 -9
- package/src/auth/browserLogin.ts +9 -3
- package/src/auth/keyAuth.ts +115 -0
- package/src/auth/keyManager.ts +166 -0
- package/src/chat/CliChatService.ts +16 -0
- package/src/chat/modules/AgentModule.ts +144 -56
- package/src/chat/modules/AskModule.ts +2 -0
- package/src/chat/modules/BaseChatModule.ts +0 -1
- package/src/chat/modules/CustomCommandsModule.ts +2 -0
- package/src/chat/modules/InternalChatModule.ts +2 -0
- package/src/chat/modules/RemoteSyncModule.ts +4 -0
- package/src/chat/modules/RendererModule.ts +2 -0
- package/src/chat/modules/SearchModule.ts +2 -0
- package/src/chat/modules/SessionsModule.ts +110 -39
- package/src/chat/modules/SetupModule.ts +2 -0
- package/src/chat/modules/ShellCommandModule.ts +2 -0
- package/src/chat/modules/SystemModule.ts +2 -0
- package/src/chat/types.ts +5 -2
- package/src/cli.ts +1 -1
- package/src/clients/anthropic.ts +24 -0
- package/src/clients/fireworks.ts +3 -0
- package/src/clients/gemini.ts +8 -0
- package/src/clients/index.ts +2 -0
- package/src/clients/openai.ts +7 -4
- package/src/clients/types.ts +30 -7
- package/src/clients/xai.ts +23 -4
- package/src/commands/agent.ts +11 -39
- package/src/commands/agents.ts +403 -53
- package/src/commands/misc.ts +3 -2
- package/src/commands/services.ts +49 -3
- package/src/login.ts +89 -28
- package/src/plugins/plugins.ts +16 -0
- package/src/processors/TokenCompressor.ts +40 -8
- package/src/processors/ToolResponseCache.ts +17 -8
- package/src/processors/tools/boundedToolResponse.ts +49 -0
- package/src/processors/tools/grepToolResponse.ts +164 -38
- package/src/processors/tools/index.ts +2 -0
- package/src/processors/tools/jqToolResponse.ts +40 -10
- package/src/processors/tools/listStoredToolResponses.ts +51 -10
- package/src/processors/tools/tailToolResponse.ts +85 -17
- package/src/services/AgentService.ts +2 -0
- package/src/services/AgentSyncFs.ts +65 -0
- package/src/services/AgentSyncKnowhowWeb.ts +22 -4
- package/src/services/BehaviorsService.ts +2 -0
- package/src/services/DockerService.ts +2 -0
- package/src/services/EmbeddingService.ts +2 -0
- package/src/services/EmbeddingsService.ts +3 -0
- package/src/services/KnowhowClient.ts +68 -7
- package/src/services/LazyToolsService.ts +16 -0
- package/src/services/Mcp.ts +11 -2
- package/src/services/McpServer.ts +2 -0
- package/src/services/MessageProcessor.ts +2 -0
- package/src/services/MinimalToolsService.ts +2 -0
- package/src/services/RuntimeReloadService.ts +31 -0
- package/src/services/SessionManager.ts +5 -0
- package/src/services/SkillsService.ts +2 -0
- package/src/services/SyncedAgentWatcher.ts +2 -0
- package/src/services/SyncerService.ts +23 -8
- package/src/services/TaskRegistry.ts +2 -0
- package/src/services/Tools.ts +13 -0
- package/src/services/TracingService.ts +116 -0
- package/src/services/index.ts +10 -0
- package/src/services/modules/index.ts +49 -3
- package/src/services/modules/types.ts +8 -0
- package/src/types.ts +2 -0
- package/src/util/Trace.ts +236 -0
- package/src/utils/http.ts +18 -2
- package/tests/clients/fireworks.test.ts +65 -0
- package/tests/clients/reasoningEffort.test.ts +79 -0
- package/tests/compressor/toolResponseCache.test.ts +2 -1
- package/tests/manual/clients/completions.test.ts +27 -10
- package/tests/processors/TokenCompressor.test.ts +17 -3
- package/tests/processors/tools/boundedRetrievalTools.test.ts +68 -0
- package/tests/processors/tools/grepToolResponse.test.ts +88 -1
- package/tests/unit/agents/historyRollback.test.ts +53 -0
- package/tests/unit/auth/keyAuth.test.ts +102 -0
- package/tests/unit/auth/keyManager.test.ts +67 -0
- package/tests/unit/chat/historyCommandArgs.test.ts +37 -0
- package/tests/unit/commands/agents.test.ts +68 -0
- package/tests/unit/login.test.ts +119 -0
- package/tests/unit/plugins/pluginLoading.test.ts +31 -0
- package/tests/unit/services/AgentSyncKnowhowWeb.test.ts +38 -0
- package/tests/unit/services/LazyToolsService.test.ts +29 -0
- package/tests/unit/services/RuntimeReloadService.test.ts +29 -0
- package/tests/unit/services/SessionManager.test.ts +43 -0
- package/tests/unit/services/SyncerService.test.ts +45 -0
- package/tests/unit/util/Trace.test.ts +119 -0
- package/tests/unit/utils/http.test.ts +43 -0
- package/ts_build/package.json +1 -1
- package/ts_build/src/agents/base/base.d.ts +1 -0
- package/ts_build/src/agents/base/base.js +31 -2
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/historyRollback.d.ts +2 -0
- package/ts_build/src/agents/historyRollback.js +22 -0
- package/ts_build/src/agents/historyRollback.js.map +1 -0
- package/ts_build/src/agents/tools/startAgentTask.d.ts +2 -0
- package/ts_build/src/agents/tools/startAgentTask.js +36 -9
- package/ts_build/src/agents/tools/startAgentTask.js.map +1 -1
- package/ts_build/src/auth/browserLogin.d.ts +1 -0
- package/ts_build/src/auth/browserLogin.js +5 -2
- package/ts_build/src/auth/browserLogin.js.map +1 -1
- package/ts_build/src/auth/keyAuth.d.ts +5 -0
- package/ts_build/src/auth/keyAuth.js +79 -0
- package/ts_build/src/auth/keyAuth.js.map +1 -0
- package/ts_build/src/auth/keyManager.d.ts +14 -0
- package/ts_build/src/auth/keyManager.js +145 -0
- package/ts_build/src/auth/keyManager.js.map +1 -0
- package/ts_build/src/chat/CliChatService.js +15 -0
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +13 -1
- package/ts_build/src/chat/modules/AgentModule.js +96 -43
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/AskModule.js +12 -2
- package/ts_build/src/chat/modules/AskModule.js.map +1 -1
- package/ts_build/src/chat/modules/BaseChatModule.js.map +1 -1
- package/ts_build/src/chat/modules/CustomCommandsModule.js +12 -2
- package/ts_build/src/chat/modules/CustomCommandsModule.js.map +1 -1
- package/ts_build/src/chat/modules/InternalChatModule.js +16 -2
- package/ts_build/src/chat/modules/InternalChatModule.js.map +1 -1
- package/ts_build/src/chat/modules/RemoteSyncModule.js +19 -2
- package/ts_build/src/chat/modules/RemoteSyncModule.js.map +1 -1
- package/ts_build/src/chat/modules/RendererModule.js +17 -2
- package/ts_build/src/chat/modules/RendererModule.js.map +1 -1
- package/ts_build/src/chat/modules/SearchModule.js +12 -2
- package/ts_build/src/chat/modules/SearchModule.js.map +1 -1
- package/ts_build/src/chat/modules/SessionsModule.d.ts +6 -0
- package/ts_build/src/chat/modules/SessionsModule.js +114 -24
- package/ts_build/src/chat/modules/SessionsModule.js.map +1 -1
- package/ts_build/src/chat/modules/SetupModule.js +17 -2
- package/ts_build/src/chat/modules/SetupModule.js.map +1 -1
- package/ts_build/src/chat/modules/ShellCommandModule.js +12 -2
- package/ts_build/src/chat/modules/ShellCommandModule.js.map +1 -1
- package/ts_build/src/chat/modules/SystemModule.js +12 -2
- package/ts_build/src/chat/modules/SystemModule.js.map +1 -1
- package/ts_build/src/chat/types.d.ts +5 -2
- package/ts_build/src/cli.js +1 -1
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +1 -0
- package/ts_build/src/clients/anthropic.js +12 -0
- package/ts_build/src/clients/anthropic.js.map +1 -1
- package/ts_build/src/clients/fireworks.js +1 -0
- package/ts_build/src/clients/fireworks.js.map +1 -1
- package/ts_build/src/clients/gemini.js +8 -0
- package/ts_build/src/clients/gemini.js.map +1 -1
- package/ts_build/src/clients/index.js +19 -4
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/clients/openai.js +4 -2
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/types.d.ts +4 -1
- package/ts_build/src/clients/types.js +14 -0
- package/ts_build/src/clients/types.js.map +1 -1
- package/ts_build/src/clients/xai.d.ts +1 -0
- package/ts_build/src/clients/xai.js +23 -4
- package/ts_build/src/clients/xai.js.map +1 -1
- package/ts_build/src/commands/agent.js +7 -22
- package/ts_build/src/commands/agent.js.map +1 -1
- package/ts_build/src/commands/agents.d.ts +1 -1
- package/ts_build/src/commands/agents.js +174 -16
- package/ts_build/src/commands/agents.js.map +1 -1
- package/ts_build/src/commands/misc.js +3 -2
- package/ts_build/src/commands/misc.js.map +1 -1
- package/ts_build/src/commands/services.d.ts +2 -0
- package/ts_build/src/commands/services.js +45 -3
- package/ts_build/src/commands/services.js.map +1 -1
- package/ts_build/src/login.d.ts +1 -1
- package/ts_build/src/login.js +53 -15
- package/ts_build/src/login.js.map +1 -1
- package/ts_build/src/plugins/plugins.d.ts +1 -0
- package/ts_build/src/plugins/plugins.js +14 -0
- package/ts_build/src/plugins/plugins.js.map +1 -1
- package/ts_build/src/processors/TokenCompressor.js +15 -6
- package/ts_build/src/processors/TokenCompressor.js.map +1 -1
- package/ts_build/src/processors/ToolResponseCache.d.ts +3 -3
- package/ts_build/src/processors/ToolResponseCache.js +8 -8
- package/ts_build/src/processors/ToolResponseCache.js.map +1 -1
- package/ts_build/src/processors/tools/boundedToolResponse.d.ts +7 -0
- package/ts_build/src/processors/tools/boundedToolResponse.js +27 -0
- package/ts_build/src/processors/tools/boundedToolResponse.js.map +1 -0
- package/ts_build/src/processors/tools/grepToolResponse.d.ts +4 -0
- package/ts_build/src/processors/tools/grepToolResponse.js +101 -25
- package/ts_build/src/processors/tools/grepToolResponse.js.map +1 -1
- package/ts_build/src/processors/tools/index.d.ts +2 -2
- package/ts_build/src/processors/tools/index.js.map +1 -1
- package/ts_build/src/processors/tools/jqToolResponse.d.ts +5 -1
- package/ts_build/src/processors/tools/jqToolResponse.js +26 -9
- package/ts_build/src/processors/tools/jqToolResponse.js.map +1 -1
- package/ts_build/src/processors/tools/listStoredToolResponses.d.ts +7 -1
- package/ts_build/src/processors/tools/listStoredToolResponses.js +39 -9
- package/ts_build/src/processors/tools/listStoredToolResponses.js.map +1 -1
- package/ts_build/src/processors/tools/tailToolResponse.d.ts +5 -0
- package/ts_build/src/processors/tools/tailToolResponse.js +56 -13
- package/ts_build/src/processors/tools/tailToolResponse.js.map +1 -1
- package/ts_build/src/services/AgentService.js +18 -2
- package/ts_build/src/services/AgentService.js.map +1 -1
- package/ts_build/src/services/AgentSyncFs.d.ts +3 -0
- package/ts_build/src/services/AgentSyncFs.js +62 -15
- package/ts_build/src/services/AgentSyncFs.js.map +1 -1
- package/ts_build/src/services/AgentSyncKnowhowWeb.d.ts +2 -0
- package/ts_build/src/services/AgentSyncKnowhowWeb.js +28 -6
- package/ts_build/src/services/AgentSyncKnowhowWeb.js.map +1 -1
- package/ts_build/src/services/BehaviorsService.js +12 -2
- package/ts_build/src/services/BehaviorsService.js.map +1 -1
- package/ts_build/src/services/DockerService.js +20 -8
- package/ts_build/src/services/DockerService.js.map +1 -1
- package/ts_build/src/services/EmbeddingService.js +16 -2
- package/ts_build/src/services/EmbeddingService.js.map +1 -1
- package/ts_build/src/services/EmbeddingsService.js +12 -2
- package/ts_build/src/services/EmbeddingsService.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.d.ts +7 -2
- package/ts_build/src/services/KnowhowClient.js +108 -10
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/LazyToolsService.d.ts +2 -0
- package/ts_build/src/services/LazyToolsService.js +26 -2
- package/ts_build/src/services/LazyToolsService.js.map +1 -1
- package/ts_build/src/services/Mcp.js +20 -4
- package/ts_build/src/services/Mcp.js.map +1 -1
- package/ts_build/src/services/McpServer.js +17 -2
- package/ts_build/src/services/McpServer.js.map +1 -1
- package/ts_build/src/services/MessageProcessor.js +16 -2
- package/ts_build/src/services/MessageProcessor.js.map +1 -1
- package/ts_build/src/services/MinimalToolsService.js +16 -2
- package/ts_build/src/services/MinimalToolsService.js.map +1 -1
- package/ts_build/src/services/RuntimeReloadService.d.ts +12 -0
- package/ts_build/src/services/RuntimeReloadService.js +26 -0
- package/ts_build/src/services/RuntimeReloadService.js.map +1 -0
- package/ts_build/src/services/SessionManager.js +19 -2
- package/ts_build/src/services/SessionManager.js.map +1 -1
- package/ts_build/src/services/SkillsService.js +16 -2
- package/ts_build/src/services/SkillsService.js.map +1 -1
- package/ts_build/src/services/SyncedAgentWatcher.js +16 -2
- package/ts_build/src/services/SyncedAgentWatcher.js.map +1 -1
- package/ts_build/src/services/SyncerService.d.ts +1 -0
- package/ts_build/src/services/SyncerService.js +27 -5
- package/ts_build/src/services/SyncerService.js.map +1 -1
- package/ts_build/src/services/TaskRegistry.js +12 -2
- package/ts_build/src/services/TaskRegistry.js.map +1 -1
- package/ts_build/src/services/Tools.d.ts +1 -0
- package/ts_build/src/services/Tools.js +21 -2
- package/ts_build/src/services/Tools.js.map +1 -1
- package/ts_build/src/services/TracingService.d.ts +16 -0
- package/ts_build/src/services/TracingService.js +35 -0
- package/ts_build/src/services/TracingService.js.map +1 -0
- package/ts_build/src/services/index.d.ts +8 -0
- package/ts_build/src/services/index.js +9 -1
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/src/services/modules/index.d.ts +6 -0
- package/ts_build/src/services/modules/index.js +29 -3
- package/ts_build/src/services/modules/index.js.map +1 -1
- package/ts_build/src/services/modules/types.d.ts +3 -0
- package/ts_build/src/types.d.ts +1 -0
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/util/Trace.d.ts +11 -0
- package/ts_build/src/util/Trace.js +107 -0
- package/ts_build/src/util/Trace.js.map +1 -0
- package/ts_build/src/utils/http.d.ts +6 -2
- package/ts_build/src/utils/http.js +8 -2
- package/ts_build/src/utils/http.js.map +1 -1
- package/ts_build/tests/clients/fireworks.test.d.ts +1 -0
- package/ts_build/tests/clients/fireworks.test.js +65 -0
- package/ts_build/tests/clients/fireworks.test.js.map +1 -0
- package/ts_build/tests/clients/reasoningEffort.test.d.ts +1 -0
- package/ts_build/tests/clients/reasoningEffort.test.js +68 -0
- package/ts_build/tests/clients/reasoningEffort.test.js.map +1 -0
- package/ts_build/tests/compressor/toolResponseCache.test.js +1 -1
- package/ts_build/tests/compressor/toolResponseCache.test.js.map +1 -1
- package/ts_build/tests/manual/clients/completions.test.js +19 -6
- package/ts_build/tests/manual/clients/completions.test.js.map +1 -1
- package/ts_build/tests/processors/TokenCompressor.test.js +11 -2
- package/ts_build/tests/processors/TokenCompressor.test.js.map +1 -1
- package/ts_build/tests/processors/tools/boundedRetrievalTools.test.d.ts +1 -0
- package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js +57 -0
- package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js.map +1 -0
- package/ts_build/tests/processors/tools/grepToolResponse.test.js +37 -0
- package/ts_build/tests/processors/tools/grepToolResponse.test.js.map +1 -1
- package/ts_build/tests/unit/agents/historyRollback.test.d.ts +1 -0
- package/ts_build/tests/unit/agents/historyRollback.test.js +42 -0
- package/ts_build/tests/unit/agents/historyRollback.test.js.map +1 -0
- package/ts_build/tests/unit/auth/keyAuth.test.d.ts +1 -0
- package/ts_build/tests/unit/auth/keyAuth.test.js +77 -0
- package/ts_build/tests/unit/auth/keyAuth.test.js.map +1 -0
- package/ts_build/tests/unit/auth/keyManager.test.d.ts +1 -0
- package/ts_build/tests/unit/auth/keyManager.test.js +52 -0
- package/ts_build/tests/unit/auth/keyManager.test.js.map +1 -0
- package/ts_build/tests/unit/chat/historyCommandArgs.test.d.ts +1 -0
- package/ts_build/tests/unit/chat/historyCommandArgs.test.js +29 -0
- package/ts_build/tests/unit/chat/historyCommandArgs.test.js.map +1 -0
- package/ts_build/tests/unit/commands/agents.test.d.ts +1 -0
- package/ts_build/tests/unit/commands/agents.test.js +91 -0
- package/ts_build/tests/unit/commands/agents.test.js.map +1 -0
- package/ts_build/tests/unit/login.test.d.ts +1 -0
- package/ts_build/tests/unit/login.test.js +97 -0
- package/ts_build/tests/unit/login.test.js.map +1 -0
- package/ts_build/tests/unit/plugins/pluginLoading.test.js +59 -0
- package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -1
- package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.d.ts +1 -0
- package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js +32 -0
- package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js.map +1 -0
- package/ts_build/tests/unit/services/LazyToolsService.test.d.ts +1 -0
- package/ts_build/tests/unit/services/LazyToolsService.test.js +27 -0
- package/ts_build/tests/unit/services/LazyToolsService.test.js.map +1 -0
- package/ts_build/tests/unit/services/RuntimeReloadService.test.d.ts +1 -0
- package/ts_build/tests/unit/services/RuntimeReloadService.test.js +26 -0
- package/ts_build/tests/unit/services/RuntimeReloadService.test.js.map +1 -0
- package/ts_build/tests/unit/services/SessionManager.test.d.ts +1 -0
- package/ts_build/tests/unit/services/SessionManager.test.js +72 -0
- package/ts_build/tests/unit/services/SessionManager.test.js.map +1 -0
- package/ts_build/tests/unit/services/SyncerService.test.d.ts +1 -0
- package/ts_build/tests/unit/services/SyncerService.test.js +40 -0
- package/ts_build/tests/unit/services/SyncerService.test.js.map +1 -0
- package/ts_build/tests/unit/util/Trace.test.d.ts +1 -0
- package/ts_build/tests/unit/util/Trace.test.js +107 -0
- package/ts_build/tests/unit/util/Trace.test.js.map +1 -0
- package/ts_build/tests/unit/utils/http.test.d.ts +1 -0
- package/ts_build/tests/unit/utils/http.test.js +69 -0
- package/ts_build/tests/unit/utils/http.test.js.map +1 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Handles synchronization via filesystem files in .knowhow/processes/agents/taskId/
|
|
4
4
|
*/
|
|
5
5
|
import { BaseAgent } from "../agents/base/base";
|
|
6
|
+
import { TraceAll } from "../util/Trace";
|
|
6
7
|
import { promises as fs } from "fs";
|
|
7
8
|
import * as path from "path";
|
|
8
9
|
import { watch } from "fs";
|
|
@@ -19,6 +20,7 @@ export interface FsSyncOptions {
|
|
|
19
20
|
* AgentSyncFs handles filesystem-based synchronization for agent tasks
|
|
20
21
|
* Creates files in .knowhow/processes/agents/{taskId}/ for status and input
|
|
21
22
|
*/
|
|
23
|
+
@TraceAll()
|
|
22
24
|
export class AgentSyncFs {
|
|
23
25
|
/** Shared cleanup interval across all instances to avoid duplicate cleanup runs */
|
|
24
26
|
private static sharedCleanupInterval: NodeJS.Timeout | null = null;
|
|
@@ -128,6 +130,66 @@ export class AgentSyncFs {
|
|
|
128
130
|
}
|
|
129
131
|
}
|
|
130
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Persist the remote identity alongside the local task. Keeping the local
|
|
135
|
+
* slug and remote UUID as separate fields lets resume reconnect without ever
|
|
136
|
+
* mistaking one for the other.
|
|
137
|
+
*/
|
|
138
|
+
static async persistRemoteIdentity(
|
|
139
|
+
taskId: string,
|
|
140
|
+
remoteTaskId: string,
|
|
141
|
+
remoteMessageId?: string
|
|
142
|
+
): Promise<void> {
|
|
143
|
+
const taskPath = path.join(AgentSyncFs.sharedBasePath, taskId);
|
|
144
|
+
await AgentSyncFs.writeRemoteIdentity(
|
|
145
|
+
taskPath,
|
|
146
|
+
remoteTaskId,
|
|
147
|
+
remoteMessageId
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async setRemoteIdentity(
|
|
152
|
+
remoteTaskId: string,
|
|
153
|
+
remoteMessageId?: string
|
|
154
|
+
): Promise<void> {
|
|
155
|
+
if (!this.taskPath) return;
|
|
156
|
+
await AgentSyncFs.writeRemoteIdentity(this.taskPath, remoteTaskId, remoteMessageId);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
private static async writeRemoteIdentity(
|
|
160
|
+
taskPath: string,
|
|
161
|
+
remoteTaskId: string,
|
|
162
|
+
remoteMessageId?: string
|
|
163
|
+
): Promise<void> {
|
|
164
|
+
try {
|
|
165
|
+
const metadataPath = path.join(taskPath, "metadata.json");
|
|
166
|
+
let metadata: any = {};
|
|
167
|
+
try {
|
|
168
|
+
metadata = JSON.parse(await fs.readFile(metadataPath, "utf8"));
|
|
169
|
+
} catch {
|
|
170
|
+
// The normal path already created metadata, but recover if it was
|
|
171
|
+
// removed or malformed while the task was running.
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
metadata.remoteTaskId = remoteTaskId;
|
|
175
|
+
// Preserve the established session field name for compatibility with
|
|
176
|
+
// callers that already read knowhowTaskId.
|
|
177
|
+
metadata.knowhowTaskId = remoteTaskId;
|
|
178
|
+
if (remoteMessageId) {
|
|
179
|
+
metadata.remoteMessageId = remoteMessageId;
|
|
180
|
+
metadata.knowhowMessageId = remoteMessageId;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
await fs.writeFile(
|
|
184
|
+
metadataPath,
|
|
185
|
+
JSON.stringify(metadata, null, 2),
|
|
186
|
+
"utf8"
|
|
187
|
+
);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.error(`❌ Failed to persist remote task identity:`, error);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
131
193
|
/**
|
|
132
194
|
* Append a token usage entry (including the full message chain sent for
|
|
133
195
|
* that call) to usage.json. This is intended for debugging cache-hit
|
|
@@ -217,6 +279,9 @@ export class AgentSyncFs {
|
|
|
217
279
|
// thread messages via `_reasoning_details` / `reasoning_summary`.)
|
|
218
280
|
metadata.reasoningEffort = agent.getReasoningEffort?.();
|
|
219
281
|
metadata.summarizeReasoning = agent.getSummarizeReasoning?.();
|
|
282
|
+
// Tool schemas are part of the provider cache prefix. Preserve the exact
|
|
283
|
+
// request-visible list so resume/fork can recreate the same request.
|
|
284
|
+
metadata.enabledTools = agent.getEnabledToolNames();
|
|
220
285
|
metadata.inProgress = inProgress;
|
|
221
286
|
metadata.lastUpdate = new Date().toISOString();
|
|
222
287
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from "./KnowhowClient";
|
|
11
11
|
import { BaseAgent } from "../agents/base/base";
|
|
12
12
|
import { wait } from "../utils";
|
|
13
|
+
import { TraceAll } from "../util/Trace";
|
|
13
14
|
|
|
14
15
|
export interface SyncOptions {
|
|
15
16
|
messageId?: string;
|
|
@@ -27,6 +28,7 @@ export interface TaskSyncState {
|
|
|
27
28
|
* AgentSynchronization handles all communication with the Knowhow API
|
|
28
29
|
* for task creation, updates, status polling, and message synchronization
|
|
29
30
|
*/
|
|
31
|
+
@TraceAll()
|
|
30
32
|
export class AgentSyncKnowhowWeb {
|
|
31
33
|
private client: KnowhowSimpleClient;
|
|
32
34
|
private baseUrl: string;
|
|
@@ -36,6 +38,7 @@ export class AgentSyncKnowhowWeb {
|
|
|
36
38
|
private agent: BaseAgent | undefined;
|
|
37
39
|
private threadUpdateHandler: ((...args: any[]) => void) | undefined;
|
|
38
40
|
private doneHandler: ((...args: any[]) => void) | undefined;
|
|
41
|
+
private syncErrorLogged = false;
|
|
39
42
|
/**
|
|
40
43
|
* Tracks the most recent in-flight thread update API call.
|
|
41
44
|
* The done handler awaits this before sending the finalization call,
|
|
@@ -48,6 +51,17 @@ export class AgentSyncKnowhowWeb {
|
|
|
48
51
|
this.client = new KnowhowSimpleClient(baseUrl);
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Remote outages can make both the update and pending-message requests fail
|
|
56
|
+
* on every thread event. Report the first failure for this task, then stay
|
|
57
|
+
* quiet so an unavailable optional sync service does not flood the chat.
|
|
58
|
+
*/
|
|
59
|
+
private reportSyncErrorOnce(message: string, error: unknown): void {
|
|
60
|
+
if (this.syncErrorLogged) return;
|
|
61
|
+
this.syncErrorLogged = true;
|
|
62
|
+
console.error(message, error);
|
|
63
|
+
}
|
|
64
|
+
|
|
51
65
|
/**
|
|
52
66
|
* Create a new chat task in Knowhow
|
|
53
67
|
*/
|
|
@@ -68,7 +82,7 @@ export class AgentSyncKnowhowWeb {
|
|
|
68
82
|
console.log(`✅ Created Knowhow chat task: ${knowhowTaskId}`);
|
|
69
83
|
return knowhowTaskId;
|
|
70
84
|
} catch (error) {
|
|
71
|
-
|
|
85
|
+
this.reportSyncErrorOnce(`❌ Failed to create Knowhow chat task:`, error);
|
|
72
86
|
return undefined;
|
|
73
87
|
}
|
|
74
88
|
}
|
|
@@ -95,7 +109,7 @@ export class AgentSyncKnowhowWeb {
|
|
|
95
109
|
});
|
|
96
110
|
console.log(`✅ Updated Knowhow chat task: ${knowhowTaskId}`);
|
|
97
111
|
} catch (error) {
|
|
98
|
-
|
|
112
|
+
this.reportSyncErrorOnce(`❌ Failed to update Knowhow chat task:`, error);
|
|
99
113
|
}
|
|
100
114
|
}
|
|
101
115
|
|
|
@@ -167,7 +181,10 @@ export class AgentSyncKnowhowWeb {
|
|
|
167
181
|
await this.client.markMessagesAsProcessed(knowhowTaskId, messageIds);
|
|
168
182
|
console.log(`✅ Marked ${messageIds.length} message(s) as processed`);
|
|
169
183
|
} catch (error) {
|
|
170
|
-
|
|
184
|
+
this.reportSyncErrorOnce(
|
|
185
|
+
`❌ Error checking/processing pending messages:`,
|
|
186
|
+
error
|
|
187
|
+
);
|
|
171
188
|
// Continue execution even if synchronization fails
|
|
172
189
|
}
|
|
173
190
|
}
|
|
@@ -226,7 +243,7 @@ export class AgentSyncKnowhowWeb {
|
|
|
226
243
|
}
|
|
227
244
|
// Still paused, continue waiting
|
|
228
245
|
} catch (error) {
|
|
229
|
-
|
|
246
|
+
this.reportSyncErrorOnce(`❌ Error polling task status:`, error);
|
|
230
247
|
// Continue polling even on errors
|
|
231
248
|
}
|
|
232
249
|
}
|
|
@@ -350,6 +367,7 @@ export class AgentSyncKnowhowWeb {
|
|
|
350
367
|
this.eventHandlersSetup = false;
|
|
351
368
|
this.finalizationPromise = null;
|
|
352
369
|
this.pendingThreadUpdatePromise = null;
|
|
370
|
+
this.syncErrorLogged = false;
|
|
353
371
|
}
|
|
354
372
|
|
|
355
373
|
/**
|
|
@@ -4,6 +4,7 @@ import * as os from "os";
|
|
|
4
4
|
import { KnowhowSimpleClient } from "./KnowhowClient";
|
|
5
5
|
import { createHash } from "crypto";
|
|
6
6
|
import { getConfig } from "../config";
|
|
7
|
+
import { TraceAll } from "../util/Trace";
|
|
7
8
|
|
|
8
9
|
const BEHAVIORS_DIR = ".knowhow/behaviors";
|
|
9
10
|
const LOCAL_SKILLS_DIRS = [".agents/skills", ".knowhow/skills"];
|
|
@@ -30,6 +31,7 @@ export interface Behavior {
|
|
|
30
31
|
* In-memory singleton for behaviors/skills.
|
|
31
32
|
* Call initFromDisk() once at startup; tools then read from memory.
|
|
32
33
|
*/
|
|
34
|
+
@TraceAll()
|
|
33
35
|
export class BehaviorsService {
|
|
34
36
|
private behaviors: Behavior[] = [];
|
|
35
37
|
private skills: Behavior[] = [];
|
|
@@ -4,6 +4,7 @@ import * as os from "os";
|
|
|
4
4
|
import { Config } from "../types";
|
|
5
5
|
import { updateConfig } from "../config";
|
|
6
6
|
import * as crypto from "crypto";
|
|
7
|
+
import { TraceAll } from "../util/Trace";
|
|
7
8
|
|
|
8
9
|
export interface DockerWorkerOptions {
|
|
9
10
|
workspaceDir: string;
|
|
@@ -14,6 +15,7 @@ export interface DockerWorkerOptions {
|
|
|
14
15
|
unshare?: boolean;
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
@TraceAll()
|
|
17
19
|
export class DockerService {
|
|
18
20
|
private static readonly IMAGE_NAME = "knowhow-worker";
|
|
19
21
|
private static readonly CONTAINER_PREFIX = "knowhow-worker";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as path from "path";
|
|
2
|
+
import { TraceAll } from "../util/Trace";
|
|
2
3
|
import { globSync } from "glob";
|
|
3
4
|
|
|
4
5
|
import {
|
|
@@ -38,6 +39,7 @@ interface EmbeddingServiceContext {
|
|
|
38
39
|
plugins: PluginService;
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
@TraceAll()
|
|
41
43
|
export class EmbeddingService {
|
|
42
44
|
private config: Config;
|
|
43
45
|
private embeddingClient: GenericClient;
|
|
@@ -20,6 +20,9 @@ export interface EmbeddingsResolver {
|
|
|
20
20
|
* Modules can register a resolver for a given remoteType (e.g. "github", "s3")
|
|
21
21
|
* via registerResolver(), and the core upload()/download() functions delegate to it.
|
|
22
22
|
*/
|
|
23
|
+
import { TraceAll } from "../util/Trace";
|
|
24
|
+
|
|
25
|
+
@TraceAll()
|
|
23
26
|
export class EmbeddingsService {
|
|
24
27
|
private resolvers = new Map<string, EmbeddingsResolver>();
|
|
25
28
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { createHash } from "crypto";
|
|
2
|
-
import
|
|
2
|
+
import { TraceAll } from "../util/Trace";
|
|
3
|
+
import http, { HTTP_UNAUTHORIZED_HANDLER, RefreshableHeaders } from "../utils/http";
|
|
3
4
|
import fs from "fs";
|
|
5
|
+
import { getConfigSync } from "../config";
|
|
6
|
+
import { exchangePublicKeyJwt, storeJwt } from "../auth/keyAuth";
|
|
7
|
+
import { keyPairExists } from "../auth/keyManager";
|
|
4
8
|
import { Message } from "../clients/types";
|
|
5
9
|
import path from "path";
|
|
6
10
|
import {
|
|
@@ -141,17 +145,32 @@ export function loadKnowhowJwt(): string {
|
|
|
141
145
|
export const KNOWHOW_API_URL =
|
|
142
146
|
process.env.KNOWHOW_API_URL || "https://api.knowhow.tyvm.ai";
|
|
143
147
|
|
|
148
|
+
@TraceAll()
|
|
144
149
|
export class KnowhowSimpleClient {
|
|
145
|
-
headers:
|
|
150
|
+
headers: RefreshableHeaders = {};
|
|
146
151
|
jwtValidated = false;
|
|
152
|
+
private readonly canRefreshJwt: boolean;
|
|
153
|
+
private refreshPromise?: Promise<void>;
|
|
147
154
|
|
|
148
155
|
constructor(
|
|
149
156
|
private baseUrl = KNOWHOW_API_URL,
|
|
150
|
-
|
|
157
|
+
jwt?: string
|
|
151
158
|
) {
|
|
152
|
-
|
|
159
|
+
// Explicit tokens (including KNOWHOW_JWT worker credentials) have no
|
|
160
|
+
// corresponding local identity and must never trigger interactive renewal.
|
|
161
|
+
this.canRefreshJwt = jwt === undefined && !process.env.KNOWHOW_JWT;
|
|
162
|
+
this.jwt = jwt ?? loadKnowhowJwt();
|
|
163
|
+
this.setJwt(this.jwt);
|
|
164
|
+
if (this.canRefreshJwt) {
|
|
165
|
+
Object.defineProperty(this.headers, HTTP_UNAUTHORIZED_HANDLER, {
|
|
166
|
+
enumerable: false,
|
|
167
|
+
value: () => this.renewJwt(true),
|
|
168
|
+
});
|
|
169
|
+
}
|
|
153
170
|
}
|
|
154
171
|
|
|
172
|
+
private jwt: string;
|
|
173
|
+
|
|
155
174
|
/**
|
|
156
175
|
* Reload the JWT from disk (useful after login refreshes the token).
|
|
157
176
|
*/
|
|
@@ -165,9 +184,45 @@ export class KnowhowSimpleClient {
|
|
|
165
184
|
|
|
166
185
|
setJwt(jwt: string) {
|
|
167
186
|
this.jwt = jwt;
|
|
168
|
-
this
|
|
169
|
-
|
|
170
|
-
|
|
187
|
+
// Keep this object stable: the HTTP wrapper retries with the same reference.
|
|
188
|
+
this.headers.Authorization = `Bearer ${this.jwt}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private jwtExpiresSoon(): boolean {
|
|
192
|
+
try {
|
|
193
|
+
const payload = JSON.parse(Buffer.from(this.jwt.split(".")[1], "base64url").toString("utf8"));
|
|
194
|
+
return typeof payload.exp === "number" && payload.exp * 1000 - Date.now() < 5 * 60 * 1000;
|
|
195
|
+
} catch {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private async renewJwt(force = false): Promise<void> {
|
|
201
|
+
if (!this.canRefreshJwt) return;
|
|
202
|
+
if (!force && !this.jwtExpiresSoon()) return;
|
|
203
|
+
if (this.refreshPromise) return this.refreshPromise;
|
|
204
|
+
|
|
205
|
+
this.refreshPromise = (async () => {
|
|
206
|
+
const config = getConfigSync();
|
|
207
|
+
const identityPath = config.cliIdentityPath;
|
|
208
|
+
if (!config.orgId || !keyPairExists(identityPath)) {
|
|
209
|
+
throw new Error("JWT expired and the CLI identity is unavailable. Please run `knowhow login` again.");
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
const freshJwt = await exchangePublicKeyJwt(config.orgId, this.baseUrl, identityPath);
|
|
213
|
+
storeJwt(freshJwt);
|
|
214
|
+
this.setJwt(freshJwt);
|
|
215
|
+
this.jwtValidated = true;
|
|
216
|
+
} catch (error) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
"Unable to renew the CLI session; the identity may have been revoked. Please run `knowhow login` again.",
|
|
219
|
+
{ cause: error }
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
})().finally(() => {
|
|
223
|
+
this.refreshPromise = undefined;
|
|
224
|
+
});
|
|
225
|
+
return this.refreshPromise;
|
|
171
226
|
}
|
|
172
227
|
|
|
173
228
|
async checkJwt() {
|
|
@@ -175,6 +230,8 @@ export class KnowhowSimpleClient {
|
|
|
175
230
|
throw new Error("No JWT found. Please login first.");
|
|
176
231
|
}
|
|
177
232
|
|
|
233
|
+
await this.renewJwt();
|
|
234
|
+
|
|
178
235
|
if (!this.jwtValidated) {
|
|
179
236
|
try {
|
|
180
237
|
this.jwtValidated = true;
|
|
@@ -186,6 +243,10 @@ export class KnowhowSimpleClient {
|
|
|
186
243
|
return org.organizationId === orgId;
|
|
187
244
|
});
|
|
188
245
|
} catch (error) {
|
|
246
|
+
this.jwtValidated = false;
|
|
247
|
+
if (error instanceof Error && error.message.includes("renew the CLI session")) {
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
189
250
|
throw new Error("Invalid JWT. Please login again.");
|
|
190
251
|
}
|
|
191
252
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { minimatch } from "minimatch";
|
|
2
|
+
import { TraceAll } from "../util/Trace";
|
|
2
3
|
import { ToolsService, ToolContext, ToolCallContext } from "./Tools";
|
|
3
4
|
import { Tool } from "../clients/types";
|
|
4
5
|
import { ToolCall } from "../clients/types";
|
|
@@ -21,6 +22,7 @@ import { definitions } from "../agents/tools/lazy/definitions";
|
|
|
21
22
|
* In web sessions where you get a new ToolService each interaction, then the cache busting is going to happen with each enable
|
|
22
23
|
*
|
|
23
24
|
*/
|
|
25
|
+
@TraceAll()
|
|
24
26
|
export class LazyToolsService extends ToolsService {
|
|
25
27
|
private allTools: Tool[] = [];
|
|
26
28
|
// Start with lazy tools enabled by default
|
|
@@ -80,6 +82,13 @@ export class LazyToolsService extends ToolsService {
|
|
|
80
82
|
return this.tools; // Returns filtered subset
|
|
81
83
|
}
|
|
82
84
|
|
|
85
|
+
/** Rebuild the lazy catalog while preserving enable/disable preferences. */
|
|
86
|
+
resetTools(): void {
|
|
87
|
+
this.allTools = [];
|
|
88
|
+
super.resetTools();
|
|
89
|
+
this.registerLazyTools();
|
|
90
|
+
}
|
|
91
|
+
|
|
83
92
|
// Enable tools matching glob patterns
|
|
84
93
|
enableTools(patterns: string[]) {
|
|
85
94
|
for (const pattern of patterns) {
|
|
@@ -97,6 +106,13 @@ export class LazyToolsService extends ToolsService {
|
|
|
97
106
|
};
|
|
98
107
|
}
|
|
99
108
|
|
|
109
|
+
/** Replace glob state with an exact persisted request-visible tool list. */
|
|
110
|
+
restoreEnabledTools(names: string[]): void {
|
|
111
|
+
this.enabledPatterns = [...new Set(names)];
|
|
112
|
+
this.disabledPatterns = [];
|
|
113
|
+
this.updateVisibleTools();
|
|
114
|
+
}
|
|
115
|
+
|
|
100
116
|
// Disable tools matching glob patterns
|
|
101
117
|
disableTools(patterns: string[]) {
|
|
102
118
|
for (const pattern of patterns) {
|
package/src/services/Mcp.ts
CHANGED
|
@@ -6,6 +6,7 @@ import fs from "fs";
|
|
|
6
6
|
import { McpConfig } from "../types";
|
|
7
7
|
import { Tool } from "../clients";
|
|
8
8
|
import { getConfig } from "../config";
|
|
9
|
+
import { TraceAll } from "../util/Trace";
|
|
9
10
|
import { ToolsService } from "./Tools";
|
|
10
11
|
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
11
12
|
import { CallToolResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -36,6 +37,7 @@ export * from "./McpWebsocketTransport";
|
|
|
36
37
|
* Each of the tools are namespaced with a prefix: mcp_index_servername_toolName
|
|
37
38
|
* This services handles calls made to the namespaced function name, and finds the proper client to call the tool on.
|
|
38
39
|
*/
|
|
40
|
+
@TraceAll()
|
|
39
41
|
export class McpService {
|
|
40
42
|
connected = [];
|
|
41
43
|
transports: Transport[] = [];
|
|
@@ -388,8 +390,15 @@ export class McpService {
|
|
|
388
390
|
}
|
|
389
391
|
|
|
390
392
|
async closeAll() {
|
|
391
|
-
await this.closeTransports();
|
|
392
|
-
await this.closeClients();
|
|
393
|
+
await Promise.allSettled([this.closeTransports()]);
|
|
394
|
+
await Promise.allSettled([this.closeClients()]);
|
|
395
|
+
// Connections are recreated from freshly-read configuration after reload.
|
|
396
|
+
this.clients = [];
|
|
397
|
+
this.transports = [];
|
|
398
|
+
this.connected = [];
|
|
399
|
+
this.config = [];
|
|
400
|
+
this.tools = [];
|
|
401
|
+
this.toolAliases = {};
|
|
393
402
|
}
|
|
394
403
|
|
|
395
404
|
getClientIndex(clientName: string) {
|
|
@@ -6,9 +6,11 @@ import { Tool, ToolProp } from "../clients/types";
|
|
|
6
6
|
import { ToolsService } from "./Tools";
|
|
7
7
|
import { MCPWebSocketTransport } from "./McpWebsocketTransport";
|
|
8
8
|
import { WebSocket } from "ws";
|
|
9
|
+
import { TraceAll } from "../util/Trace";
|
|
9
10
|
|
|
10
11
|
export type McpServerConfig = { name: string; version: string };
|
|
11
12
|
|
|
13
|
+
@TraceAll()
|
|
12
14
|
export class McpServerService {
|
|
13
15
|
server: McpServer | null = null;
|
|
14
16
|
constructor(private toolsService: ToolsService) {}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Message } from "../clients/types";
|
|
2
|
+
import { TraceAll } from "../util/Trace";
|
|
2
3
|
|
|
3
4
|
export type ProcessorLifecycle =
|
|
4
5
|
| "initial_call"
|
|
@@ -17,6 +18,7 @@ export interface ProcessorRegistration {
|
|
|
17
18
|
priority: number;
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
@TraceAll()
|
|
20
22
|
export class MessageProcessor {
|
|
21
23
|
private processors: Map<ProcessorLifecycle, ProcessorRegistration[]> =
|
|
22
24
|
new Map();
|
|
@@ -5,6 +5,7 @@ import { inspectTools } from "../agents/tools/minimal/inspectTools";
|
|
|
5
5
|
import { minimalDefinitions } from "../agents/tools/minimal/definitions";
|
|
6
6
|
import { finalAnswer } from "../agents/tools/finalAnswer";
|
|
7
7
|
import { includedTools } from "../agents/tools/list";
|
|
8
|
+
import { TraceAll } from "../util/Trace";
|
|
8
9
|
|
|
9
10
|
/*
|
|
10
11
|
* MinimalToolsService
|
|
@@ -19,6 +20,7 @@ import { includedTools } from "../agents/tools/list";
|
|
|
19
20
|
* - Works on all providers and older models (no provider-specific defer_loading needed).
|
|
20
21
|
* - Agents discover tools via inspectTools() and call them via callTool().
|
|
21
22
|
*/
|
|
23
|
+
@TraceAll()
|
|
22
24
|
export class MinimalToolsService extends ToolsService {
|
|
23
25
|
/** Full catalog of every registered tool (base + extended). */
|
|
24
26
|
private allToolsCatalog: Tool[] = [];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface RuntimeReloadResult {
|
|
2
|
+
tools: number;
|
|
3
|
+
mcps: number;
|
|
4
|
+
modules: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/** Coordinates in-place runtime refreshes and coalesces concurrent requests. */
|
|
8
|
+
export class RuntimeReloadService {
|
|
9
|
+
private handler?: () => Promise<RuntimeReloadResult>;
|
|
10
|
+
private pending?: Promise<RuntimeReloadResult>;
|
|
11
|
+
|
|
12
|
+
configure(handler: () => Promise<RuntimeReloadResult>): void {
|
|
13
|
+
this.handler = handler;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
isConfigured(): boolean {
|
|
17
|
+
return !!this.handler;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
reload(): Promise<RuntimeReloadResult> {
|
|
21
|
+
if (!this.handler) {
|
|
22
|
+
return Promise.reject(new Error("Runtime reload is unavailable for this command"));
|
|
23
|
+
}
|
|
24
|
+
if (!this.pending) {
|
|
25
|
+
this.pending = this.handler().finally(() => {
|
|
26
|
+
this.pending = undefined;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return this.pending;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -5,10 +5,12 @@ import * as fs from "fs";
|
|
|
5
5
|
import * as fsPromises from "fs/promises";
|
|
6
6
|
import * as path from "path";
|
|
7
7
|
import { TaskInfo, ChatSession } from "../chat/types";
|
|
8
|
+
import { TraceAll } from "../util/Trace";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* SessionManager handles saving, loading, and managing agent sessions
|
|
11
12
|
*/
|
|
13
|
+
@TraceAll()
|
|
12
14
|
export class SessionManager {
|
|
13
15
|
private sessionsDir: string;
|
|
14
16
|
|
|
@@ -69,6 +71,7 @@ export class SessionManager {
|
|
|
69
71
|
provider: taskInfo.provider,
|
|
70
72
|
reasoningEffort: taskInfo.reasoningEffort,
|
|
71
73
|
summarizeReasoning: taskInfo.summarizeReasoning,
|
|
74
|
+
enabledTools: taskInfo.enabledTools,
|
|
72
75
|
};
|
|
73
76
|
|
|
74
77
|
fs.writeFileSync(sessionPath, JSON.stringify(session, null, 2));
|
|
@@ -115,6 +118,8 @@ export class SessionManager {
|
|
|
115
118
|
session.reasoningEffort = taskInfo.reasoningEffort;
|
|
116
119
|
if (taskInfo.summarizeReasoning !== undefined)
|
|
117
120
|
session.summarizeReasoning = taskInfo.summarizeReasoning;
|
|
121
|
+
if (taskInfo.enabledTools !== undefined)
|
|
122
|
+
session.enabledTools = taskInfo.enabledTools;
|
|
118
123
|
}
|
|
119
124
|
|
|
120
125
|
fs.writeFileSync(sessionPath, JSON.stringify(session, null, 2));
|
|
@@ -4,6 +4,7 @@ import * as os from "os";
|
|
|
4
4
|
import { createHash } from "crypto";
|
|
5
5
|
import * as https from "https";
|
|
6
6
|
import { KnowhowSimpleClient } from "./KnowhowClient";
|
|
7
|
+
import { TraceAll } from "../util/Trace";
|
|
7
8
|
|
|
8
9
|
// Default local install dir (relative to cwd)
|
|
9
10
|
const LOCAL_SKILLS_DIR = ".knowhow/skills";
|
|
@@ -233,6 +234,7 @@ export function parseSkillRef(
|
|
|
233
234
|
return { owner, repo, skill, sourceUrl };
|
|
234
235
|
}
|
|
235
236
|
|
|
237
|
+
@TraceAll()
|
|
236
238
|
export class SkillsService {
|
|
237
239
|
private cwd: string;
|
|
238
240
|
private isGlobal: boolean;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { Message } from "../clients/types";
|
|
7
7
|
import { EventService } from "./EventService";
|
|
8
|
+
import { TraceAll } from "../util/Trace";
|
|
8
9
|
|
|
9
10
|
export interface SyncedAgentWatcher {
|
|
10
11
|
/** Start watching for changes, emitting agent events */
|
|
@@ -73,6 +74,7 @@ export interface AttachableAgent {
|
|
|
73
74
|
* - agentEvents and eventTypes are delegated to the watcher
|
|
74
75
|
* - "done" is emitted by the watcher when the remote agent completes
|
|
75
76
|
*/
|
|
77
|
+
@TraceAll()
|
|
76
78
|
export class WatcherBackedAgent implements AttachableAgent {
|
|
77
79
|
public name: string;
|
|
78
80
|
public agentEvents: EventService;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Hides complexity of choosing and managing sync backends.
|
|
4
4
|
*/
|
|
5
5
|
import { BaseAgent } from "../agents/base/base";
|
|
6
|
+
import { TraceAll } from "../util/Trace";
|
|
6
7
|
import { AgentSyncFs } from "./AgentSyncFs";
|
|
7
8
|
import { AgentSyncKnowhowWeb } from "./AgentSyncKnowhowWeb";
|
|
8
9
|
|
|
@@ -11,12 +12,13 @@ export interface SyncerOptions {
|
|
|
11
12
|
prompt: string;
|
|
12
13
|
/** If provided → use web sync (unless syncFs is set) */
|
|
13
14
|
messageId?: string;
|
|
15
|
+
/** Existing remote Knowhow task UUID. Never inferred from the local taskId. */
|
|
16
|
+
remoteTaskId?: string;
|
|
14
17
|
/** Force fs sync even if messageId is provided */
|
|
15
18
|
syncFs?: boolean;
|
|
16
19
|
/**
|
|
17
|
-
* Push the agent's work to
|
|
18
|
-
*
|
|
19
|
-
* push updates to, rather than creating a new remote task.
|
|
20
|
+
* Push the agent's work to the existing `remoteTaskId`. The local taskId is
|
|
21
|
+
* always a filesystem identity and is never used as a remote identifier.
|
|
20
22
|
*/
|
|
21
23
|
syncRemote?: boolean;
|
|
22
24
|
/** Agent name to persist in metadata.json */
|
|
@@ -44,8 +46,9 @@ export interface AgentSyncer {
|
|
|
44
46
|
* Decision logic:
|
|
45
47
|
* - Always sets up AgentSyncFs (primary local syncer)
|
|
46
48
|
* - If messageId is present AND syncFs is not forced → creates a new remote task via AgentSyncKnowhowWeb
|
|
47
|
-
* - If syncRemote
|
|
49
|
+
* - If syncRemote and a valid remoteTaskId are set → attaches to that UUID
|
|
48
50
|
*/
|
|
51
|
+
@TraceAll()
|
|
49
52
|
export class SyncerService implements AgentSyncer {
|
|
50
53
|
private fsSync: AgentSyncFs;
|
|
51
54
|
private webSync: AgentSyncKnowhowWeb;
|
|
@@ -75,14 +78,16 @@ export class SyncerService implements AgentSyncer {
|
|
|
75
78
|
|
|
76
79
|
// Determine whether to ATTACH to an already-existing remote task and push
|
|
77
80
|
// local work to it (no creation needed). This is the "--sync-remote" path:
|
|
78
|
-
// the caller wants to push work to
|
|
81
|
+
// the caller wants to push work to an explicitly identified remote task.
|
|
79
82
|
// We only auto-attach when there is NO messageId (messageId always creates
|
|
80
83
|
// a fresh remote task above).
|
|
81
84
|
//
|
|
82
85
|
// This is orthogonal to fs sync: we can push to the remote task AND keep
|
|
83
86
|
// the local .knowhow/processes/agents/<id>/ files in sync at the same time.
|
|
84
87
|
const shouldAttachExisting =
|
|
85
|
-
!!options.syncRemote &&
|
|
88
|
+
!!options.syncRemote &&
|
|
89
|
+
!options.messageId &&
|
|
90
|
+
isUuid(options.remoteTaskId);
|
|
86
91
|
|
|
87
92
|
// Always create fs sync task first
|
|
88
93
|
console.log(
|
|
@@ -104,6 +109,7 @@ export class SyncerService implements AgentSyncer {
|
|
|
104
109
|
|
|
105
110
|
if (knowhowTaskId) {
|
|
106
111
|
this.useWebSync = true;
|
|
112
|
+
await this.fsSync.setRemoteIdentity(knowhowTaskId, options.messageId);
|
|
107
113
|
this.createdTaskId = knowhowTaskId;
|
|
108
114
|
console.log(`🌐 Web sync task created: ${knowhowTaskId}`);
|
|
109
115
|
}
|
|
@@ -112,9 +118,10 @@ export class SyncerService implements AgentSyncer {
|
|
|
112
118
|
// Attach live web sync to an existing remote task (push updates to it).
|
|
113
119
|
if (!shouldUseWebSync && shouldAttachExisting) {
|
|
114
120
|
this.useWebSync = true;
|
|
115
|
-
this.
|
|
121
|
+
await this.fsSync.setRemoteIdentity(options.remoteTaskId!);
|
|
122
|
+
this.createdTaskId = options.remoteTaskId;
|
|
116
123
|
console.log(
|
|
117
|
-
`🌐 Attaching web sync to existing remote task: ${options.
|
|
124
|
+
`🌐 Attaching web sync to existing remote task: ${options.remoteTaskId}`
|
|
118
125
|
);
|
|
119
126
|
}
|
|
120
127
|
|
|
@@ -174,3 +181,11 @@ export class SyncerService implements AgentSyncer {
|
|
|
174
181
|
return this.useWebSync ? this.createdTaskId : undefined;
|
|
175
182
|
}
|
|
176
183
|
}
|
|
184
|
+
|
|
185
|
+
/** Remote task IDs are UUIDs; local filesystem IDs are timestamped slugs. */
|
|
186
|
+
function isUuid(value: string | undefined): value is string {
|
|
187
|
+
return !!value &&
|
|
188
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(
|
|
189
|
+
value
|
|
190
|
+
);
|
|
191
|
+
}
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
* Task Registry Service - Manages active agent tasks
|
|
3
3
|
*/
|
|
4
4
|
import { TaskInfo } from "../chat/types";
|
|
5
|
+
import { TraceAll } from "../util/Trace";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* TaskRegistry manages the in-memory registry of active agent tasks
|
|
8
9
|
*/
|
|
10
|
+
@TraceAll()
|
|
9
11
|
export class TaskRegistry {
|
|
10
12
|
private tasks = new Map<string, TaskInfo>();
|
|
11
13
|
|