@poolzin/pool-bot 2026.2.23 → 2026.2.25
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 +29 -0
- package/dist/acp/client.js +207 -18
- package/dist/acp/secret-file.js +22 -0
- package/dist/agents/agent-scope.js +10 -0
- package/dist/agents/bash-process-registry.test-helpers.js +29 -0
- package/dist/agents/bash-tools.exec-approval-request.js +20 -0
- package/dist/agents/bash-tools.exec-host-gateway.js +230 -0
- package/dist/agents/bash-tools.exec-host-node.js +235 -0
- package/dist/agents/bash-tools.exec-types.js +1 -0
- package/dist/agents/bash-tools.process.js +224 -218
- package/dist/agents/content-blocks.js +16 -0
- package/dist/agents/model-fallback.js +96 -101
- package/dist/agents/models-config.providers.js +299 -182
- package/dist/agents/pi-embedded-payloads.js +1 -0
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
- package/dist/agents/skills.test-helpers.js +13 -0
- package/dist/agents/stable-stringify.js +12 -0
- package/dist/agents/subagent-registry.mocks.shared.js +12 -0
- package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
- package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
- package/dist/agents/tool-policy-shared.js +108 -0
- package/dist/agents/tools/browser-tool.js +160 -54
- package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
- package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
- package/dist/agents/tools/image-tool.js +214 -99
- package/dist/agents/tools/sessions-history-tool.js +140 -108
- package/dist/agents/workspace.js +222 -46
- package/dist/auto-reply/commands-registry.js +15 -18
- package/dist/auto-reply/fallback-state.js +114 -0
- package/dist/auto-reply/model-runtime.js +68 -0
- package/dist/auto-reply/reply/agent-runner-execution.js +36 -4
- package/dist/auto-reply/reply/agent-runner.js +165 -39
- package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
- package/dist/browser/config.js +26 -0
- package/dist/browser/navigation-guard.js +31 -0
- package/dist/browser/routes/agent.act.js +431 -424
- package/dist/browser/routes/agent.shared.js +47 -3
- package/dist/browser/routes/agent.snapshot.js +122 -116
- package/dist/browser/routes/agent.storage.js +303 -297
- package/dist/browser/routes/tabs.js +154 -100
- package/dist/browser/server-lifecycle.js +37 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/allow-from.js +25 -0
- package/dist/channels/plugins/account-action-gate.js +13 -0
- package/dist/channels/plugins/message-actions.js +10 -0
- package/dist/channels/telegram/api.js +18 -0
- package/dist/cli/argv.js +84 -21
- package/dist/cli/banner.js +2 -1
- package/dist/cli/exec-approvals-cli.js +92 -124
- package/dist/cli/memory-cli.js +158 -61
- package/dist/cli/nodes-cli/register.push.js +63 -0
- package/dist/cli/nodes-media-utils.js +21 -0
- package/dist/cli/plugins-cli.js +245 -61
- package/dist/cli/program/build-program.js +3 -1
- package/dist/cli/program/command-registry.js +223 -136
- package/dist/cli/program/help.js +43 -12
- package/dist/cli/route.js +1 -1
- package/dist/cli/test-runtime-capture.js +24 -0
- package/dist/commands/agent.js +163 -87
- package/dist/commands/channels.mock-harness.js +23 -0
- package/dist/commands/daemon-install-runtime-warning.js +11 -0
- package/dist/commands/onboard-helpers.js +4 -4
- package/dist/commands/sessions.test-helpers.js +61 -0
- package/dist/compat/legacy-names.js +2 -2
- package/dist/config/commands.js +3 -0
- package/dist/config/config.js +1 -1
- package/dist/config/env-substitution.js +62 -34
- package/dist/config/env-vars.js +9 -0
- package/dist/config/io.js +571 -171
- package/dist/config/merge-patch.js +50 -4
- package/dist/config/redact-snapshot.js +404 -76
- package/dist/config/schema.js +58 -570
- package/dist/config/validation.js +140 -85
- package/dist/config/zod-schema.hooks.js +40 -11
- package/dist/config/zod-schema.installs.js +20 -0
- package/dist/config/zod-schema.js +8 -7
- package/dist/control-ui/assets/{index-HRr1grwl.js → index-Dvkl4Xlx.js} +2 -1
- package/dist/control-ui/assets/{index-HRr1grwl.js.map → index-Dvkl4Xlx.js.map} +1 -1
- package/dist/control-ui/index.html +1 -1
- package/dist/daemon/cmd-argv.js +21 -0
- package/dist/daemon/cmd-set.js +58 -0
- package/dist/daemon/service-types.js +1 -0
- package/dist/discord/monitor/exec-approvals.js +357 -162
- package/dist/gateway/auth.js +38 -3
- package/dist/gateway/call.js +149 -68
- package/dist/gateway/canvas-capability.js +75 -0
- package/dist/gateway/control-plane-audit.js +28 -0
- package/dist/gateway/control-plane-rate-limit.js +53 -0
- package/dist/gateway/events.js +1 -0
- package/dist/gateway/hooks.js +109 -54
- package/dist/gateway/http-common.js +22 -0
- package/dist/gateway/method-scopes.js +169 -0
- package/dist/gateway/net.js +23 -0
- package/dist/gateway/openresponses-http.js +120 -110
- package/dist/gateway/probe-auth.js +2 -0
- package/dist/gateway/protocol/index.js +3 -2
- package/dist/gateway/protocol/schema/protocol-schemas.js +2 -0
- package/dist/gateway/protocol/schema/push.js +18 -0
- package/dist/gateway/protocol/schema.js +1 -0
- package/dist/gateway/server-http.js +236 -52
- package/dist/gateway/server-methods/agent.js +162 -24
- package/dist/gateway/server-methods/chat.js +461 -130
- package/dist/gateway/server-methods/config.js +193 -150
- package/dist/gateway/server-methods/nodes.helpers.js +12 -0
- package/dist/gateway/server-methods/nodes.js +251 -69
- package/dist/gateway/server-methods/push.js +53 -0
- package/dist/gateway/server-reload-handlers.js +2 -3
- package/dist/gateway/server-runtime-config.js +5 -0
- package/dist/gateway/server-runtime-state.js +2 -0
- package/dist/gateway/server-ws-runtime.js +1 -0
- package/dist/gateway/server.impl.js +296 -139
- package/dist/gateway/session-preview.test-helpers.js +11 -0
- package/dist/gateway/startup-auth.js +126 -0
- package/dist/gateway/test-helpers.agent-results.js +15 -0
- package/dist/gateway/test-helpers.mocks.js +37 -14
- package/dist/gateway/test-helpers.server.js +161 -77
- package/dist/hooks/bundled/session-memory/handler.js +165 -34
- package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
- package/dist/infra/archive-path.js +49 -0
- package/dist/infra/device-pairing.js +148 -167
- package/dist/infra/exec-approvals-allowlist.js +19 -70
- package/dist/infra/exec-approvals-analysis.js +44 -17
- package/dist/infra/exec-safe-bin-policy.js +269 -0
- package/dist/infra/fixed-window-rate-limit.js +33 -0
- package/dist/infra/git-root.js +61 -0
- package/dist/infra/heartbeat-active-hours.js +2 -2
- package/dist/infra/heartbeat-reason.js +40 -0
- package/dist/infra/heartbeat-runner.js +72 -32
- package/dist/infra/install-source-utils.js +91 -7
- package/dist/infra/node-pairing.js +50 -105
- package/dist/infra/npm-integrity.js +45 -0
- package/dist/infra/npm-pack-install.js +40 -0
- package/dist/infra/outbound/channel-adapters.js +20 -7
- package/dist/infra/outbound/message-action-runner.js +107 -327
- package/dist/infra/outbound/message.js +59 -36
- package/dist/infra/outbound/outbound-policy.js +52 -25
- package/dist/infra/outbound/outbound-send-service.js +58 -71
- package/dist/infra/pairing-files.js +10 -0
- package/dist/infra/plain-object.js +9 -0
- package/dist/infra/push-apns.js +365 -0
- package/dist/infra/restart-sentinel.js +16 -1
- package/dist/infra/restart.js +229 -26
- package/dist/infra/scp-host.js +54 -0
- package/dist/infra/update-startup.js +86 -9
- package/dist/media/inbound-path-policy.js +114 -0
- package/dist/media/input-files.js +16 -0
- package/dist/memory/test-manager.js +8 -0
- package/dist/plugin-sdk/temp-path.js +47 -0
- package/dist/plugins/discovery.js +217 -23
- package/dist/plugins/hook-runner-global.js +16 -0
- package/dist/plugins/loader.js +192 -26
- package/dist/plugins/logger.js +8 -0
- package/dist/plugins/manifest-registry.js +3 -0
- package/dist/plugins/path-safety.js +34 -0
- package/dist/plugins/registry.js +5 -2
- package/dist/plugins/runtime/index.js +271 -206
- package/dist/providers/github-copilot-models.js +4 -1
- package/dist/security/audit-channel.js +8 -19
- package/dist/security/audit-extra.async.js +354 -182
- package/dist/security/audit-extra.js +11 -1
- package/dist/security/audit-extra.sync.js +340 -33
- package/dist/security/audit-fs.js +31 -13
- package/dist/security/audit.js +145 -371
- package/dist/security/dm-policy-shared.js +24 -0
- package/dist/security/external-content.js +20 -8
- package/dist/security/fix.js +49 -85
- package/dist/security/scan-paths.js +20 -0
- package/dist/security/secret-equal.js +3 -7
- package/dist/security/windows-acl.js +30 -15
- package/dist/shared/node-list-parse.js +13 -0
- package/dist/shared/operator-scope-compat.js +37 -0
- package/dist/shared/text-chunking.js +29 -0
- package/dist/slack/blocks.test-helpers.js +31 -0
- package/dist/slack/monitor/mrkdwn.js +8 -0
- package/dist/telegram/bot-message-dispatch.js +366 -164
- package/dist/telegram/draft-stream.js +30 -7
- package/dist/telegram/reasoning-lane-coordinator.js +128 -0
- package/dist/terminal/prompt-select-styled.js +9 -0
- package/dist/test-utils/command-runner.js +6 -0
- package/dist/test-utils/internal-hook-event-payload.js +10 -0
- package/dist/test-utils/model-auth-mock.js +12 -0
- package/dist/test-utils/provider-usage-fetch.js +14 -0
- package/dist/test-utils/temp-home.js +33 -0
- package/dist/tui/components/chat-log.js +9 -0
- package/dist/tui/tui-command-handlers.js +36 -27
- package/dist/tui/tui-event-handlers.js +122 -32
- package/dist/tui/tui.js +181 -45
- package/dist/utils/mask-api-key.js +10 -0
- package/dist/utils/run-with-concurrency.js +39 -0
- package/dist/web/media.js +4 -0
- package/docs/tools/slash-commands.md +5 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +1 -1
- package/extensions/feishu/src/external-keys.ts +19 -0
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/lobster/src/windows-spawn.ts +193 -0
- package/extensions/matrix/CHANGELOG.md +5 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
- package/extensions/mattermost/package.json +1 -1
- package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +5 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +5 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +5 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +5 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +5 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +5 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
package/dist/plugins/loader.js
CHANGED
|
@@ -3,37 +3,43 @@ import path from "node:path";
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { createJiti } from "jiti";
|
|
5
5
|
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
6
|
+
import { isPathInsideWithRealpath } from "../security/scan-paths.js";
|
|
6
7
|
import { resolveUserPath } from "../utils.js";
|
|
8
|
+
import { clearPluginCommands } from "./commands.js";
|
|
9
|
+
import { applyTestPluginDefaults, normalizePluginsConfig, resolveEnableState, resolveMemorySlotDecision, } from "./config-state.js";
|
|
7
10
|
import { discoverPoolBotPlugins } from "./discovery.js";
|
|
8
|
-
import { loadPluginManifestRegistry } from "./manifest-registry.js";
|
|
9
|
-
import { normalizePluginsConfig, resolveEnableState, resolveMemorySlotDecision, } from "./config-state.js";
|
|
10
11
|
import { initializeGlobalHookRunner } from "./hook-runner-global.js";
|
|
11
|
-
import {
|
|
12
|
+
import { loadPluginManifestRegistry } from "./manifest-registry.js";
|
|
13
|
+
import { isPathInside, safeStatSync } from "./path-safety.js";
|
|
12
14
|
import { createPluginRegistry } from "./registry.js";
|
|
13
|
-
import { createPluginRuntime } from "./runtime/index.js";
|
|
14
15
|
import { setActivePluginRegistry } from "./runtime.js";
|
|
16
|
+
import { createPluginRuntime } from "./runtime/index.js";
|
|
15
17
|
import { validateJsonSchemaValue } from "./schema-validator.js";
|
|
16
18
|
const registryCache = new Map();
|
|
17
19
|
const defaultLogger = () => createSubsystemLogger("plugins");
|
|
18
|
-
const
|
|
20
|
+
const resolvePluginSdkAliasFile = (params) => {
|
|
19
21
|
try {
|
|
20
22
|
const modulePath = fileURLToPath(import.meta.url);
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
24
|
+
const isTest = process.env.VITEST || process.env.NODE_ENV === "test";
|
|
23
25
|
let cursor = path.dirname(modulePath);
|
|
24
26
|
for (let i = 0; i < 6; i += 1) {
|
|
25
|
-
const srcCandidate = path.join(cursor, "src", "plugin-sdk",
|
|
26
|
-
const distCandidate = path.join(cursor, "dist", "plugin-sdk",
|
|
27
|
-
const orderedCandidates =
|
|
28
|
-
?
|
|
27
|
+
const srcCandidate = path.join(cursor, "src", "plugin-sdk", params.srcFile);
|
|
28
|
+
const distCandidate = path.join(cursor, "dist", "plugin-sdk", params.distFile);
|
|
29
|
+
const orderedCandidates = isProduction
|
|
30
|
+
? isTest
|
|
31
|
+
? [distCandidate, srcCandidate]
|
|
32
|
+
: [distCandidate]
|
|
29
33
|
: [srcCandidate, distCandidate];
|
|
30
34
|
for (const candidate of orderedCandidates) {
|
|
31
|
-
if (fs.existsSync(candidate))
|
|
35
|
+
if (fs.existsSync(candidate)) {
|
|
32
36
|
return candidate;
|
|
37
|
+
}
|
|
33
38
|
}
|
|
34
39
|
const parent = path.dirname(cursor);
|
|
35
|
-
if (parent === cursor)
|
|
40
|
+
if (parent === cursor) {
|
|
36
41
|
break;
|
|
42
|
+
}
|
|
37
43
|
cursor = parent;
|
|
38
44
|
}
|
|
39
45
|
}
|
|
@@ -42,6 +48,10 @@ const resolvePluginSdkAlias = () => {
|
|
|
42
48
|
}
|
|
43
49
|
return null;
|
|
44
50
|
};
|
|
51
|
+
const resolvePluginSdkAlias = () => resolvePluginSdkAliasFile({ srcFile: "index.ts", distFile: "index.js" });
|
|
52
|
+
const resolvePluginSdkAccountIdAlias = () => {
|
|
53
|
+
return resolvePluginSdkAliasFile({ srcFile: "account-id.ts", distFile: "account-id.js" });
|
|
54
|
+
};
|
|
45
55
|
function buildCacheKey(params) {
|
|
46
56
|
const workspaceKey = params.workspaceDir ? resolveUserPath(params.workspaceDir) : "";
|
|
47
57
|
return `${workspaceKey}::${JSON.stringify(params.plugins)}`;
|
|
@@ -109,8 +119,118 @@ function createPluginRecord(params) {
|
|
|
109
119
|
function pushDiagnostics(diagnostics, append) {
|
|
110
120
|
diagnostics.push(...append);
|
|
111
121
|
}
|
|
122
|
+
function createPathMatcher() {
|
|
123
|
+
return { exact: new Set(), dirs: [] };
|
|
124
|
+
}
|
|
125
|
+
function addPathToMatcher(matcher, rawPath) {
|
|
126
|
+
const trimmed = rawPath.trim();
|
|
127
|
+
if (!trimmed) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const resolved = resolveUserPath(trimmed);
|
|
131
|
+
if (!resolved) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (matcher.exact.has(resolved) || matcher.dirs.includes(resolved)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const stat = safeStatSync(resolved);
|
|
138
|
+
if (stat?.isDirectory()) {
|
|
139
|
+
matcher.dirs.push(resolved);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
matcher.exact.add(resolved);
|
|
143
|
+
}
|
|
144
|
+
function matchesPathMatcher(matcher, sourcePath) {
|
|
145
|
+
if (matcher.exact.has(sourcePath)) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
return matcher.dirs.some((dirPath) => isPathInside(dirPath, sourcePath));
|
|
149
|
+
}
|
|
150
|
+
function buildProvenanceIndex(params) {
|
|
151
|
+
const loadPathMatcher = createPathMatcher();
|
|
152
|
+
for (const loadPath of params.normalizedLoadPaths) {
|
|
153
|
+
addPathToMatcher(loadPathMatcher, loadPath);
|
|
154
|
+
}
|
|
155
|
+
const installRules = new Map();
|
|
156
|
+
const installs = params.config.plugins?.installs ?? {};
|
|
157
|
+
for (const [pluginId, install] of Object.entries(installs)) {
|
|
158
|
+
const rule = {
|
|
159
|
+
trackedWithoutPaths: false,
|
|
160
|
+
matcher: createPathMatcher(),
|
|
161
|
+
};
|
|
162
|
+
const trackedPaths = [install.installPath, install.sourcePath]
|
|
163
|
+
.map((entry) => (typeof entry === "string" ? entry.trim() : ""))
|
|
164
|
+
.filter(Boolean);
|
|
165
|
+
if (trackedPaths.length === 0) {
|
|
166
|
+
rule.trackedWithoutPaths = true;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
for (const trackedPath of trackedPaths) {
|
|
170
|
+
addPathToMatcher(rule.matcher, trackedPath);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
installRules.set(pluginId, rule);
|
|
174
|
+
}
|
|
175
|
+
return { loadPathMatcher, installRules };
|
|
176
|
+
}
|
|
177
|
+
function isTrackedByProvenance(params) {
|
|
178
|
+
const sourcePath = resolveUserPath(params.source);
|
|
179
|
+
const installRule = params.index.installRules.get(params.pluginId);
|
|
180
|
+
if (installRule) {
|
|
181
|
+
if (installRule.trackedWithoutPaths) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
if (matchesPathMatcher(installRule.matcher, sourcePath)) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return matchesPathMatcher(params.index.loadPathMatcher, sourcePath);
|
|
189
|
+
}
|
|
190
|
+
function warnWhenAllowlistIsOpen(params) {
|
|
191
|
+
if (!params.pluginsEnabled) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (params.allow.length > 0) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const nonBundled = params.discoverablePlugins.filter((entry) => entry.origin !== "bundled");
|
|
198
|
+
if (nonBundled.length === 0) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const preview = nonBundled
|
|
202
|
+
.slice(0, 6)
|
|
203
|
+
.map((entry) => `${entry.id} (${entry.source})`)
|
|
204
|
+
.join(", ");
|
|
205
|
+
const extra = nonBundled.length > 6 ? ` (+${nonBundled.length - 6} more)` : "";
|
|
206
|
+
params.logger.warn(`[plugins] plugins.allow is empty; discovered non-bundled plugins may auto-load: ${preview}${extra}. Set plugins.allow to explicit trusted ids.`);
|
|
207
|
+
}
|
|
208
|
+
function warnAboutUntrackedLoadedPlugins(params) {
|
|
209
|
+
for (const plugin of params.registry.plugins) {
|
|
210
|
+
if (plugin.status !== "loaded" || plugin.origin === "bundled") {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (isTrackedByProvenance({
|
|
214
|
+
pluginId: plugin.id,
|
|
215
|
+
source: plugin.source,
|
|
216
|
+
index: params.provenance,
|
|
217
|
+
})) {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
const message = "loaded without install/load-path provenance; treat as untracked local code and pin trust via plugins.allow or install records";
|
|
221
|
+
params.registry.diagnostics.push({
|
|
222
|
+
level: "warn",
|
|
223
|
+
pluginId: plugin.id,
|
|
224
|
+
source: plugin.source,
|
|
225
|
+
message,
|
|
226
|
+
});
|
|
227
|
+
params.logger.warn(`[plugins] ${plugin.id}: ${message} (${plugin.source})`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
112
230
|
export function loadPoolBotPlugins(options = {}) {
|
|
113
|
-
|
|
231
|
+
// Test env: default-disable plugins unless explicitly configured.
|
|
232
|
+
// This keeps unit/gateway suites fast and avoids loading heavyweight plugin deps by accident.
|
|
233
|
+
const cfg = applyTestPluginDefaults(options.config ?? {}, process.env);
|
|
114
234
|
const logger = options.logger ?? defaultLogger();
|
|
115
235
|
const validateOnly = options.mode === "validate";
|
|
116
236
|
const normalized = normalizePluginsConfig(cfg.plugins);
|
|
@@ -146,18 +266,44 @@ export function loadPoolBotPlugins(options = {}) {
|
|
|
146
266
|
diagnostics: discovery.diagnostics,
|
|
147
267
|
});
|
|
148
268
|
pushDiagnostics(registry.diagnostics, manifestRegistry.diagnostics);
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
: {}),
|
|
269
|
+
warnWhenAllowlistIsOpen({
|
|
270
|
+
logger,
|
|
271
|
+
pluginsEnabled: normalized.enabled,
|
|
272
|
+
allow: normalized.allow,
|
|
273
|
+
discoverablePlugins: manifestRegistry.plugins.map((plugin) => ({
|
|
274
|
+
id: plugin.id,
|
|
275
|
+
source: plugin.source,
|
|
276
|
+
origin: plugin.origin,
|
|
277
|
+
})),
|
|
160
278
|
});
|
|
279
|
+
const provenance = buildProvenanceIndex({
|
|
280
|
+
config: cfg,
|
|
281
|
+
normalizedLoadPaths: normalized.loadPaths,
|
|
282
|
+
});
|
|
283
|
+
// Lazy: avoid creating the Jiti loader when all plugins are disabled (common in unit tests).
|
|
284
|
+
let jitiLoader = null;
|
|
285
|
+
const getJiti = () => {
|
|
286
|
+
if (jitiLoader) {
|
|
287
|
+
return jitiLoader;
|
|
288
|
+
}
|
|
289
|
+
const pluginSdkAlias = resolvePluginSdkAlias();
|
|
290
|
+
const pluginSdkAccountIdAlias = resolvePluginSdkAccountIdAlias();
|
|
291
|
+
jitiLoader = createJiti(import.meta.url, {
|
|
292
|
+
interopDefault: true,
|
|
293
|
+
extensions: [".ts", ".tsx", ".mts", ".cts", ".mtsx", ".ctsx", ".js", ".mjs", ".cjs", ".json"],
|
|
294
|
+
...(pluginSdkAlias || pluginSdkAccountIdAlias
|
|
295
|
+
? {
|
|
296
|
+
alias: {
|
|
297
|
+
...(pluginSdkAlias ? { "poolbot/plugin-sdk": pluginSdkAlias } : {}),
|
|
298
|
+
...(pluginSdkAccountIdAlias
|
|
299
|
+
? { "poolbot/plugin-sdk/account-id": pluginSdkAccountIdAlias }
|
|
300
|
+
: {}),
|
|
301
|
+
},
|
|
302
|
+
}
|
|
303
|
+
: {}),
|
|
304
|
+
});
|
|
305
|
+
return jitiLoader;
|
|
306
|
+
};
|
|
161
307
|
const manifestByRoot = new Map(manifestRegistry.plugins.map((record) => [record.rootDir, record]));
|
|
162
308
|
const seenIds = new Map();
|
|
163
309
|
const memorySlot = normalized.slots.memory;
|
|
@@ -223,9 +369,24 @@ export function loadPoolBotPlugins(options = {}) {
|
|
|
223
369
|
});
|
|
224
370
|
continue;
|
|
225
371
|
}
|
|
372
|
+
if (!isPathInsideWithRealpath(candidate.rootDir, candidate.source, {
|
|
373
|
+
requireRealpath: true,
|
|
374
|
+
})) {
|
|
375
|
+
record.status = "error";
|
|
376
|
+
record.error = "plugin entry path escapes plugin root";
|
|
377
|
+
registry.plugins.push(record);
|
|
378
|
+
seenIds.set(pluginId, candidate.origin);
|
|
379
|
+
registry.diagnostics.push({
|
|
380
|
+
level: "error",
|
|
381
|
+
pluginId: record.id,
|
|
382
|
+
source: record.source,
|
|
383
|
+
message: record.error,
|
|
384
|
+
});
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
226
387
|
let mod = null;
|
|
227
388
|
try {
|
|
228
|
-
mod =
|
|
389
|
+
mod = getJiti()(candidate.source);
|
|
229
390
|
}
|
|
230
391
|
catch (err) {
|
|
231
392
|
logger.error(`[plugins] ${record.id} failed to load from ${record.source}: ${String(err)}`);
|
|
@@ -361,6 +522,11 @@ export function loadPoolBotPlugins(options = {}) {
|
|
|
361
522
|
message: `memory slot plugin not found or not marked as memory: ${memorySlot}`,
|
|
362
523
|
});
|
|
363
524
|
}
|
|
525
|
+
warnAboutUntrackedLoadedPlugins({
|
|
526
|
+
registry,
|
|
527
|
+
provenance,
|
|
528
|
+
logger,
|
|
529
|
+
});
|
|
364
530
|
if (cacheEnabled) {
|
|
365
531
|
registryCache.set(cacheKey, registry);
|
|
366
532
|
}
|
|
@@ -5,6 +5,9 @@ import { discoverPoolBotPlugins } from "./discovery.js";
|
|
|
5
5
|
import { loadPluginManifest } from "./manifest.js";
|
|
6
6
|
const registryCache = new Map();
|
|
7
7
|
const DEFAULT_MANIFEST_CACHE_MS = 200;
|
|
8
|
+
export function clearPluginManifestRegistryCache() {
|
|
9
|
+
registryCache.clear();
|
|
10
|
+
}
|
|
8
11
|
function resolveManifestCacheMs(env) {
|
|
9
12
|
const raw = env.POOLBOT_PLUGIN_MANIFEST_CACHE_MS?.trim() || env.CLAWDBOT_PLUGIN_MANIFEST_CACHE_MS?.trim();
|
|
10
13
|
if (raw === "" || raw === "0")
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export function isPathInside(baseDir, targetPath) {
|
|
4
|
+
const rel = path.relative(baseDir, targetPath);
|
|
5
|
+
if (!rel) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
return !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
9
|
+
}
|
|
10
|
+
export function safeRealpathSync(targetPath, cache) {
|
|
11
|
+
const cached = cache?.get(targetPath);
|
|
12
|
+
if (cached) {
|
|
13
|
+
return cached;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const resolved = fs.realpathSync(targetPath);
|
|
17
|
+
cache?.set(targetPath, resolved);
|
|
18
|
+
return resolved;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function safeStatSync(targetPath) {
|
|
25
|
+
try {
|
|
26
|
+
return fs.statSync(targetPath);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function formatPosixMode(mode) {
|
|
33
|
+
return (mode & 0o777).toString(8).padStart(3, "0");
|
|
34
|
+
}
|
package/dist/plugins/registry.js
CHANGED
|
@@ -3,8 +3,8 @@ import { resolveUserPath } from "../utils.js";
|
|
|
3
3
|
import { registerPluginCommand } from "./commands.js";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { normalizePluginHttpPath } from "./http-path.js";
|
|
6
|
-
export function
|
|
7
|
-
|
|
6
|
+
export function createEmptyPluginRegistry() {
|
|
7
|
+
return {
|
|
8
8
|
plugins: [],
|
|
9
9
|
tools: [],
|
|
10
10
|
hooks: [],
|
|
@@ -19,6 +19,9 @@ export function createPluginRegistry(registryParams) {
|
|
|
19
19
|
commands: [],
|
|
20
20
|
diagnostics: [],
|
|
21
21
|
};
|
|
22
|
+
}
|
|
23
|
+
export function createPluginRegistry(registryParams) {
|
|
24
|
+
const registry = createEmptyPluginRegistry();
|
|
22
25
|
const coreGatewayMethods = new Set(Object.keys(registryParams.coreGatewayHandlers ?? {}));
|
|
23
26
|
const pushDiagnostic = (diag) => {
|
|
24
27
|
registry.diagnostics.push(diag);
|