@poolzin/pool-bot 2026.2.21 → 2026.2.22
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 +17 -0
- package/dist/agents/api-key-rotation.js +47 -0
- package/dist/agents/apply-patch-update.js +19 -9
- package/dist/agents/apply-patch.js +72 -47
- package/dist/agents/bash-tools.exec.js +141 -559
- package/dist/agents/cli-backends.js +49 -6
- package/dist/agents/cli-runner/helpers.js +69 -152
- package/dist/agents/cli-runner.js +70 -19
- package/dist/agents/identity.js +20 -1
- package/dist/agents/image-sanitization.js +9 -0
- package/dist/agents/live-auth-keys.js +123 -26
- package/dist/agents/live-model-filter.js +13 -4
- package/dist/agents/model-catalog.js +40 -9
- package/dist/agents/model-forward-compat.js +60 -23
- package/dist/agents/model-selection.js +134 -41
- package/dist/agents/pi-auth-json.js +2 -2
- package/dist/agents/pi-embedded-helpers/bootstrap.js +65 -15
- package/dist/agents/pi-embedded-helpers/errors.js +140 -15
- package/dist/agents/pi-embedded-helpers/images.js +22 -12
- package/dist/agents/pi-embedded-helpers.js +2 -2
- package/dist/agents/pi-embedded-runner/abort.js +10 -3
- package/dist/agents/pi-embedded-runner/compact.js +230 -32
- package/dist/agents/pi-embedded-runner/extra-params.js +203 -12
- package/dist/agents/pi-embedded-runner/google.js +109 -19
- package/dist/agents/pi-embedded-runner/history.js +35 -17
- package/dist/agents/pi-embedded-runner/run/attempt.js +386 -95
- package/dist/agents/pi-embedded-runner/run/images.js +81 -55
- package/dist/agents/pi-embedded-runner/run/payloads.js +89 -39
- package/dist/agents/pi-embedded-runner/run.js +193 -25
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +2 -2
- package/dist/agents/pi-embedded-runner/runs.js +17 -8
- package/dist/agents/pi-embedded-runner/tool-result-context-guard.js +262 -0
- package/dist/agents/pi-embedded-runner.js +1 -1
- package/dist/agents/pi-embedded-subscribe.handlers.tools.js +180 -10
- package/dist/agents/pi-embedded-subscribe.js +37 -0
- package/dist/agents/pi-embedded-subscribe.tools.js +127 -30
- package/dist/agents/pi-model-discovery.js +9 -2
- package/dist/agents/pi-tool-definition-adapter.js +60 -8
- package/dist/agents/pi-tools.before-tool-call.js +1 -1
- package/dist/agents/pi-tools.js +113 -94
- package/dist/agents/pi-tools.read.js +337 -38
- package/dist/agents/poolbot-tools.js +14 -5
- package/dist/agents/sandbox/docker.js +10 -5
- package/dist/agents/sandbox/registry.js +96 -46
- package/dist/agents/sandbox/sanitize-env-vars.js +82 -0
- package/dist/agents/sandbox-paths.js +43 -10
- package/dist/agents/session-tool-result-guard-wrapper.js +23 -11
- package/dist/agents/session-tool-result-guard.js +39 -39
- package/dist/agents/session-transcript-repair.js +36 -33
- package/dist/agents/session-write-lock.js +62 -44
- package/dist/agents/skills/frontmatter.js +49 -88
- package/dist/agents/skills/workspace.js +335 -28
- package/dist/agents/subagent-announce.js +508 -174
- package/dist/agents/subagent-registry.js +45 -4
- package/dist/agents/subagent-spawn.js +16 -33
- package/dist/agents/system-prompt-report.js +27 -10
- package/dist/agents/system-prompt.js +26 -32
- package/dist/agents/tool-call-id.js +69 -17
- package/dist/agents/tool-display-common.js +1 -1
- package/dist/agents/tool-images.js +64 -31
- package/dist/agents/tools/canvas-tool.js +17 -11
- package/dist/agents/tools/common.js +37 -19
- package/dist/agents/tools/cron-tool.js +40 -38
- package/dist/agents/tools/gateway.js +70 -2
- package/dist/agents/tools/message-tool.js +181 -40
- package/dist/agents/tools/nodes-tool.js +128 -36
- package/dist/agents/tools/nodes-utils.js +12 -38
- package/dist/agents/tools/session-status-tool.js +24 -71
- package/dist/agents/tools/sessions-helpers.js +38 -210
- package/dist/agents/tools/sessions-spawn-tool.js +28 -198
- package/dist/agents/tools/telegram-actions.js +58 -7
- package/dist/agents/tools/web-fetch-utils.js +112 -7
- package/dist/agents/tools/web-fetch.js +279 -175
- package/dist/agents/tools/web-shared.js +71 -8
- package/dist/agents/usage.js +25 -16
- package/dist/auto-reply/commands-registry.data.js +85 -11
- package/dist/auto-reply/dispatch.js +40 -21
- package/dist/auto-reply/reply/abort.js +102 -33
- package/dist/auto-reply/reply/commands-core.js +82 -33
- package/dist/auto-reply/reply/commands-export-session.js +1 -1
- package/dist/auto-reply/reply/commands-info.js +41 -12
- package/dist/auto-reply/reply/commands-subagents.js +352 -100
- package/dist/auto-reply/reply/commands-system-prompt.js +2 -2
- package/dist/auto-reply/reply/dispatch-from-config.js +100 -29
- package/dist/auto-reply/reply/elevated-unavailable.js +1 -1
- package/dist/auto-reply/reply/inbound-meta.js +12 -1
- package/dist/auto-reply/reply/mentions.js +18 -11
- package/dist/auto-reply/reply/normalize-reply.js +17 -8
- package/dist/auto-reply/reply/reply-dispatcher.js +62 -10
- package/dist/auto-reply/reply/session.js +102 -21
- package/dist/auto-reply/reply/streaming-directives.js +16 -5
- package/dist/auto-reply/status.js +73 -50
- package/dist/browser/extension-relay.js +3 -3
- package/dist/browser/http-auth.js +1 -1
- package/dist/browser/paths.js +2 -2
- package/dist/build-info.json +3 -3
- package/dist/channels/allowlist-match.js +20 -0
- package/dist/channels/allowlists/resolve-utils.js +65 -2
- package/dist/channels/chat-type.js +8 -4
- package/dist/channels/dock.js +127 -35
- package/dist/channels/draft-stream-loop.js +6 -2
- package/dist/channels/plugins/actions/telegram.js +42 -18
- package/dist/channels/plugins/allowlist-match.js +1 -1
- package/dist/channels/plugins/group-mentions.js +51 -41
- package/dist/channels/plugins/message-action-names.js +2 -0
- package/dist/channels/plugins/message-actions.js +24 -5
- package/dist/channels/plugins/normalize/discord.js +26 -4
- package/dist/channels/plugins/normalize/signal.js +35 -22
- package/dist/channels/plugins/onboarding/helpers.js +8 -26
- package/dist/channels/plugins/outbound/imessage.js +15 -14
- package/dist/channels/registry.js +20 -7
- package/dist/cli/acp-cli.js +7 -5
- package/dist/cli/browser-cli-extension.js +25 -12
- package/dist/cli/browser-cli-state.cookies-storage.js +25 -6
- package/dist/cli/browser-cli-state.js +101 -145
- package/dist/cli/command-options.js +28 -0
- package/dist/cli/completion-cli.js +6 -6
- package/dist/cli/cron-cli/register.cron-add.js +25 -1
- package/dist/cli/cron-cli/register.cron-edit.js +44 -0
- package/dist/cli/cron-cli/shared.js +7 -1
- package/dist/cli/daemon-cli/lifecycle-core.js +23 -21
- package/dist/cli/daemon-cli/lifecycle.js +23 -247
- package/dist/cli/daemon-cli/register-service-commands.js +25 -4
- package/dist/cli/daemon-cli.js +1 -0
- package/dist/cli/devices-cli.js +33 -20
- package/dist/cli/gateway-cli/register.js +37 -105
- package/dist/cli/gateway-cli/run.js +49 -11
- package/dist/cli/nodes-camera.js +59 -4
- package/dist/cli/nodes-cli/register.camera.js +27 -24
- package/dist/cli/nodes-cli/rpc.js +21 -38
- package/dist/cli/qr-cli.js +2 -2
- package/dist/cli/skills-cli.format.js +2 -2
- package/dist/cli/update-cli/progress.js +2 -2
- package/dist/cli/update-cli/restart-helper.js +28 -7
- package/dist/cli/update-cli/shared.js +7 -7
- package/dist/cli/update-cli/status.js +1 -1
- package/dist/cli/update-cli/update-command.js +14 -8
- package/dist/cli/update-cli/wizard.js +2 -2
- package/dist/cli/update-cli.js +21 -1027
- package/dist/commands/auth-choice.apply.anthropic.js +10 -2
- package/dist/commands/channels/add-mutators.js +3 -35
- package/dist/commands/channels/add.js +39 -51
- package/dist/commands/config-validation.js +1 -1
- package/dist/commands/configure.gateway-auth.js +52 -15
- package/dist/commands/configure.gateway.js +84 -40
- package/dist/commands/doctor-completion.js +3 -3
- package/dist/commands/doctor-config-flow.js +536 -16
- package/dist/commands/doctor-gateway-services.js +103 -79
- package/dist/commands/doctor-memory-search.js +9 -9
- package/dist/commands/doctor-platform-notes.js +57 -30
- package/dist/commands/doctor-prompter.js +26 -15
- package/dist/commands/doctor-session-locks.js +1 -1
- package/dist/commands/doctor.js +21 -9
- package/dist/commands/model-picker.js +120 -95
- package/dist/commands/models/set.js +2 -21
- package/dist/commands/models/shared.js +65 -37
- package/dist/commands/onboard-helpers.js +81 -39
- package/dist/commands/openai-codex-oauth.js +1 -1
- package/dist/commands/sessions.js +52 -53
- package/dist/commands/status.summary.js +52 -34
- package/dist/commands/test-wizard-helpers.js +2 -2
- package/dist/config/defaults.js +79 -42
- package/dist/config/group-policy.js +50 -18
- package/dist/config/includes.js +37 -10
- package/dist/config/schema.help.js +5 -4
- package/dist/config/schema.hints.js +2 -2
- package/dist/config/schema.labels.js +1 -0
- package/dist/config/sessions/group.js +12 -11
- package/dist/config/sessions/paths.js +137 -11
- package/dist/config/sessions/store.js +185 -65
- package/dist/config/sessions/types.js +15 -1
- package/dist/config/sessions.js +1 -0
- package/dist/config/telegram-custom-commands.js +3 -2
- package/dist/config/types.js +2 -0
- package/dist/config/zod-schema.agent-defaults.js +6 -27
- package/dist/config/zod-schema.agent-runtime.js +171 -79
- package/dist/config/zod-schema.providers-core.js +138 -65
- package/dist/config/zod-schema.session.js +49 -22
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
- package/dist/cron/isolated-agent/run.js +224 -57
- package/dist/cron/normalize.js +48 -45
- package/dist/cron/run-log.js +14 -0
- package/dist/cron/service/jobs.js +190 -28
- package/dist/cron/service/normalize.js +29 -11
- package/dist/cron/service/store.js +30 -44
- package/dist/cron/service/timer.js +182 -96
- package/dist/cron/service.js +3 -0
- package/dist/cron/stagger.js +37 -0
- package/dist/daemon/inspect.js +132 -92
- package/dist/daemon/runtime-paths.js +25 -4
- package/dist/daemon/service-audit.js +47 -16
- package/dist/discord/accounts.js +23 -20
- package/dist/discord/monitor/agent-components.js +1115 -219
- package/dist/discord/monitor/allow-list.js +114 -34
- package/dist/discord/monitor/listeners.js +204 -97
- package/dist/discord/monitor/message-handler.js +21 -10
- package/dist/discord/monitor/message-handler.preflight.js +195 -101
- package/dist/discord/monitor/message-handler.process.js +384 -123
- package/dist/discord/monitor/message-utils.js +86 -23
- package/dist/discord/monitor/native-command.js +77 -57
- package/dist/discord/monitor/provider.js +122 -117
- package/dist/discord/monitor/reply-context.js +20 -16
- package/dist/discord/monitor/reply-delivery.js +40 -8
- package/dist/discord/monitor/rest-fetch.js +22 -0
- package/dist/discord/monitor/threading.js +117 -24
- package/dist/discord/send.js +2 -1
- package/dist/discord/send.outbound.js +124 -11
- package/dist/discord/send.shared.js +112 -72
- package/dist/discord/voice-message.js +3 -3
- package/dist/gateway/auth.js +119 -44
- package/dist/gateway/call.js +76 -34
- package/dist/gateway/channel-health-monitor.js +57 -50
- package/dist/gateway/client.js +63 -29
- package/dist/gateway/control-ui-contract.js +1 -1
- package/dist/gateway/gateway-config-prompts.shared.js +2 -2
- package/dist/gateway/net.js +109 -1
- package/dist/gateway/protocol/index.js +5 -8
- package/dist/gateway/protocol/schema/agent.js +19 -1
- package/dist/gateway/protocol/schema/channels.js +21 -0
- package/dist/gateway/protocol/schema/cron.js +43 -30
- package/dist/gateway/protocol/schema/protocol-schemas.js +6 -11
- package/dist/gateway/protocol/schema/sessions.js +5 -1
- package/dist/gateway/protocol/schema.js +0 -1
- package/dist/gateway/server/presence-events.js +12 -0
- package/dist/gateway/server/ws-connection/message-handler.js +203 -212
- package/dist/gateway/server/ws-connection.js +58 -21
- package/dist/gateway/server-broadcast.js +18 -13
- package/dist/gateway/server-cron.js +177 -10
- package/dist/gateway/server-methods/agent-job.js +131 -38
- package/dist/gateway/server-methods/send.js +60 -14
- package/dist/gateway/server-methods/sessions.js +160 -96
- package/dist/gateway/server-methods/system.js +5 -7
- package/dist/gateway/server-methods-list.js +8 -0
- package/dist/gateway/server-methods.js +24 -8
- package/dist/gateway/server-node-events.js +278 -68
- package/dist/gateway/session-utils.fs.js +316 -75
- package/dist/gateway/session-utils.js +224 -70
- package/dist/gateway/sessions-patch.js +63 -20
- package/dist/gateway/test-temp-config.js +1 -1
- package/dist/gateway/tools-invoke-http.js +118 -70
- package/dist/gateway/ws-log.js +135 -107
- package/dist/hooks/frontmatter.js +36 -82
- package/dist/hooks/install.js +149 -139
- package/dist/hooks/internal-hooks.js +29 -4
- package/dist/hooks/plugin-hooks.js +2 -1
- package/dist/imessage/monitor/deliver.js +10 -4
- package/dist/imessage/monitor/monitor-provider.js +138 -375
- package/dist/imessage/monitor/runtime.js +4 -8
- package/dist/imessage/send.js +65 -19
- package/dist/infra/exec-approvals-allowlist.js +7 -0
- package/dist/infra/exec-approvals.js +35 -920
- package/dist/infra/exec-safe-bin-trust.js +64 -0
- package/dist/infra/heartbeat-runner.js +207 -134
- package/dist/infra/heartbeat-wake.js +183 -22
- package/dist/infra/install-source-utils.js +47 -0
- package/dist/infra/net/ssrf.js +170 -36
- package/dist/infra/outbound/deliver.js +224 -58
- package/dist/infra/outbound/message-action-spec.js +12 -5
- package/dist/infra/outbound/outbound-session.js +27 -25
- package/dist/infra/poolbot-root.js +32 -22
- package/dist/infra/ports.js +14 -11
- package/dist/infra/skills-remote.js +48 -37
- package/dist/infra/system-events.js +25 -11
- package/dist/infra/system-presence.js +26 -33
- package/dist/infra/tmp-poolbot-dir.js +81 -2
- package/dist/infra/wsl.js +37 -1
- package/dist/line/bot-message-context.js +163 -191
- package/dist/logging/subsystem.js +59 -22
- package/dist/markdown/ir.js +124 -50
- package/dist/media/store.js +1 -1
- package/dist/media-understanding/runner.entries.js +42 -25
- package/dist/media-understanding/runner.js +53 -488
- package/dist/memory/embeddings-gemini.js +53 -38
- package/dist/memory/manager-embedding-ops.js +48 -69
- package/dist/pairing/pairing-store.js +178 -119
- package/dist/plugin-sdk/index.js +34 -6
- package/dist/plugins/hooks.js +135 -14
- package/dist/plugins/install.js +190 -152
- package/dist/polls.js +11 -0
- package/dist/routing/resolve-route.js +190 -56
- package/dist/routing/session-key.js +38 -22
- package/dist/runtime.js +35 -9
- package/dist/security/audit-channel.js +1 -1
- package/dist/sessions/session-key-utils.js +29 -11
- package/dist/shared/frontmatter.js +5 -5
- package/dist/shared/node-list-types.js +1 -0
- package/dist/shared/string-normalization.js +15 -0
- package/dist/signal/monitor/event-handler.js +68 -36
- package/dist/signal/send.js +29 -37
- package/dist/slack/monitor/allow-list.js +10 -11
- package/dist/slack/monitor/commands.js +14 -3
- package/dist/slack/monitor/events/interactions.js +4 -4
- package/dist/slack/monitor/media.js +224 -16
- package/dist/slack/monitor/message-handler/dispatch.js +247 -13
- package/dist/slack/monitor/message-handler/prepare.js +128 -45
- package/dist/slack/monitor/slash.js +357 -144
- package/dist/slack/streaming.js +77 -0
- package/dist/telegram/accounts.js +40 -13
- package/dist/telegram/allowed-updates.js +3 -0
- package/dist/telegram/bot/delivery.js +129 -66
- package/dist/telegram/bot/helpers.js +136 -122
- package/dist/telegram/bot-handlers.js +600 -339
- package/dist/telegram/bot-message-context.js +115 -73
- package/dist/telegram/bot-message-dispatch.js +235 -104
- package/dist/telegram/bot-native-command-menu.js +3 -1
- package/dist/telegram/bot-native-commands.js +213 -193
- package/dist/telegram/bot.js +24 -132
- package/dist/telegram/draft-stream.js +84 -75
- package/dist/telegram/format.js +150 -6
- package/dist/telegram/send.js +415 -255
- package/dist/telegram/targets.js +21 -2
- package/dist/telegram/update-offset-store.js +19 -3
- package/dist/terminal/restore.js +5 -2
- package/dist/test-utils/fetch-mock.js +5 -0
- package/dist/version.js +18 -5
- package/dist/web/auto-reply/monitor/broadcast.js +7 -3
- package/dist/web/auto-reply/monitor/on-message.js +6 -3
- package/dist/web/inbound/media.js +34 -8
- package/dist/web/inbound/monitor.js +34 -17
- package/dist/web/inbound/send-api.js +18 -17
- package/dist/web/outbound.js +12 -5
- package/dist/wizard/clack-prompter.js +40 -7
- 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/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/matrix/CHANGELOG.md +5 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- 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/skills/apple-reminders/SKILL.md +100 -49
- package/skills/coding-agent/SKILL.md +34 -28
- package/skills/github/SKILL.md +131 -16
- package/skills/imsg/SKILL.md +112 -15
- package/skills/openhue/SKILL.md +101 -19
- package/skills/tmux/SKILL.md +111 -79
- package/skills/weather/SKILL.md +88 -25
|
@@ -3,26 +3,30 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { CURRENT_SESSION_VERSION, SessionManager } from "@mariozechner/pi-coding-agent";
|
|
5
5
|
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
|
|
6
|
+
import { normalizeChatType } from "../../channels/chat-type.js";
|
|
6
7
|
import { DEFAULT_RESET_TRIGGERS, deriveSessionMetaPatch, evaluateSessionFreshness, loadSessionStore, resolveChannelResetConfig, resolveThreadFlag, resolveSessionResetPolicy, resolveSessionResetType, resolveGroupSessionKey, resolveSessionFilePath, resolveSessionKey, resolveSessionTranscriptPath, resolveStorePath, updateSessionStore, } from "../../config/sessions.js";
|
|
8
|
+
import { archiveSessionTranscripts } from "../../gateway/session-utils.fs.js";
|
|
9
|
+
import { deliverSessionMaintenanceWarning } from "../../infra/session-maintenance-warning.js";
|
|
10
|
+
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
|
|
7
11
|
import { normalizeMainKey } from "../../routing/session-key.js";
|
|
12
|
+
import { normalizeSessionDeliveryFields } from "../../utils/delivery-context.js";
|
|
8
13
|
import { resolveCommandAuthorization } from "../command-auth.js";
|
|
9
|
-
import { normalizeChatType } from "../../channels/chat-type.js";
|
|
10
|
-
import { stripMentions, stripStructuralPrefixes } from "./mentions.js";
|
|
11
|
-
import { formatInboundBodyWithSenderMeta } from "./inbound-sender-meta.js";
|
|
12
14
|
import { normalizeInboundTextNewlines } from "./inbound-text.js";
|
|
13
|
-
import {
|
|
15
|
+
import { stripMentions, stripStructuralPrefixes } from "./mentions.js";
|
|
14
16
|
function forkSessionFromParent(params) {
|
|
15
|
-
const parentSessionFile = resolveSessionFilePath(params.parentEntry.sessionId, params.parentEntry);
|
|
16
|
-
if (!parentSessionFile || !fs.existsSync(parentSessionFile))
|
|
17
|
+
const parentSessionFile = resolveSessionFilePath(params.parentEntry.sessionId, params.parentEntry, { agentId: params.agentId, sessionsDir: params.sessionsDir });
|
|
18
|
+
if (!parentSessionFile || !fs.existsSync(parentSessionFile)) {
|
|
17
19
|
return null;
|
|
20
|
+
}
|
|
18
21
|
try {
|
|
19
22
|
const manager = SessionManager.open(parentSessionFile);
|
|
20
23
|
const leafId = manager.getLeafId();
|
|
21
24
|
if (leafId) {
|
|
22
25
|
const sessionFile = manager.createBranchedSession(leafId) ?? manager.getSessionFile();
|
|
23
26
|
const sessionId = manager.getSessionId();
|
|
24
|
-
if (sessionFile && sessionId)
|
|
27
|
+
if (sessionFile && sessionId) {
|
|
25
28
|
return { sessionId, sessionFile };
|
|
29
|
+
}
|
|
26
30
|
}
|
|
27
31
|
const sessionId = crypto.randomUUID();
|
|
28
32
|
const timestamp = new Date().toISOString();
|
|
@@ -63,7 +67,13 @@ export async function initSessionState(params) {
|
|
|
63
67
|
: DEFAULT_RESET_TRIGGERS;
|
|
64
68
|
const sessionScope = sessionCfg?.scope ?? "per-sender";
|
|
65
69
|
const storePath = resolveStorePath(sessionCfg?.store, { agentId });
|
|
66
|
-
|
|
70
|
+
// CRITICAL: Skip cache to ensure fresh data when resolving session identity.
|
|
71
|
+
// Stale cache (especially with multiple gateway processes or on Windows where
|
|
72
|
+
// mtime granularity may miss rapid writes) can cause incorrect sessionId
|
|
73
|
+
// generation, leading to orphaned transcript files. See #17971.
|
|
74
|
+
const sessionStore = loadSessionStore(storePath, {
|
|
75
|
+
skipCache: true,
|
|
76
|
+
});
|
|
67
77
|
let sessionKey;
|
|
68
78
|
let sessionEntry;
|
|
69
79
|
let sessionId;
|
|
@@ -106,10 +116,12 @@ export async function initSessionState(params) {
|
|
|
106
116
|
const trimmedBodyLower = trimmedBody.toLowerCase();
|
|
107
117
|
const strippedForResetLower = strippedForReset.toLowerCase();
|
|
108
118
|
for (const trigger of resetTriggers) {
|
|
109
|
-
if (!trigger)
|
|
119
|
+
if (!trigger) {
|
|
110
120
|
continue;
|
|
111
|
-
|
|
121
|
+
}
|
|
122
|
+
if (!resetAuthorized) {
|
|
112
123
|
break;
|
|
124
|
+
}
|
|
113
125
|
const triggerLower = trigger.toLowerCase();
|
|
114
126
|
if (trimmedBodyLower === triggerLower || strippedForResetLower === triggerLower) {
|
|
115
127
|
isNewSession = true;
|
|
@@ -169,13 +181,25 @@ export async function initSessionState(params) {
|
|
|
169
181
|
isNewSession = true;
|
|
170
182
|
systemSent = false;
|
|
171
183
|
abortedLastRun = false;
|
|
184
|
+
// When a reset trigger (/new, /reset) starts a new session, carry over
|
|
185
|
+
// user-set behavior overrides (verbose, thinking, reasoning, ttsAuto)
|
|
186
|
+
// so the user doesn't have to re-enable them every time.
|
|
187
|
+
if (resetTriggered && entry) {
|
|
188
|
+
persistedThinking = entry.thinkingLevel;
|
|
189
|
+
persistedVerbose = entry.verboseLevel;
|
|
190
|
+
persistedReasoning = entry.reasoningLevel;
|
|
191
|
+
persistedTtsAuto = entry.ttsAuto;
|
|
192
|
+
}
|
|
172
193
|
}
|
|
173
194
|
const baseEntry = !isNewSession && freshEntry ? entry : undefined;
|
|
174
195
|
// Track the originating channel/to for announce routing (subagent announce-back).
|
|
175
196
|
const lastChannelRaw = ctx.OriginatingChannel || baseEntry?.lastChannel;
|
|
176
197
|
const lastToRaw = ctx.OriginatingTo || ctx.To || baseEntry?.lastTo;
|
|
177
198
|
const lastAccountIdRaw = ctx.AccountId || baseEntry?.lastAccountId;
|
|
178
|
-
|
|
199
|
+
// Only fall back to persisted threadId for thread sessions. Non-thread
|
|
200
|
+
// sessions (e.g. DM without topics) must not inherit a stale threadId from a
|
|
201
|
+
// previous interaction that happened inside a topic/thread.
|
|
202
|
+
const lastThreadIdRaw = ctx.MessageThreadId || (isThread ? baseEntry?.lastThreadId : undefined);
|
|
179
203
|
const deliveryFields = normalizeSessionDeliveryFields({
|
|
180
204
|
deliveryContext: {
|
|
181
205
|
channel: lastChannelRaw,
|
|
@@ -242,13 +266,18 @@ export async function initSessionState(params) {
|
|
|
242
266
|
parentSessionKey &&
|
|
243
267
|
parentSessionKey !== sessionKey &&
|
|
244
268
|
sessionStore[parentSessionKey]) {
|
|
269
|
+
console.warn(`[session-init] forking from parent session: parentKey=${parentSessionKey} → sessionKey=${sessionKey} ` +
|
|
270
|
+
`parentTokens=${sessionStore[parentSessionKey].totalTokens ?? "?"}`);
|
|
245
271
|
const forked = forkSessionFromParent({
|
|
246
272
|
parentEntry: sessionStore[parentSessionKey],
|
|
273
|
+
agentId,
|
|
274
|
+
sessionsDir: path.dirname(storePath),
|
|
247
275
|
});
|
|
248
276
|
if (forked) {
|
|
249
277
|
sessionId = forked.sessionId;
|
|
250
278
|
sessionEntry.sessionId = forked.sessionId;
|
|
251
279
|
sessionEntry.sessionFile = forked.sessionFile;
|
|
280
|
+
console.warn(`[session-init] forked session created: file=${forked.sessionFile}`);
|
|
252
281
|
}
|
|
253
282
|
}
|
|
254
283
|
if (!sessionEntry.sessionFile) {
|
|
@@ -258,30 +287,82 @@ export async function initSessionState(params) {
|
|
|
258
287
|
sessionEntry.compactionCount = 0;
|
|
259
288
|
sessionEntry.memoryFlushCompactionCount = undefined;
|
|
260
289
|
sessionEntry.memoryFlushAt = undefined;
|
|
290
|
+
// Clear stale token metrics from previous session so /status doesn't
|
|
291
|
+
// display the old session's context usage after /new or /reset.
|
|
292
|
+
sessionEntry.totalTokens = undefined;
|
|
293
|
+
sessionEntry.inputTokens = undefined;
|
|
294
|
+
sessionEntry.outputTokens = undefined;
|
|
295
|
+
sessionEntry.contextTokens = undefined;
|
|
261
296
|
}
|
|
262
297
|
// Preserve per-session overrides while resetting compaction state on /new.
|
|
263
298
|
sessionStore[sessionKey] = { ...sessionStore[sessionKey], ...sessionEntry };
|
|
264
299
|
await updateSessionStore(storePath, (store) => {
|
|
265
300
|
// Preserve per-session overrides while resetting compaction state on /new.
|
|
266
301
|
store[sessionKey] = { ...store[sessionKey], ...sessionEntry };
|
|
302
|
+
}, {
|
|
303
|
+
activeSessionKey: sessionKey,
|
|
304
|
+
onWarn: (warning) => deliverSessionMaintenanceWarning({
|
|
305
|
+
cfg,
|
|
306
|
+
sessionKey,
|
|
307
|
+
entry: sessionEntry,
|
|
308
|
+
warning,
|
|
309
|
+
}),
|
|
267
310
|
});
|
|
311
|
+
// Archive old transcript so it doesn't accumulate on disk (#14869).
|
|
312
|
+
if (previousSessionEntry?.sessionId) {
|
|
313
|
+
archiveSessionTranscripts({
|
|
314
|
+
sessionId: previousSessionEntry.sessionId,
|
|
315
|
+
storePath,
|
|
316
|
+
sessionFile: previousSessionEntry.sessionFile,
|
|
317
|
+
agentId,
|
|
318
|
+
reason: "reset",
|
|
319
|
+
});
|
|
320
|
+
}
|
|
268
321
|
const sessionCtx = {
|
|
269
322
|
...ctx,
|
|
270
323
|
// Keep BodyStripped aligned with Body (best default for agent prompts).
|
|
271
324
|
// RawBody is reserved for command/directive parsing and may omit context.
|
|
272
|
-
BodyStripped:
|
|
273
|
-
ctx
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
ctx.BodyForCommands ??
|
|
280
|
-
""),
|
|
281
|
-
}),
|
|
325
|
+
BodyStripped: normalizeInboundTextNewlines(bodyStripped ??
|
|
326
|
+
ctx.BodyForAgent ??
|
|
327
|
+
ctx.Body ??
|
|
328
|
+
ctx.CommandBody ??
|
|
329
|
+
ctx.RawBody ??
|
|
330
|
+
ctx.BodyForCommands ??
|
|
331
|
+
""),
|
|
282
332
|
SessionId: sessionId,
|
|
283
333
|
IsNewSession: isNewSession ? "true" : "false",
|
|
284
334
|
};
|
|
335
|
+
// Run session plugin hooks (fire-and-forget)
|
|
336
|
+
const hookRunner = getGlobalHookRunner();
|
|
337
|
+
if (hookRunner && isNewSession) {
|
|
338
|
+
const effectiveSessionId = sessionId ?? "";
|
|
339
|
+
// If replacing an existing session, fire session_end for the old one
|
|
340
|
+
if (previousSessionEntry?.sessionId && previousSessionEntry.sessionId !== effectiveSessionId) {
|
|
341
|
+
if (hookRunner.hasHooks("session_end")) {
|
|
342
|
+
void hookRunner
|
|
343
|
+
.runSessionEnd({
|
|
344
|
+
sessionId: previousSessionEntry.sessionId,
|
|
345
|
+
messageCount: 0,
|
|
346
|
+
}, {
|
|
347
|
+
sessionId: previousSessionEntry.sessionId,
|
|
348
|
+
agentId: resolveSessionAgentId({ sessionKey, config: cfg }),
|
|
349
|
+
})
|
|
350
|
+
.catch(() => { });
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// Fire session_start for the new session
|
|
354
|
+
if (hookRunner.hasHooks("session_start")) {
|
|
355
|
+
void hookRunner
|
|
356
|
+
.runSessionStart({
|
|
357
|
+
sessionId: effectiveSessionId,
|
|
358
|
+
resumedFrom: previousSessionEntry?.sessionId,
|
|
359
|
+
}, {
|
|
360
|
+
sessionId: effectiveSessionId,
|
|
361
|
+
agentId: resolveSessionAgentId({ sessionKey, config: cfg }),
|
|
362
|
+
})
|
|
363
|
+
.catch(() => { });
|
|
364
|
+
}
|
|
365
|
+
}
|
|
285
366
|
return {
|
|
286
367
|
sessionCtx,
|
|
287
368
|
sessionEntry,
|
|
@@ -3,11 +3,13 @@ import { parseInlineDirectives } from "../../utils/directive-tags.js";
|
|
|
3
3
|
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../tokens.js";
|
|
4
4
|
const splitTrailingDirective = (text) => {
|
|
5
5
|
const openIndex = text.lastIndexOf("[[");
|
|
6
|
-
if (openIndex < 0)
|
|
6
|
+
if (openIndex < 0) {
|
|
7
7
|
return { text, tail: "" };
|
|
8
|
+
}
|
|
8
9
|
const closeIndex = text.indexOf("]]", openIndex + 2);
|
|
9
|
-
if (closeIndex >= 0)
|
|
10
|
+
if (closeIndex >= 0) {
|
|
10
11
|
return { text, tail: "" };
|
|
12
|
+
}
|
|
11
13
|
return {
|
|
12
14
|
text: text.slice(0, openIndex),
|
|
13
15
|
tail: text.slice(openIndex),
|
|
@@ -47,9 +49,11 @@ const hasRenderableContent = (parsed) => Boolean(parsed.text) ||
|
|
|
47
49
|
export function createStreamingDirectiveAccumulator() {
|
|
48
50
|
let pendingTail = "";
|
|
49
51
|
let pendingReply = { sawCurrent: false, hasTag: false };
|
|
52
|
+
let activeReply = { sawCurrent: false, hasTag: false };
|
|
50
53
|
const reset = () => {
|
|
51
54
|
pendingTail = "";
|
|
52
55
|
pendingReply = { sawCurrent: false, hasTag: false };
|
|
56
|
+
activeReply = { sawCurrent: false, hasTag: false };
|
|
53
57
|
};
|
|
54
58
|
const consume = (raw, options = {}) => {
|
|
55
59
|
let combined = `${pendingTail}${raw ?? ""}`;
|
|
@@ -63,9 +67,9 @@ export function createStreamingDirectiveAccumulator() {
|
|
|
63
67
|
return null;
|
|
64
68
|
}
|
|
65
69
|
const parsed = parseChunk(combined, { silentToken: options.silentToken });
|
|
66
|
-
const hasTag = pendingReply.hasTag || parsed.replyToTag;
|
|
67
|
-
const sawCurrent = pendingReply.sawCurrent || parsed.replyToCurrent;
|
|
68
|
-
const explicitId = parsed.replyToExplicitId ?? pendingReply.explicitId;
|
|
70
|
+
const hasTag = activeReply.hasTag || pendingReply.hasTag || parsed.replyToTag;
|
|
71
|
+
const sawCurrent = activeReply.sawCurrent || pendingReply.sawCurrent || parsed.replyToCurrent;
|
|
72
|
+
const explicitId = parsed.replyToExplicitId ?? pendingReply.explicitId ?? activeReply.explicitId;
|
|
69
73
|
const combinedResult = {
|
|
70
74
|
...parsed,
|
|
71
75
|
replyToId: explicitId,
|
|
@@ -82,6 +86,13 @@ export function createStreamingDirectiveAccumulator() {
|
|
|
82
86
|
}
|
|
83
87
|
return null;
|
|
84
88
|
}
|
|
89
|
+
// Keep reply context sticky for the full assistant message so split/newline chunks
|
|
90
|
+
// stay on the same native reply target until reset() is called for the next message.
|
|
91
|
+
activeReply = {
|
|
92
|
+
explicitId,
|
|
93
|
+
sawCurrent,
|
|
94
|
+
hasTag,
|
|
95
|
+
};
|
|
85
96
|
pendingReply = { sawCurrent: false, hasTag: false };
|
|
86
97
|
return combinedResult;
|
|
87
98
|
};
|
|
@@ -5,13 +5,15 @@ import { resolveModelAuthMode } from "../agents/model-auth.js";
|
|
|
5
5
|
import { resolveConfiguredModelRef } from "../agents/model-selection.js";
|
|
6
6
|
import { resolveSandboxRuntimeStatus } from "../agents/sandbox.js";
|
|
7
7
|
import { derivePromptTokens, normalizeUsage } from "../agents/usage.js";
|
|
8
|
-
import { resolveMainSessionKey, resolveSessionFilePath, } from "../config/sessions.js";
|
|
9
|
-
import {
|
|
8
|
+
import { resolveMainSessionKey, resolveSessionFilePath, resolveSessionFilePathOptions, } from "../config/sessions.js";
|
|
9
|
+
import { formatTimeAgo } from "../infra/format-time/format-relative.js";
|
|
10
10
|
import { resolveCommitHash } from "../infra/git-commit.js";
|
|
11
|
+
import { listPluginCommands } from "../plugins/commands.js";
|
|
12
|
+
import { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
|
13
|
+
import { getTtsMaxLength, getTtsProvider, isSummarizationEnabled, resolveTtsAutoMode, resolveTtsConfig, resolveTtsPrefsPath, } from "../tts/tts.js";
|
|
11
14
|
import { estimateUsageCost, formatTokenCount as formatTokenCountShared, formatUsd, resolveModelCostConfig, } from "../utils/usage-format.js";
|
|
12
15
|
import { VERSION } from "../version.js";
|
|
13
16
|
import { listChatCommands, listChatCommandsForConfig, } from "./commands-registry.js";
|
|
14
|
-
import { listPluginCommands } from "../plugins/commands.js";
|
|
15
17
|
export const formatTokenCount = formatTokenCountShared;
|
|
16
18
|
function resolveRuntimeLabel(args) {
|
|
17
19
|
const sessionKey = args.sessionKey?.trim();
|
|
@@ -21,19 +23,23 @@ function resolveRuntimeLabel(args) {
|
|
|
21
23
|
sessionKey,
|
|
22
24
|
});
|
|
23
25
|
const sandboxMode = runtimeStatus.mode ?? "off";
|
|
24
|
-
if (sandboxMode === "off")
|
|
26
|
+
if (sandboxMode === "off") {
|
|
25
27
|
return "direct";
|
|
28
|
+
}
|
|
26
29
|
const runtime = runtimeStatus.sandboxed ? "docker" : sessionKey ? "direct" : "unknown";
|
|
27
30
|
return `${runtime}/${sandboxMode}`;
|
|
28
31
|
}
|
|
29
32
|
const sandboxMode = args.agent?.sandbox?.mode ?? "off";
|
|
30
|
-
if (sandboxMode === "off")
|
|
33
|
+
if (sandboxMode === "off") {
|
|
31
34
|
return "direct";
|
|
35
|
+
}
|
|
32
36
|
const sandboxed = (() => {
|
|
33
|
-
if (!sessionKey)
|
|
37
|
+
if (!sessionKey) {
|
|
34
38
|
return false;
|
|
35
|
-
|
|
39
|
+
}
|
|
40
|
+
if (sandboxMode === "all") {
|
|
36
41
|
return true;
|
|
42
|
+
}
|
|
37
43
|
if (args.config) {
|
|
38
44
|
return resolveSandboxRuntimeStatus({
|
|
39
45
|
cfg: args.config,
|
|
@@ -61,48 +67,47 @@ const formatTokens = (total, contextTokens) => {
|
|
|
61
67
|
return `${totalLabel}/${ctxLabel}${pct !== null ? ` (${pct}%)` : ""}`;
|
|
62
68
|
};
|
|
63
69
|
export const formatContextUsageShort = (total, contextTokens) => `Context ${formatTokens(total, contextTokens ?? null)}`;
|
|
64
|
-
const formatAge = (ms) => {
|
|
65
|
-
if (!ms || ms < 0)
|
|
66
|
-
return "unknown";
|
|
67
|
-
const minutes = Math.round(ms / 60_000);
|
|
68
|
-
if (minutes < 1)
|
|
69
|
-
return "just now";
|
|
70
|
-
if (minutes < 60)
|
|
71
|
-
return `${minutes}m ago`;
|
|
72
|
-
const hours = Math.round(minutes / 60);
|
|
73
|
-
if (hours < 48)
|
|
74
|
-
return `${hours}h ago`;
|
|
75
|
-
const days = Math.round(hours / 24);
|
|
76
|
-
return `${days}d ago`;
|
|
77
|
-
};
|
|
78
70
|
const formatQueueDetails = (queue) => {
|
|
79
|
-
if (!queue)
|
|
71
|
+
if (!queue) {
|
|
80
72
|
return "";
|
|
73
|
+
}
|
|
81
74
|
const depth = typeof queue.depth === "number" ? `depth ${queue.depth}` : null;
|
|
82
75
|
if (!queue.showDetails) {
|
|
83
76
|
return depth ? ` (${depth})` : "";
|
|
84
77
|
}
|
|
85
78
|
const detailParts = [];
|
|
86
|
-
if (depth)
|
|
79
|
+
if (depth) {
|
|
87
80
|
detailParts.push(depth);
|
|
81
|
+
}
|
|
88
82
|
if (typeof queue.debounceMs === "number") {
|
|
89
83
|
const ms = Math.max(0, Math.round(queue.debounceMs));
|
|
90
84
|
const label = ms >= 1000 ? `${ms % 1000 === 0 ? ms / 1000 : (ms / 1000).toFixed(1)}s` : `${ms}ms`;
|
|
91
85
|
detailParts.push(`debounce ${label}`);
|
|
92
86
|
}
|
|
93
|
-
if (typeof queue.cap === "number")
|
|
87
|
+
if (typeof queue.cap === "number") {
|
|
94
88
|
detailParts.push(`cap ${queue.cap}`);
|
|
95
|
-
|
|
89
|
+
}
|
|
90
|
+
if (queue.dropPolicy) {
|
|
96
91
|
detailParts.push(`drop ${queue.dropPolicy}`);
|
|
92
|
+
}
|
|
97
93
|
return detailParts.length ? ` (${detailParts.join(" · ")})` : "";
|
|
98
94
|
};
|
|
99
|
-
const readUsageFromSessionLog = (sessionId, sessionEntry) => {
|
|
95
|
+
const readUsageFromSessionLog = (sessionId, sessionEntry, agentId, sessionKey, storePath) => {
|
|
100
96
|
// Transcripts are stored at the session file path (fallback: ~/.poolbot/sessions/<SessionId>.jsonl)
|
|
101
|
-
if (!sessionId)
|
|
97
|
+
if (!sessionId) {
|
|
102
98
|
return undefined;
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
}
|
|
100
|
+
let logPath;
|
|
101
|
+
try {
|
|
102
|
+
const resolvedAgentId = agentId ?? (sessionKey ? resolveAgentIdFromSessionKey(sessionKey) : undefined);
|
|
103
|
+
logPath = resolveSessionFilePath(sessionId, sessionEntry, resolveSessionFilePathOptions({ agentId: resolvedAgentId, storePath }));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
if (!fs.existsSync(logPath)) {
|
|
105
109
|
return undefined;
|
|
110
|
+
}
|
|
106
111
|
try {
|
|
107
112
|
const lines = fs.readFileSync(logPath, "utf-8").split(/\n+/);
|
|
108
113
|
let input = 0;
|
|
@@ -111,28 +116,32 @@ const readUsageFromSessionLog = (sessionId, sessionEntry) => {
|
|
|
111
116
|
let model;
|
|
112
117
|
let lastUsage;
|
|
113
118
|
for (const line of lines) {
|
|
114
|
-
if (!line.trim())
|
|
119
|
+
if (!line.trim()) {
|
|
115
120
|
continue;
|
|
121
|
+
}
|
|
116
122
|
try {
|
|
117
123
|
const parsed = JSON.parse(line);
|
|
118
124
|
const usageRaw = parsed.message?.usage ?? parsed.usage;
|
|
119
125
|
const usage = normalizeUsage(usageRaw);
|
|
120
|
-
if (usage)
|
|
126
|
+
if (usage) {
|
|
121
127
|
lastUsage = usage;
|
|
128
|
+
}
|
|
122
129
|
model = parsed.message?.model ?? parsed.model ?? model;
|
|
123
130
|
}
|
|
124
131
|
catch {
|
|
125
132
|
// ignore bad lines
|
|
126
133
|
}
|
|
127
134
|
}
|
|
128
|
-
if (!lastUsage)
|
|
135
|
+
if (!lastUsage) {
|
|
129
136
|
return undefined;
|
|
137
|
+
}
|
|
130
138
|
input = lastUsage.input ?? 0;
|
|
131
139
|
output = lastUsage.output ?? 0;
|
|
132
140
|
promptTokens = derivePromptTokens(lastUsage) ?? lastUsage.total ?? input + output;
|
|
133
141
|
const total = lastUsage.total ?? promptTokens + output;
|
|
134
|
-
if (promptTokens === 0 && total === 0)
|
|
142
|
+
if (promptTokens === 0 && total === 0) {
|
|
135
143
|
return undefined;
|
|
144
|
+
}
|
|
136
145
|
return { input, output, promptTokens, total, model };
|
|
137
146
|
}
|
|
138
147
|
catch {
|
|
@@ -140,15 +149,17 @@ const readUsageFromSessionLog = (sessionId, sessionEntry) => {
|
|
|
140
149
|
}
|
|
141
150
|
};
|
|
142
151
|
const formatUsagePair = (input, output) => {
|
|
143
|
-
if (input == null && output == null)
|
|
152
|
+
if (input == null && output == null) {
|
|
144
153
|
return null;
|
|
154
|
+
}
|
|
145
155
|
const inputLabel = typeof input === "number" ? formatTokenCount(input) : "?";
|
|
146
156
|
const outputLabel = typeof output === "number" ? formatTokenCount(output) : "?";
|
|
147
157
|
return `🧮 Tokens: ${inputLabel} in / ${outputLabel} out`;
|
|
148
158
|
};
|
|
149
159
|
const formatMediaUnderstandingLine = (decisions) => {
|
|
150
|
-
if (!decisions || decisions.length === 0)
|
|
160
|
+
if (!decisions || decisions.length === 0) {
|
|
151
161
|
return null;
|
|
162
|
+
}
|
|
152
163
|
const parts = decisions
|
|
153
164
|
.map((decision) => {
|
|
154
165
|
const count = decision.attachments.length;
|
|
@@ -179,15 +190,18 @@ const formatMediaUnderstandingLine = (decisions) => {
|
|
|
179
190
|
return null;
|
|
180
191
|
})
|
|
181
192
|
.filter((part) => part != null);
|
|
182
|
-
if (parts.length === 0)
|
|
193
|
+
if (parts.length === 0) {
|
|
183
194
|
return null;
|
|
184
|
-
|
|
195
|
+
}
|
|
196
|
+
if (parts.every((part) => part.endsWith(" none"))) {
|
|
185
197
|
return null;
|
|
198
|
+
}
|
|
186
199
|
return `📎 Media: ${parts.join(" · ")}`;
|
|
187
200
|
};
|
|
188
201
|
const formatVoiceModeLine = (config, sessionEntry) => {
|
|
189
|
-
if (!config)
|
|
202
|
+
if (!config) {
|
|
190
203
|
return null;
|
|
204
|
+
}
|
|
191
205
|
const ttsConfig = resolveTtsConfig(config);
|
|
192
206
|
const prefsPath = resolveTtsPrefsPath(ttsConfig);
|
|
193
207
|
const autoMode = resolveTtsAutoMode({
|
|
@@ -195,8 +209,9 @@ const formatVoiceModeLine = (config, sessionEntry) => {
|
|
|
195
209
|
prefsPath,
|
|
196
210
|
sessionAuto: sessionEntry?.ttsAuto,
|
|
197
211
|
});
|
|
198
|
-
if (autoMode === "off")
|
|
212
|
+
if (autoMode === "off") {
|
|
199
213
|
return null;
|
|
214
|
+
}
|
|
200
215
|
const provider = getTtsProvider(ttsConfig, prefsPath);
|
|
201
216
|
const maxLength = getTtsMaxLength(prefsPath);
|
|
202
217
|
const summarize = isSummarizationEnabled(prefsPath) ? "on" : "off";
|
|
@@ -226,21 +241,24 @@ export function buildStatusMessage(args) {
|
|
|
226
241
|
// Prefer prompt-size tokens from the session transcript when it looks larger
|
|
227
242
|
// (cached prompt tokens are often missing from agent meta/store).
|
|
228
243
|
if (args.includeTranscriptUsage) {
|
|
229
|
-
const logUsage = readUsageFromSessionLog(entry?.sessionId, entry);
|
|
244
|
+
const logUsage = readUsageFromSessionLog(entry?.sessionId, entry, args.agentId, args.sessionKey, args.sessionStorePath);
|
|
230
245
|
if (logUsage) {
|
|
231
246
|
const candidate = logUsage.promptTokens || logUsage.total;
|
|
232
247
|
if (!totalTokens || totalTokens === 0 || candidate > totalTokens) {
|
|
233
248
|
totalTokens = candidate;
|
|
234
249
|
}
|
|
235
|
-
if (!model)
|
|
250
|
+
if (!model) {
|
|
236
251
|
model = logUsage.model ?? model;
|
|
252
|
+
}
|
|
237
253
|
if (!contextTokens && logUsage.model) {
|
|
238
254
|
contextTokens = lookupContextTokens(logUsage.model) ?? contextTokens;
|
|
239
255
|
}
|
|
240
|
-
if (!inputTokens || inputTokens === 0)
|
|
256
|
+
if (!inputTokens || inputTokens === 0) {
|
|
241
257
|
inputTokens = logUsage.input;
|
|
242
|
-
|
|
258
|
+
}
|
|
259
|
+
if (!outputTokens || outputTokens === 0) {
|
|
243
260
|
outputTokens = logUsage.output;
|
|
261
|
+
}
|
|
244
262
|
}
|
|
245
263
|
}
|
|
246
264
|
const thinkLevel = args.resolvedThink ?? args.agent?.thinkingDefault ?? "off";
|
|
@@ -254,7 +272,7 @@ export function buildStatusMessage(args) {
|
|
|
254
272
|
const updatedAt = entry?.updatedAt;
|
|
255
273
|
const sessionLine = [
|
|
256
274
|
`Session: ${args.sessionKey ?? "unknown"}`,
|
|
257
|
-
typeof updatedAt === "number" ? `updated ${
|
|
275
|
+
typeof updatedAt === "number" ? `updated ${formatTimeAgo(now - updatedAt)}` : "no activity",
|
|
258
276
|
]
|
|
259
277
|
.filter(Boolean)
|
|
260
278
|
.join(" • ");
|
|
@@ -317,7 +335,7 @@ export function buildStatusMessage(args) {
|
|
|
317
335
|
const authLabel = authLabelValue ? ` · 🔑 ${authLabelValue}` : "";
|
|
318
336
|
const modelLine = `🧠 Model: ${modelLabel}${authLabel}`;
|
|
319
337
|
const commit = resolveCommitHash();
|
|
320
|
-
const versionLine = `🦞
|
|
338
|
+
const versionLine = `🦞 Pool Bot ${VERSION}${commit ? ` (${commit})` : ""}`;
|
|
321
339
|
const usagePair = formatUsagePair(inputTokens, outputTokens);
|
|
322
340
|
const costLine = costLabel ? `💵 Cost: ${costLabel}` : null;
|
|
323
341
|
const usageCostLine = usagePair && costLine ? `${usagePair} · ${costLine}` : (usagePair ?? costLine);
|
|
@@ -377,10 +395,12 @@ export function buildHelpMessage(cfg) {
|
|
|
377
395
|
lines.push(" /new | /reset | /compact [instructions] | /stop");
|
|
378
396
|
lines.push("");
|
|
379
397
|
const optionParts = ["/think <level>", "/model <id>", "/verbose on|off"];
|
|
380
|
-
if (cfg?.commands?.config === true)
|
|
398
|
+
if (cfg?.commands?.config === true) {
|
|
381
399
|
optionParts.push("/config");
|
|
382
|
-
|
|
400
|
+
}
|
|
401
|
+
if (cfg?.commands?.debug === true) {
|
|
383
402
|
optionParts.push("/debug");
|
|
403
|
+
}
|
|
384
404
|
lines.push("Options");
|
|
385
405
|
lines.push(` ${optionParts.join(" | ")}`);
|
|
386
406
|
lines.push("");
|
|
@@ -405,8 +425,9 @@ function formatCommandEntry(command) {
|
|
|
405
425
|
.filter((alias) => alias.toLowerCase() !== primary.toLowerCase())
|
|
406
426
|
.filter((alias) => {
|
|
407
427
|
const key = alias.toLowerCase();
|
|
408
|
-
if (seen.has(key))
|
|
428
|
+
if (seen.has(key)) {
|
|
409
429
|
return false;
|
|
430
|
+
}
|
|
410
431
|
seen.add(key);
|
|
411
432
|
return true;
|
|
412
433
|
});
|
|
@@ -419,8 +440,9 @@ function buildCommandItems(commands, pluginCommands) {
|
|
|
419
440
|
const items = [];
|
|
420
441
|
for (const category of CATEGORY_ORDER) {
|
|
421
442
|
const categoryCommands = grouped.get(category) ?? [];
|
|
422
|
-
if (categoryCommands.length === 0)
|
|
443
|
+
if (categoryCommands.length === 0) {
|
|
423
444
|
continue;
|
|
445
|
+
}
|
|
424
446
|
const label = CATEGORY_LABELS[category];
|
|
425
447
|
for (const command of categoryCommands) {
|
|
426
448
|
items.push({ label, text: formatCommandEntry(command) });
|
|
@@ -440,8 +462,9 @@ function formatCommandList(items) {
|
|
|
440
462
|
let currentLabel = null;
|
|
441
463
|
for (const item of items) {
|
|
442
464
|
if (item.label !== currentLabel) {
|
|
443
|
-
if (lines.length > 0)
|
|
465
|
+
if (lines.length > 0) {
|
|
444
466
|
lines.push("");
|
|
467
|
+
}
|
|
445
468
|
lines.push(item.label);
|
|
446
469
|
currentLabel = item.label;
|
|
447
470
|
}
|
|
@@ -144,9 +144,9 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
144
144
|
case "Browser.getVersion":
|
|
145
145
|
return {
|
|
146
146
|
protocolVersion: "1.3",
|
|
147
|
-
product: "Chrome/
|
|
147
|
+
product: "Chrome/PoolBot-Extension-Relay",
|
|
148
148
|
revision: "0",
|
|
149
|
-
userAgent: "
|
|
149
|
+
userAgent: "PoolBot-Extension-Relay",
|
|
150
150
|
jsVersion: "V8",
|
|
151
151
|
};
|
|
152
152
|
case "Browser.setDownloadBehavior":
|
|
@@ -240,7 +240,7 @@ export async function ensureChromeExtensionRelayServer(opts) {
|
|
|
240
240
|
if ((path === "/json/version" || path === "/json/version/") &&
|
|
241
241
|
(req.method === "GET" || req.method === "PUT")) {
|
|
242
242
|
const payload = {
|
|
243
|
-
Browser: "
|
|
243
|
+
Browser: "PoolBot/extension-relay",
|
|
244
244
|
"Protocol-Version": "1.3",
|
|
245
245
|
};
|
|
246
246
|
// Only advertise the WS URL if a real extension is connected.
|
|
@@ -39,7 +39,7 @@ export function isAuthorizedBrowserRequest(req, auth) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
if (auth.password) {
|
|
42
|
-
const passwordHeader = firstHeaderValue(req.headers["x-
|
|
42
|
+
const passwordHeader = firstHeaderValue(req.headers["x-poolbot-password"]).trim();
|
|
43
43
|
if (passwordHeader && safeEqualSecret(passwordHeader, auth.password)) {
|
|
44
44
|
return true;
|
|
45
45
|
}
|
package/dist/browser/paths.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
export const DEFAULT_BROWSER_TMP_DIR =
|
|
2
|
+
import { resolvePreferredPoolbotTmpDir } from "../infra/tmp-poolbot-dir.js";
|
|
3
|
+
export const DEFAULT_BROWSER_TMP_DIR = resolvePreferredPoolbotTmpDir();
|
|
4
4
|
export const DEFAULT_TRACE_DIR = DEFAULT_BROWSER_TMP_DIR;
|
|
5
5
|
export const DEFAULT_DOWNLOAD_DIR = path.join(DEFAULT_BROWSER_TMP_DIR, "downloads");
|
|
6
6
|
export const DEFAULT_UPLOAD_DIR = path.join(DEFAULT_BROWSER_TMP_DIR, "uploads");
|
package/dist/build-info.json
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
export function formatAllowlistMatchMeta(match) {
|
|
2
2
|
return `matchKey=${match?.matchKey ?? "none"} matchSource=${match?.matchSource ?? "none"}`;
|
|
3
3
|
}
|
|
4
|
+
export function resolveAllowlistMatchSimple(params) {
|
|
5
|
+
const allowFrom = params.allowFrom
|
|
6
|
+
.map((entry) => String(entry).trim().toLowerCase())
|
|
7
|
+
.filter(Boolean);
|
|
8
|
+
if (allowFrom.length === 0) {
|
|
9
|
+
return { allowed: false };
|
|
10
|
+
}
|
|
11
|
+
if (allowFrom.includes("*")) {
|
|
12
|
+
return { allowed: true, matchKey: "*", matchSource: "wildcard" };
|
|
13
|
+
}
|
|
14
|
+
const senderId = params.senderId.toLowerCase();
|
|
15
|
+
if (allowFrom.includes(senderId)) {
|
|
16
|
+
return { allowed: true, matchKey: senderId, matchSource: "id" };
|
|
17
|
+
}
|
|
18
|
+
const senderName = params.senderName?.toLowerCase();
|
|
19
|
+
if (senderName && allowFrom.includes(senderName)) {
|
|
20
|
+
return { allowed: true, matchKey: senderName, matchSource: "name" };
|
|
21
|
+
}
|
|
22
|
+
return { allowed: false };
|
|
23
|
+
}
|