@vellumai/assistant 0.12.5 → 0.12.6-dev.202609292019.a6f6d85
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/.env.example +2 -0
- package/ARCHITECTURE.md +23 -0
- package/docs/automatic-done.md +32 -0
- package/docs/desktop-browser-cli.md +3 -2
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/mcp-oauth.test.ts +53 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/mcp-oauth.ts +60 -0
- package/node_modules/@vellumai/environments/src/shell.test.ts +13 -1
- package/node_modules/@vellumai/environments/src/shell.ts +22 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/mcp-oauth.test.ts +53 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/mcp-oauth.ts +60 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/status-contracts.test.ts +39 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +25 -0
- package/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/mcp-oauth.test.ts +53 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/mcp-oauth.ts +60 -0
- package/openapi.yaml +270 -10
- package/package.json +1 -1
- package/src/__tests__/agent-loop.test.ts +76 -0
- package/src/__tests__/anthropic-provider.test.ts +2 -0
- package/src/__tests__/byok-default-profile-ensure.test.ts +7 -0
- package/src/__tests__/config-get-vision-flag.test.ts +1 -1
- package/src/__tests__/config-loader-validation-reset-notice.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +160 -154
- package/src/__tests__/conversation-evictor.test.ts +54 -0
- package/src/__tests__/conversation-pairing.test.ts +112 -0
- package/src/__tests__/document-append-idempotency.test.ts +13 -0
- package/src/__tests__/document-create-dedupe.test.ts +13 -0
- package/src/__tests__/document-find-replace.test.ts +13 -0
- package/src/__tests__/document-revision-history.test.ts +390 -0
- package/src/__tests__/document-revision.test.ts +425 -0
- package/src/__tests__/document-tool-security.test.ts +13 -0
- package/src/__tests__/document-update-default-surface.test.ts +13 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +270 -0
- package/src/__tests__/gateway-flag-listener.test.ts +59 -6
- package/src/__tests__/headless-browser-navigate.test.ts +20 -30
- package/src/__tests__/host-cu-proxy.test.ts +79 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +14 -5
- package/src/__tests__/host-shell-tool.test.ts +6 -2
- package/src/__tests__/identity-routes.test.ts +4 -3
- package/src/__tests__/llm-catalog-parity.test.ts +4 -4
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/notification-platform-adapter.test.ts +83 -1
- package/src/__tests__/oauth2-gateway-transport.test.ts +2 -0
- package/src/__tests__/openai-provider.test.ts +11 -11
- package/src/__tests__/pricing.test.ts +11 -0
- package/src/__tests__/public-ingress-urls.test.ts +26 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +47 -0
- package/src/__tests__/usage-attribution.test.ts +31 -0
- package/src/__tests__/workspace-migration-133-collapse-provider-connections.test.ts +3 -3
- package/src/__tests__/workspace-migration-160-repair-retired-fireworks-model-ids.test.ts +262 -0
- package/src/__tests__/workspace-migration-161-repair-retired-fireworks-glm-5p2-model-id.test.ts +233 -0
- package/src/acp/agent-process.ts +6 -1
- package/src/acp/client-handler.ts +6 -1
- package/src/agent/loop.ts +29 -6
- package/src/api/events/document-editor-show.ts +5 -0
- package/src/api/events/document-editor-update.ts +10 -0
- package/src/api/events/tool-result.ts +1 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +54 -0
- package/src/calls/channel-admission-reader.ts +15 -9
- package/src/calls/twilio-provider.ts +14 -31
- package/src/calls/voice-session-bridge.ts +18 -1
- package/src/cli/commands/browser.ts +1 -2
- package/src/cli/lib/__tests__/plugin-artifact.test.ts +23 -0
- package/src/cli/lib/__tests__/plugin-catalog-visibility.test.ts +2 -0
- package/src/cli/lib/__tests__/plugin-details.test.ts +16 -0
- package/src/cli/lib/bundled-marketplace.json +41 -2
- package/src/cli/lib/inspect-plugin.ts +15 -15
- package/src/cli/lib/list-installed-plugins.ts +29 -28
- package/src/cli/lib/plugin-artifact.ts +74 -63
- package/src/cli/lib/plugin-catalog-visibility.ts +1 -0
- package/src/cli/lib/plugin-details.ts +27 -42
- package/src/cli/lib/plugin-marketplace.ts +6 -8
- package/src/cli/lib/plugin-surfaces.ts +8 -7
- package/src/cli.ts +1 -3
- package/src/config/__tests__/chat-settings.test.ts +121 -0
- package/src/config/assistant-feature-flags.ts +28 -23
- package/src/config/bundled-skills/computer-use/SKILL.md +20 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +11 -11
- package/src/config/chat-settings.ts +100 -0
- package/src/config/default-profile-catalog.ts +1 -1
- package/src/config/feature-flag-cache.ts +7 -25
- package/src/config/feature-flag-registry.json +1 -9
- package/src/config/loader.ts +5 -1
- package/src/config/profile-text-generation.ts +25 -21
- package/src/config/schemas/conversations.ts +14 -0
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/notifications.ts +8 -1
- package/src/contacts/gateway-channel-read.ts +1 -1
- package/src/conversations/__tests__/auto-archive-activity.test.ts +136 -0
- package/src/conversations/__tests__/auto-archive.test.ts +304 -0
- package/src/conversations/auto-archive-activity.ts +61 -0
- package/src/conversations/auto-archive.ts +201 -0
- package/src/daemon/computer-use-observation.test.ts +81 -0
- package/src/daemon/computer-use-observation.ts +23 -0
- package/src/daemon/conversation-agent-loop.ts +11 -6
- package/src/daemon/conversation-evictor.ts +50 -16
- package/src/daemon/doordash-steps.ts +1 -3
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +43 -1
- package/src/daemon/handlers/__tests__/config-channels.test.ts +1 -1
- package/src/daemon/handlers/config-a2a.ts +75 -2
- package/src/daemon/host-cu-proxy.ts +34 -3
- package/src/daemon/lifecycle.ts +15 -2
- package/src/daemon/shutdown-handlers.ts +3 -0
- package/src/daemon/turn-finalization.ts +4 -0
- package/src/desktop/desktop-browser-endpoint.ts +11 -2
- package/src/desktop/desktop-chrome-policy.test.ts +1 -0
- package/src/desktop/desktop-chrome-policy.ts +7 -1
- package/src/desktop/desktop-computer-use.test.ts +14 -4
- package/src/desktop/desktop-session-manager.ts +5 -3
- package/src/documents/document-revisions-store.ts +153 -0
- package/src/documents/document-store.ts +471 -133
- package/src/followups/followup-store.ts +0 -4
- package/src/inbound/__tests__/oauth-callback-url.test.ts +25 -2
- package/src/inbound/oauth-callback-url.ts +30 -1
- package/src/inbound/public-ingress-urls.ts +12 -2
- package/src/ipc/gateway-client.test.ts +40 -0
- package/src/ipc/gateway-client.ts +12 -29
- package/src/ipc/gateway-flag-listener.ts +7 -10
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +71 -0
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +83 -0
- package/src/live-voice/__tests__/protocol.test.ts +77 -0
- package/src/live-voice/__tests__/share-targets.test.ts +163 -0
- package/src/live-voice/live-voice-session.ts +23 -6
- package/src/live-voice/protocol.ts +22 -0
- package/src/live-voice/share-targets.ts +225 -0
- package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +144 -3
- package/src/mcp/__tests__/mcp-oauth-provider.test.ts +2 -0
- package/src/mcp/client.ts +1 -19
- package/src/mcp/mcp-oauth-provider.ts +66 -49
- package/src/media/openrouter-image-service.ts +39 -22
- package/src/monitoring/__tests__/oom-inheritance-sweep.test.ts +86 -0
- package/src/monitoring/__tests__/oom-kill-reporter.test.ts +374 -0
- package/src/monitoring/control.ts +2 -1
- package/src/monitoring/oom-inheritance-sweep.ts +96 -0
- package/src/monitoring/oom-kill-reporter.ts +469 -0
- package/src/monitoring/resource-sampler.ts +30 -0
- package/src/notifications/README.md +53 -4
- package/src/notifications/__tests__/assistant-initiated-thread.test.ts +254 -0
- package/src/notifications/__tests__/broadcaster.test.ts +558 -6
- package/src/notifications/__tests__/completion-policy.test.ts +37 -0
- package/src/notifications/__tests__/from-me-alert-integration.test.ts +192 -0
- package/src/notifications/adapters/platform.ts +14 -0
- package/src/notifications/assistant-initiated-thread.ts +101 -0
- package/src/notifications/broadcaster.ts +94 -16
- package/src/notifications/chat-reply-policy.ts +11 -0
- package/src/notifications/completion-policy.ts +12 -2
- package/src/notifications/conversation-pairing.ts +15 -70
- package/src/notifications/emit-signal.ts +34 -3
- package/src/notifications/types.ts +2 -0
- package/src/oauth/connect-orchestrator.ts +1 -2
- package/src/persistence/__tests__/conversation-auto-archive.test.ts +330 -0
- package/src/persistence/conversation-auto-archive.ts +170 -0
- package/src/persistence/conversation-crud.ts +2 -1
- package/src/persistence/conversation-queries.ts +15 -8
- package/src/persistence/embeddings/embed.test.ts +96 -0
- package/src/persistence/embeddings/embed.ts +20 -2
- package/src/persistence/embeddings/embedding-gemini.test.ts +39 -3
- package/src/persistence/embeddings/embedding-gemini.ts +39 -1
- package/src/persistence/embeddings/embedding-local.ts +6 -0
- package/src/persistence/embeddings/qdrant-manager.ts +5 -0
- package/src/persistence/job-utils.ts +10 -0
- package/src/persistence/migrations/384-add-document-revision.test.ts +83 -0
- package/src/persistence/migrations/384-add-document-revision.ts +21 -0
- package/src/persistence/migrations/385-create-document-revisions.test.ts +67 -0
- package/src/persistence/migrations/385-create-document-revisions.ts +28 -0
- package/src/persistence/migrations/386-conversations-last-reopened-at.ts +10 -0
- package/src/persistence/migrations/__tests__/386-conversations-last-reopened-at.test.ts +32 -0
- package/src/persistence/schema/conversations.ts +1 -0
- package/src/persistence/schema/documents.ts +20 -0
- package/src/persistence/steps.ts +6 -0
- package/src/platform/managed-speech.ts +42 -46
- package/src/plugin-api/vision-support.test.ts +21 -21
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +11 -6
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +1 -1
- package/src/providers/__tests__/search-provider-catalog.test.ts +8 -0
- package/src/providers/anthropic/client.ts +1 -1
- package/src/providers/fireworks/client.test.ts +168 -0
- package/src/providers/fireworks/client.ts +24 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/ionet/client.test.ts +143 -0
- package/src/providers/ionet/client.ts +37 -0
- package/src/providers/model-catalog.ts +141 -84
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/openai/chat-completions-provider.ts +23 -1
- package/src/providers/retry.ts +56 -4
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/types.ts +10 -2
- package/src/providers/usage-tracking.ts +5 -3
- package/src/runtime/assistant-event-hub.ts +23 -0
- package/src/runtime/auth/__tests__/guard-tests.test.ts +0 -7
- package/src/runtime/auth/__tests__/route-policy.test.ts +1 -1
- package/src/runtime/channel-retry-sweep.ts +1 -2
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +35 -10
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +48 -0
- package/src/runtime/migrations/vbundle-builder.ts +19 -3
- package/src/runtime/migrations/vbundle-streaming-importer.ts +14 -19
- package/src/runtime/migrations/vbundle-streaming-validator.ts +14 -7
- package/src/runtime/migrations/vbundle-validator.ts +54 -1
- package/src/runtime/pending-interactions.ts +20 -2
- package/src/runtime/routes/__tests__/contact-routes.test.ts +5 -3
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +36 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +375 -2
- package/src/runtime/routes/__tests__/inference-send-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +12 -0
- package/src/runtime/routes/contact-routes.ts +2 -2
- package/src/runtime/routes/conversation-list-routes.ts +10 -2
- package/src/runtime/routes/conversation-query-routes.ts +48 -10
- package/src/runtime/routes/documents-routes.ts +185 -47
- package/src/runtime/routes/events-routes.ts +1 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -0
- package/src/runtime/routes/host-bash-routes.ts +1 -0
- package/src/runtime/routes/host-browser-routes.ts +15 -0
- package/src/runtime/routes/host-cu-routes.ts +4 -1
- package/src/runtime/routes/host-file-routes.ts +1 -0
- package/src/runtime/routes/host-proxy-result-binding.test.ts +83 -0
- package/src/runtime/routes/host-proxy-result-binding.ts +25 -0
- package/src/runtime/routes/host-transfer-routes.ts +1 -0
- package/src/runtime/routes/identity-routes.ts +3 -3
- package/src/runtime/routes/integrations/a2a.ts +4 -1
- package/src/runtime/routes/migration-routes.ts +3 -1
- package/src/runtime/routes/notification-routes.ts +1 -2
- package/src/runtime/routes/ui-snapshot-routes.test.ts +1 -0
- package/src/runtime/routes/user-route-dispatcher.ts +5 -1
- package/src/runtime/verification-templates.ts +1 -2
- package/src/sequence/analytics.ts +0 -4
- package/src/sequence/engine.ts +1 -11
- package/src/sequence/guardrails.ts +1 -6
- package/src/sequence/importer.ts +0 -8
- package/src/sequence/store.ts +0 -10
- package/src/signals/user-message.ts +0 -6
- package/src/skills/catalog-install.ts +52 -23
- package/src/tools/browser/browser-execution.ts +20 -23
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +1 -3
- package/src/tools/document/document-tool.ts +13 -11
- package/src/tools/executor.ts +1 -2
- package/src/tools/host-terminal/host-shell.ts +4 -2
- package/src/tools/network/__tests__/web-search.test.ts +105 -0
- package/src/tools/network/web-fetch.ts +2 -4
- package/src/tools/network/web-search.ts +239 -12
- package/src/tools/shared/filesystem/format-diff.ts +1 -2
- package/src/tools/shared/shell-output.test.ts +42 -0
- package/src/tools/shared/shell-output.ts +27 -4
- package/src/tools/terminal/shell.ts +3 -3
- package/src/tools/ui-surface/visual-validation.ts +1 -2
- package/src/usage/attribution.ts +18 -1
- package/src/util/__tests__/oom-priority.test.ts +55 -0
- package/src/util/__tests__/worker-memory.test.ts +16 -0
- package/src/util/debounce.ts +0 -4
- package/src/util/oom-priority.ts +79 -0
- package/src/util/platform.ts +0 -2
- package/src/util/plugin-manifest.ts +5 -7
- package/src/util/pricing.ts +25 -0
- package/src/util/worker-memory.ts +9 -3
- package/src/util/worker-process.ts +8 -0
- package/src/workspace/byok-default-profile-ensure.ts +11 -0
- package/src/workspace/hatched-date.ts +11 -4
- package/src/workspace/migrations/160-repair-retired-fireworks-model-ids.ts +209 -0
- package/src/workspace/migrations/161-repair-retired-fireworks-glm-5p2-model-id.ts +197 -0
- package/src/workspace/migrations/registry.ts +4 -0
|
@@ -166,6 +166,7 @@ describe("identity routes — health endpoint", () => {
|
|
|
166
166
|
memoryOptOut: true,
|
|
167
167
|
retryLastTurn: true,
|
|
168
168
|
appPins: true,
|
|
169
|
+
chatsSettings: true,
|
|
169
170
|
});
|
|
170
171
|
|
|
171
172
|
// Profiler should either be absent or show enabled: false
|
|
@@ -492,9 +493,9 @@ describe("identity routes — /readyz readiness gate", () => {
|
|
|
492
493
|
expect(body.ready).toBe(false);
|
|
493
494
|
expect(body.reason).toBe("db_migrations_failed");
|
|
494
495
|
expect((body.dbMigrations as Record<string, unknown>).state).toBe("failed");
|
|
495
|
-
expect(
|
|
496
|
-
|
|
497
|
-
);
|
|
496
|
+
expect(
|
|
497
|
+
(body.dbMigrations as Record<string, unknown>).failedMigrations,
|
|
498
|
+
).toEqual([{ name: "flakyStep", error: "transient failure" }]);
|
|
498
499
|
});
|
|
499
500
|
|
|
500
501
|
test("returns 200 even if CES is down", async () => {
|
|
@@ -390,9 +390,9 @@ describe("LLM catalog parity: daemon vs client", () => {
|
|
|
390
390
|
});
|
|
391
391
|
});
|
|
392
392
|
|
|
393
|
-
test("Fireworks catalog includes GLM 5.
|
|
393
|
+
test("Fireworks catalog includes GLM 5.3", () => {
|
|
394
394
|
expect(
|
|
395
|
-
isModelInCatalog("fireworks", "accounts/fireworks/models/glm-
|
|
395
|
+
isModelInCatalog("fireworks", "accounts/fireworks/models/glm-5p3"),
|
|
396
396
|
).toBe(true);
|
|
397
397
|
|
|
398
398
|
const fireworks = PROVIDER_CATALOG.find(
|
|
@@ -400,10 +400,10 @@ describe("LLM catalog parity: daemon vs client", () => {
|
|
|
400
400
|
);
|
|
401
401
|
expect(
|
|
402
402
|
fireworks?.models.find(
|
|
403
|
-
(model) => model.id === "accounts/fireworks/models/glm-
|
|
403
|
+
(model) => model.id === "accounts/fireworks/models/glm-5p3",
|
|
404
404
|
),
|
|
405
405
|
).toMatchObject({
|
|
406
|
-
displayName: "GLM 5.
|
|
406
|
+
displayName: "GLM 5.3",
|
|
407
407
|
contextWindowTokens: 1040000,
|
|
408
408
|
maxOutputTokens: 131072,
|
|
409
409
|
supportsToolUse: true,
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import { saveRawConfig } from "../config/loader.js";
|
|
4
|
+
|
|
3
5
|
// ── Mock logger ──────────────────────────────────────────────────────────────
|
|
4
6
|
|
|
5
7
|
// ── Mock sleep so retry tests don't slow down the suite ──────────────────────
|
|
6
8
|
|
|
9
|
+
let onRetrySleep: () => Promise<void> = async () => {};
|
|
7
10
|
mock.module("../util/retry.js", () => ({
|
|
8
|
-
sleep: async (_ms: number): Promise<void> =>
|
|
11
|
+
sleep: async (_ms: number): Promise<void> => onRetrySleep(),
|
|
9
12
|
isRetryableStatus: (status: number): boolean =>
|
|
10
13
|
status === 429 || status >= 500,
|
|
11
14
|
isRetryableNetworkError: (error: unknown): boolean => {
|
|
@@ -41,10 +44,12 @@ const fetchResponses: Array<{ ok: boolean; status: number; body?: string }> =
|
|
|
41
44
|
[];
|
|
42
45
|
const fetchErrors: Error[] = [];
|
|
43
46
|
let clientAvailable = true;
|
|
47
|
+
let onClientCreation: () => Promise<void> = async () => {};
|
|
44
48
|
|
|
45
49
|
mock.module("../platform/client.js", () => ({
|
|
46
50
|
VellumPlatformClient: {
|
|
47
51
|
create: async () => {
|
|
52
|
+
await onClientCreation();
|
|
48
53
|
if (!clientAvailable) {
|
|
49
54
|
return null;
|
|
50
55
|
}
|
|
@@ -117,12 +122,89 @@ function makeDestination(
|
|
|
117
122
|
|
|
118
123
|
describe("PlatformPushAdapter", () => {
|
|
119
124
|
beforeEach(() => {
|
|
125
|
+
saveRawConfig({});
|
|
120
126
|
fetchCalls.length = 0;
|
|
121
127
|
fetchResponses.length = 0;
|
|
122
128
|
fetchErrors.length = 0;
|
|
123
129
|
clientAvailable = true;
|
|
130
|
+
onRetrySleep = async () => {};
|
|
131
|
+
onClientCreation = async () => {};
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("skips a disabled chat reply without sending a native push", async () => {
|
|
135
|
+
saveRawConfig({ notifications: { newMessageEnabled: false } });
|
|
136
|
+
const result = await new PlatformPushAdapter().send(
|
|
137
|
+
makePayload({ sourceEventName: "chat.assistant_reply" }),
|
|
138
|
+
makeDestination(),
|
|
139
|
+
);
|
|
140
|
+
expect(result).toMatchObject({
|
|
141
|
+
success: false,
|
|
142
|
+
skipped: true,
|
|
143
|
+
remotePushAccepted: false,
|
|
144
|
+
});
|
|
145
|
+
expect(fetchCalls).toHaveLength(0);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("rechecks the setting after platform client creation", async () => {
|
|
149
|
+
onClientCreation = async () => {
|
|
150
|
+
saveRawConfig({ notifications: { newMessageEnabled: false } });
|
|
151
|
+
};
|
|
152
|
+
const result = await new PlatformPushAdapter().send(
|
|
153
|
+
makePayload({ sourceEventName: "chat.assistant_reply" }),
|
|
154
|
+
makeDestination(),
|
|
155
|
+
);
|
|
156
|
+
expect(result).toMatchObject({
|
|
157
|
+
success: false,
|
|
158
|
+
skipped: true,
|
|
159
|
+
remotePushAccepted: false,
|
|
160
|
+
});
|
|
161
|
+
expect(fetchCalls).toHaveLength(0);
|
|
124
162
|
});
|
|
125
163
|
|
|
164
|
+
test.each([false, true])(
|
|
165
|
+
"stops retries after disabling replies (accepted push: %s)",
|
|
166
|
+
async (accepted) => {
|
|
167
|
+
fetchResponses.push({
|
|
168
|
+
ok: false,
|
|
169
|
+
status: 503,
|
|
170
|
+
body: accepted ? '{"accepted_platforms":["ios"]}' : "{}",
|
|
171
|
+
});
|
|
172
|
+
onRetrySleep = async () => {
|
|
173
|
+
saveRawConfig({ notifications: { newMessageEnabled: false } });
|
|
174
|
+
};
|
|
175
|
+
const result = await new PlatformPushAdapter().send(
|
|
176
|
+
makePayload({ sourceEventName: "chat.assistant_reply" }),
|
|
177
|
+
makeDestination(),
|
|
178
|
+
);
|
|
179
|
+
expect(fetchCalls).toHaveLength(1);
|
|
180
|
+
expect(result).toMatchObject({
|
|
181
|
+
success: accepted,
|
|
182
|
+
skipped: !accepted,
|
|
183
|
+
remotePushAccepted: accepted,
|
|
184
|
+
remotePushPlatforms: accepted ? ["ios"] : undefined,
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
test.each([
|
|
190
|
+
"schedule.result",
|
|
191
|
+
"schedule.notify",
|
|
192
|
+
"guardian.question",
|
|
193
|
+
"activity.failed",
|
|
194
|
+
"chat.assistant_reply.extra",
|
|
195
|
+
])(
|
|
196
|
+
"keeps %s native push enabled when ordinary reply alerts are off",
|
|
197
|
+
async (sourceEventName) => {
|
|
198
|
+
saveRawConfig({ notifications: { newMessageEnabled: false } });
|
|
199
|
+
const result = await new PlatformPushAdapter().send(
|
|
200
|
+
makePayload({ sourceEventName }),
|
|
201
|
+
makeDestination(),
|
|
202
|
+
);
|
|
203
|
+
expect(result.success).toBe(true);
|
|
204
|
+
expect(fetchCalls).toHaveLength(1);
|
|
205
|
+
},
|
|
206
|
+
);
|
|
207
|
+
|
|
126
208
|
test("channel is 'platform'", () => {
|
|
127
209
|
expect(new PlatformPushAdapter().channel).toBe("platform");
|
|
128
210
|
});
|
|
@@ -48,6 +48,8 @@ let mockOAuthCallbackUrl = "";
|
|
|
48
48
|
// getPublicBaseUrl.
|
|
49
49
|
mock.module("../inbound/public-ingress-urls.js", () => ({
|
|
50
50
|
getOAuthCallbackUrl: () => mockOAuthCallbackUrl,
|
|
51
|
+
getMcpOAuthClientMetadataUrl: () =>
|
|
52
|
+
"http://localhost/oauth/client-metadata.json",
|
|
51
53
|
getPublicBaseUrl: (config?: { ingress?: { publicBaseUrl?: string } }) => {
|
|
52
54
|
const url = config?.ingress?.publicBaseUrl ?? "";
|
|
53
55
|
if (!url) {
|
|
@@ -1960,10 +1960,10 @@ describe("FireworksProvider reasoning_effort ceiling", () => {
|
|
|
1960
1960
|
lastCreateParams = null;
|
|
1961
1961
|
});
|
|
1962
1962
|
|
|
1963
|
-
test('DeepSeek V4
|
|
1963
|
+
test('DeepSeek V4.1 Flash accepts "max" unclamped', async () => {
|
|
1964
1964
|
const fw = new FireworksProvider(
|
|
1965
1965
|
"fw-key",
|
|
1966
|
-
"accounts/fireworks/models/deepseek-
|
|
1966
|
+
"accounts/fireworks/models/deepseek-v4p1-flash",
|
|
1967
1967
|
);
|
|
1968
1968
|
await fw.sendMessage([userMsg("hi")], {
|
|
1969
1969
|
systemPrompt: "system",
|
|
@@ -1972,10 +1972,10 @@ describe("FireworksProvider reasoning_effort ceiling", () => {
|
|
|
1972
1972
|
expect(lastCreateParams!.reasoning_effort).toBe("max");
|
|
1973
1973
|
});
|
|
1974
1974
|
|
|
1975
|
-
test('DeepSeek V4
|
|
1975
|
+
test('DeepSeek V4.1 Flash accepts "xhigh" unclamped', async () => {
|
|
1976
1976
|
const fw = new FireworksProvider(
|
|
1977
1977
|
"fw-key",
|
|
1978
|
-
"accounts/fireworks/models/deepseek-
|
|
1978
|
+
"accounts/fireworks/models/deepseek-v4p1-flash",
|
|
1979
1979
|
);
|
|
1980
1980
|
await fw.sendMessage([userMsg("hi")], {
|
|
1981
1981
|
systemPrompt: "system",
|
|
@@ -1984,10 +1984,10 @@ describe("FireworksProvider reasoning_effort ceiling", () => {
|
|
|
1984
1984
|
expect(lastCreateParams!.reasoning_effort).toBe("xhigh");
|
|
1985
1985
|
});
|
|
1986
1986
|
|
|
1987
|
-
test('
|
|
1987
|
+
test('MiniMax M3 clamps "xhigh"/"max" down to "high"', async () => {
|
|
1988
1988
|
const fw = new FireworksProvider(
|
|
1989
1989
|
"fw-key",
|
|
1990
|
-
"accounts/fireworks/models/
|
|
1990
|
+
"accounts/fireworks/models/minimax-m3",
|
|
1991
1991
|
);
|
|
1992
1992
|
await fw.sendMessage([userMsg("hi")], {
|
|
1993
1993
|
systemPrompt: "system",
|
|
@@ -2016,7 +2016,7 @@ describe("FireworksProvider reasoning_effort ceiling", () => {
|
|
|
2016
2016
|
test("effort below ceiling is forwarded verbatim", async () => {
|
|
2017
2017
|
const fw = new FireworksProvider(
|
|
2018
2018
|
"fw-key",
|
|
2019
|
-
"accounts/fireworks/models/deepseek-
|
|
2019
|
+
"accounts/fireworks/models/deepseek-v4p1-flash",
|
|
2020
2020
|
);
|
|
2021
2021
|
await fw.sendMessage([userMsg("hi")], {
|
|
2022
2022
|
systemPrompt: "system",
|
|
@@ -2028,7 +2028,7 @@ describe("FireworksProvider reasoning_effort ceiling", () => {
|
|
|
2028
2028
|
test('effort: "none" passes through regardless of ceiling', async () => {
|
|
2029
2029
|
const fw = new FireworksProvider(
|
|
2030
2030
|
"fw-key",
|
|
2031
|
-
"accounts/fireworks/models/
|
|
2031
|
+
"accounts/fireworks/models/minimax-m3",
|
|
2032
2032
|
);
|
|
2033
2033
|
await fw.sendMessage([userMsg("hi")], {
|
|
2034
2034
|
systemPrompt: "system",
|
|
@@ -2040,13 +2040,13 @@ describe("FireworksProvider reasoning_effort ceiling", () => {
|
|
|
2040
2040
|
test("model override picks ceiling from runtime model, not constructor model", async () => {
|
|
2041
2041
|
const fw = new FireworksProvider(
|
|
2042
2042
|
"fw-key",
|
|
2043
|
-
"accounts/fireworks/models/
|
|
2043
|
+
"accounts/fireworks/models/minimax-m3",
|
|
2044
2044
|
);
|
|
2045
2045
|
await fw.sendMessage([userMsg("hi")], {
|
|
2046
2046
|
systemPrompt: "system",
|
|
2047
2047
|
config: {
|
|
2048
2048
|
effort: "max",
|
|
2049
|
-
model: "accounts/fireworks/models/deepseek-
|
|
2049
|
+
model: "accounts/fireworks/models/deepseek-v4p1-flash",
|
|
2050
2050
|
},
|
|
2051
2051
|
});
|
|
2052
2052
|
expect(lastCreateParams!.reasoning_effort).toBe("max");
|
|
@@ -2111,7 +2111,7 @@ describe("FireworksProvider sparse reasoning_effort support (GLM 5.3)", () => {
|
|
|
2111
2111
|
|
|
2112
2112
|
test("models without supportedEfforts are unaffected", async () => {
|
|
2113
2113
|
expect(
|
|
2114
|
-
await send("accounts/fireworks/models/deepseek-
|
|
2114
|
+
await send("accounts/fireworks/models/deepseek-v4p1-flash", "medium"),
|
|
2115
2115
|
).toBe("medium");
|
|
2116
2116
|
});
|
|
2117
2117
|
});
|
|
@@ -10,6 +10,17 @@ import {
|
|
|
10
10
|
} from "../util/pricing.js";
|
|
11
11
|
|
|
12
12
|
describe("resolvePricing", () => {
|
|
13
|
+
test.each([
|
|
14
|
+
["accounts/fireworks/models/glm-5p2", 1.4 + 4.4],
|
|
15
|
+
["accounts/fireworks/models/kimi-k2p6", 0.95 + 4.0],
|
|
16
|
+
["accounts/fireworks/models/deepseek-v4-pro-0813", 1.32 + 3.96],
|
|
17
|
+
["accounts/fireworks/models/deepseek-v4-flash-0731", 0.14 + 0.28],
|
|
18
|
+
])("prices stored usage for retired Fireworks model %s", (model, cost) => {
|
|
19
|
+
const result = resolvePricing("fireworks", model, 1_000_000, 1_000_000);
|
|
20
|
+
expect(result.pricingStatus).toBe("priced");
|
|
21
|
+
expect(result.estimatedCostUsd).toBeCloseTo(cost, 10);
|
|
22
|
+
});
|
|
23
|
+
|
|
13
24
|
describe("Anthropic models", () => {
|
|
14
25
|
test("returns priced for claude-opus-4-6", () => {
|
|
15
26
|
const result = resolvePricing(
|
|
@@ -6,6 +6,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
|
6
6
|
import { setIngressPublicBaseUrl } from "../config/env.js";
|
|
7
7
|
import { IngressConfigSchema } from "../config/schemas/ingress.js";
|
|
8
8
|
import {
|
|
9
|
+
getMcpOAuthClientMetadataUrl,
|
|
9
10
|
getOAuthCallbackUrl,
|
|
10
11
|
getPublicBaseUrl,
|
|
11
12
|
getTelegramWebhookUrl,
|
|
@@ -307,6 +308,31 @@ describe("getOAuthCallbackUrl", () => {
|
|
|
307
308
|
});
|
|
308
309
|
expect(url).toBe("https://example.com/webhooks/oauth/callback");
|
|
309
310
|
});
|
|
311
|
+
|
|
312
|
+
test("canonicalizes the base before building OAuth URLs", () => {
|
|
313
|
+
const config = {
|
|
314
|
+
ingress: {
|
|
315
|
+
publicBaseUrl: "https://EXAMPLE.com:443/a/../assistant-123///",
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
expect(getOAuthCallbackUrl(config)).toBe(
|
|
320
|
+
"https://example.com/assistant-123/webhooks/oauth/callback",
|
|
321
|
+
);
|
|
322
|
+
expect(getMcpOAuthClientMetadataUrl(config)).toBe(
|
|
323
|
+
"https://example.com/assistant-123/oauth/client-metadata.json",
|
|
324
|
+
);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
describe("getMcpOAuthClientMetadataUrl", () => {
|
|
329
|
+
test("builds the public metadata URL", () => {
|
|
330
|
+
expect(
|
|
331
|
+
getMcpOAuthClientMetadataUrl({
|
|
332
|
+
ingress: { publicBaseUrl: "https://example.com/assistant-123/" },
|
|
333
|
+
}),
|
|
334
|
+
).toBe("https://example.com/assistant-123/oauth/client-metadata.json");
|
|
335
|
+
});
|
|
310
336
|
});
|
|
311
337
|
|
|
312
338
|
// ---------------------------------------------------------------------------
|
|
@@ -144,6 +144,53 @@ describe("retry normalization: thinking + forced tool_choice", () => {
|
|
|
144
144
|
expect(lastConfig()?.thinking).toEqual({ type: "adaptive" });
|
|
145
145
|
});
|
|
146
146
|
|
|
147
|
+
for (const [providerName, model] of [
|
|
148
|
+
["anthropic", "claude-sonnet-5-5"],
|
|
149
|
+
["anthropic", "claude-opus-5-5"],
|
|
150
|
+
["openrouter", "anthropic/claude-sonnet-5.5"],
|
|
151
|
+
["vercel-ai-gateway", "anthropic/claude-sonnet-5.5"],
|
|
152
|
+
] as const) {
|
|
153
|
+
test(`downgrades forced tool_choice to auto for ${providerName} ${model}`, async () => {
|
|
154
|
+
// These models always reason and reject forced tool use, so stripping
|
|
155
|
+
// `thinking` is not enough: the forced choice itself has to go.
|
|
156
|
+
setLlmConfig({
|
|
157
|
+
callSites: {
|
|
158
|
+
memoryExtraction: { provider: providerName, model },
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
const { provider, lastConfig } = makePipeline(providerName);
|
|
162
|
+
await provider.sendMessage([userMessage], {
|
|
163
|
+
config: {
|
|
164
|
+
callSite: "memoryExtraction",
|
|
165
|
+
tool_choice: { type: "tool", name: "extract_graph_diff" },
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
expect(lastConfig()?.tool_choice).toEqual({ type: "auto" });
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
test("keeps forced tool_choice for an adaptive-only model off the Anthropic wire", async () => {
|
|
173
|
+
setLlmConfig({
|
|
174
|
+
callSites: {
|
|
175
|
+
memoryExtraction: {
|
|
176
|
+
provider: "fireworks",
|
|
177
|
+
model: "accounts/fireworks/models/glm-5p3",
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
const { provider, lastConfig } = makePipeline("fireworks");
|
|
182
|
+
await provider.sendMessage([userMessage], {
|
|
183
|
+
config: {
|
|
184
|
+
callSite: "memoryExtraction",
|
|
185
|
+
tool_choice: { type: "tool", name: "extract_graph_diff" },
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
expect(lastConfig()?.tool_choice).toEqual({
|
|
189
|
+
type: "tool",
|
|
190
|
+
name: "extract_graph_diff",
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
147
194
|
test("preserves explicit thinking: disabled with forced tool_choice", async () => {
|
|
148
195
|
// Callers like the retriever explicitly set thinking: { type: "disabled" }
|
|
149
196
|
// alongside forced tool_choice. This should pass through unchanged since
|
|
@@ -109,6 +109,37 @@ describe("resolveUsageAttribution", () => {
|
|
|
109
109
|
expectResolvedProviderModelMatchesResolver("mainAgent", "pinned");
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
+
test("reports an override the Auto router chose as the auto source", () => {
|
|
113
|
+
setLlmConfig({
|
|
114
|
+
profiles: {
|
|
115
|
+
active: { provider: "openai", model: "gpt-5.4" },
|
|
116
|
+
routed: { provider: "gemini", model: "gemini-3-pro" },
|
|
117
|
+
},
|
|
118
|
+
activeProfile: "active",
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const snapshot = resolveUsageAttribution({
|
|
122
|
+
callSite: "mainAgent",
|
|
123
|
+
overrideProfile: "routed",
|
|
124
|
+
overrideProfileOrigin: "auto",
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
expect(snapshot).toMatchObject({
|
|
128
|
+
appliedProfile: "routed",
|
|
129
|
+
profileSource: "auto",
|
|
130
|
+
resolvedProvider: "gemini",
|
|
131
|
+
resolvedModel: "gemini-3-pro",
|
|
132
|
+
});
|
|
133
|
+
// The origin only relabels an override that actually won.
|
|
134
|
+
expect(
|
|
135
|
+
resolveUsageAttribution({
|
|
136
|
+
callSite: "mainAgent",
|
|
137
|
+
overrideProfile: "missing",
|
|
138
|
+
overrideProfileOrigin: "auto",
|
|
139
|
+
}).profileSource,
|
|
140
|
+
).toBe("active");
|
|
141
|
+
});
|
|
142
|
+
|
|
112
143
|
test("resolves call-site profile attribution", () => {
|
|
113
144
|
setLlmConfig({
|
|
114
145
|
profiles: {
|
|
@@ -100,7 +100,7 @@ describe("133-collapse-provider-connections migration", () => {
|
|
|
100
100
|
source: "user",
|
|
101
101
|
provider: "fireworks",
|
|
102
102
|
provider_connection: "vellum",
|
|
103
|
-
model: "accounts/fireworks/models/
|
|
103
|
+
model: "accounts/fireworks/models/minimax-m3",
|
|
104
104
|
},
|
|
105
105
|
},
|
|
106
106
|
},
|
|
@@ -257,7 +257,7 @@ describe("133-collapse-provider-connections migration", () => {
|
|
|
257
257
|
encoded: {
|
|
258
258
|
source: "user",
|
|
259
259
|
provider: "vellum",
|
|
260
|
-
model: "fireworks/accounts/fireworks/models/
|
|
260
|
+
model: "fireworks/accounts/fireworks/models/minimax-m3",
|
|
261
261
|
},
|
|
262
262
|
},
|
|
263
263
|
},
|
|
@@ -272,7 +272,7 @@ describe("133-collapse-provider-connections migration", () => {
|
|
|
272
272
|
expect(llm.profiles.encoded).toEqual({
|
|
273
273
|
source: "user",
|
|
274
274
|
provider: "vellum",
|
|
275
|
-
model: "accounts/fireworks/models/
|
|
275
|
+
model: "accounts/fireworks/models/minimax-m3",
|
|
276
276
|
});
|
|
277
277
|
});
|
|
278
278
|
|