@vellumai/assistant 0.11.2 → 0.11.3-staging.2
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/ARCHITECTURE.md +58 -3
- package/docs/trusted-contact-access.md +9 -5
- package/docs/vellum-doctor.md +195 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +19 -2
- package/node_modules/@vellumai/environments/package.json +2 -1
- package/node_modules/@vellumai/environments/src/__tests__/cloud-assistant-hub-url.test.ts +38 -0
- package/node_modules/@vellumai/environments/src/__tests__/install-layout.test.ts +98 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +5 -5
- package/node_modules/@vellumai/environments/src/index.ts +17 -6
- package/node_modules/@vellumai/environments/src/install-layout.ts +49 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +29 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +4 -0
- package/node_modules/@vellumai/gateway-client/src/verification-session-contract.ts +91 -6
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.test.ts +36 -0
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.ts +142 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +2 -0
- package/node_modules/@vellumai/ipc-server-utils/src/listen-options.ts +3 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +15 -1
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +17 -2
- package/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +16 -2
- package/openapi.yaml +589 -30
- package/package.json +1 -1
- package/src/__tests__/agent-image-optimize.test.ts +4 -4
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +113 -66
- package/src/__tests__/agent-loop-override-profile.test.ts +38 -48
- package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +166 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/answered-question-persistence.test.ts +240 -0
- package/src/__tests__/anthropic-provider.test.ts +165 -30
- package/src/__tests__/app-control-flow.test.ts +9 -8
- package/src/__tests__/assistant-event-hub.test.ts +48 -0
- package/src/__tests__/attachments-store-heic-normalize.test.ts +16 -12
- package/src/__tests__/attachments-store.test.ts +130 -68
- package/src/__tests__/attachments.test.ts +36 -36
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
- package/src/__tests__/call-start-guardian-guard.test.ts +18 -4
- package/src/__tests__/canned-reply-release.test.ts +86 -0
- package/src/__tests__/channel-guardian.test.ts +59 -29
- package/src/__tests__/channel-readiness-telegram-remote.test.ts +154 -0
- package/src/__tests__/channel-setup-panel-ack.test.ts +6 -5
- package/src/__tests__/client-os-metadata-persistence.test.ts +103 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
- package/src/__tests__/consult-deadline.test.ts +65 -0
- package/src/__tests__/conversation-agent-loop.test.ts +438 -2
- package/src/__tests__/conversation-disk-view-integration.test.ts +5 -1
- package/src/__tests__/conversation-disk-view.test.ts +4 -4
- package/src/__tests__/conversation-error.test.ts +22 -3
- package/src/__tests__/conversation-fork-crud.test.ts +5 -1
- package/src/__tests__/conversation-fork-referential.test.ts +352 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +5 -1
- package/src/__tests__/conversation-group-tools.test.ts +32 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +27 -1
- package/src/__tests__/conversation-initial-prompt.test.ts +51 -22
- package/src/__tests__/conversation-key-store-bootstrap-cleanup.test.ts +119 -0
- package/src/__tests__/conversation-key-store-origin.test.ts +105 -0
- package/src/__tests__/conversation-list-recency-ordering.test.ts +104 -0
- package/src/__tests__/conversation-origin-at-creation.test.ts +153 -0
- package/src/__tests__/conversation-origin-channel-filter.test.ts +95 -0
- package/src/__tests__/conversation-placement-promotion.test.ts +172 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +123 -0
- package/src/__tests__/conversation-queue.test.ts +433 -1
- package/src/__tests__/conversation-retry-route.test.ts +3 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +64 -1
- package/src/__tests__/conversation-store-ephemeral.test.ts +4 -0
- package/src/__tests__/conversation-store.test.ts +26 -10
- package/src/__tests__/conversation-summarize-route.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +15 -6
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-app-control.test.ts +12 -11
- package/src/__tests__/conversation-surfaces-app-open.test.ts +11 -5
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +5 -4
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +967 -0
- package/src/__tests__/conversation-surfaces-persisted-info.test.ts +312 -0
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -8
- package/src/__tests__/conversation-surfaces-standalone.test.ts +21 -11
- package/src/__tests__/conversation-surfaces-state-update.test.ts +7 -11
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -6
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +11 -6
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -6
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +70 -7
- package/src/__tests__/conversation-wait-for-idle.test.ts +6 -11
- package/src/__tests__/credential-prompt-route.test.ts +57 -7
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +89 -28
- package/src/__tests__/custom-group-listing-visibility.test.ts +1 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +4 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +366 -0
- package/src/__tests__/discord-requester-notice-privacy.test.ts +87 -0
- package/src/__tests__/disk-pressure-guard.test.ts +55 -55
- package/src/__tests__/disk-pressure-routes.test.ts +10 -10
- package/src/__tests__/disk-pressure-tools.test.ts +2 -2
- package/src/__tests__/disk-usage.test.ts +35 -20
- package/src/__tests__/document-sync-tags.test.ts +379 -0
- package/src/__tests__/document-update-default-surface.test.ts +28 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +2 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -4
- package/src/__tests__/ensure-conversation-exists.test.ts +8 -5
- package/src/__tests__/events-dev-bypass-actor.test.ts +183 -1
- package/src/__tests__/evict-conversations-for-reload.test.ts +90 -0
- package/src/__tests__/file-list-tool.test.ts +12 -10
- package/src/__tests__/file-ops-service.test.ts +151 -44
- package/src/__tests__/file-read-container-boundary.test.ts +137 -0
- package/src/__tests__/file-read-tool.test.ts +21 -9
- package/src/__tests__/file-url-path-guard.test.ts +83 -0
- package/src/__tests__/filesystem-tools.test.ts +82 -66
- package/src/__tests__/guardian-outbound-http.test.ts +8 -8
- package/src/__tests__/helpers/gateway-verification-sessions-stub.ts +14 -1
- package/src/__tests__/helpers/hub-clients.ts +42 -0
- package/src/__tests__/helpers/mock-conversation.ts +46 -0
- package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +61 -57
- package/src/__tests__/history-repair.test.ts +112 -12
- package/src/__tests__/host-bash-proxy.test.ts +10 -5
- package/src/__tests__/host-bash-routes.test.ts +67 -0
- package/src/__tests__/host-browser-proxy.test.ts +2 -2
- package/src/__tests__/host-cu-proxy.test.ts +3 -7
- package/src/__tests__/host-file-proxy.test.ts +3 -7
- package/src/__tests__/host-file-read-tool.test.ts +5 -1
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +6 -4
- package/src/__tests__/http-conversation-lineage.test.ts +2 -5
- package/src/__tests__/http-user-message-parity.test.ts +44 -0
- package/src/__tests__/identity-routes.test.ts +13 -13
- package/src/__tests__/image-conversion.test.ts +29 -26
- package/src/__tests__/image-source-path-reinject.test.ts +2 -2
- package/src/__tests__/inference-profile-session-handler.test.ts +95 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +25 -0
- package/src/__tests__/introduction-card-resolver.test.ts +6 -1
- package/src/__tests__/list-messages-attachments.test.ts +56 -32
- package/src/__tests__/list-messages-background-tool-completion.test.ts +4 -4
- package/src/__tests__/list-messages-client-message-id.test.ts +2 -2
- package/src/__tests__/list-messages-hidden-metadata.test.ts +16 -16
- package/src/__tests__/list-messages-page-latest.test.ts +61 -61
- package/src/__tests__/list-messages-provider-error.test.ts +6 -6
- package/src/__tests__/list-messages-queued.test.ts +49 -6
- package/src/__tests__/list-messages-system-card.test.ts +4 -4
- package/src/__tests__/list-messages-tool-merge.test.ts +9 -9
- package/src/__tests__/llm-resolver-override-or-default.test.ts +141 -0
- package/src/__tests__/llm-usage-store.test.ts +55 -0
- package/src/__tests__/manual-token-reconciliation.test.ts +45 -0
- package/src/__tests__/mcp-tool-annotations-risk.test.ts +133 -0
- package/src/__tests__/media-stream-server-integration.test.ts +36 -0
- package/src/__tests__/migration-export-http.test.ts +1 -1
- package/src/__tests__/migration-import-commit-http.test.ts +1 -1
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -1
- package/src/__tests__/migration-validate-http.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +65 -3
- package/src/__tests__/notification-platform-adapter.test.ts +104 -0
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +4 -2
- package/src/__tests__/oauth-provider-seed-logos.test.ts +65 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +17 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/openai-responses-prompt-cache.test.ts +5 -2
- package/src/__tests__/path-policy.test.ts +164 -1
- package/src/__tests__/persist-media-references.test.ts +2 -2
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +5 -5
- package/src/__tests__/persist-unsendable-image.test.ts +23 -23
- package/src/__tests__/persona-resolver.test.ts +154 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +170 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +6 -0
- package/src/__tests__/processing-flag-persist-failure.test.ts +15 -10
- package/src/__tests__/profile-availability-incomplete.test.ts +113 -0
- package/src/__tests__/profiler-routes.test.ts +13 -13
- package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +593 -0
- package/src/__tests__/proxy-approval-callback.test.ts +3 -3
- package/src/__tests__/queued-message-cancel-and-steer.test.ts +189 -0
- package/src/__tests__/queued-message-steer-actor-scoping.test.ts +164 -0
- package/src/__tests__/resolve-trust-class.test.ts +20 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +1 -1
- package/src/__tests__/run-due-schedules.test.ts +174 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +15 -7
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +166 -0
- package/src/__tests__/schedule-routes.test.ts +730 -8
- package/src/__tests__/schedule-store.test.ts +540 -0
- package/src/__tests__/schedule-tools.test.ts +103 -0
- package/src/__tests__/scheduler-wake.test.ts +5 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +29 -1
- package/src/__tests__/secure-keys.test.ts +91 -0
- package/src/__tests__/server-history-render.test.ts +97 -7
- package/src/__tests__/size-guard.test.ts +8 -8
- package/src/__tests__/skill-docs-sync-guard.test.ts +3 -2
- package/src/__tests__/skill-tool-factory.test.ts +247 -0
- package/src/__tests__/skills-install-staging.test.ts +15 -6
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +103 -0
- package/src/__tests__/slack-inbound-verification.test.ts +4 -1
- package/src/__tests__/slack-mention-binding-invariance.test.ts +103 -0
- package/src/__tests__/slack-mention-provider-leak-audit.test.ts +135 -0
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/steer-on-enqueue-question.test.ts +3 -2
- package/src/__tests__/stt-language-catalog-parity.test.ts +38 -0
- package/src/__tests__/subagent-allowlist-validation.test.ts +26 -4
- package/src/__tests__/subagent-cron-run-attribution.test.ts +301 -0
- package/src/__tests__/subagent-disposal.test.ts +10 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +10 -0
- package/src/__tests__/subagent-fork-prompt-role.test.ts +85 -11
- package/src/__tests__/subagent-fork-spawn.test.ts +15 -7
- package/src/__tests__/subagent-manager-notify.test.ts +148 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/subagent-persistence.test.ts +141 -0
- package/src/__tests__/subagent-role-registry.test.ts +172 -63
- package/src/__tests__/subagent-role-resolution.test.ts +88 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +48 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +111 -10
- package/src/__tests__/subagent-terminal-message.test.ts +88 -1
- package/src/__tests__/subagent-tool-gate-mode.test.ts +225 -10
- package/src/__tests__/subagent-tools.test.ts +1901 -108
- package/src/__tests__/surface-completion-compaction-boundary.test.ts +124 -0
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +298 -0
- package/src/__tests__/system-prompt.test.ts +82 -7
- package/src/__tests__/tool-grant-request-escalation.test.ts +40 -1
- package/src/__tests__/tool-result-spool.test.ts +74 -18
- package/src/__tests__/tool-side-effects-documents.test.ts +174 -0
- package/src/__tests__/tool-side-effects-hook-failures.test.ts +129 -0
- package/src/__tests__/tools-audio-read.test.ts +10 -10
- package/src/__tests__/tools-get-route.test.ts +85 -12
- package/src/__tests__/tools-list-cli.test.ts +171 -0
- package/src/__tests__/top-level-renderer.test.ts +54 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +68 -1
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -1
- package/src/__tests__/turn-tail-chain.test.ts +135 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +6 -4
- package/src/__tests__/ui-visual-surface.test.ts +5 -4
- package/src/__tests__/ui-work-result-surface.test.ts +5 -4
- package/src/__tests__/unified-turn-context-visible-app.test.ts +7 -8
- package/src/__tests__/usage-routes.test.ts +62 -0
- package/src/__tests__/verification-outbound-delivery.test.ts +176 -0
- package/src/__tests__/visible-app-context.test.ts +20 -4
- package/src/__tests__/web-search-history.test.ts +96 -0
- package/src/__tests__/workspace-migration-139-clear-renamed-cost-profile-label.test.ts +6 -6
- package/src/__tests__/workspace-migration-140-repair-seed-pinned-memory-v3-live.test.ts +330 -0
- package/src/acp/failure-error.ts +3 -5
- package/src/agent/attachments.ts +26 -24
- package/src/agent/history-repair/history-repair.ts +27 -26
- package/src/agent/image-optimize.ts +6 -6
- package/src/agent/loop.ts +40 -22
- package/src/agent/message-types.ts +3 -3
- package/src/api/constants/document-tools.ts +55 -0
- package/src/api/events/question-answered.ts +53 -0
- package/src/api/events/tool-result.ts +7 -0
- package/src/api/index.ts +13 -0
- package/src/api/responses/conversation-message.ts +11 -0
- package/src/api/surfaces-oauth-connect.test.ts +96 -0
- package/src/api/surfaces.ts +36 -8
- package/src/approvals/guardian-channel-delivery.ts +83 -0
- package/src/approvals/guardian-expiry-notifier.ts +13 -11
- package/src/approvals/guardian-request-resolvers.ts +222 -135
- package/src/calls/__tests__/voice-session-bridge.test.ts +50 -0
- package/src/calls/media-stream-server.ts +9 -1
- package/src/calls/voice-session-bridge.ts +38 -0
- package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
- package/src/channels/config.ts +7 -2
- package/src/channels/gateway-verification-sessions.ts +7 -2
- package/src/channels/types.ts +7 -1
- package/src/cli/commands/__tests__/cache.test.ts +7 -4
- package/src/cli/commands/__tests__/cli-test-harness.ts +82 -0
- package/src/cli/commands/__tests__/conversations-wake.test.ts +51 -6
- package/src/cli/commands/__tests__/inference-models.test.ts +14 -0
- package/src/cli/commands/__tests__/inference-profiles.test.ts +44 -1
- package/src/cli/commands/__tests__/inference-providers.test.ts +7 -0
- package/src/cli/commands/__tests__/plugins.test.ts +692 -0
- package/src/cli/commands/__tests__/schedules.test.ts +136 -37
- package/src/cli/commands/conversations.ts +7 -3
- package/src/cli/commands/credentials.help.ts +7 -0
- package/src/cli/commands/inference-profiles.ts +9 -3
- package/src/cli/commands/inference.help.ts +16 -2
- package/src/cli/commands/mcp.help.ts +4 -2
- package/src/cli/commands/memory/memory-retrospective.ts +18 -0
- package/src/cli/commands/notifications.ts +3 -6
- package/src/cli/commands/oauth/connect-surface-guidance.test.ts +16 -0
- package/src/cli/commands/oauth/connect-surface-guidance.ts +25 -7
- package/src/cli/commands/oauth/connect.test.ts +26 -1
- package/src/cli/commands/oauth/connect.ts +4 -1
- package/src/cli/commands/oauth/index.help.ts +3 -1
- package/src/cli/commands/oauth/providers.ts +3 -0
- package/src/cli/commands/plugins.help.ts +25 -2
- package/src/cli/commands/plugins.ts +289 -10
- package/src/cli/commands/schedules.help.ts +14 -12
- package/src/cli/commands/schedules.ts +19 -5
- package/src/cli/commands/tools.help.ts +4 -2
- package/src/cli/commands/tools.ts +38 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +1 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +79 -0
- package/src/cli/lib/__tests__/install-from-platform.test.ts +47 -1
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +86 -7
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +122 -0
- package/src/cli/lib/install-from-github.ts +61 -0
- package/src/cli/lib/install-from-platform.ts +13 -2
- package/src/cli/lib/plugin-surfaces.ts +124 -4
- package/src/cli/lib/upgrade-plugin.ts +18 -0
- package/src/cli.ts +1 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +73 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +40 -0
- package/src/config/__tests__/plugin-updates-schema.test.ts +43 -0
- package/src/config/__tests__/profile-tool-support.test.ts +131 -0
- package/src/config/bundled-skills/AGENTS.md +1 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
- package/src/config/bundled-skills/schedule/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +53 -22
- package/src/config/bundled-skills/subagent/TOOLS.json +14 -13
- package/src/config/bundled-skills/visualize/SKILL.md +1 -1
- package/src/config/default-profile-catalog.ts +6 -2
- package/src/config/feature-flag-registry.json +25 -17
- package/src/config/llm-resolver.ts +45 -15
- package/src/config/loader.ts +70 -1
- package/src/config/profile-tool-support.ts +110 -0
- package/src/config/sanitize-for-transfer.ts +11 -0
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/stt.test.ts +20 -5
- package/src/config/schemas/channels.ts +13 -0
- package/src/config/schemas/memory-retrospective.ts +25 -0
- package/src/config/schemas/plugin-updates.ts +55 -0
- package/src/config/schemas/services.ts +8 -4
- package/src/config/schemas/stt.ts +17 -5
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +16 -0
- package/src/contacts/guardian-delivery-reader.ts +29 -2
- package/src/context/compactor.ts +4 -4
- package/src/context/post-turn-tool-result-truncation.ts +32 -16
- package/src/context/strip-injections.ts +42 -0
- package/src/context/tool-result-spool.ts +32 -18
- package/src/credential-execution/ces-runtime.ts +3 -0
- package/src/credential-execution/client.ts +22 -1
- package/src/credential-execution/process-manager.test.ts +99 -0
- package/src/credential-execution/process-manager.ts +62 -16
- package/src/daemon/__tests__/abort-null-controller.test.ts +141 -5
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +8 -12
- package/src/daemon/__tests__/install-assistant-command.test.ts +234 -0
- package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +2 -4
- package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +20 -29
- package/src/daemon/channel-ui-capability.ts +4 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +117 -61
- package/src/daemon/conversation-agent-loop.ts +318 -148
- package/src/daemon/conversation-attachments.ts +1 -1
- package/src/daemon/conversation-error.ts +8 -1
- package/src/daemon/conversation-initial-prompt.ts +16 -38
- package/src/daemon/conversation-lifecycle.ts +154 -32
- package/src/daemon/conversation-messaging.ts +106 -43
- package/src/daemon/conversation-process.ts +131 -33
- package/src/daemon/conversation-queue-manager.ts +10 -0
- package/src/daemon/conversation-runtime-assembly.ts +9 -4
- package/src/daemon/conversation-store.ts +52 -3
- package/src/daemon/conversation-surface-state.ts +9 -0
- package/src/daemon/conversation-surfaces.ts +403 -210
- package/src/daemon/conversation-tool-setup.ts +56 -7
- package/src/daemon/conversation-turn-finalize.ts +134 -89
- package/src/daemon/conversation.ts +111 -27
- package/src/daemon/disk-pressure-guard-lifecycle.ts +2 -2
- package/src/daemon/disk-pressure-guard.ts +3 -3
- package/src/daemon/doordash-steps.ts +5 -5
- package/src/daemon/external-plugins-bootstrap.ts +7 -1
- package/src/daemon/handlers/config-channels.ts +48 -5
- package/src/daemon/handlers/conversation-history.ts +1 -1
- package/src/daemon/handlers/conversations.ts +62 -17
- package/src/daemon/handlers/shared.ts +12 -0
- package/src/daemon/handlers/skills.ts +11 -1
- package/src/daemon/identity-helpers.ts +38 -10
- package/src/daemon/install-assistant-command.ts +322 -0
- package/src/daemon/lifecycle.ts +14 -3
- package/src/daemon/message-types/conversations.ts +6 -7
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/persist-media-references.ts +23 -14
- package/src/daemon/process-message.ts +6 -6
- package/src/daemon/tool-setup-types.ts +19 -122
- package/src/daemon/tool-side-effects.ts +17 -94
- package/src/daemon/trust-context-types.ts +39 -0
- package/src/daemon/trust-context.ts +14 -6
- package/src/daemon/turn-tail-chain.ts +73 -0
- package/src/daemon/web-search-history.ts +47 -33
- package/src/heartbeat/heartbeat-service.ts +6 -6
- package/src/ipc/__tests__/socket-path.test.ts +21 -0
- package/src/ipc/assistant-server.ts +17 -10
- package/src/ipc/cli-client.ts +10 -1
- package/src/ipc/routes/__tests__/documents-sync-ipc-routes.test.ts +56 -0
- package/src/ipc/routes/documents-sync-ipc-routes.ts +42 -0
- package/src/ipc/socket-cleanup.ts +9 -7
- package/src/ipc/socket-path.ts +4 -96
- package/src/live-voice/__tests__/live-voice-archive.test.ts +16 -16
- package/src/live-voice/__tests__/live-voice-attach-image.test.ts +209 -0
- package/src/live-voice/__tests__/live-voice-connection.test.ts +20 -0
- package/src/live-voice/__tests__/live-voice-integration.test.ts +7 -5
- package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +6 -1
- package/src/live-voice/__tests__/live-voice-vad.test.ts +35 -15
- package/src/live-voice/__tests__/protocol.test.ts +52 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +3 -0
- package/src/live-voice/live-voice-archive.ts +13 -13
- package/src/live-voice/live-voice-connection.ts +7 -1
- package/src/live-voice/live-voice-photo.ts +169 -0
- package/src/live-voice/live-voice-session.ts +108 -4
- package/src/live-voice/protocol.ts +89 -1
- package/src/mcp/client.ts +10 -0
- package/src/messaging/providers/__tests__/callback-routing.test.ts +5 -1
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +66 -4
- package/src/messaging/providers/callback-routing.ts +1 -0
- package/src/messaging/providers/discord/api.ts +312 -0
- package/src/messaging/providers/discord/dm-delivery.test.ts +204 -0
- package/src/messaging/providers/discord/render.test.ts +204 -0
- package/src/messaging/providers/discord/render.ts +195 -0
- package/src/messaging/providers/discord/send.test.ts +179 -0
- package/src/messaging/providers/discord/send.ts +212 -0
- package/src/messaging/providers/discord/transport.ts +81 -0
- package/src/messaging/providers/index.ts +3 -1
- package/src/messaging/providers/retry-policy.test.ts +247 -0
- package/src/messaging/providers/retry-policy.ts +206 -0
- package/src/messaging/providers/slack/mention-source.test.ts +285 -0
- package/src/messaging/providers/slack/mention-source.ts +287 -0
- package/src/messaging/providers/telegram-bot/api.ts +47 -130
- package/src/messaging/providers/whatsapp/api.ts +47 -136
- package/src/monitoring/__tests__/db-integrity-sample.test.ts +4 -1
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +332 -0
- package/src/monitoring/db-integrity-sample.ts +6 -1
- package/src/monitoring/plugin-auto-update.ts +359 -0
- package/src/monitoring/resource-sampler.ts +21 -5
- package/src/monitoring/worker.ts +13 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +375 -2
- package/src/notifications/__tests__/broadcaster.test.ts +37 -1
- package/src/notifications/__tests__/copy-composer.test.ts +165 -0
- package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +205 -0
- package/src/notifications/__tests__/notification-utils.test.ts +249 -0
- package/src/notifications/adapters/platform.ts +31 -2
- package/src/notifications/assistant-reply-producer.ts +79 -32
- package/src/notifications/broadcaster.ts +30 -10
- package/src/notifications/copy-composer.ts +69 -0
- package/src/notifications/emit-signal.ts +82 -15
- package/src/notifications/events-store.ts +10 -2
- package/src/notifications/home-feed-side-effect.ts +6 -3
- package/src/notifications/notification-utils.ts +173 -5
- package/src/notifications/signal.ts +12 -0
- package/src/oauth/AGENTS.md +4 -2
- package/src/oauth/byo-connection.ts +6 -1
- package/src/oauth/credential-token-resolver.ts +3 -10
- package/src/oauth/manual-token-connection.ts +29 -64
- package/src/oauth/manual-token-providers.ts +62 -0
- package/src/oauth/provider-serializer.ts +13 -0
- package/src/oauth/seed-providers.ts +62 -11
- package/src/onboarding/onboarding-events-store.ts +91 -1
- package/src/permissions/question-prompter.test.ts +4 -0
- package/src/permissions/question-prompter.ts +21 -4
- package/src/persistence/__tests__/conversation-lineage.test.ts +248 -0
- package/src/persistence/attachments-store.ts +15 -15
- package/src/persistence/conversation-attention-store.ts +30 -10
- package/src/persistence/conversation-bootstrap.ts +17 -0
- package/src/persistence/conversation-crud.ts +363 -97
- package/src/persistence/conversation-group-migration.ts +1 -1
- package/src/persistence/conversation-key-store.ts +38 -10
- package/src/persistence/conversation-lineage.ts +226 -0
- package/src/persistence/conversation-plugin-facade.ts +28 -3
- package/src/persistence/conversation-queries.ts +207 -33
- package/src/persistence/conversation-types.ts +107 -1
- package/src/persistence/jobs-store.ts +32 -8
- package/src/persistence/llm-usage-store.ts +22 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +168 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +76 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.test.ts +187 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.ts +93 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.test.ts +229 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.ts +127 -0
- package/src/persistence/migrations/364-add-schedule-source-key.test.ts +120 -0
- package/src/persistence/migrations/364-add-schedule-source-key.ts +43 -0
- package/src/persistence/migrations/365-add-conversation-fork-strategy.ts +27 -0
- package/src/persistence/schema/conversations.ts +32 -0
- package/src/persistence/schema/infrastructure.ts +3 -0
- package/src/persistence/steps.ts +30 -0
- package/src/persistence/subagent-store.ts +148 -6
- package/src/platform/managed-speech.test.ts +20 -0
- package/src/platform/managed-speech.ts +9 -0
- package/src/plugin-api/index.ts +8 -0
- package/src/plugin-api/webhook-url.ts +151 -0
- package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -0
- package/src/plugins/__tests__/source-fingerprint.test.ts +5 -1
- package/src/plugins/collect-source-versions.ts +4 -27
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +5 -5
- package/src/plugins/defaults/exploration-drift/package.json +1 -1
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +4 -2
- package/src/plugins/defaults/image-recovery/recover.ts +67 -57
- package/src/plugins/defaults/index.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +64 -18
- package/src/plugins/defaults/memory/__tests__/jobs-worker-outcome-contract.test.ts +242 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-retrospective-sweep.test.ts +24 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +48 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +511 -19
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +39 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +493 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +5 -4
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -1
- package/src/plugins/defaults/memory/job-handlers.ts +87 -5
- package/src/plugins/defaults/memory/jobs-worker.ts +60 -6
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +11 -0
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +29 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +342 -60
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +23 -3
- package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +9 -4
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +7 -0
- package/src/plugins/defaults/memory/v1/graph/injection.ts +1 -1
- package/src/plugins/defaults/memory/v2/router.ts +8 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +1 -2
- package/src/plugins/external-plugin-loader.ts +17 -8
- package/src/plugins/installed-plugin-dirs.ts +101 -0
- package/src/plugins/mtime-cache.ts +34 -22
- package/src/plugins/types.ts +69 -8
- package/src/prompts/persona-resolver.ts +6 -2
- package/src/prompts/system-prompt.ts +72 -17
- package/src/providers/__tests__/inference.test.ts +40 -0
- package/src/providers/__tests__/preflight-resolved-config.test.ts +58 -1
- package/src/providers/__tests__/retry-callsite.test.ts +67 -0
- package/src/providers/__tests__/vellum-connection-routing.test.ts +42 -11
- package/src/providers/anthropic/client.ts +112 -95
- package/src/providers/connection-resolution.ts +35 -1
- package/src/providers/gemini/client.ts +5 -5
- package/src/providers/inference/adapter-factory.ts +16 -10
- package/src/providers/inference/auth.ts +16 -0
- package/src/providers/inference/connection-availability.ts +164 -12
- package/src/providers/inference/connections.ts +25 -1
- package/src/providers/media-resolve.ts +21 -11
- package/src/providers/model-catalog.ts +15 -0
- package/src/providers/openai/chat-completions-provider.ts +4 -4
- package/src/providers/openai/responses-provider.ts +12 -25
- package/src/providers/registry.ts +9 -4
- package/src/providers/retry.ts +25 -0
- package/src/providers/server-tool-pairing.ts +134 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +187 -6
- package/src/providers/speech-to-text/deepgram.ts +1 -0
- package/src/providers/speech-to-text/resolve.ts +80 -10
- package/src/providers/speech-to-text/vellum-managed.ts +7 -1
- package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +3 -1
- package/src/providers/types.ts +26 -6
- package/src/providers/vellum-model-routing.ts +6 -7
- package/src/runtime/AGENTS.md +2 -0
- package/src/runtime/__tests__/agent-wake.test.ts +16 -16
- package/src/runtime/__tests__/background-job-runner.test.ts +0 -144
- package/src/runtime/__tests__/desktop-presence.test.ts +162 -0
- package/src/runtime/agent-wake.ts +63 -24
- package/src/runtime/assistant-event-hub.ts +87 -12
- package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -0
- package/src/runtime/auth/__tests__/scopes.test.ts +20 -0
- package/src/runtime/auth/same-actor.ts +56 -8
- package/src/runtime/auth/scopes.ts +12 -0
- package/src/runtime/auth/types.ts +2 -0
- package/src/runtime/background-job-runner.ts +5 -27
- package/src/runtime/channel-readiness-service.ts +59 -3
- package/src/runtime/channel-readiness-types.ts +18 -0
- package/src/runtime/desktop-presence.ts +69 -0
- package/src/runtime/http-server.ts +12 -0
- package/src/runtime/local-actor-identity.ts +11 -9
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/client-routes.test.ts +186 -14
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +547 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +162 -7
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +14 -10
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +340 -3
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +28 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +173 -1
- package/src/runtime/routes/__tests__/question-routes.test.ts +64 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +20 -0
- package/src/runtime/routes/__tests__/skill-history-route.test.ts +116 -0
- package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +60 -2
- package/src/runtime/routes/archive-utils.ts +16 -12
- package/src/runtime/routes/attachment-routes.ts +13 -6
- package/src/runtime/routes/canned-reply-release.ts +54 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -27
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +5 -0
- package/src/runtime/routes/client-routes.ts +114 -2
- package/src/runtime/routes/conversation-cli-routes.ts +10 -12
- package/src/runtime/routes/conversation-list-routes.ts +59 -10
- package/src/runtime/routes/conversation-management-routes.ts +47 -18
- package/src/runtime/routes/conversation-query-routes.ts +32 -53
- package/src/runtime/routes/conversation-routes.ts +360 -293
- package/src/runtime/routes/credential-prompt-routes.ts +23 -2
- package/src/runtime/routes/debug-routes.ts +4 -1
- package/src/runtime/routes/default-provider-routes.ts +7 -11
- package/src/runtime/routes/documents-routes.ts +44 -1
- package/src/runtime/routes/events-routes.ts +28 -1
- package/src/runtime/routes/host-app-control-routes.ts +2 -0
- package/src/runtime/routes/host-bash-routes.ts +2 -0
- package/src/runtime/routes/host-browser-routes.ts +2 -0
- package/src/runtime/routes/host-cu-routes.ts +2 -0
- package/src/runtime/routes/host-file-routes.ts +2 -0
- package/src/runtime/routes/host-transfer-routes.ts +4 -0
- package/src/runtime/routes/identity-routes.ts +6 -6
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +14 -0
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +14 -11
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -17
- package/src/runtime/routes/inference-profile-availability-guard.ts +171 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +26 -2
- package/src/runtime/routes/inference-profile-session-routes.ts +2 -1
- package/src/runtime/routes/inference-profiles-routes.ts +152 -73
- package/src/runtime/routes/inference-provider-connection-routes.ts +0 -16
- package/src/runtime/routes/llm-call-sites-routes.ts +13 -0
- package/src/runtime/routes/log-export-routes.ts +1 -1
- package/src/runtime/routes/notification-routes.ts +0 -14
- package/src/runtime/routes/oauth-providers.ts +1 -0
- package/src/runtime/routes/plugins-routes.ts +106 -1
- package/src/runtime/routes/profiler-routes.ts +4 -2
- package/src/runtime/routes/question-routes.ts +28 -10
- package/src/runtime/routes/retrospective-routes.ts +9 -3
- package/src/runtime/routes/schedule-routes.ts +210 -12
- package/src/runtime/routes/secret-routes.ts +40 -23
- package/src/runtime/routes/settings-routes.ts +41 -13
- package/src/runtime/routes/skills-routes.ts +79 -0
- package/src/runtime/routes/ui-snapshot-routes.ts +1 -0
- package/src/runtime/routes/wake-conversation-routes.ts +23 -0
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
- package/src/runtime/services/conversation-serializer.ts +24 -9
- package/src/runtime/sync/documents-sidecar-publish.test.ts +101 -0
- package/src/runtime/sync/resource-sync-events.ts +79 -1
- package/src/runtime/sync/worker-daemon-notify.test.ts +34 -0
- package/src/runtime/sync/worker-daemon-notify.ts +44 -6
- package/src/runtime/verification-outbound-actions.ts +250 -222
- package/src/runtime/verification-templates.ts +41 -30
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +614 -0
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1066 -0
- package/src/schedule/inference-profile.ts +64 -3
- package/src/schedule/plugin-schedule-declarations.ts +518 -0
- package/src/schedule/plugin-schedule-reconciler.ts +605 -0
- package/src/schedule/plugin-schedules-gate.ts +23 -0
- package/src/schedule/schedule-store.ts +520 -26
- package/src/schedule/scheduler.ts +38 -0
- package/src/security/credential-backend.ts +51 -4
- package/src/security/encrypted-store.ts +64 -42
- package/src/security/secure-keys.ts +55 -7
- package/src/skills/catalog-install.ts +20 -7
- package/src/skills/inline-command-runner.ts +2 -7
- package/src/skills/skill-history.test.ts +269 -0
- package/src/skills/skill-history.ts +250 -0
- package/src/skills/skillssh-registry.ts +1 -1
- package/src/stt/daemon-batch-transcriber.ts +8 -6
- package/src/subagent/__tests__/consult-prompt.test.ts +25 -0
- package/src/subagent/consult-prompt.ts +3 -1
- package/src/subagent/consult-transcript.ts +1 -1
- package/src/subagent/manager.ts +304 -44
- package/src/subagent/progress-events.ts +35 -0
- package/src/subagent/role-resolution.ts +88 -0
- package/src/subagent/types.ts +302 -67
- package/src/subagent/validate-allowlists.ts +3 -4
- package/src/telegram/__tests__/webhook-health.test.ts +73 -1
- package/src/telegram/webhook-health.ts +101 -3
- package/src/telemetry/__tests__/telemetry-event-fixtures.ts +2 -0
- package/src/telemetry/activation-funnel.ts +6 -1
- package/src/telemetry/live-voice-funnel.ts +75 -0
- package/src/telemetry/telemetry-event-sources.ts +6 -0
- package/src/telemetry/telemetry-wire-source.json +1 -1
- package/src/telemetry/telemetry-wire.generated.ts +2 -0
- package/src/telemetry/types.ts +23 -4
- package/src/telemetry/usage-telemetry-reporter.test.ts +4 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +118 -3
- package/src/tools/ask-question/ask-question-tool.ts +56 -2
- package/src/tools/browser/browser-execution.ts +1 -1
- package/src/tools/calls/call-start.ts +8 -5
- package/src/tools/conversation-groups/move_to_group.ts +10 -12
- package/src/tools/document/document-tool.ts +11 -4
- package/src/tools/execution-timeout.ts +9 -2
- package/src/tools/executor.ts +7 -6
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +7 -13
- package/src/tools/filesystem/search.ts +23 -21
- package/src/tools/filesystem/write.ts +4 -1
- package/src/tools/host-filesystem/edit.ts +7 -2
- package/src/tools/host-filesystem/read.ts +21 -8
- package/src/tools/host-filesystem/write.ts +10 -2
- package/src/tools/host-terminal/host-shell.ts +2 -2
- package/src/tools/mcp/mcp-tool-factory.ts +25 -1
- package/src/tools/permission-checker.ts +8 -3
- package/src/tools/schedule/delete.ts +13 -1
- package/src/tools/schedule/list.ts +14 -3
- package/src/tools/schedule/update.ts +56 -33
- package/src/tools/shared/filesystem/audio-read.ts +6 -4
- package/src/tools/shared/filesystem/file-ops-service.ts +176 -116
- package/src/tools/shared/filesystem/image-read.ts +12 -12
- package/src/tools/shared/filesystem/path-policy.ts +70 -5
- package/src/tools/shared/filesystem/size-guard.ts +6 -6
- package/src/tools/shared/input-misuse.ts +72 -0
- package/src/tools/skills/scaffold-managed.ts +82 -0
- package/src/tools/skills/skill-tool-factory.ts +14 -1
- package/src/tools/subagent/consult-deadline.ts +12 -7
- package/src/tools/subagent/message.ts +3 -1
- package/src/tools/subagent/read.ts +66 -4
- package/src/tools/subagent/spawn.ts +500 -78
- package/src/tools/tool-approval-handler.ts +45 -4
- package/src/tools/types.ts +22 -3
- package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
- package/src/tools/ui-surface/visual-validation.ts +2 -0
- package/src/usage/__tests__/subagent-attribution.test.ts +109 -0
- package/src/usage/subagent-attribution.ts +108 -0
- package/src/util/__tests__/sqlite-retry.test.ts +112 -0
- package/src/util/abort-reasons.ts +16 -0
- package/src/util/ansi.ts +44 -0
- package/src/util/disk-usage.ts +17 -13
- package/src/util/image-conversion.ts +20 -13
- package/src/util/schedule-source-key.ts +23 -0
- package/src/util/worker-process.ts +7 -1
- package/src/workspace/git-service.ts +33 -9
- package/src/workspace/migrations/140-repair-seed-pinned-memory-v3-live.ts +260 -0
- package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +111 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +126 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/workspace/top-level-renderer.ts +15 -2
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -357
- package/src/daemon/install-symlink.ts +0 -207
- package/src/notifications/deferred-emit.ts +0 -147
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed, validated representation of a Slack message's inline mention source:
|
|
3
|
+
* the verbatim mention markup plus the label snapshot resolved at ingress,
|
|
4
|
+
* with explicit workspace/install scope and a persist-time projectability
|
|
5
|
+
* fact.
|
|
6
|
+
*
|
|
7
|
+
* This module is pure and has no persistence or network callers. It defines
|
|
8
|
+
* the v1 contract (LUM-3023): consumers project readable text from persisted
|
|
9
|
+
* source data instead of trusting a one-shot ingress render. Projection is
|
|
10
|
+
* deterministic and snapshot-first; live lookups never participate at render
|
|
11
|
+
* time.
|
|
12
|
+
*
|
|
13
|
+
* Scope note: a Slack channel or user id is only meaningful within one
|
|
14
|
+
* workspace. `installTeamId` records the workspace the labels were resolved
|
|
15
|
+
* under when the ingress payload carries it; `null` means the deployment's
|
|
16
|
+
* single install implicitly defines the scope. Persisting cross-workspace
|
|
17
|
+
* data is blocked until ingress can prove scope (see the LUM-3023 plan's
|
|
18
|
+
* open blockers); nothing in this module resolves ids against any workspace.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
extractSlackChannelReferenceIds,
|
|
23
|
+
extractSlackUserMentionIds,
|
|
24
|
+
renderSlackTextForModel,
|
|
25
|
+
sanitizeSlackLabel,
|
|
26
|
+
} from "@vellumai/slack-text";
|
|
27
|
+
|
|
28
|
+
export interface SlackMentionLabelMaps {
|
|
29
|
+
/** Slack user id (`U…`/`W…`) to sanitized display label. */
|
|
30
|
+
users: Record<string, string>;
|
|
31
|
+
/** Slack conversation id (`C…`/`G…`/`D…`) to sanitized channel name. */
|
|
32
|
+
channels: Record<string, string>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SlackMentionSourceV1 {
|
|
36
|
+
/** Schema version marker; readers must reject unknown versions. */
|
|
37
|
+
v: 1;
|
|
38
|
+
/**
|
|
39
|
+
* Workspace the labels were resolved under, when ingress supplied it.
|
|
40
|
+
* `null` means the install's implicit single-workspace scope.
|
|
41
|
+
*/
|
|
42
|
+
installTeamId: string | null;
|
|
43
|
+
/** The verbatim Slack event text, mention markup intact. */
|
|
44
|
+
rawText: string;
|
|
45
|
+
/** Ingress-resolved labels, filtered to ids present in `rawText`. */
|
|
46
|
+
labels: SlackMentionLabelMaps;
|
|
47
|
+
/**
|
|
48
|
+
* True when the stored message body is exactly the render of
|
|
49
|
+
* (`rawText`, `labels`), computed once at persist time. Only projectable
|
|
50
|
+
* rows may ever be re-rendered; false covers composed bodies (e.g. voice
|
|
51
|
+
* transcription prepended at ingress), edits that diverged, and any
|
|
52
|
+
* unexpected mismatch.
|
|
53
|
+
*/
|
|
54
|
+
projectable: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Upper bound on persisted raw text, in UTF-8 bytes. Oversize input is
|
|
59
|
+
* REJECTED (the whole source is dropped), never truncated: truncation can
|
|
60
|
+
* split a mention token and silently change what the text parses as.
|
|
61
|
+
*/
|
|
62
|
+
export const MENTION_RAW_TEXT_MAX_BYTES = 8192;
|
|
63
|
+
|
|
64
|
+
/** Per-label character cap, matching the renderer's sanitizer budget. */
|
|
65
|
+
export const MENTION_LABEL_MAX_CHARS = 200;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Per-map entry cap. Overflow drops entries deterministically from the end
|
|
69
|
+
* of the sorted key order, so the same input always persists the same maps.
|
|
70
|
+
*/
|
|
71
|
+
export const MENTION_LABEL_MAP_MAX_ENTRIES = 32;
|
|
72
|
+
|
|
73
|
+
const CHANNEL_ID_RE = /^[CDG][A-Z0-9]{1,31}$/;
|
|
74
|
+
const USER_ID_RE = /^[UW][A-Z0-9]{1,31}$/;
|
|
75
|
+
const TEAM_ID_RE = /^[TE][A-Z0-9]{1,31}$/;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Sanitize a label for persistence: the shared renderer normalization from
|
|
79
|
+
* `@vellumai/slack-text` (single source of truth, so persisted labels can
|
|
80
|
+
* never drift from render-time semantics), plus the persistence-only
|
|
81
|
+
* bounds this module owns: well-formedness rejection and a length cap.
|
|
82
|
+
* Returns `undefined` when the input is malformed or nothing usable remains.
|
|
83
|
+
*/
|
|
84
|
+
export function sanitizeMentionLabel(value: unknown): string | undefined {
|
|
85
|
+
if (typeof value !== "string" || !isWellFormedString(value)) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
const normalized = sanitizeSlackLabel(value);
|
|
89
|
+
if (!normalized) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
// Truncate on code-point boundaries: a UTF-16 `slice` can split a
|
|
93
|
+
// surrogate pair and persist a lone surrogate, violating the same
|
|
94
|
+
// well-formedness rule this module enforces on rawText.
|
|
95
|
+
const sanitized = [...normalized]
|
|
96
|
+
.slice(0, MENTION_LABEL_MAX_CHARS)
|
|
97
|
+
.join("")
|
|
98
|
+
.trim();
|
|
99
|
+
return sanitized.length > 0 ? sanitized : undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function utf8ByteLength(value: string): number {
|
|
103
|
+
return new TextEncoder().encode(value).length;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Reject strings carrying unpaired surrogates (not valid UTF-8 material). */
|
|
107
|
+
function isWellFormedString(value: string): boolean {
|
|
108
|
+
const withIsWellFormed = value as string & { isWellFormed?: () => boolean };
|
|
109
|
+
if (typeof withIsWellFormed.isWellFormed === "function") {
|
|
110
|
+
return withIsWellFormed.isWellFormed();
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
encodeURIComponent(value);
|
|
114
|
+
return true;
|
|
115
|
+
} catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function buildLabelMap(
|
|
121
|
+
ids: readonly string[],
|
|
122
|
+
provided: Record<string, unknown> | undefined,
|
|
123
|
+
idPattern: RegExp,
|
|
124
|
+
): Record<string, string> {
|
|
125
|
+
const out: Record<string, string> = {};
|
|
126
|
+
if (!provided) {
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
// Deterministic overflow: iterate ids in sorted order and stop at the cap.
|
|
130
|
+
const sortedIds = [...new Set(ids)].sort();
|
|
131
|
+
for (const id of sortedIds) {
|
|
132
|
+
if (Object.keys(out).length >= MENTION_LABEL_MAP_MAX_ENTRIES) {
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
if (!idPattern.test(id)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (!Object.prototype.hasOwnProperty.call(provided, id)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const label = sanitizeMentionLabel(provided[id]);
|
|
142
|
+
// An id-shaped "label" is not a resolution; the renderer treats it as
|
|
143
|
+
// unresolved, so persisting it would only waste bytes.
|
|
144
|
+
if (!label || label === id) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
out[id] = label;
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface BuildSlackMentionSourceInput {
|
|
153
|
+
/** The verbatim Slack event text. */
|
|
154
|
+
rawText: unknown;
|
|
155
|
+
/** Ingress-resolved user labels keyed by user id, unvalidated. */
|
|
156
|
+
userLabels?: Record<string, unknown>;
|
|
157
|
+
/** Ingress-resolved channel labels keyed by conversation id, unvalidated. */
|
|
158
|
+
channelLabels?: Record<string, unknown>;
|
|
159
|
+
/** Workspace scope the labels were resolved under, when ingress knows it. */
|
|
160
|
+
installTeamId?: unknown;
|
|
161
|
+
/**
|
|
162
|
+
* The message body text as it will be persisted, used to compute
|
|
163
|
+
* `projectable` (exact-render equality).
|
|
164
|
+
*/
|
|
165
|
+
storedBodyText: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Validate ingress inputs into a persistable `SlackMentionSourceV1`, or
|
|
170
|
+
* `undefined` when the text carries no mention tokens or fails validation.
|
|
171
|
+
* All bounds are enforced here regardless of how trusted the caller is:
|
|
172
|
+
* this function is the persistence boundary for mention data.
|
|
173
|
+
*/
|
|
174
|
+
export function buildSlackMentionSource(
|
|
175
|
+
input: BuildSlackMentionSourceInput,
|
|
176
|
+
): SlackMentionSourceV1 | undefined {
|
|
177
|
+
const { rawText, storedBodyText } = input;
|
|
178
|
+
if (typeof rawText !== "string" || rawText.length === 0) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
if (!isWellFormedString(rawText)) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
if (utf8ByteLength(rawText) > MENTION_RAW_TEXT_MAX_BYTES) {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const userIds = extractSlackUserMentionIds(rawText);
|
|
189
|
+
const channelIds = extractSlackChannelReferenceIds(rawText);
|
|
190
|
+
if (userIds.length === 0 && channelIds.length === 0) {
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const labels: SlackMentionLabelMaps = {
|
|
195
|
+
users: buildLabelMap(userIds, input.userLabels, USER_ID_RE),
|
|
196
|
+
channels: buildLabelMap(channelIds, input.channelLabels, CHANNEL_ID_RE),
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const installTeamId =
|
|
200
|
+
typeof input.installTeamId === "string" &&
|
|
201
|
+
TEAM_ID_RE.test(input.installTeamId)
|
|
202
|
+
? input.installTeamId
|
|
203
|
+
: null;
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
v: 1,
|
|
207
|
+
installTeamId,
|
|
208
|
+
rawText,
|
|
209
|
+
labels,
|
|
210
|
+
projectable:
|
|
211
|
+
renderMentionSourceText(rawText, labels) === storedBodyText.trim(),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Parse a persisted (or wire) value back into a validated
|
|
217
|
+
* `SlackMentionSourceV1`. Unknown versions, malformed shapes, and
|
|
218
|
+
* out-of-bounds data return `undefined` so readers fall back to stored text.
|
|
219
|
+
*/
|
|
220
|
+
export function readSlackMentionSource(
|
|
221
|
+
value: unknown,
|
|
222
|
+
): SlackMentionSourceV1 | undefined {
|
|
223
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
const record = value as Record<string, unknown>;
|
|
227
|
+
if (record.v !== 1) {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
// A malformed labels container is a rejected shape, not "no labels": a
|
|
231
|
+
// value that lost its maps but kept `projectable: true` must fall back to
|
|
232
|
+
// stored text rather than project fallback labels over it.
|
|
233
|
+
const labels = asRecord(record.labels);
|
|
234
|
+
const users = asRecord(labels?.users);
|
|
235
|
+
const channels = asRecord(labels?.channels);
|
|
236
|
+
if (!labels || !users || !channels) {
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
const rebuilt = buildSlackMentionSource({
|
|
240
|
+
rawText: record.rawText,
|
|
241
|
+
userLabels: users,
|
|
242
|
+
channelLabels: channels,
|
|
243
|
+
installTeamId: record.installTeamId ?? undefined,
|
|
244
|
+
// `projectable` is a stored fact; re-deriving it needs the stored body,
|
|
245
|
+
// which readers do not always have. Preserve the persisted flag but only
|
|
246
|
+
// when it is a real boolean.
|
|
247
|
+
storedBodyText: "",
|
|
248
|
+
});
|
|
249
|
+
if (!rebuilt || typeof record.projectable !== "boolean") {
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
return { ...rebuilt, projectable: record.projectable };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
|
256
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
257
|
+
? (value as Record<string, unknown>)
|
|
258
|
+
: undefined;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function renderMentionSourceText(
|
|
262
|
+
rawText: string,
|
|
263
|
+
labels: SlackMentionLabelMaps,
|
|
264
|
+
): string {
|
|
265
|
+
return renderSlackTextForModel(rawText, {
|
|
266
|
+
userLabels: labels.users,
|
|
267
|
+
channelLabels: labels.channels,
|
|
268
|
+
}).trim();
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Pure, synchronous projection: render the persisted mention source when the
|
|
273
|
+
* row is projectable, otherwise return the stored text unchanged. No live
|
|
274
|
+
* cache or lookup participates; historical messages render the historical
|
|
275
|
+
* snapshot. Callers apply untrusted-content fencing AFTER this function
|
|
276
|
+
* (render-then-fence), matching the ingress pipeline's order.
|
|
277
|
+
*/
|
|
278
|
+
export function projectSlackMentionText(
|
|
279
|
+
source: SlackMentionSourceV1 | undefined,
|
|
280
|
+
storedText: string,
|
|
281
|
+
): string {
|
|
282
|
+
if (!source || !source.projectable) {
|
|
283
|
+
return storedText;
|
|
284
|
+
}
|
|
285
|
+
const projected = renderMentionSourceText(source.rawText, source.labels);
|
|
286
|
+
return projected.length > 0 ? projected : storedText;
|
|
287
|
+
}
|
|
@@ -11,6 +11,7 @@ import { credentialKey } from "../../../security/credential-key.js";
|
|
|
11
11
|
import { getSecureKeyResultAsync } from "../../../security/secure-keys.js";
|
|
12
12
|
import { BackendUnavailableError, ConfigError } from "../../../util/errors.js";
|
|
13
13
|
import { getLogger } from "../../../util/logger.js";
|
|
14
|
+
import { retryableCall } from "../retry-policy.js";
|
|
14
15
|
|
|
15
16
|
const log = getLogger("telegram-api");
|
|
16
17
|
|
|
@@ -71,142 +72,58 @@ interface TelegramApiResponse<T> {
|
|
|
71
72
|
parameters?: { retry_after?: number };
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
): number {
|
|
83
|
-
if (retryAfterHeader) {
|
|
84
|
-
const seconds = Number(retryAfterHeader);
|
|
85
|
-
if (Number.isFinite(seconds) && seconds > 0) {
|
|
86
|
-
return Math.min(seconds * 1000, 2_147_483_647);
|
|
87
|
-
}
|
|
88
|
-
const targetTime = new Date(retryAfterHeader).getTime();
|
|
89
|
-
if (Number.isFinite(targetTime)) {
|
|
90
|
-
const delayMs = targetTime - Date.now();
|
|
91
|
-
if (delayMs > 0) {
|
|
92
|
-
return Math.min(delayMs, 2_147_483_647);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
75
|
+
/** The Bot API envelope, or undefined when the body is not JSON. */
|
|
76
|
+
function parseTelegramBody<T>(
|
|
77
|
+
body: string,
|
|
78
|
+
): TelegramApiResponse<T> | undefined {
|
|
79
|
+
try {
|
|
80
|
+
return JSON.parse(body) as TelegramApiResponse<T>;
|
|
81
|
+
} catch {
|
|
82
|
+
return undefined;
|
|
95
83
|
}
|
|
96
|
-
const exponential = initialBackoffMs * Math.pow(2, attempt - 1);
|
|
97
|
-
const jitter = Math.random() * exponential * 0.5;
|
|
98
|
-
return exponential + jitter;
|
|
99
84
|
}
|
|
100
85
|
|
|
101
|
-
|
|
86
|
+
function telegramCall<T>(
|
|
102
87
|
method: string,
|
|
103
88
|
doFetch: () => Promise<Response>,
|
|
104
89
|
): Promise<T> {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
log.warn(
|
|
130
|
-
{ error: redactBotTokens(message), attempt, method },
|
|
131
|
-
"Telegram API fetch failed",
|
|
132
|
-
);
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (!isRetryable(response.status) && !response.ok) {
|
|
137
|
-
const body = await response.text().catch(() => "");
|
|
138
|
-
let description: string | undefined;
|
|
139
|
-
try {
|
|
140
|
-
const data = JSON.parse(body) as TelegramApiResponse<T>;
|
|
141
|
-
description = data.description;
|
|
142
|
-
} catch {
|
|
143
|
-
// not JSON
|
|
90
|
+
return retryableCall<T>({
|
|
91
|
+
provider: "Telegram",
|
|
92
|
+
operation: method,
|
|
93
|
+
maxRetries: TELEGRAM_DEFAULT_MAX_RETRIES,
|
|
94
|
+
initialBackoffMs: TELEGRAM_DEFAULT_INITIAL_BACKOFF_MS,
|
|
95
|
+
log,
|
|
96
|
+
doFetch,
|
|
97
|
+
// Telegram errors can echo the bot token, which is in the request URL.
|
|
98
|
+
redact: redactBotTokens,
|
|
99
|
+
detailFrom: (body) => parseTelegramBody<T>(body)?.description,
|
|
100
|
+
retryAfterFrom: (_response, body) => {
|
|
101
|
+
const retryAfter = parseTelegramBody<T>(body)?.parameters?.retry_after;
|
|
102
|
+
return retryAfter != null ? String(retryAfter) : null;
|
|
103
|
+
},
|
|
104
|
+
nonRetryableError: ({ message, detail }) =>
|
|
105
|
+
new TelegramNonRetryableError(message, detail),
|
|
106
|
+
decode: (body, response) => {
|
|
107
|
+
const data = parseTelegramBody<T>(body);
|
|
108
|
+
if (!data) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
body
|
|
111
|
+
? `Telegram ${method} failed: unparseable response body: ${redactBotTokens(body)}`
|
|
112
|
+
: `Telegram ${method} failed with status ${response.status}: empty response`,
|
|
113
|
+
);
|
|
144
114
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
throw new TelegramNonRetryableError(message, description);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (isRetryable(response.status)) {
|
|
155
|
-
const body = await response.text().catch(() => "");
|
|
156
|
-
let description: string | undefined;
|
|
157
|
-
let retryAfterParam: number | undefined;
|
|
158
|
-
try {
|
|
159
|
-
const data = JSON.parse(body) as TelegramApiResponse<T>;
|
|
160
|
-
description = data.description;
|
|
161
|
-
retryAfterParam = data.parameters?.retry_after;
|
|
162
|
-
} catch {
|
|
163
|
-
// not JSON
|
|
164
|
-
}
|
|
165
|
-
lastRetryAfter =
|
|
166
|
-
response.headers.get("retry-after") ??
|
|
167
|
-
(retryAfterParam != null ? String(retryAfterParam) : null);
|
|
168
|
-
lastError = new Error(
|
|
169
|
-
description
|
|
170
|
-
? `Telegram ${method} failed: ${description}`
|
|
171
|
-
: body
|
|
172
|
-
? `Telegram ${method} failed with status ${response.status}: ${redactBotTokens(body)}`
|
|
115
|
+
// A 200 can still carry a failure: the Bot API reports it in the
|
|
116
|
+
// envelope rather than the status.
|
|
117
|
+
if (!data.ok || data.result === undefined) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
data.description
|
|
120
|
+
? `Telegram ${method} failed: ${data.description}`
|
|
173
121
|
: `Telegram ${method} failed with status ${response.status}`,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
method,
|
|
180
|
-
retryAfter: lastRetryAfter,
|
|
181
|
-
},
|
|
182
|
-
"Telegram API returned retryable error",
|
|
183
|
-
);
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const body = await response.text().catch(() => "");
|
|
188
|
-
let data: TelegramApiResponse<T>;
|
|
189
|
-
try {
|
|
190
|
-
data = JSON.parse(body) as TelegramApiResponse<T>;
|
|
191
|
-
} catch {
|
|
192
|
-
throw new Error(
|
|
193
|
-
body
|
|
194
|
-
? `Telegram ${method} failed: unparseable response body: ${redactBotTokens(body)}`
|
|
195
|
-
: `Telegram ${method} failed with status ${response.status}: empty response`,
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
if (!data.ok || data.result === undefined) {
|
|
199
|
-
throw new Error(
|
|
200
|
-
data.description
|
|
201
|
-
? `Telegram ${method} failed: ${data.description}`
|
|
202
|
-
: `Telegram ${method} failed with status ${response.status}`,
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return data.result;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
throw lastError ?? new Error(`Telegram ${method} failed after retries`);
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
return data.result;
|
|
125
|
+
},
|
|
126
|
+
});
|
|
210
127
|
}
|
|
211
128
|
|
|
212
129
|
// ---------------------------------------------------------------------------
|
|
@@ -250,7 +167,7 @@ export async function callTelegramBotApi<T>(
|
|
|
250
167
|
body: Record<string, unknown>,
|
|
251
168
|
): Promise<T> {
|
|
252
169
|
const botToken = await resolveBotToken();
|
|
253
|
-
return
|
|
170
|
+
return telegramCall<T>(method, () =>
|
|
254
171
|
fetch(`${TELEGRAM_API_BASE}/bot${botToken}/${method}`, {
|
|
255
172
|
method: "POST",
|
|
256
173
|
headers: { "Content-Type": "application/json" },
|
|
@@ -268,7 +185,7 @@ export async function callTelegramBotApiMultipart<T>(
|
|
|
268
185
|
form: FormData,
|
|
269
186
|
): Promise<T> {
|
|
270
187
|
const botToken = await resolveBotToken();
|
|
271
|
-
return
|
|
188
|
+
return telegramCall<T>(method, () =>
|
|
272
189
|
fetch(`${TELEGRAM_API_BASE}/bot${botToken}/${method}`, {
|
|
273
190
|
method: "POST",
|
|
274
191
|
body: form,
|