@tyvm/knowhow 0.0.108 → 0.0.109-dev.2b94ba2
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/README.md +45 -0
- package/package.json +9 -4
- package/scripts/build-for-node.sh +10 -24
- package/scripts/publish.sh +86 -0
- package/src/agents/base/base.ts +10 -0
- package/src/agents/tools/execCommand.ts +49 -6
- package/src/agents/tools/index.ts +0 -1
- package/src/agents/tools/list.ts +2 -4
- package/src/chat/CliChatService.ts +11 -2
- package/src/chat/modules/AgentModule.ts +61 -31
- package/src/chat/modules/SessionsModule.ts +47 -3
- package/src/chat/modules/SystemModule.ts +2 -2
- package/src/chat/renderer/CompactRenderer.ts +20 -0
- package/src/chat/renderer/ConsoleRenderer.ts +19 -0
- package/src/chat/renderer/FancyRenderer.ts +19 -0
- package/src/chat/renderer/types.ts +11 -0
- package/src/cli.ts +91 -659
- package/src/clients/anthropic.ts +18 -17
- package/src/clients/index.ts +31 -11
- package/src/clients/openai.ts +8 -5
- package/src/clients/types.ts +48 -10
- package/src/clients/withRetry.ts +89 -0
- package/src/cloudWorker.ts +175 -113
- package/src/commands/agent.ts +246 -0
- package/src/commands/misc.ts +174 -0
- package/src/commands/modules.ts +552 -0
- package/src/commands/services.ts +77 -0
- package/src/commands/workers.ts +168 -0
- package/src/config.ts +38 -1
- package/src/fileSync.ts +70 -29
- package/src/hashes.ts +35 -13
- package/src/index.ts +18 -0
- package/src/logger.ts +197 -0
- package/src/plugins/embedding.ts +11 -6
- package/src/plugins/plugins.ts +0 -21
- package/src/plugins/vim.ts +5 -16
- package/src/processors/JsonCompressor.ts +6 -6
- package/src/services/EventService.ts +61 -1
- package/src/services/KnowhowClient.ts +34 -4
- package/src/services/MediaProcessorService.ts +79 -10
- package/src/services/modules/index.ts +102 -53
- package/src/services/modules/types.ts +6 -0
- package/src/tunnel.ts +216 -0
- package/src/types.ts +0 -1
- package/src/worker.ts +105 -312
- package/src/workers/auth/WsMiddleware.ts +99 -0
- package/src/workers/auth/authMiddleware.ts +104 -0
- package/src/workers/auth/types.ts +14 -2
- package/src/workers/tools/index.ts +2 -0
- package/src/workers/tools/reloadConfig.ts +84 -0
- package/tests/services/WorkerReloadConfig.test.ts +141 -0
- package/tests/unit/clients/AIClient.test.ts +446 -0
- package/tests/unit/clients/withRetry.test.ts +319 -0
- package/tests/unit/commands/github-credentials.test.ts +210 -0
- package/tests/unit/modules/moduleLoading.test.ts +39 -37
- package/tests/unit/plugins/pluginLoading.test.ts +0 -85
- package/ts_build/package.json +9 -4
- package/ts_build/src/agents/base/base.js +11 -0
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/tools/execCommand.d.ts +1 -1
- package/ts_build/src/agents/tools/execCommand.js +39 -5
- package/ts_build/src/agents/tools/execCommand.js.map +1 -1
- package/ts_build/src/agents/tools/index.d.ts +0 -1
- package/ts_build/src/agents/tools/index.js +0 -1
- package/ts_build/src/agents/tools/index.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +2 -4
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/chat/CliChatService.js +14 -2
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +1 -1
- package/ts_build/src/chat/modules/AgentModule.js +43 -20
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/SessionsModule.js +37 -3
- package/ts_build/src/chat/modules/SessionsModule.js.map +1 -1
- package/ts_build/src/chat/modules/SystemModule.js +2 -2
- package/ts_build/src/chat/modules/SystemModule.js.map +1 -1
- package/ts_build/src/chat/renderer/CompactRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/CompactRenderer.js +16 -0
- package/ts_build/src/chat/renderer/CompactRenderer.js.map +1 -1
- package/ts_build/src/chat/renderer/ConsoleRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/ConsoleRenderer.js +16 -0
- package/ts_build/src/chat/renderer/ConsoleRenderer.js.map +1 -1
- package/ts_build/src/chat/renderer/FancyRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/FancyRenderer.js +16 -0
- package/ts_build/src/chat/renderer/FancyRenderer.js.map +1 -1
- package/ts_build/src/chat/renderer/types.d.ts +2 -0
- package/ts_build/src/cli.js +47 -519
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +5 -5
- package/ts_build/src/clients/anthropic.js +18 -17
- package/ts_build/src/clients/anthropic.js.map +1 -1
- package/ts_build/src/clients/index.js +9 -10
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/clients/openai.js +4 -4
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/types.d.ts +15 -8
- package/ts_build/src/clients/withRetry.d.ts +2 -0
- package/ts_build/src/clients/withRetry.js +60 -0
- package/ts_build/src/clients/withRetry.js.map +1 -0
- package/ts_build/src/cloudWorker.d.ts +14 -0
- package/ts_build/src/cloudWorker.js +105 -66
- package/ts_build/src/cloudWorker.js.map +1 -1
- package/ts_build/src/commands/agent.d.ts +6 -0
- package/ts_build/src/commands/agent.js +229 -0
- package/ts_build/src/commands/agent.js.map +1 -0
- package/ts_build/src/commands/misc.d.ts +10 -0
- package/ts_build/src/commands/misc.js +197 -0
- package/ts_build/src/commands/misc.js.map +1 -0
- package/ts_build/src/commands/modules.d.ts +3 -0
- package/ts_build/src/commands/modules.js +487 -0
- package/ts_build/src/commands/modules.js.map +1 -0
- package/ts_build/src/commands/services.d.ts +5 -0
- package/ts_build/src/commands/services.js +87 -0
- package/ts_build/src/commands/services.js.map +1 -0
- package/ts_build/src/commands/workers.d.ts +6 -0
- package/ts_build/src/commands/workers.js +168 -0
- package/ts_build/src/commands/workers.js.map +1 -0
- package/ts_build/src/config.d.ts +1 -0
- package/ts_build/src/config.js +33 -1
- package/ts_build/src/config.js.map +1 -1
- package/ts_build/src/fileSync.d.ts +6 -0
- package/ts_build/src/fileSync.js +50 -23
- package/ts_build/src/fileSync.js.map +1 -1
- package/ts_build/src/hashes.d.ts +2 -2
- package/ts_build/src/hashes.js +35 -9
- package/ts_build/src/hashes.js.map +1 -1
- package/ts_build/src/index.d.ts +1 -0
- package/ts_build/src/index.js +17 -1
- package/ts_build/src/index.js.map +1 -1
- package/ts_build/src/logger.d.ts +21 -0
- package/ts_build/src/logger.js +106 -0
- package/ts_build/src/logger.js.map +1 -0
- package/ts_build/src/plugins/embedding.js +4 -3
- package/ts_build/src/plugins/embedding.js.map +1 -1
- package/ts_build/src/plugins/plugins.d.ts +0 -2
- package/ts_build/src/plugins/plugins.js +0 -11
- package/ts_build/src/plugins/plugins.js.map +1 -1
- package/ts_build/src/plugins/vim.js +3 -9
- package/ts_build/src/plugins/vim.js.map +1 -1
- package/ts_build/src/processors/JsonCompressor.js +4 -4
- package/ts_build/src/processors/JsonCompressor.js.map +1 -1
- package/ts_build/src/services/EventService.d.ts +6 -1
- package/ts_build/src/services/EventService.js +29 -0
- package/ts_build/src/services/EventService.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.d.ts +13 -1
- package/ts_build/src/services/KnowhowClient.js +19 -2
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/MediaProcessorService.d.ts +5 -4
- package/ts_build/src/services/MediaProcessorService.js +53 -8
- package/ts_build/src/services/MediaProcessorService.js.map +1 -1
- package/ts_build/src/services/modules/index.d.ts +33 -0
- package/ts_build/src/services/modules/index.js +73 -49
- package/ts_build/src/services/modules/index.js.map +1 -1
- package/ts_build/src/services/modules/types.d.ts +6 -0
- package/ts_build/src/tunnel.d.ts +27 -0
- package/ts_build/src/tunnel.js +112 -0
- package/ts_build/src/tunnel.js.map +1 -0
- package/ts_build/src/types.d.ts +0 -1
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/worker.d.ts +1 -4
- package/ts_build/src/worker.js +59 -227
- package/ts_build/src/worker.js.map +1 -1
- package/ts_build/src/workers/auth/WsMiddleware.d.ts +8 -0
- package/ts_build/src/workers/auth/WsMiddleware.js +65 -0
- package/ts_build/src/workers/auth/WsMiddleware.js.map +1 -0
- package/ts_build/src/workers/auth/authMiddleware.d.ts +3 -0
- package/ts_build/src/workers/auth/authMiddleware.js +60 -0
- package/ts_build/src/workers/auth/authMiddleware.js.map +1 -0
- package/ts_build/src/workers/auth/types.d.ts +8 -1
- package/ts_build/src/workers/tools/index.d.ts +2 -0
- package/ts_build/src/workers/tools/index.js +4 -1
- package/ts_build/src/workers/tools/index.js.map +1 -1
- package/ts_build/src/workers/tools/reloadConfig.d.ts +14 -0
- package/ts_build/src/workers/tools/reloadConfig.js +48 -0
- package/ts_build/src/workers/tools/reloadConfig.js.map +1 -0
- package/ts_build/tests/services/WorkerReloadConfig.test.d.ts +1 -0
- package/ts_build/tests/services/WorkerReloadConfig.test.js +86 -0
- package/ts_build/tests/services/WorkerReloadConfig.test.js.map +1 -0
- package/ts_build/tests/unit/clients/AIClient.test.d.ts +1 -0
- package/ts_build/tests/unit/clients/AIClient.test.js +339 -0
- package/ts_build/tests/unit/clients/AIClient.test.js.map +1 -0
- package/ts_build/tests/unit/clients/withRetry.test.d.ts +1 -0
- package/ts_build/tests/unit/clients/withRetry.test.js +225 -0
- package/ts_build/tests/unit/clients/withRetry.test.js.map +1 -0
- package/ts_build/tests/unit/commands/github-credentials.test.d.ts +1 -0
- package/ts_build/tests/unit/commands/github-credentials.test.js +145 -0
- package/ts_build/tests/unit/commands/github-credentials.test.js.map +1 -0
- package/ts_build/tests/unit/modules/moduleLoading.test.js +20 -26
- package/ts_build/tests/unit/modules/moduleLoading.test.js.map +1 -1
- package/ts_build/tests/unit/plugins/pluginLoading.test.js +0 -65
- package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -1
- package/src/agents/tools/executeScript/README.md +0 -94
- package/src/agents/tools/executeScript/definition.ts +0 -79
- package/src/agents/tools/executeScript/examples/dependency-injection-validation.ts +0 -272
- package/src/agents/tools/executeScript/examples/quick-test.ts +0 -74
- package/src/agents/tools/executeScript/examples/serialization-test.ts +0 -321
- package/src/agents/tools/executeScript/examples/test-runner.ts +0 -197
- package/src/agents/tools/executeScript/index.ts +0 -98
- package/src/services/script-execution/SandboxContext.ts +0 -282
- package/src/services/script-execution/ScriptExecutor.ts +0 -441
- package/src/services/script-execution/ScriptPolicy.ts +0 -194
- package/src/services/script-execution/ScriptTracer.ts +0 -249
- package/src/services/script-execution/types.ts +0 -134
- package/ts_build/src/agents/tools/executeScript/definition.d.ts +0 -2
- package/ts_build/src/agents/tools/executeScript/definition.js +0 -76
- package/ts_build/src/agents/tools/executeScript/definition.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/examples/dependency-injection-validation.d.ts +0 -18
- package/ts_build/src/agents/tools/executeScript/examples/dependency-injection-validation.js +0 -192
- package/ts_build/src/agents/tools/executeScript/examples/dependency-injection-validation.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/examples/quick-test.d.ts +0 -3
- package/ts_build/src/agents/tools/executeScript/examples/quick-test.js +0 -64
- package/ts_build/src/agents/tools/executeScript/examples/quick-test.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/examples/serialization-test.d.ts +0 -15
- package/ts_build/src/agents/tools/executeScript/examples/serialization-test.js +0 -266
- package/ts_build/src/agents/tools/executeScript/examples/serialization-test.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/examples/test-runner.d.ts +0 -4
- package/ts_build/src/agents/tools/executeScript/examples/test-runner.js +0 -208
- package/ts_build/src/agents/tools/executeScript/examples/test-runner.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/index.d.ts +0 -28
- package/ts_build/src/agents/tools/executeScript/index.js +0 -72
- package/ts_build/src/agents/tools/executeScript/index.js.map +0 -1
- package/ts_build/src/services/script-execution/SandboxContext.d.ts +0 -34
- package/ts_build/src/services/script-execution/SandboxContext.js +0 -189
- package/ts_build/src/services/script-execution/SandboxContext.js.map +0 -1
- package/ts_build/src/services/script-execution/ScriptExecutor.d.ts +0 -19
- package/ts_build/src/services/script-execution/ScriptExecutor.js +0 -269
- package/ts_build/src/services/script-execution/ScriptExecutor.js.map +0 -1
- package/ts_build/src/services/script-execution/ScriptPolicy.d.ts +0 -28
- package/ts_build/src/services/script-execution/ScriptPolicy.js +0 -115
- package/ts_build/src/services/script-execution/ScriptPolicy.js.map +0 -1
- package/ts_build/src/services/script-execution/ScriptTracer.d.ts +0 -19
- package/ts_build/src/services/script-execution/ScriptTracer.js +0 -186
- package/ts_build/src/services/script-execution/ScriptTracer.js.map +0 -1
- package/ts_build/src/services/script-execution/types.d.ts +0 -108
- package/ts_build/src/services/script-execution/types.js +0 -3
- package/ts_build/src/services/script-execution/types.js.map +0 -1
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
* Auth message types for the worker WebSocket authentication protocol.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
// Client → Worker: request a challenge
|
|
6
|
+
export interface AuthGetChallengeMessage {
|
|
7
|
+
type: "auth:getChallenge";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Worker → Client: sent when a non-auth message is received while locked
|
|
11
|
+
export interface AuthLockedMessage {
|
|
12
|
+
type: "auth:locked";
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
// Worker → Client: challenge
|
|
6
17
|
export interface AuthChallengeMessage {
|
|
7
18
|
type: "auth:challenge";
|
|
@@ -31,12 +42,13 @@ export interface AuthFailureMessage {
|
|
|
31
42
|
type: "auth:failure";
|
|
32
43
|
reason: "invalid_signature" | "expired" | "unknown_credential";
|
|
33
44
|
}
|
|
34
|
-
|
|
35
45
|
export type AuthMessage =
|
|
46
|
+
| AuthGetChallengeMessage
|
|
36
47
|
| AuthChallengeMessage
|
|
37
48
|
| AuthResponseMessage
|
|
38
49
|
| AuthSuccessMessage
|
|
39
|
-
| AuthFailureMessage
|
|
50
|
+
| AuthFailureMessage
|
|
51
|
+
| AuthLockedMessage;
|
|
40
52
|
|
|
41
53
|
// Passkey credential stored in config
|
|
42
54
|
export interface PasskeyCredential {
|
|
@@ -2,6 +2,7 @@ export * from "./listAllowedPorts";
|
|
|
2
2
|
export * from "./getChallenge";
|
|
3
3
|
export * from "./unlock";
|
|
4
4
|
export * from "./lock";
|
|
5
|
+
export * from "./reloadConfig";
|
|
5
6
|
|
|
6
7
|
import {
|
|
7
8
|
listAllowedPorts,
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
export { makeGetChallengeTool } from "./getChallenge";
|
|
12
13
|
export { makeUnlockTool } from "./unlock";
|
|
13
14
|
export { makeLockTool } from "./lock";
|
|
15
|
+
export { makeReloadConfigTool } from "./reloadConfig";
|
|
14
16
|
|
|
15
17
|
export default {
|
|
16
18
|
tools: { listAllowedPorts },
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Tool } from "../../clients/types";
|
|
2
|
+
import { getConfig } from "../../config";
|
|
3
|
+
import { McpServerService } from "../../services/McpServer";
|
|
4
|
+
import { McpService } from "../../services/Mcp";
|
|
5
|
+
import { ToolsService } from "../../services/Tools";
|
|
6
|
+
|
|
7
|
+
export interface ReloadConfigResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
toolCount: number;
|
|
10
|
+
mcpCount: number;
|
|
11
|
+
message: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Factory that creates the reloadConfig tool with access to runtime services.
|
|
16
|
+
* The tool re-reads the config from disk, reconnects all MCPs, and rebuilds
|
|
17
|
+
* the active tool list — the same logic as the WebSocket reloadConfig handler.
|
|
18
|
+
*
|
|
19
|
+
* Typical usage after pulling updated config from the cloud worker API:
|
|
20
|
+
* 1. execCommand("knowhow cloudworker --pull <cloudWorkerId>")
|
|
21
|
+
* 2. reloadConfig()
|
|
22
|
+
*/
|
|
23
|
+
export function makeReloadConfigTool(
|
|
24
|
+
Mcp: McpService,
|
|
25
|
+
Tools: ToolsService,
|
|
26
|
+
mcpServer: McpServerService,
|
|
27
|
+
setToolsToUse: (tools: ReturnType<typeof Tools.getToolsByNames>) => void
|
|
28
|
+
) {
|
|
29
|
+
const reloadConfig = async (): Promise<ReloadConfigResult> => {
|
|
30
|
+
try {
|
|
31
|
+
// Re-read fresh config from disk
|
|
32
|
+
const freshConfig = await getConfig();
|
|
33
|
+
|
|
34
|
+
// Close all existing MCP connections
|
|
35
|
+
await Mcp.closeAll();
|
|
36
|
+
|
|
37
|
+
// Reconnect from fresh config and re-register tools
|
|
38
|
+
await Mcp.connectToConfigured(Tools);
|
|
39
|
+
|
|
40
|
+
// Rebuild the allowed tools list from fresh config
|
|
41
|
+
const allowedToolNames =
|
|
42
|
+
freshConfig.worker?.allowedTools ?? Tools.getToolNames();
|
|
43
|
+
const newToolsToUse = Tools.getToolsByNames(allowedToolNames);
|
|
44
|
+
setToolsToUse(newToolsToUse);
|
|
45
|
+
|
|
46
|
+
// Update the MCP server with the new tool list
|
|
47
|
+
mcpServer.withTools(newToolsToUse);
|
|
48
|
+
|
|
49
|
+
const mcpCount = freshConfig.mcps?.length ?? 0;
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
success: true,
|
|
53
|
+
toolCount: newToolsToUse.length,
|
|
54
|
+
mcpCount,
|
|
55
|
+
message: `Config reloaded: ${newToolsToUse.length} tools active, ${mcpCount} MCP(s) configured`,
|
|
56
|
+
};
|
|
57
|
+
} catch (err) {
|
|
58
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
59
|
+
return {
|
|
60
|
+
success: false,
|
|
61
|
+
toolCount: 0,
|
|
62
|
+
mcpCount: 0,
|
|
63
|
+
message: `Failed to reload config: ${message}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const reloadConfigDefinition: Tool = {
|
|
69
|
+
type: "function" as const,
|
|
70
|
+
function: {
|
|
71
|
+
name: "reloadConfig",
|
|
72
|
+
description:
|
|
73
|
+
"Reload the worker config from disk, reconnect all MCPs, and rebuild the active tool list. " +
|
|
74
|
+
"Call this after running `knowhow cloudworker --pull <id>` to apply updated MCPs without restarting the worker.",
|
|
75
|
+
parameters: {
|
|
76
|
+
type: "object",
|
|
77
|
+
properties: {},
|
|
78
|
+
required: [],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return { reloadConfig, reloadConfigDefinition };
|
|
84
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the worker reloadConfig message handler.
|
|
3
|
+
*
|
|
4
|
+
* We test the core logic in isolation — simulating the "reloadConfig" message
|
|
5
|
+
* arriving on the WebSocket and verifying that MCPs are torn down and
|
|
6
|
+
* re-connected, and that the tool list is rebuilt from fresh config.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { McpService } from "../../src/services/Mcp";
|
|
10
|
+
import { ToolsService } from "../../src/services/Tools";
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Helpers: build the same reload logic that lives in worker.ts so we can
|
|
14
|
+
// test it in isolation without spinning up a real WebSocket server.
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
async function simulateReloadConfig(
|
|
18
|
+
Mcp: McpService,
|
|
19
|
+
Tools: ToolsService,
|
|
20
|
+
mcpServer: { withTools: (tools: unknown[]) => void },
|
|
21
|
+
getConfig: () => Promise<{ worker?: { allowedTools?: string[] } }>,
|
|
22
|
+
toolsToUseRef: { value: unknown[] }
|
|
23
|
+
) {
|
|
24
|
+
// This mirrors the handler in worker.ts
|
|
25
|
+
const freshConfig = await getConfig();
|
|
26
|
+
await Mcp.closeAll();
|
|
27
|
+
await Mcp.connectToConfigured(Tools);
|
|
28
|
+
const allowedToolNames =
|
|
29
|
+
freshConfig.worker?.allowedTools ?? Tools.getToolNames();
|
|
30
|
+
toolsToUseRef.value = Tools.getToolsByNames(allowedToolNames);
|
|
31
|
+
mcpServer.withTools(toolsToUseRef.value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Tests
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
describe("Worker reloadConfig handler", () => {
|
|
39
|
+
let Mcp: McpService;
|
|
40
|
+
let Tools: ToolsService;
|
|
41
|
+
let mcpServer: { withTools: jest.Mock };
|
|
42
|
+
let toolsToUseRef: { value: unknown[] };
|
|
43
|
+
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
Mcp = new McpService();
|
|
46
|
+
Tools = new ToolsService();
|
|
47
|
+
mcpServer = { withTools: jest.fn() };
|
|
48
|
+
toolsToUseRef = { value: [] };
|
|
49
|
+
|
|
50
|
+
// Spy on MCP methods
|
|
51
|
+
jest.spyOn(Mcp, "closeAll").mockResolvedValue(undefined);
|
|
52
|
+
jest.spyOn(Mcp, "connectToConfigured").mockResolvedValue(undefined);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
jest.restoreAllMocks();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should call closeAll() to tear down existing MCP connections", async () => {
|
|
60
|
+
const getConfig = jest
|
|
61
|
+
.fn()
|
|
62
|
+
.mockResolvedValue({ worker: { allowedTools: [] } });
|
|
63
|
+
|
|
64
|
+
await simulateReloadConfig(Mcp, Tools, mcpServer, getConfig, toolsToUseRef);
|
|
65
|
+
|
|
66
|
+
expect(Mcp.closeAll).toHaveBeenCalledTimes(1);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("should call connectToConfigured() to reconnect MCPs from fresh config", async () => {
|
|
70
|
+
const getConfig = jest
|
|
71
|
+
.fn()
|
|
72
|
+
.mockResolvedValue({ worker: { allowedTools: [] } });
|
|
73
|
+
|
|
74
|
+
await simulateReloadConfig(Mcp, Tools, mcpServer, getConfig, toolsToUseRef);
|
|
75
|
+
|
|
76
|
+
expect(Mcp.connectToConfigured).toHaveBeenCalledWith(Tools);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("should rebuild the tool list from allowedTools in fresh config", async () => {
|
|
80
|
+
// Spy on getToolsByNames so we can track what names were requested
|
|
81
|
+
const toolsByNamesSpy = jest
|
|
82
|
+
.spyOn(Tools, "getToolsByNames")
|
|
83
|
+
.mockReturnValue([{ function: { name: "execCommand" } }] as ReturnType<ToolsService["getToolsByNames"]>);
|
|
84
|
+
|
|
85
|
+
const getConfig = jest
|
|
86
|
+
.fn()
|
|
87
|
+
.mockResolvedValue({ worker: { allowedTools: ["execCommand"] } });
|
|
88
|
+
|
|
89
|
+
await simulateReloadConfig(Mcp, Tools, mcpServer, getConfig, toolsToUseRef);
|
|
90
|
+
|
|
91
|
+
expect(toolsByNamesSpy).toHaveBeenCalledWith(["execCommand"]);
|
|
92
|
+
expect(toolsToUseRef.value).toHaveLength(1);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("should fall back to all tool names when allowedTools is not set", async () => {
|
|
96
|
+
const allNames = ["execCommand", "readFile", "writeFileChunk"];
|
|
97
|
+
jest.spyOn(Tools, "getToolNames").mockReturnValue(allNames);
|
|
98
|
+
const toolsByNamesSpy = jest
|
|
99
|
+
.spyOn(Tools, "getToolsByNames")
|
|
100
|
+
.mockReturnValue([] as ReturnType<ToolsService["getToolsByNames"]>);
|
|
101
|
+
|
|
102
|
+
// Config has no worker.allowedTools
|
|
103
|
+
const getConfig = jest.fn().mockResolvedValue({});
|
|
104
|
+
|
|
105
|
+
await simulateReloadConfig(Mcp, Tools, mcpServer, getConfig, toolsToUseRef);
|
|
106
|
+
|
|
107
|
+
expect(toolsByNamesSpy).toHaveBeenCalledWith(allNames);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("should call mcpServer.withTools() with the rebuilt tool list", async () => {
|
|
111
|
+
const fakeTools = [{ function: { name: "readFile" } }] as ReturnType<ToolsService["getToolsByNames"]>;
|
|
112
|
+
jest.spyOn(Tools, "getToolsByNames").mockReturnValue(fakeTools);
|
|
113
|
+
|
|
114
|
+
const getConfig = jest
|
|
115
|
+
.fn()
|
|
116
|
+
.mockResolvedValue({ worker: { allowedTools: ["readFile"] } });
|
|
117
|
+
|
|
118
|
+
await simulateReloadConfig(Mcp, Tools, mcpServer, getConfig, toolsToUseRef);
|
|
119
|
+
|
|
120
|
+
expect(mcpServer.withTools).toHaveBeenCalledWith(fakeTools);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("should re-read the config on every reload (not use stale config)", async () => {
|
|
124
|
+
const getConfig = jest
|
|
125
|
+
.fn()
|
|
126
|
+
.mockResolvedValueOnce({ worker: { allowedTools: ["execCommand"] } })
|
|
127
|
+
.mockResolvedValueOnce({ worker: { allowedTools: ["readFile", "writeFileChunk"] } });
|
|
128
|
+
|
|
129
|
+
jest.spyOn(Tools, "getToolsByNames").mockReturnValue([]);
|
|
130
|
+
|
|
131
|
+
// First reload
|
|
132
|
+
await simulateReloadConfig(Mcp, Tools, mcpServer, getConfig, toolsToUseRef);
|
|
133
|
+
// Second reload
|
|
134
|
+
await simulateReloadConfig(Mcp, Tools, mcpServer, getConfig, toolsToUseRef);
|
|
135
|
+
|
|
136
|
+
expect(getConfig).toHaveBeenCalledTimes(2);
|
|
137
|
+
// Each reload should tear down and reconnect
|
|
138
|
+
expect(Mcp.closeAll).toHaveBeenCalledTimes(2);
|
|
139
|
+
expect(Mcp.connectToConfigured).toHaveBeenCalledTimes(2);
|
|
140
|
+
});
|
|
141
|
+
});
|