@poolzin/pool-bot 2026.3.25 → 2026.3.26
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/dist/agents/model-fallback.js +5 -4
- package/dist/agents/tools/common.js +16 -201
- package/dist/auto-reply/auto-reply/reply/agent-runner-execution.js +502 -0
- package/dist/auto-reply/auto-reply/reply/agent-runner-helpers.js +65 -0
- package/dist/auto-reply/auto-reply/reply/agent-runner-memory.js +160 -0
- package/dist/auto-reply/auto-reply/reply/agent-runner-payloads.js +85 -0
- package/dist/auto-reply/auto-reply/reply/agent-runner-utils.js +101 -0
- package/dist/auto-reply/auto-reply/reply/bash-command.js +338 -0
- package/dist/auto-reply/auto-reply/reply/block-streaming.js +91 -0
- package/dist/auto-reply/auto-reply/reply/commands-approve.js +88 -0
- package/dist/auto-reply/auto-reply/reply/commands-bash.js +26 -0
- package/dist/auto-reply/auto-reply/reply/commands-compact.js +107 -0
- package/dist/auto-reply/auto-reply/reply/commands-config.js +241 -0
- package/dist/auto-reply/auto-reply/reply/commands-context-report.js +295 -0
- package/dist/auto-reply/auto-reply/reply/commands-context.js +30 -0
- package/dist/auto-reply/auto-reply/reply/commands-core.js +151 -0
- package/dist/auto-reply/auto-reply/reply/commands-export-session.js +163 -0
- package/dist/auto-reply/auto-reply/reply/commands-info.js +184 -0
- package/dist/auto-reply/auto-reply/reply/commands-models.js +299 -0
- package/dist/auto-reply/auto-reply/reply/commands-plugin.js +35 -0
- package/dist/auto-reply/auto-reply/reply/commands-ptt.js +171 -0
- package/dist/auto-reply/auto-reply/reply/commands-setunset-standard.js +13 -0
- package/dist/auto-reply/auto-reply/reply/commands-setunset.js +73 -0
- package/dist/auto-reply/auto-reply/reply/commands-slash-parse.js +31 -0
- package/dist/auto-reply/auto-reply/reply/commands-status.js +178 -0
- package/dist/auto-reply/auto-reply/reply/commands-subagents.js +73 -0
- package/dist/auto-reply/auto-reply/reply/commands-system-prompt.js +117 -0
- package/dist/auto-reply/auto-reply/reply/commands-tts.js +231 -0
- package/dist/auto-reply/auto-reply/reply/directive-handling.impl.js +380 -0
- package/dist/auto-reply/auto-reply/reply/followup-runner.js +227 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-directives-apply.js +201 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-directives-utils.js +54 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-directives.js +332 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-inline-actions.js +258 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-run.js +297 -0
- package/dist/auto-reply/auto-reply/reply/groups.js +102 -0
- package/dist/auto-reply/auto-reply/reply/mentions.js +129 -0
- package/dist/auto-reply/auto-reply/reply/reply-delivery.js +92 -0
- package/dist/auto-reply/auto-reply/reply/reply-directives.js +30 -0
- package/dist/auto-reply/auto-reply/reply/reply-dispatcher.js +152 -0
- package/dist/auto-reply/auto-reply/reply/reply-elevated.js +166 -0
- package/dist/auto-reply/auto-reply/reply/reply-inline.js +28 -0
- package/dist/auto-reply/auto-reply/reply/reply-payloads.js +114 -0
- package/dist/auto-reply/auto-reply/reply/reply-reference.js +36 -0
- package/dist/auto-reply/auto-reply/reply/reply-tags.js +13 -0
- package/dist/auto-reply/auto-reply/reply/reply-threading.js +41 -0
- package/dist/auto-reply/auto-reply/reply/session-updates.js +233 -0
- package/dist/auto-reply/auto-reply/reply/stage-sandbox-media.js +146 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/canvas-host/a2ui/a2ui.bundle.js +2 -17772
- package/dist/canvas-host/a2ui/index.html +1 -307
- package/dist/channels/channels/directory-config.js +185 -0
- package/dist/channels/channels/discord/handle-action.guild-admin.js +332 -0
- package/dist/channels/channels/discord/handle-action.js +165 -0
- package/dist/channels/channels/discord.js +413 -0
- package/dist/channels/channels/dock.js +436 -0
- package/dist/channels/channels/index.js +51 -0
- package/dist/channels/channels/plugins/outbound/discord.js +101 -0
- package/dist/channels/channels/whatsapp.js +17 -0
- package/dist/channels/plugins/types.js +1 -1
- package/dist/channels/run-state-machine.js +7 -0
- package/dist/commands/models/auth.js +47 -1
- package/dist/commands-subagents/action-agents.js +44 -0
- package/dist/commands-subagents/action-focus.js +64 -0
- package/dist/commands-subagents/action-help.js +4 -0
- package/dist/commands-subagents/action-info.js +45 -0
- package/dist/commands-subagents/action-kill.js +60 -0
- package/dist/commands-subagents/action-list.js +44 -0
- package/dist/commands-subagents/action-log.js +29 -0
- package/dist/commands-subagents/action-send.js +119 -0
- package/dist/commands-subagents/action-spawn.js +52 -0
- package/dist/commands-subagents/action-unfocus.js +30 -0
- package/dist/commands-subagents/shared.js +303 -0
- package/dist/config/config.js +1 -8
- package/dist/config/types.secrets.js +61 -0
- package/dist/control-ui/assets/{index-D7shnQwQ.js → index-umCsvrWy.js} +884 -741
- package/dist/control-ui/assets/index-umCsvrWy.js.map +1 -0
- package/dist/control-ui/assets/pt-BR-DedEVAvY.js +2 -0
- package/dist/control-ui/assets/pt-BR-DedEVAvY.js.map +1 -0
- package/dist/control-ui/assets/zh-CN-CDzeklK-.js +2 -0
- package/dist/control-ui/assets/zh-CN-CDzeklK-.js.map +1 -0
- package/dist/control-ui/assets/zh-TW-BJCRYNWH.js +2 -0
- package/dist/control-ui/assets/zh-TW-BJCRYNWH.js.map +1 -0
- package/dist/control-ui/index.html +1 -1
- package/dist/gateway/method-scopes.js +9 -1
- package/dist/gateway/node-pending-work.js +142 -0
- package/dist/gateway/protocol/index.js +5 -1
- package/dist/gateway/protocol/schema/nodes.js +18 -0
- package/dist/gateway/server-methods/nodes-pending.js +96 -0
- package/dist/gateway/server-methods-list.js +4 -0
- package/dist/gateway/server-methods.js +2 -0
- package/dist/imessage/channel.js +253 -0
- package/dist/imessage/monitor/echo-cache.js +70 -0
- package/dist/imessage/monitor/loop-rate-limiter.js +51 -0
- package/dist/imessage/monitor/reflection-guard.js +50 -0
- package/dist/imessage/monitor/sanitize-outbound.js +25 -0
- package/dist/imessage/monitor/self-chat-cache.js +75 -0
- package/dist/imessage/runtime.js +3 -0
- package/dist/infra/exec-approval-reply.js +7 -0
- package/dist/infra/tmp-openclaw-dir.js +84 -0
- package/dist/pairing/pairing-challenge.js +15 -0
- package/dist/plugin-sdk/account-id.d.ts +1 -0
- package/dist/plugin-sdk/agent-media-payload.d.ts +12 -0
- package/dist/plugin-sdk/allow-from.d.ts +27 -0
- package/dist/plugin-sdk/command-auth.d.ts +25 -0
- package/dist/plugin-sdk/command-auth.js +3 -1
- package/dist/plugin-sdk/config-paths.d.ts +6 -0
- package/dist/plugin-sdk/file-lock.d.ts +16 -0
- package/dist/plugin-sdk/index.d.ts +428 -0
- package/dist/plugin-sdk/index.js +237 -103
- package/dist/plugin-sdk/json-store.d.ts +5 -0
- package/dist/plugin-sdk/keyed-async-queue.d.ts +12 -0
- package/dist/plugin-sdk/onboarding.d.ts +11 -0
- package/dist/plugin-sdk/provider-auth-result.d.ts +14 -0
- package/dist/plugin-sdk/slack-message-actions.d.ts +11 -0
- package/dist/plugin-sdk/status-helpers.d.ts +25 -0
- package/dist/plugin-sdk/temp-path.d.ts +12 -0
- package/dist/plugin-sdk/text-chunking.d.ts +1 -0
- package/dist/plugin-sdk/tool-send.d.ts +4 -0
- package/dist/plugin-sdk/webhook-path.d.ts +6 -0
- package/dist/plugin-sdk/webhook-targets.d.ts +23 -0
- package/dist/plugin-sdk/windows-spawn.d.ts +39 -0
- package/dist/plugin-sdk-internal/accounts.js +6 -0
- package/dist/plugin-sdk-internal/discord.js +23 -0
- package/dist/plugin-sdk-internal/imessage.js +13 -0
- package/dist/plugin-sdk-internal/setup.js +9 -0
- package/dist/plugin-sdk-internal/signal.js +13 -0
- package/dist/plugin-sdk-internal/slack.js +22 -0
- package/dist/plugin-sdk-internal/telegram.js +32 -0
- package/dist/plugin-sdk-internal/whatsapp.js +29 -0
- package/dist/routing/session-key.js +4 -185
- package/dist/shared/pid-alive.js +2 -61
- package/dist/shared/process-scoped-map.js +5 -7
- package/dist/signal/channel.js +264 -0
- package/dist/signal/monitor/access-policy.js +60 -0
- package/dist/signal/runtime.js +3 -0
- package/dist/slack/account-inspect.js +135 -0
- package/dist/slack/blocks-input.js +7 -38
- package/dist/slack/channel.js +394 -0
- package/dist/slack/interactive-replies.js +28 -0
- package/dist/slack/monitor/channel-type.js +31 -0
- package/dist/slack/monitor/dm-auth.js +49 -0
- package/dist/slack/monitor/events/interactions.modal.js +137 -0
- package/dist/slack/monitor/events/message-subtype-handlers.js +68 -0
- package/dist/slack/monitor/events/system-event-context.js +29 -0
- package/dist/slack/monitor/events/system-event-test-harness.js +41 -0
- package/dist/slack/monitor/external-arg-menu-store.js +46 -0
- package/dist/slack/monitor/message-handler/prepare-content.js +69 -0
- package/dist/slack/monitor/message-handler/prepare-thread-context.js +91 -0
- package/dist/slack/monitor/message-handler/prepare.test-helpers.js +55 -0
- package/dist/slack/monitor/reconnect-policy.js +78 -0
- package/dist/slack/monitor/slash-commands.runtime.js +1 -0
- package/dist/slack/monitor/slash-dispatch.runtime.js +9 -0
- package/dist/slack/monitor/slash-skill-commands.runtime.js +1 -0
- package/dist/slack/resolve-allowlist-common.js +36 -0
- package/dist/slack/runtime.js +3 -0
- package/dist/slack/sent-thread-cache.js +61 -0
- package/dist/slack/truncate.js +10 -0
- package/dist/telegram/account-inspect.js +175 -0
- package/dist/telegram/allow-from.js +10 -0
- package/dist/telegram/api-fetch.js +18 -0
- package/dist/telegram/approval-buttons.js +30 -0
- package/dist/telegram/audit-membership-runtime.js +61 -0
- package/dist/telegram/bot/delivery.replies.js +508 -0
- package/dist/telegram/bot/delivery.resolve-media.js +227 -0
- package/dist/telegram/bot/delivery.send.js +132 -0
- package/dist/telegram/bot/reply-threading.js +46 -0
- package/dist/telegram/bot-message-context.body.js +186 -0
- package/dist/telegram/bot-message-context.session.js +207 -0
- package/dist/telegram/bot-message-context.types.js +1 -0
- package/dist/telegram/bot-native-commands.test-helpers.js +117 -0
- package/dist/telegram/bot.media.e2e-harness.js +81 -0
- package/dist/telegram/bot.media.test-utils.js +81 -0
- package/dist/telegram/channel-actions.js +225 -0
- package/dist/telegram/channel.js +515 -0
- package/dist/telegram/conversation-route.js +107 -0
- package/dist/telegram/delivery.js +2 -0
- package/dist/telegram/delivery.replies.js +508 -0
- package/dist/telegram/dm-access.js +86 -0
- package/dist/telegram/draft-stream.test-helpers.js +62 -0
- package/dist/telegram/exec-approvals-handler.js +281 -0
- package/dist/telegram/exec-approvals.js +62 -0
- package/dist/telegram/forum-service-message.js +22 -0
- package/dist/telegram/group-config-helpers.js +10 -0
- package/dist/telegram/lane-delivery-state.js +19 -0
- package/dist/telegram/lane-delivery-text-deliverer.js +357 -0
- package/dist/telegram/lane-delivery.js +2 -0
- package/dist/telegram/normalize.js +37 -0
- package/dist/telegram/onboarding.js +192 -0
- package/dist/telegram/outbound-adapter.js +100 -0
- package/dist/telegram/polling-session.js +275 -0
- package/dist/telegram/runtime.js +3 -0
- package/dist/telegram/sendchataction-401-backoff.js +71 -0
- package/dist/telegram/sequential-key.js +46 -0
- package/dist/telegram/status-issues.js +105 -0
- package/dist/telegram/target-writeback.js +165 -0
- package/dist/telegram/thread-bindings.js +560 -0
- package/dist/utils.js +10 -276
- package/dist/wizard/prompts.js +5 -5
- package/extensions/feishu/src/policy.ts +1 -1
- package/extensions/firecrawl/index.test.ts +82 -0
- package/extensions/firecrawl/index.ts +20 -0
- package/extensions/firecrawl/openclaw.plugin.json +8 -0
- package/extensions/firecrawl/package.json +12 -0
- package/extensions/firecrawl/src/config.ts +159 -0
- package/extensions/firecrawl/src/firecrawl-client.ts +446 -0
- package/extensions/firecrawl/src/firecrawl-scrape-tool.ts +89 -0
- package/extensions/firecrawl/src/firecrawl-search-provider.ts +63 -0
- package/extensions/firecrawl/src/firecrawl-search-tool.ts +76 -0
- package/package.json +1 -1
- package/dist/.buildstamp +0 -1
- package/dist/acp/bindings-store.js +0 -209
- package/dist/acp/control-plane/runtime-cache.js +0 -54
- package/dist/acp/control-plane/runtime-options.js +0 -215
- package/dist/acp/control-plane/session-actor-queue.js +0 -36
- package/dist/acp/index.js +0 -2
- package/dist/acp/runtime/errors.js +0 -47
- package/dist/acp/runtime/registry.js +0 -86
- package/dist/acp/secret-file.js +0 -22
- package/dist/agents/auth-profiles.resolve-auth-profile-order.fixtures.js +0 -23
- package/dist/agents/bash-process-registry.test-helpers.js +0 -29
- package/dist/agents/bash-tools.exec-approval-request.js +0 -20
- package/dist/agents/bash-tools.exec-host-gateway.js +0 -240
- package/dist/agents/bash-tools.exec-host-node.js +0 -235
- package/dist/agents/checkpoint-manager.js +0 -290
- package/dist/agents/claude-cli-runner.js +0 -3
- package/dist/agents/error-classifier.js +0 -251
- package/dist/agents/live-model-filter.js +0 -84
- package/dist/agents/nvidia-models.js +0 -228
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +0 -34
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +0 -156
- package/dist/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.js +0 -30
- package/dist/agents/provider/config-loader.js +0 -76
- package/dist/agents/provider/index.js +0 -15
- package/dist/agents/provider/models-dev.js +0 -129
- package/dist/agents/provider/session-binding.js +0 -376
- package/dist/agents/queued-file-writer.js +0 -22
- package/dist/agents/skills/bundled-context.js +0 -23
- package/dist/agents/skills/security.js +0 -211
- package/dist/agents/skills/tools-dir.js +0 -9
- package/dist/agents/skills-install-download.js +0 -290
- package/dist/agents/skills-install-output.js +0 -30
- package/dist/agents/skills-install.download-test-utils.js +0 -36
- package/dist/agents/skills.test-helpers.js +0 -13
- package/dist/agents/subagent-announce-reliability.js +0 -160
- package/dist/agents/subagent-registry.mocks.shared.js +0 -12
- package/dist/agents/test-helpers/assistant-message-fixtures.js +0 -29
- package/dist/agents/test-helpers/fast-coding-tools.js +0 -1
- package/dist/agents/test-helpers/fast-core-tools.js +0 -8
- package/dist/agents/test-helpers/fast-tool-stubs.js +0 -18
- package/dist/agents/test-helpers/host-sandbox-fs-bridge.js +0 -74
- package/dist/agents/test-helpers/pi-tools-sandbox-context.js +0 -27
- package/dist/agents/tool-display-common.js +0 -915
- package/dist/agents/tool-policy-shared.js +0 -108
- package/dist/agents/tool-policy.conformance.js +0 -14
- package/dist/agents/tool-result-truncation.js +0 -299
- package/dist/agents/tools/cron-tool.test-helpers.js +0 -12
- package/dist/agents/tools/discord-actions-moderation-shared.js +0 -27
- package/dist/agents/tools/discord-actions-presence.js +0 -78
- package/dist/control-ui/assets/index-D7shnQwQ.js.map +0 -1
- package/dist/discord/discord-improvements.js +0 -167
- package/dist/discord/index.js +0 -2
- package/dist/hooks/bundled/boot-md/HOOK.md +0 -19
- package/dist/hooks/bundled/command-logger/HOOK.md +0 -122
- package/dist/hooks/bundled/session-memory/HOOK.md +0 -86
- package/dist/hooks/bundled/soul-evil/HOOK.md +0 -71
- package/dist/whatsapp/normalize.js +0 -66
- package/dist/whatsapp/resolve-outbound-target.js +0 -42
- /package/dist/{acp/runtime/types.js → auto-reply/auto-reply/reply/commands-types.js} +0 -0
- /package/dist/{agents/pi-embedded-payloads.js → slack/account-surface-fields.js} +0 -0
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session Manager
|
|
3
|
-
*
|
|
4
|
-
* Manages sticky session bindings between conversation sessions and API tokens.
|
|
5
|
-
* Ensures conversation continuity by routing requests to the same key when possible.
|
|
6
|
-
*
|
|
7
|
-
* @module provider/session-binding
|
|
8
|
-
*/
|
|
9
|
-
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
|
10
|
-
export var SessionManager;
|
|
11
|
-
(function (SessionManager) {
|
|
12
|
-
const log = createSubsystemLogger("provider/session-binding");
|
|
13
|
-
// ============================================================================
|
|
14
|
-
// Internal State
|
|
15
|
-
// ============================================================================
|
|
16
|
-
/** Session bindings: sessionID:providerID -> Binding */
|
|
17
|
-
const bindings = new Map();
|
|
18
|
-
/** Configuration */
|
|
19
|
-
let config = {
|
|
20
|
-
defaultTTLMs: 60_000, // 60 seconds
|
|
21
|
-
maxBindings: 10_000,
|
|
22
|
-
extendOnAccess: true,
|
|
23
|
-
};
|
|
24
|
-
/** Cleanup interval handle */
|
|
25
|
-
let cleanupInterval = null;
|
|
26
|
-
// ============================================================================
|
|
27
|
-
// Helper Functions
|
|
28
|
-
// ============================================================================
|
|
29
|
-
/**
|
|
30
|
-
* Creates a composite key for the bindings map.
|
|
31
|
-
*/
|
|
32
|
-
function getBindingKey(sessionID, providerID) {
|
|
33
|
-
return `${sessionID}:${providerID}`;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Checks if a binding is expired.
|
|
37
|
-
*/
|
|
38
|
-
function isExpired(binding) {
|
|
39
|
-
return Date.now() > binding.expiresAt;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Evicts oldest bindings if over capacity.
|
|
43
|
-
*/
|
|
44
|
-
function evictIfNeeded() {
|
|
45
|
-
if (bindings.size <= config.maxBindings)
|
|
46
|
-
return;
|
|
47
|
-
// Sort by last accessed time and remove oldest
|
|
48
|
-
const sorted = Array.from(bindings.entries()).sort((a, b) => a[1].lastAccessedAt - b[1].lastAccessedAt);
|
|
49
|
-
const toRemove = sorted.slice(0, bindings.size - config.maxBindings);
|
|
50
|
-
for (const [key] of toRemove) {
|
|
51
|
-
bindings.delete(key);
|
|
52
|
-
}
|
|
53
|
-
log.info("evicted", { count: toRemove.length });
|
|
54
|
-
}
|
|
55
|
-
// ============================================================================
|
|
56
|
-
// Public API
|
|
57
|
-
// ============================================================================
|
|
58
|
-
/**
|
|
59
|
-
* Configures the session manager.
|
|
60
|
-
*
|
|
61
|
-
* @param newConfig - Partial configuration to merge
|
|
62
|
-
*
|
|
63
|
-
* @example
|
|
64
|
-
* ```typescript
|
|
65
|
-
* SessionManager.configure({
|
|
66
|
-
* defaultTTLMs: 120_000, // 2 minutes
|
|
67
|
-
* extendOnAccess: true
|
|
68
|
-
* })
|
|
69
|
-
* ```
|
|
70
|
-
*/
|
|
71
|
-
function configure(newConfig) {
|
|
72
|
-
config = { ...config, ...newConfig };
|
|
73
|
-
log.info("configured", { ...config });
|
|
74
|
-
}
|
|
75
|
-
SessionManager.configure = configure;
|
|
76
|
-
/**
|
|
77
|
-
* Gets the current configuration.
|
|
78
|
-
*/
|
|
79
|
-
function getConfig() {
|
|
80
|
-
return { ...config };
|
|
81
|
-
}
|
|
82
|
-
SessionManager.getConfig = getConfig;
|
|
83
|
-
/**
|
|
84
|
-
* Creates or updates a session binding.
|
|
85
|
-
*
|
|
86
|
-
* @param sessionID - Session identifier
|
|
87
|
-
* @param providerID - Provider identifier
|
|
88
|
-
* @param tokenID - Token identifier to bind to
|
|
89
|
-
* @param ttlMs - Custom TTL (uses default if not specified)
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* ```typescript
|
|
93
|
-
* SessionManager.bind("session-123", "anthropic", "key-1")
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
function bind(sessionID, providerID, tokenID, ttlMs) {
|
|
97
|
-
const key = getBindingKey(sessionID, providerID);
|
|
98
|
-
const now = Date.now();
|
|
99
|
-
const ttl = ttlMs ?? config.defaultTTLMs;
|
|
100
|
-
const existing = bindings.get(key);
|
|
101
|
-
if (existing && existing.tokenID === tokenID) {
|
|
102
|
-
// Update existing binding
|
|
103
|
-
existing.lastAccessedAt = now;
|
|
104
|
-
existing.expiresAt = now + ttl;
|
|
105
|
-
existing.requestCount++;
|
|
106
|
-
return existing;
|
|
107
|
-
}
|
|
108
|
-
// Create new binding
|
|
109
|
-
const binding = {
|
|
110
|
-
sessionID,
|
|
111
|
-
providerID,
|
|
112
|
-
tokenID,
|
|
113
|
-
createdAt: now,
|
|
114
|
-
lastAccessedAt: now,
|
|
115
|
-
expiresAt: now + ttl,
|
|
116
|
-
requestCount: 1,
|
|
117
|
-
};
|
|
118
|
-
bindings.set(key, binding);
|
|
119
|
-
evictIfNeeded();
|
|
120
|
-
log.info("bound", { sessionID, providerID, tokenID, ttlMs: ttl });
|
|
121
|
-
return binding;
|
|
122
|
-
}
|
|
123
|
-
SessionManager.bind = bind;
|
|
124
|
-
/**
|
|
125
|
-
* Looks up a session binding.
|
|
126
|
-
*
|
|
127
|
-
* @param sessionID - Session identifier
|
|
128
|
-
* @param providerID - Provider identifier
|
|
129
|
-
* @returns Lookup result with binding if found and valid
|
|
130
|
-
*
|
|
131
|
-
* @example
|
|
132
|
-
* ```typescript
|
|
133
|
-
* const result = SessionManager.lookup("session-123", "anthropic")
|
|
134
|
-
* if (result.found && !result.expired) {
|
|
135
|
-
* console.log("Using token:", result.binding.tokenID)
|
|
136
|
-
* }
|
|
137
|
-
* ```
|
|
138
|
-
*/
|
|
139
|
-
function lookup(sessionID, providerID) {
|
|
140
|
-
const key = getBindingKey(sessionID, providerID);
|
|
141
|
-
const binding = bindings.get(key);
|
|
142
|
-
if (!binding) {
|
|
143
|
-
return { found: false, expired: false };
|
|
144
|
-
}
|
|
145
|
-
if (isExpired(binding)) {
|
|
146
|
-
bindings.delete(key);
|
|
147
|
-
return { found: true, expired: true };
|
|
148
|
-
}
|
|
149
|
-
// Extend TTL on access if configured
|
|
150
|
-
if (config.extendOnAccess) {
|
|
151
|
-
binding.lastAccessedAt = Date.now();
|
|
152
|
-
binding.expiresAt = binding.lastAccessedAt + config.defaultTTLMs;
|
|
153
|
-
}
|
|
154
|
-
return { binding, found: true, expired: false };
|
|
155
|
-
}
|
|
156
|
-
SessionManager.lookup = lookup;
|
|
157
|
-
/**
|
|
158
|
-
* Gets the bound token ID for a session, if any.
|
|
159
|
-
*
|
|
160
|
-
* @param sessionID - Session identifier
|
|
161
|
-
* @param providerID - Provider identifier
|
|
162
|
-
* @returns Token ID or undefined if not bound
|
|
163
|
-
*/
|
|
164
|
-
function getBoundToken(sessionID, providerID) {
|
|
165
|
-
const result = lookup(sessionID, providerID);
|
|
166
|
-
return result.binding?.tokenID;
|
|
167
|
-
}
|
|
168
|
-
SessionManager.getBoundToken = getBoundToken;
|
|
169
|
-
/**
|
|
170
|
-
* Removes a session binding.
|
|
171
|
-
*
|
|
172
|
-
* @param sessionID - Session identifier
|
|
173
|
-
* @param providerID - Provider identifier
|
|
174
|
-
* @returns Whether a binding was found and removed
|
|
175
|
-
*/
|
|
176
|
-
function unbind(sessionID, providerID) {
|
|
177
|
-
const key = getBindingKey(sessionID, providerID);
|
|
178
|
-
const removed = bindings.delete(key);
|
|
179
|
-
if (removed) {
|
|
180
|
-
log.info("unbound", { sessionID, providerID });
|
|
181
|
-
}
|
|
182
|
-
return removed;
|
|
183
|
-
}
|
|
184
|
-
SessionManager.unbind = unbind;
|
|
185
|
-
/**
|
|
186
|
-
* Removes all bindings for a session.
|
|
187
|
-
*
|
|
188
|
-
* @param sessionID - Session identifier
|
|
189
|
-
* @returns Number of bindings removed
|
|
190
|
-
*/
|
|
191
|
-
function unbindSession(sessionID) {
|
|
192
|
-
let count = 0;
|
|
193
|
-
const prefix = `${sessionID}:`;
|
|
194
|
-
for (const key of bindings.keys()) {
|
|
195
|
-
if (key.startsWith(prefix)) {
|
|
196
|
-
bindings.delete(key);
|
|
197
|
-
count++;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
if (count > 0) {
|
|
201
|
-
log.info("session-unbound", { sessionID, count });
|
|
202
|
-
}
|
|
203
|
-
return count;
|
|
204
|
-
}
|
|
205
|
-
SessionManager.unbindSession = unbindSession;
|
|
206
|
-
/**
|
|
207
|
-
* Removes all bindings for a provider.
|
|
208
|
-
*
|
|
209
|
-
* @param providerID - Provider identifier
|
|
210
|
-
* @returns Number of bindings removed
|
|
211
|
-
*/
|
|
212
|
-
function unbindProvider(providerID) {
|
|
213
|
-
let count = 0;
|
|
214
|
-
const suffix = `:${providerID}`;
|
|
215
|
-
for (const key of bindings.keys()) {
|
|
216
|
-
if (key.endsWith(suffix)) {
|
|
217
|
-
bindings.delete(key);
|
|
218
|
-
count++;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
if (count > 0) {
|
|
222
|
-
log.info("provider-unbound", { providerID, count });
|
|
223
|
-
}
|
|
224
|
-
return count;
|
|
225
|
-
}
|
|
226
|
-
SessionManager.unbindProvider = unbindProvider;
|
|
227
|
-
/**
|
|
228
|
-
* Removes all bindings for a specific token.
|
|
229
|
-
*
|
|
230
|
-
* @param providerID - Provider identifier
|
|
231
|
-
* @param tokenID - Token identifier
|
|
232
|
-
* @returns Number of bindings removed
|
|
233
|
-
*/
|
|
234
|
-
function unbindToken(providerID, tokenID) {
|
|
235
|
-
let count = 0;
|
|
236
|
-
for (const [key, binding] of bindings.entries()) {
|
|
237
|
-
if (binding.providerID === providerID && binding.tokenID === tokenID) {
|
|
238
|
-
bindings.delete(key);
|
|
239
|
-
count++;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
if (count > 0) {
|
|
243
|
-
log.info("token-unbound", { providerID, tokenID, count });
|
|
244
|
-
}
|
|
245
|
-
return count;
|
|
246
|
-
}
|
|
247
|
-
SessionManager.unbindToken = unbindToken;
|
|
248
|
-
/**
|
|
249
|
-
* Gets all bindings for a session.
|
|
250
|
-
*
|
|
251
|
-
* @param sessionID - Session identifier
|
|
252
|
-
* @returns Array of bindings
|
|
253
|
-
*/
|
|
254
|
-
function getSessionBindings(sessionID) {
|
|
255
|
-
const result = [];
|
|
256
|
-
const now = Date.now();
|
|
257
|
-
const prefix = `${sessionID}:`;
|
|
258
|
-
for (const [key, binding] of bindings.entries()) {
|
|
259
|
-
if (key.startsWith(prefix) && binding.expiresAt > now) {
|
|
260
|
-
result.push({ ...binding });
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return result;
|
|
264
|
-
}
|
|
265
|
-
SessionManager.getSessionBindings = getSessionBindings;
|
|
266
|
-
/**
|
|
267
|
-
* Gets all bindings for a provider.
|
|
268
|
-
*
|
|
269
|
-
* @param providerID - Provider identifier
|
|
270
|
-
* @returns Array of bindings
|
|
271
|
-
*/
|
|
272
|
-
function getProviderBindings(providerID) {
|
|
273
|
-
const result = [];
|
|
274
|
-
const now = Date.now();
|
|
275
|
-
for (const binding of bindings.values()) {
|
|
276
|
-
if (binding.providerID === providerID && binding.expiresAt > now) {
|
|
277
|
-
result.push({ ...binding });
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return result;
|
|
281
|
-
}
|
|
282
|
-
SessionManager.getProviderBindings = getProviderBindings;
|
|
283
|
-
/**
|
|
284
|
-
* Gets summary statistics for session bindings.
|
|
285
|
-
*/
|
|
286
|
-
function getSummary() {
|
|
287
|
-
const now = Date.now();
|
|
288
|
-
let activeCount = 0;
|
|
289
|
-
let expiredCount = 0;
|
|
290
|
-
let totalRequests = 0;
|
|
291
|
-
let totalAge = 0;
|
|
292
|
-
const byProvider = {};
|
|
293
|
-
for (const binding of bindings.values()) {
|
|
294
|
-
if (binding.expiresAt > now) {
|
|
295
|
-
activeCount++;
|
|
296
|
-
totalRequests += binding.requestCount;
|
|
297
|
-
totalAge += now - binding.createdAt;
|
|
298
|
-
byProvider[binding.providerID] = (byProvider[binding.providerID] ?? 0) + 1;
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
expiredCount++;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
return {
|
|
305
|
-
totalBindings: bindings.size,
|
|
306
|
-
activeBindings: activeCount,
|
|
307
|
-
expiredBindings: expiredCount,
|
|
308
|
-
byProvider,
|
|
309
|
-
avgRequestsPerBinding: activeCount > 0 ? totalRequests / activeCount : 0,
|
|
310
|
-
avgAgeMs: activeCount > 0 ? totalAge / activeCount : 0,
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
SessionManager.getSummary = getSummary;
|
|
314
|
-
/**
|
|
315
|
-
* Removes expired bindings.
|
|
316
|
-
*
|
|
317
|
-
* @returns Number of bindings removed
|
|
318
|
-
*/
|
|
319
|
-
function cleanupExpired() {
|
|
320
|
-
const now = Date.now();
|
|
321
|
-
let removed = 0;
|
|
322
|
-
for (const [key, binding] of bindings.entries()) {
|
|
323
|
-
if (binding.expiresAt <= now) {
|
|
324
|
-
bindings.delete(key);
|
|
325
|
-
removed++;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
if (removed > 0) {
|
|
329
|
-
log.info("cleanup", { removed });
|
|
330
|
-
}
|
|
331
|
-
return removed;
|
|
332
|
-
}
|
|
333
|
-
SessionManager.cleanupExpired = cleanupExpired;
|
|
334
|
-
/**
|
|
335
|
-
* Clears all bindings.
|
|
336
|
-
*/
|
|
337
|
-
function clear() {
|
|
338
|
-
const count = bindings.size;
|
|
339
|
-
bindings.clear();
|
|
340
|
-
if (count > 0) {
|
|
341
|
-
log.info("cleared", { count });
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
SessionManager.clear = clear;
|
|
345
|
-
/**
|
|
346
|
-
* Starts the automatic cleanup interval.
|
|
347
|
-
*
|
|
348
|
-
* @param intervalMs - Cleanup interval in milliseconds (default: 30000)
|
|
349
|
-
*/
|
|
350
|
-
function startCleanup(intervalMs = 30_000) {
|
|
351
|
-
if (cleanupInterval)
|
|
352
|
-
return;
|
|
353
|
-
cleanupInterval = setInterval(() => {
|
|
354
|
-
cleanupExpired();
|
|
355
|
-
}, intervalMs);
|
|
356
|
-
// Don't keep the process alive just for cleanup
|
|
357
|
-
if (typeof cleanupInterval.unref === "function") {
|
|
358
|
-
cleanupInterval.unref();
|
|
359
|
-
}
|
|
360
|
-
log.debug("cleanup-started", { intervalMs });
|
|
361
|
-
}
|
|
362
|
-
SessionManager.startCleanup = startCleanup;
|
|
363
|
-
/**
|
|
364
|
-
* Stops the automatic cleanup interval.
|
|
365
|
-
*/
|
|
366
|
-
function stopCleanup() {
|
|
367
|
-
if (cleanupInterval) {
|
|
368
|
-
clearInterval(cleanupInterval);
|
|
369
|
-
cleanupInterval = null;
|
|
370
|
-
log.info("cleanup-stopped");
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
SessionManager.stopCleanup = stopCleanup;
|
|
374
|
-
// Start cleanup on module load
|
|
375
|
-
startCleanup();
|
|
376
|
-
})(SessionManager || (SessionManager = {}));
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
export function getQueuedFileWriter(writers, filePath) {
|
|
4
|
-
const existing = writers.get(filePath);
|
|
5
|
-
if (existing) {
|
|
6
|
-
return existing;
|
|
7
|
-
}
|
|
8
|
-
const dir = path.dirname(filePath);
|
|
9
|
-
const ready = fs.mkdir(dir, { recursive: true }).catch(() => undefined);
|
|
10
|
-
let queue = Promise.resolve();
|
|
11
|
-
const writer = {
|
|
12
|
-
filePath,
|
|
13
|
-
write: (line) => {
|
|
14
|
-
queue = queue
|
|
15
|
-
.then(() => ready)
|
|
16
|
-
.then(() => fs.appendFile(filePath, line, "utf8"))
|
|
17
|
-
.catch(() => undefined);
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
writers.set(filePath, writer);
|
|
21
|
-
return writer;
|
|
22
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { loadSkillsFromDir } from "@mariozechner/pi-coding-agent";
|
|
2
|
-
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
|
3
|
-
import { resolveBundledSkillsDir } from "./bundled-dir.js";
|
|
4
|
-
const skillsLogger = createSubsystemLogger("skills");
|
|
5
|
-
let hasWarnedMissingBundledDir = false;
|
|
6
|
-
export function resolveBundledSkillsContext(opts = {}) {
|
|
7
|
-
const dir = resolveBundledSkillsDir(opts);
|
|
8
|
-
const names = new Set();
|
|
9
|
-
if (!dir) {
|
|
10
|
-
if (!hasWarnedMissingBundledDir) {
|
|
11
|
-
hasWarnedMissingBundledDir = true;
|
|
12
|
-
skillsLogger.warn("Bundled skills directory could not be resolved; built-in skills may be missing.");
|
|
13
|
-
}
|
|
14
|
-
return { dir, names };
|
|
15
|
-
}
|
|
16
|
-
const result = loadSkillsFromDir({ dir, source: "poolbot-bundled" });
|
|
17
|
-
for (const skill of result.skills) {
|
|
18
|
-
if (skill.name.trim()) {
|
|
19
|
-
names.add(skill.name);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return { dir, names };
|
|
23
|
-
}
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill Security Scanner
|
|
3
|
-
*
|
|
4
|
-
* Security scanning for PoolBot skills.
|
|
5
|
-
* Detects potential security issues in skill files.
|
|
6
|
-
*
|
|
7
|
-
* @module agents/skills/security
|
|
8
|
-
*/
|
|
9
|
-
// ============================================================================
|
|
10
|
-
// Constants
|
|
11
|
-
// ============================================================================
|
|
12
|
-
const SCANNER_VERSION = "1.0.0";
|
|
13
|
-
// Patterns that indicate potential security issues
|
|
14
|
-
const PATTERNS = [
|
|
15
|
-
// Prompt injection attempts
|
|
16
|
-
{
|
|
17
|
-
type: "prompt_injection",
|
|
18
|
-
severity: "critical",
|
|
19
|
-
pattern: /ignore\s+(?:previous|above|prior)|disregard\s+(?:instructions?|prompt)|system\s*:\s*you\s+are|new\s+instructions?\s*:/i,
|
|
20
|
-
description: "Potential prompt injection attempt detected",
|
|
21
|
-
remediation: "Review skill content for malicious instruction overrides",
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
type: "prompt_injection",
|
|
25
|
-
severity: "high",
|
|
26
|
-
pattern: /\[\s*system\s*\]|\(\s*system\s*\)|\{\s*system\s*\}|\bDAN\b|do\s+anything\s+now/i,
|
|
27
|
-
description: "Suspicious system role reference",
|
|
28
|
-
remediation: "Verify skill doesn't attempt to override system behavior",
|
|
29
|
-
},
|
|
30
|
-
// Command injection
|
|
31
|
-
{
|
|
32
|
-
type: "command_injection",
|
|
33
|
-
severity: "critical",
|
|
34
|
-
pattern: /(?:bash|sh|zsh|cmd|powershell)\s+-c\s+["']|exec\s*\(|eval\s*\(|system\s*\(/i,
|
|
35
|
-
description: "Potential command injection pattern",
|
|
36
|
-
remediation: "Avoid executing arbitrary shell commands from skill content",
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
type: "command_injection",
|
|
40
|
-
severity: "high",
|
|
41
|
-
pattern: /`[^`]*(?:rm|del|format|mkfs|dd|wget|curl|fetch)[^`]*`|\$\([^)]*(?:rm|del|wget|curl)[^)]*\)/i,
|
|
42
|
-
description: "Dangerous command in template literal",
|
|
43
|
-
remediation: "Review shell command usage for safety",
|
|
44
|
-
},
|
|
45
|
-
// Path traversal
|
|
46
|
-
{
|
|
47
|
-
type: "path_traversal",
|
|
48
|
-
severity: "high",
|
|
49
|
-
pattern: /\.\.[/\\]|\.\.%2f|\.\.%5c|%2e%2e[/\\]/i,
|
|
50
|
-
description: "Path traversal attempt detected",
|
|
51
|
-
remediation: "Validate and sanitize all file paths",
|
|
52
|
-
},
|
|
53
|
-
// Suspicious patterns
|
|
54
|
-
{
|
|
55
|
-
type: "suspicious_pattern",
|
|
56
|
-
severity: "medium",
|
|
57
|
-
pattern: /(?:password|secret|token|key|credential)\s*=\s*["'][^"']{8,}["']/i,
|
|
58
|
-
description: "Hardcoded credential-like pattern",
|
|
59
|
-
remediation: "Use environment variables or secure secret storage",
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
type: "suspicious_pattern",
|
|
63
|
-
severity: "medium",
|
|
64
|
-
pattern: /base64\s*\(\s*["'][^"']{20,}["']\s*\)|atob\s*\(|btoa\s*\(/i,
|
|
65
|
-
description: "Suspicious encoding/decoding pattern",
|
|
66
|
-
remediation: "Verify encoding is not used to obfuscate malicious content",
|
|
67
|
-
},
|
|
68
|
-
// External dependencies
|
|
69
|
-
{
|
|
70
|
-
type: "external_dependency",
|
|
71
|
-
severity: "low",
|
|
72
|
-
pattern: /(?:npm|pip|gem|cargo|go\s+get)\s+install/i,
|
|
73
|
-
description: "External package installation mentioned",
|
|
74
|
-
remediation: "Verify all external dependencies are trustworthy",
|
|
75
|
-
},
|
|
76
|
-
// Data exfiltration
|
|
77
|
-
{
|
|
78
|
-
type: "data_exfiltration",
|
|
79
|
-
severity: "high",
|
|
80
|
-
pattern: /(?:https?:\/\/|ftp:\/\/)[^\s"']+(?:webhook|callback|exfil|collect|steal|send)/i,
|
|
81
|
-
description: "Potential data exfiltration endpoint",
|
|
82
|
-
remediation: "Verify all external URLs are legitimate",
|
|
83
|
-
},
|
|
84
|
-
];
|
|
85
|
-
// ============================================================================
|
|
86
|
-
// Scanner
|
|
87
|
-
// ============================================================================
|
|
88
|
-
/**
|
|
89
|
-
* Scan skill content for security issues
|
|
90
|
-
*/
|
|
91
|
-
export function scanSkill(skillName, content) {
|
|
92
|
-
const findings = [];
|
|
93
|
-
const lines = content.split("\n");
|
|
94
|
-
for (const { type, severity, pattern, description, remediation } of PATTERNS) {
|
|
95
|
-
for (let i = 0; i < lines.length; i++) {
|
|
96
|
-
const line = lines[i];
|
|
97
|
-
const matches = line.matchAll(pattern);
|
|
98
|
-
for (const match of matches) {
|
|
99
|
-
if (match.index !== undefined) {
|
|
100
|
-
findings.push({
|
|
101
|
-
type,
|
|
102
|
-
severity,
|
|
103
|
-
line: i + 1,
|
|
104
|
-
column: match.index + 1,
|
|
105
|
-
match: match[0].slice(0, 100), // Limit match length
|
|
106
|
-
description,
|
|
107
|
-
remediation,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
// Sort by severity
|
|
114
|
-
const severityOrder = ["critical", "high", "medium", "low", "info"];
|
|
115
|
-
findings.sort((a, b) => severityOrder.indexOf(a.severity) - severityOrder.indexOf(b.severity));
|
|
116
|
-
return {
|
|
117
|
-
skillName,
|
|
118
|
-
scannerVersion: SCANNER_VERSION,
|
|
119
|
-
scannedAt: new Date(),
|
|
120
|
-
findings,
|
|
121
|
-
passed: !findings.some((f) => f.severity === "critical" || f.severity === "high"),
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Quick security check - returns true if skill passes basic security
|
|
126
|
-
*/
|
|
127
|
-
export function quickSecurityCheck(skillName, content) {
|
|
128
|
-
const report = scanSkill(skillName, content);
|
|
129
|
-
return report.passed;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Get security summary for display
|
|
133
|
-
*/
|
|
134
|
-
export function getSecuritySummary(report) {
|
|
135
|
-
const counts = {
|
|
136
|
-
critical: 0,
|
|
137
|
-
high: 0,
|
|
138
|
-
medium: 0,
|
|
139
|
-
low: 0,
|
|
140
|
-
info: 0,
|
|
141
|
-
};
|
|
142
|
-
for (const finding of report.findings) {
|
|
143
|
-
counts[finding.severity]++;
|
|
144
|
-
}
|
|
145
|
-
const hasCritical = counts.critical > 0;
|
|
146
|
-
const hasHigh = counts.high > 0;
|
|
147
|
-
const hasMedium = counts.medium > 0;
|
|
148
|
-
const hasLow = counts.low > 0;
|
|
149
|
-
if (hasCritical) {
|
|
150
|
-
return {
|
|
151
|
-
status: "Failed",
|
|
152
|
-
color: "red",
|
|
153
|
-
summary: `${counts.critical} critical, ${counts.high} high severity issues`,
|
|
154
|
-
counts,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
if (hasHigh) {
|
|
158
|
-
return {
|
|
159
|
-
status: "Warning",
|
|
160
|
-
color: "yellow",
|
|
161
|
-
summary: `${counts.high} high severity issues`,
|
|
162
|
-
counts,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
if (hasMedium || hasLow) {
|
|
166
|
-
return {
|
|
167
|
-
status: "Passed",
|
|
168
|
-
color: "yellow",
|
|
169
|
-
summary: `${counts.medium} medium, ${counts.low} low severity issues`,
|
|
170
|
-
counts,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
return {
|
|
174
|
-
status: "Passed",
|
|
175
|
-
color: "green",
|
|
176
|
-
summary: "No security issues found",
|
|
177
|
-
counts,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Format findings for display
|
|
182
|
-
*/
|
|
183
|
-
export function formatFindings(findings) {
|
|
184
|
-
if (findings.length === 0) {
|
|
185
|
-
return ["No security issues found."];
|
|
186
|
-
}
|
|
187
|
-
const lines = [];
|
|
188
|
-
const bySeverity = {
|
|
189
|
-
critical: [],
|
|
190
|
-
high: [],
|
|
191
|
-
medium: [],
|
|
192
|
-
low: [],
|
|
193
|
-
info: [],
|
|
194
|
-
};
|
|
195
|
-
for (const finding of findings) {
|
|
196
|
-
bySeverity[finding.severity].push(finding);
|
|
197
|
-
}
|
|
198
|
-
for (const severity of ["critical", "high", "medium", "low", "info"]) {
|
|
199
|
-
const items = bySeverity[severity];
|
|
200
|
-
if (items.length === 0)
|
|
201
|
-
continue;
|
|
202
|
-
lines.push(`\n${severity.toUpperCase()} (${items.length}):`);
|
|
203
|
-
for (const finding of items) {
|
|
204
|
-
lines.push(` [${finding.type}] Line ${finding.line}: ${finding.description}`);
|
|
205
|
-
if (finding.remediation) {
|
|
206
|
-
lines.push(` → ${finding.remediation}`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return lines;
|
|
211
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { safePathSegmentHashed } from "../../infra/install-safe-path.js";
|
|
3
|
-
import { resolveConfigDir } from "../../utils.js";
|
|
4
|
-
import { resolveSkillKey } from "./frontmatter.js";
|
|
5
|
-
export function resolveSkillToolsRootDir(entry) {
|
|
6
|
-
const key = resolveSkillKey(entry.skill, entry);
|
|
7
|
-
const safeKey = safePathSegmentHashed(key);
|
|
8
|
-
return path.join(resolveConfigDir(), "tools", safeKey);
|
|
9
|
-
}
|