@vellumai/assistant 0.8.12 → 0.9.0-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/AGENTS.md +0 -14
- package/ARCHITECTURE.md +45 -45
- package/README.md +1 -1
- package/bun.lock +200 -154
- package/docs/architecture/integrations.md +3 -3
- package/docs/architecture/memory.md +2 -2
- package/docs/architecture/security.md +10 -10
- package/docs/runbook-trusted-contacts.md +12 -12
- package/docs/skills.md +6 -6
- package/docs/workflows-testing.md +221 -0
- package/docs/workflows.md +510 -0
- package/examples/plugins/echo/README.md +5 -5
- package/knip.json +2 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +105 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +12 -0
- package/openapi.yaml +7197 -5708
- package/package.json +8 -4
- package/scripts/generate-openapi.ts +66 -114
- package/src/__tests__/access-request-seed-content-blocks.test.ts +213 -0
- package/src/__tests__/adaptive-thinking-repair.test.ts +32 -3
- package/src/__tests__/agent-loop-output-hooks.test.ts +183 -0
- package/src/__tests__/agent-loop-regrowth-guard.test.ts +506 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +77 -0
- package/src/__tests__/app-compiler.test.ts +7 -1
- package/src/__tests__/app-dir-path-guard.test.ts +27 -3
- package/src/__tests__/app-executors.test.ts +43 -0
- package/src/__tests__/approval-cascade.test.ts +0 -5
- package/src/__tests__/approval-routes-http.test.ts +91 -0
- package/src/__tests__/assistant-stream-state.test.ts +107 -0
- package/src/__tests__/browser-fill-credential.test.ts +3 -3
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +63 -7
- package/src/__tests__/compaction-trail-store.test.ts +74 -1
- package/src/__tests__/compaction.benchmark.test.ts +63 -41
- package/src/__tests__/compactor-low-watermark-cut.test.ts +349 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +64 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -5
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -5
- package/src/__tests__/conversation-history-web-search.test.ts +7 -0
- package/src/__tests__/conversation-process-callsite.test.ts +0 -5
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -5
- package/src/__tests__/conversation-queue.test.ts +0 -5
- package/src/__tests__/conversation-slash-queue.test.ts +0 -5
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -5
- package/src/__tests__/conversation-speed-override.test.ts +0 -5
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +97 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
- package/src/__tests__/conversation-usage.test.ts +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -5
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -5
- package/src/__tests__/credential-broker-browser-fill.test.ts +2 -2
- package/src/__tests__/credential-broker-server-use.test.ts +2 -2
- package/src/__tests__/credential-broker.test.ts +1 -1
- package/src/__tests__/credential-prompt-route.test.ts +417 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault.test.ts +37 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +24 -0
- package/src/__tests__/dynamic-page-surface.test.ts +219 -0
- package/src/__tests__/empty-state-greeting-cache.test.ts +94 -0
- package/src/__tests__/gateway-flag-listener.test.ts +24 -7
- package/src/__tests__/guardian-action-sweep.test.ts +56 -219
- package/src/__tests__/guardian-routing-invariants.test.ts +138 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/list-messages-hidden-metadata.test.ts +99 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +87 -1
- package/src/__tests__/llm-resolver.test.ts +115 -0
- package/src/__tests__/managed-profile-guard.test.ts +6 -5
- package/src/__tests__/max-tokens-continue-hook.test.ts +184 -0
- package/src/__tests__/media-generate-image.test.ts +20 -9
- package/src/__tests__/mock-gateway-ipc.ts +23 -0
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/normalize-onboarding.test.ts +26 -0
- package/src/__tests__/notification-decision-strategy.test.ts +4 -2
- package/src/__tests__/notification-telegram-adapter.test.ts +21 -3
- package/src/__tests__/pending-interactions-resolved-event.test.ts +62 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +72 -18
- package/src/__tests__/require-fresh-approval.test.ts +425 -1
- package/src/__tests__/resolve-app-id.test.ts +56 -0
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -0
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +408 -0
- package/src/__tests__/schedule-routes.test.ts +257 -4
- package/src/__tests__/schedule-store.test.ts +60 -0
- package/src/__tests__/schedule-tools.test.ts +247 -2
- package/src/__tests__/skill-execute-input.test.ts +85 -0
- package/src/__tests__/skill-secret-handling-guard.test.ts +21 -20
- package/src/__tests__/skills.test.ts +3 -3
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +1 -1
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +547 -0
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/task-progress-nudge-hook.test.ts +372 -0
- package/src/__tests__/task-scheduler.test.ts +299 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +209 -0
- package/src/__tests__/tool-result-spool.test.ts +3 -1
- package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +181 -0
- package/src/__tests__/workspace-migration-103-upgrade-quality-profile-to-opus-4-8.test.ts +174 -0
- package/src/agent/compaction-circuit.ts +11 -0
- package/src/agent/loop.ts +181 -12
- package/src/api/constants/call-sites.ts +12 -0
- package/src/api/events/assistant-thinking-delta.ts +10 -0
- package/src/api/events/usage-update.ts +7 -0
- package/src/api/index.ts +4 -1
- package/src/api/responses/memory-v3-selection-log.ts +18 -11
- package/src/approvals/approval-primitive.ts +2 -2
- package/src/background-wake/background-wake-routes.test.ts +5 -2
- package/src/bundler/compiler-tools.ts +1 -1
- package/src/bundler/package-resolver.ts +0 -1
- package/src/calls/call-domain.ts +1 -1
- package/src/calls/guardian-action-sweep.ts +16 -93
- package/src/cli/AGENTS.md +4 -0
- package/src/cli/commands/__tests__/schedules.test.ts +430 -1
- package/src/cli/commands/credentials.ts +28 -24
- package/src/cli/commands/image-generation.ts +23 -9
- package/src/cli/commands/notifications.ts +1 -1
- package/src/cli/commands/plugins.ts +89 -46
- package/src/cli/commands/schedules.ts +384 -11
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +69 -5
- package/src/cli/lib/__tests__/install-from-github.test.ts +15 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +81 -4
- package/src/cli/lib/inspect-plugin.ts +62 -1
- package/src/cli/lib/install-from-github.ts +52 -5
- package/src/cli/lib/upgrade-plugin.ts +18 -0
- package/src/config/__tests__/workflows-schema.test.ts +60 -0
- package/src/config/bundled-skills/acp/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +6 -1
- package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +7 -1
- package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +7 -1
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +10 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +66 -19
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -6
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +22 -3
- package/src/config/bundled-skills/personal-page/SKILL.md +57 -0
- package/src/config/bundled-skills/personal-page/TOOLS.json +27 -0
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +17 -0
- package/src/config/bundled-skills/schedule/SKILL.md +7 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +48 -4
- package/src/config/bundled-skills/workflows/SKILL.md +214 -0
- package/src/config/bundled-skills/workflows/TOOLS.json +84 -0
- package/src/config/bundled-skills/workflows/tools/manage-workflows.ts +12 -0
- package/src/config/bundled-skills/workflows/tools/run-workflow.ts +12 -0
- package/src/config/bundled-tool-registry.ts +14 -2
- package/src/config/call-site-defaults.ts +5 -0
- package/src/config/feature-flag-registry.json +12 -4
- package/src/config/llm-context-resolution.ts +8 -0
- package/src/config/llm-resolver.ts +30 -0
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +22 -0
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +16 -0
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +77 -0
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +57 -0
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +28 -0
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +234 -0
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +48 -0
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +16 -0
- package/src/config/preloaded-apps/personal-page/src/index.html +20 -0
- package/src/config/preloaded-apps/personal-page/src/main.tsx +7 -0
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +82 -0
- package/src/config/preloaded-apps/personal-page/src/styles.css +759 -0
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/heartbeat.ts +4 -1
- package/src/config/schemas/llm.ts +33 -26
- package/src/config/schemas/memory-retrospective.ts +19 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/services.ts +5 -2
- package/src/config/schemas/workflows.ts +42 -0
- package/src/config/skills.ts +3 -3
- package/src/context/compactor.ts +273 -39
- package/src/context/post-turn-tool-result-truncation.ts +23 -6
- package/src/context/tool-result-spool.ts +12 -17
- package/src/credential-execution/executable-discovery.ts +1 -1
- package/src/credential-execution/process-manager.ts +37 -3
- package/src/credential-execution/prompted-credential.ts +205 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +14 -0
- package/src/daemon/conversation-process.ts +11 -2
- package/src/daemon/conversation-surfaces.ts +167 -3
- package/src/daemon/conversation-tool-setup.ts +103 -26
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +115 -11
- package/src/daemon/handlers/shared.ts +26 -14
- package/src/daemon/host-cu-proxy.ts +15 -12
- package/src/daemon/host-file-proxy.ts +15 -12
- package/src/daemon/host-transfer-proxy.ts +30 -24
- package/src/daemon/lifecycle.ts +40 -3
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/messages.ts +2 -10
- package/src/daemon/message-types/workflows.ts +49 -0
- package/src/daemon/parse-actual-tokens-from-error.test.ts +62 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +43 -4
- package/src/daemon/process-message.ts +6 -0
- package/src/daemon/tool-setup-types.ts +57 -0
- package/src/daemon/wake-conversation-ops.ts +18 -0
- package/src/heartbeat/heartbeat-run-store.ts +8 -2
- package/src/home/feed-types.ts +1 -1
- package/src/ipc/gateway-flag-listener.ts +28 -6
- package/src/mcp/mcp-auth-state.ts +8 -20
- package/src/media/__tests__/image-models.test.ts +57 -0
- package/src/media/image-models.ts +66 -0
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +38 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +12 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +911 -34
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +227 -5
- package/src/memory/__tests__/memory-retrospective-state.test.ts +195 -0
- package/src/memory/__tests__/preloaded-apps.test.ts +85 -0
- package/src/memory/auto-analysis-enqueue.ts +14 -1
- package/src/memory/compaction-log-store-clickhouse.ts +6 -4
- package/src/memory/conversation-crud.ts +9 -2
- package/src/memory/conversation-disk-view.ts +1 -1
- package/src/memory/conversation-queries.ts +22 -7
- package/src/memory/db-init.ts +20 -0
- package/src/memory/db-maintenance.ts +16 -0
- package/src/memory/embedding-runtime-manager.ts +1 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +112 -14
- package/src/memory/llm-request-log-source-local.ts +19 -1
- package/src/memory/llm-request-log-source.ts +35 -6
- package/src/memory/llm-request-log-store.ts +90 -2
- package/src/memory/memory-retrospective-constants.ts +9 -0
- package/src/memory/memory-retrospective-enqueue.ts +3 -6
- package/src/memory/memory-retrospective-fork-boundary.ts +94 -0
- package/src/memory/memory-retrospective-job.ts +500 -208
- package/src/memory/memory-retrospective-startup-cleanup.ts +97 -19
- package/src/memory/memory-retrospective-state.ts +85 -2
- package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +40 -0
- package/src/memory/migrations/282-schedule-inference-profile.test.ts +77 -0
- package/src/memory/migrations/282-schedule-inference-profile.ts +26 -0
- package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.test.ts +102 -0
- package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.ts +53 -0
- package/src/memory/migrations/284-workflow-runs.ts +51 -0
- package/src/memory/migrations/285-schedule-workflow-mode.ts +26 -0
- package/src/memory/migrations/286-workflow-run-trust.ts +27 -0
- package/src/memory/migrations/287-conversation-origin-channel-index.ts +15 -0
- package/src/memory/migrations/288-backfill-origin-channel-from-bindings.ts +43 -0
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +115 -0
- package/src/memory/migrations/290-schedule-capabilities.test.ts +77 -0
- package/src/memory/migrations/290-schedule-capabilities.ts +25 -0
- package/src/memory/migrations/__tests__/281-memory-retrospective-remembered-log.test.ts +96 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +571 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/preloaded-apps.ts +116 -0
- package/src/memory/schema/infrastructure.ts +4 -0
- package/src/memory/schema/memory-core.ts +4 -0
- package/src/memory/v2/__tests__/concept-page-frontmatter-schema.test.ts +45 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +11 -7
- package/src/memory/v2/__tests__/page-store.test.ts +13 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +24 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -6
- package/src/memory/v2/page-store.ts +4 -3
- package/src/memory/v2/qdrant.ts +42 -3
- package/src/memory/v2/types.ts +16 -10
- package/src/messaging/draft-store.ts +1 -1
- package/src/notifications/access-request-copy.ts +200 -113
- package/src/notifications/adapters/slack.ts +250 -111
- package/src/notifications/adapters/telegram.ts +7 -44
- package/src/notifications/approval-card-builder.ts +93 -0
- package/src/notifications/broadcaster.ts +74 -0
- package/src/notifications/conversation-pairing.ts +8 -6
- package/src/notifications/copy-composer.ts +32 -26
- package/src/notifications/decision-engine.ts +59 -7
- package/src/notifications/guardian-question-mode.ts +145 -155
- package/src/notifications/home-feed-side-effect.ts +28 -11
- package/src/notifications/notification-utils.ts +66 -0
- package/src/notifications/signal.ts +6 -0
- package/src/notifications/tool-approval-copy.ts +142 -0
- package/src/notifications/types.ts +19 -0
- package/src/permissions/threshold.ts +11 -0
- package/src/plugin-api/types.ts +16 -4
- package/src/plugins/defaults/compaction/window-manager.ts +44 -0
- package/src/plugins/defaults/index.ts +46 -0
- package/src/plugins/defaults/max-tokens-continue/continue-state-store.ts +53 -0
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +80 -0
- package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +20 -0
- package/src/plugins/defaults/max-tokens-continue/package.json +14 -0
- package/src/plugins/defaults/memory-retrieval/hooks/__tests__/user-prompt-submit.test.ts +37 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +29 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +8 -3
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +4 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +28 -18
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +67 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +122 -22
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +2 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +63 -1
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +61 -18
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +1 -1
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +39 -10
- package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +34 -1
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +112 -47
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +78 -15
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +206 -0
- package/src/plugins/defaults/task-progress-nudge/package.json +15 -0
- package/src/prompts/__tests__/system-prompt.test.ts +100 -1
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +5 -7
- package/src/prompts/normalize-onboarding.ts +2 -0
- package/src/prompts/persona-resolver.ts +3 -0
- package/src/prompts/system-prompt.ts +51 -2
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +3 -1
- package/src/prompts/templates/system-sections.ts +8 -3
- package/src/providers/call-site-routing.ts +6 -3
- package/src/providers/fireworks/client.ts +3 -0
- package/src/providers/inference/auth.ts +52 -46
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/__tests__/coerce-object-args.test.ts +105 -0
- package/src/providers/openai/chat-completions-provider.ts +47 -9
- package/src/providers/openai/coerce-object-args.ts +104 -0
- package/src/providers/retry.ts +8 -5
- package/src/providers/types.ts +10 -0
- package/src/runtime/__tests__/agent-wake.test.ts +629 -7
- package/src/runtime/access-request-helper.ts +16 -9
- package/src/runtime/agent-wake.ts +302 -51
- package/src/runtime/assistant-stream-state.ts +141 -8
- package/src/runtime/background-job-runner.ts +9 -0
- package/src/runtime/channel-approval-types.ts +1 -0
- package/src/runtime/channel-invite-transports/telegram.ts +6 -5
- package/src/runtime/channel-invite-transports/voice.ts +2 -2
- package/src/runtime/channel-invite-types.ts +4 -2
- package/src/runtime/channel-retry-sweep.ts +19 -41
- package/src/runtime/finalize-event-delivery.ts +72 -0
- package/src/runtime/guardian-action-message-composer.ts +0 -54
- package/src/runtime/http-server.ts +6 -14
- package/src/runtime/http-types.ts +0 -1
- package/src/runtime/message-composer-types.ts +0 -9
- package/src/runtime/middleware/__tests__/rate-limiter.test.ts +63 -0
- package/src/runtime/middleware/auth.ts +27 -3
- package/src/runtime/middleware/rate-limiter.ts +28 -1
- package/src/runtime/migrations/vbundle-builder.ts +6 -5
- package/src/runtime/pending-interactions.ts +20 -1
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +232 -173
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +18 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +436 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +11 -0
- package/src/runtime/routes/approval-routes.ts +35 -8
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -1
- package/src/runtime/routes/btw-routes.ts +37 -1
- package/src/runtime/routes/channel-delivery-routes.ts +11 -7
- package/src/runtime/routes/channel-route-definitions.ts +3 -0
- package/src/runtime/routes/channel-route-shared.ts +3 -1
- package/src/runtime/routes/consolidation-routes.ts +17 -13
- package/src/runtime/routes/conversation-compaction-routes.ts +159 -119
- package/src/runtime/routes/conversation-list-routes.ts +41 -4
- package/src/runtime/routes/conversation-query-routes.ts +196 -11
- package/src/runtime/routes/conversation-routes.ts +15 -1
- package/src/runtime/routes/credential-prompt-routes.ts +39 -17
- package/src/runtime/routes/empty-state-greeting-cache.ts +65 -0
- package/src/runtime/routes/heartbeat-routes.ts +18 -13
- package/src/runtime/routes/image-generation-routes.ts +20 -2
- package/src/runtime/routes/inbound-message-handler.ts +13 -12
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +32 -31
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +7 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -21
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +5 -5
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +6 -15
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +1 -1
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/log-export/AGENTS.md +1 -1
- package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
- package/src/runtime/routes/migration-routes.ts +5 -9
- package/src/runtime/routes/plugins-routes.ts +26 -0
- package/src/runtime/routes/ps-routes.ts +10 -8
- package/src/runtime/routes/retrospective-routes.ts +235 -0
- package/src/runtime/routes/runs-pagination.ts +75 -0
- package/src/runtime/routes/schedule-routes.ts +367 -59
- package/src/runtime/routes/sounds-config-routes.ts +239 -0
- package/src/runtime/routes/surface-action-routes.ts +84 -4
- package/src/runtime/routes/workflow-routes.test.ts +372 -0
- package/src/runtime/routes/workflow-routes.ts +363 -0
- package/src/runtime/routes/workspace-routes.test.ts +61 -1
- package/src/runtime/routes/workspace-routes.ts +26 -1
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +38 -0
- package/src/runtime/services/analyze-conversation.ts +26 -13
- package/src/schedule/inference-profile.ts +28 -0
- package/src/schedule/schedule-store.ts +152 -4
- package/src/schedule/scheduler-types.ts +6 -0
- package/src/schedule/scheduler.ts +96 -0
- package/src/security/secret-allowlist.ts +1 -1
- package/src/skills/path-classifier.ts +1 -1
- package/src/tools/apps/executors.ts +23 -0
- package/src/tools/apps/resolve-app-id.ts +42 -0
- package/src/tools/browser/browser-execution.ts +9 -11
- package/src/tools/credentials/broker.ts +4 -4
- package/src/tools/credentials/vault.ts +26 -137
- package/src/tools/executor.ts +69 -0
- package/src/tools/flag-gated-tools.test.ts +76 -0
- package/src/tools/permission-checker.ts +8 -1
- package/src/tools/registry.ts +51 -0
- package/src/tools/schedule/create.ts +77 -1
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +73 -1
- package/src/tools/skills/execute.ts +56 -0
- package/src/tools/terminal/shell.ts +1 -1
- package/src/tools/ui-surface/definitions.ts +91 -2
- package/src/tools/workflows/manage-workflows.ts +183 -0
- package/src/tools/workflows/run-workflow.test.ts +442 -0
- package/src/tools/workflows/run-workflow.ts +88 -0
- package/src/types/onboarding-context.ts +2 -0
- package/src/usage/attribution.ts +24 -0
- package/src/util/canonicalize-identity.ts +12 -3
- package/src/util/platform.ts +17 -17
- package/src/watcher/__tests__/engine.test.ts +24 -0
- package/src/watcher/__tests__/telemetry.test.ts +135 -0
- package/src/watcher/engine.ts +7 -0
- package/src/watcher/telemetry.ts +74 -0
- package/src/workflows/capabilities.test.ts +365 -0
- package/src/workflows/capabilities.ts +359 -0
- package/src/workflows/deterministic-stringify.ts +27 -0
- package/src/workflows/engine-integration.test.ts +656 -0
- package/src/workflows/engine.test.ts +1144 -0
- package/src/workflows/engine.ts +1078 -0
- package/src/workflows/fanout-load.test.ts +168 -0
- package/src/workflows/journal-store.test.ts +369 -0
- package/src/workflows/journal-store.ts +470 -0
- package/src/workflows/leaf-runner.test.ts +704 -0
- package/src/workflows/leaf-runner.ts +589 -0
- package/src/workflows/library.test.ts +134 -0
- package/src/workflows/library.ts +124 -0
- package/src/workflows/run-manager.test.ts +711 -0
- package/src/workflows/run-manager.ts +593 -0
- package/src/workflows/sandbox-escape.test.ts +339 -0
- package/src/workflows/sandbox.test.ts +251 -0
- package/src/workflows/sandbox.ts +447 -0
- package/src/workspace/adaptive-thinking-repair.ts +33 -11
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +1 -1
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +1 -1
- package/src/workspace/migrations/026-backfill-install-meta.ts +1 -1
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +2 -1
- package/src/workspace/migrations/031-drop-user-md.ts +1 -4
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +1 -1
- package/src/workspace/migrations/056-release-notes-inference-profile-reordering.ts +5 -2
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +1 -1
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +8 -2
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +41 -14
- package/src/workspace/migrations/102-preserve-heartbeat-enabled-for-existing-workspaces.ts +69 -0
- package/src/workspace/migrations/103-upgrade-quality-profile-to-opus-4-8.ts +83 -0
- package/src/workspace/migrations/104-recheck-adaptive-thinking-model-implied-anthropic.ts +133 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/migrations/runner.ts +1 -1
- package/tsconfig.json +1 -1
- package/src/__tests__/guardian-action-copy-generator.test.ts +0 -200
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -579
- package/src/__tests__/guardian-action-store.test.ts +0 -106
- package/src/daemon/guardian-action-generators.ts +0 -71
- package/src/memory/guardian-action-store.ts +0 -484
- package/src/runtime/guardian-action-grant-minter.ts +0 -150
|
@@ -18,26 +18,28 @@ import { PROVIDER_CATALOG } from "../model-catalog.js";
|
|
|
18
18
|
* Schema-accepted variants (runtime rejects with a clear "not yet shipped" error):
|
|
19
19
|
* - service_account: service-account credentials (Vertex AI, Bedrock).
|
|
20
20
|
*/
|
|
21
|
-
export const AuthSchema = z
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
21
|
+
export const AuthSchema = z
|
|
22
|
+
.discriminatedUnion("type", [
|
|
23
|
+
z.object({
|
|
24
|
+
type: z.literal("api_key"),
|
|
25
|
+
credential: z.string().min(1),
|
|
26
|
+
}),
|
|
27
|
+
z.object({
|
|
28
|
+
type: z.literal("platform"),
|
|
29
|
+
}),
|
|
30
|
+
z.object({
|
|
31
|
+
type: z.literal("none"),
|
|
32
|
+
}),
|
|
33
|
+
z.object({
|
|
34
|
+
type: z.literal("oauth_subscription"),
|
|
35
|
+
credential: z.string().min(1),
|
|
36
|
+
}),
|
|
37
|
+
z.object({
|
|
38
|
+
type: z.literal("service_account"),
|
|
39
|
+
credential: z.string().min(1),
|
|
40
|
+
}),
|
|
41
|
+
])
|
|
42
|
+
.meta({ id: "Auth" });
|
|
41
43
|
|
|
42
44
|
export type Auth = z.infer<typeof AuthSchema>;
|
|
43
45
|
|
|
@@ -75,42 +77,46 @@ export const VALID_CONNECTION_PROVIDERS: readonly string[] =
|
|
|
75
77
|
|
|
76
78
|
export type ConnectionProvider = string;
|
|
77
79
|
|
|
78
|
-
export const ConnectionProviderSchema = z
|
|
79
|
-
VALID_CONNECTION_PROVIDERS as readonly [string, ...string[]]
|
|
80
|
-
);
|
|
80
|
+
export const ConnectionProviderSchema = z
|
|
81
|
+
.enum(VALID_CONNECTION_PROVIDERS as readonly [string, ...string[]])
|
|
82
|
+
.meta({ id: "ConnectionProvider" });
|
|
81
83
|
|
|
82
84
|
// ---------------------------------------------------------------------------
|
|
83
85
|
// Per-connection model entries (openai-compatible)
|
|
84
86
|
// ---------------------------------------------------------------------------
|
|
85
87
|
|
|
86
|
-
export const ConnectionModelSchema = z
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
export const ConnectionModelSchema = z
|
|
89
|
+
.object({
|
|
90
|
+
id: z.string().min(1),
|
|
91
|
+
displayName: z.string().min(1).optional(),
|
|
92
|
+
})
|
|
93
|
+
.meta({ id: "ConnectionModel" });
|
|
90
94
|
export type ConnectionModel = z.infer<typeof ConnectionModelSchema>;
|
|
91
95
|
|
|
92
96
|
// ---------------------------------------------------------------------------
|
|
93
97
|
// Full connection shape used by CRUD layer
|
|
94
98
|
// ---------------------------------------------------------------------------
|
|
95
99
|
|
|
96
|
-
export const ProviderConnectionSchema = z
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
100
|
+
export const ProviderConnectionSchema = z
|
|
101
|
+
.object({
|
|
102
|
+
name: z.string().min(1),
|
|
103
|
+
provider: ConnectionProviderSchema,
|
|
104
|
+
auth: AuthSchema,
|
|
105
|
+
label: z.string().min(1).nullable(),
|
|
106
|
+
baseUrl: z.string().url().nullable(),
|
|
107
|
+
models: z.array(ConnectionModelSchema).nullable(),
|
|
108
|
+
createdAt: z.number().int(),
|
|
109
|
+
updatedAt: z.number().int(),
|
|
110
|
+
/**
|
|
111
|
+
* Whether this row is a Vellum-managed connection (`anthropic-managed`,
|
|
112
|
+
* `openai-managed`, `gemini-managed`). Derived from
|
|
113
|
+
* `MANAGED_CONNECTION_NAMES` in `connections.ts` at serialize time; the
|
|
114
|
+
* DB column does not exist. Clients use this to render the read-only
|
|
115
|
+
* "Vellum" badge + view-only editor and to disable the delete affordance
|
|
116
|
+
* without mirroring the canonical name list locally.
|
|
117
|
+
*/
|
|
118
|
+
isManaged: z.boolean(),
|
|
119
|
+
})
|
|
120
|
+
.meta({ id: "ProviderConnection" });
|
|
115
121
|
|
|
116
122
|
export type ProviderConnection = z.infer<typeof ProviderConnectionSchema>;
|
|
@@ -13,7 +13,7 @@ const PROVIDER_MODEL_INTENTS: Record<string, Record<ModelIntent, string>> = {
|
|
|
13
13
|
anthropic: {
|
|
14
14
|
balanced: "claude-sonnet-4-6",
|
|
15
15
|
"latency-optimized": "claude-haiku-4-5-20251001",
|
|
16
|
-
"quality-optimized": "claude-
|
|
16
|
+
"quality-optimized": "claude-opus-4-8",
|
|
17
17
|
"vision-optimized": "claude-opus-4-6",
|
|
18
18
|
},
|
|
19
19
|
openai: {
|
|
@@ -43,7 +43,7 @@ const PROVIDER_MODEL_INTENTS: Record<string, Record<ModelIntent, string>> = {
|
|
|
43
43
|
openrouter: {
|
|
44
44
|
balanced: "anthropic/claude-sonnet-4.6",
|
|
45
45
|
"latency-optimized": "anthropic/claude-haiku-4.5",
|
|
46
|
-
"quality-optimized": "anthropic/claude-
|
|
46
|
+
"quality-optimized": "anthropic/claude-opus-4.8",
|
|
47
47
|
"vision-optimized": "anthropic/claude-opus-4.6",
|
|
48
48
|
},
|
|
49
49
|
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
coerceObjectParamsToJsonString,
|
|
5
|
+
decodeCoercedObjectArgs,
|
|
6
|
+
} from "../coerce-object-args.js";
|
|
7
|
+
|
|
8
|
+
const SKILL_EXECUTE_SCHEMA = {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: {
|
|
11
|
+
tool: { type: "string", description: "The skill tool name" },
|
|
12
|
+
input: { type: "object", description: "Tool-specific parameters" },
|
|
13
|
+
activity: { type: "string", description: "Progress update" },
|
|
14
|
+
},
|
|
15
|
+
required: ["tool", "input", "activity"],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe("coerceObjectParamsToJsonString", () => {
|
|
19
|
+
test("rewrites object params to strings and reports the keys", () => {
|
|
20
|
+
const { parameters, objectKeys } =
|
|
21
|
+
coerceObjectParamsToJsonString(SKILL_EXECUTE_SCHEMA);
|
|
22
|
+
|
|
23
|
+
expect(objectKeys).toEqual(["input"]);
|
|
24
|
+
const props = (
|
|
25
|
+
parameters as { properties: Record<string, { type: string }> }
|
|
26
|
+
).properties;
|
|
27
|
+
expect(props.input.type).toBe("string");
|
|
28
|
+
// Scalars are left untouched.
|
|
29
|
+
expect(props.tool.type).toBe("string");
|
|
30
|
+
expect(props.activity.type).toBe("string");
|
|
31
|
+
// The required list is preserved.
|
|
32
|
+
expect((parameters as { required: string[] }).required).toEqual([
|
|
33
|
+
"tool",
|
|
34
|
+
"input",
|
|
35
|
+
"activity",
|
|
36
|
+
]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("leaves array and scalar params alone (no coercion)", () => {
|
|
40
|
+
const schema = {
|
|
41
|
+
type: "object",
|
|
42
|
+
properties: {
|
|
43
|
+
query: { type: "string" },
|
|
44
|
+
sources: { type: "array", items: { type: "string" } },
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
const { parameters, objectKeys } = coerceObjectParamsToJsonString(schema);
|
|
48
|
+
expect(objectKeys).toEqual([]);
|
|
49
|
+
expect(parameters).toEqual(schema);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("handles type unions that include object", () => {
|
|
53
|
+
const schema = {
|
|
54
|
+
type: "object",
|
|
55
|
+
properties: { data: { type: ["object", "null"] } },
|
|
56
|
+
};
|
|
57
|
+
const { objectKeys } = coerceObjectParamsToJsonString(schema);
|
|
58
|
+
expect(objectKeys).toEqual(["data"]);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("decodeCoercedObjectArgs", () => {
|
|
63
|
+
test("round-trips a JSON-string object back into an object", () => {
|
|
64
|
+
const { objectKeys } = coerceObjectParamsToJsonString(SKILL_EXECUTE_SCHEMA);
|
|
65
|
+
// What minimax would send once `input` is a string param.
|
|
66
|
+
const onWire = {
|
|
67
|
+
tool: "app_delete",
|
|
68
|
+
input: '{"app_id": "5ee3d2d5-46e8-4a79-928f-00a7471d340b"}',
|
|
69
|
+
activity: "Delete placeholder",
|
|
70
|
+
};
|
|
71
|
+
const { input, failedKey } = decodeCoercedObjectArgs(onWire, objectKeys);
|
|
72
|
+
expect(failedKey).toBeUndefined();
|
|
73
|
+
expect(input.input).toEqual({
|
|
74
|
+
app_id: "5ee3d2d5-46e8-4a79-928f-00a7471d340b",
|
|
75
|
+
});
|
|
76
|
+
// Scalars pass through unchanged.
|
|
77
|
+
expect(input.tool).toBe("app_delete");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("empty string decodes to an empty object", () => {
|
|
81
|
+
const { input } = decodeCoercedObjectArgs({ input: "" }, ["input"]);
|
|
82
|
+
expect(input.input).toEqual({});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("is idempotent when the value is already an object", () => {
|
|
86
|
+
const args = { input: { app_id: "x" } };
|
|
87
|
+
const { input, failedKey } = decodeCoercedObjectArgs(args, ["input"]);
|
|
88
|
+
expect(failedKey).toBeUndefined();
|
|
89
|
+
expect(input.input).toEqual({ app_id: "x" });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("reports failedKey on invalid JSON instead of throwing", () => {
|
|
93
|
+
const { failedKey } = decodeCoercedObjectArgs(
|
|
94
|
+
{ input: "{not valid json" },
|
|
95
|
+
["input"],
|
|
96
|
+
);
|
|
97
|
+
expect(failedKey).toBe("input");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("no-op when there are no coerced keys", () => {
|
|
101
|
+
const args = { tool: "x", input: "{}" };
|
|
102
|
+
const { input } = decodeCoercedObjectArgs(args, []);
|
|
103
|
+
expect(input).toEqual(args);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -18,7 +18,14 @@ import {
|
|
|
18
18
|
ContextOverflowError,
|
|
19
19
|
extractOverflowTokensFromMessage,
|
|
20
20
|
} from "../types.js";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
isUnparseableToolArgs,
|
|
23
|
+
wrapUnparseableToolArgs,
|
|
24
|
+
} from "../unparseable-tool-args.js";
|
|
25
|
+
import {
|
|
26
|
+
coerceObjectParamsToJsonString,
|
|
27
|
+
decodeCoercedObjectArgs,
|
|
28
|
+
} from "./coerce-object-args.js";
|
|
22
29
|
|
|
23
30
|
/**
|
|
24
31
|
* Detect OpenAI-compatible context-overflow signals on an `OpenAI.APIError`.
|
|
@@ -199,6 +206,12 @@ export interface OpenAIChatCompletionsProviderOptions {
|
|
|
199
206
|
* content or tool_calls must be set`. See {@link
|
|
200
207
|
* EMPTY_ASSISTANT_TURN_PLACEHOLDER}. */
|
|
201
208
|
backfillEmptyAssistantContent?: boolean;
|
|
209
|
+
/** Present object-typed tool params to the model as JSON-string params and
|
|
210
|
+
* decode them back to objects on the response. Works around models whose
|
|
211
|
+
* function-call serialization collapses nested objects to `{}` (observed
|
|
212
|
+
* with minimax-m3 on Fireworks). Off by default; scalars/arrays unaffected.
|
|
213
|
+
* See {@link coerceObjectParamsToJsonString}. */
|
|
214
|
+
coerceObjectArgsToJsonString?: boolean;
|
|
202
215
|
}
|
|
203
216
|
|
|
204
217
|
/** Wire-level reasoning_effort values. The OpenAI SDK type doesn't include
|
|
@@ -312,6 +325,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
312
325
|
| "reasoning_content"
|
|
313
326
|
| undefined;
|
|
314
327
|
private backfillEmptyAssistantContent: boolean;
|
|
328
|
+
private coerceObjectArgsToJsonString: boolean;
|
|
315
329
|
|
|
316
330
|
constructor(
|
|
317
331
|
apiKey: string,
|
|
@@ -337,6 +351,8 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
337
351
|
this.assistantReasoningField = options.assistantReasoningField;
|
|
338
352
|
this.backfillEmptyAssistantContent =
|
|
339
353
|
options.backfillEmptyAssistantContent ?? false;
|
|
354
|
+
this.coerceObjectArgsToJsonString =
|
|
355
|
+
options.coerceObjectArgsToJsonString ?? false;
|
|
340
356
|
}
|
|
341
357
|
|
|
342
358
|
async sendMessage(
|
|
@@ -355,6 +371,11 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
355
371
|
| Record<string, string>
|
|
356
372
|
| undefined;
|
|
357
373
|
|
|
374
|
+
// Per-tool keys whose object schemas were rewritten to JSON strings for the
|
|
375
|
+
// wire, to be decoded back on the response. Empty unless
|
|
376
|
+
// `coerceObjectArgsToJsonString` is enabled.
|
|
377
|
+
const coercedObjectKeys = new Map<string, string[]>();
|
|
378
|
+
|
|
358
379
|
try {
|
|
359
380
|
const openaiMessages = this.toOpenAIMessages(messages, systemPrompt);
|
|
360
381
|
|
|
@@ -398,14 +419,24 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
398
419
|
}
|
|
399
420
|
|
|
400
421
|
if (tools && tools.length > 0) {
|
|
401
|
-
params.tools = tools.map((t) =>
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
422
|
+
params.tools = tools.map((t) => {
|
|
423
|
+
let parameters = t.input_schema as OpenAI.FunctionParameters;
|
|
424
|
+
if (this.coerceObjectArgsToJsonString) {
|
|
425
|
+
const coerced = coerceObjectParamsToJsonString(t.input_schema);
|
|
426
|
+
parameters = coerced.parameters as OpenAI.FunctionParameters;
|
|
427
|
+
if (coerced.objectKeys.length > 0) {
|
|
428
|
+
coercedObjectKeys.set(t.name, coerced.objectKeys);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return {
|
|
432
|
+
type: "function" as const,
|
|
433
|
+
function: {
|
|
434
|
+
name: t.name,
|
|
435
|
+
description: t.description,
|
|
436
|
+
parameters,
|
|
437
|
+
},
|
|
438
|
+
};
|
|
439
|
+
});
|
|
409
440
|
|
|
410
441
|
// Honor a caller-supplied tool_choice (e.g. `{ type: "none" }` to force
|
|
411
442
|
// a text-only answer, or `{ type: "tool", name }` for a forced call).
|
|
@@ -638,6 +669,13 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
638
669
|
} catch {
|
|
639
670
|
input = wrapUnparseableToolArgs(tc.args);
|
|
640
671
|
}
|
|
672
|
+
const objectKeys = coercedObjectKeys.get(tc.name);
|
|
673
|
+
if (objectKeys && !isUnparseableToolArgs(input)) {
|
|
674
|
+
const decoded = decodeCoercedObjectArgs(input, objectKeys);
|
|
675
|
+
input = decoded.failedKey
|
|
676
|
+
? wrapUnparseableToolArgs(tc.args)
|
|
677
|
+
: decoded.input;
|
|
678
|
+
}
|
|
641
679
|
content.push({
|
|
642
680
|
type: "tool_use",
|
|
643
681
|
id: tc.id,
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Some OpenAI-compatible models (notably minimax-m3 served via Fireworks)
|
|
3
|
+
* collapse nested *object*-typed tool arguments to `{}` during their
|
|
4
|
+
* function-call serialization, while scalars and arrays survive intact. The
|
|
5
|
+
* model reasons correctly about the intended fields, but the object value is
|
|
6
|
+
* lost on the wire before it reaches us as valid-but-empty JSON, so there is
|
|
7
|
+
* nothing to recover at parse time.
|
|
8
|
+
*
|
|
9
|
+
* The workaround presents every top-level object-typed parameter to the model
|
|
10
|
+
* as a `string` it fills with JSON (strings survive the serializer), then
|
|
11
|
+
* decodes that string back into an object before dispatch. The transform is a
|
|
12
|
+
* matched pair — {@link coerceObjectParamsToJsonString} on the outbound schema
|
|
13
|
+
* and {@link decodeCoercedObjectArgs} on the inbound tool-call arguments — and
|
|
14
|
+
* is gated to the affected providers so other models keep native object
|
|
15
|
+
* passthrough.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
interface ObjectSchemaLike {
|
|
19
|
+
type?: unknown;
|
|
20
|
+
properties?: Record<string, { type?: unknown; description?: string }>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isObjectTyped(prop: { type?: unknown }): boolean {
|
|
24
|
+
if (prop?.type === "object") return true;
|
|
25
|
+
if (Array.isArray(prop?.type) && prop.type.includes("object")) return true;
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface CoercedToolSchema {
|
|
30
|
+
/** The tool's JSON schema with object params rewritten to JSON-string params. */
|
|
31
|
+
parameters: Record<string, unknown>;
|
|
32
|
+
/** Top-level param keys that were object-typed and are now JSON strings. */
|
|
33
|
+
objectKeys: string[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Rewrite top-level `type: "object"` properties of a tool's input schema into
|
|
38
|
+
* `type: "string"` params the model fills with JSON. Returns the rewritten
|
|
39
|
+
* schema plus the list of converted keys so the inbound side can reverse it.
|
|
40
|
+
* Non-object params (scalars, arrays) are passed through unchanged. Arrays and
|
|
41
|
+
* deeper-nested objects are intentionally left alone — only top-level object
|
|
42
|
+
* params are observed to collapse.
|
|
43
|
+
*/
|
|
44
|
+
export function coerceObjectParamsToJsonString(
|
|
45
|
+
inputSchema: unknown,
|
|
46
|
+
): CoercedToolSchema {
|
|
47
|
+
const schema = inputSchema as ObjectSchemaLike | undefined;
|
|
48
|
+
if (!schema || schema.type !== "object" || !schema.properties) {
|
|
49
|
+
return {
|
|
50
|
+
parameters: (inputSchema as Record<string, unknown>) ?? {},
|
|
51
|
+
objectKeys: [],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const objectKeys: string[] = [];
|
|
56
|
+
const properties: Record<string, unknown> = {};
|
|
57
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
58
|
+
if (isObjectTyped(prop)) {
|
|
59
|
+
objectKeys.push(key);
|
|
60
|
+
properties[key] = {
|
|
61
|
+
type: "string",
|
|
62
|
+
description:
|
|
63
|
+
`${prop.description ?? ""}\n\nPass this argument as a JSON object encoded as a string, e.g. "{\\"key\\": \\"value\\"}".`.trim(),
|
|
64
|
+
};
|
|
65
|
+
} else {
|
|
66
|
+
properties[key] = prop;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { parameters: { ...schema, properties }, objectKeys };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Reverse {@link coerceObjectParamsToJsonString}: for each coerced key whose
|
|
75
|
+
* value arrived as a string, JSON-parse it back into an object. Values that are
|
|
76
|
+
* already objects (e.g. replayed conversation history, or a model that sent the
|
|
77
|
+
* object natively) are left untouched, so the decode is idempotent. An empty
|
|
78
|
+
* string decodes to `{}`. If a non-empty string fails to parse, the key name is
|
|
79
|
+
* returned in `failedKey` so the caller can surface a retryable error instead of
|
|
80
|
+
* silently dispatching garbage.
|
|
81
|
+
*/
|
|
82
|
+
export function decodeCoercedObjectArgs(
|
|
83
|
+
input: Record<string, unknown>,
|
|
84
|
+
objectKeys: string[],
|
|
85
|
+
): { input: Record<string, unknown>; failedKey?: string } {
|
|
86
|
+
if (objectKeys.length === 0) return { input };
|
|
87
|
+
|
|
88
|
+
const result: Record<string, unknown> = { ...input };
|
|
89
|
+
for (const key of objectKeys) {
|
|
90
|
+
const value = result[key];
|
|
91
|
+
if (typeof value !== "string") continue;
|
|
92
|
+
const trimmed = value.trim();
|
|
93
|
+
if (trimmed === "") {
|
|
94
|
+
result[key] = {};
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
result[key] = JSON.parse(trimmed);
|
|
99
|
+
} catch {
|
|
100
|
+
return { input: result, failedKey: key };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return { input: result };
|
|
104
|
+
}
|
package/src/providers/retry.ts
CHANGED
|
@@ -197,22 +197,25 @@ function normalizeSendMessageOptions(
|
|
|
197
197
|
delete nextConfig.usageAttributionHeaders;
|
|
198
198
|
delete nextConfig.usageTracking;
|
|
199
199
|
|
|
200
|
-
// `overrideProfile` and `selectionSeed` are
|
|
201
|
-
// (consumed by the resolver below and
|
|
202
|
-
// selection);
|
|
203
|
-
// never leak into provider request
|
|
204
|
-
// a `callSite`.
|
|
200
|
+
// `overrideProfile`, `forceOverrideProfile`, and `selectionSeed` are
|
|
201
|
+
// routing/resolution-time concerns (consumed by the resolver below and
|
|
202
|
+
// `CallSiteRoutingProvider`'s provider selection); none is a wire-format
|
|
203
|
+
// field. Strip unconditionally so they never leak into provider request
|
|
204
|
+
// bodies even when callers set them without a `callSite`.
|
|
205
205
|
delete nextConfig.overrideProfile;
|
|
206
|
+
delete nextConfig.forceOverrideProfile;
|
|
206
207
|
delete nextConfig.selectionSeed;
|
|
207
208
|
|
|
208
209
|
if (config.callSite !== undefined) {
|
|
209
210
|
const resolved = resolveCallSiteConfig(config.callSite, getConfig().llm, {
|
|
210
211
|
overrideProfile: config.overrideProfile,
|
|
212
|
+
forceOverrideProfile: config.forceOverrideProfile,
|
|
211
213
|
selectionSeed: config.selectionSeed,
|
|
212
214
|
});
|
|
213
215
|
const attribution = resolveUsageAttribution({
|
|
214
216
|
callSite: config.callSite,
|
|
215
217
|
overrideProfile: config.overrideProfile,
|
|
218
|
+
forceOverrideProfile: config.forceOverrideProfile,
|
|
216
219
|
selectionSeed: config.selectionSeed,
|
|
217
220
|
});
|
|
218
221
|
|
package/src/providers/types.ts
CHANGED
|
@@ -182,6 +182,16 @@ export interface SendMessageConfig {
|
|
|
182
182
|
* silently fall through.
|
|
183
183
|
*/
|
|
184
184
|
overrideProfile?: string;
|
|
185
|
+
/**
|
|
186
|
+
* When true, the resolver floats `overrideProfile` above the call-site
|
|
187
|
+
* layers (named site profile + call-site override) for non-main-agent call
|
|
188
|
+
* sites — see `ResolveCallSiteOpts.forceOverrideProfile`. Used by callers
|
|
189
|
+
* that must run a background call site under a specific conversation's
|
|
190
|
+
* inference profile (e.g. fork-based memory retrospectives). A
|
|
191
|
+
* resolution/routing-time concern only; stripped before any provider wire
|
|
192
|
+
* request.
|
|
193
|
+
*/
|
|
194
|
+
forceOverrideProfile?: boolean;
|
|
185
195
|
/**
|
|
186
196
|
* Per-conversation seed for deterministic `mix`-profile expansion. The agent
|
|
187
197
|
* loop sets this to the conversation id so every resolver call this send
|