diff --git a/packages/server/src/server/agent/agent-sdk-types.ts b/packages/server/src/server/agent/agent-sdk-types.ts index 64e5b11eca..d42d98aaf7 100644 --- a/packages/server/src/server/agent/agent-sdk-types.ts +++ b/packages/server/src/server/agent/agent-sdk-types.ts @@ -660,6 +660,11 @@ export interface AgentPermissionResult { followUpPrompt?: AgentPromptInput; } +export interface UsageReference { + source: string; + input: JsonValue; +} + export interface AgentSession { readonly provider: AgentProvider; readonly id: string | null; @@ -669,7 +674,7 @@ export interface AgentSession { * replay them at their original timestamps; restored sessions omit old rows. */ readonly initialTimeline?: ImportedTimelineEntry[]; /** Resolved at fetch time because model and credentials may change during a session. */ - getUsageReference?(): Promise<{ source: string; input: JsonValue } | null>; + getUsageReference?(): Promise; run(prompt: AgentPromptInput, options?: AgentRunOptions): Promise; startTurn(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<{ turnId: string }>; steerActiveTurn?(prompt: AgentPromptInput, options: SteerActiveTurnOptions): Promise; diff --git a/packages/server/src/server/agent/plugin-provider.ts b/packages/server/src/server/agent/plugin-provider.ts index bd5a7d9986..2ebeb3c797 100644 --- a/packages/server/src/server/agent/plugin-provider.ts +++ b/packages/server/src/server/agent/plugin-provider.ts @@ -51,6 +51,7 @@ import type { ProviderRefreshContext, SteerActiveTurnOptions, SteerResult, + UsageReference, } from "./agent-sdk-types.js"; import { isDefaultAgentCreateConfigUnattended, @@ -567,7 +568,7 @@ class ProviderRuntimeSession { return this.capabilities; } - async getUsageReference(): Promise<{ source: string; input: JsonValue } | null> { + async getUsageReference(): Promise { if (!this.capabilities.includes("session.usage_reference")) return null; const event = await this.runtime.complete({ type: "session.usage_reference", @@ -1087,7 +1088,7 @@ class PluginAgentSession implements AgentSession { return agentCapabilities(this.bridge.negotiatedCapabilities); } - getUsageReference(): Promise<{ source: string; input: JsonValue } | null> { + getUsageReference(): Promise { return this.bridge.getUsageReference(); } diff --git a/packages/server/src/server/agent/providers/opencode-agent.ts b/packages/server/src/server/agent/providers/opencode-agent.ts index 0de0d4cd33..e3100025a5 100644 --- a/packages/server/src/server/agent/providers/opencode-agent.ts +++ b/packages/server/src/server/agent/providers/opencode-agent.ts @@ -58,6 +58,7 @@ import { type SteerResult, type ToolCallDetail, type ToolCallTimelineItem, + type UsageReference, } from "../agent-sdk-types.js"; import { importSessionFromPersistence } from "../provider-session-import.js"; import { @@ -3390,7 +3391,7 @@ async function readOpenCodeUsageAuth( function resolveOpenCodeUsageReference( model: string, auth: Record | null, -): { source: string; input: import("@getpaseo/protocol/agent-types").JsonValue } | null { +): UsageReference | null { if (!auth) return null; if (model.startsWith("openai/")) { const entry = auth.openai; @@ -3607,10 +3608,7 @@ class OpenCodeAgentSession implements AgentSession { }; } - async getUsageReference(): Promise<{ - source: string; - input: import("@getpaseo/protocol/agent-types").JsonValue; - } | null> { + async getUsageReference(): Promise { const model = this.config.model; if (!model?.startsWith("openai/") && !model?.startsWith("opencode-go/")) return null; const auth = await readOpenCodeUsageAuth(this.usageEnv); diff --git a/packages/server/src/server/plugins/index.ts b/packages/server/src/server/plugins/index.ts index f49bd95e48..2b0c943cf5 100644 --- a/packages/server/src/server/plugins/index.ts +++ b/packages/server/src/server/plugins/index.ts @@ -28,6 +28,7 @@ import type { PluginProviderMetadata } from "./plugin-process-protocol.js"; import { readPluginProviderIcon } from "./provider-icon.js"; import { UsageSourceRegistry } from "./usage-sources/index.js"; import type { PluginUsageSourceMetadata } from "./plugin-process-protocol.js"; +import type { UsageReference } from "../agent/agent-sdk-types.js"; const BUILTIN_PROVIDER_ID_SET: ReadonlySet = new Set(BUILTIN_PROVIDER_IDS); @@ -142,17 +143,11 @@ export class PluginService { return [...this.providers.values()].sort((left, right) => left.id.localeCompare(right.id)); } - listUsageReports(options?: { - forceRefresh?: boolean; - references?: Array<{ source: string; input: unknown }>; - }) { + listUsageReports(options?: { forceRefresh?: boolean; references?: UsageReference[] }) { return this.usageSources.listReports(options); } - fetchUsageReference( - reference: { source: string; input: unknown }, - options?: { forceRefresh?: boolean }, - ) { + fetchUsageReference(reference: UsageReference, options?: { forceRefresh?: boolean }) { return this.usageSources.fetchReference(reference, options); } diff --git a/packages/server/src/server/plugins/session-usage-reference.e2e.test.ts b/packages/server/src/server/plugins/session-usage-reference.e2e.test.ts index 1c8512f805..f35cc1e021 100644 --- a/packages/server/src/server/plugins/session-usage-reference.e2e.test.ts +++ b/packages/server/src/server/plugins/session-usage-reference.e2e.test.ts @@ -1,6 +1,7 @@ import { fileURLToPath } from "node:url"; import { expect, test } from "vitest"; import { ACPAgentSession } from "../agent/providers/acp-agent.js"; +import type { UsageReference } from "../agent/agent-sdk-types.js"; import { ClaudeAgentClient } from "../agent/providers/claude/agent.js"; import { CodexAppServerAgentSession } from "../agent/providers/codex-app-server-agent.js"; import { createTestLogger } from "../../test-utils/test-logger.js"; @@ -49,7 +50,7 @@ test("agent.get_usage_report resolves source IDs from default built-in and ACP s ); const providers = ["claude", "codex", "copilot", "cursor", "kimi", "generic-acp"] as const; const logger = createTestLogger(); - const references = new Map } | null>(); + const references = new Map(); const claude = await new ClaudeAgentClient({ logger, resolveBinary: async () => "/test/claude/bin", diff --git a/packages/server/src/server/plugins/usage-sources/index.ts b/packages/server/src/server/plugins/usage-sources/index.ts index cb52f98328..686a3e509a 100644 --- a/packages/server/src/server/plugins/usage-sources/index.ts +++ b/packages/server/src/server/plugins/usage-sources/index.ts @@ -4,6 +4,7 @@ import { type UsageReportEntry, type ProviderUsage, } from "@getpaseo/protocol/messages"; +import type { UsageReference } from "../../agent/agent-sdk-types.js"; export interface UsageSource { id: string; @@ -37,7 +38,7 @@ export class UsageSourceRegistry { async listReports( options: { forceRefresh?: boolean; - references?: Array<{ source: string; input: unknown }>; + references?: UsageReference[]; } = {}, ): Promise { const discovered = await Promise.all( @@ -67,7 +68,7 @@ export class UsageSourceRegistry { } fetchReference( - reference: { source: string; input: unknown }, + reference: UsageReference, options: { forceRefresh?: boolean } = {}, ): Promise { return this.sources.has(reference.source) diff --git a/packages/server/src/server/session.ts b/packages/server/src/server/session.ts index 9d6c1d79cf..893021ec67 100644 --- a/packages/server/src/server/session.ts +++ b/packages/server/src/server/session.ts @@ -134,6 +134,7 @@ import { type AgentPermissionResponse, type AgentRunOptions, type AgentSessionConfig, + type UsageReference, } from "./agent/agent-sdk-types.js"; import type { StoredAgentRecord } from "./agent/agent-storage.js"; import type { AgentStorage } from "./agent/agent-storage.js"; @@ -511,10 +512,10 @@ export interface SessionOptions { invokePluginRpc(pluginId: string, method: string, input: unknown): Promise; listUsageReports(options?: { forceRefresh?: boolean; - references?: Array<{ source: string; input: unknown }>; + references?: UsageReference[]; }): Promise; fetchUsageReference( - reference: { source: string; input: unknown }, + reference: UsageReference, options?: { forceRefresh?: boolean }, ): Promise; listLegacyUsage(): Promise<{ fetchedAt: string; providers: ProviderUsage[] }>;