@@ -2,7 +2,6 @@ import * as fs from "fs";
22import * as path from "path" ;
33import * as os from "os" ;
44import * as crypto from "crypto" ;
5- import { fileURLToPath } from "url" ;
65import matter from "gray-matter" ;
76import ejs from "ejs" ;
87import type { ChatCompletionContentPart , ChatCompletionMessageParam } from "openai/resources/chat/completions" ;
@@ -44,7 +43,15 @@ import {
4443 type UserToolPermission ,
4544} from "../common/permissions" ;
4645
47- import { getCompactPromptTokenThreshold , getTotalTokens } from "./utils" ;
46+ import {
47+ accumulateUsage ,
48+ accumulateUsagePerModel ,
49+ getCompactPromptTokenThreshold ,
50+ getExtensionRoot ,
51+ getTotalTokens ,
52+ isUsageRecord ,
53+ summarizeCompletionOptions ,
54+ } from "./utils" ;
4855import {
4956 type BashTimeoutAdjustment ,
5057 type LlmStreamProgress ,
@@ -72,76 +79,6 @@ type ChatCompletionDebugOptions = {
7279 params ?: Record < string , unknown > ;
7380} ;
7481
75- function isUsageRecord ( value : unknown ) : value is Record < string , unknown > {
76- return value !== null && typeof value === "object" && ! Array . isArray ( value ) ;
77- }
78-
79- function summarizeCompletionOptions ( options ?: Record < string , unknown > ) : Record < string , unknown > | undefined {
80- if ( ! options ) {
81- return undefined ;
82- }
83- return {
84- ...options ,
85- signal : options . signal instanceof AbortSignal ? { aborted : options . signal . aborted } : options . signal ,
86- } ;
87- }
88-
89- function addUsageValue ( current : unknown , next : unknown ) : unknown {
90- if ( typeof next === "number" ) {
91- return ( typeof current === "number" ? current : 0 ) + next ;
92- }
93-
94- if ( isUsageRecord ( next ) ) {
95- const currentRecord = isUsageRecord ( current ) ? current : { } ;
96- const result : Record < string , unknown > = { ...currentRecord } ;
97- for ( const [ key , value ] of Object . entries ( next ) ) {
98- result [ key ] = addUsageValue ( currentRecord [ key ] , value ) ;
99- }
100- return result ;
101- }
102-
103- return next ;
104- }
105-
106- function accumulateUsage ( current : ModelUsage | null , next : unknown | null | undefined ) : ModelUsage | null {
107- if ( next == null ) {
108- return current ?? null ;
109- }
110- return addUsageValue ( current , next ) as ModelUsage ;
111- }
112-
113- function usageWithRequestCount ( usage : ModelUsage ) : ModelUsage {
114- const totalReqs = typeof usage . total_reqs === "number" ? usage . total_reqs + 1 : 1 ;
115- return {
116- ...usage ,
117- total_reqs : totalReqs ,
118- } ;
119- }
120-
121- function accumulateUsagePerModel (
122- current : Record < string , ModelUsage > | null | undefined ,
123- model : string ,
124- next : ModelUsage | null | undefined
125- ) : Record < string , ModelUsage > | null {
126- if ( next == null ) {
127- return current ?? null ;
128- }
129-
130- const usagePerModel = { ...( current ?? { } ) } ;
131- const modelName = model . trim ( ) || "unknown" ;
132- usagePerModel [ modelName ] = accumulateUsage ( usagePerModel [ modelName ] ?? null , usageWithRequestCount ( next ) ) ! ;
133- return usagePerModel ;
134- }
135-
136- function getExtensionRoot ( ) : string {
137- if ( typeof __dirname !== "undefined" ) {
138- return path . resolve ( __dirname , "../.." ) ;
139- }
140-
141- const currentFilePath = fileURLToPath ( import . meta. url ) ;
142- return path . resolve ( path . dirname ( currentFilePath ) , "../.." ) ;
143- }
144-
14582export class SessionManager {
14683 private readonly projectRoot : string ;
14784 private readonly createOpenAIClient : CreateOpenAIClient ;
0 commit comments