@theia/ai-ide 1.71.0-next.72 → 1.71.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 (41) hide show
  1. package/lib/browser/frontend-module.d.ts.map +1 -1
  2. package/lib/browser/frontend-module.js +8 -0
  3. package/lib/browser/frontend-module.js.map +1 -1
  4. package/lib/browser/review/pr-review-agent.d.ts +19 -0
  5. package/lib/browser/review/pr-review-agent.d.ts.map +1 -0
  6. package/lib/browser/review/pr-review-agent.js +47 -0
  7. package/lib/browser/review/pr-review-agent.js.map +1 -0
  8. package/lib/browser/review/pr-review-prompt-template.d.ts +4 -0
  9. package/lib/browser/review/pr-review-prompt-template.d.ts.map +1 -0
  10. package/lib/browser/review/pr-review-prompt-template.js +437 -0
  11. package/lib/browser/review/pr-review-prompt-template.js.map +1 -0
  12. package/lib/browser/user-interaction-tool-renderer.d.ts +18 -0
  13. package/lib/browser/user-interaction-tool-renderer.d.ts.map +1 -0
  14. package/lib/browser/user-interaction-tool-renderer.js +330 -0
  15. package/lib/browser/user-interaction-tool-renderer.js.map +1 -0
  16. package/lib/browser/user-interaction-tool.d.ts +47 -0
  17. package/lib/browser/user-interaction-tool.d.ts.map +1 -0
  18. package/lib/browser/user-interaction-tool.js +397 -0
  19. package/lib/browser/user-interaction-tool.js.map +1 -0
  20. package/lib/browser/user-interaction-tool.spec.d.ts +2 -0
  21. package/lib/browser/user-interaction-tool.spec.d.ts.map +1 -0
  22. package/lib/browser/user-interaction-tool.spec.js +336 -0
  23. package/lib/browser/user-interaction-tool.spec.js.map +1 -0
  24. package/lib/common/user-interaction-tool.d.ts +53 -0
  25. package/lib/common/user-interaction-tool.d.ts.map +1 -0
  26. package/lib/common/user-interaction-tool.js +176 -0
  27. package/lib/common/user-interaction-tool.js.map +1 -0
  28. package/lib/common/user-interaction-tool.spec.d.ts +2 -0
  29. package/lib/common/user-interaction-tool.spec.d.ts.map +1 -0
  30. package/lib/common/user-interaction-tool.spec.js +216 -0
  31. package/lib/common/user-interaction-tool.spec.js.map +1 -0
  32. package/package.json +22 -22
  33. package/src/browser/frontend-module.ts +9 -0
  34. package/src/browser/review/pr-review-agent.ts +42 -0
  35. package/src/browser/review/pr-review-prompt-template.ts +449 -0
  36. package/src/browser/style/index.css +299 -0
  37. package/src/browser/user-interaction-tool-renderer.tsx +531 -0
  38. package/src/browser/user-interaction-tool.spec.ts +396 -0
  39. package/src/browser/user-interaction-tool.ts +423 -0
  40. package/src/common/user-interaction-tool.spec.ts +241 -0
  41. package/src/common/user-interaction-tool.ts +237 -0
@@ -0,0 +1,237 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2026 EclipseSource GmbH.
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/lib/common/nls';
18
+
19
+ export const USER_INTERACTION_FUNCTION_ID = 'userInteraction';
20
+
21
+ export interface EmptyContentRef {
22
+ empty: true;
23
+ label?: string;
24
+ }
25
+
26
+ export interface PathContentRef {
27
+ path: string;
28
+ gitRef?: string;
29
+ line?: number;
30
+ }
31
+
32
+ export type ContentRef = string | PathContentRef | EmptyContentRef;
33
+
34
+ export function isEmptyContentRef(ref: ContentRef): ref is EmptyContentRef {
35
+ return typeof ref === 'object' && 'empty' in ref && ref.empty === true;
36
+ }
37
+
38
+ export interface UserInteractionLink {
39
+ ref: ContentRef;
40
+ rightRef?: ContentRef;
41
+ label?: string;
42
+ autoOpen?: boolean;
43
+ }
44
+
45
+ export function resolveContentRef(ref: ContentRef): PathContentRef | EmptyContentRef {
46
+ if (typeof ref === 'string') {
47
+ return { path: ref };
48
+ }
49
+ return ref;
50
+ }
51
+
52
+ const SHA_PREFIX_LENGTH = 7;
53
+
54
+ function workingCopyLabel(): string {
55
+ return nls.localize('theia/ai-ide/userInteractionWorkingCopy', 'Working Copy');
56
+ }
57
+
58
+ function emptyLabel(): string {
59
+ return nls.localize('theia/ai-ide/userInteractionEmpty', 'Empty');
60
+ }
61
+
62
+ function gitRefTag(ref: PathContentRef): string {
63
+ return ref.gitRef ? ref.gitRef.substring(0, SHA_PREFIX_LENGTH) : workingCopyLabel();
64
+ }
65
+
66
+ export function buildDiffLabel(
67
+ left: PathContentRef | EmptyContentRef,
68
+ right: PathContentRef | EmptyContentRef
69
+ ): string {
70
+ const leftIsEmpty = isEmptyContentRef(left);
71
+ const rightIsEmpty = isEmptyContentRef(right);
72
+ if (leftIsEmpty && rightIsEmpty) {
73
+ return `${left.label || emptyLabel()} ⟷ ${right.label || emptyLabel()}`;
74
+ }
75
+ if (leftIsEmpty) {
76
+ return `${(right as PathContentRef).path} (${left.label || emptyLabel()} ⟷ ${gitRefTag(right as PathContentRef)})`;
77
+ }
78
+ if (rightIsEmpty) {
79
+ return `${(left as PathContentRef).path} (${gitRefTag(left as PathContentRef)} ⟷ ${right.label || emptyLabel()})`;
80
+ }
81
+ const leftPath = left as PathContentRef;
82
+ const rightPath = right as PathContentRef;
83
+ if (leftPath.path === rightPath.path) {
84
+ return `${leftPath.path} (${gitRefTag(leftPath)} ⟷ ${gitRefTag(rightPath)})`;
85
+ }
86
+ return `${leftPath.path} ⟷ ${rightPath.path}`;
87
+ }
88
+
89
+ export interface UserInteractionOption {
90
+ text: string;
91
+ value: string;
92
+ description?: string;
93
+ buttonLabel?: string;
94
+ }
95
+
96
+ export interface UserInteractionStep {
97
+ title: string;
98
+ message: string;
99
+ options?: UserInteractionOption[];
100
+ links?: UserInteractionLink[];
101
+ }
102
+
103
+ export interface UserInteractionStepResult {
104
+ title: string;
105
+ value?: string;
106
+ comments?: string[];
107
+ skipped?: boolean;
108
+ }
109
+
110
+ export interface UserInteractionResult {
111
+ completed: boolean;
112
+ steps: UserInteractionStepResult[];
113
+ }
114
+
115
+ export interface UserInteractionArgs {
116
+ interactions: UserInteractionStep[];
117
+ }
118
+
119
+ export interface UserInteractionInput {
120
+ title: string;
121
+ stepCount: number;
122
+ }
123
+
124
+ export function parseUserInteractionInput(args: string | undefined): UserInteractionInput {
125
+ if (!args) {
126
+ return { title: '', stepCount: 0 };
127
+ }
128
+ try {
129
+ const parsed = JSON.parse(args);
130
+ const interactions = Array.isArray(parsed.interactions) ? parsed.interactions : [];
131
+ const firstTitle = typeof interactions[0]?.title === 'string' ? interactions[0].title : '';
132
+ return { title: firstTitle, stepCount: interactions.length };
133
+ } catch {
134
+ const match = /"title"\s*:\s*"([^"]*)"?/.exec(args);
135
+ return { title: match?.[1] ?? '', stepCount: 0 };
136
+ }
137
+ }
138
+
139
+ export function parseUserInteractionResult(raw: unknown): UserInteractionResult | undefined {
140
+ let candidate: unknown = raw;
141
+ if (typeof raw === 'string') {
142
+ try {
143
+ candidate = JSON.parse(raw);
144
+ } catch {
145
+ return undefined;
146
+ }
147
+ }
148
+ if (!candidate || typeof candidate !== 'object') {
149
+ return undefined;
150
+ }
151
+ const obj = candidate as Record<string, unknown>;
152
+ if (typeof obj.completed !== 'boolean' || !Array.isArray(obj.steps)) {
153
+ return undefined;
154
+ }
155
+ return obj as unknown as UserInteractionResult;
156
+ }
157
+
158
+ export function parseUserInteractionArgs(args: string | undefined): UserInteractionArgs | undefined {
159
+ if (!args) {
160
+ return undefined;
161
+ }
162
+ try {
163
+ const parsed = JSON.parse(args);
164
+ if (!Array.isArray(parsed.interactions)) {
165
+ return undefined;
166
+ }
167
+ const validSteps = parsed.interactions
168
+ .map(parseStep)
169
+ .filter((step: UserInteractionStep | undefined): step is UserInteractionStep => step !== undefined);
170
+ if (validSteps.length === 0) {
171
+ return undefined;
172
+ }
173
+ return { interactions: validSteps };
174
+ } catch {
175
+ return undefined;
176
+ }
177
+ }
178
+
179
+ function parseStep(raw: unknown): UserInteractionStep | undefined {
180
+ if (!raw || typeof raw !== 'object') {
181
+ return undefined;
182
+ }
183
+ const obj = raw as Record<string, unknown>;
184
+ if (typeof obj.title !== 'string' || typeof obj.message !== 'string') {
185
+ return undefined;
186
+ }
187
+ let options: UserInteractionOption[] | undefined;
188
+ if (Array.isArray(obj.options)) {
189
+ const validOptions = obj.options.filter(
190
+ (opt: unknown) => !!opt && typeof opt === 'object'
191
+ && typeof (opt as Record<string, unknown>).text === 'string'
192
+ && typeof (opt as Record<string, unknown>).value === 'string'
193
+ ) as UserInteractionOption[];
194
+ options = validOptions.length > 0 ? validOptions : undefined;
195
+ }
196
+ let links: UserInteractionLink[] | undefined;
197
+ if (Array.isArray(obj.links)) {
198
+ const filtered = obj.links.filter(isValidLink) as UserInteractionLink[];
199
+ links = filtered.length > 0 ? filtered : undefined;
200
+ } else if (isValidLink(obj.link)) {
201
+ links = [obj.link as UserInteractionLink];
202
+ }
203
+ return {
204
+ title: obj.title,
205
+ message: obj.message,
206
+ options,
207
+ links
208
+ };
209
+ }
210
+
211
+ function isValidContentRef(ref: unknown): ref is ContentRef {
212
+ if (typeof ref === 'string') {
213
+ return ref.length > 0;
214
+ }
215
+ if (ref && typeof ref === 'object') {
216
+ const obj = ref as Record<string, unknown>;
217
+ if (obj.empty === true) {
218
+ return true;
219
+ }
220
+ return typeof obj.path === 'string' && obj.path.length > 0;
221
+ }
222
+ return false;
223
+ }
224
+
225
+ function isValidLink(link: unknown): link is UserInteractionLink {
226
+ if (!link || typeof link !== 'object') {
227
+ return false;
228
+ }
229
+ const obj = link as Record<string, unknown>;
230
+ if (!isValidContentRef(obj.ref)) {
231
+ return false;
232
+ }
233
+ if (obj.rightRef !== undefined && !isValidContentRef(obj.rightRef)) {
234
+ return false;
235
+ }
236
+ return true;
237
+ }