@vellumai/assistant 0.8.6 → 0.8.7
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/AGENTS.md +4 -4
- package/Dockerfile +1 -0
- package/bun.lock +11 -2
- package/docker-entrypoint.sh +8 -6
- package/docs/plugins.md +63 -28
- package/examples/plugins/echo/register.ts +4 -7
- package/knip.json +1 -0
- package/node_modules/@vellumai/environments/bun.lock +24 -0
- package/node_modules/@vellumai/environments/package.json +18 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +95 -0
- package/node_modules/@vellumai/environments/src/index.ts +11 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +73 -0
- package/node_modules/@vellumai/environments/src/types.ts +70 -0
- package/node_modules/@vellumai/environments/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +11 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +3 -4
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +6 -2
- package/openapi.yaml +3735 -353
- package/package.json +7 -3
- package/scripts/generate-openapi.ts +20 -13
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
- package/src/__tests__/agent-loop-exit-reason.test.ts +240 -39
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +19 -32
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +6 -4
- package/src/__tests__/agent-loop-thinking.test.ts +17 -12
- package/src/__tests__/agent-loop.test.ts +207 -341
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +4 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +22 -40
- package/src/__tests__/anthropic-provider.test.ts +201 -55
- package/src/__tests__/app-builder-skill-instructions.test.ts +22 -0
- package/src/__tests__/app-control-flow.test.ts +5 -0
- package/src/__tests__/approval-cascade.test.ts +4 -11
- package/src/__tests__/approval-routes-http.test.ts +4 -2
- package/src/__tests__/assistant-event.test.ts +15 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/avatar-e2e.test.ts +7 -37
- package/src/__tests__/avatar-generator.test.ts +12 -42
- package/src/__tests__/avatar-identity-sync.test.ts +28 -3
- package/src/__tests__/background-shell-bash.test.ts +3 -7
- package/src/__tests__/btw-routes.test.ts +7 -12
- package/src/__tests__/call-pointer-messages.test.ts +5 -3
- package/src/__tests__/call-site-routing-provider.test.ts +22 -40
- package/src/__tests__/catalog-files.test.ts +1 -0
- package/src/__tests__/channel-approval-routes.test.ts +48 -20
- package/src/__tests__/channel-approvals.test.ts +3 -1
- package/src/__tests__/channel-invite-transport.test.ts +1 -5
- package/src/__tests__/channel-readiness-routes.test.ts +0 -4
- package/src/__tests__/channel-readiness-slack-remote.test.ts +2 -7
- package/src/__tests__/channel-retry-sweep.test.ts +71 -79
- package/src/__tests__/circuit-breaker-pipeline.test.ts +3 -3
- package/src/__tests__/clawhub-files.test.ts +1 -0
- package/src/__tests__/compaction-events.test.ts +5 -17
- package/src/__tests__/compaction-pipeline.test.ts +1 -1
- package/src/__tests__/compaction-timeout-recovery.test.ts +37 -48
- package/src/__tests__/compaction-trail-store.test.ts +1 -79
- package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
- package/src/__tests__/computer-use-tools.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +28 -0
- package/src/__tests__/context-search-agent-runner.test.ts +6 -3
- package/src/__tests__/context-token-estimator.test.ts +34 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +14 -7
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +12 -27
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +430 -90
- package/src/__tests__/conversation-agent-loop.test.ts +581 -62
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -3
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clear-safety.test.ts +20 -10
- package/src/__tests__/conversation-confirmation-signals.test.ts +15 -45
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-disk-view.test.ts +10 -17
- package/src/__tests__/conversation-fork-crud.test.ts +86 -172
- package/src/__tests__/conversation-fork-route.test.ts +16 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
- package/src/__tests__/conversation-lifecycle.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +3 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -1
- package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
- package/src/__tests__/conversation-pairing.test.ts +34 -4
- package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -0
- package/src/__tests__/conversation-process-callsite.test.ts +27 -30
- package/src/__tests__/conversation-provider-retry-repair.test.ts +53 -44
- package/src/__tests__/conversation-queue.test.ts +270 -164
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -2
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +20 -22
- package/src/__tests__/conversation-runtime-workspace.test.ts +19 -1
- package/src/__tests__/conversation-slash-queue.test.ts +37 -31
- package/src/__tests__/conversation-slash-unknown.test.ts +13 -15
- package/src/__tests__/conversation-speed-override.test.ts +8 -22
- package/src/__tests__/conversation-stream-state.test.ts +484 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +6 -15
- package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
- package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -2
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -15
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +23 -11
- package/src/__tests__/conversation-unread-route.test.ts +14 -2
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-wipe.test.ts +1 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +3 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +48 -22
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +27 -7
- package/src/__tests__/credential-execution-tools.test.ts +1 -2
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/cross-provider-web-search.test.ts +6 -2
- package/src/__tests__/cu-unified-flow.test.ts +26 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +11 -0
- package/src/__tests__/disk-pressure-guard.test.ts +66 -0
- package/src/__tests__/disk-pressure-routes.test.ts +9 -2
- package/src/__tests__/dm-persistence.test.ts +7 -2
- package/src/__tests__/dynamic-page-surface.test.ts +68 -0
- package/src/__tests__/edit-propagation.test.ts +1 -2
- package/src/__tests__/empty-response-pipeline.test.ts +127 -5
- package/src/__tests__/filing-service.test.ts +2 -2
- package/src/__tests__/first-greeting.test.ts +55 -14
- package/src/__tests__/gemini-inline-media.test.ts +78 -0
- package/src/__tests__/gemini-provider.test.ts +351 -28
- package/src/__tests__/guardian-routing-state.test.ts +60 -71
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +9 -7
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +2 -1
- package/src/__tests__/history-repair-hook.test.ts +161 -0
- package/src/__tests__/history-repair-observability.test.ts +1 -1
- package/src/__tests__/history-repair.test.ts +2 -1
- package/src/__tests__/host-app-control-proxy.test.ts +2 -0
- package/src/__tests__/host-cu-proxy.test.ts +2 -0
- package/src/__tests__/host-file-edit-tool.test.ts +4 -2
- package/src/__tests__/host-file-proxy.test.ts +31 -0
- package/src/__tests__/host-file-read-tool.test.ts +4 -2
- package/src/__tests__/host-file-write-tool.test.ts +9 -3
- package/src/__tests__/host-proxy-preactivation.test.ts +53 -14
- package/src/__tests__/host-shell-tool.test.ts +9 -4
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/identity-intro-cache.test.ts +35 -14
- package/src/__tests__/inbound-slack-persistence.test.ts +7 -2
- package/src/__tests__/injector-background-turn.test.ts +1 -1
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-disk-pressure.test.ts +1 -1
- package/src/__tests__/injector-document-comments.test.ts +1 -1
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +1 -1
- package/src/__tests__/injector-v3-suppression.test.ts +220 -0
- package/src/__tests__/list-messages-attachments.test.ts +7 -8
- package/src/__tests__/list-messages-hidden-metadata.test.ts +17 -15
- package/src/__tests__/list-messages-page-latest.test.ts +0 -1
- package/src/__tests__/list-messages-tool-merge.test.ts +36 -6
- package/src/__tests__/llm-call-pipeline.test.ts +21 -15
- package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
- package/src/__tests__/llm-resolver.test.ts +23 -47
- package/src/__tests__/llm-usage-store.test.ts +45 -0
- package/src/__tests__/log-export-routes.test.ts +59 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +1 -8
- package/src/__tests__/mcp-auth-routes.test.ts +15 -10
- package/src/__tests__/mcp-health-check.test.ts +18 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +1 -1
- package/src/__tests__/memory-v2-static-injector.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +8 -4
- package/src/__tests__/migration-export-http.test.ts +12 -12
- package/src/__tests__/migration-import-commit-http.test.ts +8 -8
- package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +14 -20
- package/src/__tests__/notification-decision-identity.test.ts +9 -18
- package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
- package/src/__tests__/oauth-commands-routes.test.ts +1 -1
- package/src/__tests__/onboarding-template-contract.test.ts +10 -0
- package/src/__tests__/openai-provider.test.ts +66 -70
- package/src/__tests__/openai-responses-provider.test.ts +21 -77
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -1
- package/src/__tests__/overflow-reduce-pipeline.test.ts +2 -4
- package/src/__tests__/parallel-tool.benchmark.test.ts +24 -36
- package/src/__tests__/persistence-pipeline.test.ts +15 -26
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -1
- package/src/__tests__/pipeline-runner.test.ts +2 -3
- package/src/__tests__/plugin-bootstrap.test.ts +51 -25
- package/src/__tests__/plugin-route-contribution.test.ts +6 -16
- package/src/__tests__/plugin-skill-contribution.test.ts +7 -17
- package/src/__tests__/plugin-tool-contribution.test.ts +10 -26
- package/src/__tests__/plugin-types.test.ts +7 -14
- package/src/__tests__/prechat-onboarding-contract.test.ts +23 -0
- package/src/__tests__/process-message-background-slack.test.ts +17 -16
- package/src/__tests__/process-message-display-content.test.ts +30 -42
- package/src/__tests__/provider-commit-message-generator.test.ts +19 -14
- package/src/__tests__/provider-error-scenarios.test.ts +7 -6
- package/src/__tests__/provider-platform-proxy-integration.test.ts +3 -8
- package/src/__tests__/provider-send-message-override-profile.test.ts +9 -25
- package/src/__tests__/provider-streaming.benchmark.test.ts +12 -22
- package/src/__tests__/provider-usage-tracking.test.ts +0 -6
- package/src/__tests__/ratelimit.test.ts +9 -4
- package/src/__tests__/relay-server.test.ts +20 -13
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +5 -8
- package/src/__tests__/retry-thinking-tool-choice.test.ts +10 -13
- package/src/__tests__/retry-verbosity-normalization.test.ts +5 -8
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +353 -0
- package/src/__tests__/schedule-routes.test.ts +80 -10
- package/src/__tests__/schedule-store.test.ts +67 -0
- package/src/__tests__/schedule-tools.test.ts +125 -0
- package/src/__tests__/secret-ingress-http.test.ts +2 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +11 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +11 -9
- package/src/__tests__/secret-response-routing.test.ts +13 -11
- package/src/__tests__/send-endpoint-busy.test.ts +2 -1
- package/src/__tests__/shell-observability.test.ts +249 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +11 -11
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +10 -10
- package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
- package/src/__tests__/skillssh-files.test.ts +1 -0
- package/src/__tests__/starter-task-flow.test.ts +6 -6
- package/src/__tests__/strip-memory-injections.test.ts +102 -14
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +19 -16
- package/src/__tests__/system-prompt.test.ts +54 -0
- package/src/__tests__/terminal-tools.test.ts +3 -24
- package/src/__tests__/thread-backfill.test.ts +4 -9
- package/src/__tests__/title-generate-pipeline.test.ts +1 -1
- package/src/__tests__/token-estimate-pipeline.test.ts +2 -4
- package/src/__tests__/tool-error-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execute-pipeline.test.ts +1 -1
- package/src/__tests__/tool-preview-lifecycle.test.ts +13 -11
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +9 -12
- package/src/__tests__/tool-result-truncation.test.ts +3 -1
- package/src/__tests__/tools-audio-read.test.ts +113 -0
- package/src/__tests__/turn-boundary-resolution.test.ts +44 -84
- package/src/__tests__/turn-events-store.test.ts +11 -7
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +8 -6
- package/src/__tests__/voice-session-bridge.test.ts +13 -7
- package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
- package/src/acp/prepare-agent-env.ts +52 -11
- package/src/agent/compaction-circuit.ts +140 -0
- package/src/agent/loop.ts +409 -85
- package/src/api/README.md +19 -17
- package/src/api/constants/tool-execution.ts +21 -0
- package/src/api/events/assistant-activity-state.ts +75 -0
- package/src/api/events/assistant-outbound-attachment.ts +25 -27
- package/src/api/events/assistant-text-delta.ts +6 -8
- package/src/api/events/assistant-turn-start.ts +5 -7
- package/src/api/events/avatar-updated.ts +24 -0
- package/src/api/events/compaction-circuit-closed.ts +26 -0
- package/src/api/events/compaction-circuit-open.ts +28 -0
- package/src/api/events/confirmation-request.ts +114 -0
- package/src/api/events/contact-request.ts +33 -0
- package/src/api/events/conversation-error.ts +77 -0
- package/src/api/events/conversation-list-invalidated.ts +38 -0
- package/src/api/events/conversation-title-updated.ts +24 -0
- package/src/api/events/disk-pressure-status-changed.ts +61 -0
- package/src/api/events/document-comment-created.ts +24 -28
- package/src/api/events/document-comment-deleted.ts +6 -8
- package/src/api/events/document-comment-reopened.ts +6 -8
- package/src/api/events/document-comment-resolved.ts +8 -10
- package/src/api/events/document-editor-update.ts +27 -0
- package/src/api/events/error.ts +32 -0
- package/src/api/events/generation-cancelled.ts +4 -6
- package/src/api/events/generation-handoff.ts +13 -15
- package/src/api/events/home-feed-updated.ts +26 -0
- package/src/api/events/identity-changed.ts +32 -0
- package/src/api/events/interaction-resolved.ts +50 -0
- package/src/api/events/message-complete.ts +10 -12
- package/src/api/events/message-dequeued.ts +21 -0
- package/src/api/events/message-queued-deleted.ts +23 -0
- package/src/api/events/message-queued.ts +22 -0
- package/src/api/events/message-request-complete.ts +29 -0
- package/src/api/events/navigate-settings.ts +20 -0
- package/src/api/events/notification-intent.ts +33 -0
- package/src/api/events/open-url.ts +6 -8
- package/src/api/events/question-request.ts +67 -0
- package/src/api/events/relationship-state-updated.ts +4 -6
- package/src/api/events/secret-request.ts +42 -0
- package/src/api/events/subagent-event.ts +79 -0
- package/src/api/events/subagent-spawned.ts +40 -0
- package/src/api/events/subagent-status-changed.ts +65 -0
- package/src/api/events/sync-changed.ts +29 -0
- package/src/api/events/tool-result.ts +129 -0
- package/src/api/events/tool-use-start.ts +8 -10
- package/src/api/events/turn-profile-auto-routed.ts +28 -0
- package/src/api/events/ui-surface-complete.ts +30 -0
- package/src/api/events/ui-surface-dismiss.ts +22 -0
- package/src/api/events/ui-surface-show.ts +67 -0
- package/src/api/events/ui-surface-update.ts +26 -0
- package/src/api/events/usage-update.ts +34 -0
- package/src/api/events/user-message-echo.ts +35 -0
- package/src/api/index.ts +354 -0
- package/src/api/requests/dictation.ts +45 -0
- package/src/api/responses/disk-pressure-status.ts +26 -0
- package/src/api/responses/home.ts +217 -0
- package/src/api/responses/llm-context-response.ts +2 -0
- package/src/api/responses/memory-v3-selection-log.ts +50 -0
- package/src/api/responses/subagent-detail.ts +48 -0
- package/src/approvals/guardian-decision-primitive.ts +7 -15
- package/src/approvals/guardian-request-resolvers.ts +6 -9
- package/src/avatar/__tests__/avatar-manifest.test.ts +236 -0
- package/src/avatar/__tests__/avatar-store.test.ts +193 -0
- package/src/avatar/avatar-manifest.ts +195 -0
- package/src/avatar/avatar-store.ts +113 -0
- package/src/avatar/traits-png-sync.ts +8 -2
- package/src/background-wake/next-wake.test.ts +31 -1
- package/src/background-wake/next-wake.ts +4 -1
- package/src/calls/call-conversation-messages.ts +6 -4
- package/src/calls/guardian-action-sweep.ts +6 -4
- package/src/calls/relay-server.ts +12 -8
- package/src/calls/voice-session-bridge.ts +13 -27
- package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
- package/src/cli/commands/avatar.ts +17 -11
- package/src/cli/commands/conversations.ts +15 -1
- package/src/cli/commands/db/__tests__/repair.test.ts +540 -0
- package/src/cli/commands/db/__tests__/status.test.ts +253 -0
- package/src/cli/commands/db/format.ts +48 -0
- package/src/cli/commands/db/index.ts +29 -0
- package/src/cli/commands/db/repair-step-conversation-backfill.ts +345 -0
- package/src/cli/commands/db/repair-step-integrity.ts +146 -0
- package/src/cli/commands/db/repair-steps.ts +164 -0
- package/src/cli/commands/db/repair.ts +141 -0
- package/src/cli/commands/db/status.ts +366 -0
- package/src/cli/commands/memory-v3.ts +159 -445
- package/src/cli/lib/cli-colors.ts +24 -6
- package/src/cli/program.ts +4 -5
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/assistant-feature-flags.ts +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -3
- package/src/config/bundled-skills/media-processing/services/reduce.ts +6 -9
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +7 -2
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/call-site-defaults.ts +2 -7
- package/src/config/feature-flag-registry.json +25 -9
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -226
- package/src/config/schemas/call-site-catalog.ts +8 -15
- package/src/config/schemas/llm.ts +2 -3
- package/src/config/schemas/memory-lifecycle.ts +24 -0
- package/src/config/schemas/memory-v2.ts +0 -253
- package/src/config/schemas/memory-v3.ts +39 -0
- package/src/config/schemas/memory.ts +6 -1
- package/src/config/schemas/timeouts.ts +3 -1
- package/src/context/compactor.ts +54 -31
- package/src/context/token-estimator.ts +19 -0
- package/src/context/tool-result-truncation.ts +1 -43
- package/src/context/window-manager.ts +138 -20
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +2 -2
- package/src/daemon/__tests__/web-search-status-text.test.ts +10 -6
- package/src/daemon/approval-generators.ts +4 -4
- package/src/daemon/config-watcher.ts +7 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +225 -88
- package/src/daemon/conversation-agent-loop.ts +284 -584
- package/src/daemon/conversation-error.ts +7 -7
- package/src/daemon/conversation-history.ts +22 -6
- package/src/daemon/conversation-launch.ts +4 -8
- package/src/daemon/conversation-lifecycle.ts +10 -38
- package/src/daemon/conversation-messaging.ts +1 -3
- package/src/daemon/conversation-notifiers.ts +7 -5
- package/src/daemon/conversation-process.ts +100 -79
- package/src/daemon/conversation-runtime-assembly.ts +47 -21
- package/src/daemon/conversation-store.ts +6 -5
- package/src/daemon/conversation-surfaces.ts +55 -69
- package/src/daemon/conversation-tool-setup.ts +3 -0
- package/src/daemon/conversation.ts +91 -126
- package/src/daemon/daemon-skill-host.ts +2 -6
- package/src/daemon/disk-pressure-guard.ts +35 -29
- package/src/daemon/external-plugins-bootstrap.ts +46 -24
- package/src/daemon/first-greeting.ts +26 -4
- package/src/daemon/guardian-action-generators.ts +2 -2
- package/src/daemon/handlers/conversations.ts +6 -22
- package/src/daemon/handlers/shared.ts +4 -0
- package/src/daemon/handlers/skills.ts +15 -14
- package/src/daemon/host-app-control-proxy.ts +54 -1
- package/src/daemon/host-cu-proxy.ts +46 -22
- package/src/daemon/host-file-proxy.ts +25 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -6
- package/src/daemon/lifecycle.ts +28 -55
- package/src/daemon/message-protocol.ts +2 -3
- package/src/daemon/message-provenance.ts +49 -0
- package/src/daemon/message-types/contacts.ts +3 -20
- package/src/daemon/message-types/conversations.ts +13 -111
- package/src/daemon/message-types/documents.ts +3 -9
- package/src/daemon/message-types/home.ts +4 -17
- package/src/daemon/message-types/integrations.ts +2 -6
- package/src/daemon/message-types/messages.ts +28 -343
- package/src/daemon/message-types/notifications.ts +2 -32
- package/src/daemon/message-types/settings.ts +3 -8
- package/src/daemon/message-types/skills.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/sync.ts +12 -25
- package/src/daemon/message-types/workspace.ts +3 -11
- package/src/daemon/process-message.ts +49 -46
- package/src/daemon/server.ts +12 -0
- package/src/daemon/tool-side-effects.ts +10 -7
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +11 -1
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -1
- package/src/heartbeat/heartbeat-run-store.ts +31 -0
- package/src/heartbeat/heartbeat-service.ts +16 -0
- package/src/home/feature-gate.ts +22 -0
- package/src/home/feed-types.ts +36 -221
- package/src/ipc/__tests__/email-ipc.test.ts +0 -9
- package/src/ipc/routes/__tests__/route-adapter.test.ts +244 -0
- package/src/ipc/routes/route-adapter.ts +45 -6
- package/src/ipc/skill-routes/__tests__/memory.test.ts +18 -9
- package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
- package/src/ipc/skill-routes/__tests__/registries.test.ts +28 -18
- package/src/ipc/skill-routes/memory.ts +26 -13
- package/src/ipc/skill-routes/providers.ts +5 -6
- package/src/ipc/skill-routes/registries.ts +13 -61
- package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -11
- package/src/memory/__tests__/conversation-queries.test.ts +192 -8
- package/src/memory/__tests__/db-maintenance.test.ts +128 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
- package/src/memory/__tests__/memory-retrospective-job.test.ts +10 -6
- package/src/memory/__tests__/memory-v3-selections-migration.test.ts +103 -0
- package/src/memory/context-search/agent-runner.ts +2 -4
- package/src/memory/conversation-crud.ts +39 -8
- package/src/memory/conversation-queries.ts +78 -22
- package/src/memory/db-init.ts +8 -0
- package/src/memory/db-maintenance.ts +18 -2
- package/src/memory/graph/consolidation.ts +8 -11
- package/src/memory/graph/conversation-graph-memory.ts +41 -8
- package/src/memory/graph/extraction.ts +6 -9
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.ts +20 -26
- package/src/memory/graph/tools.ts +4 -4
- package/src/memory/job-handlers/conversation-starters.ts +32 -32
- package/src/memory/job-handlers/summarization.ts +1 -2
- package/src/memory/jobs-store.ts +3 -1
- package/src/memory/jobs-worker.ts +51 -39
- package/src/memory/llm-request-log-source-clickhouse.ts +5 -31
- package/src/memory/llm-request-log-source-local.ts +0 -11
- package/src/memory/llm-request-log-source.ts +9 -25
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +10 -0
- package/src/memory/memory-marker.ts +17 -0
- package/src/memory/memory-retrospective-job.ts +6 -2
- package/src/memory/memory-v2-activation-log-store.ts +1 -83
- package/src/memory/migrations/267-llm-usage-events-add-assistant-version.ts +46 -0
- package/src/memory/migrations/268-add-memory-v3-selections.ts +28 -0
- package/src/memory/migrations/269-schedule-script-timeout.ts +11 -0
- package/src/memory/migrations/270-messages-role-created-at-index.ts +18 -0
- package/src/memory/migrations/__tests__/267-llm-usage-events-add-assistant-version.test.ts +117 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/schema/infrastructure.ts +11 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +124 -0
- package/src/memory/v2/__tests__/migration.test.ts +11 -3
- package/src/memory/v2/__tests__/page-index.test.ts +37 -1
- package/src/memory/v2/__tests__/router.test.ts +14 -4
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -5
- package/src/memory/v2/backfill-jobs.ts +6 -0
- package/src/memory/v2/consolidation-job.ts +89 -9
- package/src/memory/v2/migration.ts +5 -3
- package/src/memory/v2/page-index.ts +11 -0
- package/src/memory/v2/router.ts +8 -11
- package/src/memory/v2/sweep-job.ts +8 -11
- package/src/memory/v2/types.ts +1 -0
- package/src/memory/v3/__tests__/assign.test.ts +242 -0
- package/src/memory/v3/__tests__/capabilities.test.ts +118 -0
- package/src/memory/v3/__tests__/core.test.ts +39 -0
- package/src/memory/v3/__tests__/fixtures/eval-turns.json +36 -0
- package/src/memory/v3/__tests__/fixtures/live-turns.json +37 -0
- package/src/memory/v3/__tests__/health.test.ts +203 -0
- package/src/memory/v3/__tests__/live-integration.test.ts +330 -0
- package/src/memory/v3/__tests__/maintain-job.test.ts +288 -0
- package/src/memory/v3/__tests__/needle.test.ts +107 -0
- package/src/memory/v3/__tests__/orchestrate.test.ts +400 -0
- package/src/memory/v3/__tests__/reconcile.test.ts +274 -0
- package/src/memory/v3/__tests__/render-injection.test.ts +61 -0
- package/src/memory/v3/__tests__/router.test.ts +260 -0
- package/src/memory/v3/__tests__/selection-log-store.test.ts +179 -0
- package/src/memory/v3/__tests__/selector.test.ts +404 -0
- package/src/memory/v3/__tests__/shadow-plugin.test.ts +414 -0
- package/src/memory/v3/__tests__/snapshot.test.ts +168 -0
- package/src/memory/v3/__tests__/tree.test.ts +192 -0
- package/src/memory/v3/__tests__/types.test.ts +54 -0
- package/src/memory/v3/__tests__/working-set-eviction.test.ts +106 -0
- package/src/memory/v3/__tests__/working-set-skeleton.test.ts +44 -0
- package/src/memory/v3/assign.ts +268 -0
- package/src/memory/v3/capabilities.ts +124 -0
- package/src/memory/v3/core.ts +26 -0
- package/src/memory/v3/data/README.md +84 -0
- package/src/memory/v3/data/assignments.json +5 -0
- package/src/memory/v3/data/core.json +1 -0
- package/src/memory/v3/data/leaves/domain-a/topic-x.md +9 -0
- package/src/memory/v3/data/leaves/domain-a/topic-y.md +9 -0
- package/src/memory/v3/data/leaves/domain-b/topic-z.md +9 -0
- package/src/memory/v3/health.ts +0 -0
- package/src/memory/v3/maintain-job.ts +314 -0
- package/src/memory/v3/needle.ts +115 -0
- package/src/memory/v3/orchestrate.ts +114 -0
- package/src/memory/v3/page-content.ts +34 -0
- package/src/memory/v3/provider-blocks.ts +16 -0
- package/src/memory/v3/reconcile.ts +523 -0
- package/src/memory/v3/render-injection.ts +32 -0
- package/src/memory/v3/router.ts +184 -0
- package/src/memory/v3/selection-log-store.ts +84 -0
- package/src/memory/v3/selector.ts +211 -0
- package/src/memory/v3/shadow-plugin.ts +379 -0
- package/src/memory/v3/snapshot.ts +209 -0
- package/src/memory/v3/tree.ts +174 -0
- package/src/memory/v3/types.ts +46 -60
- package/src/memory/v3/working-set.ts +88 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1 -1
- package/src/messaging/providers/slack/render-transcript.ts +2 -2
- package/src/messaging/style-analyzer.ts +8 -11
- package/src/notifications/conversation-pairing.ts +8 -6
- package/src/notifications/decision-engine.ts +10 -13
- package/src/notifications/preference-extractor.ts +11 -14
- package/src/permissions/prompter.ts +42 -36
- package/src/permissions/question-prompter.test.ts +35 -26
- package/src/permissions/question-prompter.ts +6 -10
- package/src/plugin-api/index.ts +2 -0
- package/src/plugin-api/types.ts +25 -3
- package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +93 -0
- package/src/plugins/defaults/circuit-breaker/package.json +15 -0
- package/src/plugins/defaults/circuit-breaker/register.ts +39 -0
- package/src/plugins/defaults/compaction/middlewares/compaction.ts +25 -0
- package/src/plugins/defaults/compaction/package.json +15 -0
- package/src/plugins/defaults/compaction/register.ts +35 -0
- package/src/plugins/defaults/compaction/terminal.ts +73 -0
- package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +22 -0
- package/src/plugins/defaults/empty-response/package.json +15 -0
- package/src/plugins/defaults/empty-response/register.ts +28 -0
- package/src/plugins/defaults/empty-response/terminal.ts +106 -0
- package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/history-repair/package.json +15 -0
- package/src/plugins/defaults/history-repair/register.ts +24 -0
- package/src/{daemon/history-repair.ts → plugins/defaults/history-repair/terminal.ts} +48 -35
- package/src/plugins/defaults/index.ts +29 -40
- package/src/plugins/defaults/injectors/package.json +15 -0
- package/src/plugins/defaults/{injectors.ts → injectors/register.ts} +14 -38
- package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +17 -0
- package/src/plugins/defaults/llm-call/package.json +15 -0
- package/src/plugins/defaults/{llm-call.ts → llm-call/register.ts} +6 -38
- package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +17 -0
- package/src/plugins/defaults/memory-retrieval/package.json +15 -0
- package/src/plugins/defaults/{memory-retrieval.ts → memory-retrieval/register.ts} +10 -48
- package/src/plugins/defaults/{overflow-reduce.ts → overflow-reduce/middlewares/overflowReduce.ts} +18 -77
- package/src/plugins/defaults/overflow-reduce/package.json +15 -0
- package/src/plugins/defaults/overflow-reduce/register.ts +42 -0
- package/src/plugins/defaults/persistence/middlewares/persistence.ts +19 -0
- package/src/plugins/defaults/persistence/package.json +15 -0
- package/src/plugins/defaults/persistence/register.ts +38 -0
- package/src/plugins/defaults/persistence/terminal.ts +83 -0
- package/src/plugins/defaults/title-generate/package.json +15 -0
- package/src/plugins/defaults/title-generate/register.ts +35 -0
- package/src/plugins/defaults/title-generate/terminal.ts +31 -0
- package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +23 -0
- package/src/plugins/defaults/token-estimate/package.json +15 -0
- package/src/plugins/defaults/token-estimate/register.ts +34 -0
- package/src/plugins/defaults/token-estimate/terminal.ts +40 -0
- package/src/plugins/defaults/tool-error/middlewares/toolError.ts +21 -0
- package/src/plugins/defaults/tool-error/package.json +15 -0
- package/src/plugins/defaults/tool-error/register.ts +35 -0
- package/src/plugins/defaults/tool-error/terminal.ts +47 -0
- package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +23 -0
- package/src/plugins/defaults/tool-execute/package.json +15 -0
- package/src/plugins/defaults/{tool-execute.ts → tool-execute/register.ts} +8 -46
- package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +23 -0
- package/src/plugins/defaults/tool-result-truncate/package.json +15 -0
- package/src/plugins/defaults/tool-result-truncate/register.ts +35 -0
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +113 -0
- package/src/plugins/defaults/tool-result-truncate/types.ts +22 -0
- package/src/plugins/external-plugin-loader.ts +2 -2
- package/src/plugins/pipeline.ts +0 -12
- package/src/plugins/types.ts +51 -90
- package/src/plugins/user-loader.ts +4 -3
- package/src/proactive-artifact/aux-message-injector.ts +0 -1
- package/src/proactive-artifact/job.test.ts +20 -8
- package/src/proactive-artifact/job.ts +3 -1
- package/src/prompts/sections.ts +20 -7
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
- package/src/prompts/templates/BOOTSTRAP.md +5 -1
- package/src/prompts/templates/system-sections.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -25
- package/src/providers/__tests__/satellite-connection-routing.test.ts +7 -21
- package/src/providers/anthropic/client.ts +24 -5
- package/src/providers/call-site-routing.ts +1 -9
- package/src/providers/gemini/client.ts +152 -34
- package/src/providers/gemini/inline-media.ts +74 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +0 -2
- package/src/providers/openai/chat-completions-provider.ts +1 -4
- package/src/providers/openai/responses-provider.ts +1 -4
- package/src/providers/openrouter/client.ts +1 -6
- package/src/providers/provider-send-message.ts +6 -6
- package/src/providers/ratelimit.ts +1 -9
- package/src/providers/retry.ts +0 -5
- package/src/providers/types.ts +11 -2
- package/src/providers/usage-tracking.ts +1 -9
- package/src/runtime/__tests__/agent-wake.test.ts +131 -26
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -3
- package/src/runtime/agent-wake.ts +93 -18
- package/src/runtime/assistant-event-hub.ts +2 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +75 -109
- package/src/runtime/auth/__tests__/route-policy.test.ts +153 -170
- package/src/runtime/auth/route-policy.ts +42 -1079
- package/src/runtime/background-job-runner.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -1
- package/src/runtime/channel-approvals.ts +3 -14
- package/src/runtime/channel-invite-transport.ts +5 -6
- package/src/runtime/channel-readiness-service.ts +2 -5
- package/src/runtime/channel-retry-sweep.ts +12 -16
- package/src/runtime/conversation-stream-state.ts +294 -0
- package/src/runtime/http-router.ts +19 -22
- package/src/runtime/http-types.ts +12 -6
- package/src/runtime/invite-instruction-generator.ts +3 -3
- package/src/runtime/pending-interactions.ts +2 -2
- package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +565 -0
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +62 -32
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -22
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +7 -2
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
- package/src/runtime/routes/__tests__/stt-routes.test.ts +3 -3
- package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +5 -2
- package/src/runtime/routes/__tests__/tts-routes.test.ts +3 -3
- package/src/runtime/routes/acp-routes.test.ts +97 -75
- package/src/runtime/routes/acp-routes.ts +29 -6
- package/src/runtime/routes/app-management-routes.ts +97 -24
- package/src/runtime/routes/app-routes.ts +25 -5
- package/src/runtime/routes/approval-routes.ts +16 -4
- package/src/runtime/routes/attachment-routes.ts +25 -1
- package/src/runtime/routes/audio-routes.ts +1 -0
- package/src/runtime/routes/audit-routes.ts +5 -0
- package/src/runtime/routes/auth-routes.ts +5 -0
- package/src/runtime/routes/avatar-routes.ts +238 -59
- package/src/runtime/routes/background-tool-routes.ts +9 -0
- package/src/runtime/routes/background-wake-routes.ts +13 -3
- package/src/runtime/routes/backup-routes.ts +45 -0
- package/src/runtime/routes/bookmark-routes.ts +13 -0
- package/src/runtime/routes/brain-graph-routes.ts +9 -0
- package/src/runtime/routes/browser-routes.ts +5 -0
- package/src/runtime/routes/browser-tabs-routes.ts +5 -0
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/cache-routes.ts +13 -0
- package/src/runtime/routes/call-routes.ts +21 -10
- package/src/runtime/routes/channel-availability-routes.ts +5 -1
- package/src/runtime/routes/channel-readiness-routes.ts +37 -4
- package/src/runtime/routes/channel-route-definitions.ts +21 -0
- package/src/runtime/routes/channel-verification-routes.ts +21 -0
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +9 -2
- package/src/runtime/routes/client-routes.ts +9 -0
- package/src/runtime/routes/consolidation-routes.ts +13 -5
- package/src/runtime/routes/contact-prompt-routes.ts +9 -0
- package/src/runtime/routes/contact-routes.ts +90 -23
- package/src/runtime/routes/content-source-routes.ts +5 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +5 -1
- package/src/runtime/routes/conversation-attention-routes.ts +5 -0
- package/src/runtime/routes/conversation-cli-routes.ts +54 -7
- package/src/runtime/routes/conversation-compaction-routes.ts +54 -25
- package/src/runtime/routes/conversation-list-routes.ts +81 -12
- package/src/runtime/routes/conversation-management-routes.ts +57 -14
- package/src/runtime/routes/conversation-query-routes.ts +88 -41
- package/src/runtime/routes/conversation-routes.ts +74 -19
- package/src/runtime/routes/conversation-starter-routes.ts +22 -13
- package/src/runtime/routes/conversations-import-routes.ts +6 -1
- package/src/runtime/routes/credential-prompt-routes.ts +5 -0
- package/src/runtime/routes/credential-routes.ts +25 -6
- package/src/runtime/routes/debug-bash-routes.ts +5 -0
- package/src/runtime/routes/debug-routes.ts +11 -2
- package/src/runtime/routes/defer-routes.ts +13 -0
- package/src/runtime/routes/diagnostics-routes.ts +37 -46
- package/src/runtime/routes/disk-pressure-routes.ts +17 -31
- package/src/runtime/routes/document-comments-routes.ts +46 -27
- package/src/runtime/routes/documents-routes.ts +21 -10
- package/src/runtime/routes/domain-routes.ts +61 -28
- package/src/runtime/routes/email-routes.ts +33 -0
- package/src/runtime/routes/events-routes.ts +114 -9
- package/src/runtime/routes/filing-routes.ts +9 -4
- package/src/runtime/routes/gateway-log-routes.ts +5 -0
- package/src/runtime/routes/global-search-routes.ts +53 -50
- package/src/runtime/routes/group-routes.ts +21 -5
- package/src/runtime/routes/guardian-action-routes.ts +9 -0
- package/src/runtime/routes/guardian-approval-interception.ts +0 -31
- package/src/runtime/routes/heartbeat-routes.ts +25 -9
- package/src/runtime/routes/home-feed-routes.ts +23 -19
- package/src/runtime/routes/home-state-routes.ts +8 -40
- package/src/runtime/routes/host-app-control-routes.ts +5 -0
- package/src/runtime/routes/host-bash-routes.ts +5 -0
- package/src/runtime/routes/host-browser-routes.ts +13 -0
- package/src/runtime/routes/host-cu-routes.ts +5 -0
- package/src/runtime/routes/host-file-routes.ts +26 -6
- package/src/runtime/routes/host-transfer-routes.ts +13 -2
- package/src/runtime/routes/http-adapter.ts +1 -2
- package/src/runtime/routes/identity-intro-cache.ts +17 -6
- package/src/runtime/routes/identity-routes.ts +12 -2
- package/src/runtime/routes/image-generation-routes.ts +5 -0
- package/src/runtime/routes/inbound-message-handler.ts +15 -11
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +15 -19
- package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
- package/src/runtime/routes/inference-provider-connection-routes.ts +21 -5
- package/src/runtime/routes/inference-send-routes.ts +11 -11
- package/src/runtime/routes/integrations/a2a.ts +30 -7
- package/src/runtime/routes/integrations/slack/channel.ts +19 -3
- package/src/runtime/routes/integrations/slack/share.ts +9 -2
- package/src/runtime/routes/integrations/telegram.ts +28 -9
- package/src/runtime/routes/integrations/twilio.ts +35 -7
- package/src/runtime/routes/integrations/vercel.ts +3 -3
- package/src/runtime/routes/internal-oauth-routes.ts +5 -0
- package/src/runtime/routes/internal-twilio-routes.ts +13 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +39 -4
- package/src/runtime/routes/log-export-routes.ts +28 -10
- package/src/runtime/routes/mcp-auth-routes.ts +25 -0
- package/src/runtime/routes/memory-item-routes.ts +21 -10
- package/src/runtime/routes/memory-v2-routes.ts +90 -36
- package/src/runtime/routes/memory-v3-routes.ts +273 -407
- package/src/runtime/routes/migration-rollback-routes.ts +5 -1
- package/src/runtime/routes/migration-routes.ts +29 -0
- package/src/runtime/routes/notification-routes.ts +17 -1
- package/src/runtime/routes/oauth-apps.ts +33 -11
- package/src/runtime/routes/oauth-commands-routes.ts +37 -14
- package/src/runtime/routes/oauth-connect-routes.ts +9 -0
- package/src/runtime/routes/oauth-lifecycle-routes.ts +5 -1
- package/src/runtime/routes/oauth-providers.ts +35 -10
- package/src/runtime/routes/platform-routes.ts +21 -0
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +3 -2
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +37 -16
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +7 -3
- package/src/runtime/routes/playground/__tests__/state.test.ts +10 -3
- package/src/runtime/routes/playground/force-compact.ts +1 -1
- package/src/runtime/routes/playground/helpers.ts +0 -1
- package/src/runtime/routes/playground/inject-failures.ts +13 -8
- package/src/runtime/routes/playground/reset-circuit.ts +14 -9
- package/src/runtime/routes/playground/seed-conversation.ts +1 -1
- package/src/runtime/routes/playground/seeded-conversations.ts +3 -3
- package/src/runtime/routes/playground/state.ts +4 -3
- package/src/runtime/routes/plugins-routes.ts +22 -19
- package/src/runtime/routes/profiler-routes.ts +17 -4
- package/src/runtime/routes/ps-routes.ts +5 -0
- package/src/runtime/routes/publish-routes.ts +13 -3
- package/src/runtime/routes/question-routes.ts +5 -0
- package/src/runtime/routes/recording-routes.ts +25 -12
- package/src/runtime/routes/rename-conversation-routes.ts +5 -0
- package/src/runtime/routes/sanity-routes.ts +9 -2
- package/src/runtime/routes/schedule-routes.ts +137 -47
- package/src/runtime/routes/secret-routes.ts +17 -4
- package/src/runtime/routes/sequence-routes.ts +33 -0
- package/src/runtime/routes/settings-routes.ts +65 -19
- package/src/runtime/routes/skills-routes.ts +133 -69
- package/src/runtime/routes/slack-channel-routes.ts +5 -0
- package/src/runtime/routes/stt-routes.ts +13 -6
- package/src/runtime/routes/subagents-routes.ts +24 -18
- package/src/runtime/routes/suggest-trust-rule-routes.ts +7 -2
- package/src/runtime/routes/surface-action-routes.ts +9 -0
- package/src/runtime/routes/surface-content-routes.ts +10 -2
- package/src/runtime/routes/task-routes.ts +37 -0
- package/src/runtime/routes/telemetry-routes.ts +9 -0
- package/src/runtime/routes/trace-event-routes.ts +42 -1
- package/src/runtime/routes/trust-rules-routes.ts +5 -0
- package/src/runtime/routes/tts-routes.ts +13 -6
- package/src/runtime/routes/types.ts +17 -8
- package/src/runtime/routes/ui-request-routes.ts +5 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +5 -0
- package/src/runtime/routes/usage-routes.ts +71 -3
- package/src/runtime/routes/user-routes-cli.ts +9 -0
- package/src/runtime/routes/user-routes.ts +5 -1
- package/src/runtime/routes/wake-conversation-routes.ts +5 -0
- package/src/runtime/routes/watcher-routes.ts +21 -0
- package/src/runtime/routes/webhook-routes.ts +9 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +5 -0
- package/src/runtime/routes/work-items-routes.ts +47 -19
- package/src/runtime/routes/workspace-commit-routes.ts +5 -0
- package/src/runtime/routes/workspace-routes.test.ts +42 -0
- package/src/runtime/routes/workspace-routes.ts +120 -9
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -4
- package/src/runtime/services/analyze-conversation.ts +3 -6
- package/src/runtime/services/conversation-serializer.ts +24 -2
- package/src/runtime/sync/resource-sync-events.ts +16 -2
- package/src/runtime/sync/sync-publisher.ts +2 -2
- package/src/schedule/run-script.ts +28 -3
- package/src/schedule/schedule-store.ts +8 -0
- package/src/schedule/scheduler.ts +3 -1
- package/src/signals/user-message.ts +5 -8
- package/src/skills/catalog-files.ts +4 -1
- package/src/skills/clawhub-files.ts +2 -0
- package/src/skills/skillssh-files.ts +2 -0
- package/src/subagent/manager.ts +3 -6
- package/src/telemetry/types.ts +26 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +138 -1
- package/src/telemetry/usage-telemetry-reporter.ts +31 -0
- package/src/tools/acp/spawn.test.ts +88 -38
- package/src/tools/apps/definitions.ts +8 -4
- package/src/tools/ask-question/ask-question-tool.test.ts +120 -105
- package/src/tools/ask-question/ask-question-tool.ts +85 -90
- package/src/tools/computer-use/definitions.ts +28 -24
- package/src/tools/credential-execution/make-authenticated-request.ts +56 -51
- package/src/tools/credential-execution/manage-secure-command-tool.ts +2 -2
- package/src/tools/credential-execution/run-authenticated-command.ts +82 -77
- package/src/tools/credentials/vault.ts +112 -111
- package/src/tools/execution-target.ts +1 -1
- package/src/tools/execution-timeout.ts +3 -4
- package/src/tools/filesystem/edit.ts +45 -42
- package/src/tools/filesystem/list.ts +33 -30
- package/src/tools/filesystem/read.ts +54 -35
- package/src/tools/filesystem/write.ts +34 -31
- package/src/tools/host-filesystem/edit.ts +44 -42
- package/src/tools/host-filesystem/read.ts +49 -35
- package/src/tools/host-filesystem/transfer.ts +121 -108
- package/src/tools/host-filesystem/write.ts +33 -31
- package/src/tools/host-terminal/host-shell.ts +50 -48
- package/src/tools/memory/register.ts +23 -24
- package/src/tools/network/web-fetch.ts +49 -46
- package/src/tools/network/web-search.ts +16 -13
- package/src/tools/registry.ts +39 -16
- package/src/tools/schedule/create.ts +11 -0
- package/src/tools/schedule/update.ts +16 -0
- package/src/tools/shared/filesystem/audio-read.ts +122 -0
- package/src/tools/shared/filesystem/image-read.ts +1 -1
- package/src/tools/skills/execute.ts +34 -31
- package/src/tools/skills/load.ts +29 -23
- package/src/tools/subagent/notify-parent.ts +35 -32
- package/src/tools/system/avatar-generator.ts +13 -22
- package/src/tools/system/request-permission.ts +30 -27
- package/src/tools/terminal/shell.ts +190 -61
- package/src/tools/tool-defaults.ts +20 -9
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +74 -23
- package/src/tools/ui-surface/definitions.ts +69 -9
- package/src/usage/types.ts +10 -0
- package/src/util/errors.ts +2 -2
- package/src/util/map-limit.ts +27 -0
- package/src/util/platform.ts +15 -12
- package/src/work-items/work-item-runner.ts +7 -2
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +7 -20
- package/src/workspace/migrations/092-backfill-v3-leaves.ts +169 -0
- package/src/workspace/migrations/093-backfill-leaf-ids.ts +144 -0
- package/src/workspace/migrations/094-seed-avatar-manifest.ts +155 -0
- package/src/workspace/migrations/__tests__/094-seed-avatar-manifest.test.ts +136 -0
- package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +175 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +124 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/provider-commit-message-generator.ts +15 -17
- package/tsconfig.json +4 -1
- package/src/__tests__/history-repair-pipeline.test.ts +0 -396
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +0 -340
- package/src/cli/commands/memory-v3-render.ts +0 -491
- package/src/daemon/message-types/disk-pressure.ts +0 -9
- package/src/email/feature-gate.ts +0 -23
- package/src/memory/v3/__tests__/coactivation-store.test.ts +0 -422
- package/src/memory/v3/__tests__/consolidation-job.test.ts +0 -466
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +0 -270
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
- package/src/memory/v3/__tests__/edges.test.ts +0 -706
- package/src/memory/v3/__tests__/filter.test.ts +0 -560
- package/src/memory/v3/__tests__/gate.test.ts +0 -637
- package/src/memory/v3/__tests__/index-composition.test.ts +0 -291
- package/src/memory/v3/__tests__/loop.test.ts +0 -775
- package/src/memory/v3/__tests__/retriever.test.ts +0 -226
- package/src/memory/v3/__tests__/scouts.test.ts +0 -489
- package/src/memory/v3/__tests__/shadow-diff.test.ts +0 -225
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -398
- package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
- package/src/memory/v3/__tests__/traversal.test.ts +0 -508
- package/src/memory/v3/__tests__/tree-index.test.ts +0 -280
- package/src/memory/v3/__tests__/tree-store.test.ts +0 -529
- package/src/memory/v3/__tests__/tree-walk.test.ts +0 -784
- package/src/memory/v3/__tests__/validate.test.ts +0 -277
- package/src/memory/v3/auto-edges.ts +0 -223
- package/src/memory/v3/coactivation-store.ts +0 -124
- package/src/memory/v3/consolidation-job.ts +0 -323
- package/src/memory/v3/coretrieval-seed.ts +0 -240
- package/src/memory/v3/edge-learning-job.ts +0 -160
- package/src/memory/v3/edges.ts +0 -286
- package/src/memory/v3/filter.ts +0 -286
- package/src/memory/v3/gate.ts +0 -349
- package/src/memory/v3/index-composition.ts +0 -126
- package/src/memory/v3/llm-capture.ts +0 -46
- package/src/memory/v3/loop.ts +0 -430
- package/src/memory/v3/maintenance.ts +0 -144
- package/src/memory/v3/prompt-context.ts +0 -33
- package/src/memory/v3/prompts/consolidation.ts +0 -458
- package/src/memory/v3/prompts/system-prompts.ts +0 -196
- package/src/memory/v3/retriever.ts +0 -33
- package/src/memory/v3/scouts.ts +0 -431
- package/src/memory/v3/shadow-diff.ts +0 -287
- package/src/memory/v3/shadow-middleware.ts +0 -347
- package/src/memory/v3/traversal.ts +0 -211
- package/src/memory/v3/tree-index.ts +0 -237
- package/src/memory/v3/tree-store.ts +0 -394
- package/src/memory/v3/tree-walk.ts +0 -356
- package/src/memory/v3/validate.ts +0 -323
- package/src/plugins/defaults/circuit-breaker.ts +0 -141
- package/src/plugins/defaults/compaction.ts +0 -141
- package/src/plugins/defaults/empty-response.ts +0 -124
- package/src/plugins/defaults/history-repair.ts +0 -83
- package/src/plugins/defaults/persistence.ts +0 -146
- package/src/plugins/defaults/title-generate.ts +0 -90
- package/src/plugins/defaults/token-estimate.ts +0 -101
- package/src/plugins/defaults/tool-error.ts +0 -119
- package/src/plugins/defaults/tool-result-truncate.ts +0 -84
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +0 -35
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type * as genai from "@google/genai";
|
|
2
2
|
import { ApiError, GoogleGenAI, ThinkingLevel } from "@google/genai";
|
|
3
3
|
|
|
4
|
+
import {
|
|
5
|
+
THINKING_LEVELS,
|
|
6
|
+
type ThinkingLevel as ThinkingLevelName,
|
|
7
|
+
} from "../../config/schemas/llm.js";
|
|
4
8
|
import { isAbortReason } from "../../util/abort-reasons.js";
|
|
5
9
|
import { ProviderError } from "../../util/errors.js";
|
|
6
10
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -12,12 +16,16 @@ import type {
|
|
|
12
16
|
Provider,
|
|
13
17
|
ProviderResponse,
|
|
14
18
|
SendMessageOptions,
|
|
15
|
-
ToolDefinition,
|
|
16
19
|
} from "../types.js";
|
|
17
20
|
import {
|
|
18
21
|
ContextOverflowError,
|
|
19
22
|
extractOverflowTokensFromMessage,
|
|
20
23
|
} from "../types.js";
|
|
24
|
+
import {
|
|
25
|
+
base64ByteLength,
|
|
26
|
+
GEMINI_MAX_INLINE_AUDIO_BYTES,
|
|
27
|
+
normalizeGeminiAudioMime,
|
|
28
|
+
} from "./inline-media.js";
|
|
21
29
|
|
|
22
30
|
/**
|
|
23
31
|
* Token/context-specific phrases that reliably indicate context-overflow
|
|
@@ -34,40 +42,100 @@ function isGemini3Model(model: string): boolean {
|
|
|
34
42
|
return model.startsWith("gemini-3") || model.startsWith("models/gemini-3");
|
|
35
43
|
}
|
|
36
44
|
|
|
37
|
-
const THINKING_LEVEL_BY_NAME: Record<
|
|
45
|
+
const THINKING_LEVEL_BY_NAME: Record<ThinkingLevelName, ThinkingLevel> = {
|
|
38
46
|
minimal: ThinkingLevel.MINIMAL,
|
|
39
47
|
low: ThinkingLevel.LOW,
|
|
40
48
|
medium: ThinkingLevel.MEDIUM,
|
|
41
49
|
high: ThinkingLevel.HIGH,
|
|
42
50
|
};
|
|
43
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Default thinking level for Gemini Pro models when the profile doesn't pin
|
|
54
|
+
* one. Pro rejects `"minimal"` and an absent level resolves to `"minimal"`
|
|
55
|
+
* upstream, so we pin Google's documented Pro default (`"high"`) — always a
|
|
56
|
+
* supported value.
|
|
57
|
+
*/
|
|
58
|
+
const GEMINI_PRO_DEFAULT_THINKING_LEVEL: ThinkingLevelName = "high";
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Gemini 3.x Pro family accepts only `low`/`medium`/`high` (no `"minimal"`) and
|
|
62
|
+
* cannot fully disable thinking. Matches `gemini-3.1-pro-preview`,
|
|
63
|
+
* `gemini-3.1-pro-preview-customtools`, and future `gemini-3*pro*`.
|
|
64
|
+
*/
|
|
65
|
+
function isGeminiProModel(model: string): boolean {
|
|
66
|
+
const normalized = model.startsWith("models/")
|
|
67
|
+
? model.slice("models/".length)
|
|
68
|
+
: model;
|
|
69
|
+
return /^gemini-3.*pro/.test(normalized);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Lowest thinking level the model accepts. Pro's floor is `"low"`; every other
|
|
74
|
+
* thinking-capable Gemini model accepts `"minimal"`.
|
|
75
|
+
*/
|
|
76
|
+
function geminiThinkingFloor(model: string): ThinkingLevelName {
|
|
77
|
+
return isGeminiProModel(model) ? "low" : "minimal";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Raise `level` to `floor` when it sits below it, so we never send a level the
|
|
82
|
+
* model rejects (e.g. `"minimal"` to a Pro model).
|
|
83
|
+
*/
|
|
84
|
+
function clampThinkingLevelToFloor(
|
|
85
|
+
level: ThinkingLevelName,
|
|
86
|
+
floor: ThinkingLevelName,
|
|
87
|
+
): ThinkingLevelName {
|
|
88
|
+
return THINKING_LEVELS.indexOf(level) < THINKING_LEVELS.indexOf(floor)
|
|
89
|
+
? floor
|
|
90
|
+
: level;
|
|
91
|
+
}
|
|
92
|
+
|
|
44
93
|
/**
|
|
45
94
|
* Translate the resolved wire-shape `thinking` config into Gemini's
|
|
46
|
-
* `thinkingConfig
|
|
47
|
-
*
|
|
48
|
-
*
|
|
95
|
+
* `thinkingConfig`, guaranteeing the emitted `thinkingLevel` is one the model
|
|
96
|
+
* accepts. Returns `undefined` when nothing needs to be set, which lets
|
|
97
|
+
* Google's per-model default apply (e.g. `gemini-3.5-flash` defaults to
|
|
98
|
+
* dynamic medium-level thinking).
|
|
99
|
+
*
|
|
100
|
+
* - `enabled: false` maps to the model's floor — the most "off" state it
|
|
101
|
+
* allows (`"minimal"` for most models, `"low"` for Pro, which can't disable
|
|
102
|
+
* thinking).
|
|
103
|
+
* - An explicit `level` below the floor is raised to the floor.
|
|
104
|
+
* - When no `level` is pinned, Pro models get the documented default (`"high"`)
|
|
105
|
+
* because an absent level resolves to the unsupported `"minimal"` upstream;
|
|
106
|
+
* other models keep Google's per-model default by leaving the level unset.
|
|
49
107
|
*
|
|
50
|
-
* `
|
|
51
|
-
*
|
|
52
|
-
* gated on `streamThinking` so callers that opted out of streaming thoughts
|
|
53
|
-
* don't pay for thought tokens in the response.
|
|
108
|
+
* `includeThoughts` is gated on `streamThinking` so callers that opted out of
|
|
109
|
+
* streaming thoughts don't pay for thought tokens in the response.
|
|
54
110
|
*/
|
|
55
111
|
function buildThinkingConfig(
|
|
56
112
|
thinking: Record<string, unknown> | undefined,
|
|
113
|
+
model: string,
|
|
57
114
|
): genai.ThinkingConfig | undefined {
|
|
58
115
|
if (!thinking) return undefined;
|
|
116
|
+
const floor = geminiThinkingFloor(model);
|
|
117
|
+
|
|
59
118
|
if (thinking.type === "disabled") {
|
|
60
119
|
return {
|
|
61
|
-
thinkingLevel:
|
|
120
|
+
thinkingLevel: THINKING_LEVEL_BY_NAME[floor],
|
|
62
121
|
includeThoughts: false,
|
|
63
122
|
};
|
|
64
123
|
}
|
|
65
124
|
if (thinking.type !== "adaptive") return undefined;
|
|
66
125
|
|
|
67
126
|
const result: genai.ThinkingConfig = {};
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
127
|
+
if (
|
|
128
|
+
typeof thinking.level === "string" &&
|
|
129
|
+
thinking.level in THINKING_LEVEL_BY_NAME
|
|
130
|
+
) {
|
|
131
|
+
const clamped = clampThinkingLevelToFloor(
|
|
132
|
+
thinking.level as ThinkingLevelName,
|
|
133
|
+
floor,
|
|
134
|
+
);
|
|
135
|
+
result.thinkingLevel = THINKING_LEVEL_BY_NAME[clamped];
|
|
136
|
+
} else if (isGeminiProModel(model)) {
|
|
137
|
+
result.thinkingLevel =
|
|
138
|
+
THINKING_LEVEL_BY_NAME[GEMINI_PRO_DEFAULT_THINKING_LEVEL];
|
|
71
139
|
}
|
|
72
140
|
if (typeof thinking.streamThinking === "boolean") {
|
|
73
141
|
result.includeThoughts = thinking.streamThinking;
|
|
@@ -223,11 +291,9 @@ export class GeminiProvider implements Provider {
|
|
|
223
291
|
|
|
224
292
|
async sendMessage(
|
|
225
293
|
messages: Message[],
|
|
226
|
-
tools?: ToolDefinition[],
|
|
227
|
-
systemPrompt?: string,
|
|
228
294
|
options?: SendMessageOptions,
|
|
229
295
|
): Promise<ProviderResponse> {
|
|
230
|
-
const { config, onEvent, signal } = options ?? {};
|
|
296
|
+
const { tools, systemPrompt, config, onEvent, signal } = options ?? {};
|
|
231
297
|
const configObj = config as Record<string, unknown> | undefined;
|
|
232
298
|
const maxTokens = configObj?.max_tokens as number | undefined;
|
|
233
299
|
const modelOverride = configObj?.model as string | undefined;
|
|
@@ -238,6 +304,7 @@ export class GeminiProvider implements Provider {
|
|
|
238
304
|
const thinkingConfig = geminiModelSupportsThinking(activeModel)
|
|
239
305
|
? buildThinkingConfig(
|
|
240
306
|
configObj?.thinking as Record<string, unknown> | undefined,
|
|
307
|
+
activeModel,
|
|
241
308
|
)
|
|
242
309
|
: undefined;
|
|
243
310
|
|
|
@@ -296,6 +363,7 @@ export class GeminiProvider implements Provider {
|
|
|
296
363
|
let finishReason = "unknown";
|
|
297
364
|
let promptTokens = 0;
|
|
298
365
|
let outputTokens = 0;
|
|
366
|
+
let cachedTokens = 0;
|
|
299
367
|
let responseModel = activeModel;
|
|
300
368
|
|
|
301
369
|
try {
|
|
@@ -343,6 +411,11 @@ export class GeminiProvider implements Provider {
|
|
|
343
411
|
if (chunk.usageMetadata) {
|
|
344
412
|
promptTokens = chunk.usageMetadata.promptTokenCount ?? 0;
|
|
345
413
|
outputTokens = chunk.usageMetadata.candidatesTokenCount ?? 0;
|
|
414
|
+
// Gemini 2.5+/3.x cache a stable request prefix implicitly (on by
|
|
415
|
+
// default). promptTokenCount already includes these cached tokens,
|
|
416
|
+
// so cachedContentTokenCount is the read subset — surface it so the
|
|
417
|
+
// pricing layer applies the discounted cache-read rate.
|
|
418
|
+
cachedTokens = chunk.usageMetadata.cachedContentTokenCount ?? 0;
|
|
346
419
|
}
|
|
347
420
|
|
|
348
421
|
if (chunk.modelVersion) {
|
|
@@ -386,13 +459,18 @@ export class GeminiProvider implements Provider {
|
|
|
386
459
|
usageMetadata: {
|
|
387
460
|
promptTokenCount: promptTokens,
|
|
388
461
|
candidatesTokenCount: outputTokens,
|
|
462
|
+
cachedContentTokenCount: cachedTokens,
|
|
389
463
|
},
|
|
390
464
|
};
|
|
391
465
|
|
|
392
466
|
return {
|
|
393
467
|
content,
|
|
394
468
|
model: responseModel,
|
|
395
|
-
usage: {
|
|
469
|
+
usage: {
|
|
470
|
+
inputTokens: promptTokens,
|
|
471
|
+
outputTokens,
|
|
472
|
+
...(cachedTokens > 0 ? { cacheReadInputTokens: cachedTokens } : {}),
|
|
473
|
+
},
|
|
396
474
|
stopReason: finishReason,
|
|
397
475
|
rawRequest,
|
|
398
476
|
rawResponse,
|
|
@@ -456,7 +534,7 @@ export class GeminiProvider implements Provider {
|
|
|
456
534
|
|
|
457
535
|
for (const msg of messages) {
|
|
458
536
|
const role = msg.role === "assistant" ? "model" : "user";
|
|
459
|
-
const { parts,
|
|
537
|
+
const { parts, toolResultMediaParts } = this.toGeminiParts(
|
|
460
538
|
msg.content,
|
|
461
539
|
toolCallNames,
|
|
462
540
|
model,
|
|
@@ -468,8 +546,8 @@ export class GeminiProvider implements Provider {
|
|
|
468
546
|
// Gemini requires that a Content with functionResponse parts must not
|
|
469
547
|
// contain non-functionResponse parts. Emit tool-result images in a
|
|
470
548
|
// separate user Content entry.
|
|
471
|
-
if (
|
|
472
|
-
result.push({ role: "user", parts:
|
|
549
|
+
if (toolResultMediaParts.length > 0) {
|
|
550
|
+
result.push({ role: "user", parts: toolResultMediaParts });
|
|
473
551
|
}
|
|
474
552
|
}
|
|
475
553
|
|
|
@@ -482,9 +560,9 @@ export class GeminiProvider implements Provider {
|
|
|
482
560
|
toolCallNames: Map<string, string>,
|
|
483
561
|
model: string,
|
|
484
562
|
role: "model" | "user",
|
|
485
|
-
): { parts: genai.Part[];
|
|
563
|
+
): { parts: genai.Part[]; toolResultMediaParts: genai.Part[] } {
|
|
486
564
|
const parts: genai.Part[] = [];
|
|
487
|
-
const
|
|
565
|
+
const toolResultMediaParts: genai.Part[] = [];
|
|
488
566
|
|
|
489
567
|
for (const block of blocks) {
|
|
490
568
|
switch (block.type) {
|
|
@@ -499,14 +577,27 @@ export class GeminiProvider implements Provider {
|
|
|
499
577
|
},
|
|
500
578
|
});
|
|
501
579
|
break;
|
|
502
|
-
case "file":
|
|
580
|
+
case "file": {
|
|
503
581
|
if (this.supportsGeminiInlineFile(block.source.media_type)) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
582
|
+
// Normalize audio MIME onto Gemini's spelling (e.g. audio/mpeg →
|
|
583
|
+
// audio/mp3); PDFs pass through unchanged. Guard the 20 MB inline
|
|
584
|
+
// request limit for audio so an oversize clip degrades to a text
|
|
585
|
+
// note rather than 400ing the whole request.
|
|
586
|
+
const audioMime = normalizeGeminiAudioMime(block.source.media_type);
|
|
587
|
+
const rawBytes = base64ByteLength(block.source.data);
|
|
588
|
+
if (audioMime && rawBytes > GEMINI_MAX_INLINE_AUDIO_BYTES) {
|
|
589
|
+
const approxMb = Math.round(rawBytes / (1024 * 1024));
|
|
590
|
+
parts.push({
|
|
591
|
+
text: `[Audio file too large to send inline: ${block.source.filename} (${block.source.media_type}, ~${approxMb}MB). Gemini's inline request limit is 20MB; this file was omitted. Ask the user for a shorter clip.]`,
|
|
592
|
+
});
|
|
593
|
+
} else {
|
|
594
|
+
parts.push({
|
|
595
|
+
inlineData: {
|
|
596
|
+
mimeType: audioMime ?? block.source.media_type,
|
|
597
|
+
data: block.source.data,
|
|
598
|
+
},
|
|
599
|
+
});
|
|
600
|
+
}
|
|
510
601
|
} else {
|
|
511
602
|
const fallback = block.extracted_text?.trim()
|
|
512
603
|
? `[Attached file: ${block.source.filename} (${block.source.media_type})]\n${block.extracted_text}`
|
|
@@ -514,6 +605,7 @@ export class GeminiProvider implements Provider {
|
|
|
514
605
|
parts.push({ text: fallback });
|
|
515
606
|
}
|
|
516
607
|
break;
|
|
608
|
+
}
|
|
517
609
|
case "tool_use":
|
|
518
610
|
{
|
|
519
611
|
const functionCallPart: genai.Part = {
|
|
@@ -542,16 +634,39 @@ export class GeminiProvider implements Provider {
|
|
|
542
634
|
if (extraText.length > 0) {
|
|
543
635
|
outputText = outputText + "\n" + extraText.join("\n");
|
|
544
636
|
}
|
|
545
|
-
// Collect images separately — Gemini rejects
|
|
546
|
-
// with functionResponse in the same Content entry.
|
|
637
|
+
// Collect images and inline-able audio separately — Gemini rejects
|
|
638
|
+
// mixing inlineData with functionResponse in the same Content entry.
|
|
547
639
|
for (const cb of block.contentBlocks) {
|
|
548
640
|
if (cb.type === "image") {
|
|
549
|
-
|
|
641
|
+
toolResultMediaParts.push({
|
|
550
642
|
inlineData: {
|
|
551
643
|
mimeType: cb.source.media_type,
|
|
552
644
|
data: cb.source.data,
|
|
553
645
|
},
|
|
554
646
|
});
|
|
647
|
+
} else if (cb.type === "file") {
|
|
648
|
+
const audioMime = normalizeGeminiAudioMime(
|
|
649
|
+
cb.source.media_type,
|
|
650
|
+
);
|
|
651
|
+
if (
|
|
652
|
+
audioMime &&
|
|
653
|
+
base64ByteLength(cb.source.data) <=
|
|
654
|
+
GEMINI_MAX_INLINE_AUDIO_BYTES
|
|
655
|
+
) {
|
|
656
|
+
toolResultMediaParts.push({
|
|
657
|
+
inlineData: { mimeType: audioMime, data: cb.source.data },
|
|
658
|
+
});
|
|
659
|
+
} else if (audioMime) {
|
|
660
|
+
// Oversize audio: note it in the functionResponse output
|
|
661
|
+
// rather than a media part (a text part can't ride the
|
|
662
|
+
// separate media Content, and inline audio would blow
|
|
663
|
+
// Gemini's request-size limit).
|
|
664
|
+
outputText =
|
|
665
|
+
outputText +
|
|
666
|
+
`\n[Audio too large to send inline: ${cb.source.filename}. Ask for a shorter clip.]`;
|
|
667
|
+
}
|
|
668
|
+
// Non-inline-able file sub-blocks (m4a/opus/pdf) are skipped
|
|
669
|
+
// here; the tool's text output already conveys the file.
|
|
555
670
|
}
|
|
556
671
|
}
|
|
557
672
|
}
|
|
@@ -577,7 +692,7 @@ export class GeminiProvider implements Provider {
|
|
|
577
692
|
this.addGemini3UnsignedToolCallFallback(parts, model);
|
|
578
693
|
}
|
|
579
694
|
|
|
580
|
-
return { parts,
|
|
695
|
+
return { parts, toolResultMediaParts };
|
|
581
696
|
}
|
|
582
697
|
|
|
583
698
|
private addGemini3UnsignedToolCallFallback(
|
|
@@ -601,6 +716,9 @@ export class GeminiProvider implements Provider {
|
|
|
601
716
|
}
|
|
602
717
|
|
|
603
718
|
private supportsGeminiInlineFile(mimeType: string): boolean {
|
|
604
|
-
return
|
|
719
|
+
return (
|
|
720
|
+
mimeType === "application/pdf" ||
|
|
721
|
+
normalizeGeminiAudioMime(mimeType) !== null
|
|
722
|
+
);
|
|
605
723
|
}
|
|
606
724
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared source of truth for how Gemini ingests inline audio: which MIME types
|
|
3
|
+
* it accepts, how our stored MIME types normalize onto Gemini's spelling, the
|
|
4
|
+
* inline-request size ceiling, and the token cost.
|
|
5
|
+
*
|
|
6
|
+
* Imported by both the Gemini serializer (`client.ts`) and the token estimator
|
|
7
|
+
* (`context/token-estimator.ts`) so the two cannot drift — if they disagreed on
|
|
8
|
+
* which audio is sent inline, the context budgeter would mis-count what
|
|
9
|
+
* actually goes on the wire.
|
|
10
|
+
*
|
|
11
|
+
* Ref: https://ai.google.dev/gemini-api/docs/audio
|
|
12
|
+
* - Inline-accepted audio: wav, mp3, aiff, aac, ogg, flac
|
|
13
|
+
* - Inline request size limit: 20 MB total (prompt + system + inline files)
|
|
14
|
+
* - Audio is billed at ~32 tokens/second
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Audio MIME types Gemini accepts as inline data, in Gemini's own spelling
|
|
19
|
+
* (the values we emit on the wire). Our upload allowlist stores mp3 as
|
|
20
|
+
* `audio/mpeg`; {@link normalizeGeminiAudioMime} maps that onto `audio/mp3`.
|
|
21
|
+
*/
|
|
22
|
+
export const GEMINI_INLINE_AUDIO_MIME_TYPES = new Set([
|
|
23
|
+
"audio/wav",
|
|
24
|
+
"audio/mp3",
|
|
25
|
+
"audio/aiff",
|
|
26
|
+
"audio/aac",
|
|
27
|
+
"audio/ogg",
|
|
28
|
+
"audio/flac",
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Map a stored attachment MIME type onto Gemini's inline-audio spelling, or
|
|
33
|
+
* `null` when Gemini cannot take it inline.
|
|
34
|
+
*
|
|
35
|
+
* m4a (`audio/x-m4a`, `audio/mp4`) and opus are intentionally unsupported:
|
|
36
|
+
* m4a bytes are an MP4 container, not raw AAC, so we must not relabel them as
|
|
37
|
+
* `audio/aac` — they fall through to a text placeholder instead.
|
|
38
|
+
*/
|
|
39
|
+
export function normalizeGeminiAudioMime(mimeType: string): string | null {
|
|
40
|
+
const normalized = mimeType.toLowerCase().split(";")[0]?.trim() ?? "";
|
|
41
|
+
const remapped = normalized === "audio/mpeg" ? "audio/mp3" : normalized;
|
|
42
|
+
return GEMINI_INLINE_AUDIO_MIME_TYPES.has(remapped) ? remapped : null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Raw byte length backing a base64 string (4 base64 chars → 3 bytes). */
|
|
46
|
+
export function base64ByteLength(base64Data: string): number {
|
|
47
|
+
return Math.floor((base64Data.length * 3) / 4);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Max raw bytes of audio we send inline to Gemini. Gemini's total inline
|
|
52
|
+
* request limit is 20 MB and base64 inflates payloads ~33%, so we cap raw
|
|
53
|
+
* audio at ~12 MB (≈16 MB encoded) to leave headroom for the prompt, system
|
|
54
|
+
* instruction, and conversation history. Larger files degrade to a text
|
|
55
|
+
* placeholder (the Gemini Files API is a future enhancement).
|
|
56
|
+
*/
|
|
57
|
+
export const GEMINI_MAX_INLINE_AUDIO_BYTES = 12 * 1024 * 1024;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Gemini bills audio at ~32 tokens/second, NOT by payload size. We don't have
|
|
61
|
+
* the decoded duration at estimate time, so approximate it from byte size
|
|
62
|
+
* assuming ~128 kbps (~16 KB/s) typical compressed audio. This keeps the
|
|
63
|
+
* context budgeter within range instead of the ~170x over-count that treating
|
|
64
|
+
* the base64 payload as text produces. (Uncompressed WAV is under-counted, but
|
|
65
|
+
* the inline size guard caps it at {@link GEMINI_MAX_INLINE_AUDIO_BYTES}.)
|
|
66
|
+
*/
|
|
67
|
+
const GEMINI_AUDIO_TOKENS_PER_SECOND = 32;
|
|
68
|
+
const APPROX_AUDIO_BYTES_PER_SECOND = 16_000;
|
|
69
|
+
|
|
70
|
+
export function estimateGeminiAudioTokens(base64Data: string): number {
|
|
71
|
+
const approxSeconds =
|
|
72
|
+
base64ByteLength(base64Data) / APPROX_AUDIO_BYTES_PER_SECOND;
|
|
73
|
+
return Math.ceil(approxSeconds * GEMINI_AUDIO_TOKENS_PER_SECOND);
|
|
74
|
+
}
|
|
@@ -74,8 +74,6 @@ async function runStream(
|
|
|
74
74
|
}> {
|
|
75
75
|
const response = await provider.sendMessage(
|
|
76
76
|
[{ role: "user", content: [{ type: "text", text: "hi" }] }],
|
|
77
|
-
undefined,
|
|
78
|
-
undefined,
|
|
79
77
|
{
|
|
80
78
|
onEvent: (e) => {
|
|
81
79
|
events.push(e as { type: string; thinking?: string; text?: string });
|
|
@@ -11,7 +11,6 @@ import type {
|
|
|
11
11
|
Provider,
|
|
12
12
|
ProviderResponse,
|
|
13
13
|
SendMessageOptions,
|
|
14
|
-
ToolDefinition,
|
|
15
14
|
} from "../types.js";
|
|
16
15
|
import {
|
|
17
16
|
ContextOverflowError,
|
|
@@ -256,11 +255,9 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
256
255
|
|
|
257
256
|
async sendMessage(
|
|
258
257
|
messages: Message[],
|
|
259
|
-
tools?: ToolDefinition[],
|
|
260
|
-
systemPrompt?: string,
|
|
261
258
|
options?: SendMessageOptions,
|
|
262
259
|
): Promise<ProviderResponse> {
|
|
263
|
-
const { config, onEvent, signal } = options ?? {};
|
|
260
|
+
const { tools, systemPrompt, config, onEvent, signal } = options ?? {};
|
|
264
261
|
const configObj = config as Record<string, unknown> | undefined;
|
|
265
262
|
const maxTokens = configObj?.max_tokens as number | undefined;
|
|
266
263
|
const modelOverride = configObj?.model as string | undefined;
|
|
@@ -12,7 +12,6 @@ import type {
|
|
|
12
12
|
Provider,
|
|
13
13
|
ProviderResponse,
|
|
14
14
|
SendMessageOptions,
|
|
15
|
-
ToolDefinition,
|
|
16
15
|
} from "../types.js";
|
|
17
16
|
import { ContextOverflowError } from "../types.js";
|
|
18
17
|
import { detectOpenAICompatibleContextOverflow } from "./chat-completions-provider.js";
|
|
@@ -160,11 +159,9 @@ export class OpenAIResponsesProvider implements Provider {
|
|
|
160
159
|
|
|
161
160
|
async sendMessage(
|
|
162
161
|
messages: Message[],
|
|
163
|
-
tools?: ToolDefinition[],
|
|
164
|
-
systemPrompt?: string,
|
|
165
162
|
options?: SendMessageOptions,
|
|
166
163
|
): Promise<ProviderResponse> {
|
|
167
|
-
const { config, onEvent, signal } = options ?? {};
|
|
164
|
+
const { tools, systemPrompt, config, onEvent, signal } = options ?? {};
|
|
168
165
|
const configObj = config as Record<string, unknown> | undefined;
|
|
169
166
|
const maxTokens = configObj?.max_tokens as number | undefined;
|
|
170
167
|
const modelOverride = configObj?.model as string | undefined;
|
|
@@ -10,7 +10,6 @@ import type {
|
|
|
10
10
|
Message,
|
|
11
11
|
ProviderResponse,
|
|
12
12
|
SendMessageOptions,
|
|
13
|
-
ToolDefinition,
|
|
14
13
|
} from "../types.js";
|
|
15
14
|
import { ContextOverflowError, isContextOverflowError } from "../types.js";
|
|
16
15
|
|
|
@@ -142,8 +141,6 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
|
|
|
142
141
|
|
|
143
142
|
override async sendMessage(
|
|
144
143
|
messages: Message[],
|
|
145
|
-
tools?: ToolDefinition[],
|
|
146
|
-
systemPrompt?: string,
|
|
147
144
|
options?: SendMessageOptions,
|
|
148
145
|
): Promise<ProviderResponse> {
|
|
149
146
|
const effectiveModel = this.resolveEffectiveModel(options);
|
|
@@ -151,12 +148,10 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
|
|
|
151
148
|
if (isAnthropicModel(effectiveModel)) {
|
|
152
149
|
return await this.getAnthropicInner().sendMessage(
|
|
153
150
|
messages,
|
|
154
|
-
tools,
|
|
155
|
-
systemPrompt,
|
|
156
151
|
withOpenRouterBodyExtras(options),
|
|
157
152
|
);
|
|
158
153
|
}
|
|
159
|
-
return await super.sendMessage(messages,
|
|
154
|
+
return await super.sendMessage(messages, options);
|
|
160
155
|
} catch (error) {
|
|
161
156
|
// Re-tag delegate-thrown ContextOverflowError so the outer provider name
|
|
162
157
|
// matches the configured provider ("openrouter"). This keeps downstream
|
|
@@ -22,7 +22,6 @@ import type {
|
|
|
22
22
|
Provider,
|
|
23
23
|
ProviderResponse,
|
|
24
24
|
SendMessageOptions,
|
|
25
|
-
ToolDefinition,
|
|
26
25
|
ToolUseContent,
|
|
27
26
|
} from "./types.js";
|
|
28
27
|
|
|
@@ -56,16 +55,14 @@ export class CallSiteConfiguredProvider implements Provider {
|
|
|
56
55
|
|
|
57
56
|
sendMessage(
|
|
58
57
|
messages: Message[],
|
|
59
|
-
tools?: ToolDefinition[],
|
|
60
|
-
systemPrompt?: string,
|
|
61
58
|
options?: SendMessageOptions,
|
|
62
59
|
): Promise<ProviderResponse> {
|
|
63
60
|
const config = options?.config;
|
|
64
61
|
if (config?.callSite) {
|
|
65
|
-
return this.inner.sendMessage(messages,
|
|
62
|
+
return this.inner.sendMessage(messages, options);
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
return this.inner.sendMessage(messages,
|
|
65
|
+
return this.inner.sendMessage(messages, {
|
|
69
66
|
...options,
|
|
70
67
|
config: {
|
|
71
68
|
...config,
|
|
@@ -141,7 +138,10 @@ export async function resolveConfiguredProvider(
|
|
|
141
138
|
resolved.model,
|
|
142
139
|
);
|
|
143
140
|
if (incompatMsg) {
|
|
144
|
-
log.warn(
|
|
141
|
+
log.warn(
|
|
142
|
+
{ callSite, inferenceProvider, model: resolved.model },
|
|
143
|
+
incompatMsg,
|
|
144
|
+
);
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
} catch {
|
|
@@ -6,7 +6,6 @@ import type {
|
|
|
6
6
|
Provider,
|
|
7
7
|
ProviderResponse,
|
|
8
8
|
SendMessageOptions,
|
|
9
|
-
ToolDefinition,
|
|
10
9
|
} from "./types.js";
|
|
11
10
|
|
|
12
11
|
const log = getLogger("rate-limit");
|
|
@@ -36,8 +35,6 @@ export class RateLimitProvider implements Provider {
|
|
|
36
35
|
|
|
37
36
|
async sendMessage(
|
|
38
37
|
messages: Message[],
|
|
39
|
-
tools?: ToolDefinition[],
|
|
40
|
-
systemPrompt?: string,
|
|
41
38
|
options?: SendMessageOptions,
|
|
42
39
|
): Promise<ProviderResponse> {
|
|
43
40
|
this.enforceRequestRate();
|
|
@@ -46,12 +43,7 @@ export class RateLimitProvider implements Provider {
|
|
|
46
43
|
// calls from bypassing the rate limit during the async gap.
|
|
47
44
|
this.recordRequest();
|
|
48
45
|
|
|
49
|
-
const response = await this.inner.sendMessage(
|
|
50
|
-
messages,
|
|
51
|
-
tools,
|
|
52
|
-
systemPrompt,
|
|
53
|
-
options,
|
|
54
|
-
);
|
|
46
|
+
const response = await this.inner.sendMessage(messages, options);
|
|
55
47
|
|
|
56
48
|
return response;
|
|
57
49
|
}
|
package/src/providers/retry.ts
CHANGED
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
type Provider,
|
|
24
24
|
type ProviderResponse,
|
|
25
25
|
type SendMessageOptions,
|
|
26
|
-
type ToolDefinition,
|
|
27
26
|
} from "./types.js";
|
|
28
27
|
|
|
29
28
|
const log = getLogger("retry");
|
|
@@ -525,8 +524,6 @@ export class RetryProvider implements Provider {
|
|
|
525
524
|
|
|
526
525
|
async sendMessage(
|
|
527
526
|
messages: Message[],
|
|
528
|
-
tools?: ToolDefinition[],
|
|
529
|
-
systemPrompt?: string,
|
|
530
527
|
options?: SendMessageOptions,
|
|
531
528
|
): Promise<ProviderResponse> {
|
|
532
529
|
let lastError: unknown;
|
|
@@ -541,8 +538,6 @@ export class RetryProvider implements Provider {
|
|
|
541
538
|
try {
|
|
542
539
|
const result = await this.inner.sendMessage(
|
|
543
540
|
messages,
|
|
544
|
-
tools,
|
|
545
|
-
systemPrompt,
|
|
546
541
|
normalizedOptions,
|
|
547
542
|
);
|
|
548
543
|
return result;
|
package/src/providers/types.ts
CHANGED
|
@@ -207,10 +207,21 @@ export interface SendMessageConfig {
|
|
|
207
207
|
effort?: "none" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
208
208
|
speed?: "standard" | "fast";
|
|
209
209
|
verbosity?: "low" | "medium" | "high";
|
|
210
|
+
/**
|
|
211
|
+
* When true, the most recent user message's content varies across
|
|
212
|
+
* otherwise-identical turns (e.g. a per-turn memory block was injected into
|
|
213
|
+
* it). The provider places the primary long-TTL cache breakpoint on the most
|
|
214
|
+
* recent *stable* user message instead of the volatile latest one, so the
|
|
215
|
+
* cached prefix stays reusable across turns. Default false — existing
|
|
216
|
+
* behavior.
|
|
217
|
+
*/
|
|
218
|
+
mutableLatestUserMessage?: boolean;
|
|
210
219
|
[key: string]: unknown;
|
|
211
220
|
}
|
|
212
221
|
|
|
213
222
|
export interface SendMessageOptions {
|
|
223
|
+
tools?: ToolDefinition[];
|
|
224
|
+
systemPrompt?: string;
|
|
214
225
|
config?: SendMessageConfig;
|
|
215
226
|
onEvent?: (event: ProviderEvent) => void;
|
|
216
227
|
signal?: AbortSignal;
|
|
@@ -229,8 +240,6 @@ export interface Provider {
|
|
|
229
240
|
tokenEstimationProvider?: string;
|
|
230
241
|
sendMessage(
|
|
231
242
|
messages: Message[],
|
|
232
|
-
tools?: ToolDefinition[],
|
|
233
|
-
systemPrompt?: string,
|
|
234
243
|
options?: SendMessageOptions,
|
|
235
244
|
): Promise<ProviderResponse>;
|
|
236
245
|
}
|
|
@@ -11,7 +11,6 @@ import type {
|
|
|
11
11
|
Provider,
|
|
12
12
|
ProviderResponse,
|
|
13
13
|
SendMessageOptions,
|
|
14
|
-
ToolDefinition,
|
|
15
14
|
} from "./types.js";
|
|
16
15
|
|
|
17
16
|
const log = getLogger("provider-usage-tracking");
|
|
@@ -27,16 +26,9 @@ export class UsageTrackingProvider implements Provider {
|
|
|
27
26
|
|
|
28
27
|
async sendMessage(
|
|
29
28
|
messages: Message[],
|
|
30
|
-
tools?: ToolDefinition[],
|
|
31
|
-
systemPrompt?: string,
|
|
32
29
|
options?: SendMessageOptions,
|
|
33
30
|
): Promise<ProviderResponse> {
|
|
34
|
-
const response = await this.inner.sendMessage(
|
|
35
|
-
messages,
|
|
36
|
-
tools,
|
|
37
|
-
systemPrompt,
|
|
38
|
-
options,
|
|
39
|
-
);
|
|
31
|
+
const response = await this.inner.sendMessage(messages, options);
|
|
40
32
|
this.recordUsage(response, options);
|
|
41
33
|
return response;
|
|
42
34
|
}
|