Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assistant/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2094,7 +2094,7 @@ Connected channels are resolved at signal emission time: vellum is always includ

**Audit trail (SQLite):** `notification_events` → `notification_decisions` (with `conversationActions` in validation results) → `notification_deliveries` (with `conversation_id`, `message_id`, `conversation_strategy`, `conversation_action`, `conversation_target_id`, `conversation_fallback_used`)

**Configuration:** `notifications.decisionModelIntent` in `config.json`.
**Configuration:** `llm.callSites.notificationDecision` (decision engine) and `llm.callSites.preferenceExtraction` (preference extractor) in `config.json`. Both fall back to `llm.default` when unset.

---

Expand Down
3 changes: 1 addition & 2 deletions assistant/src/__tests__/call-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ mock.module("../config/loader.js", () => {
silenceTimeoutSeconds: 30,
disclosure: { enabled: false, text: "" },
safety: { denyCategories: [] },
model: undefined,
},
memory: { enabled: false },
notifications: { decisionModelIntent: "latency-optimized" },
notifications: {},
services: {
tts: {
mode: "your-own" as const,
Expand Down
11 changes: 7 additions & 4 deletions assistant/src/__tests__/conversation-process-callsite.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/**
* Verify that `callSite` threads from `Conversation.processMessage` options
* all the way down to the per-call provider config, and that user-initiated
* turns default to `'mainAgent'` when no caller-supplied `callSite` is set.
* Verifies that `callSite` threads from `Conversation.processMessage`
* options all the way down to the per-call provider config, and that
* user-initiated turns default to `'mainAgent'` when no caller-supplied
* `callSite` is set.
*
* The test mocks `AgentLoop.run()` so it can capture the `callSite` parameter
* the conversation passes after `processMessage` runs the slash-resolver and
* runtime-injection pipeline.
* runtime-injection pipeline. Adapter callers (heartbeat, filing, scheduler)
* pass an explicit `callSite` so `RetryProvider` resolves their per-call
* config from `llm.callSites.<id>`.
*/
import { describe, expect, mock, test } from "bun:test";

Expand Down
17 changes: 8 additions & 9 deletions assistant/src/__tests__/heartbeat-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ let mockConfig = {
heartbeat: {
enabled: true,
intervalMs: 60_000,
speed: "standard" as "standard" | "fast",
activeHoursStart: undefined as number | undefined,
activeHoursEnd: undefined as number | undefined,
},
Expand Down Expand Up @@ -185,7 +184,6 @@ describe("HeartbeatService", () => {
heartbeat: {
enabled: true,
intervalMs: 60_000,
speed: "standard",
activeHoursStart: undefined,
activeHoursEnd: undefined,
},
Expand Down Expand Up @@ -547,17 +545,18 @@ describe("HeartbeatService", () => {
});
});

test("callSite is passed regardless of legacy heartbeat.speed value", async () => {
// The legacy `heartbeat.speed` field is no longer read by the heartbeat
// service — every run unconditionally passes `callSite: 'heartbeatAgent'`
// and the resolver maps that to whatever `llm.callSites.heartbeatAgent`
// (or the default) configures. PR 19 will remove the schema field.
mockConfig.heartbeat.speed = "fast";
test("processMessage receives only callSite — no legacy speed knob", async () => {
// The heartbeat service unconditionally passes `callSite:
// 'heartbeatAgent'` and nothing else. The resolver maps that identifier
// to whatever `llm.callSites.heartbeatAgent` (or `llm.default`)
// configures.
const service = createService();
await service.runOnce();

expect(processMessageCalls).toHaveLength(1);
expect(processMessageCalls[0].options?.callSite).toBe("heartbeatAgent");
expect(processMessageCalls[0].options).toEqual({
callSite: "heartbeatAgent",
});
});

test("end-to-end: llm.callSites.heartbeatAgent.speed resolves to 'fast'", async () => {
Expand Down
12 changes: 7 additions & 5 deletions assistant/src/__tests__/model-intents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ describe("model intents", () => {
});
});

// `RetryProvider`'s legacy `modelIntent` normalization path was removed in
// PR 19 of the unify-llm-callsites plan. The remaining `resolveModelIntent`
// helper lives in `providers/model-intents.ts` for use by the workspace
// migration's snapshot table — see `workspace/migrations/038-unify-llm-
// callsite-configs.ts`.
// `RetryProvider` normalizes outbound calls through call-site routing
// (`resolveCallSiteConfig` against `llm.callSites.<id>` / `llm.default`).
// The `resolveModelIntent` helper exercised above lives in
// `providers/model-intents.ts` and is used by the unify-llm workspace
// migration's snapshot table (see
// `workspace/migrations/038-unify-llm-callsite-configs.ts`) to seed
// `llm.default` from any pre-existing `modelIntent` setting.
Loading
Loading