@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
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { resolveUserTimezone } from "../../agents/date-time.js";
|
|
3
|
+
import { buildWorkspaceSkillSnapshot } from "../../agents/skills.js";
|
|
4
|
+
import { ensureSkillsWatcher, getSkillsSnapshotVersion } from "../../agents/skills/refresh.js";
|
|
5
|
+
import { updateSessionStore } from "../../config/sessions.js";
|
|
6
|
+
import { buildChannelSummary } from "../../infra/channel-summary.js";
|
|
7
|
+
import { getRemoteSkillEligibility } from "../../infra/skills-remote.js";
|
|
8
|
+
import { drainSystemEventEntries } from "../../infra/system-events.js";
|
|
9
|
+
export async function prependSystemEvents(params) {
|
|
10
|
+
const compactSystemEvent = (line) => {
|
|
11
|
+
const trimmed = line.trim();
|
|
12
|
+
if (!trimmed)
|
|
13
|
+
return null;
|
|
14
|
+
const lower = trimmed.toLowerCase();
|
|
15
|
+
if (lower.includes("reason periodic"))
|
|
16
|
+
return null;
|
|
17
|
+
// Filter out the actual heartbeat prompt, but not cron jobs that mention "heartbeat"
|
|
18
|
+
// The heartbeat prompt starts with "Read HEARTBEAT.md" - cron payloads won't match this
|
|
19
|
+
if (lower.startsWith("read heartbeat.md"))
|
|
20
|
+
return null;
|
|
21
|
+
// Also filter heartbeat poll/wake noise
|
|
22
|
+
if (lower.includes("heartbeat poll") || lower.includes("heartbeat wake"))
|
|
23
|
+
return null;
|
|
24
|
+
if (trimmed.startsWith("Node:")) {
|
|
25
|
+
return trimmed.replace(/ · last input [^·]+/i, "").trim();
|
|
26
|
+
}
|
|
27
|
+
return trimmed;
|
|
28
|
+
};
|
|
29
|
+
const resolveExplicitTimezone = (value) => {
|
|
30
|
+
try {
|
|
31
|
+
new Intl.DateTimeFormat("en-US", { timeZone: value }).format(new Date());
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const resolveSystemEventTimezone = (cfg) => {
|
|
39
|
+
const raw = cfg.agents?.defaults?.envelopeTimezone?.trim();
|
|
40
|
+
if (!raw)
|
|
41
|
+
return { mode: "local" };
|
|
42
|
+
const lowered = raw.toLowerCase();
|
|
43
|
+
if (lowered === "utc" || lowered === "gmt")
|
|
44
|
+
return { mode: "utc" };
|
|
45
|
+
if (lowered === "local" || lowered === "host")
|
|
46
|
+
return { mode: "local" };
|
|
47
|
+
if (lowered === "user") {
|
|
48
|
+
return {
|
|
49
|
+
mode: "iana",
|
|
50
|
+
timeZone: resolveUserTimezone(cfg.agents?.defaults?.userTimezone),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const explicit = resolveExplicitTimezone(raw);
|
|
54
|
+
return explicit ? { mode: "iana", timeZone: explicit } : { mode: "local" };
|
|
55
|
+
};
|
|
56
|
+
const formatUtcTimestamp = (date) => {
|
|
57
|
+
const yyyy = String(date.getUTCFullYear()).padStart(4, "0");
|
|
58
|
+
const mm = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
59
|
+
const dd = String(date.getUTCDate()).padStart(2, "0");
|
|
60
|
+
const hh = String(date.getUTCHours()).padStart(2, "0");
|
|
61
|
+
const min = String(date.getUTCMinutes()).padStart(2, "0");
|
|
62
|
+
const sec = String(date.getUTCSeconds()).padStart(2, "0");
|
|
63
|
+
return `${yyyy}-${mm}-${dd}T${hh}:${min}:${sec}Z`;
|
|
64
|
+
};
|
|
65
|
+
const formatZonedTimestamp = (date, timeZone) => {
|
|
66
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
67
|
+
timeZone,
|
|
68
|
+
year: "numeric",
|
|
69
|
+
month: "2-digit",
|
|
70
|
+
day: "2-digit",
|
|
71
|
+
hour: "2-digit",
|
|
72
|
+
minute: "2-digit",
|
|
73
|
+
second: "2-digit",
|
|
74
|
+
hourCycle: "h23",
|
|
75
|
+
timeZoneName: "short",
|
|
76
|
+
}).formatToParts(date);
|
|
77
|
+
const pick = (type) => parts.find((part) => part.type === type)?.value;
|
|
78
|
+
const yyyy = pick("year");
|
|
79
|
+
const mm = pick("month");
|
|
80
|
+
const dd = pick("day");
|
|
81
|
+
const hh = pick("hour");
|
|
82
|
+
const min = pick("minute");
|
|
83
|
+
const sec = pick("second");
|
|
84
|
+
const tz = [...parts]
|
|
85
|
+
.reverse()
|
|
86
|
+
.find((part) => part.type === "timeZoneName")
|
|
87
|
+
?.value?.trim();
|
|
88
|
+
if (!yyyy || !mm || !dd || !hh || !min || !sec)
|
|
89
|
+
return undefined;
|
|
90
|
+
return `${yyyy}-${mm}-${dd} ${hh}:${min}:${sec}${tz ? ` ${tz}` : ""}`;
|
|
91
|
+
};
|
|
92
|
+
const formatSystemEventTimestamp = (ts, cfg) => {
|
|
93
|
+
const date = new Date(ts);
|
|
94
|
+
if (Number.isNaN(date.getTime()))
|
|
95
|
+
return "unknown-time";
|
|
96
|
+
const zone = resolveSystemEventTimezone(cfg);
|
|
97
|
+
if (zone.mode === "utc")
|
|
98
|
+
return formatUtcTimestamp(date);
|
|
99
|
+
if (zone.mode === "local")
|
|
100
|
+
return formatZonedTimestamp(date) ?? "unknown-time";
|
|
101
|
+
return formatZonedTimestamp(date, zone.timeZone) ?? "unknown-time";
|
|
102
|
+
};
|
|
103
|
+
const systemLines = [];
|
|
104
|
+
const queued = drainSystemEventEntries(params.sessionKey);
|
|
105
|
+
systemLines.push(...queued
|
|
106
|
+
.map((event) => {
|
|
107
|
+
const compacted = compactSystemEvent(event.text);
|
|
108
|
+
if (!compacted)
|
|
109
|
+
return null;
|
|
110
|
+
return `[${formatSystemEventTimestamp(event.ts, params.cfg)}] ${compacted}`;
|
|
111
|
+
})
|
|
112
|
+
.filter((v) => Boolean(v)));
|
|
113
|
+
if (params.isMainSession && params.isNewSession) {
|
|
114
|
+
const summary = await buildChannelSummary(params.cfg);
|
|
115
|
+
if (summary.length > 0)
|
|
116
|
+
systemLines.unshift(...summary);
|
|
117
|
+
}
|
|
118
|
+
if (systemLines.length === 0)
|
|
119
|
+
return params.prefixedBodyBase;
|
|
120
|
+
const block = systemLines.map((l) => `System: ${l}`).join("\n");
|
|
121
|
+
return `${block}\n\n${params.prefixedBodyBase}`;
|
|
122
|
+
}
|
|
123
|
+
export async function ensureSkillSnapshot(params) {
|
|
124
|
+
const { sessionEntry, sessionStore, sessionKey, storePath, sessionId, isFirstTurnInSession, workspaceDir, cfg, skillFilter, } = params;
|
|
125
|
+
let nextEntry = sessionEntry;
|
|
126
|
+
let systemSent = sessionEntry?.systemSent ?? false;
|
|
127
|
+
const remoteEligibility = getRemoteSkillEligibility();
|
|
128
|
+
const snapshotVersion = getSkillsSnapshotVersion(workspaceDir);
|
|
129
|
+
ensureSkillsWatcher({ workspaceDir, config: cfg });
|
|
130
|
+
const shouldRefreshSnapshot = snapshotVersion > 0 && (nextEntry?.skillsSnapshot?.version ?? 0) < snapshotVersion;
|
|
131
|
+
if (isFirstTurnInSession && sessionStore && sessionKey) {
|
|
132
|
+
const current = nextEntry ??
|
|
133
|
+
sessionStore[sessionKey] ?? {
|
|
134
|
+
sessionId: sessionId ?? crypto.randomUUID(),
|
|
135
|
+
updatedAt: Date.now(),
|
|
136
|
+
};
|
|
137
|
+
const skillSnapshot = isFirstTurnInSession || !current.skillsSnapshot || shouldRefreshSnapshot
|
|
138
|
+
? buildWorkspaceSkillSnapshot(workspaceDir, {
|
|
139
|
+
config: cfg,
|
|
140
|
+
skillFilter,
|
|
141
|
+
eligibility: { remote: remoteEligibility },
|
|
142
|
+
snapshotVersion,
|
|
143
|
+
})
|
|
144
|
+
: current.skillsSnapshot;
|
|
145
|
+
nextEntry = {
|
|
146
|
+
...current,
|
|
147
|
+
sessionId: sessionId ?? current.sessionId ?? crypto.randomUUID(),
|
|
148
|
+
updatedAt: Date.now(),
|
|
149
|
+
systemSent: true,
|
|
150
|
+
skillsSnapshot: skillSnapshot,
|
|
151
|
+
};
|
|
152
|
+
sessionStore[sessionKey] = { ...sessionStore[sessionKey], ...nextEntry };
|
|
153
|
+
if (storePath) {
|
|
154
|
+
await updateSessionStore(storePath, (store) => {
|
|
155
|
+
store[sessionKey] = { ...store[sessionKey], ...nextEntry };
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
systemSent = true;
|
|
159
|
+
}
|
|
160
|
+
const skillsSnapshot = shouldRefreshSnapshot
|
|
161
|
+
? buildWorkspaceSkillSnapshot(workspaceDir, {
|
|
162
|
+
config: cfg,
|
|
163
|
+
skillFilter,
|
|
164
|
+
eligibility: { remote: remoteEligibility },
|
|
165
|
+
snapshotVersion,
|
|
166
|
+
})
|
|
167
|
+
: (nextEntry?.skillsSnapshot ??
|
|
168
|
+
(isFirstTurnInSession
|
|
169
|
+
? undefined
|
|
170
|
+
: buildWorkspaceSkillSnapshot(workspaceDir, {
|
|
171
|
+
config: cfg,
|
|
172
|
+
skillFilter,
|
|
173
|
+
eligibility: { remote: remoteEligibility },
|
|
174
|
+
snapshotVersion,
|
|
175
|
+
})));
|
|
176
|
+
if (skillsSnapshot &&
|
|
177
|
+
sessionStore &&
|
|
178
|
+
sessionKey &&
|
|
179
|
+
!isFirstTurnInSession &&
|
|
180
|
+
(!nextEntry?.skillsSnapshot || shouldRefreshSnapshot)) {
|
|
181
|
+
const current = nextEntry ?? {
|
|
182
|
+
sessionId: sessionId ?? crypto.randomUUID(),
|
|
183
|
+
updatedAt: Date.now(),
|
|
184
|
+
};
|
|
185
|
+
nextEntry = {
|
|
186
|
+
...current,
|
|
187
|
+
sessionId: sessionId ?? current.sessionId ?? crypto.randomUUID(),
|
|
188
|
+
updatedAt: Date.now(),
|
|
189
|
+
skillsSnapshot,
|
|
190
|
+
};
|
|
191
|
+
sessionStore[sessionKey] = { ...sessionStore[sessionKey], ...nextEntry };
|
|
192
|
+
if (storePath) {
|
|
193
|
+
await updateSessionStore(storePath, (store) => {
|
|
194
|
+
store[sessionKey] = { ...store[sessionKey], ...nextEntry };
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return { sessionEntry: nextEntry, skillsSnapshot, systemSent };
|
|
199
|
+
}
|
|
200
|
+
export async function incrementCompactionCount(params) {
|
|
201
|
+
const { sessionEntry, sessionStore, sessionKey, storePath, now = Date.now(), tokensAfter, } = params;
|
|
202
|
+
if (!sessionStore || !sessionKey)
|
|
203
|
+
return undefined;
|
|
204
|
+
const entry = sessionStore[sessionKey] ?? sessionEntry;
|
|
205
|
+
if (!entry)
|
|
206
|
+
return undefined;
|
|
207
|
+
const nextCount = (entry.compactionCount ?? 0) + 1;
|
|
208
|
+
// Build update payload with compaction count and optionally updated token counts
|
|
209
|
+
const updates = {
|
|
210
|
+
compactionCount: nextCount,
|
|
211
|
+
updatedAt: now,
|
|
212
|
+
};
|
|
213
|
+
// If tokensAfter is provided, update the cached token counts to reflect post-compaction state
|
|
214
|
+
if (tokensAfter != null && tokensAfter > 0) {
|
|
215
|
+
updates.totalTokens = tokensAfter;
|
|
216
|
+
// Clear input/output breakdown since we only have the total estimate after compaction
|
|
217
|
+
updates.inputTokens = undefined;
|
|
218
|
+
updates.outputTokens = undefined;
|
|
219
|
+
}
|
|
220
|
+
sessionStore[sessionKey] = {
|
|
221
|
+
...entry,
|
|
222
|
+
...updates,
|
|
223
|
+
};
|
|
224
|
+
if (storePath) {
|
|
225
|
+
await updateSessionStore(storePath, (store) => {
|
|
226
|
+
store[sessionKey] = {
|
|
227
|
+
...store[sessionKey],
|
|
228
|
+
...updates,
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
return nextCount;
|
|
233
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { ensureSandboxWorkspaceForSession } from "../../agents/sandbox.js";
|
|
6
|
+
import { logVerbose } from "../../globals.js";
|
|
7
|
+
import { CONFIG_DIR } from "../../utils.js";
|
|
8
|
+
export async function stageSandboxMedia(params) {
|
|
9
|
+
const { ctx, sessionCtx, cfg, sessionKey, workspaceDir } = params;
|
|
10
|
+
const hasPathsArray = Array.isArray(ctx.MediaPaths) && ctx.MediaPaths.length > 0;
|
|
11
|
+
const pathsFromArray = Array.isArray(ctx.MediaPaths) ? ctx.MediaPaths : undefined;
|
|
12
|
+
const rawPaths = pathsFromArray && pathsFromArray.length > 0
|
|
13
|
+
? pathsFromArray
|
|
14
|
+
: ctx.MediaPath?.trim()
|
|
15
|
+
? [ctx.MediaPath.trim()]
|
|
16
|
+
: [];
|
|
17
|
+
if (rawPaths.length === 0 || !sessionKey)
|
|
18
|
+
return;
|
|
19
|
+
const sandbox = await ensureSandboxWorkspaceForSession({
|
|
20
|
+
config: cfg,
|
|
21
|
+
sessionKey,
|
|
22
|
+
workspaceDir,
|
|
23
|
+
});
|
|
24
|
+
// For remote attachments without sandbox, use ~/.poolbot/media (not agent workspace for privacy)
|
|
25
|
+
const remoteMediaCacheDir = ctx.MediaRemoteHost
|
|
26
|
+
? path.join(CONFIG_DIR, "media", "remote-cache", sessionKey)
|
|
27
|
+
: null;
|
|
28
|
+
const effectiveWorkspaceDir = sandbox?.workspaceDir ?? remoteMediaCacheDir;
|
|
29
|
+
if (!effectiveWorkspaceDir)
|
|
30
|
+
return;
|
|
31
|
+
const resolveAbsolutePath = (value) => {
|
|
32
|
+
let resolved = value.trim();
|
|
33
|
+
if (!resolved)
|
|
34
|
+
return null;
|
|
35
|
+
if (resolved.startsWith("file://")) {
|
|
36
|
+
try {
|
|
37
|
+
resolved = fileURLToPath(resolved);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!path.isAbsolute(resolved))
|
|
44
|
+
return null;
|
|
45
|
+
return resolved;
|
|
46
|
+
};
|
|
47
|
+
try {
|
|
48
|
+
// For sandbox: <workspace>/media/inbound, for remote cache: use dir directly
|
|
49
|
+
const destDir = sandbox
|
|
50
|
+
? path.join(effectiveWorkspaceDir, "media", "inbound")
|
|
51
|
+
: effectiveWorkspaceDir;
|
|
52
|
+
await fs.mkdir(destDir, { recursive: true });
|
|
53
|
+
const usedNames = new Set();
|
|
54
|
+
const staged = new Map(); // absolute source -> relative sandbox path
|
|
55
|
+
for (const raw of rawPaths) {
|
|
56
|
+
const source = resolveAbsolutePath(raw);
|
|
57
|
+
if (!source)
|
|
58
|
+
continue;
|
|
59
|
+
if (staged.has(source))
|
|
60
|
+
continue;
|
|
61
|
+
const baseName = path.basename(source);
|
|
62
|
+
if (!baseName)
|
|
63
|
+
continue;
|
|
64
|
+
const parsed = path.parse(baseName);
|
|
65
|
+
let fileName = baseName;
|
|
66
|
+
let suffix = 1;
|
|
67
|
+
while (usedNames.has(fileName)) {
|
|
68
|
+
fileName = `${parsed.name}-${suffix}${parsed.ext}`;
|
|
69
|
+
suffix += 1;
|
|
70
|
+
}
|
|
71
|
+
usedNames.add(fileName);
|
|
72
|
+
const dest = path.join(destDir, fileName);
|
|
73
|
+
if (ctx.MediaRemoteHost) {
|
|
74
|
+
// Always use SCP when remote host is configured - local paths refer to remote machine
|
|
75
|
+
await scpFile(ctx.MediaRemoteHost, source, dest);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
await fs.copyFile(source, dest);
|
|
79
|
+
}
|
|
80
|
+
// For sandbox use relative path, for remote cache use absolute path
|
|
81
|
+
const stagedPath = sandbox ? path.posix.join("media", "inbound", fileName) : dest;
|
|
82
|
+
staged.set(source, stagedPath);
|
|
83
|
+
}
|
|
84
|
+
const rewriteIfStaged = (value) => {
|
|
85
|
+
const raw = value?.trim();
|
|
86
|
+
if (!raw)
|
|
87
|
+
return value;
|
|
88
|
+
const abs = resolveAbsolutePath(raw);
|
|
89
|
+
if (!abs)
|
|
90
|
+
return value;
|
|
91
|
+
const mapped = staged.get(abs);
|
|
92
|
+
return mapped ?? value;
|
|
93
|
+
};
|
|
94
|
+
const nextMediaPaths = hasPathsArray ? rawPaths.map((p) => rewriteIfStaged(p) ?? p) : undefined;
|
|
95
|
+
if (nextMediaPaths) {
|
|
96
|
+
ctx.MediaPaths = nextMediaPaths;
|
|
97
|
+
sessionCtx.MediaPaths = nextMediaPaths;
|
|
98
|
+
ctx.MediaPath = nextMediaPaths[0];
|
|
99
|
+
sessionCtx.MediaPath = nextMediaPaths[0];
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const rewritten = rewriteIfStaged(ctx.MediaPath);
|
|
103
|
+
if (rewritten && rewritten !== ctx.MediaPath) {
|
|
104
|
+
ctx.MediaPath = rewritten;
|
|
105
|
+
sessionCtx.MediaPath = rewritten;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (Array.isArray(ctx.MediaUrls) && ctx.MediaUrls.length > 0) {
|
|
109
|
+
const nextUrls = ctx.MediaUrls.map((u) => rewriteIfStaged(u) ?? u);
|
|
110
|
+
ctx.MediaUrls = nextUrls;
|
|
111
|
+
sessionCtx.MediaUrls = nextUrls;
|
|
112
|
+
}
|
|
113
|
+
const rewrittenUrl = rewriteIfStaged(ctx.MediaUrl);
|
|
114
|
+
if (rewrittenUrl && rewrittenUrl !== ctx.MediaUrl) {
|
|
115
|
+
ctx.MediaUrl = rewrittenUrl;
|
|
116
|
+
sessionCtx.MediaUrl = rewrittenUrl;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
logVerbose(`Failed to stage inbound media for sandbox: ${String(err)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function scpFile(remoteHost, remotePath, localPath) {
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
const child = spawn("/usr/bin/scp", [
|
|
126
|
+
"-o",
|
|
127
|
+
"BatchMode=yes",
|
|
128
|
+
"-o",
|
|
129
|
+
"StrictHostKeyChecking=accept-new",
|
|
130
|
+
`${remoteHost}:${remotePath}`,
|
|
131
|
+
localPath,
|
|
132
|
+
], { stdio: ["ignore", "ignore", "pipe"] });
|
|
133
|
+
let stderr = "";
|
|
134
|
+
child.stderr?.setEncoding("utf8");
|
|
135
|
+
child.stderr?.on("data", (chunk) => {
|
|
136
|
+
stderr += chunk;
|
|
137
|
+
});
|
|
138
|
+
child.once("error", reject);
|
|
139
|
+
child.once("exit", (code) => {
|
|
140
|
+
if (code === 0)
|
|
141
|
+
resolve();
|
|
142
|
+
else
|
|
143
|
+
reject(new Error(`scp failed (${code}): ${stderr.trim()}`));
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
stub
|