@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.
Files changed (55) hide show
  1. package/lib/browser/ai-core-frontend-module.d.ts.map +1 -1
  2. package/lib/browser/ai-core-frontend-module.js +2 -0
  3. package/lib/browser/ai-core-frontend-module.js.map +1 -1
  4. package/lib/browser/ai-core-preferences.d.ts +2 -0
  5. package/lib/browser/ai-core-preferences.d.ts.map +1 -1
  6. package/lib/browser/ai-core-preferences.js +9 -1
  7. package/lib/browser/ai-core-preferences.js.map +1 -1
  8. package/lib/browser/frontend-variable-service.d.ts +12 -0
  9. package/lib/browser/frontend-variable-service.d.ts.map +1 -1
  10. package/lib/browser/frontend-variable-service.js +23 -0
  11. package/lib/browser/frontend-variable-service.js.map +1 -1
  12. package/lib/browser/index.d.ts +1 -0
  13. package/lib/browser/index.d.ts.map +1 -1
  14. package/lib/browser/index.js +1 -0
  15. package/lib/browser/index.js.map +1 -1
  16. package/lib/browser/open-editors-variable-contribution.d.ts +17 -0
  17. package/lib/browser/open-editors-variable-contribution.d.ts.map +1 -0
  18. package/lib/browser/open-editors-variable-contribution.js +84 -0
  19. package/lib/browser/open-editors-variable-contribution.js.map +1 -0
  20. package/lib/browser/token-usage-frontend-service-impl.d.ts.map +1 -1
  21. package/lib/browser/token-usage-frontend-service-impl.js +20 -2
  22. package/lib/browser/token-usage-frontend-service-impl.js.map +1 -1
  23. package/lib/browser/token-usage-frontend-service.d.ts +4 -0
  24. package/lib/browser/token-usage-frontend-service.d.ts.map +1 -1
  25. package/lib/browser/token-usage-frontend-service.js.map +1 -1
  26. package/lib/common/language-model.d.ts +20 -1
  27. package/lib/common/language-model.d.ts.map +1 -1
  28. package/lib/common/language-model.js +12 -1
  29. package/lib/common/language-model.js.map +1 -1
  30. package/lib/common/token-usage-service.d.ts +8 -0
  31. package/lib/common/token-usage-service.d.ts.map +1 -1
  32. package/lib/common/tool-invocation-registry.d.ts +7 -0
  33. package/lib/common/tool-invocation-registry.d.ts.map +1 -1
  34. package/lib/common/tool-invocation-registry.js +12 -1
  35. package/lib/common/tool-invocation-registry.js.map +1 -1
  36. package/lib/common/variable-service.d.ts +2 -0
  37. package/lib/common/variable-service.d.ts.map +1 -1
  38. package/lib/common/variable-service.js +10 -2
  39. package/lib/common/variable-service.js.map +1 -1
  40. package/lib/node/token-usage-service-impl.d.ts.map +1 -1
  41. package/lib/node/token-usage-service-impl.js +14 -1
  42. package/lib/node/token-usage-service-impl.js.map +1 -1
  43. package/package.json +9 -9
  44. package/src/browser/ai-core-frontend-module.ts +2 -0
  45. package/src/browser/ai-core-preferences.ts +10 -0
  46. package/src/browser/frontend-variable-service.ts +36 -0
  47. package/src/browser/index.ts +1 -0
  48. package/src/browser/open-editors-variable-contribution.ts +88 -0
  49. package/src/browser/token-usage-frontend-service-impl.ts +27 -2
  50. package/src/browser/token-usage-frontend-service.ts +4 -0
  51. package/src/common/language-model.ts +20 -1
  52. package/src/common/token-usage-service.ts +8 -0
  53. package/src/common/tool-invocation-registry.ts +20 -2
  54. package/src/common/variable-service.ts +11 -1
  55. 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
- result.push({
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
- toolsToRemove.forEach(id => this.tools.delete(id));
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
- registerResolver(variable: AIVariable, resolver: AIVariableResolver): Disposable {
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
- console.log(`Input Tokens: ${params.inputTokens}; Output Tokens: ${params.outputTokens}; Model: ${model}${params.requestId ? `; RequestId: ${params.requestId}` : ''}`);
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();