@theia/ai-core-ui 1.75.0-next.8 → 1.75.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.
Files changed (113) hide show
  1. package/lib/browser/ai-configuration/ai-configuration-category-registry.d.ts +29 -0
  2. package/lib/browser/ai-configuration/ai-configuration-category-registry.d.ts.map +1 -0
  3. package/lib/browser/ai-configuration/ai-configuration-category-registry.js +83 -0
  4. package/lib/browser/ai-configuration/ai-configuration-category-registry.js.map +1 -0
  5. package/lib/browser/ai-configuration/ai-configuration-category-registry.spec.d.ts +2 -0
  6. package/lib/browser/ai-configuration/ai-configuration-category-registry.spec.d.ts.map +1 -0
  7. package/lib/browser/ai-configuration/ai-configuration-category-registry.spec.js +122 -0
  8. package/lib/browser/ai-configuration/ai-configuration-category-registry.spec.js.map +1 -0
  9. package/lib/browser/ai-configuration/ai-configuration-category.d.ts +204 -0
  10. package/lib/browser/ai-configuration/ai-configuration-category.d.ts.map +1 -0
  11. package/lib/browser/ai-configuration/ai-configuration-category.js +86 -0
  12. package/lib/browser/ai-configuration/ai-configuration-category.js.map +1 -0
  13. package/lib/browser/ai-configuration/ai-configuration-selection-model.d.ts +15 -0
  14. package/lib/browser/ai-configuration/ai-configuration-selection-model.d.ts.map +1 -0
  15. package/lib/browser/ai-configuration/ai-configuration-selection-model.js +44 -0
  16. package/lib/browser/ai-configuration/ai-configuration-selection-model.js.map +1 -0
  17. package/lib/browser/ai-configuration/ai-configuration-setting-commands.d.ts +48 -0
  18. package/lib/browser/ai-configuration/ai-configuration-setting-commands.d.ts.map +1 -0
  19. package/lib/browser/ai-configuration/ai-configuration-setting-commands.js +98 -0
  20. package/lib/browser/ai-configuration/ai-configuration-setting-commands.js.map +1 -0
  21. package/lib/browser/ai-configuration/ai-configuration-setting-commands.spec.d.ts +2 -0
  22. package/lib/browser/ai-configuration/ai-configuration-setting-commands.spec.d.ts.map +1 -0
  23. package/lib/browser/ai-configuration/ai-configuration-setting-commands.spec.js +70 -0
  24. package/lib/browser/ai-configuration/ai-configuration-setting-commands.spec.js.map +1 -0
  25. package/lib/browser/ai-configuration/components/ai-configuration-components.spec.d.ts +2 -0
  26. package/lib/browser/ai-configuration/components/ai-configuration-components.spec.d.ts.map +1 -0
  27. package/lib/browser/ai-configuration/components/ai-configuration-components.spec.js +596 -0
  28. package/lib/browser/ai-configuration/components/ai-configuration-components.spec.js.map +1 -0
  29. package/lib/browser/ai-configuration/components/ai-configuration-controls.d.ts +118 -0
  30. package/lib/browser/ai-configuration/components/ai-configuration-controls.d.ts.map +1 -0
  31. package/lib/browser/ai-configuration/components/ai-configuration-controls.js +191 -0
  32. package/lib/browser/ai-configuration/components/ai-configuration-controls.js.map +1 -0
  33. package/lib/browser/ai-configuration/components/ai-configuration-item-row.d.ts +57 -0
  34. package/lib/browser/ai-configuration/components/ai-configuration-item-row.d.ts.map +1 -0
  35. package/lib/browser/ai-configuration/components/ai-configuration-item-row.js +48 -0
  36. package/lib/browser/ai-configuration/components/ai-configuration-item-row.js.map +1 -0
  37. package/lib/browser/ai-configuration/components/ai-configuration-origin-badge.d.ts +49 -0
  38. package/lib/browser/ai-configuration/components/ai-configuration-origin-badge.d.ts.map +1 -0
  39. package/lib/browser/ai-configuration/components/ai-configuration-origin-badge.js +79 -0
  40. package/lib/browser/ai-configuration/components/ai-configuration-origin-badge.js.map +1 -0
  41. package/lib/browser/ai-configuration/components/ai-configuration-primitives.d.ts +161 -0
  42. package/lib/browser/ai-configuration/components/ai-configuration-primitives.d.ts.map +1 -0
  43. package/lib/browser/ai-configuration/components/ai-configuration-primitives.js +131 -0
  44. package/lib/browser/ai-configuration/components/ai-configuration-primitives.js.map +1 -0
  45. package/lib/browser/ai-configuration/components/ai-configuration-setting-row.d.ts +54 -0
  46. package/lib/browser/ai-configuration/components/ai-configuration-setting-row.d.ts.map +1 -0
  47. package/lib/browser/ai-configuration/components/ai-configuration-setting-row.js +77 -0
  48. package/lib/browser/ai-configuration/components/ai-configuration-setting-row.js.map +1 -0
  49. package/lib/browser/ai-configuration/components/ai-settings-row-service.d.ts +194 -0
  50. package/lib/browser/ai-configuration/components/ai-settings-row-service.d.ts.map +1 -0
  51. package/lib/browser/ai-configuration/components/ai-settings-row-service.js +352 -0
  52. package/lib/browser/ai-configuration/components/ai-settings-row-service.js.map +1 -0
  53. package/lib/browser/ai-configuration/components/ai-settings-row-service.spec.d.ts +2 -0
  54. package/lib/browser/ai-configuration/components/ai-settings-row-service.spec.d.ts.map +1 -0
  55. package/lib/browser/ai-configuration/components/ai-settings-row-service.spec.js +233 -0
  56. package/lib/browser/ai-configuration/components/ai-settings-row-service.spec.js.map +1 -0
  57. package/lib/browser/ai-configuration/components/ai-settings-row.d.ts +50 -0
  58. package/lib/browser/ai-configuration/components/ai-settings-row.d.ts.map +1 -0
  59. package/lib/browser/ai-configuration/components/ai-settings-row.js +85 -0
  60. package/lib/browser/ai-configuration/components/ai-settings-row.js.map +1 -0
  61. package/lib/browser/ai-configuration/components/collapsible-list.d.ts +65 -0
  62. package/lib/browser/ai-configuration/components/collapsible-list.d.ts.map +1 -0
  63. package/lib/browser/ai-configuration/components/collapsible-list.js +82 -0
  64. package/lib/browser/ai-configuration/components/collapsible-list.js.map +1 -0
  65. package/lib/browser/ai-configuration/components/prompt-customization-dialogs.d.ts +35 -0
  66. package/lib/browser/ai-configuration/components/prompt-customization-dialogs.d.ts.map +1 -0
  67. package/lib/browser/ai-configuration/components/prompt-customization-dialogs.js +83 -0
  68. package/lib/browser/ai-configuration/components/prompt-customization-dialogs.js.map +1 -0
  69. package/lib/browser/ai-configuration/components/variant-set-card.d.ts +25 -0
  70. package/lib/browser/ai-configuration/components/variant-set-card.d.ts.map +1 -0
  71. package/lib/browser/ai-configuration/components/variant-set-card.js +133 -0
  72. package/lib/browser/ai-configuration/components/variant-set-card.js.map +1 -0
  73. package/lib/browser/ai-configuration/renderers/collection-category-renderer.d.ts +44 -0
  74. package/lib/browser/ai-configuration/renderers/collection-category-renderer.d.ts.map +1 -0
  75. package/lib/browser/ai-configuration/renderers/collection-category-renderer.js +106 -0
  76. package/lib/browser/ai-configuration/renderers/collection-category-renderer.js.map +1 -0
  77. package/lib/browser/ai-configuration/renderers/collection-category-renderer.spec.d.ts +2 -0
  78. package/lib/browser/ai-configuration/renderers/collection-category-renderer.spec.d.ts.map +1 -0
  79. package/lib/browser/ai-configuration/renderers/collection-category-renderer.spec.js +120 -0
  80. package/lib/browser/ai-configuration/renderers/collection-category-renderer.spec.js.map +1 -0
  81. package/lib/browser/ai-configuration/renderers/single-page-category-renderer.d.ts +15 -0
  82. package/lib/browser/ai-configuration/renderers/single-page-category-renderer.d.ts.map +1 -0
  83. package/lib/browser/ai-configuration/renderers/single-page-category-renderer.js +20 -0
  84. package/lib/browser/ai-configuration/renderers/single-page-category-renderer.js.map +1 -0
  85. package/lib/browser/ai-core-ui-frontend-module.d.ts +1 -0
  86. package/lib/browser/ai-core-ui-frontend-module.d.ts.map +1 -1
  87. package/lib/browser/ai-core-ui-frontend-module.js +11 -0
  88. package/lib/browser/ai-core-ui-frontend-module.js.map +1 -1
  89. package/package.json +6 -5
  90. package/src/browser/ai-configuration/ai-configuration-category-registry.spec.ts +137 -0
  91. package/src/browser/ai-configuration/ai-configuration-category-registry.ts +79 -0
  92. package/src/browser/ai-configuration/ai-configuration-category.ts +246 -0
  93. package/src/browser/ai-configuration/ai-configuration-selection-model.ts +42 -0
  94. package/src/browser/ai-configuration/ai-configuration-setting-commands.spec.ts +82 -0
  95. package/src/browser/ai-configuration/ai-configuration-setting-commands.ts +104 -0
  96. package/src/browser/ai-configuration/components/ai-configuration-components.spec.ts +655 -0
  97. package/src/browser/ai-configuration/components/ai-configuration-controls.tsx +382 -0
  98. package/src/browser/ai-configuration/components/ai-configuration-item-row.tsx +127 -0
  99. package/src/browser/ai-configuration/components/ai-configuration-origin-badge.tsx +114 -0
  100. package/src/browser/ai-configuration/components/ai-configuration-primitives.tsx +359 -0
  101. package/src/browser/ai-configuration/components/ai-configuration-setting-row.tsx +154 -0
  102. package/src/browser/ai-configuration/components/ai-settings-row-service.spec.ts +275 -0
  103. package/src/browser/ai-configuration/components/ai-settings-row-service.ts +401 -0
  104. package/src/browser/ai-configuration/components/ai-settings-row.tsx +176 -0
  105. package/src/browser/ai-configuration/components/collapsible-list.tsx +205 -0
  106. package/src/browser/ai-configuration/components/prompt-customization-dialogs.ts +89 -0
  107. package/src/browser/ai-configuration/components/variant-set-card.tsx +200 -0
  108. package/src/browser/ai-configuration/renderers/collection-category-renderer.spec.ts +126 -0
  109. package/src/browser/ai-configuration/renderers/collection-category-renderer.tsx +164 -0
  110. package/src/browser/ai-configuration/renderers/single-page-category-renderer.tsx +41 -0
  111. package/src/browser/ai-core-ui-frontend-module.ts +14 -1
  112. package/src/browser/style/ai-configuration-components.css +1410 -0
  113. package/src/browser/style/index.css +17 -0
@@ -0,0 +1,126 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2026 EclipseSource and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
18
+ let disableJSDOM = enableJSDOM();
19
+
20
+ import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
21
+ FrontendApplicationConfigProvider.set({});
22
+
23
+ import { expect } from 'chai';
24
+ import * as React from '@theia/core/shared/react';
25
+ import { flushSync } from '@theia/core/shared/react-dom';
26
+ import { createRoot } from '@theia/core/shared/react-dom/client';
27
+ import { AiConfigurationRenderContext, AiConfigurationTreeItem } from '../ai-configuration-category';
28
+ import { CollectionCategoryRenderer } from './collection-category-renderer';
29
+
30
+ disableJSDOM();
31
+
32
+ describe('CollectionCategoryRenderer', () => {
33
+
34
+ before(() => disableJSDOM = enableJSDOM());
35
+ after(() => disableJSDOM());
36
+
37
+ class TestCollection extends CollectionCategoryRenderer {
38
+ constructor(protected readonly items: AiConfigurationTreeItem[]) {
39
+ super();
40
+ }
41
+ protected get categoryId(): string {
42
+ return 'agents';
43
+ }
44
+ getTreeChildren(): AiConfigurationTreeItem[] {
45
+ return this.items;
46
+ }
47
+ protected renderItemSections(): React.ReactNode {
48
+ return undefined;
49
+ }
50
+ protected override getEmptyMessage(): string {
51
+ return 'No agents';
52
+ }
53
+ }
54
+
55
+ function renderOverview(items: AiConfigurationTreeItem[]): { container: HTMLElement; warnings: string[]; dispose: () => void } {
56
+ // React reports duplicate keys through console.error; capture it so the test can assert on it, and
57
+ // capture console.warn too so the renderer's expected duplicate-id warning stays out of the output.
58
+ const warnings: string[] = [];
59
+ const originalError = console.error;
60
+ const originalWarn = console.warn;
61
+ console.error = (...args: unknown[]) => { warnings.push(String(args[0])); };
62
+ console.warn = (...args: unknown[]) => { warnings.push(String(args[0])); };
63
+ const container = document.createElement('div');
64
+ document.body.appendChild(container);
65
+ const root = createRoot(container);
66
+ const ctx: AiConfigurationRenderContext = { scope: 'user', navigate: () => { }, update: () => { } };
67
+ try {
68
+ flushSync(() => root.render(new TestCollection(items).renderOverview(ctx) as React.ReactElement));
69
+ } finally {
70
+ console.error = originalError;
71
+ console.warn = originalWarn;
72
+ }
73
+ return { container, warnings, dispose: () => { flushSync(() => root.unmount()); container.remove(); } };
74
+ }
75
+
76
+ it('shows one row per id, dropping an entry that repeats one', () => {
77
+ const { container, warnings, dispose } = renderOverview([
78
+ { id: 'code-reviewer', label: 'Code Reviewer' },
79
+ { id: 'code-reviewer', label: 'Code Reviewer (copy)' },
80
+ { id: 'coder', label: 'Coder' }
81
+ ]);
82
+ try {
83
+ const labels = Array.from(container.querySelectorAll('.ai-configuration-item-row-label')).map(label => label.textContent);
84
+ // The first wins: a repeated id is not addressable, so showing it would be a row that opens another.
85
+ expect(labels).to.deep.equal(['Code Reviewer', 'Coder']);
86
+ // And no React duplicate-key warnings, which is what a rendered duplicate produced.
87
+ expect(warnings.filter(warning => warning.includes('same key'))).to.be.empty;
88
+ } finally {
89
+ dispose();
90
+ }
91
+ });
92
+
93
+ it('logs the dropped id once, however often the overview re-renders', () => {
94
+ const items: AiConfigurationTreeItem[] = [
95
+ { id: 'code-reviewer', label: 'Code Reviewer' },
96
+ { id: 'code-reviewer', label: 'Code Reviewer (copy)' }
97
+ ];
98
+ const collection = new TestCollection(items);
99
+ const ctx: AiConfigurationRenderContext = { scope: 'user', navigate: () => { }, update: () => { } };
100
+ const logged: string[] = [];
101
+ const originalWarn = console.warn;
102
+ console.warn = (...args: unknown[]) => { logged.push(String(args[0])); };
103
+ try {
104
+ collection.renderOverview(ctx);
105
+ collection.renderOverview(ctx);
106
+ } finally {
107
+ console.warn = originalWarn;
108
+ }
109
+
110
+ expect(logged).to.have.lengthOf(1);
111
+ expect(logged[0]).to.include('code-reviewer').and.to.include('agents');
112
+ });
113
+
114
+ it('leaves items with unique ids untouched, reporting their own status', () => {
115
+ const { container, dispose } = renderOverview([
116
+ { id: 'coder', label: 'Coder', status: { kind: 'on', label: 'Enabled' } },
117
+ { id: 'architect', label: 'Architect', status: { kind: 'off', label: 'Disabled' } }
118
+ ]);
119
+ try {
120
+ const badges = Array.from(container.querySelectorAll('.ai-configuration-status-badge-label')).map(badge => badge.textContent);
121
+ expect(badges).to.deep.equal(['Enabled', 'Disabled']);
122
+ } finally {
123
+ dispose();
124
+ }
125
+ });
126
+ });
@@ -0,0 +1,164 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2026 EclipseSource and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { nls } from '@theia/core';
18
+ import * as React from '@theia/core/shared/react';
19
+ import {
20
+ AiConfigurationAddDescriptor,
21
+ AiConfigurationCategoryRenderer,
22
+ AiConfigurationRenderContext,
23
+ AiConfigurationTreeItem
24
+ } from '../ai-configuration-category';
25
+
26
+ // The descriptor moved to the contribution point (the tree renders the action too); re-exported so the
27
+ // categories that build one keep importing it from the base class they extend.
28
+ export { AiConfigurationAddDescriptor };
29
+ import {
30
+ AiConfigurationAddAction,
31
+ AiConfigurationEmptyState,
32
+ AiConfigurationItemDetailHeader,
33
+ AiConfigurationSection
34
+ } from '../components/ai-configuration-primitives';
35
+ import { AiConfigurationItemRow } from '../components/ai-configuration-item-row';
36
+
37
+ /** Describes the overview's "Add …" affordance. */
38
+ /**
39
+ * Convenience base for `collection` categories. Renders the overview (category
40
+ * settings slot + item card grid + add action + empty state) and the per-item
41
+ * detail frame (header + sections). Subclasses provide the items, the item
42
+ * sections, and optionally category-level settings and an add action.
43
+ */
44
+ export abstract class CollectionCategoryRenderer implements AiConfigurationCategoryRenderer {
45
+
46
+ /** The owning category id, used to build navigation targets for the cards. */
47
+ protected abstract get categoryId(): string;
48
+
49
+ /** Ids already reported as duplicated, so the warning is logged once rather than on every render. */
50
+ protected readonly reportedDuplicateIds = new Set<string>();
51
+
52
+ abstract getTreeChildren(): AiConfigurationTreeItem[];
53
+
54
+ renderOverview(ctx: AiConfigurationRenderContext): React.ReactNode {
55
+ const items = this.addressableItems(this.getTreeChildren());
56
+ const add = this.getAddAction(ctx);
57
+ const addAction = add && <AiConfigurationAddAction label={add.label} iconClass={add.iconClass} onClick={() => add.run()} />;
58
+ const body = items.length === 0
59
+ ? <AiConfigurationEmptyState message={this.getEmptyMessage()} action={addAction} />
60
+ : <>
61
+ <div className='ai-configuration-item-list'>
62
+ {items.map(item => <AiConfigurationItemRow
63
+ key={item.id}
64
+ label={item.label}
65
+ iconClass={item.iconClass}
66
+ description={item.description}
67
+ tags={item.tags}
68
+ origins={item.origins}
69
+ status={item.status}
70
+ onSelect={() => ctx.navigate({ categoryId: this.categoryId, itemId: item.id })}
71
+ />)}
72
+ </div>
73
+ {addAction && <div className='ai-configuration-overview-actions'>{addAction}</div>}
74
+ </>;
75
+ const listTitle = this.overviewListTitle;
76
+ return <div className='ai-configuration-page'>
77
+ {this.renderCategorySettings(ctx)}
78
+ {listTitle !== undefined
79
+ // Foldable with its size on the header once there is a list to fold; an empty state stays plain.
80
+ ? <AiConfigurationSection
81
+ title={listTitle}
82
+ count={items.length > 0 ? items.length : undefined}
83
+ collapsible={items.length > 0}
84
+ >{body}</AiConfigurationSection>
85
+ : body}
86
+ </div>;
87
+ }
88
+
89
+ /**
90
+ * The items this page can actually address, i.e. one per id. Everything downstream keys on the id — the
91
+ * tree node, the navigation target, the detail lookup and the per-item settings — so an item repeating an
92
+ * id could neither be opened nor configured on its own; it is dropped here and logged once. Representing
93
+ * such a clash properly is a separate concern from this view (it starts where the items are registered).
94
+ */
95
+ protected addressableItems(items: AiConfigurationTreeItem[]): AiConfigurationTreeItem[] {
96
+ const byId = new Map<string, AiConfigurationTreeItem>();
97
+ for (const item of items) {
98
+ if (byId.has(item.id)) {
99
+ this.warnAboutDuplicateId(item.id);
100
+ continue;
101
+ }
102
+ byId.set(item.id, item);
103
+ }
104
+ return [...byId.values()];
105
+ }
106
+
107
+ /**
108
+ * Warns once per id, since the overview re-renders and would otherwise repeat itself indefinitely.
109
+ * `console` rather than an `ILogger`: this base class is not injectable, so it has no injection context
110
+ * of its own; subclasses that want their named logger can override this.
111
+ */
112
+ protected warnAboutDuplicateId(id: string): void {
113
+ if (this.reportedDuplicateIds.has(id)) {
114
+ return;
115
+ }
116
+ this.reportedDuplicateIds.add(id);
117
+ console.warn(`More than one entry of the AI configuration category "${this.categoryId}" declares the id "${id}". `
118
+ + 'Only the first is shown, since everything (navigation, settings) is keyed by that id. Give each entry a unique id.');
119
+ }
120
+
121
+ /** Optional heading shown above the item list (e.g. "Agents"), like the Providers page. None by default. */
122
+ protected get overviewListTitle(): string | undefined {
123
+ return undefined;
124
+ }
125
+
126
+ renderItemDetail(itemId: string, ctx: AiConfigurationRenderContext): React.ReactNode {
127
+ const item = this.getTreeChildren().find(child => child.id === itemId);
128
+ if (!item) {
129
+ return undefined;
130
+ }
131
+ return <div className='ai-configuration-page'>
132
+ {this.renderItemHeader(item, ctx)}
133
+ {this.renderItemSections(item, ctx)}
134
+ </div>;
135
+ }
136
+
137
+ /** Category-level settings shown above the card grid; nothing by default. */
138
+ protected renderCategorySettings(ctx: AiConfigurationRenderContext): React.ReactNode {
139
+ return undefined;
140
+ }
141
+
142
+ /** Header of an item detail page; icon/title/subtitle/origins from the item by default. */
143
+ protected renderItemHeader(item: AiConfigurationTreeItem, ctx: AiConfigurationRenderContext): React.ReactNode {
144
+ return <AiConfigurationItemDetailHeader
145
+ title={item.label}
146
+ iconClass={item.iconClass}
147
+ subtitle={item.description}
148
+ status={item.status}
149
+ origins={item.origins}
150
+ />;
151
+ }
152
+
153
+ /** Body of an item detail page: typically {@link AiConfigurationSection}s of rows. */
154
+ protected abstract renderItemSections(item: AiConfigurationTreeItem, ctx: AiConfigurationRenderContext): React.ReactNode;
155
+
156
+ /** The overview "Add …" affordance; none by default. */
157
+ getAddAction(ctx: AiConfigurationRenderContext): AiConfigurationAddDescriptor | undefined {
158
+ return undefined;
159
+ }
160
+
161
+ protected getEmptyMessage(): string {
162
+ return nls.localize('theia/ai/core/aiConfiguration/collectionEmpty', 'No items to configure yet.');
163
+ }
164
+ }
@@ -0,0 +1,41 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2026 EclipseSource and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import * as React from '@theia/core/shared/react';
18
+ import { AiConfigurationCategoryRenderer, AiConfigurationRenderContext } from '../ai-configuration-category';
19
+
20
+ /**
21
+ * Convenience base for `single-page` categories. Subclasses implement
22
+ * {@link renderSections} (and optionally {@link renderHeader}); the page frame
23
+ * and scrolling container are provided.
24
+ */
25
+ export abstract class SinglePageCategoryRenderer implements AiConfigurationCategoryRenderer {
26
+
27
+ renderPage(ctx: AiConfigurationRenderContext): React.ReactNode {
28
+ return <div className='ai-configuration-page'>
29
+ {this.renderHeader(ctx)}
30
+ {this.renderSections(ctx)}
31
+ </div>;
32
+ }
33
+
34
+ /** Optional page header (title/description); nothing by default. */
35
+ protected renderHeader(ctx: AiConfigurationRenderContext): React.ReactNode {
36
+ return undefined;
37
+ }
38
+
39
+ /** The page body: typically one or more {@link AiConfigurationSection}s of rows. */
40
+ protected abstract renderSections(ctx: AiConfigurationRenderContext): React.ReactNode;
41
+ }
@@ -14,12 +14,25 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
+ import '../../src/browser/style/index.css';
18
+
17
19
  import { ContainerModule } from '@theia/core/shared/inversify';
18
- import { PreferenceContribution } from '@theia/core';
20
+ import { bindRootContributionProvider, PreferenceContribution } from '@theia/core';
19
21
  import { AgentSettingsPreferenceSchema } from '@theia/ai-core/lib/common/agent-preferences';
20
22
  import { aiCorePreferenceSchema } from '@theia/ai-core/lib/common/ai-core-preferences';
23
+ import { AiConfigurationCategory } from './ai-configuration/ai-configuration-category';
24
+ import { AiConfigurationCategoryRegistry } from './ai-configuration/ai-configuration-category-registry';
25
+ import { AiConfigurationSelectionModel } from './ai-configuration/ai-configuration-selection-model';
26
+ import { AiSettingsRowService } from './ai-configuration/components/ai-settings-row-service';
27
+ import { bindAiConfigurationSettingCommands } from './ai-configuration/ai-configuration-setting-commands';
21
28
 
22
29
  export default new ContainerModule(bind => {
23
30
  bind(PreferenceContribution).toConstantValue({ schema: AgentSettingsPreferenceSchema });
24
31
  bind(PreferenceContribution).toConstantValue({ schema: aiCorePreferenceSchema });
32
+
33
+ bindRootContributionProvider(bind, AiConfigurationCategory);
34
+ bind(AiConfigurationCategoryRegistry).toSelf().inSingletonScope();
35
+ bind(AiConfigurationSelectionModel).toSelf().inSingletonScope();
36
+ bind(AiSettingsRowService).toSelf().inSingletonScope();
37
+ bindAiConfigurationSettingCommands(bind);
25
38
  });