diff --git a/assistant/src/config/schemas/llm.ts b/assistant/src/config/schemas/llm.ts index 4c4800be790..8cfaab22f1a 100644 --- a/assistant/src/config/schemas/llm.ts +++ b/assistant/src/config/schemas/llm.ts @@ -65,6 +65,8 @@ export const LLMCallSiteEnum = z.enum([ "styleAnalyzer", "inviteInstructionGenerator", "skillCategoryInference", + "meetConsentMonitor", + "meetChatOpportunity", ]); export type LLMCallSite = z.infer; diff --git a/clients/macos/vellum-assistant/Features/Settings/CallSiteOverride.swift b/clients/macos/vellum-assistant/Features/Settings/CallSiteOverride.swift index 7fc7543e16e..ce832fb1af7 100644 --- a/clients/macos/vellum-assistant/Features/Settings/CallSiteOverride.swift +++ b/clients/macos/vellum-assistant/Features/Settings/CallSiteOverride.swift @@ -14,6 +14,7 @@ public enum CallSiteDomain: String, CaseIterable, Identifiable, Hashable { case notifications case voice case utility + case skills public var id: String { rawValue } @@ -28,6 +29,7 @@ public enum CallSiteDomain: String, CaseIterable, Identifiable, Hashable { case .notifications: return "Notifications" case .voice: return "Voice" case .utility: return "Utility" + case .skills: return "Skills" } } @@ -42,6 +44,7 @@ public enum CallSiteDomain: String, CaseIterable, Identifiable, Hashable { case .notifications: return 4 case .voice: return 5 case .utility: return 6 + case .skills: return 7 } } } @@ -140,6 +143,9 @@ public enum CallSiteCatalog { CallSiteOverride(id: "styleAnalyzer", displayName: "Style analyzer", domain: .utility), CallSiteOverride(id: "inviteInstructionGenerator", displayName: "Invite instruction generator", domain: .utility), CallSiteOverride(id: "skillCategoryInference", displayName: "Skill category inference", domain: .utility), + // Skills + CallSiteOverride(id: "meetConsentMonitor", displayName: "Meet · Consent monitor", domain: .skills), + CallSiteOverride(id: "meetChatOpportunity", displayName: "Meet · Chat opportunity", domain: .skills), ] /// Lookup table from call-site ID to its catalog entry. Constructed diff --git a/skills/meet-join/daemon/consent-monitor.ts b/skills/meet-join/daemon/consent-monitor.ts index 5689aba690b..4da97335ab9 100644 --- a/skills/meet-join/daemon/consent-monitor.ts +++ b/skills/meet-join/daemon/consent-monitor.ts @@ -127,8 +127,9 @@ export interface MeetConsentMonitorDeps { config: MeetConsentMonitorConfig; /** * Ask the LLM for an objection verdict. Defaults to a wrapper around the - * repo-wide provider abstraction using {@link CONSENT_LLM_MAX_TOKENS} and - * `modelIntent: "latency-optimized"`. Tests inject scripted responses. + * repo-wide provider abstraction using {@link CONSENT_LLM_MAX_TOKENS} + * under the `meetConsentMonitor` call site. Tests inject scripted + * responses. */ llmAsk?: ObjectionLLMAsk; /** Override the dispatcher subscribe (tests). */ @@ -693,7 +694,7 @@ const OBJECTION_TOOL: ToolDefinition = { /** * Default {@link ObjectionLLMAsk} — routes through the repo-wide provider - * abstraction with `modelIntent: "latency-optimized"`, times out at + * abstraction under the `meetConsentMonitor` call site, times out at * {@link CONSENT_LLM_TIMEOUT_MS}, and extracts the tool-use input as the * structured verdict. * @@ -701,7 +702,8 @@ const OBJECTION_TOOL: ToolDefinition = { * real provider. */ async function defaultLLMAsk(prompt: string): Promise { - const provider: Provider | null = await getConfiguredProvider(); + const provider: Provider | null = + await getConfiguredProvider("meetConsentMonitor"); if (!provider) { // No provider available — conservatively assume no objection so the // monitor doesn't interrupt a meeting based on missing infra. @@ -716,7 +718,7 @@ async function defaultLLMAsk(prompt: string): Promise { "You are a strict JSON classifier. Only respond via the report_objection tool.", { config: { - modelIntent: "latency-optimized", + callSite: "meetConsentMonitor", max_tokens: CONSENT_LLM_MAX_TOKENS, tool_choice: { type: "tool" as const, name: OBJECTION_TOOL.name }, }, diff --git a/skills/meet-join/daemon/session-manager.ts b/skills/meet-join/daemon/session-manager.ts index 3cc831558a8..07b47b779ba 100644 --- a/skills/meet-join/daemon/session-manager.ts +++ b/skills/meet-join/daemon/session-manager.ts @@ -505,9 +505,9 @@ export interface MeetSessionManagerDeps { /** * Override the chat-opportunity-detector factory. Default constructs a * {@link MeetChatOpportunityDetector} with a Tier 2 LLM callback that - * routes through the repo-wide provider abstraction at - * `modelIntent: "latency-optimized"`. Tests can inject a fake to - * observe start/dispose/stats without spinning up the LLM path. + * routes through the repo-wide provider abstraction under the + * `meetChatOpportunity` call site. Tests can inject a fake to observe + * start/dispose/stats without spinning up the LLM path. * * Only consulted when `services.meet.proactiveChat.enabled === true`. */ @@ -1689,10 +1689,9 @@ const CHAT_OPPORTUNITY_TOOL: ToolDefinition = { /** * Default Tier 2 chat-opportunity LLM callback. Routes through the - * repo-wide provider abstraction at - * `modelIntent: "latency-optimized"` — keeping the proactive-chat path - * on the same latency tier the consent monitor uses so both background - * loops share tuning. Times out at + * repo-wide provider abstraction under the `meetChatOpportunity` call + * site, keeping the proactive-chat path on its own configurable lane + * alongside the consent monitor. Times out at * {@link CHAT_OPPORTUNITY_LLM_TIMEOUT_MS} and extracts the tool-use * input as the structured verdict. * @@ -1703,7 +1702,8 @@ const CHAT_OPPORTUNITY_TOOL: ToolDefinition = { async function defaultCallDetectorLLM( prompt: string, ): Promise { - const provider: Provider | null = await getConfiguredProvider(); + const provider: Provider | null = + await getConfiguredProvider("meetChatOpportunity"); if (!provider) { return { shouldRespond: false, reason: "" }; } @@ -1716,7 +1716,7 @@ async function defaultCallDetectorLLM( "You are a strict JSON classifier. Only respond via the report_chat_opportunity tool.", { config: { - modelIntent: "latency-optimized", + callSite: "meetChatOpportunity", max_tokens: CHAT_OPPORTUNITY_LLM_MAX_TOKENS, tool_choice: { type: "tool" as const,