@theia/ai-core 1.63.0-next.0 → 1.63.0-next.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/ai-core-frontend-module.d.ts.map +1 -1
- package/lib/browser/ai-core-frontend-module.js +2 -0
- package/lib/browser/ai-core-frontend-module.js.map +1 -1
- package/lib/browser/ai-core-preferences.d.ts +2 -0
- package/lib/browser/ai-core-preferences.d.ts.map +1 -1
- package/lib/browser/ai-core-preferences.js +9 -1
- package/lib/browser/ai-core-preferences.js.map +1 -1
- package/lib/browser/frontend-variable-service.d.ts +12 -0
- package/lib/browser/frontend-variable-service.d.ts.map +1 -1
- package/lib/browser/frontend-variable-service.js +23 -0
- package/lib/browser/frontend-variable-service.js.map +1 -1
- package/lib/browser/index.d.ts +1 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +1 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/open-editors-variable-contribution.d.ts +17 -0
- package/lib/browser/open-editors-variable-contribution.d.ts.map +1 -0
- package/lib/browser/open-editors-variable-contribution.js +84 -0
- package/lib/browser/open-editors-variable-contribution.js.map +1 -0
- package/lib/browser/token-usage-frontend-service-impl.d.ts.map +1 -1
- package/lib/browser/token-usage-frontend-service-impl.js +20 -2
- package/lib/browser/token-usage-frontend-service-impl.js.map +1 -1
- package/lib/browser/token-usage-frontend-service.d.ts +4 -0
- package/lib/browser/token-usage-frontend-service.d.ts.map +1 -1
- package/lib/browser/token-usage-frontend-service.js.map +1 -1
- package/lib/common/language-model.d.ts +20 -1
- package/lib/common/language-model.d.ts.map +1 -1
- package/lib/common/language-model.js +12 -1
- package/lib/common/language-model.js.map +1 -1
- package/lib/common/token-usage-service.d.ts +8 -0
- package/lib/common/token-usage-service.d.ts.map +1 -1
- package/lib/common/tool-invocation-registry.d.ts +7 -0
- package/lib/common/tool-invocation-registry.d.ts.map +1 -1
- package/lib/common/tool-invocation-registry.js +12 -1
- package/lib/common/tool-invocation-registry.js.map +1 -1
- package/lib/common/variable-service.d.ts +2 -0
- package/lib/common/variable-service.d.ts.map +1 -1
- package/lib/common/variable-service.js +10 -2
- package/lib/common/variable-service.js.map +1 -1
- package/lib/node/token-usage-service-impl.d.ts.map +1 -1
- package/lib/node/token-usage-service-impl.js +14 -1
- package/lib/node/token-usage-service-impl.js.map +1 -1
- package/package.json +9 -9
- package/src/browser/ai-core-frontend-module.ts +2 -0
- package/src/browser/ai-core-preferences.ts +10 -0
- package/src/browser/frontend-variable-service.ts +36 -0
- package/src/browser/index.ts +1 -0
- package/src/browser/open-editors-variable-contribution.ts +88 -0
- package/src/browser/token-usage-frontend-service-impl.ts +27 -2
- package/src/browser/token-usage-frontend-service.ts +4 -0
- package/src/common/language-model.ts +20 -1
- package/src/common/token-usage-service.ts +8 -0
- package/src/common/tool-invocation-registry.ts +20 -2
- package/src/common/variable-service.ts +11 -1
- package/src/node/token-usage-service-impl.ts +19 -1
|
@@ -76,6 +76,8 @@ export class TokenUsageFrontendServiceImpl implements TokenUsageFrontendService
|
|
|
76
76
|
const modelMap = new Map<string, {
|
|
77
77
|
inputTokens: number;
|
|
78
78
|
outputTokens: number;
|
|
79
|
+
cachedInputTokens: number;
|
|
80
|
+
readCachedInputTokens: number;
|
|
79
81
|
lastUsed?: Date;
|
|
80
82
|
}>();
|
|
81
83
|
|
|
@@ -87,6 +89,16 @@ export class TokenUsageFrontendServiceImpl implements TokenUsageFrontendService
|
|
|
87
89
|
existing.inputTokens += usage.inputTokens;
|
|
88
90
|
existing.outputTokens += usage.outputTokens;
|
|
89
91
|
|
|
92
|
+
// Add cached tokens if they exist
|
|
93
|
+
if (usage.cachedInputTokens !== undefined) {
|
|
94
|
+
existing.cachedInputTokens += usage.cachedInputTokens;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Add read cached tokens if they exist
|
|
98
|
+
if (usage.readCachedInputTokens !== undefined) {
|
|
99
|
+
existing.readCachedInputTokens += usage.readCachedInputTokens;
|
|
100
|
+
}
|
|
101
|
+
|
|
90
102
|
// Update last used if this usage is more recent
|
|
91
103
|
if (!existing.lastUsed || (usage.timestamp && usage.timestamp > existing.lastUsed)) {
|
|
92
104
|
existing.lastUsed = usage.timestamp;
|
|
@@ -95,6 +107,8 @@ export class TokenUsageFrontendServiceImpl implements TokenUsageFrontendService
|
|
|
95
107
|
modelMap.set(usage.model, {
|
|
96
108
|
inputTokens: usage.inputTokens,
|
|
97
109
|
outputTokens: usage.outputTokens,
|
|
110
|
+
cachedInputTokens: usage.cachedInputTokens || 0,
|
|
111
|
+
readCachedInputTokens: usage.readCachedInputTokens || 0,
|
|
98
112
|
lastUsed: usage.timestamp
|
|
99
113
|
});
|
|
100
114
|
}
|
|
@@ -104,12 +118,23 @@ export class TokenUsageFrontendServiceImpl implements TokenUsageFrontendService
|
|
|
104
118
|
const result: ModelTokenUsageData[] = [];
|
|
105
119
|
|
|
106
120
|
for (const [modelId, data] of modelMap.entries()) {
|
|
107
|
-
|
|
121
|
+
const modelData: ModelTokenUsageData = {
|
|
108
122
|
modelId,
|
|
109
123
|
inputTokens: data.inputTokens,
|
|
110
124
|
outputTokens: data.outputTokens,
|
|
111
125
|
lastUsed: data.lastUsed
|
|
112
|
-
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Only include cache-related fields if they have non-zero values
|
|
129
|
+
if (data.cachedInputTokens > 0) {
|
|
130
|
+
modelData.cachedInputTokens = data.cachedInputTokens;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (data.readCachedInputTokens > 0) {
|
|
134
|
+
modelData.readCachedInputTokens = data.readCachedInputTokens;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
result.push(modelData);
|
|
113
138
|
}
|
|
114
139
|
|
|
115
140
|
return result;
|
|
@@ -26,6 +26,10 @@ export interface ModelTokenUsageData {
|
|
|
26
26
|
inputTokens: number;
|
|
27
27
|
/** Number of output tokens used */
|
|
28
28
|
outputTokens: number;
|
|
29
|
+
/** Number of input tokens written to cache */
|
|
30
|
+
cachedInputTokens?: number;
|
|
31
|
+
/** Number of input tokens read from cache */
|
|
32
|
+
readCachedInputTokens?: number;
|
|
29
33
|
/** Date when the model was last used */
|
|
30
34
|
lastUsed?: Date;
|
|
31
35
|
}
|
|
@@ -19,7 +19,7 @@ import { inject, injectable, named, postConstruct } from '@theia/core/shared/inv
|
|
|
19
19
|
|
|
20
20
|
export type MessageActor = 'user' | 'ai' | 'system';
|
|
21
21
|
|
|
22
|
-
export type LanguageModelMessage = TextMessage | ThinkingMessage | ToolUseMessage | ToolResultMessage;
|
|
22
|
+
export type LanguageModelMessage = TextMessage | ThinkingMessage | ToolUseMessage | ToolResultMessage | ImageMessage;
|
|
23
23
|
export namespace LanguageModelMessage {
|
|
24
24
|
|
|
25
25
|
export function isTextMessage(obj: LanguageModelMessage): obj is TextMessage {
|
|
@@ -34,6 +34,9 @@ export namespace LanguageModelMessage {
|
|
|
34
34
|
export function isToolResultMessage(obj: LanguageModelMessage): obj is ToolResultMessage {
|
|
35
35
|
return obj.type === 'tool_result';
|
|
36
36
|
}
|
|
37
|
+
export function isImageMessage(obj: LanguageModelMessage): obj is ImageMessage {
|
|
38
|
+
return obj.type === 'image';
|
|
39
|
+
}
|
|
37
40
|
}
|
|
38
41
|
export interface TextMessage {
|
|
39
42
|
actor: MessageActor;
|
|
@@ -63,6 +66,22 @@ export interface ToolUseMessage {
|
|
|
63
66
|
input: unknown;
|
|
64
67
|
name: string;
|
|
65
68
|
}
|
|
69
|
+
export type ImageMimeType = 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp' | 'image/bmp' | 'image/svg+xml' | string & {};
|
|
70
|
+
export interface UrlImageContent { url: string };
|
|
71
|
+
export interface Base64ImageContent {
|
|
72
|
+
base64data: string;
|
|
73
|
+
mimeType: ImageMimeType;
|
|
74
|
+
};
|
|
75
|
+
export type ImageContent = UrlImageContent | Base64ImageContent;
|
|
76
|
+
export namespace ImageContent {
|
|
77
|
+
export const isUrl = (obj: ImageContent): obj is UrlImageContent => 'url' in obj;
|
|
78
|
+
export const isBase64 = (obj: ImageContent): obj is Base64ImageContent => 'base64data' in obj && 'mimeType' in obj;
|
|
79
|
+
}
|
|
80
|
+
export interface ImageMessage {
|
|
81
|
+
actor: 'ai' | 'user';
|
|
82
|
+
type: 'image';
|
|
83
|
+
image: ImageContent;
|
|
84
|
+
}
|
|
66
85
|
|
|
67
86
|
export const isLanguageModelRequestMessage = (obj: unknown): obj is LanguageModelMessage =>
|
|
68
87
|
!!(obj && typeof obj === 'object' &&
|
|
@@ -23,6 +23,10 @@ export interface TokenUsage {
|
|
|
23
23
|
inputTokens: number;
|
|
24
24
|
/** The output token count */
|
|
25
25
|
outputTokens: number;
|
|
26
|
+
/** Input tokens written to cache */
|
|
27
|
+
cachedInputTokens?: number;
|
|
28
|
+
/** Input tokens read from cache */
|
|
29
|
+
readCachedInputTokens?: number;
|
|
26
30
|
/** The model identifier */
|
|
27
31
|
model: string;
|
|
28
32
|
/** The timestamp of when the tokens were used */
|
|
@@ -36,6 +40,10 @@ export interface TokenUsageParams {
|
|
|
36
40
|
inputTokens: number;
|
|
37
41
|
/** The output token count */
|
|
38
42
|
outputTokens: number;
|
|
43
|
+
/** Input tokens placed in cache */
|
|
44
|
+
cachedInputTokens?: number;
|
|
45
|
+
/** Input tokens read from cache */
|
|
46
|
+
readCachedInputTokens?: number;
|
|
39
47
|
/** Request identifier */
|
|
40
48
|
requestId: string;
|
|
41
49
|
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { inject, injectable, named, postConstruct, interfaces } from '@theia/core/shared/inversify';
|
|
18
18
|
import { ToolRequest } from './language-model';
|
|
19
|
-
import { ContributionProvider } from '@theia/core';
|
|
19
|
+
import { ContributionProvider, Emitter, Event } from '@theia/core';
|
|
20
20
|
|
|
21
21
|
export const ToolInvocationRegistry = Symbol('ToolInvocationRegistry');
|
|
22
22
|
|
|
@@ -62,6 +62,11 @@ export interface ToolInvocationRegistry {
|
|
|
62
62
|
* @param providerName - The name of the tool provider whose tools should be removed (as specificed in the `ToolRequest`).
|
|
63
63
|
*/
|
|
64
64
|
unregisterAllTools(providerName: string): void;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Event that is fired whenever the registry changes (tool registered or unregistered).
|
|
68
|
+
*/
|
|
69
|
+
onDidChange: Event<void>;
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
export const ToolProvider = Symbol('ToolProvider');
|
|
@@ -80,6 +85,9 @@ export class ToolInvocationRegistryImpl implements ToolInvocationRegistry {
|
|
|
80
85
|
|
|
81
86
|
private tools: Map<string, ToolRequest> = new Map<string, ToolRequest>();
|
|
82
87
|
|
|
88
|
+
private readonly onDidChangeEmitter = new Emitter<void>();
|
|
89
|
+
readonly onDidChange: Event<void> = this.onDidChangeEmitter.event;
|
|
90
|
+
|
|
83
91
|
@inject(ContributionProvider)
|
|
84
92
|
@named(ToolProvider)
|
|
85
93
|
private providers: ContributionProvider<ToolProvider>;
|
|
@@ -98,7 +106,15 @@ export class ToolInvocationRegistryImpl implements ToolInvocationRegistry {
|
|
|
98
106
|
toolsToRemove.push(id);
|
|
99
107
|
}
|
|
100
108
|
}
|
|
101
|
-
|
|
109
|
+
let changed = false;
|
|
110
|
+
toolsToRemove.forEach(id => {
|
|
111
|
+
if (this.tools.delete(id)) {
|
|
112
|
+
changed = true;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
if (changed) {
|
|
116
|
+
this.onDidChangeEmitter.fire();
|
|
117
|
+
}
|
|
102
118
|
}
|
|
103
119
|
getAllFunctions(): ToolRequest[] {
|
|
104
120
|
return Array.from(this.tools.values());
|
|
@@ -109,6 +125,7 @@ export class ToolInvocationRegistryImpl implements ToolInvocationRegistry {
|
|
|
109
125
|
console.warn(`Function with id ${tool.id} is already registered.`);
|
|
110
126
|
} else {
|
|
111
127
|
this.tools.set(tool.id, tool);
|
|
128
|
+
this.onDidChangeEmitter.fire();
|
|
112
129
|
}
|
|
113
130
|
}
|
|
114
131
|
|
|
@@ -128,3 +145,4 @@ export class ToolInvocationRegistryImpl implements ToolInvocationRegistry {
|
|
|
128
145
|
return tools;
|
|
129
146
|
}
|
|
130
147
|
}
|
|
148
|
+
|
|
@@ -172,6 +172,7 @@ export interface AIVariableService {
|
|
|
172
172
|
getVariable(name: string): Readonly<AIVariable> | undefined;
|
|
173
173
|
getVariables(): Readonly<AIVariable>[];
|
|
174
174
|
getContextVariables(): Readonly<AIContextVariable>[];
|
|
175
|
+
registerVariable(variable: AIVariable): Disposable;
|
|
175
176
|
unregisterVariable(name: string): void;
|
|
176
177
|
readonly onDidChangeVariables: Event<void>;
|
|
177
178
|
|
|
@@ -287,12 +288,19 @@ export class DefaultAIVariableService implements AIVariableService {
|
|
|
287
288
|
return this.getVariables().filter(AIContextVariable.is);
|
|
288
289
|
}
|
|
289
290
|
|
|
290
|
-
|
|
291
|
+
registerVariable(variable: AIVariable): Disposable {
|
|
291
292
|
const key = this.getKey(variable.name);
|
|
292
293
|
if (!this.variables.get(key)) {
|
|
293
294
|
this.variables.set(key, variable);
|
|
294
295
|
this.onDidChangeVariablesEmitter.fire();
|
|
296
|
+
return Disposable.create(() => this.unregisterVariable(variable.name));
|
|
295
297
|
}
|
|
298
|
+
return Disposable.NULL;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
registerResolver(variable: AIVariable, resolver: AIVariableResolver): Disposable {
|
|
302
|
+
this.registerVariable(variable);
|
|
303
|
+
const key = this.getKey(variable.name);
|
|
296
304
|
const resolvers = this.resolvers.get(key) ?? [];
|
|
297
305
|
resolvers.push(resolver);
|
|
298
306
|
this.resolvers.set(key, resolvers);
|
|
@@ -315,6 +323,7 @@ export class DefaultAIVariableService implements AIVariableService {
|
|
|
315
323
|
}
|
|
316
324
|
|
|
317
325
|
registerArgumentPicker(variable: AIVariable, argPicker: AIVariableArgPicker): Disposable {
|
|
326
|
+
this.registerVariable(variable);
|
|
318
327
|
const key = this.getKey(variable.name);
|
|
319
328
|
this.argPickers.set(key, argPicker);
|
|
320
329
|
return Disposable.create(() => this.unregisterArgumentPicker(variable, argPicker));
|
|
@@ -333,6 +342,7 @@ export class DefaultAIVariableService implements AIVariableService {
|
|
|
333
342
|
}
|
|
334
343
|
|
|
335
344
|
registerArgumentCompletionProvider(variable: AIVariable, completionProvider: AIVariableArgCompletionProvider): Disposable {
|
|
345
|
+
this.registerVariable(variable);
|
|
336
346
|
const key = this.getKey(variable.name);
|
|
337
347
|
this.argCompletionProviders.set(key, completionProvider);
|
|
338
348
|
return Disposable.create(() => this.unregisterArgumentCompletionProvider(variable, completionProvider));
|
|
@@ -41,6 +41,8 @@ export class TokenUsageServiceImpl implements TokenUsageService {
|
|
|
41
41
|
async recordTokenUsage(model: string, params: TokenUsageParams): Promise<void> {
|
|
42
42
|
const usage: TokenUsage = {
|
|
43
43
|
inputTokens: params.inputTokens,
|
|
44
|
+
cachedInputTokens: params.cachedInputTokens,
|
|
45
|
+
readCachedInputTokens: params.readCachedInputTokens,
|
|
44
46
|
outputTokens: params.outputTokens,
|
|
45
47
|
model,
|
|
46
48
|
timestamp: new Date(),
|
|
@@ -50,7 +52,23 @@ export class TokenUsageServiceImpl implements TokenUsageService {
|
|
|
50
52
|
this.tokenUsages.push(usage);
|
|
51
53
|
this.client?.notifyTokenUsage(usage);
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
let logMessage = `Input Tokens: ${params.inputTokens};`;
|
|
56
|
+
|
|
57
|
+
if (params.cachedInputTokens) {
|
|
58
|
+
logMessage += ` Input Tokens written to cache: ${params.cachedInputTokens};`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (params.readCachedInputTokens) {
|
|
62
|
+
logMessage += ` Input Tokens read from cache: ${params.readCachedInputTokens};`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
logMessage += ` Output Tokens: ${params.outputTokens}; Model: ${model};`;
|
|
66
|
+
|
|
67
|
+
if (params.requestId) {
|
|
68
|
+
logMessage += `; RequestId: ${params.requestId}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.debug(logMessage);
|
|
54
72
|
// For now we just store in memory
|
|
55
73
|
// In the future, this could be persisted to disk, a database, or sent to a service
|
|
56
74
|
return Promise.resolve();
|