File tree Expand file tree Collapse file tree 4 files changed +33
-4
lines changed Expand file tree Collapse file tree 4 files changed +33
-4
lines changed Original file line number Diff line number Diff line change @@ -70,7 +70,16 @@ function createBrowserClient(authToken: string | null): {
7070}
7171
7272export const ORPCProvider = ( props : ORPCProviderProps ) => {
73- const [ state , setState ] = useState < ConnectionState > ( { status : "connecting" } ) ;
73+ // If client is provided externally, start in connected state immediately
74+ // This avoids a flash of null content on first render
75+ const [ state , setState ] = useState < ConnectionState > ( ( ) => {
76+ if ( props . client ) {
77+ // Also set the global client reference immediately
78+ window . __ORPC_CLIENT__ = props . client ;
79+ return { status : "connected" , client : props . client , cleanup : ( ) => undefined } ;
80+ }
81+ return { status : "connecting" } ;
82+ } ) ;
7483 const [ authToken , setAuthToken ] = useState < string | null > ( ( ) => {
7584 // Check URL param first, then localStorage
7685 const urlParams = new URLSearchParams ( window . location . search ) ;
Original file line number Diff line number Diff line change @@ -469,6 +469,20 @@ export const ReasoningEndEventSchema = z.object({
469469 messageId : z . string ( ) ,
470470} ) ;
471471
472+ // Usage schema matching LanguageModelV2Usage from @ai -sdk/provider
473+ export const LanguageModelUsageSchema = z . object ( {
474+ inputTokens : z . number ( ) . optional ( ) ,
475+ outputTokens : z . number ( ) . optional ( ) ,
476+ totalTokens : z . number ( ) . optional ( ) ,
477+ } ) ;
478+
479+ export const UsageDeltaEventSchema = z . object ( {
480+ type : z . literal ( "usage-delta" ) ,
481+ workspaceId : z . string ( ) ,
482+ messageId : z . string ( ) ,
483+ usage : LanguageModelUsageSchema ,
484+ } ) ;
485+
472486export const WorkspaceInitEventSchema = z . discriminatedUnion ( "type" , [
473487 z . object ( {
474488 type : z . literal ( "init-start" ) ,
@@ -518,6 +532,7 @@ export const WorkspaceChatMessageSchema = z.union([
518532 ToolCallEndEventSchema ,
519533 ReasoningDeltaEventSchema ,
520534 ReasoningEndEventSchema ,
535+ UsageDeltaEventSchema ,
521536 // Flatten WorkspaceInitEventSchema members into this union if possible,
522537 // or just include it as a union member. Zod discriminated union is strict.
523538 // WorkspaceInitEventSchema is already a discriminated union.
Original file line number Diff line number Diff line change @@ -12,6 +12,7 @@ import type {
1212 ToolCallEndEvent ,
1313 ReasoningDeltaEvent ,
1414 ReasoningEndEvent ,
15+ UsageDeltaEvent ,
1516} from "@/common/types/stream" ;
1617
1718export type BranchListResult = z . infer < typeof schemas . BranchListResultSchema > ;
@@ -76,6 +77,10 @@ export function isReasoningEnd(msg: WorkspaceChatMessage): msg is ReasoningEndEv
7677 return ( msg as { type ?: string } ) . type === "reasoning-end" ;
7778}
7879
80+ export function isUsageDelta ( msg : WorkspaceChatMessage ) : msg is UsageDeltaEvent {
81+ return ( msg as { type ?: string } ) . type === "usage-delta" ;
82+ }
83+
7984export function isMuxMessage ( msg : WorkspaceChatMessage ) : msg is MuxMessage {
8085 return "role" in msg && ! ( "type" in ( msg as { type ?: string } ) ) ;
8186}
Original file line number Diff line number Diff line change 55 modelString ,
66 assertStreamSuccess ,
77} from "./helpers" ;
8+ import { isUsageDelta } from "../../src/common/orpc/types" ;
89import { KNOWN_MODELS } from "../../src/common/constants/knownModels" ;
910
1011// Skip all tests if TEST_INTEGRATION is not set
@@ -45,16 +46,15 @@ describeIntegration("usage-delta events", () => {
4546
4647 // Verify usage-delta events were emitted
4748 const allEvents = collector . getEvents ( ) ;
48- const usageDeltas = allEvents . filter (
49- ( e ) => "type" in e && e . type === "usage-delta"
50- ) as Array < { type : "usage-delta" ; usage : { inputTokens : number ; outputTokens : number } } > ;
49+ const usageDeltas = allEvents . filter ( isUsageDelta ) ;
5150
5251 // Multi-step stream should emit at least one usage-delta (on finish-step)
5352 expect ( usageDeltas . length ) . toBeGreaterThan ( 0 ) ;
5453
5554 // Each usage-delta should have valid usage data
5655 for ( const delta of usageDeltas ) {
5756 expect ( delta . usage ) . toBeDefined ( ) ;
57+ // inputTokens should be present and > 0 (full context)
5858 expect ( delta . usage . inputTokens ) . toBeGreaterThan ( 0 ) ;
5959 // outputTokens may be 0 for some steps, but should be defined
6060 expect ( typeof delta . usage . outputTokens ) . toBe ( "number" ) ;
You can’t perform that action at this time.
0 commit comments