@vellumai/assistant 0.12.5-dev.202609281620.da5cb5b → 0.12.5-dev.202609281822.fb70dee
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/openapi.yaml +10 -4
- package/package.json +1 -1
- 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-pairing.test.ts +112 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +159 -0
- package/src/__tests__/llm-catalog-parity.test.ts +4 -4
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/openai-provider.test.ts +11 -11
- package/src/__tests__/pricing.test.ts +11 -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/config/default-profile-catalog.ts +1 -1
- package/src/notifications/README.md +41 -3
- package/src/notifications/__tests__/assistant-initiated-thread.test.ts +254 -0
- package/src/notifications/__tests__/broadcaster.test.ts +299 -4
- 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/assistant-initiated-thread.ts +101 -0
- package/src/notifications/broadcaster.ts +71 -12
- package/src/notifications/completion-policy.ts +7 -1
- package/src/notifications/conversation-pairing.ts +15 -70
- package/src/notifications/emit-signal.ts +34 -3
- package/src/persistence/conversation-queries.ts +15 -8
- package/src/plugin-api/vision-support.test.ts +21 -21
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +1 -1
- package/src/providers/model-catalog.ts +47 -84
- package/src/providers/model-intents.ts +4 -4
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +36 -0
- 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/conversation-list-routes.ts +10 -2
- package/src/runtime/routes/user-route-dispatcher.ts +5 -1
- package/src/util/pricing.ts +25 -0
- package/src/workspace/byok-default-profile-ensure.ts +11 -0
- 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
package/openapi.yaml
CHANGED
|
@@ -8042,8 +8042,9 @@ paths:
|
|
|
8042
8042
|
Filter by conversation type. Pass "background" to list background and scheduled conversations together (the
|
|
8043
8043
|
back-compat umbrella), "scheduled" to list only scheduled conversations, or "all" for the union of the
|
|
8044
8044
|
standard listing and that umbrella, so one paginated cursor spans every type. Combine "all" with
|
|
8045
|
-
archiveStatus=all for a whole-history read; rows are
|
|
8046
|
-
descending) like every other list read, and pinned rows are never
|
|
8045
|
+
archiveStatus=all for a whole-history read; rows are ordered by last activity (the later of the last message
|
|
8046
|
+
and the time the row was marked done, descending) like every other list read, and pinned rows are never
|
|
8047
|
+
appended to it.
|
|
8047
8048
|
- name: archiveStatus
|
|
8048
8049
|
in: query
|
|
8049
8050
|
required: false
|
|
@@ -8083,8 +8084,9 @@ paths:
|
|
|
8083
8084
|
description:
|
|
8084
8085
|
Filter to a single group, so each sidebar section can load independently of the paginated list. Pass
|
|
8085
8086
|
"system:all" for conversations in no group, "system:pinned" for the Pinned section, or a custom group id. A
|
|
8086
|
-
group-scoped request is
|
|
8087
|
-
descending) and never has pinned rows appended to it. Omit to span every
|
|
8087
|
+
group-scoped request is ordered by last activity like every list read (the later of the last message and the
|
|
8088
|
+
time the row was marked done, descending) and never has pinned rows appended to it. Omit to span every
|
|
8089
|
+
group.
|
|
8088
8090
|
- name: needsAttention
|
|
8089
8091
|
in: query
|
|
8090
8092
|
required: false
|
|
@@ -8340,10 +8342,14 @@ paths:
|
|
|
8340
8342
|
- sortPosition
|
|
8341
8343
|
- isSystemGroup
|
|
8342
8344
|
additionalProperties: false
|
|
8345
|
+
orderedBy:
|
|
8346
|
+
type: string
|
|
8347
|
+
const: lastActivity
|
|
8343
8348
|
required:
|
|
8344
8349
|
- conversations
|
|
8345
8350
|
- nextOffset
|
|
8346
8351
|
- hasMore
|
|
8352
|
+
- orderedBy
|
|
8347
8353
|
additionalProperties: false
|
|
8348
8354
|
post:
|
|
8349
8355
|
operationId: conversations_post
|
package/package.json
CHANGED
|
@@ -302,6 +302,13 @@ describe("ensureByokDefaultProfiles", () => {
|
|
|
302
302
|
"cost-optimized",
|
|
303
303
|
"accounts/fireworks/models/deepseek-v4-flash",
|
|
304
304
|
],
|
|
305
|
+
[
|
|
306
|
+
"fireworks",
|
|
307
|
+
"cost-optimized",
|
|
308
|
+
"accounts/fireworks/models/deepseek-v4-flash-0731",
|
|
309
|
+
],
|
|
310
|
+
["fireworks", "balanced", "accounts/fireworks/models/deepseek-v4p1-flash"],
|
|
311
|
+
["fireworks", "quality-optimized", "accounts/fireworks/models/kimi-k2p6"],
|
|
305
312
|
] as const)(
|
|
306
313
|
"a historical intent-era copy converts (%s %s pinned to %s)",
|
|
307
314
|
(provider, key, model) => {
|
|
@@ -171,7 +171,7 @@ describe("config-validation-reset notice sentinel", () => {
|
|
|
171
171
|
profiles: {
|
|
172
172
|
"glm-default": {
|
|
173
173
|
provider: "vellum",
|
|
174
|
-
model: "accounts/fireworks/models/glm-
|
|
174
|
+
model: "accounts/fireworks/models/glm-5p3",
|
|
175
175
|
},
|
|
176
176
|
},
|
|
177
177
|
activeProfile: "glm-default",
|
|
@@ -193,7 +193,7 @@ describe("config-validation-reset notice sentinel", () => {
|
|
|
193
193
|
expect(config.llm.activeProfile).toBe("glm-default");
|
|
194
194
|
expect(config.llm.callSites.mainAgent?.profile).toBe("glm-default");
|
|
195
195
|
expect(config.llm.profiles["glm-default"]?.model).toBe(
|
|
196
|
-
"accounts/fireworks/models/glm-
|
|
196
|
+
"accounts/fireworks/models/glm-5p3",
|
|
197
197
|
);
|
|
198
198
|
});
|
|
199
199
|
|
|
@@ -116,6 +116,7 @@ mock.module("../config/assistant-initiated-threads-gate.js", () => ({
|
|
|
116
116
|
isAssistantInitiatedThreadsEnabled: () => assistantInitiatedThreadsEnabled,
|
|
117
117
|
}));
|
|
118
118
|
|
|
119
|
+
import { resolveAssistantInitiatedThread } from "../notifications/assistant-initiated-thread.js";
|
|
119
120
|
import { pairDeliveryWithConversation } from "../notifications/conversation-pairing.js";
|
|
120
121
|
import type { NotificationSignal } from "../notifications/signal.js";
|
|
121
122
|
import type {
|
|
@@ -1478,6 +1479,117 @@ describe("pairDeliveryWithConversation", () => {
|
|
|
1478
1479
|
...overrides,
|
|
1479
1480
|
});
|
|
1480
1481
|
|
|
1482
|
+
test("a prepared resolution is reused even if the source changes before pairing", async () => {
|
|
1483
|
+
assistantInitiatedThreadsEnabled = true;
|
|
1484
|
+
const signal = share({
|
|
1485
|
+
conversationMetadata: { groupId: "group-123" },
|
|
1486
|
+
});
|
|
1487
|
+
const original = structuredClone(signal);
|
|
1488
|
+
const assistantInitiatedThread = resolveAssistantInitiatedThread(signal);
|
|
1489
|
+
getConversationMock.mockClear();
|
|
1490
|
+
mockExistingConversations[signal.sourceContextId] = {
|
|
1491
|
+
id: signal.sourceContextId,
|
|
1492
|
+
source: "user",
|
|
1493
|
+
title: null,
|
|
1494
|
+
conversationType: "standard",
|
|
1495
|
+
};
|
|
1496
|
+
|
|
1497
|
+
const result = await pairDeliveryWithConversation(
|
|
1498
|
+
signal,
|
|
1499
|
+
"vellum",
|
|
1500
|
+
makeCopy(),
|
|
1501
|
+
{ assistantInitiatedThread },
|
|
1502
|
+
);
|
|
1503
|
+
|
|
1504
|
+
expect(result.createdNewConversation).toBe(true);
|
|
1505
|
+
expect(result.messageId).toBe("msg-001");
|
|
1506
|
+
expect(createConversationMock).toHaveBeenCalledWith(
|
|
1507
|
+
expect.objectContaining({
|
|
1508
|
+
source: "assistant_initiated",
|
|
1509
|
+
groupId: "group-123",
|
|
1510
|
+
}),
|
|
1511
|
+
);
|
|
1512
|
+
expect(getConversationMock).not.toHaveBeenCalled();
|
|
1513
|
+
expect(signal).toEqual(original);
|
|
1514
|
+
});
|
|
1515
|
+
|
|
1516
|
+
test("an ineligible prepared resolution retains passive pairing when the flag changes", async () => {
|
|
1517
|
+
const signal = share();
|
|
1518
|
+
const assistantInitiatedThread = resolveAssistantInitiatedThread(signal);
|
|
1519
|
+
assistantInitiatedThreadsEnabled = true;
|
|
1520
|
+
mockExistingConversations[signal.sourceContextId] = {
|
|
1521
|
+
id: signal.sourceContextId,
|
|
1522
|
+
source: "heartbeat",
|
|
1523
|
+
title: null,
|
|
1524
|
+
conversationType: "background",
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1527
|
+
const result = await pairDeliveryWithConversation(
|
|
1528
|
+
signal,
|
|
1529
|
+
"vellum",
|
|
1530
|
+
makeCopy(),
|
|
1531
|
+
{ assistantInitiatedThread },
|
|
1532
|
+
);
|
|
1533
|
+
|
|
1534
|
+
expect(result.createdNewConversation).toBe(false);
|
|
1535
|
+
expect(result.conversationId).toBe(signal.sourceContextId);
|
|
1536
|
+
expect(createConversationMock).not.toHaveBeenCalled();
|
|
1537
|
+
expect(addMessageMock).toHaveBeenCalledTimes(1);
|
|
1538
|
+
});
|
|
1539
|
+
|
|
1540
|
+
test.each(["slack", "telegram", "discord"] as const)(
|
|
1541
|
+
"%s retains the producer metadata despite a prepared vellum resolution",
|
|
1542
|
+
async (channel) => {
|
|
1543
|
+
assistantInitiatedThreadsEnabled = true;
|
|
1544
|
+
const signal = share({
|
|
1545
|
+
conversationMetadata: { groupId: "group-123" },
|
|
1546
|
+
});
|
|
1547
|
+
const original = structuredClone(signal);
|
|
1548
|
+
const assistantInitiatedThread =
|
|
1549
|
+
resolveAssistantInitiatedThread(signal);
|
|
1550
|
+
getConversationMock.mockClear();
|
|
1551
|
+
|
|
1552
|
+
const result = await pairDeliveryWithConversation(
|
|
1553
|
+
signal,
|
|
1554
|
+
channel,
|
|
1555
|
+
makeCopy(),
|
|
1556
|
+
{ assistantInitiatedThread },
|
|
1557
|
+
);
|
|
1558
|
+
|
|
1559
|
+
expect(result.createdNewConversation).toBe(true);
|
|
1560
|
+
expect(result.strategy).toBe("continue_existing_conversation");
|
|
1561
|
+
expect(createConversationMock).toHaveBeenCalledWith(
|
|
1562
|
+
expect.objectContaining({
|
|
1563
|
+
conversationType: "background",
|
|
1564
|
+
source: "notification",
|
|
1565
|
+
groupId: "group-123",
|
|
1566
|
+
}),
|
|
1567
|
+
);
|
|
1568
|
+
expect(addMessageMock).not.toHaveBeenCalled();
|
|
1569
|
+
expect(getConversationMock).not.toHaveBeenCalled();
|
|
1570
|
+
expect(signal).toEqual(original);
|
|
1571
|
+
},
|
|
1572
|
+
);
|
|
1573
|
+
|
|
1574
|
+
test("platform delivery does not pair a prepared vellum resolution", async () => {
|
|
1575
|
+
assistantInitiatedThreadsEnabled = true;
|
|
1576
|
+
const signal = share();
|
|
1577
|
+
const assistantInitiatedThread = resolveAssistantInitiatedThread(signal);
|
|
1578
|
+
|
|
1579
|
+
const result = await pairDeliveryWithConversation(
|
|
1580
|
+
signal,
|
|
1581
|
+
"platform",
|
|
1582
|
+
makeCopy(),
|
|
1583
|
+
{ assistantInitiatedThread },
|
|
1584
|
+
);
|
|
1585
|
+
|
|
1586
|
+
expect(result.strategy).toBe("push_only");
|
|
1587
|
+
expect(result.createdNewConversation).toBe(false);
|
|
1588
|
+
expect(result.conversationId).toBeNull();
|
|
1589
|
+
expect(createConversationMock).not.toHaveBeenCalled();
|
|
1590
|
+
expect(addMessageMock).not.toHaveBeenCalled();
|
|
1591
|
+
});
|
|
1592
|
+
|
|
1481
1593
|
test("flag on: a share from a background run materializes a section thread", async () => {
|
|
1482
1594
|
assistantInitiatedThreadsEnabled = true;
|
|
1483
1595
|
mockExistingConversations["conv-heartbeat"] = {
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import { saveRawConfig } from "../config/loader.js";
|
|
4
|
+
import type { NotificationSignal } from "../notifications/signal.js";
|
|
4
5
|
import type { NotificationChannel } from "../notifications/types.js";
|
|
5
6
|
|
|
7
|
+
let assistantInitiatedCandidate = false;
|
|
8
|
+
const resolveAssistantInitiatedThreadMock = mock(
|
|
9
|
+
(signal: NotificationSignal) => ({
|
|
10
|
+
isCandidate: assistantInitiatedCandidate,
|
|
11
|
+
vellumSignal: assistantInitiatedCandidate
|
|
12
|
+
? {
|
|
13
|
+
...signal,
|
|
14
|
+
requiresConversation: true,
|
|
15
|
+
conversationMetadata: { source: "assistant_initiated" },
|
|
16
|
+
}
|
|
17
|
+
: signal,
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
20
|
+
mock.module("../notifications/assistant-initiated-thread.js", () => ({
|
|
21
|
+
resolveAssistantInitiatedThread: resolveAssistantInitiatedThreadMock,
|
|
22
|
+
}));
|
|
23
|
+
|
|
6
24
|
const evaluateSignalMock = mock();
|
|
7
25
|
const enforceRoutingIntentMock = mock();
|
|
8
26
|
const updateDecisionMock = mock();
|
|
@@ -113,6 +131,8 @@ import {
|
|
|
113
131
|
|
|
114
132
|
beforeEach(() => {
|
|
115
133
|
saveRawConfig({});
|
|
134
|
+
assistantInitiatedCandidate = false;
|
|
135
|
+
resolveAssistantInitiatedThreadMock.mockClear();
|
|
116
136
|
writeHomeFeedItemForSignalMock.mockClear();
|
|
117
137
|
evaluateSignalMock.mockReset();
|
|
118
138
|
enforceRoutingIntentMock.mockReset();
|
|
@@ -1020,3 +1040,142 @@ describe("classifyNotificationReceipt", () => {
|
|
|
1020
1040
|
).toBe("unknown");
|
|
1021
1041
|
});
|
|
1022
1042
|
});
|
|
1043
|
+
|
|
1044
|
+
describe("emitNotificationSignal From me push defaults", () => {
|
|
1045
|
+
const params = {
|
|
1046
|
+
sourceEventName: "assistant.share",
|
|
1047
|
+
sourceChannel: "assistant_tool" as const,
|
|
1048
|
+
sourceContextId: "conv-background",
|
|
1049
|
+
attentionHints: {
|
|
1050
|
+
urgency: "low" as const,
|
|
1051
|
+
requiresAction: false,
|
|
1052
|
+
isAsyncBackground: true,
|
|
1053
|
+
visibleInSourceNow: false,
|
|
1054
|
+
},
|
|
1055
|
+
};
|
|
1056
|
+
const decision = (selectedChannels: NotificationChannel[] = ["vellum"]) => ({
|
|
1057
|
+
shouldNotify: true,
|
|
1058
|
+
selectedChannels,
|
|
1059
|
+
reasoningSummary: "Assistant-authored share",
|
|
1060
|
+
renderedCopy: { vellum: { title: "An update", body: "A useful result." } },
|
|
1061
|
+
dedupeKey: "share-1",
|
|
1062
|
+
confidence: 1,
|
|
1063
|
+
fallbackUsed: false,
|
|
1064
|
+
persistedDecisionId: "decision-share",
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
beforeEach(() => {
|
|
1068
|
+
assistantInitiatedCandidate = true;
|
|
1069
|
+
evaluateSignalMock.mockResolvedValue(decision());
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
test("adds configured platform after routing and persists the final decision", async () => {
|
|
1073
|
+
const result = await emitNotificationSignal(params);
|
|
1074
|
+
expect(result.selectedChannels).toEqual(["vellum", "platform"]);
|
|
1075
|
+
expect(resolveAssistantInitiatedThreadMock).toHaveBeenCalledTimes(1);
|
|
1076
|
+
expect(updateDecisionMock).toHaveBeenCalledWith(
|
|
1077
|
+
"decision-share",
|
|
1078
|
+
expect.objectContaining({
|
|
1079
|
+
selectedChannels: ["vellum", "platform"],
|
|
1080
|
+
}),
|
|
1081
|
+
);
|
|
1082
|
+
expect(dispatchDecisionMock.mock.calls[0]?.[0]).toMatchObject({
|
|
1083
|
+
attentionHints: { urgency: "low" },
|
|
1084
|
+
});
|
|
1085
|
+
expect(dispatchDecisionMock.mock.calls[0]?.[3]).toMatchObject({
|
|
1086
|
+
assistantInitiatedThread: {
|
|
1087
|
+
platformAdded: true,
|
|
1088
|
+
resolution: {
|
|
1089
|
+
isCandidate: true,
|
|
1090
|
+
vellumSignal: {
|
|
1091
|
+
requiresConversation: true,
|
|
1092
|
+
conversationMetadata: { source: "assistant_initiated" },
|
|
1093
|
+
},
|
|
1094
|
+
},
|
|
1095
|
+
},
|
|
1096
|
+
});
|
|
1097
|
+
});
|
|
1098
|
+
|
|
1099
|
+
test.each([
|
|
1100
|
+
"quiet",
|
|
1101
|
+
"unconfigured",
|
|
1102
|
+
"noncandidate",
|
|
1103
|
+
"suppressed",
|
|
1104
|
+
"single_channel",
|
|
1105
|
+
"external_only",
|
|
1106
|
+
"vellum_allowlist",
|
|
1107
|
+
])("respects %s policy without adding platform", async (scenario) => {
|
|
1108
|
+
assistantInitiatedCandidate = scenario !== "noncandidate";
|
|
1109
|
+
isPlatformClientConfiguredMock.mockResolvedValue(
|
|
1110
|
+
scenario !== "unconfigured",
|
|
1111
|
+
);
|
|
1112
|
+
evaluateSignalMock.mockResolvedValue({
|
|
1113
|
+
...decision(scenario === "external_only" ? ["telegram"] : ["vellum"]),
|
|
1114
|
+
shouldNotify: scenario !== "suppressed",
|
|
1115
|
+
});
|
|
1116
|
+
const result = await emitNotificationSignal({
|
|
1117
|
+
...params,
|
|
1118
|
+
routingIntent:
|
|
1119
|
+
scenario === "single_channel" ? "single_channel" : undefined,
|
|
1120
|
+
contextPayload: {
|
|
1121
|
+
quiet: scenario === "quiet",
|
|
1122
|
+
...(scenario === "vellum_allowlist"
|
|
1123
|
+
? { channelAllowlist: ["vellum"] }
|
|
1124
|
+
: {}),
|
|
1125
|
+
},
|
|
1126
|
+
});
|
|
1127
|
+
expect(result.selectedChannels).not.toContain("platform");
|
|
1128
|
+
expect(dispatchDecisionMock.mock.calls[0]?.[3]).toMatchObject({
|
|
1129
|
+
assistantInitiatedThread: { platformAdded: false },
|
|
1130
|
+
});
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
test("keeps existing platform and external selections independent of this feature", async () => {
|
|
1134
|
+
evaluateSignalMock.mockResolvedValue(
|
|
1135
|
+
decision(["vellum", "platform", "telegram"]),
|
|
1136
|
+
);
|
|
1137
|
+
const result = await emitNotificationSignal({
|
|
1138
|
+
...params,
|
|
1139
|
+
contextPayload: { quiet: true },
|
|
1140
|
+
});
|
|
1141
|
+
expect(result.selectedChannels).toEqual(["vellum", "platform", "telegram"]);
|
|
1142
|
+
expect(isPlatformClientConfiguredMock).not.toHaveBeenCalled();
|
|
1143
|
+
expect(dispatchDecisionMock.mock.calls[0]?.[3]).toMatchObject({
|
|
1144
|
+
assistantInitiatedThread: { platformAdded: false },
|
|
1145
|
+
});
|
|
1146
|
+
});
|
|
1147
|
+
|
|
1148
|
+
test("probes an unbound platform once across urgency and From me policy", async () => {
|
|
1149
|
+
isPlatformClientConfiguredMock.mockResolvedValue(false);
|
|
1150
|
+
const result = await emitNotificationSignal({
|
|
1151
|
+
...params,
|
|
1152
|
+
attentionHints: { ...params.attentionHints, urgency: "high" },
|
|
1153
|
+
});
|
|
1154
|
+
expect(result.selectedChannels).toEqual(["vellum"]);
|
|
1155
|
+
expect(isPlatformClientConfiguredMock).toHaveBeenCalledTimes(1);
|
|
1156
|
+
});
|
|
1157
|
+
|
|
1158
|
+
test("preserves preferred external selections while adding the platform default", async () => {
|
|
1159
|
+
evaluateSignalMock.mockResolvedValue(decision(["vellum", "telegram"]));
|
|
1160
|
+
const result = await emitNotificationSignal(params);
|
|
1161
|
+
expect(result.selectedChannels).toEqual(["vellum", "telegram", "platform"]);
|
|
1162
|
+
});
|
|
1163
|
+
|
|
1164
|
+
test.each(["deduplicated", "source_active"])(
|
|
1165
|
+
"does not resolve candidates for %s signals",
|
|
1166
|
+
async (scenario) => {
|
|
1167
|
+
if (scenario === "deduplicated") {
|
|
1168
|
+
createEventMock.mockReturnValue(null);
|
|
1169
|
+
}
|
|
1170
|
+
await emitNotificationSignal({
|
|
1171
|
+
...params,
|
|
1172
|
+
attentionHints: {
|
|
1173
|
+
...params.attentionHints,
|
|
1174
|
+
visibleInSourceNow: scenario === "source_active",
|
|
1175
|
+
},
|
|
1176
|
+
});
|
|
1177
|
+
expect(resolveAssistantInitiatedThreadMock).not.toHaveBeenCalled();
|
|
1178
|
+
expect(dispatchDecisionMock).not.toHaveBeenCalled();
|
|
1179
|
+
},
|
|
1180
|
+
);
|
|
1181
|
+
});
|
|
@@ -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,
|
|
@@ -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(
|
|
@@ -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
|
|