@poolzin/pool-bot 2026.1.39 → 2026.2.1
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/assets/chrome-extension/README.md +3 -3
- package/assets/chrome-extension/background.js +5 -5
- package/assets/chrome-extension/manifest.json +3 -3
- package/assets/chrome-extension/options.html +4 -4
- package/assets/chrome-extension/options.js +1 -1
- package/dist/acp/client.js +3 -3
- package/dist/acp/types.js +1 -1
- package/dist/agents/agent-paths.js +3 -3
- package/dist/agents/auth-profiles/paths.js +3 -3
- package/dist/agents/bash-tools.exec.js +76 -25
- package/dist/agents/cli-runner/helpers.js +10 -12
- package/dist/agents/cli-runner.js +2 -2
- package/dist/agents/cloudflare-ai-gateway.js +31 -0
- package/dist/agents/compaction.js +16 -2
- package/dist/agents/context-window-guard.js +13 -10
- package/dist/agents/context.js +4 -4
- package/dist/agents/docs-path.js +1 -1
- package/dist/agents/identity.js +47 -7
- package/dist/agents/memory-search.js +25 -8
- package/dist/agents/minimax-vlm.js +1 -1
- package/dist/agents/model-auth.js +12 -1
- package/dist/agents/model-catalog.js +4 -4
- package/dist/agents/model-selection.js +31 -4
- package/dist/agents/models-config.js +3 -3
- package/dist/agents/models-config.providers.js +147 -39
- package/dist/agents/pi-embedded-block-chunker.js +117 -42
- package/dist/agents/pi-embedded-helpers/errors.js +183 -78
- package/dist/agents/pi-embedded-helpers/openai.js +1 -1
- package/dist/agents/pi-embedded-helpers.js +1 -1
- package/dist/agents/pi-embedded-runner/compact.js +9 -8
- package/dist/agents/pi-embedded-runner/model.js +63 -4
- package/dist/agents/pi-embedded-runner/run/attempt.js +27 -17
- package/dist/agents/pi-embedded-runner/run.js +203 -50
- package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
- package/dist/agents/pi-embedded-runner/tool-result-truncation.js +275 -0
- package/dist/agents/pi-embedded-runner/utils.js +1 -1
- package/dist/agents/pi-embedded-subscribe.js +118 -29
- package/dist/agents/pi-model-discovery.js +10 -0
- package/dist/agents/pi-tool-definition-adapter.js +50 -9
- package/dist/agents/pi-tools.before-tool-call.js +67 -0
- package/dist/agents/pi-tools.js +20 -10
- package/dist/agents/pi-tools.read.js +2 -2
- package/dist/agents/poolbot-tools.js +15 -10
- package/dist/agents/sandbox-paths.js +31 -0
- package/dist/agents/session-file-repair.js +83 -0
- package/dist/agents/session-tool-result-guard.js +94 -15
- package/dist/agents/session-transcript-repair.js +68 -0
- package/dist/agents/shell-utils.js +51 -0
- package/dist/agents/skills/bundled-context.js +23 -0
- package/dist/agents/skills/bundled-dir.js +41 -7
- package/dist/agents/skills/frontmatter.js +1 -1
- package/dist/agents/skills/workspace.js +2 -2
- package/dist/agents/skills-install.js +60 -23
- package/dist/agents/subagent-announce.js +79 -34
- package/dist/agents/system-prompt.js +28 -4
- package/dist/agents/together-models.js +127 -0
- package/dist/agents/tool-images.js +1 -1
- package/dist/agents/tool-policy.conformance.js +14 -0
- package/dist/agents/tool-policy.js +25 -1
- package/dist/agents/tools/browser-tool.js +3 -3
- package/dist/agents/tools/cron-tool.js +166 -19
- package/dist/agents/tools/discord-actions-presence.js +78 -0
- package/dist/agents/tools/image-tool.js +2 -2
- package/dist/agents/tools/memory-tool.js +93 -5
- package/dist/agents/tools/message-tool.js +56 -2
- package/dist/agents/tools/sessions-history-tool.js +69 -1
- package/dist/agents/tools/web-search.js +211 -42
- package/dist/agents/usage.js +23 -1
- package/dist/agents/workspace-run.js +67 -0
- package/dist/agents/workspace-templates.js +44 -0
- package/dist/auto-reply/command-auth.js +121 -6
- package/dist/auto-reply/commands-registry.data.js +1 -1
- package/dist/auto-reply/envelope.js +50 -72
- package/dist/auto-reply/reply/commands-compact.js +1 -0
- package/dist/auto-reply/reply/commands-context-report.js +3 -2
- package/dist/auto-reply/reply/commands-context.js +1 -0
- package/dist/auto-reply/reply/commands-models.js +107 -60
- package/dist/auto-reply/reply/commands-ptt.js +171 -0
- package/dist/auto-reply/reply/commands-session.js +2 -2
- package/dist/auto-reply/reply/get-reply-run.js +16 -5
- package/dist/auto-reply/reply/groups.js +1 -1
- package/dist/auto-reply/reply/inbound-context.js +9 -1
- package/dist/auto-reply/reply/inbound-meta.js +130 -0
- package/dist/auto-reply/reply/model-selection.js +3 -3
- package/dist/auto-reply/reply/untrusted-context.js +15 -0
- package/dist/auto-reply/status.js +1 -1
- package/dist/auto-reply/thinking.js +88 -43
- package/dist/browser/bridge-server.js +13 -0
- package/dist/browser/cdp.helpers.js +38 -24
- package/dist/browser/client-fetch.js +51 -8
- package/dist/browser/config.js +2 -11
- package/dist/browser/extension-relay.js +104 -43
- package/dist/browser/pw-ai.js +1 -1
- package/dist/browser/pw-session.js +143 -8
- package/dist/browser/pw-tools-core.interactions.js +125 -27
- package/dist/browser/pw-tools-core.responses.js +1 -1
- package/dist/browser/pw-tools-core.state.js +1 -1
- package/dist/browser/routes/agent.act.js +86 -41
- package/dist/browser/routes/dispatcher.js +4 -4
- package/dist/browser/screenshot.js +1 -1
- package/dist/browser/server-context.js +2 -2
- package/dist/browser/server.js +13 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui.js +3 -3
- package/dist/channels/plugins/catalog.js +2 -2
- package/dist/channels/plugins/onboarding/imessage.js +1 -1
- package/dist/channels/plugins/onboarding/signal.js +1 -1
- package/dist/channels/plugins/onboarding/slack.js +4 -4
- package/dist/channels/plugins/onboarding/whatsapp.js +3 -3
- package/dist/channels/plugins/pairing-message.js +1 -1
- package/dist/channels/reply-prefix.js +8 -1
- package/dist/cli/browser-cli-extension.js +2 -2
- package/dist/cli/cron-cli/register.cron-add.js +61 -40
- package/dist/cli/cron-cli/register.cron-edit.js +60 -34
- package/dist/cli/cron-cli/shared.js +56 -41
- package/dist/cli/dns-cli.js +26 -14
- package/dist/cli/docs-cli.js +1 -1
- package/dist/cli/gateway-cli/dev.js +1 -1
- package/dist/cli/gateway-cli/register.js +37 -19
- package/dist/cli/memory-cli.js +30 -20
- package/dist/cli/nodes-cli/register.canvas.js +1 -1
- package/dist/cli/parse-bytes.js +37 -0
- package/dist/cli/plugins-cli.js +1 -1
- package/dist/cli/run-main.js +2 -2
- package/dist/cli/security-cli.js +1 -1
- package/dist/cli/tagline.js +1 -1
- package/dist/cli/update-cli.js +173 -52
- package/dist/cli/webhooks-cli.js +5 -5
- package/dist/commands/agent.js +1 -0
- package/dist/commands/agents.commands.add.js +1 -1
- package/dist/commands/auth-choice.apply.api-providers.js +305 -17
- package/dist/commands/auth-choice.apply.js +4 -1
- package/dist/commands/auth-choice.apply.plugin-provider.js +2 -2
- package/dist/commands/auth-choice.apply.xai.js +63 -0
- package/dist/commands/auth-choice.preferred-provider.js +7 -1
- package/dist/commands/configure.wizard.js +1 -1
- package/dist/commands/dashboard.js +1 -1
- package/dist/commands/docs.js +1 -1
- package/dist/commands/doctor-config-flow.js +61 -5
- package/dist/commands/doctor-gateway-services.js +3 -3
- package/dist/commands/doctor-state-migrations.js +1 -1
- package/dist/commands/doctor-update.js +3 -3
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/health.js +1 -1
- package/dist/commands/model-allowlist.js +29 -0
- package/dist/commands/model-picker.js +2 -1
- package/dist/commands/models/list.probe.js +2 -2
- package/dist/commands/models/list.registry.js +4 -4
- package/dist/commands/models/list.status-command.js +44 -24
- package/dist/commands/models/shared.js +15 -0
- package/dist/commands/onboard-auth.config-core.js +366 -28
- package/dist/commands/onboard-auth.credentials.js +71 -9
- package/dist/commands/onboard-auth.js +3 -3
- package/dist/commands/onboard-auth.models.js +26 -24
- package/dist/commands/onboard-custom.js +384 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +35 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +146 -9
- package/dist/commands/onboard-skills.js +63 -38
- package/dist/commands/openai-model-default.js +41 -0
- package/dist/commands/status-all/report-lines.js +1 -1
- package/dist/commands/status.command.js +1 -1
- package/dist/commands/uninstall.js +3 -3
- package/dist/compat/legacy-names.js +1 -1
- package/dist/config/defaults.js +3 -2
- package/dist/config/io.js +3 -3
- package/dist/config/paths.js +136 -35
- package/dist/config/plugin-auto-enable.js +21 -5
- package/dist/config/redact-snapshot.js +153 -0
- package/dist/config/schema.field-metadata.js +590 -0
- package/dist/config/schema.js +3 -3
- package/dist/config/sessions/store.js +291 -23
- package/dist/config/types.memory.js +1 -0
- package/dist/config/version.js +4 -4
- package/dist/config/zod-schema.agent-defaults.js +3 -0
- package/dist/config/zod-schema.agent-runtime.js +13 -2
- package/dist/config/zod-schema.providers-core.js +142 -0
- package/dist/config/zod-schema.session.js +3 -0
- package/dist/cron/delivery.js +57 -0
- package/dist/cron/isolated-agent/delivery-target.js +18 -3
- package/dist/cron/isolated-agent/helpers.js +22 -5
- package/dist/cron/isolated-agent/run.js +171 -63
- package/dist/cron/isolated-agent/session.js +2 -0
- package/dist/cron/normalize.js +356 -28
- package/dist/cron/parse.js +10 -5
- package/dist/cron/run-log.js +35 -10
- package/dist/cron/schedule.js +41 -6
- package/dist/cron/service/jobs.js +208 -35
- package/dist/cron/service/ops.js +72 -16
- package/dist/cron/service/state.js +2 -0
- package/dist/cron/service/store.js +386 -14
- package/dist/cron/service/timer.js +390 -147
- package/dist/cron/session-reaper.js +86 -0
- package/dist/cron/store.js +23 -8
- package/dist/cron/validate-timestamp.js +43 -0
- package/dist/daemon/constants.js +7 -7
- package/dist/daemon/inspect.js +6 -6
- package/dist/daemon/systemd-unit.js +1 -1
- package/dist/discord/monitor/agent-components.js +438 -0
- package/dist/discord/monitor/allow-list.js +28 -5
- package/dist/discord/monitor/gateway-registry.js +29 -0
- package/dist/discord/monitor/native-command.js +44 -23
- package/dist/discord/monitor/sender-identity.js +45 -0
- package/dist/discord/pluralkit.js +27 -0
- package/dist/discord/send.outbound.js +92 -5
- package/dist/discord/send.shared.js +60 -23
- package/dist/discord/targets.js +84 -1
- package/dist/entry.js +15 -9
- package/dist/extensionAPI.js +8 -0
- package/dist/gateway/control-ui.js +8 -1
- package/dist/gateway/hooks-mapping.js +3 -0
- package/dist/gateway/hooks.js +65 -0
- package/dist/gateway/live-image-probe.js +1 -66
- package/dist/gateway/net.js +96 -31
- package/dist/gateway/node-command-policy.js +50 -15
- package/dist/gateway/openai-http.js +2 -2
- package/dist/gateway/openresponses-http.js +4 -4
- package/dist/gateway/origin-check.js +56 -0
- package/dist/gateway/protocol/client-info.js +9 -0
- package/dist/gateway/protocol/index.js +9 -2
- package/dist/gateway/protocol/schema/agents-models-skills.js +71 -1
- package/dist/gateway/protocol/schema/cron.js +22 -10
- package/dist/gateway/protocol/schema/protocol-schemas.js +16 -2
- package/dist/gateway/protocol/schema/sessions.js +12 -0
- package/dist/gateway/server/hooks.js +1 -1
- package/dist/gateway/server-broadcast.js +26 -9
- package/dist/gateway/server-chat.js +112 -23
- package/dist/gateway/server-discovery-runtime.js +10 -2
- package/dist/gateway/server-discovery.js +2 -2
- package/dist/gateway/server-http.js +110 -12
- package/dist/gateway/server-methods/agent-timestamp.js +60 -0
- package/dist/gateway/server-methods/agents.js +321 -2
- package/dist/gateway/server-methods/usage.js +559 -16
- package/dist/gateway/server-runtime-state.js +22 -8
- package/dist/gateway/server-startup-memory.js +16 -0
- package/dist/gateway/server.impl.js +7 -3
- package/dist/gateway/session-utils.fs.js +23 -25
- package/dist/gateway/session-utils.js +20 -10
- package/dist/gateway/sessions-patch.js +7 -22
- package/dist/gateway/test-helpers.server.js +35 -2
- package/dist/hooks/frontmatter.js +1 -1
- package/dist/hooks/hooks-status.js +1 -1
- package/dist/hooks/install.js +2 -2
- package/dist/hooks/loader.js +1 -1
- package/dist/hooks/workspace.js +3 -3
- package/dist/imessage/constants.js +2 -0
- package/dist/imessage/monitor/deliver.js +4 -1
- package/dist/imessage/monitor/monitor-provider.js +51 -1
- package/dist/index.js +2 -2
- package/dist/infra/bonjour-discovery.js +131 -70
- package/dist/infra/bonjour.js +3 -3
- package/dist/infra/control-ui-assets.js +134 -12
- package/dist/infra/errors.js +12 -0
- package/dist/infra/exec-approvals.js +266 -57
- package/dist/infra/format-time/format-datetime.js +79 -0
- package/dist/infra/format-time/format-duration.js +81 -0
- package/dist/infra/format-time/format-relative.js +80 -0
- package/dist/infra/heartbeat-runner.js +140 -49
- package/dist/infra/home-dir.js +54 -0
- package/dist/infra/net/fetch-guard.js +122 -0
- package/dist/infra/net/ssrf.js +65 -29
- package/dist/infra/outbound/abort.js +14 -0
- package/dist/infra/outbound/message-action-runner.js +77 -13
- package/dist/infra/outbound/outbound-session.js +143 -37
- package/dist/infra/path-env.js +3 -3
- package/dist/infra/poolbot-root.js +43 -1
- package/dist/infra/provider-usage.fetch.minimax.js +1 -1
- package/dist/infra/restart.js +1 -1
- package/dist/infra/session-cost-usage.js +631 -41
- package/dist/infra/state-migrations.js +317 -47
- package/dist/infra/tailscale.js +1 -1
- package/dist/infra/update-global.js +35 -0
- package/dist/infra/update-runner.js +149 -43
- package/dist/infra/warning-filter.js +65 -0
- package/dist/infra/widearea-dns.js +30 -9
- package/dist/logging/redact-identifier.js +12 -0
- package/dist/macos/relay.js +2 -2
- package/dist/media/fetch.js +81 -58
- package/dist/media/input-files.js +1 -1
- package/dist/media/mime.js +4 -0
- package/dist/media/png-encode.js +74 -0
- package/dist/media-understanding/apply.js +403 -3
- package/dist/media-understanding/attachments.js +38 -27
- package/dist/media-understanding/defaults.js +16 -0
- package/dist/media-understanding/providers/deepgram/audio.js +22 -14
- package/dist/media-understanding/providers/google/audio.js +24 -17
- package/dist/media-understanding/providers/google/video.js +24 -17
- package/dist/media-understanding/providers/image.js +4 -4
- package/dist/media-understanding/providers/index.js +4 -1
- package/dist/media-understanding/providers/openai/audio.js +22 -14
- package/dist/media-understanding/providers/shared.js +16 -11
- package/dist/media-understanding/providers/zai/index.js +6 -0
- package/dist/media-understanding/runner.js +158 -90
- package/dist/memory/backend-config.js +207 -0
- package/dist/memory/batch-voyage.js +277 -0
- package/dist/memory/embeddings-voyage.js +75 -0
- package/dist/memory/embeddings.js +29 -17
- package/dist/memory/internal.js +101 -18
- package/dist/memory/manager.js +155 -48
- package/dist/memory/search-manager.js +173 -0
- package/dist/memory/session-files.js +9 -3
- package/dist/memory/types.js +1 -0
- package/dist/node-host/runner.js +36 -26
- package/dist/node-host/with-timeout.js +27 -0
- package/dist/pairing/pairing-messages.js +1 -1
- package/dist/plugins/commands.js +5 -1
- package/dist/plugins/config-state.js +86 -7
- package/dist/plugins/discovery.js +1 -1
- package/dist/plugins/install.js +2 -2
- package/dist/plugins/source-display.js +51 -0
- package/dist/plugins/update.js +1 -1
- package/dist/process/exec.js +20 -2
- package/dist/routing/resolve-route.js +12 -0
- package/dist/routing/session-key.js +15 -0
- package/dist/runtime.js +2 -0
- package/dist/security/audit-extra.async.js +601 -0
- package/dist/security/audit-extra.js +2 -830
- package/dist/security/audit-extra.sync.js +505 -0
- package/dist/security/audit.js +2 -2
- package/dist/security/channel-metadata.js +34 -0
- package/dist/security/external-content.js +88 -6
- package/dist/security/skill-scanner.js +330 -0
- package/dist/sessions/session-key-utils.js +7 -0
- package/dist/shared/text/reasoning-tags.js +52 -7
- package/dist/signal/monitor/event-handler.js +80 -1
- package/dist/slack/monitor/media.js +85 -15
- package/dist/tailscale/detect.js +145 -0
- package/dist/telegram/bot/helpers.js +109 -28
- package/dist/telegram/bot-handlers.js +144 -3
- package/dist/telegram/bot-message-context.js +38 -11
- package/dist/telegram/bot-message-dispatch.js +48 -15
- package/dist/telegram/bot-native-commands.js +86 -29
- package/dist/telegram/bot.js +30 -29
- package/dist/telegram/model-buttons.js +163 -0
- package/dist/telegram/monitor.js +110 -85
- package/dist/telegram/send.js +129 -47
- package/dist/terminal/restore.js +45 -0
- package/dist/test-helpers/state-dir-env.js +16 -0
- package/dist/test-helpers/workspace.js +11 -0
- package/dist/test-utils/channel-plugins.js +82 -0
- package/dist/test-utils/ports.js +73 -0
- package/dist/tts/tts.js +12 -6
- package/dist/tui/tui-session-actions.js +166 -54
- package/dist/utils/fetch-timeout.js +20 -0
- package/dist/utils/normalize-secret-input.js +19 -0
- package/dist/utils/shell-argv.js +61 -0
- package/dist/utils/transcript-tools.js +58 -0
- package/dist/utils.js +55 -14
- package/dist/version.js +42 -5
- package/dist/web/qr-image.js +1 -61
- package/dist/wizard/onboarding.finalize.js +7 -7
- package/dist/wizard/onboarding.js +3 -3
- package/docs/RELEASE_WORKFOTS_COMPARISON.md +3 -3
- package/docs/_config.yml +2 -2
- package/docs/_layouts/default.html +9 -9
- package/docs/concepts/typebox.md +1 -1
- package/docs/docs.json +1 -1
- package/docs/northflank.mdx +7 -7
- package/docs/railway.mdx +3 -3
- package/docs/render.mdx +5 -5
- package/docs/start/lore.md +2 -2
- package/extensions/bluebubbles/index.ts +2 -2
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/bluebubbles/src/accounts.ts +8 -8
- package/extensions/bluebubbles/src/actions.test.ts +22 -22
- package/extensions/bluebubbles/src/actions.ts +5 -5
- package/extensions/bluebubbles/src/attachments.ts +2 -2
- package/extensions/bluebubbles/src/channel.ts +16 -16
- package/extensions/bluebubbles/src/chat.ts +2 -2
- package/extensions/bluebubbles/src/media-send.ts +2 -2
- package/extensions/bluebubbles/src/monitor.test.ts +46 -46
- package/extensions/bluebubbles/src/monitor.ts +5 -5
- package/extensions/bluebubbles/src/onboarding.ts +7 -7
- package/extensions/bluebubbles/src/reactions.ts +2 -2
- package/extensions/bluebubbles/src/send.ts +2 -2
- package/extensions/copilot-proxy/README.md +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/index.ts +2 -2
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/diagnostics-otel/src/service.ts +3 -3
- package/extensions/discord/index.ts +2 -2
- package/extensions/discord/package.json +1 -1
- package/extensions/google-antigravity-auth/README.md +1 -1
- package/extensions/google-antigravity-auth/index.ts +1 -1
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/README.md +1 -1
- package/extensions/google-gemini-cli-auth/oauth.ts +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/index.ts +3 -3
- package/extensions/googlechat/package.json +1 -1
- package/extensions/googlechat/src/accounts.ts +8 -8
- package/extensions/googlechat/src/actions.ts +6 -6
- package/extensions/googlechat/src/channel.ts +21 -21
- package/extensions/googlechat/src/monitor.ts +8 -8
- package/extensions/googlechat/src/onboarding.ts +10 -10
- package/extensions/imessage/index.ts +2 -2
- package/extensions/imessage/package.json +1 -1
- package/extensions/line/index.ts +2 -2
- package/extensions/line/package.json +1 -1
- package/extensions/line/src/card-command.ts +2 -2
- package/extensions/line/src/channel.logout.test.ts +4 -4
- package/extensions/line/src/channel.sendPayload.test.ts +8 -8
- package/extensions/line/src/channel.ts +3 -3
- package/extensions/llm-task/README.md +3 -3
- package/extensions/llm-task/index.ts +2 -2
- package/extensions/llm-task/package.json +1 -1
- package/extensions/llm-task/src/llm-task-tool.ts +4 -4
- package/extensions/lobster/README.md +6 -6
- package/extensions/lobster/index.ts +2 -2
- package/extensions/lobster/src/lobster-tool.test.ts +4 -4
- package/extensions/lobster/src/lobster-tool.ts +2 -2
- package/extensions/matrix/index.ts +2 -2
- package/extensions/matrix/package.json +1 -1
- package/extensions/matrix/src/matrix/client/config.ts +1 -1
- package/extensions/matrix/src/matrix/monitor/handler.ts +1 -1
- package/extensions/matrix/src/onboarding.ts +1 -1
- package/extensions/mattermost/index.ts +2 -2
- package/extensions/mattermost/package.json +1 -1
- package/extensions/mattermost/src/mattermost/accounts.ts +8 -8
- package/extensions/mattermost/src/mattermost/monitor-helpers.ts +5 -5
- package/extensions/mattermost/src/mattermost/monitor.ts +2 -2
- package/extensions/mattermost/src/onboarding-helpers.ts +3 -3
- package/extensions/mattermost/src/onboarding.ts +2 -2
- package/extensions/memory-core/index.ts +2 -2
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/index.ts +3 -3
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/msteams/index.ts +2 -2
- package/extensions/msteams/package.json +1 -1
- package/extensions/msteams/src/channel.directory.test.ts +2 -2
- package/extensions/msteams/src/channel.ts +2 -2
- package/extensions/msteams/src/graph-upload.ts +4 -4
- package/extensions/msteams/src/monitor-handler.ts +2 -2
- package/extensions/msteams/src/monitor.ts +2 -2
- package/extensions/msteams/src/onboarding.ts +9 -9
- package/extensions/msteams/src/reply-dispatcher.ts +2 -2
- package/extensions/msteams/src/send-context.ts +2 -2
- package/extensions/msteams/src/send.ts +4 -4
- package/extensions/nextcloud-talk/index.ts +2 -2
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nextcloud-talk/src/channel.ts +7 -7
- package/extensions/nextcloud-talk/src/inbound.ts +7 -7
- package/extensions/nextcloud-talk/src/onboarding.ts +1 -1
- package/extensions/nostr/README.md +2 -2
- package/extensions/nostr/index.ts +5 -5
- package/extensions/nostr/package.json +1 -1
- package/extensions/nostr/src/types.ts +4 -4
- package/extensions/open-prose/index.ts +2 -2
- package/extensions/qwen-portal-auth/README.md +1 -1
- package/extensions/signal/index.ts +2 -2
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/index.ts +2 -2
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/index.ts +2 -2
- package/extensions/telegram/package.json +1 -1
- package/extensions/telegram/src/channel.ts +2 -2
- package/extensions/tlon/README.md +2 -2
- package/extensions/tlon/index.ts +2 -2
- package/extensions/tlon/package.json +1 -1
- package/extensions/tlon/src/channel.ts +13 -13
- package/extensions/tlon/src/monitor/index.ts +3 -3
- package/extensions/tlon/src/onboarding.ts +3 -3
- package/extensions/tlon/src/types.ts +3 -3
- package/extensions/twitch/README.md +1 -1
- package/extensions/twitch/index.ts +2 -2
- package/extensions/twitch/package.json +1 -1
- package/extensions/twitch/src/config.ts +3 -3
- package/extensions/twitch/src/monitor.ts +3 -3
- package/extensions/twitch/src/onboarding.ts +9 -9
- package/extensions/twitch/src/outbound.test.ts +2 -2
- package/extensions/twitch/src/plugin.test.ts +2 -2
- package/extensions/twitch/src/plugin.ts +8 -8
- package/extensions/twitch/src/send.test.ts +2 -2
- package/extensions/twitch/src/send.ts +4 -4
- package/extensions/twitch/src/token.test.ts +8 -8
- package/extensions/twitch/src/token.ts +3 -3
- package/extensions/twitch/src/twitch-client.ts +3 -3
- package/extensions/twitch/src/types.ts +3 -3
- package/extensions/twitch/src/utils/markdown.ts +1 -1
- package/extensions/voice-call/README.md +3 -3
- package/extensions/voice-call/package.json +1 -1
- package/extensions/voice-call/src/core-bridge.ts +2 -2
- package/extensions/voice-call/src/response-generator.ts +1 -1
- package/extensions/whatsapp/index.ts +2 -2
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/README.md +1 -1
- package/extensions/zalo/index.ts +2 -2
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalo/src/accounts.ts +8 -8
- package/extensions/zalo/src/actions.ts +4 -4
- package/extensions/zalo/src/channel.directory.test.ts +2 -2
- package/extensions/zalo/src/channel.ts +18 -18
- package/extensions/zalo/src/monitor.ts +9 -9
- package/extensions/zalo/src/monitor.webhook.test.ts +2 -2
- package/extensions/zalo/src/onboarding.ts +24 -24
- package/extensions/zalo/src/send.ts +2 -2
- package/extensions/zalouser/README.md +2 -2
- package/extensions/zalouser/index.ts +2 -2
- package/extensions/zalouser/package.json +1 -1
- package/extensions/zalouser/src/accounts.ts +9 -9
- package/extensions/zalouser/src/channel.ts +24 -24
- package/extensions/zalouser/src/monitor.ts +4 -4
- package/extensions/zalouser/src/onboarding.ts +28 -28
- package/package.json +13 -251
- package/skills/nano-banana-pro/scripts/generate_image.py +1 -1
- package/skills/tmux/scripts/find-sessions.sh +1 -1
- package/CHANGELOG.md +0 -102
- package/README-header.png +0 -0
- package/git-hooks/pre-commit +0 -4
- package/scripts/format-staged.js +0 -148
- package/scripts/postinstall.js +0 -300
- package/scripts/setup-git-hooks.js +0 -96
|
@@ -25,9 +25,17 @@ export function buildEmbeddedSystemPrompt(params) {
|
|
|
25
25
|
userTime: params.userTime,
|
|
26
26
|
userTimeFormat: params.userTimeFormat,
|
|
27
27
|
contextFiles: params.contextFiles,
|
|
28
|
+
memoryCitationsMode: params.memoryCitationsMode,
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
31
|
export function createSystemPromptOverride(systemPrompt) {
|
|
31
|
-
const
|
|
32
|
-
return () =>
|
|
32
|
+
const override = systemPrompt.trim();
|
|
33
|
+
return (_defaultPrompt) => override;
|
|
34
|
+
}
|
|
35
|
+
export function applySystemPromptOverrideToSession(session, override) {
|
|
36
|
+
const prompt = typeof override === "function" ? override() : override.trim();
|
|
37
|
+
session.agent.setSystemPrompt(prompt);
|
|
38
|
+
const mutableSession = session;
|
|
39
|
+
mutableSession._baseSystemPrompt = prompt;
|
|
40
|
+
mutableSession._rebuildSystemPrompt = () => prompt;
|
|
33
41
|
}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { SessionManager } from "@mariozechner/pi-coding-agent";
|
|
2
|
+
import { log } from "./logger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Maximum share of the context window a single tool result should occupy.
|
|
5
|
+
* This is intentionally conservative – a single tool result should not
|
|
6
|
+
* consume more than 30% of the context window even without other messages.
|
|
7
|
+
*/
|
|
8
|
+
const MAX_TOOL_RESULT_CONTEXT_SHARE = 0.3;
|
|
9
|
+
/**
|
|
10
|
+
* Hard character limit for a single tool result text block.
|
|
11
|
+
* Even for the largest context windows (~2M tokens), a single tool result
|
|
12
|
+
* should not exceed ~400K characters (~100K tokens).
|
|
13
|
+
* This acts as a safety net when we don't know the context window size.
|
|
14
|
+
*/
|
|
15
|
+
export const HARD_MAX_TOOL_RESULT_CHARS = 400_000;
|
|
16
|
+
/**
|
|
17
|
+
* Minimum characters to keep when truncating.
|
|
18
|
+
* We always keep at least the first portion so the model understands
|
|
19
|
+
* what was in the content.
|
|
20
|
+
*/
|
|
21
|
+
const MIN_KEEP_CHARS = 2_000;
|
|
22
|
+
/**
|
|
23
|
+
* Suffix appended to truncated tool results.
|
|
24
|
+
*/
|
|
25
|
+
const TRUNCATION_SUFFIX = "\n\n⚠️ [Content truncated — original was too large for the model's context window. " +
|
|
26
|
+
"The content above is a partial view. If you need more, request specific sections or use " +
|
|
27
|
+
"offset/limit parameters to read smaller chunks.]";
|
|
28
|
+
/**
|
|
29
|
+
* Truncate a single text string to fit within maxChars, preserving the beginning.
|
|
30
|
+
*/
|
|
31
|
+
export function truncateToolResultText(text, maxChars) {
|
|
32
|
+
if (text.length <= maxChars) {
|
|
33
|
+
return text;
|
|
34
|
+
}
|
|
35
|
+
const keepChars = Math.max(MIN_KEEP_CHARS, maxChars - TRUNCATION_SUFFIX.length);
|
|
36
|
+
// Try to break at a newline boundary to avoid cutting mid-line
|
|
37
|
+
let cutPoint = keepChars;
|
|
38
|
+
const lastNewline = text.lastIndexOf("\n", keepChars);
|
|
39
|
+
if (lastNewline > keepChars * 0.8) {
|
|
40
|
+
cutPoint = lastNewline;
|
|
41
|
+
}
|
|
42
|
+
return text.slice(0, cutPoint) + TRUNCATION_SUFFIX;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Calculate the maximum allowed characters for a single tool result
|
|
46
|
+
* based on the model's context window tokens.
|
|
47
|
+
*
|
|
48
|
+
* Uses a rough 4 chars ≈ 1 token heuristic (conservative for English text;
|
|
49
|
+
* actual ratio varies by tokenizer).
|
|
50
|
+
*/
|
|
51
|
+
export function calculateMaxToolResultChars(contextWindowTokens) {
|
|
52
|
+
const maxTokens = Math.floor(contextWindowTokens * MAX_TOOL_RESULT_CONTEXT_SHARE);
|
|
53
|
+
// Rough conversion: ~4 chars per token on average
|
|
54
|
+
const maxChars = maxTokens * 4;
|
|
55
|
+
return Math.min(maxChars, HARD_MAX_TOOL_RESULT_CHARS);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get the total character count of text content blocks in a tool result message.
|
|
59
|
+
*/
|
|
60
|
+
function getToolResultTextLength(msg) {
|
|
61
|
+
if (!msg || msg.role !== "toolResult") {
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
const content = msg.content;
|
|
65
|
+
if (!Array.isArray(content)) {
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
let totalLength = 0;
|
|
69
|
+
for (const block of content) {
|
|
70
|
+
if (block && typeof block === "object" && block.type === "text") {
|
|
71
|
+
const text = block.text;
|
|
72
|
+
if (typeof text === "string") {
|
|
73
|
+
totalLength += text.length;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return totalLength;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Truncate a tool result message's text content blocks to fit within maxChars.
|
|
81
|
+
* Returns a new message (does not mutate the original).
|
|
82
|
+
*/
|
|
83
|
+
function truncateToolResultMessage(msg, maxChars) {
|
|
84
|
+
const content = msg.content;
|
|
85
|
+
if (!Array.isArray(content)) {
|
|
86
|
+
return msg;
|
|
87
|
+
}
|
|
88
|
+
// Calculate total text size
|
|
89
|
+
const totalTextChars = getToolResultTextLength(msg);
|
|
90
|
+
if (totalTextChars <= maxChars) {
|
|
91
|
+
return msg;
|
|
92
|
+
}
|
|
93
|
+
// Distribute the budget proportionally among text blocks
|
|
94
|
+
const newContent = content.map((block) => {
|
|
95
|
+
if (!block || typeof block !== "object" || block.type !== "text") {
|
|
96
|
+
return block; // Keep non-text blocks (images) as-is
|
|
97
|
+
}
|
|
98
|
+
const textBlock = block;
|
|
99
|
+
if (typeof textBlock.text !== "string") {
|
|
100
|
+
return block;
|
|
101
|
+
}
|
|
102
|
+
// Proportional budget for this block
|
|
103
|
+
const blockShare = textBlock.text.length / totalTextChars;
|
|
104
|
+
const blockBudget = Math.max(MIN_KEEP_CHARS, Math.floor(maxChars * blockShare));
|
|
105
|
+
return {
|
|
106
|
+
...textBlock,
|
|
107
|
+
text: truncateToolResultText(textBlock.text, blockBudget),
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
return { ...msg, content: newContent };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Find oversized tool result entries in a session and truncate them.
|
|
114
|
+
*
|
|
115
|
+
* This operates on the session file by:
|
|
116
|
+
* 1. Opening the session manager
|
|
117
|
+
* 2. Walking the current branch to find oversized tool results
|
|
118
|
+
* 3. Branching from before the first oversized tool result
|
|
119
|
+
* 4. Re-appending all entries from that point with truncated tool results
|
|
120
|
+
*
|
|
121
|
+
* @returns Object indicating whether any truncation was performed
|
|
122
|
+
*/
|
|
123
|
+
export async function truncateOversizedToolResultsInSession(params) {
|
|
124
|
+
const { sessionFile, contextWindowTokens } = params;
|
|
125
|
+
const maxChars = calculateMaxToolResultChars(contextWindowTokens);
|
|
126
|
+
try {
|
|
127
|
+
const sessionManager = SessionManager.open(sessionFile);
|
|
128
|
+
const branch = sessionManager.getBranch();
|
|
129
|
+
if (branch.length === 0) {
|
|
130
|
+
return { truncated: false, truncatedCount: 0, reason: "empty session" };
|
|
131
|
+
}
|
|
132
|
+
// Find oversized tool result entries and their indices in the branch
|
|
133
|
+
const oversizedIndices = [];
|
|
134
|
+
for (let i = 0; i < branch.length; i++) {
|
|
135
|
+
const entry = branch[i];
|
|
136
|
+
if (entry.type !== "message") {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const msg = entry.message;
|
|
140
|
+
if (msg.role !== "toolResult") {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const textLength = getToolResultTextLength(msg);
|
|
144
|
+
if (textLength > maxChars) {
|
|
145
|
+
oversizedIndices.push(i);
|
|
146
|
+
log.info(`[tool-result-truncation] Found oversized tool result: ` +
|
|
147
|
+
`entry=${entry.id} chars=${textLength} maxChars=${maxChars} ` +
|
|
148
|
+
`sessionKey=${params.sessionKey ?? params.sessionId ?? "unknown"}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (oversizedIndices.length === 0) {
|
|
152
|
+
return { truncated: false, truncatedCount: 0, reason: "no oversized tool results" };
|
|
153
|
+
}
|
|
154
|
+
// Branch from the parent of the first oversized entry
|
|
155
|
+
const firstOversizedIdx = oversizedIndices[0];
|
|
156
|
+
const firstOversizedEntry = branch[firstOversizedIdx];
|
|
157
|
+
const branchFromId = firstOversizedEntry.parentId;
|
|
158
|
+
if (!branchFromId) {
|
|
159
|
+
// The oversized entry is the root - very unusual but handle it
|
|
160
|
+
sessionManager.resetLeaf();
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
sessionManager.branch(branchFromId);
|
|
164
|
+
}
|
|
165
|
+
// Re-append all entries from the first oversized one onwards,
|
|
166
|
+
// with truncated tool results
|
|
167
|
+
const oversizedSet = new Set(oversizedIndices);
|
|
168
|
+
let truncatedCount = 0;
|
|
169
|
+
for (let i = firstOversizedIdx; i < branch.length; i++) {
|
|
170
|
+
const entry = branch[i];
|
|
171
|
+
if (entry.type === "message") {
|
|
172
|
+
let message = entry.message;
|
|
173
|
+
if (oversizedSet.has(i)) {
|
|
174
|
+
message = truncateToolResultMessage(message, maxChars);
|
|
175
|
+
truncatedCount++;
|
|
176
|
+
const newLength = getToolResultTextLength(message);
|
|
177
|
+
log.info(`[tool-result-truncation] Truncated tool result: ` +
|
|
178
|
+
`originalEntry=${entry.id} newChars=${newLength} ` +
|
|
179
|
+
`sessionKey=${params.sessionKey ?? params.sessionId ?? "unknown"}`);
|
|
180
|
+
}
|
|
181
|
+
// appendMessage expects Message | CustomMessage | BashExecutionMessage
|
|
182
|
+
sessionManager.appendMessage(message);
|
|
183
|
+
}
|
|
184
|
+
else if (entry.type === "compaction") {
|
|
185
|
+
sessionManager.appendCompaction(entry.summary, entry.firstKeptEntryId, entry.tokensBefore, entry.details, entry.fromHook);
|
|
186
|
+
}
|
|
187
|
+
else if (entry.type === "thinking_level_change") {
|
|
188
|
+
sessionManager.appendThinkingLevelChange(entry.thinkingLevel);
|
|
189
|
+
}
|
|
190
|
+
else if (entry.type === "model_change") {
|
|
191
|
+
sessionManager.appendModelChange(entry.provider, entry.modelId);
|
|
192
|
+
}
|
|
193
|
+
else if (entry.type === "custom") {
|
|
194
|
+
sessionManager.appendCustomEntry(entry.customType, entry.data);
|
|
195
|
+
}
|
|
196
|
+
else if (entry.type === "custom_message") {
|
|
197
|
+
sessionManager.appendCustomMessageEntry(entry.customType, entry.content, entry.display, entry.details);
|
|
198
|
+
}
|
|
199
|
+
else if (entry.type === "branch_summary") {
|
|
200
|
+
// Branch summaries reference specific entry IDs - skip to avoid inconsistency
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
else if (entry.type === "label") {
|
|
204
|
+
// Labels reference specific entry IDs - skip to avoid inconsistency
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
else if (entry.type === "session_info") {
|
|
208
|
+
if (entry.name) {
|
|
209
|
+
sessionManager.appendSessionInfo(entry.name);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
log.info(`[tool-result-truncation] Truncated ${truncatedCount} tool result(s) in session ` +
|
|
214
|
+
`(contextWindow=${contextWindowTokens} maxChars=${maxChars}) ` +
|
|
215
|
+
`sessionKey=${params.sessionKey ?? params.sessionId ?? "unknown"}`);
|
|
216
|
+
return { truncated: true, truncatedCount };
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
220
|
+
log.warn(`[tool-result-truncation] Failed to truncate: ${errMsg}`);
|
|
221
|
+
return { truncated: false, truncatedCount: 0, reason: errMsg };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Truncate oversized tool results in an array of messages (in-memory).
|
|
226
|
+
* Returns a new array with truncated messages.
|
|
227
|
+
*
|
|
228
|
+
* This is used as a pre-emptive guard before sending messages to the LLM,
|
|
229
|
+
* without modifying the session file.
|
|
230
|
+
*/
|
|
231
|
+
export function truncateOversizedToolResultsInMessages(messages, contextWindowTokens) {
|
|
232
|
+
const maxChars = calculateMaxToolResultChars(contextWindowTokens);
|
|
233
|
+
let truncatedCount = 0;
|
|
234
|
+
const result = messages.map((msg) => {
|
|
235
|
+
if (msg.role !== "toolResult") {
|
|
236
|
+
return msg;
|
|
237
|
+
}
|
|
238
|
+
const textLength = getToolResultTextLength(msg);
|
|
239
|
+
if (textLength <= maxChars) {
|
|
240
|
+
return msg;
|
|
241
|
+
}
|
|
242
|
+
truncatedCount++;
|
|
243
|
+
return truncateToolResultMessage(msg, maxChars);
|
|
244
|
+
});
|
|
245
|
+
return { messages: result, truncatedCount };
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Check if a tool result message exceeds the size limit for a given context window.
|
|
249
|
+
*/
|
|
250
|
+
export function isOversizedToolResult(msg, contextWindowTokens) {
|
|
251
|
+
if (msg.role !== "toolResult") {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
const maxChars = calculateMaxToolResultChars(contextWindowTokens);
|
|
255
|
+
return getToolResultTextLength(msg) > maxChars;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Estimate whether the session likely has oversized tool results that caused
|
|
259
|
+
* a context overflow. Used as a heuristic to decide whether to attempt
|
|
260
|
+
* tool result truncation before giving up.
|
|
261
|
+
*/
|
|
262
|
+
export function sessionLikelyHasOversizedToolResults(params) {
|
|
263
|
+
const { messages, contextWindowTokens } = params;
|
|
264
|
+
const maxChars = calculateMaxToolResultChars(contextWindowTokens);
|
|
265
|
+
for (const msg of messages) {
|
|
266
|
+
if (msg.role !== "toolResult") {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const textLength = getToolResultTextLength(msg);
|
|
270
|
+
if (textLength > maxChars) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
@@ -6,7 +6,8 @@ import { buildCodeSpanIndex, createInlineCodeState } from "../markdown/code-span
|
|
|
6
6
|
import { EmbeddedBlockChunker } from "./pi-embedded-block-chunker.js";
|
|
7
7
|
import { isMessagingToolDuplicateNormalized, normalizeTextForComparison, } from "./pi-embedded-helpers.js";
|
|
8
8
|
import { createEmbeddedPiSessionEventHandler } from "./pi-embedded-subscribe.handlers.js";
|
|
9
|
-
import { formatReasoningMessage } from "./pi-embedded-utils.js";
|
|
9
|
+
import { formatReasoningMessage, stripDowngradedToolCallText } from "./pi-embedded-utils.js";
|
|
10
|
+
import { hasNonzeroUsage, normalizeUsage } from "./usage.js";
|
|
10
11
|
const THINKING_TAG_SCAN_RE = /<\s*(\/?)\s*(?:think(?:ing)?|thought|antthinking)\s*>/gi;
|
|
11
12
|
const FINAL_TAG_SCAN_RE = /<\s*(\/?)\s*final\s*>/gi;
|
|
12
13
|
const log = createSubsystemLogger("agent/embedded");
|
|
@@ -29,7 +30,10 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
29
30
|
blockBuffer: "",
|
|
30
31
|
// Track if a streamed chunk opened a <think> block (stateful across chunks).
|
|
31
32
|
blockState: { thinking: false, final: false, inlineCode: createInlineCodeState() },
|
|
33
|
+
partialBlockState: { thinking: false, final: false, inlineCode: createInlineCodeState() },
|
|
32
34
|
lastStreamedAssistant: undefined,
|
|
35
|
+
lastStreamedAssistantCleaned: undefined,
|
|
36
|
+
emittedAssistantUpdate: false,
|
|
33
37
|
lastStreamedReasoning: undefined,
|
|
34
38
|
lastBlockReplyText: undefined,
|
|
35
39
|
assistantMessageIndex: 0,
|
|
@@ -49,6 +53,14 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
49
53
|
pendingMessagingTexts: new Map(),
|
|
50
54
|
pendingMessagingTargets: new Map(),
|
|
51
55
|
};
|
|
56
|
+
const usageTotals = {
|
|
57
|
+
input: 0,
|
|
58
|
+
output: 0,
|
|
59
|
+
cacheRead: 0,
|
|
60
|
+
cacheWrite: 0,
|
|
61
|
+
total: 0,
|
|
62
|
+
};
|
|
63
|
+
let compactionCount = 0;
|
|
52
64
|
const assistantTexts = state.assistantTexts;
|
|
53
65
|
const toolMetas = state.toolMetas;
|
|
54
66
|
const toolMetaById = state.toolMetaById;
|
|
@@ -59,15 +71,22 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
59
71
|
const pendingMessagingTexts = state.pendingMessagingTexts;
|
|
60
72
|
const pendingMessagingTargets = state.pendingMessagingTargets;
|
|
61
73
|
const replyDirectiveAccumulator = createStreamingDirectiveAccumulator();
|
|
74
|
+
const partialReplyDirectiveAccumulator = createStreamingDirectiveAccumulator();
|
|
62
75
|
const resetAssistantMessageState = (nextAssistantTextBaseline) => {
|
|
63
76
|
state.deltaBuffer = "";
|
|
64
77
|
state.blockBuffer = "";
|
|
65
78
|
blockChunker?.reset();
|
|
66
79
|
replyDirectiveAccumulator.reset();
|
|
80
|
+
partialReplyDirectiveAccumulator.reset();
|
|
67
81
|
state.blockState.thinking = false;
|
|
68
82
|
state.blockState.final = false;
|
|
69
83
|
state.blockState.inlineCode = createInlineCodeState();
|
|
84
|
+
state.partialBlockState.thinking = false;
|
|
85
|
+
state.partialBlockState.final = false;
|
|
86
|
+
state.partialBlockState.inlineCode = createInlineCodeState();
|
|
70
87
|
state.lastStreamedAssistant = undefined;
|
|
88
|
+
state.lastStreamedAssistantCleaned = undefined;
|
|
89
|
+
state.emittedAssistantUpdate = false;
|
|
71
90
|
state.lastBlockReplyText = undefined;
|
|
72
91
|
state.lastStreamedReasoning = undefined;
|
|
73
92
|
state.lastReasoningSent = undefined;
|
|
@@ -85,21 +104,26 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
85
104
|
state.lastAssistantTextNormalized = normalized.length > 0 ? normalized : undefined;
|
|
86
105
|
};
|
|
87
106
|
const shouldSkipAssistantText = (text) => {
|
|
88
|
-
if (state.lastAssistantTextMessageIndex !== state.assistantMessageIndex)
|
|
107
|
+
if (state.lastAssistantTextMessageIndex !== state.assistantMessageIndex) {
|
|
89
108
|
return false;
|
|
109
|
+
}
|
|
90
110
|
const trimmed = text.trimEnd();
|
|
91
|
-
if (trimmed && trimmed === state.lastAssistantTextTrimmed)
|
|
111
|
+
if (trimmed && trimmed === state.lastAssistantTextTrimmed) {
|
|
92
112
|
return true;
|
|
113
|
+
}
|
|
93
114
|
const normalized = normalizeTextForComparison(text);
|
|
94
|
-
if (normalized.length > 0 && normalized === state.lastAssistantTextNormalized)
|
|
115
|
+
if (normalized.length > 0 && normalized === state.lastAssistantTextNormalized) {
|
|
95
116
|
return true;
|
|
117
|
+
}
|
|
96
118
|
return false;
|
|
97
119
|
};
|
|
98
120
|
const pushAssistantText = (text) => {
|
|
99
|
-
if (!text)
|
|
121
|
+
if (!text) {
|
|
100
122
|
return;
|
|
101
|
-
|
|
123
|
+
}
|
|
124
|
+
if (shouldSkipAssistantText(text)) {
|
|
102
125
|
return;
|
|
126
|
+
}
|
|
103
127
|
assistantTexts.push(text);
|
|
104
128
|
rememberAssistantText(text);
|
|
105
129
|
};
|
|
@@ -154,8 +178,9 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
154
178
|
ensureCompactionPromise();
|
|
155
179
|
};
|
|
156
180
|
const resolveCompactionRetry = () => {
|
|
157
|
-
if (state.pendingCompactionRetry <= 0)
|
|
181
|
+
if (state.pendingCompactionRetry <= 0) {
|
|
158
182
|
return;
|
|
183
|
+
}
|
|
159
184
|
state.pendingCompactionRetry -= 1;
|
|
160
185
|
if (state.pendingCompactionRetry === 0 && !state.compactionInFlight) {
|
|
161
186
|
state.compactionRetryResolve?.();
|
|
@@ -170,6 +195,40 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
170
195
|
state.compactionRetryPromise = null;
|
|
171
196
|
}
|
|
172
197
|
};
|
|
198
|
+
const recordAssistantUsage = (usageLike) => {
|
|
199
|
+
const usage = normalizeUsage((usageLike ?? undefined));
|
|
200
|
+
if (!hasNonzeroUsage(usage)) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
usageTotals.input += usage.input ?? 0;
|
|
204
|
+
usageTotals.output += usage.output ?? 0;
|
|
205
|
+
usageTotals.cacheRead += usage.cacheRead ?? 0;
|
|
206
|
+
usageTotals.cacheWrite += usage.cacheWrite ?? 0;
|
|
207
|
+
const usageTotal = usage.total ??
|
|
208
|
+
(usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
|
|
209
|
+
usageTotals.total += usageTotal;
|
|
210
|
+
};
|
|
211
|
+
const getUsageTotals = () => {
|
|
212
|
+
const hasUsage = usageTotals.input > 0 ||
|
|
213
|
+
usageTotals.output > 0 ||
|
|
214
|
+
usageTotals.cacheRead > 0 ||
|
|
215
|
+
usageTotals.cacheWrite > 0 ||
|
|
216
|
+
usageTotals.total > 0;
|
|
217
|
+
if (!hasUsage) {
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
const derivedTotal = usageTotals.input + usageTotals.output + usageTotals.cacheRead + usageTotals.cacheWrite;
|
|
221
|
+
return {
|
|
222
|
+
input: usageTotals.input || undefined,
|
|
223
|
+
output: usageTotals.output || undefined,
|
|
224
|
+
cacheRead: usageTotals.cacheRead || undefined,
|
|
225
|
+
cacheWrite: usageTotals.cacheWrite || undefined,
|
|
226
|
+
total: usageTotals.total || derivedTotal || undefined,
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
const incrementCompactionCount = () => {
|
|
230
|
+
compactionCount += 1;
|
|
231
|
+
};
|
|
173
232
|
const blockChunking = params.blockReplyChunking;
|
|
174
233
|
const blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : null;
|
|
175
234
|
// KNOWN: Provider streams are not strictly once-only or perfectly ordered.
|
|
@@ -183,21 +242,25 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
183
242
|
: params.verboseLevel === "full";
|
|
184
243
|
const formatToolOutputBlock = (text) => {
|
|
185
244
|
const trimmed = text.trim();
|
|
186
|
-
if (!trimmed)
|
|
245
|
+
if (!trimmed) {
|
|
187
246
|
return "(no output)";
|
|
188
|
-
|
|
247
|
+
}
|
|
248
|
+
if (!useMarkdown) {
|
|
189
249
|
return trimmed;
|
|
250
|
+
}
|
|
190
251
|
return `\`\`\`txt\n${trimmed}\n\`\`\``;
|
|
191
252
|
};
|
|
192
253
|
const emitToolSummary = (toolName, meta) => {
|
|
193
|
-
if (!params.onToolResult)
|
|
254
|
+
if (!params.onToolResult) {
|
|
194
255
|
return;
|
|
256
|
+
}
|
|
195
257
|
const agg = formatToolAggregate(toolName, meta ? [meta] : undefined, {
|
|
196
258
|
markdown: useMarkdown,
|
|
197
259
|
});
|
|
198
260
|
const { text: cleanedText, mediaUrls } = parseReplyDirectives(agg);
|
|
199
|
-
if (!cleanedText && (!mediaUrls || mediaUrls.length === 0))
|
|
261
|
+
if (!cleanedText && (!mediaUrls || mediaUrls.length === 0)) {
|
|
200
262
|
return;
|
|
263
|
+
}
|
|
201
264
|
try {
|
|
202
265
|
void params.onToolResult({
|
|
203
266
|
text: cleanedText,
|
|
@@ -209,15 +272,17 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
209
272
|
}
|
|
210
273
|
};
|
|
211
274
|
const emitToolOutput = (toolName, meta, output) => {
|
|
212
|
-
if (!params.onToolResult || !output)
|
|
275
|
+
if (!params.onToolResult || !output) {
|
|
213
276
|
return;
|
|
277
|
+
}
|
|
214
278
|
const agg = formatToolAggregate(toolName, meta ? [meta] : undefined, {
|
|
215
279
|
markdown: useMarkdown,
|
|
216
280
|
});
|
|
217
281
|
const message = `${agg}\n${formatToolOutputBlock(output)}`;
|
|
218
282
|
const { text: cleanedText, mediaUrls } = parseReplyDirectives(message);
|
|
219
|
-
if (!cleanedText && (!mediaUrls || mediaUrls.length === 0))
|
|
283
|
+
if (!cleanedText && (!mediaUrls || mediaUrls.length === 0)) {
|
|
220
284
|
return;
|
|
285
|
+
}
|
|
221
286
|
try {
|
|
222
287
|
void params.onToolResult({
|
|
223
288
|
text: cleanedText,
|
|
@@ -229,8 +294,9 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
229
294
|
}
|
|
230
295
|
};
|
|
231
296
|
const stripBlockTags = (text, state) => {
|
|
232
|
-
if (!text)
|
|
297
|
+
if (!text) {
|
|
233
298
|
return text;
|
|
299
|
+
}
|
|
234
300
|
const inlineStateStart = state.inlineCode ?? createInlineCodeState();
|
|
235
301
|
const codeSpans = buildCodeSpanIndex(text, inlineStateStart);
|
|
236
302
|
// 1. Handle <think> blocks (stateful, strip content inside)
|
|
@@ -240,8 +306,9 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
240
306
|
let inThinking = state.thinking;
|
|
241
307
|
for (const match of text.matchAll(THINKING_TAG_SCAN_RE)) {
|
|
242
308
|
const idx = match.index ?? 0;
|
|
243
|
-
if (codeSpans.isInside(idx))
|
|
309
|
+
if (codeSpans.isInside(idx)) {
|
|
244
310
|
continue;
|
|
311
|
+
}
|
|
245
312
|
if (!inThinking) {
|
|
246
313
|
processed += text.slice(lastIndex, idx);
|
|
247
314
|
}
|
|
@@ -271,8 +338,9 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
271
338
|
let everInFinal = state.final;
|
|
272
339
|
for (const match of processed.matchAll(FINAL_TAG_SCAN_RE)) {
|
|
273
340
|
const idx = match.index ?? 0;
|
|
274
|
-
if (finalCodeSpans.isInside(idx))
|
|
341
|
+
if (finalCodeSpans.isInside(idx)) {
|
|
275
342
|
continue;
|
|
343
|
+
}
|
|
276
344
|
const isClose = match[1] === "/";
|
|
277
345
|
if (!inFinal && !isClose) {
|
|
278
346
|
// Found <final> start tag.
|
|
@@ -309,8 +377,9 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
309
377
|
pattern.lastIndex = 0;
|
|
310
378
|
for (const match of text.matchAll(pattern)) {
|
|
311
379
|
const idx = match.index ?? 0;
|
|
312
|
-
if (isInside(idx))
|
|
380
|
+
if (isInside(idx)) {
|
|
313
381
|
continue;
|
|
382
|
+
}
|
|
314
383
|
output += text.slice(lastIndex, idx);
|
|
315
384
|
lastIndex = idx + match[0].length;
|
|
316
385
|
}
|
|
@@ -318,14 +387,18 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
318
387
|
return output;
|
|
319
388
|
};
|
|
320
389
|
const emitBlockChunk = (text) => {
|
|
321
|
-
if (state.suppressBlockChunks)
|
|
390
|
+
if (state.suppressBlockChunks) {
|
|
322
391
|
return;
|
|
392
|
+
}
|
|
323
393
|
// Strip <think> and <final> blocks across chunk boundaries to avoid leaking reasoning.
|
|
324
|
-
|
|
325
|
-
|
|
394
|
+
// Also strip downgraded tool call text ([Tool Call: ...], [Historical context: ...], etc.).
|
|
395
|
+
const chunk = stripDowngradedToolCallText(stripBlockTags(text, state.blockState)).trimEnd();
|
|
396
|
+
if (!chunk) {
|
|
326
397
|
return;
|
|
327
|
-
|
|
398
|
+
}
|
|
399
|
+
if (chunk === state.lastBlockReplyText) {
|
|
328
400
|
return;
|
|
401
|
+
}
|
|
329
402
|
// Only check committed (successful) messaging tool texts - checking pending texts
|
|
330
403
|
// is risky because if the tool fails after suppression, the user gets no response
|
|
331
404
|
const normalizedChunk = normalizeTextForComparison(chunk);
|
|
@@ -333,20 +406,24 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
333
406
|
log.debug(`Skipping block reply - already sent via messaging tool: ${chunk.slice(0, 50)}...`);
|
|
334
407
|
return;
|
|
335
408
|
}
|
|
336
|
-
if (shouldSkipAssistantText(chunk))
|
|
409
|
+
if (shouldSkipAssistantText(chunk)) {
|
|
337
410
|
return;
|
|
411
|
+
}
|
|
338
412
|
state.lastBlockReplyText = chunk;
|
|
339
413
|
assistantTexts.push(chunk);
|
|
340
414
|
rememberAssistantText(chunk);
|
|
341
|
-
if (!params.onBlockReply)
|
|
415
|
+
if (!params.onBlockReply) {
|
|
342
416
|
return;
|
|
417
|
+
}
|
|
343
418
|
const splitResult = replyDirectiveAccumulator.consume(chunk);
|
|
344
|
-
if (!splitResult)
|
|
419
|
+
if (!splitResult) {
|
|
345
420
|
return;
|
|
421
|
+
}
|
|
346
422
|
const { text: cleanedText, mediaUrls, audioAsVoice, replyToId, replyToTag, replyToCurrent, } = splitResult;
|
|
347
423
|
// Skip empty payloads, but always emit if audioAsVoice is set (to propagate the flag)
|
|
348
|
-
if (!cleanedText && (!mediaUrls || mediaUrls.length === 0) && !audioAsVoice)
|
|
424
|
+
if (!cleanedText && (!mediaUrls || mediaUrls.length === 0) && !audioAsVoice) {
|
|
349
425
|
return;
|
|
426
|
+
}
|
|
350
427
|
void params.onBlockReply({
|
|
351
428
|
text: cleanedText,
|
|
352
429
|
mediaUrls: mediaUrls?.length ? mediaUrls : undefined,
|
|
@@ -357,9 +434,11 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
357
434
|
});
|
|
358
435
|
};
|
|
359
436
|
const consumeReplyDirectives = (text, options) => replyDirectiveAccumulator.consume(text, options);
|
|
437
|
+
const consumePartialReplyDirectives = (text, options) => partialReplyDirectiveAccumulator.consume(text, options);
|
|
360
438
|
const flushBlockReplyBuffer = () => {
|
|
361
|
-
if (!params.onBlockReply)
|
|
439
|
+
if (!params.onBlockReply) {
|
|
362
440
|
return;
|
|
441
|
+
}
|
|
363
442
|
if (blockChunker?.hasBuffered()) {
|
|
364
443
|
blockChunker.drain({ force: true, emit: emitBlockChunk });
|
|
365
444
|
blockChunker.reset();
|
|
@@ -371,13 +450,16 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
371
450
|
}
|
|
372
451
|
};
|
|
373
452
|
const emitReasoningStream = (text) => {
|
|
374
|
-
if (!state.streamReasoning || !params.onReasoningStream)
|
|
453
|
+
if (!state.streamReasoning || !params.onReasoningStream) {
|
|
375
454
|
return;
|
|
455
|
+
}
|
|
376
456
|
const formatted = formatReasoningMessage(text);
|
|
377
|
-
if (!formatted)
|
|
457
|
+
if (!formatted) {
|
|
378
458
|
return;
|
|
379
|
-
|
|
459
|
+
}
|
|
460
|
+
if (formatted === state.lastStreamedReasoning) {
|
|
380
461
|
return;
|
|
462
|
+
}
|
|
381
463
|
state.lastStreamedReasoning = formatted;
|
|
382
464
|
void params.onReasoningStream({
|
|
383
465
|
text: formatted,
|
|
@@ -411,6 +493,7 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
411
493
|
flushBlockReplyBuffer,
|
|
412
494
|
emitReasoningStream,
|
|
413
495
|
consumeReplyDirectives,
|
|
496
|
+
consumePartialReplyDirectives,
|
|
414
497
|
resetAssistantMessageState,
|
|
415
498
|
resetForCompactionRetry,
|
|
416
499
|
finalizeAssistantTexts,
|
|
@@ -419,6 +502,10 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
419
502
|
noteCompactionRetry,
|
|
420
503
|
resolveCompactionRetry,
|
|
421
504
|
maybeResolveCompactionWait,
|
|
505
|
+
recordAssistantUsage,
|
|
506
|
+
incrementCompactionCount,
|
|
507
|
+
getUsageTotals,
|
|
508
|
+
getCompactionCount: () => compactionCount,
|
|
422
509
|
};
|
|
423
510
|
const unsubscribe = params.session.subscribe(createEmbeddedPiSessionEventHandler(ctx));
|
|
424
511
|
return {
|
|
@@ -433,6 +520,8 @@ export function subscribeEmbeddedPiSession(params) {
|
|
|
433
520
|
// which is generated AFTER the tool sends the actual answer.
|
|
434
521
|
didSendViaMessagingTool: () => messagingToolSentTexts.length > 0,
|
|
435
522
|
getLastToolError: () => (state.lastToolError ? { ...state.lastToolError } : undefined),
|
|
523
|
+
getUsageTotals,
|
|
524
|
+
getCompactionCount: () => compactionCount,
|
|
436
525
|
waitForCompactionRetry: () => {
|
|
437
526
|
if (state.compactionInFlight || state.pendingCompactionRetry > 0) {
|
|
438
527
|
ensureCompactionPromise();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
|
|
4
|
+
// Compatibility helpers for pi-coding-agent 0.50+ (discover* helpers removed).
|
|
5
|
+
export function discoverAuthStorage(agentDir) {
|
|
6
|
+
return new AuthStorage(path.join(agentDir, "auth.json"));
|
|
7
|
+
}
|
|
8
|
+
export function discoverModels(authStorage, agentDir) {
|
|
9
|
+
return new ModelRegistry(authStorage, path.join(agentDir, "models.json"));
|
|
10
|
+
}
|