@poolzin/pool-bot 2026.3.16 → 2026.3.18
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/CHANGELOG.md +69 -0
- package/dist/agents/tools/web-fetch.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/commands/skills-openclaw.command.js +123 -0
- package/dist/config/paths.js +7 -0
- package/dist/infra/net/fetch-guard.js +191 -146
- package/dist/media/fetch.js +83 -112
- package/dist/media/inbound-path-policy.js +90 -97
- package/dist/media/read-response-with-limit.js +49 -26
- package/dist/media-understanding/attachments.js +1 -1
- package/dist/plugin-sdk/audio.js +7 -0
- package/dist/plugin-sdk/bluebubbles.js +7 -0
- package/dist/plugin-sdk/browser.js +7 -0
- package/dist/plugin-sdk/canvas.js +7 -0
- package/dist/plugin-sdk/cron.js +7 -0
- package/dist/plugin-sdk/discord-actions.js +6 -0
- package/dist/plugin-sdk/discord.js +7 -0
- package/dist/plugin-sdk/image.js +7 -0
- package/dist/plugin-sdk/imessage.js +6 -0
- package/dist/plugin-sdk/keyed-async-queue.js +35 -0
- package/dist/plugin-sdk/media.js +8 -0
- package/dist/plugin-sdk/memory.js +7 -0
- package/dist/plugin-sdk/pdf.js +7 -0
- package/dist/plugin-sdk/sessions.js +7 -0
- package/dist/plugin-sdk/signal.js +6 -0
- package/dist/plugin-sdk/slack-actions.js +7 -0
- package/dist/plugin-sdk/slack.js +7 -0
- package/dist/plugin-sdk/telegram-actions.js +6 -0
- package/dist/plugin-sdk/telegram.js +6 -0
- package/dist/plugin-sdk/test-utils.js +110 -0
- package/dist/plugin-sdk/tts.js +7 -0
- package/dist/plugin-sdk/whatsapp.js +6 -0
- package/dist/providers/github-copilot-auth.js +53 -76
- package/dist/providers/github-copilot-models.js +63 -35
- package/dist/providers/github-copilot-token.js +46 -89
- package/dist/security/audit-findings.js +165 -0
- package/dist/security/audit.js +141 -572
- package/dist/skills/openclaw-skill-loader.js +191 -0
- package/dist/slack/monitor/media.js +2 -1
- package/docs/branding-evaluation-2026-03-12.md +285 -0
- package/docs/improvements/OPENCLAW-IMPLEMENTATION.md +45 -0
- package/docs/skills/openclaw-integration.md +295 -0
- package/docs/testing/TEST-PLAN-2026-03-13.md +338 -0
- package/docs/version-2026.3.16-evaluation.md +190 -0
- package/extensions/acpx/package.json +19 -0
- package/extensions/acpx/poolbot.plugin.json +9 -0
- package/extensions/acpx/src/index.ts +34 -0
- package/extensions/bluebubbles/src/runtime.ts +1 -0
- package/extensions/diffs/package.json +15 -0
- package/extensions/diffs/poolbot.plugin.json +10 -0
- package/extensions/diffs/src/index.ts +106 -0
- package/extensions/discord/src/runtime.ts +1 -0
- package/extensions/feishu/src/runtime.ts +1 -0
- package/extensions/github-copilot/package.json +28 -0
- package/extensions/github-copilot/poolbot.plugin.json +29 -0
- package/extensions/github-copilot/src/index.ts +126 -0
- package/extensions/github-copilot/tsconfig.json +10 -0
- package/extensions/googlechat/src/runtime.ts +1 -0
- package/extensions/imessage/src/runtime.ts +1 -0
- package/extensions/irc/src/runtime.ts +1 -0
- package/extensions/line/src/runtime.ts +1 -0
- package/extensions/matrix/src/runtime.ts +1 -0
- package/extensions/mattermost/src/mattermost/monitor-helpers.ts +10 -1
- package/extensions/mattermost/src/runtime.ts +6 -3
- package/extensions/msteams/src/runtime.ts +1 -0
- package/extensions/nextcloud-talk/src/runtime.ts +1 -0
- package/extensions/nostr/src/runtime.ts +5 -2
- package/extensions/ollama/package.json +20 -0
- package/extensions/ollama/poolbot.plugin.json +14 -0
- package/extensions/ollama/src/index.ts +95 -0
- package/extensions/sglang/package.json +18 -0
- package/extensions/sglang/poolbot.plugin.json +13 -0
- package/extensions/sglang/src/index.ts +62 -0
- package/extensions/signal/src/runtime.ts +1 -0
- package/extensions/slack/src/runtime.ts +1 -0
- package/extensions/telegram/src/runtime.ts +1 -0
- package/extensions/test-utils/package.json +17 -0
- package/extensions/test-utils/poolbot.plugin.json +16 -0
- package/extensions/test-utils/src/index.ts +220 -0
- package/extensions/tlon/src/runtime.ts +1 -0
- package/extensions/twitch/src/runtime.ts +1 -0
- package/extensions/vllm/package.json +19 -0
- package/extensions/vllm/poolbot.plugin.json +13 -0
- package/extensions/vllm/src/index.ts +90 -0
- package/extensions/whatsapp/src/runtime.ts +1 -0
- package/extensions/zalo/src/runtime.ts +1 -0
- package/extensions/zalouser/src/runtime.ts +1 -0
- package/package.json +77 -3
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { PluginRuntime } from "poolbot/plugin-sdk";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// MattermostPluginRuntime wrapper interface to avoid lint resolution issues
|
|
4
|
+
interface MattermostPluginRuntime extends PluginRuntime {}
|
|
5
|
+
|
|
6
|
+
let runtime: MattermostPluginRuntime | null = null;
|
|
4
7
|
|
|
5
8
|
export function setMattermostRuntime(next: PluginRuntime) {
|
|
6
|
-
runtime = next;
|
|
9
|
+
runtime = next as MattermostPluginRuntime;
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
export function getMattermostRuntime(): PluginRuntime {
|
|
10
13
|
if (!runtime) {
|
|
11
14
|
throw new Error("Mattermost runtime not initialized");
|
|
12
15
|
}
|
|
13
|
-
return runtime;
|
|
16
|
+
return runtime as PluginRuntime;
|
|
14
17
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { PluginRuntime } from "poolbot/plugin-sdk";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// NostrPluginRuntime wrapper interface to avoid lint resolution issues
|
|
4
|
+
interface NostrPluginRuntime extends PluginRuntime {}
|
|
5
|
+
|
|
6
|
+
let runtime: NostrPluginRuntime | null = null;
|
|
4
7
|
|
|
5
8
|
export function setNostrRuntime(next: PluginRuntime): void {
|
|
6
9
|
runtime = next;
|
|
@@ -10,5 +13,5 @@ export function getNostrRuntime(): PluginRuntime {
|
|
|
10
13
|
if (!runtime) {
|
|
11
14
|
throw new Error("Nostr runtime not initialized");
|
|
12
15
|
}
|
|
13
|
-
return runtime;
|
|
16
|
+
return runtime as PluginRuntime;
|
|
14
17
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@poolbot/ollama",
|
|
3
|
+
"version": "2026.3.17",
|
|
4
|
+
"description": "Ollama provider for Pool Bot - local LLM inference",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"poolbot": "workspace:*",
|
|
9
|
+
"ollama": "^0.6.3"
|
|
10
|
+
},
|
|
11
|
+
"poolbot": {
|
|
12
|
+
"extensions": ["./src/index.ts"],
|
|
13
|
+
"provider": {
|
|
14
|
+
"id": "ollama",
|
|
15
|
+
"name": "Ollama",
|
|
16
|
+
"description": "Local LLM inference with Ollama",
|
|
17
|
+
"models": ["llama3", "mistral", "codellama", "phi", "gemma"]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "ollama",
|
|
3
|
+
"name": "Ollama Provider",
|
|
4
|
+
"version": "2026.3.17",
|
|
5
|
+
"description": "Local LLM inference with Ollama",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"capabilities": ["provider", "local-llm"],
|
|
8
|
+
"commands": ["ollama.status", "ollama.models", "ollama.pull"],
|
|
9
|
+
"config": {
|
|
10
|
+
"host": "http://127.0.0.1",
|
|
11
|
+
"port": 11434,
|
|
12
|
+
"defaultModel": "llama3"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool Bot Ollama Provider Extension
|
|
3
|
+
*
|
|
4
|
+
* Provides local LLM inference via Ollama
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export default async function createPlugin(ctx: any): Promise<any> {
|
|
8
|
+
const config = ctx.config as {
|
|
9
|
+
host?: string;
|
|
10
|
+
port?: number;
|
|
11
|
+
defaultModel?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const host = config.host ?? "http://127.0.0.1";
|
|
15
|
+
const port = config.port ?? 11434;
|
|
16
|
+
const baseUrl = `${host}:${port}`;
|
|
17
|
+
|
|
18
|
+
ctx.logger.info(`Ollama Provider initialized (${baseUrl})`);
|
|
19
|
+
|
|
20
|
+
ctx.cli
|
|
21
|
+
.command("ollama.status")
|
|
22
|
+
.description("Check Ollama server status")
|
|
23
|
+
.action(async () => {
|
|
24
|
+
try {
|
|
25
|
+
const res = await fetch(`${baseUrl}/api/tags`);
|
|
26
|
+
if (res.ok) {
|
|
27
|
+
const data = await res.json() as { models: Array<{ name: string }> };
|
|
28
|
+
console.log("✅ Ollama Status");
|
|
29
|
+
console.log(` URL: ${baseUrl}`);
|
|
30
|
+
console.log(` Models: ${data.models.length}`);
|
|
31
|
+
data.models.slice(0, 5).forEach((m) => console.log(` - ${m.name}`));
|
|
32
|
+
} else {
|
|
33
|
+
console.log("❌ Ollama not running");
|
|
34
|
+
}
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.log("❌ Ollama connection failed");
|
|
37
|
+
console.log(` Error: ${error instanceof Error ? error.message : error}`);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
ctx.cli
|
|
42
|
+
.command("ollama.models")
|
|
43
|
+
.description("List available Ollama models")
|
|
44
|
+
.action(async () => {
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch(`${baseUrl}/api/tags`);
|
|
47
|
+
if (!res.ok) throw new Error("Ollama not running");
|
|
48
|
+
|
|
49
|
+
const data = await res.json() as { models: Array<{ name: string; size: number }> };
|
|
50
|
+
console.log("📦 Ollama Models\n");
|
|
51
|
+
|
|
52
|
+
for (const model of data.models) {
|
|
53
|
+
const sizeGB = (model.size / 1e9).toFixed(2);
|
|
54
|
+
console.log(`🤖 ${model.name}`);
|
|
55
|
+
console.log(` Size: ${sizeGB} GB`);
|
|
56
|
+
}
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error("Failed to list models:", error instanceof Error ? error.message : error);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
ctx.cli
|
|
64
|
+
.command("ollama.pull")
|
|
65
|
+
.description("Pull an Ollama model")
|
|
66
|
+
.argument("<model>", "Model name (e.g., llama3, mistral)")
|
|
67
|
+
.action(async (modelName: string) => {
|
|
68
|
+
console.log(`📥 Pulling ${modelName}...`);
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const res = await fetch(`${baseUrl}/api/pull`, {
|
|
72
|
+
method: "POST",
|
|
73
|
+
headers: { "Content-Type": "application/json" },
|
|
74
|
+
body: JSON.stringify({ name: modelName }),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
if (res.ok) {
|
|
78
|
+
console.log(`✅ Model ${modelName} pulled successfully`);
|
|
79
|
+
} else {
|
|
80
|
+
const error = await res.text();
|
|
81
|
+
console.error(`❌ Failed to pull: ${error}`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error("Failed to pull model:", error instanceof Error ? error.message : error);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
name: "ollama",
|
|
92
|
+
version: "2026.3.17",
|
|
93
|
+
commands: ["ollama.status", "ollama.models", "ollama.pull"],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@poolbot/sglang",
|
|
3
|
+
"version": "2026.3.17",
|
|
4
|
+
"description": "SGLang provider for Pool Bot - optimized LLM inference",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"poolbot": "workspace:*"
|
|
9
|
+
},
|
|
10
|
+
"poolbot": {
|
|
11
|
+
"extensions": ["./src/index.ts"],
|
|
12
|
+
"provider": {
|
|
13
|
+
"id": "sglang",
|
|
14
|
+
"name": "SGLang",
|
|
15
|
+
"description": "SGLang runtime for optimized LLM inference"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "sglang",
|
|
3
|
+
"name": "SGLang Provider",
|
|
4
|
+
"version": "2026.3.17",
|
|
5
|
+
"description": "SGLang runtime for optimized LLM inference",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"capabilities": ["provider", "optimized-inference"],
|
|
8
|
+
"commands": ["sglang.status", "sglang.models"],
|
|
9
|
+
"config": {
|
|
10
|
+
"host": "http://127.0.0.1",
|
|
11
|
+
"port": 30000
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool Bot SGLang Provider Extension
|
|
3
|
+
*
|
|
4
|
+
* Provides SGLang runtime for optimized LLM inference
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export default async function createPlugin(ctx: any): Promise<any> {
|
|
8
|
+
const config = ctx.config as {
|
|
9
|
+
host?: string;
|
|
10
|
+
port?: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const host = config.host ?? "http://127.0.0.1";
|
|
14
|
+
const port = config.port ?? 30000;
|
|
15
|
+
const baseUrl = `${host}:${port}`;
|
|
16
|
+
|
|
17
|
+
ctx.logger.info(`SGLang Provider initialized (${baseUrl})`);
|
|
18
|
+
|
|
19
|
+
ctx.cli
|
|
20
|
+
.command("sglang.status")
|
|
21
|
+
.description("Check SGLang server status")
|
|
22
|
+
.action(async () => {
|
|
23
|
+
try {
|
|
24
|
+
const res = await fetch(`${baseUrl}/health`);
|
|
25
|
+
if (res.ok) {
|
|
26
|
+
console.log("✅ SGLang Status");
|
|
27
|
+
console.log(` URL: ${baseUrl}`);
|
|
28
|
+
console.log(` Status: Running`);
|
|
29
|
+
} else {
|
|
30
|
+
console.log("❌ SGLang not running");
|
|
31
|
+
}
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.log("❌ SGLang connection failed");
|
|
34
|
+
console.log(` Error: ${error instanceof Error ? error.message : error}`);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
ctx.cli
|
|
39
|
+
.command("sglang.models")
|
|
40
|
+
.description("List available SGLang models")
|
|
41
|
+
.action(async () => {
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetch(`${baseUrl}/v1/models`);
|
|
44
|
+
if (!res.ok) throw new Error("SGLang not running");
|
|
45
|
+
|
|
46
|
+
const data = await res.json() as { data: Array<{ id: string }> };
|
|
47
|
+
console.log("📦 SGLang Models\n");
|
|
48
|
+
|
|
49
|
+
for (const model of data.data) {
|
|
50
|
+
console.log(`🤖 ${model.id}`);
|
|
51
|
+
}
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error("Failed to list models:", error instanceof Error ? error.message : error);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
name: "sglang",
|
|
59
|
+
version: "2026.3.17",
|
|
60
|
+
commands: ["sglang.status", "sglang.models"],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@poolbot/test-utils",
|
|
3
|
+
"version": "2026.3.17",
|
|
4
|
+
"description": "Pool Bot test utilities and helpers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"poolbot": "workspace:*"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"vitest": "^4.0.18"
|
|
12
|
+
},
|
|
13
|
+
"poolbot": {
|
|
14
|
+
"extensions": ["./src/index.ts"],
|
|
15
|
+
"testUtils": true
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "test-utils",
|
|
3
|
+
"name": "Test Utilities",
|
|
4
|
+
"version": "2026.3.17",
|
|
5
|
+
"description": "Testing utilities and helpers for Pool Bot development",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"capabilities": ["testing", "mocking"],
|
|
8
|
+
"commands": ["test.mock-config"],
|
|
9
|
+
"exports": {
|
|
10
|
+
"createMockConfig": "./dist/index.js",
|
|
11
|
+
"createMockRuntime": "./dist/index.js",
|
|
12
|
+
"waitForCondition": "./dist/index.js",
|
|
13
|
+
"createTempFile": "./dist/index.js",
|
|
14
|
+
"cleanupTempFiles": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool Bot Test Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides testing utilities and helpers for Pool Bot development
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { PoolBotConfig } from "poolbot/config/config.js";
|
|
8
|
+
import type { PluginRuntime } from "poolbot/plugins/runtime/types.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create a mock Pool Bot config for testing
|
|
12
|
+
*/
|
|
13
|
+
export function createMockConfig(overrides?: Partial<PoolBotConfig>): PoolBotConfig {
|
|
14
|
+
return {
|
|
15
|
+
models: {
|
|
16
|
+
primary: "gpt-4o",
|
|
17
|
+
},
|
|
18
|
+
agents: {
|
|
19
|
+
list: [],
|
|
20
|
+
},
|
|
21
|
+
channels: {},
|
|
22
|
+
gateway: {
|
|
23
|
+
port: 18789,
|
|
24
|
+
host: "127.0.0.1",
|
|
25
|
+
},
|
|
26
|
+
...overrides,
|
|
27
|
+
} as PoolBotConfig;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create a mock Plugin Runtime for testing
|
|
32
|
+
*/
|
|
33
|
+
export function createMockRuntime(): PluginRuntime {
|
|
34
|
+
return {
|
|
35
|
+
version: "test",
|
|
36
|
+
config: {
|
|
37
|
+
loadConfig: async () => createMockConfig(),
|
|
38
|
+
writeConfigFile: async () => {},
|
|
39
|
+
},
|
|
40
|
+
system: {
|
|
41
|
+
enqueueSystemEvent: async () => {},
|
|
42
|
+
runCommandWithTimeout: async () => ({ stdout: "", stderr: "", exitCode: 0 }),
|
|
43
|
+
formatNativeDependencyHint: () => "",
|
|
44
|
+
},
|
|
45
|
+
media: {
|
|
46
|
+
loadWebMedia: async () => ({ buffer: Buffer.from([]) }),
|
|
47
|
+
detectMime: async () => "application/octet-stream",
|
|
48
|
+
mediaKindFromMime: () => "unknown" as any,
|
|
49
|
+
isVoiceCompatibleAudio: () => false,
|
|
50
|
+
getImageMetadata: async () => ({ width: 0, height: 0 }),
|
|
51
|
+
resizeToJpeg: async () => Buffer.from([]),
|
|
52
|
+
},
|
|
53
|
+
tts: {
|
|
54
|
+
textToSpeechTelephony: async () => ({ audioPath: "" }),
|
|
55
|
+
},
|
|
56
|
+
tools: {
|
|
57
|
+
createMemoryGetTool: () => ({} as any),
|
|
58
|
+
createMemorySearchTool: () => ({} as any),
|
|
59
|
+
registerMemoryCli: () => {},
|
|
60
|
+
},
|
|
61
|
+
channel: {
|
|
62
|
+
text: {
|
|
63
|
+
chunkByNewline: () => [],
|
|
64
|
+
chunkMarkdownText: () => [],
|
|
65
|
+
chunkMarkdownTextWithMode: () => [],
|
|
66
|
+
chunkText: () => [],
|
|
67
|
+
chunkTextWithMode: () => [],
|
|
68
|
+
resolveChunkMode: () => "markdown" as const,
|
|
69
|
+
resolveTextChunkLimit: () => 4000,
|
|
70
|
+
hasControlCommand: () => false,
|
|
71
|
+
resolveMarkdownTableMode: () => "convert" as const,
|
|
72
|
+
convertMarkdownTables: () => "",
|
|
73
|
+
},
|
|
74
|
+
reply: {
|
|
75
|
+
dispatchReplyWithBufferedBlockDispatcher: async () => {},
|
|
76
|
+
createReplyDispatcherWithTyping: () => ({} as any),
|
|
77
|
+
resolveEffectiveMessagesConfig: () => ({} as any),
|
|
78
|
+
resolveHumanDelayConfig: () => ({} as any),
|
|
79
|
+
dispatchReplyFromConfig: async () => {},
|
|
80
|
+
finalizeInboundContext: async () => ({} as any),
|
|
81
|
+
formatAgentEnvelope: () => "",
|
|
82
|
+
formatInboundEnvelope: () => "",
|
|
83
|
+
resolveEnvelopeFormatOptions: () => ({} as any),
|
|
84
|
+
},
|
|
85
|
+
routing: {
|
|
86
|
+
resolveAgentRoute: async () => null,
|
|
87
|
+
},
|
|
88
|
+
pairing: {
|
|
89
|
+
buildPairingReply: () => "",
|
|
90
|
+
readAllowFromStore: async () => [],
|
|
91
|
+
upsertPairingRequest: async () => {},
|
|
92
|
+
},
|
|
93
|
+
identity: {
|
|
94
|
+
resolveEffectiveMessagesConfig: () => ({} as any),
|
|
95
|
+
resolveHumanDelayConfig: () => ({} as any),
|
|
96
|
+
},
|
|
97
|
+
lifecycle: {
|
|
98
|
+
enqueueSystemEvent: async () => {},
|
|
99
|
+
},
|
|
100
|
+
gateway: {
|
|
101
|
+
call: async () => ({} as any),
|
|
102
|
+
},
|
|
103
|
+
security: {
|
|
104
|
+
checkDmPolicy: async () => "allow" as const,
|
|
105
|
+
},
|
|
106
|
+
mentions: {
|
|
107
|
+
buildMentionRegexes: () => [],
|
|
108
|
+
matchesMentionPatterns: () => false,
|
|
109
|
+
matchesMentionWithExplicit: () => false,
|
|
110
|
+
},
|
|
111
|
+
reactions: {
|
|
112
|
+
shouldAckReaction: () => false,
|
|
113
|
+
removeAckReactionAfterReply: async () => {},
|
|
114
|
+
},
|
|
115
|
+
group: {
|
|
116
|
+
resolveChannelGroupPolicy: () => "mention" as const,
|
|
117
|
+
resolveChannelGroupRequireMention: () => true,
|
|
118
|
+
},
|
|
119
|
+
debounce: {
|
|
120
|
+
createInboundDebouncer: () => ({} as any),
|
|
121
|
+
resolveInboundDebounceMs: () => 0,
|
|
122
|
+
},
|
|
123
|
+
gating: {
|
|
124
|
+
resolveCommandAuthorizedFromAuthorizers: async () => false,
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
logging: {
|
|
128
|
+
debug: () => {},
|
|
129
|
+
info: () => {},
|
|
130
|
+
warn: () => {},
|
|
131
|
+
error: () => {},
|
|
132
|
+
},
|
|
133
|
+
state: {
|
|
134
|
+
getStateDir: () => "/tmp/poolbot-test",
|
|
135
|
+
},
|
|
136
|
+
logger: {
|
|
137
|
+
debug: () => {},
|
|
138
|
+
info: () => {},
|
|
139
|
+
warn: () => {},
|
|
140
|
+
error: () => {},
|
|
141
|
+
},
|
|
142
|
+
} as PluginRuntime;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Test helper: wait for a condition to be true
|
|
147
|
+
*/
|
|
148
|
+
export async function waitForCondition(
|
|
149
|
+
condition: () => boolean | Promise<boolean>,
|
|
150
|
+
timeoutMs: number = 5000,
|
|
151
|
+
intervalMs: number = 100,
|
|
152
|
+
): Promise<void> {
|
|
153
|
+
const start = Date.now();
|
|
154
|
+
|
|
155
|
+
while (Date.now() - start < timeoutMs) {
|
|
156
|
+
const result = await condition();
|
|
157
|
+
if (result) return;
|
|
158
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
throw new Error(`Condition not met within ${timeoutMs}ms`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Test helper: create a temporary file
|
|
166
|
+
*/
|
|
167
|
+
export async function createTempFile(content: string, extension: string = ".txt"): Promise<string> {
|
|
168
|
+
const fs = await import("node:fs/promises");
|
|
169
|
+
const path = await import("node:path");
|
|
170
|
+
const os = await import("node:os");
|
|
171
|
+
|
|
172
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "poolbot-test-"));
|
|
173
|
+
const filePath = path.join(tmpDir, `test${extension}`);
|
|
174
|
+
await fs.writeFile(filePath, content, "utf-8");
|
|
175
|
+
|
|
176
|
+
return filePath;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Test helper: cleanup temporary files
|
|
181
|
+
*/
|
|
182
|
+
export async function cleanupTempFiles(...paths: string[]): Promise<void> {
|
|
183
|
+
const fs = await import("node:fs/promises");
|
|
184
|
+
|
|
185
|
+
for (const p of paths) {
|
|
186
|
+
try {
|
|
187
|
+
await fs.rm(p, { recursive: true, force: true });
|
|
188
|
+
} catch {
|
|
189
|
+
// Ignore cleanup errors
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Export CLI command for test utilities
|
|
195
|
+
export default async function createPlugin(ctx: any): Promise<any> {
|
|
196
|
+
ctx.logger.info("Test Utils initialized");
|
|
197
|
+
|
|
198
|
+
ctx.cli
|
|
199
|
+
.command("test.mock-config")
|
|
200
|
+
.description("Generate a mock config for testing")
|
|
201
|
+
.option("-o, --output <file>", "Output file path")
|
|
202
|
+
.action(async (options?: { output?: string }) => {
|
|
203
|
+
const config = createMockConfig();
|
|
204
|
+
const json = JSON.stringify(config, null, 2);
|
|
205
|
+
|
|
206
|
+
if (options?.output) {
|
|
207
|
+
const fs = await import("node:fs/promises");
|
|
208
|
+
await fs.writeFile(options.output, json, "utf-8");
|
|
209
|
+
console.log(`✅ Mock config written to ${options.output}`);
|
|
210
|
+
} else {
|
|
211
|
+
console.log(json);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
name: "test-utils",
|
|
217
|
+
version: "2026.3.17",
|
|
218
|
+
commands: ["test.mock-config"],
|
|
219
|
+
};
|
|
220
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@poolbot/vllm",
|
|
3
|
+
"version": "2026.3.17",
|
|
4
|
+
"description": "vLLM provider for Pool Bot - high-throughput LLM inference",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"poolbot": "workspace:*"
|
|
9
|
+
},
|
|
10
|
+
"poolbot": {
|
|
11
|
+
"extensions": ["./src/index.ts"],
|
|
12
|
+
"provider": {
|
|
13
|
+
"id": "vllm",
|
|
14
|
+
"name": "vLLM",
|
|
15
|
+
"description": "vLLM for high-throughput LLM inference",
|
|
16
|
+
"models": ["llama", "mistral", "qwen", "yi"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "vllm",
|
|
3
|
+
"name": "vLLM Provider",
|
|
4
|
+
"version": "2026.3.17",
|
|
5
|
+
"description": "vLLM for high-throughput LLM inference",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"capabilities": ["provider", "high-throughput"],
|
|
8
|
+
"commands": ["vllm.status", "vllm.models", "vllm.generate"],
|
|
9
|
+
"config": {
|
|
10
|
+
"host": "http://127.0.0.1",
|
|
11
|
+
"port": 8000
|
|
12
|
+
}
|
|
13
|
+
}
|