@theia/ai-ide 1.67.0-next.59 → 1.67.0
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/address-pr-review-command-contribution.d.ts +9 -0
- package/lib/browser/address-pr-review-command-contribution.d.ts.map +1 -0
- package/lib/browser/address-pr-review-command-contribution.js +176 -0
- package/lib/browser/address-pr-review-command-contribution.js.map +1 -0
- package/lib/browser/ai-configuration/agent-configuration-widget.d.ts +12 -6
- package/lib/browser/ai-configuration/agent-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/agent-configuration-widget.js +158 -106
- package/lib/browser/ai-configuration/agent-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/base/ai-card-grid-configuration-widget.d.ts +32 -0
- package/lib/browser/ai-configuration/base/ai-card-grid-configuration-widget.d.ts.map +1 -0
- package/lib/browser/ai-configuration/base/ai-card-grid-configuration-widget.js +55 -0
- package/lib/browser/ai-configuration/base/ai-card-grid-configuration-widget.js.map +1 -0
- package/lib/browser/ai-configuration/base/ai-configuration-base-widget.d.ts +14 -0
- package/lib/browser/ai-configuration/base/ai-configuration-base-widget.d.ts.map +1 -0
- package/lib/browser/ai-configuration/base/ai-configuration-base-widget.js +35 -0
- package/lib/browser/ai-configuration/base/ai-configuration-base-widget.js.map +1 -0
- package/lib/browser/ai-configuration/base/ai-hierarchical-configuration-widget.d.ts +23 -0
- package/lib/browser/ai-configuration/base/ai-hierarchical-configuration-widget.d.ts.map +1 -0
- package/lib/browser/ai-configuration/base/ai-hierarchical-configuration-widget.js +60 -0
- package/lib/browser/ai-configuration/base/ai-hierarchical-configuration-widget.js.map +1 -0
- package/lib/browser/ai-configuration/base/ai-list-detail-configuration-widget.d.ts +56 -0
- package/lib/browser/ai-configuration/base/ai-list-detail-configuration-widget.d.ts.map +1 -0
- package/lib/browser/ai-configuration/base/ai-list-detail-configuration-widget.js +96 -0
- package/lib/browser/ai-configuration/base/ai-list-detail-configuration-widget.js.map +1 -0
- package/lib/browser/ai-configuration/base/ai-table-configuration-widget.d.ts +45 -0
- package/lib/browser/ai-configuration/base/ai-table-configuration-widget.d.ts.map +1 -0
- package/lib/browser/ai-configuration/base/ai-table-configuration-widget.js +66 -0
- package/lib/browser/ai-configuration/base/ai-table-configuration-widget.js.map +1 -0
- package/lib/browser/ai-configuration/components/configuration-section.d.ts +13 -0
- package/lib/browser/ai-configuration/components/configuration-section.d.ts.map +1 -0
- package/lib/browser/ai-configuration/components/configuration-section.js +28 -0
- package/lib/browser/ai-configuration/components/configuration-section.js.map +1 -0
- package/lib/browser/ai-configuration/components/empty-state.d.ts +11 -0
- package/lib/browser/ai-configuration/components/empty-state.d.ts.map +1 -0
- package/lib/browser/ai-configuration/components/empty-state.js +26 -0
- package/lib/browser/ai-configuration/components/empty-state.js.map +1 -0
- package/lib/browser/ai-configuration/components/expandable-section.d.ts +14 -0
- package/lib/browser/ai-configuration/components/expandable-section.d.ts.map +1 -0
- package/lib/browser/ai-configuration/components/expandable-section.js +31 -0
- package/lib/browser/ai-configuration/components/expandable-section.js.map +1 -0
- package/lib/browser/ai-configuration/language-model-renderer.d.ts.map +1 -1
- package/lib/browser/ai-configuration/language-model-renderer.js +23 -22
- package/lib/browser/ai-configuration/language-model-renderer.js.map +1 -1
- package/lib/browser/ai-configuration/mcp-configuration-widget.d.ts +0 -1
- package/lib/browser/ai-configuration/mcp-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/mcp-configuration-widget.js +88 -82
- package/lib/browser/ai-configuration/mcp-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.d.ts +8 -22
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.js +49 -78
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js +10 -10
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/template-settings-renderer.d.ts.map +1 -1
- package/lib/browser/ai-configuration/template-settings-renderer.js +11 -11
- package/lib/browser/ai-configuration/template-settings-renderer.js.map +1 -1
- package/lib/browser/ai-configuration/token-usage-configuration-widget.d.ts +7 -8
- package/lib/browser/ai-configuration/token-usage-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/token-usage-configuration-widget.js +93 -79
- package/lib/browser/ai-configuration/token-usage-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/tools-configuration-widget.d.ts +12 -7
- package/lib/browser/ai-configuration/tools-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/tools-configuration-widget.js +45 -37
- package/lib/browser/ai-configuration/tools-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/variable-configuration-widget.d.ts +8 -4
- package/lib/browser/ai-configuration/variable-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/variable-configuration-widget.js +61 -28
- package/lib/browser/ai-configuration/variable-configuration-widget.js.map +1 -1
- package/lib/browser/analyze-gh-ticket-command-contribution.d.ts +9 -0
- package/lib/browser/analyze-gh-ticket-command-contribution.d.ts.map +1 -0
- package/lib/browser/analyze-gh-ticket-command-contribution.js +172 -0
- package/lib/browser/analyze-gh-ticket-command-contribution.js.map +1 -0
- package/lib/browser/default-chat-agent-recommendation-service.d.ts +5 -0
- package/lib/browser/default-chat-agent-recommendation-service.d.ts.map +1 -0
- package/lib/browser/default-chat-agent-recommendation-service.js +47 -0
- package/lib/browser/default-chat-agent-recommendation-service.js.map +1 -0
- package/lib/browser/frontend-module.d.ts.map +1 -1
- package/lib/browser/frontend-module.js +9 -3
- package/lib/browser/frontend-module.js.map +1 -1
- package/lib/browser/ide-chat-welcome-message-provider.d.ts +36 -0
- package/lib/browser/ide-chat-welcome-message-provider.d.ts.map +1 -1
- package/lib/browser/ide-chat-welcome-message-provider.js +204 -1
- package/lib/browser/ide-chat-welcome-message-provider.js.map +1 -1
- package/lib/browser/implement-gh-ticket-command-contribution.d.ts +9 -0
- package/lib/browser/implement-gh-ticket-command-contribution.d.ts.map +1 -0
- package/lib/browser/implement-gh-ticket-command-contribution.js +156 -0
- package/lib/browser/implement-gh-ticket-command-contribution.js.map +1 -0
- package/package.json +21 -21
- package/src/browser/address-pr-review-command-contribution.ts +180 -0
- package/src/browser/ai-configuration/agent-configuration-widget.tsx +258 -137
- package/src/browser/ai-configuration/base/ai-card-grid-configuration-widget.tsx +72 -0
- package/src/browser/ai-configuration/base/ai-configuration-base-widget.tsx +37 -0
- package/src/browser/ai-configuration/base/ai-hierarchical-configuration-widget.tsx +51 -0
- package/src/browser/ai-configuration/base/ai-list-detail-configuration-widget.tsx +140 -0
- package/src/browser/ai-configuration/base/ai-table-configuration-widget.tsx +107 -0
- package/src/browser/ai-configuration/components/configuration-section.tsx +37 -0
- package/src/browser/ai-configuration/components/empty-state.tsx +30 -0
- package/src/browser/ai-configuration/components/expandable-section.tsx +51 -0
- package/src/browser/ai-configuration/language-model-renderer.tsx +68 -63
- package/src/browser/ai-configuration/mcp-configuration-widget.tsx +82 -87
- package/src/browser/ai-configuration/model-aliases-configuration-widget.tsx +93 -107
- package/src/browser/ai-configuration/prompt-fragments-configuration-widget.tsx +10 -10
- package/src/browser/ai-configuration/template-settings-renderer.tsx +25 -29
- package/src/browser/ai-configuration/token-usage-configuration-widget.tsx +131 -131
- package/src/browser/ai-configuration/tools-configuration-widget.tsx +70 -61
- package/src/browser/ai-configuration/variable-configuration-widget.tsx +95 -45
- package/src/browser/analyze-gh-ticket-command-contribution.ts +176 -0
- package/src/browser/default-chat-agent-recommendation-service.ts +43 -0
- package/src/browser/frontend-module.ts +12 -7
- package/src/browser/ide-chat-welcome-message-provider.tsx +300 -2
- package/src/browser/implement-gh-ticket-command-contribution.ts +160 -0
- package/src/browser/style/ai-configuration-base.css +90 -0
- package/src/browser/style/ai-configuration-cards.css +60 -0
- package/src/browser/style/ai-configuration-hierarchical.css +61 -0
- package/src/browser/style/ai-configuration-list-detail.css +88 -0
- package/src/browser/style/ai-configuration-table.css +73 -0
- package/src/browser/style/index.css +596 -261
- package/src/browser/style/widgets/mcp-configuration.css +253 -0
- package/src/browser/style/widgets/model-aliases-configuration.css +74 -0
|
@@ -270,8 +270,8 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
270
270
|
msg: nls.localize('theia/ai/core/promptFragmentsConfiguration/resetToCustomizationDialogMsg',
|
|
271
271
|
'Are you sure you want to reset the prompt fragment "{0}" to use the {1} customization? This will remove all higher-priority customizations.',
|
|
272
272
|
customization.id, type),
|
|
273
|
-
ok: nls.
|
|
274
|
-
cancel: nls.
|
|
273
|
+
ok: nls.localizeByDefault('Reset'),
|
|
274
|
+
cancel: nls.localizeByDefault('Cancel')
|
|
275
275
|
});
|
|
276
276
|
|
|
277
277
|
const shouldReset = await dialog.open();
|
|
@@ -283,8 +283,8 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
283
283
|
title: nls.localize('theia/ai/core/promptFragmentsConfiguration/resetToBuiltInDialogTitle', 'Reset to Built-in'),
|
|
284
284
|
msg: nls.localize('theia/ai/core/promptFragmentsConfiguration/resetToBuiltInDialogMsg',
|
|
285
285
|
'Are you sure you want to reset the prompt fragment "{0}" to its built-in version? This will remove all customizations.', customization.id),
|
|
286
|
-
ok: nls.
|
|
287
|
-
cancel: nls.
|
|
286
|
+
ok: nls.localizeByDefault('Reset'),
|
|
287
|
+
cancel: nls.localizeByDefault('Cancel')
|
|
288
288
|
});
|
|
289
289
|
|
|
290
290
|
const shouldReset = await dialog.open();
|
|
@@ -323,8 +323,8 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
323
323
|
'Are you sure you want to remove the {0} customization for prompt fragment "{1}" ({2})?', type, customization.id, description) :
|
|
324
324
|
nls.localize('theia/ai/core/promptFragmentsConfiguration/removeCustomizationDialogMsg',
|
|
325
325
|
'Are you sure you want to remove the {0} customization for prompt fragment "{1}"?', type, customization.id),
|
|
326
|
-
ok: nls.
|
|
327
|
-
cancel: nls.
|
|
326
|
+
ok: nls.localizeByDefault('Remove'),
|
|
327
|
+
cancel: nls.localizeByDefault('Cancel')
|
|
328
328
|
});
|
|
329
329
|
|
|
330
330
|
const shouldDelete = await dialog.open();
|
|
@@ -342,7 +342,7 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
342
342
|
msg: nls.localize('theia/ai/core/promptFragmentsConfiguration/resetAllCustomizationsDialogMsg',
|
|
343
343
|
'Are you sure you want to reset all prompt fragments to their built-in versions? This will remove all customizations.'),
|
|
344
344
|
ok: nls.localize('theia/ai/core/promptFragmentsConfiguration/resetAllButton', 'Reset All'),
|
|
345
|
-
cancel: nls.
|
|
345
|
+
cancel: nls.localizeByDefault('Cancel')
|
|
346
346
|
});
|
|
347
347
|
|
|
348
348
|
const shouldReset = await dialog.open();
|
|
@@ -492,7 +492,7 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
492
492
|
{defaultVariantId === variantId && (
|
|
493
493
|
<span className="badge default-variant"
|
|
494
494
|
title={nls.localize('theia/ai/core/promptFragmentsConfiguration/defaultVariantTitle', 'Default variant')}>
|
|
495
|
-
{nls.
|
|
495
|
+
{nls.localizeByDefault('Default')}
|
|
496
496
|
</span>
|
|
497
497
|
)}
|
|
498
498
|
{selectedVariantId === variantId && (
|
|
@@ -601,7 +601,7 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
601
601
|
{isActive && (
|
|
602
602
|
<span className="active-indicator"
|
|
603
603
|
title={nls.localize('theia/ai/core/promptFragmentsConfiguration/activeCustomizationTitle', 'Active customization')}>
|
|
604
|
-
{nls.
|
|
604
|
+
{nls.localizeByDefault('Active')}
|
|
605
605
|
</span>
|
|
606
606
|
)}
|
|
607
607
|
</div>
|
|
@@ -695,7 +695,7 @@ const CustomizationTypeBadge: React.FC<CustomizationTypeBadgeProps> = ({ promptF
|
|
|
695
695
|
customizationType + ' ' + nls.localize('theia/ai/core/promptFragmentsConfiguration/customization', 'customization')
|
|
696
696
|
: nls.localize('theia/ai/core/promptFragmentsConfiguration/customizationLabel', 'Customization')}`);
|
|
697
697
|
} else {
|
|
698
|
-
setTypeLabel(nls.
|
|
698
|
+
setTypeLabel(nls.localizeByDefault('Built-in'));
|
|
699
699
|
}
|
|
700
700
|
};
|
|
701
701
|
|
|
@@ -63,16 +63,11 @@ export const PromptVariantRenderer: React.FC<PromptVariantRendererProps> = ({
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
return (
|
|
66
|
-
|
|
67
|
-
<
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
{(variantIds.length > 1 || isInvalidVariant) && (
|
|
72
|
-
<>
|
|
73
|
-
<label htmlFor={`variant-selector-${promptVariantSet.id}`} className="template-select-label">
|
|
74
|
-
{nls.localize('theia/ai/core/templateSettings/selectVariant', 'Select Variant:')}
|
|
75
|
-
</label>
|
|
66
|
+
<>
|
|
67
|
+
<tr>
|
|
68
|
+
<td className="template-name-cell">{promptVariantSet.id}</td>
|
|
69
|
+
<td className="template-variant-cell">
|
|
70
|
+
{(variantIds.length > 1 || isInvalidVariant) && (
|
|
76
71
|
<select
|
|
77
72
|
id={`variant-selector-${promptVariantSet.id}`}
|
|
78
73
|
className={`theia-select template-variant-selector ${isInvalidVariant ? 'error' : ''}`}
|
|
@@ -81,7 +76,7 @@ export const PromptVariantRenderer: React.FC<PromptVariantRendererProps> = ({
|
|
|
81
76
|
>
|
|
82
77
|
{isInvalidVariant && (
|
|
83
78
|
<option value="invalid" disabled>
|
|
84
|
-
{nls.localize('theia/ai/core/templateSettings/unavailableVariant', '
|
|
79
|
+
{nls.localize('theia/ai/core/templateSettings/unavailableVariant', 'Unavailable')}
|
|
85
80
|
</option>
|
|
86
81
|
)}
|
|
87
82
|
{variantIds.map(variantId => (
|
|
@@ -90,23 +85,24 @@ export const PromptVariantRenderer: React.FC<PromptVariantRendererProps> = ({
|
|
|
90
85
|
</option>
|
|
91
86
|
))}
|
|
92
87
|
</select>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
88
|
+
)}
|
|
89
|
+
{variantIds.length === 1 && !isInvalidVariant && <span>{selectedVariant}</span>}
|
|
90
|
+
</td>
|
|
91
|
+
<td className="template-actions-cell">
|
|
92
|
+
<button
|
|
93
|
+
className="template-action-icon-button codicon codicon-edit"
|
|
94
|
+
onClick={openTemplate}
|
|
95
|
+
disabled={isInvalidVariant}
|
|
96
|
+
title={nls.localizeByDefault('Edit')}
|
|
97
|
+
/>
|
|
98
|
+
<button
|
|
99
|
+
className="template-action-icon-button codicon codicon-discard"
|
|
100
|
+
onClick={resetTemplate}
|
|
101
|
+
disabled={isInvalidVariant}
|
|
102
|
+
title={nls.localizeByDefault('Reset')}
|
|
103
|
+
/>
|
|
104
|
+
</td>
|
|
105
|
+
</tr>
|
|
106
|
+
</>
|
|
111
107
|
);
|
|
112
108
|
};
|
|
@@ -14,24 +14,19 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { ReactWidget } from '@theia/core/lib/browser';
|
|
18
17
|
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
19
18
|
import * as React from '@theia/core/shared/react';
|
|
20
19
|
import { MessageService, nls } from '@theia/core';
|
|
21
20
|
import { TokenUsageFrontendService, ModelTokenUsageData } from '@theia/ai-core/lib/browser/token-usage-frontend-service';
|
|
22
21
|
import { formatDistanceToNow } from 'date-fns';
|
|
23
|
-
|
|
24
|
-
// Using the interface from the token usage service
|
|
22
|
+
import { AITableConfigurationWidget, TableColumn } from './base/ai-table-configuration-widget';
|
|
25
23
|
|
|
26
24
|
@injectable()
|
|
27
|
-
export class AITokenUsageConfigurationWidget extends
|
|
25
|
+
export class AITokenUsageConfigurationWidget extends AITableConfigurationWidget<ModelTokenUsageData> {
|
|
28
26
|
|
|
29
27
|
static readonly ID = 'ai-token-usage-configuration-container-widget';
|
|
30
28
|
static readonly LABEL = nls.localize('theia/ai/tokenUsage/label', 'Token Usage');
|
|
31
29
|
|
|
32
|
-
// Data will be fetched from the service
|
|
33
|
-
protected tokenUsageData: ModelTokenUsageData[] = [];
|
|
34
|
-
|
|
35
30
|
@inject(MessageService)
|
|
36
31
|
protected readonly messageService: MessageService;
|
|
37
32
|
|
|
@@ -43,168 +38,173 @@ export class AITokenUsageConfigurationWidget extends ReactWidget {
|
|
|
43
38
|
this.id = AITokenUsageConfigurationWidget.ID;
|
|
44
39
|
this.title.label = AITokenUsageConfigurationWidget.LABEL;
|
|
45
40
|
this.title.closable = false;
|
|
41
|
+
this.addClass('ai-configuration-widget');
|
|
46
42
|
|
|
47
|
-
this.
|
|
43
|
+
this.loadItems().then(() => this.update());
|
|
48
44
|
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
this.toDispose.push(
|
|
46
|
+
this.tokenUsageService.onTokenUsageUpdated(data => {
|
|
47
|
+
this.items = data;
|
|
48
|
+
this.update();
|
|
49
|
+
})
|
|
50
|
+
);
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
protected async
|
|
53
|
+
protected async loadItems(): Promise<void> {
|
|
56
54
|
try {
|
|
57
|
-
this.
|
|
58
|
-
this.update();
|
|
55
|
+
this.items = await this.tokenUsageService.getTokenUsageData();
|
|
59
56
|
} catch (error) {
|
|
60
57
|
this.messageService.error(nls.localize('theia/ai/tokenUsage/failedToGetTokenUsageData', 'Failed to fetch token usage data: {0}', error));
|
|
61
58
|
}
|
|
62
59
|
}
|
|
63
60
|
|
|
61
|
+
protected getItemId(item: ModelTokenUsageData): string {
|
|
62
|
+
return item.modelId;
|
|
63
|
+
}
|
|
64
|
+
|
|
64
65
|
protected formatNumber(num: number): string {
|
|
65
66
|
return num.toLocaleString();
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
protected formatDate(date?: Date): string {
|
|
69
70
|
if (!date) {
|
|
70
|
-
return nls.
|
|
71
|
+
return nls.localizeByDefault('Never');
|
|
71
72
|
}
|
|
72
73
|
return formatDistanceToNow(date, { addSuffix: true });
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
protected hasCacheData(): boolean {
|
|
76
|
-
return this.
|
|
77
|
+
return this.items.some(model =>
|
|
77
78
|
model.cachedInputTokens !== undefined ||
|
|
78
79
|
model.readCachedInputTokens !== undefined
|
|
79
80
|
);
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
protected
|
|
83
|
+
protected getColumns(): TableColumn<ModelTokenUsageData>[] {
|
|
83
84
|
const showCacheColumns = this.hasCacheData();
|
|
85
|
+
const columns: TableColumn<ModelTokenUsageData>[] = [
|
|
86
|
+
{
|
|
87
|
+
id: 'model',
|
|
88
|
+
label: nls.localize('theia/ai/tokenUsage/model', 'Model'),
|
|
89
|
+
className: 'token-usage-model-column',
|
|
90
|
+
renderCell: item => <span>{item.modelId}</span>
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: 'input-tokens',
|
|
94
|
+
label: nls.localize('theia/ai/tokenUsage/inputTokens', 'Input Tokens'),
|
|
95
|
+
className: 'token-usage-column',
|
|
96
|
+
renderCell: item => <span>{this.formatNumber(item.inputTokens)}</span>
|
|
97
|
+
}
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
if (showCacheColumns) {
|
|
101
|
+
columns.push(
|
|
102
|
+
{
|
|
103
|
+
id: 'cached-input-tokens',
|
|
104
|
+
label: nls.localize('theia/ai/tokenUsage/cachedInputTokens', 'Input Tokens Written to Cache'),
|
|
105
|
+
className: 'token-usage-column',
|
|
106
|
+
renderCell: item => (
|
|
107
|
+
<span title={nls.localize(
|
|
108
|
+
'theia/ai/tokenUsage/cachedInputTokensTooltip',
|
|
109
|
+
"Tracked additionally to 'Input Tokens'. Usually more expensive than non-cached tokens."
|
|
110
|
+
)}>
|
|
111
|
+
{item.cachedInputTokens !== undefined ? this.formatNumber(item.cachedInputTokens) : '-'}
|
|
112
|
+
</span>
|
|
113
|
+
)
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: 'read-cached-input-tokens',
|
|
117
|
+
label: nls.localize('theia/ai/tokenUsage/readCachedInputTokens', 'Input Tokens Read From Cache'),
|
|
118
|
+
className: 'token-usage-column',
|
|
119
|
+
renderCell: item => (
|
|
120
|
+
<span title={nls.localize(
|
|
121
|
+
'theia/ai/tokenUsage/readCachedInputTokensTooltip',
|
|
122
|
+
"Tracked additionally to 'Input Token'. Usually much less expensive than not cached. Usually does not count to rate limits."
|
|
123
|
+
)}>
|
|
124
|
+
{item.readCachedInputTokens !== undefined ? this.formatNumber(item.readCachedInputTokens) : '-'}
|
|
125
|
+
</span>
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
}
|
|
84
130
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
)}
|
|
116
|
-
>
|
|
117
|
-
{nls.localize('theia/ai/tokenUsage/totalTokens', 'Total Tokens')}
|
|
118
|
-
</th>
|
|
119
|
-
<th className="token-usage-column">{nls.localize('theia/ai/tokenUsage/lastUsed', 'Last Used')}</th>
|
|
120
|
-
</tr >
|
|
131
|
+
columns.push(
|
|
132
|
+
{
|
|
133
|
+
id: 'output-tokens',
|
|
134
|
+
label: nls.localize('theia/ai/tokenUsage/outputTokens', 'Output Tokens'),
|
|
135
|
+
className: 'token-usage-column',
|
|
136
|
+
renderCell: item => <span>{this.formatNumber(item.outputTokens)}</span>
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: 'total-tokens',
|
|
140
|
+
label: nls.localize('theia/ai/tokenUsage/totalTokens', 'Total Tokens'),
|
|
141
|
+
className: 'token-usage-column',
|
|
142
|
+
renderCell: item => {
|
|
143
|
+
const totalTokens = item.inputTokens + item.outputTokens + (item.cachedInputTokens ?? 0);
|
|
144
|
+
return (
|
|
145
|
+
<span title={nls.localize('theia/ai/tokenUsage/totalTokensTooltip', "'Input Tokens' + 'Output Tokens'")}>
|
|
146
|
+
{this.formatNumber(totalTokens)}
|
|
147
|
+
</span>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
id: 'last-used',
|
|
153
|
+
label: nls.localize('theia/ai/tokenUsage/lastUsed', 'Last Used'),
|
|
154
|
+
className: 'token-usage-column',
|
|
155
|
+
renderCell: item => {
|
|
156
|
+
const lastUsedDate = item.lastUsed ? new Date(item.lastUsed) : undefined;
|
|
157
|
+
const exactDateString = lastUsedDate ? lastUsedDate.toLocaleString() : '';
|
|
158
|
+
return <span title={exactDateString}>{this.formatDate(lastUsedDate)}</span>;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
121
161
|
);
|
|
122
|
-
}
|
|
123
162
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const exactDateString = lastUsedDate ? lastUsedDate.toLocaleString() : '';
|
|
127
|
-
const showCacheColumns = this.hasCacheData();
|
|
128
|
-
const totalTokens = model.inputTokens + model.outputTokens + (model.cachedInputTokens ?? 0);
|
|
163
|
+
return columns;
|
|
164
|
+
}
|
|
129
165
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
<td className="token-usage-model-cell">{model.modelId}</td>
|
|
133
|
-
<td className="token-usage-cell">{this.formatNumber(model.inputTokens)}</td>
|
|
134
|
-
{showCacheColumns && (
|
|
135
|
-
<>
|
|
136
|
-
<td className="token-usage-cell">{model.cachedInputTokens !== undefined ? this.formatNumber(model.cachedInputTokens) : '-'}</td>
|
|
137
|
-
<td className="token-usage-cell">{model.readCachedInputTokens !== undefined ? this.formatNumber(model.readCachedInputTokens) : '-'}</td>
|
|
138
|
-
</>
|
|
139
|
-
)}
|
|
140
|
-
<td className="token-usage-cell">{this.formatNumber(model.outputTokens)}</td>
|
|
141
|
-
<td className="token-usage-cell">{this.formatNumber(totalTokens)}</td>
|
|
142
|
-
<td className="token-usage-cell" title={exactDateString}>{this.formatDate(lastUsedDate)}</td>
|
|
143
|
-
</tr>
|
|
144
|
-
);
|
|
166
|
+
protected override renderHeader(): React.ReactNode {
|
|
167
|
+
return undefined;
|
|
145
168
|
}
|
|
146
169
|
|
|
147
|
-
protected
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
170
|
+
protected override renderFooter(): React.ReactNode {
|
|
171
|
+
if (this.items.length === 0) {
|
|
172
|
+
return (
|
|
173
|
+
<div className="ai-empty-state-content">
|
|
174
|
+
<p>{nls.localize('theia/ai/tokenUsage/noData', 'No token usage data available yet.')}</p>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
151
177
|
}
|
|
152
178
|
|
|
153
|
-
const totalInputTokens = this.tokenUsageData.reduce((sum, model) => sum + model.inputTokens, 0);
|
|
154
|
-
const totalOutputTokens = this.tokenUsageData.reduce((sum, model) => sum + model.outputTokens, 0);
|
|
155
|
-
const totalCachedInputTokens = this.tokenUsageData.reduce(
|
|
156
|
-
(sum, model) => sum + (model.cachedInputTokens || 0), 0
|
|
157
|
-
);
|
|
158
|
-
const totalReadCachedInputTokens = this.tokenUsageData.reduce(
|
|
159
|
-
(sum, model) => sum + (model.readCachedInputTokens || 0), 0
|
|
160
|
-
);
|
|
161
|
-
const totalTokens = totalInputTokens + totalCachedInputTokens + totalOutputTokens;
|
|
162
|
-
|
|
163
179
|
const showCacheColumns = this.hasCacheData();
|
|
180
|
+
const totalInputTokens = this.items.reduce((sum, model) => sum + model.inputTokens, 0);
|
|
181
|
+
const totalOutputTokens = this.items.reduce((sum, model) => sum + model.outputTokens, 0);
|
|
182
|
+
const totalCachedInputTokens = this.items.reduce((sum, model) => sum + (model.cachedInputTokens || 0), 0);
|
|
183
|
+
const totalReadCachedInputTokens = this.items.reduce((sum, model) => sum + (model.readCachedInputTokens || 0), 0);
|
|
184
|
+
const totalTokens = totalInputTokens + totalCachedInputTokens + totalOutputTokens;
|
|
164
185
|
|
|
165
186
|
return (
|
|
166
|
-
<
|
|
167
|
-
<
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
<div className="token-usage-table-container">
|
|
188
|
-
{this.tokenUsageData.length > 0 ? (
|
|
189
|
-
<table className="token-usage-table">
|
|
190
|
-
<thead>
|
|
191
|
-
{this.renderHeaderRow()}
|
|
192
|
-
</thead>
|
|
193
|
-
<tbody>
|
|
194
|
-
{this.tokenUsageData.map(model => this.renderModelRow(model))}
|
|
195
|
-
{this.renderSummaryRow()}
|
|
196
|
-
</tbody>
|
|
197
|
-
</table>
|
|
198
|
-
) : (
|
|
199
|
-
<div className="token-usage-empty">
|
|
200
|
-
<p>{nls.localize('theia/ai/tokenUsage/noData', 'No token usage data available yet.')}</p>
|
|
201
|
-
</div>
|
|
202
|
-
)}
|
|
203
|
-
</div>
|
|
204
|
-
|
|
205
|
-
<div className="token-usage-notes">
|
|
206
|
-
<p className="token-usage-note">
|
|
207
|
-
<i className="codicon codicon-info"></i>
|
|
187
|
+
<div className="ai-configuration-footer-total">
|
|
188
|
+
<table className="ai-configuration-table">
|
|
189
|
+
<tfoot>
|
|
190
|
+
<tr className="ai-configuration-footer-total-row">
|
|
191
|
+
<td className="token-usage-model-column">{nls.localize('theia/ai/tokenUsage/total', 'Total')}</td>
|
|
192
|
+
<td className="token-usage-column">{this.formatNumber(totalInputTokens)}</td>
|
|
193
|
+
{showCacheColumns && (
|
|
194
|
+
<>
|
|
195
|
+
<td className="token-usage-column">{this.formatNumber(totalCachedInputTokens)}</td>
|
|
196
|
+
<td className="token-usage-column">{this.formatNumber(totalReadCachedInputTokens)}</td>
|
|
197
|
+
</>
|
|
198
|
+
)}
|
|
199
|
+
<td className="token-usage-column">{this.formatNumber(totalOutputTokens)}</td>
|
|
200
|
+
<td className="token-usage-column">{this.formatNumber(totalTokens)}</td>
|
|
201
|
+
<td className="token-usage-column"></td>
|
|
202
|
+
</tr>
|
|
203
|
+
</tfoot>
|
|
204
|
+
</table>
|
|
205
|
+
<div className="ai-configuration-info-box">
|
|
206
|
+
<p className="ai-configuration-info-text">
|
|
207
|
+
<i className="codicon codicon-info ai-configuration-info-icon"></i>
|
|
208
208
|
{nls.localize('theia/ai/tokenUsage/note', 'Token usage is tracked since the start of the application and is not persisted.')}
|
|
209
209
|
</p>
|
|
210
210
|
</div>
|