@theia/ai-ide 1.65.0-next.6 → 1.65.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 (116) hide show
  1. package/lib/browser/ai-configuration/agent-configuration-widget.d.ts +13 -3
  2. package/lib/browser/ai-configuration/agent-configuration-widget.d.ts.map +1 -1
  3. package/lib/browser/ai-configuration/agent-configuration-widget.js +72 -38
  4. package/lib/browser/ai-configuration/agent-configuration-widget.js.map +1 -1
  5. package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.d.ts.map +1 -1
  6. package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js +3 -6
  7. package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js.map +1 -1
  8. package/lib/browser/ai-configuration/tools-configuration-widget.d.ts +4 -2
  9. package/lib/browser/ai-configuration/tools-configuration-widget.d.ts.map +1 -1
  10. package/lib/browser/ai-configuration/tools-configuration-widget.js +6 -4
  11. package/lib/browser/ai-configuration/tools-configuration-widget.js.map +1 -1
  12. package/lib/browser/ai-ide-activation-service.d.ts +2 -2
  13. package/lib/browser/ai-ide-activation-service.d.ts.map +1 -1
  14. package/lib/browser/ai-ide-activation-service.js +2 -3
  15. package/lib/browser/ai-ide-activation-service.js.map +1 -1
  16. package/lib/browser/app-tester-chat-agent.d.ts +1 -1
  17. package/lib/browser/app-tester-chat-agent.d.ts.map +1 -1
  18. package/lib/browser/app-tester-chat-agent.js +4 -4
  19. package/lib/browser/app-tester-chat-agent.js.map +1 -1
  20. package/lib/browser/app-tester-prompt-template.d.ts.map +1 -1
  21. package/lib/browser/app-tester-prompt-template.js +5 -1
  22. package/lib/browser/app-tester-prompt-template.js.map +1 -1
  23. package/lib/browser/architect-agent.d.ts +0 -1
  24. package/lib/browser/architect-agent.d.ts.map +1 -1
  25. package/lib/browser/architect-agent.js +0 -2
  26. package/lib/browser/architect-agent.js.map +1 -1
  27. package/lib/browser/coder-agent.d.ts +0 -1
  28. package/lib/browser/coder-agent.d.ts.map +1 -1
  29. package/lib/browser/coder-agent.js +0 -3
  30. package/lib/browser/coder-agent.js.map +1 -1
  31. package/lib/browser/file-changeset-functions.d.ts.map +1 -1
  32. package/lib/browser/file-changeset-functions.js +2 -1
  33. package/lib/browser/file-changeset-functions.js.map +1 -1
  34. package/lib/browser/frontend-module.d.ts.map +1 -1
  35. package/lib/browser/frontend-module.js +7 -6
  36. package/lib/browser/frontend-module.js.map +1 -1
  37. package/lib/browser/task-context-file-storage-service.d.ts +3 -3
  38. package/lib/browser/task-context-file-storage-service.d.ts.map +1 -1
  39. package/lib/browser/task-context-file-storage-service.js +5 -5
  40. package/lib/browser/task-context-file-storage-service.js.map +1 -1
  41. package/lib/browser/template-preference-contribution.d.ts +2 -1
  42. package/lib/browser/template-preference-contribution.d.ts.map +1 -1
  43. package/lib/browser/template-preference-contribution.js +5 -6
  44. package/lib/browser/template-preference-contribution.js.map +1 -1
  45. package/lib/browser/workspace-functions.d.ts +12 -2
  46. package/lib/browser/workspace-functions.d.ts.map +1 -1
  47. package/lib/browser/workspace-functions.js +181 -19
  48. package/lib/browser/workspace-functions.js.map +1 -1
  49. package/lib/browser/workspace-functions.spec.js +1 -1
  50. package/lib/browser/workspace-functions.spec.js.map +1 -1
  51. package/lib/browser/workspace-search-provider.d.ts +1 -1
  52. package/lib/browser/workspace-search-provider.d.ts.map +1 -1
  53. package/lib/browser/workspace-search-provider.js +2 -2
  54. package/lib/browser/workspace-search-provider.js.map +1 -1
  55. package/lib/browser/workspace-search-provider.spec.js +1 -2
  56. package/lib/browser/workspace-search-provider.spec.js.map +1 -1
  57. package/lib/{browser/ai-configuration → common}/ai-configuration-preferences.d.ts +1 -1
  58. package/lib/common/ai-configuration-preferences.d.ts.map +1 -0
  59. package/lib/{browser/ai-configuration → common}/ai-configuration-preferences.js +0 -1
  60. package/lib/common/ai-configuration-preferences.js.map +1 -0
  61. package/lib/{browser → common}/ai-ide-preferences.d.ts +1 -1
  62. package/lib/common/ai-ide-preferences.d.ts.map +1 -0
  63. package/lib/{browser → common}/ai-ide-preferences.js +3 -4
  64. package/lib/common/ai-ide-preferences.js.map +1 -0
  65. package/lib/common/architect-prompt-template.d.ts.map +1 -1
  66. package/lib/common/architect-prompt-template.js +5 -2
  67. package/lib/common/architect-prompt-template.js.map +1 -1
  68. package/lib/common/coder-replace-prompt-template.d.ts.map +1 -1
  69. package/lib/common/coder-replace-prompt-template.js +11 -7
  70. package/lib/common/coder-replace-prompt-template.js.map +1 -1
  71. package/lib/common/orchestrator-chat-agent.d.ts +0 -1
  72. package/lib/common/orchestrator-chat-agent.d.ts.map +1 -1
  73. package/lib/common/orchestrator-chat-agent.js +0 -1
  74. package/lib/common/orchestrator-chat-agent.js.map +1 -1
  75. package/lib/common/workspace-functions.d.ts +1 -0
  76. package/lib/common/workspace-functions.d.ts.map +1 -1
  77. package/lib/common/workspace-functions.js +2 -1
  78. package/lib/common/workspace-functions.js.map +1 -1
  79. package/lib/{browser → common}/workspace-preferences.d.ts +1 -1
  80. package/lib/common/workspace-preferences.d.ts.map +1 -0
  81. package/lib/{browser → common}/workspace-preferences.js +0 -1
  82. package/lib/common/workspace-preferences.js.map +1 -0
  83. package/lib/node/backend-module.d.ts.map +1 -1
  84. package/lib/node/backend-module.js +6 -0
  85. package/lib/node/backend-module.js.map +1 -1
  86. package/package.json +19 -19
  87. package/src/browser/ai-configuration/agent-configuration-widget.tsx +86 -44
  88. package/src/browser/ai-configuration/prompt-fragments-configuration-widget.tsx +3 -5
  89. package/src/browser/ai-configuration/tools-configuration-widget.tsx +4 -2
  90. package/src/browser/ai-ide-activation-service.ts +4 -4
  91. package/src/browser/app-tester-chat-agent.ts +2 -2
  92. package/src/browser/app-tester-prompt-template.ts +5 -1
  93. package/src/browser/architect-agent.ts +0 -2
  94. package/src/browser/coder-agent.ts +0 -3
  95. package/src/browser/file-changeset-functions.ts +2 -1
  96. package/src/browser/frontend-module.ts +13 -6
  97. package/src/browser/task-context-file-storage-service.ts +6 -6
  98. package/src/browser/template-preference-contribution.ts +3 -3
  99. package/src/browser/workspace-functions.spec.ts +2 -2
  100. package/src/browser/workspace-functions.ts +201 -19
  101. package/src/browser/workspace-search-provider.spec.ts +1 -2
  102. package/src/browser/workspace-search-provider.ts +2 -2
  103. package/src/{browser/ai-configuration → common}/ai-configuration-preferences.ts +1 -2
  104. package/src/{browser → common}/ai-ide-preferences.ts +3 -5
  105. package/src/common/architect-prompt-template.ts +7 -4
  106. package/src/common/coder-replace-prompt-template.ts +12 -8
  107. package/src/common/orchestrator-chat-agent.ts +0 -1
  108. package/src/common/workspace-functions.ts +1 -0
  109. package/src/{browser → common}/workspace-preferences.ts +1 -3
  110. package/src/node/backend-module.ts +8 -1
  111. package/lib/browser/ai-configuration/ai-configuration-preferences.d.ts.map +0 -1
  112. package/lib/browser/ai-configuration/ai-configuration-preferences.js.map +0 -1
  113. package/lib/browser/ai-ide-preferences.d.ts.map +0 -1
  114. package/lib/browser/ai-ide-preferences.js.map +0 -1
  115. package/lib/browser/workspace-preferences.d.ts.map +0 -1
  116. package/lib/browser/workspace-preferences.js.map +0 -1
@@ -15,9 +15,7 @@
15
15
  // *****************************************************************************
16
16
  import { AbstractStreamParsingChatAgent, ChatRequestModel, ChatService, ChatSession, MutableChatModel, MutableChatRequestModel } from '@theia/ai-chat/lib/common';
17
17
  import { inject, injectable } from '@theia/core/shared/inversify';
18
- import { FILE_CONTENT_FUNCTION_ID, GET_WORKSPACE_FILE_LIST_FUNCTION_ID, GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID } from '../common/workspace-functions';
19
18
  import { CODER_SYSTEM_PROMPT_ID, getCoderAgentModePromptTemplate, getCoderPromptTemplateEdit, getCoderPromptTemplateSimpleEdit } from '../common/coder-replace-prompt-template';
20
- import { SuggestFileContent } from './file-changeset-functions';
21
19
  import { LanguageModelRequirement, PromptVariantSet } from '@theia/ai-core';
22
20
  import { nls } from '@theia/core';
23
21
  import { MarkdownStringImpl } from '@theia/core/lib/common/markdown-rendering';
@@ -43,7 +41,6 @@ export class CoderAgent extends AbstractStreamParsingChatAgent {
43
41
  defaultVariant: getCoderPromptTemplateEdit(),
44
42
  variants: [getCoderPromptTemplateSimpleEdit(), getCoderAgentModePromptTemplate()]
45
43
  }];
46
- override functions = [GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID, GET_WORKSPACE_FILE_LIST_FUNCTION_ID, FILE_CONTENT_FUNCTION_ID, SuggestFileContent.ID];
47
44
  protected override systemPromptId: string | undefined = CODER_SYSTEM_PROMPT_ID;
48
45
  override async invoke(request: MutableChatRequestModel): Promise<void> {
49
46
  await super.invoke(request);
@@ -241,7 +241,8 @@ export class ReplaceContentInFileFunctionHelper {
241
241
  properties: replacementProperties,
242
242
  required: ['oldContent', 'newContent']
243
243
  },
244
- description: 'An array of replacement objects, each containing oldContent and newContent strings.'
244
+ description: `An array of replacement objects, each containing oldContent and newContent strings.
245
+ Ensure these strings are valid JSON string values, escaping quotes only as required.`
245
246
  },
246
247
  reset: {
247
248
  type: 'boolean',
@@ -22,11 +22,17 @@ import { Agent, AIVariableContribution, bindToolProvider } from '@theia/ai-core/
22
22
  import { ArchitectAgent } from './architect-agent';
23
23
  import { CoderAgent } from './coder-agent';
24
24
  import { SummarizeSessionCommandContribution } from './summarize-session-command-contribution';
25
- import { FileContentFunction, FileDiagnosticProvider, GetWorkspaceDirectoryStructure, GetWorkspaceFileList, WorkspaceFunctionScope } from './workspace-functions';
25
+ import {
26
+ FileContentFunction,
27
+ FileDiagnosticProvider,
28
+ FindFilesByPattern,
29
+ GetWorkspaceDirectoryStructure,
30
+ GetWorkspaceFileList,
31
+ WorkspaceFunctionScope
32
+ } from './workspace-functions';
26
33
  import { WorkspaceSearchProvider } from './workspace-search-provider';
27
34
  import {
28
35
  FrontendApplicationContribution,
29
- PreferenceContribution,
30
36
  WidgetFactory,
31
37
  bindViewContribution,
32
38
  RemoteConnectionProvider,
@@ -38,7 +44,7 @@ import {
38
44
  LaunchRunnerProvider,
39
45
  LaunchStopProvider,
40
46
  } from './workspace-launch-provider';
41
- import { WorkspacePreferencesSchema } from './workspace-preferences';
47
+ import { WorkspacePreferencesSchema } from '../common/workspace-preferences';
42
48
  import {
43
49
  ClearFileChanges,
44
50
  GetProposedFileState,
@@ -65,7 +71,6 @@ import { AIVariableConfigurationWidget } from './ai-configuration/variable-confi
65
71
  import { ContextFilesVariableContribution } from '../common/context-files-variable';
66
72
  import { AIToolsConfigurationWidget } from './ai-configuration/tools-configuration-widget';
67
73
  import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
68
- import { AiConfigurationPreferences } from './ai-configuration/ai-configuration-preferences';
69
74
  import { TemplatePreferenceContribution } from './template-preference-contribution';
70
75
  import { AIMCPConfigurationWidget } from './ai-configuration/mcp-configuration-widget';
71
76
  import { ChatWelcomeMessageProvider } from '@theia/ai-chat-ui/lib/browser/chat-tree-view';
@@ -74,14 +79,15 @@ import { AITokenUsageConfigurationWidget } from './ai-configuration/token-usage-
74
79
  import { TaskContextSummaryVariableContribution } from './task-background-summary-variable';
75
80
  import { TaskContextFileStorageService } from './task-context-file-storage-service';
76
81
  import { TaskContextStorageService } from '@theia/ai-chat/lib/browser/task-context-service';
77
- import { CommandContribution } from '@theia/core';
82
+ import { CommandContribution, PreferenceContribution } from '@theia/core';
78
83
  import { AIPromptFragmentsConfigurationWidget } from './ai-configuration/prompt-fragments-configuration-widget';
79
84
  import { BrowserAutomation, browserAutomationPath } from '../common/browser-automation-protocol';
80
85
  import { CloseBrowserProvider, IsBrowserRunningProvider, LaunchBrowserProvider, QueryDomProvider } from './app-tester-chat-functions';
81
86
  import { ModelAliasesConfigurationWidget } from './ai-configuration/model-aliases-configuration-widget';
82
- import { aiIdePreferenceSchema } from './ai-ide-preferences';
87
+ import { aiIdePreferenceSchema } from '../common/ai-ide-preferences';
83
88
  import { AIActivationService } from '@theia/ai-core/lib/browser';
84
89
  import { AIIdeActivationServiceImpl } from './ai-ide-activation-service';
90
+ import { AiConfigurationPreferences } from '../common/ai-configuration-preferences';
85
91
 
86
92
  export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
87
93
  bind(PreferenceContribution).toConstantValue({ schema: aiIdePreferenceSchema });
@@ -128,6 +134,7 @@ export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
128
134
  bindToolProvider(FileContentFunction, bind);
129
135
  bindToolProvider(GetWorkspaceDirectoryStructure, bind);
130
136
  bindToolProvider(FileDiagnosticProvider, bind);
137
+ bindToolProvider(FindFilesByPattern, bind);
131
138
  bind(WorkspaceFunctionScope).toSelf().inSingletonScope();
132
139
  bindToolProvider(WorkspaceSearchProvider, bind);
133
140
 
@@ -17,13 +17,13 @@
17
17
  import { Summary, SummaryMetadata, TaskContextStorageService } from '@theia/ai-chat/lib/browser/task-context-service';
18
18
  import { InMemoryTaskContextStorage } from '@theia/ai-chat/lib/browser/task-context-storage-service';
19
19
  import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
20
- import { DisposableCollection, EOL, Emitter, ILogger, Path, URI, unreachable } from '@theia/core';
21
- import { PreferenceService, OpenerService, open } from '@theia/core/lib/browser';
20
+ import { DisposableCollection, EOL, Emitter, ILogger, Path, PreferenceService, URI, unreachable } from '@theia/core';
21
+ import { OpenerService, open } from '@theia/core/lib/browser';
22
22
  import { FileService } from '@theia/filesystem/lib/browser/file-service';
23
23
  import { WorkspaceService } from '@theia/workspace/lib/browser';
24
24
  import * as yaml from 'js-yaml';
25
25
  import { FileChange, FileChangeType } from '@theia/filesystem/lib/common/files';
26
- import { TASK_CONTEXT_STORAGE_DIRECTORY_PREF } from './workspace-preferences';
26
+ import { TASK_CONTEXT_STORAGE_DIRECTORY_PREF } from '../common/workspace-preferences';
27
27
  import { BinaryBuffer } from '@theia/core/lib/common/buffer';
28
28
 
29
29
  @injectable()
@@ -67,16 +67,16 @@ export class TaskContextFileStorageService implements TaskContextStorageService
67
67
  this.watchStorage();
68
68
  this.preferenceService.onPreferenceChanged(e => {
69
69
  if (e.preferenceName === TASK_CONTEXT_STORAGE_DIRECTORY_PREF) {
70
- this.watchStorage();
70
+ this.watchStorage().catch(error => this.logger.error(error));
71
71
  }
72
72
  });
73
73
  }
74
74
 
75
75
  protected toDisposeOnStorageChange?: DisposableCollection;
76
- protected watchStorage(): void {
76
+ protected async watchStorage(): Promise<void> {
77
+ const newStorage = await this.getStorageLocation();
77
78
  this.toDisposeOnStorageChange?.dispose();
78
79
  this.toDisposeOnStorageChange = undefined;
79
- const newStorage = this.getStorageLocation();
80
80
  if (!newStorage) { return; }
81
81
  this.toDisposeOnStorageChange = new DisposableCollection(
82
82
  this.fileService.watch(newStorage, { recursive: true, excludes: [] }),
@@ -14,16 +14,16 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { FrontendApplicationContribution, PreferenceService } from '@theia/core/lib/browser';
17
+ import { FrontendApplicationContribution } from '@theia/core/lib/browser';
18
18
  import { inject, injectable } from '@theia/core/shared/inversify';
19
19
  import { DefaultPromptFragmentCustomizationService, PromptFragmentCustomizationProperties } from '@theia/ai-core/lib/browser/frontend-prompt-customization-service';
20
20
  import {
21
21
  PROMPT_TEMPLATE_WORKSPACE_DIRECTORIES_PREF,
22
22
  PROMPT_TEMPLATE_ADDITIONAL_EXTENSIONS_PREF,
23
23
  PROMPT_TEMPLATE_WORKSPACE_FILES_PREF
24
- } from './workspace-preferences';
24
+ } from '../common/workspace-preferences';
25
25
  import { WorkspaceService } from '@theia/workspace/lib/browser';
26
- import { Path } from '@theia/core';
26
+ import { Path, PreferenceService } from '@theia/core';
27
27
 
28
28
  @injectable()
29
29
  export class TemplatePreferenceContribution implements FrontendApplicationContribution {
@@ -20,7 +20,7 @@ import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/front
20
20
  FrontendApplicationConfigProvider.set({});
21
21
 
22
22
  import { expect } from 'chai';
23
- import { CancellationTokenSource } from '@theia/core';
23
+ import { CancellationTokenSource, PreferenceService } from '@theia/core';
24
24
  import {
25
25
  GetWorkspaceDirectoryStructure,
26
26
  FileContentFunction,
@@ -33,7 +33,7 @@ import { Container } from '@theia/core/shared/inversify';
33
33
  import { FileService } from '@theia/filesystem/lib/browser/file-service';
34
34
  import { URI } from '@theia/core/lib/common/uri';
35
35
  import { WorkspaceService } from '@theia/workspace/lib/browser';
36
- import { PreferenceService, OpenerService } from '@theia/core/lib/browser';
36
+ import { OpenerService } from '@theia/core/lib/browser';
37
37
  import { ProblemManager } from '@theia/markers/lib/browser';
38
38
  import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
39
39
  import { MonacoWorkspace } from '@theia/monaco/lib/browser/monaco-workspace';
@@ -14,7 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
  import { ToolProvider, ToolRequest } from '@theia/ai-core';
17
- import { CancellationToken, Disposable, URI } from '@theia/core';
17
+ import { CancellationToken, Disposable, PreferenceService, URI } from '@theia/core';
18
18
  import { inject, injectable } from '@theia/core/shared/inversify';
19
19
  import { FileService } from '@theia/filesystem/lib/browser/file-service';
20
20
  import { FileStat } from '@theia/filesystem/lib/common/files';
@@ -22,12 +22,12 @@ import { WorkspaceService } from '@theia/workspace/lib/browser';
22
22
  import {
23
23
  FILE_CONTENT_FUNCTION_ID, GET_FILE_DIAGNOSTICS_ID,
24
24
  GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID,
25
- GET_WORKSPACE_FILE_LIST_FUNCTION_ID
25
+ GET_WORKSPACE_FILE_LIST_FUNCTION_ID, FIND_FILES_BY_PATTERN_FUNCTION_ID
26
26
  } from '../common/workspace-functions';
27
27
  import ignore from 'ignore';
28
28
  import { Minimatch } from 'minimatch';
29
- import { PreferenceService, OpenerService, open } from '@theia/core/lib/browser';
30
- import { CONSIDER_GITIGNORE_PREF, USER_EXCLUDE_PATTERN_PREF } from './workspace-preferences';
29
+ import { OpenerService, open } from '@theia/core/lib/browser';
30
+ import { CONSIDER_GITIGNORE_PREF, USER_EXCLUDE_PATTERN_PREF } from '../common/workspace-preferences';
31
31
  import { MonacoWorkspace } from '@theia/monaco/lib/browser/monaco-workspace';
32
32
  import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
33
33
  import { ProblemManager } from '@theia/markers/lib/browser';
@@ -141,8 +141,8 @@ export class GetWorkspaceDirectoryStructure implements ToolProvider {
141
141
  return {
142
142
  id: GetWorkspaceDirectoryStructure.ID,
143
143
  name: GetWorkspaceDirectoryStructure.ID,
144
- description: `Retrieve the complete directory structure of the workspace, listing only directories (no file contents). This structure excludes specific directories,
145
- such as node_modules and hidden files, ensuring paths are within workspace boundaries.`,
144
+ description: 'Retrieve the complete directory structure of the workspace, listing only directories (no file contents). ' +
145
+ 'This structure excludes specific directories, such as node_modules and hidden files, ensuring paths are within workspace boundaries.',
146
146
  parameters: {
147
147
  type: 'object',
148
148
  properties: {}
@@ -209,15 +209,17 @@ export class FileContentFunction implements ToolProvider {
209
209
  return {
210
210
  id: FileContentFunction.ID,
211
211
  name: FileContentFunction.ID,
212
- description: `Return the content of a specified file within the workspace. The file path must be provided relative to the workspace root. Only files within
213
- workspace boundaries are accessible; attempting to access files outside the workspace will return an error.`,
212
+ description: 'Return the content of a specified file within the workspace. ' +
213
+ 'The file path must be provided relative to the workspace root. Only files within ' +
214
+ 'workspace boundaries are accessible; attempting to access files outside the workspace will return an error.',
214
215
  parameters: {
215
216
  type: 'object',
216
217
  properties: {
217
218
  file: {
218
219
  type: 'string',
219
- description: `The relative path to the target file within the workspace. This path is resolved from the workspace root, and only files within the workspace
220
- boundaries are accessible. Attempting to access paths outside the workspace will result in an error.`,
220
+ description: 'The relative path to the target file within the workspace. ' +
221
+ 'This path is resolved from the workspace root, and only files within the workspace ' +
222
+ 'boundaries are accessible. Attempting to access paths outside the workspace will result in an error.',
221
223
  }
222
224
  },
223
225
  required: ['file']
@@ -289,14 +291,16 @@ export class GetWorkspaceFileList implements ToolProvider {
289
291
  properties: {
290
292
  path: {
291
293
  type: 'string',
292
- description: `Optional relative path to a directory within the workspace. If no path is specified, the function lists contents directly in the workspace
293
- root. Paths are resolved within workspace boundaries only; paths outside the workspace or unvalidated paths will result in an error.`
294
+ description: 'Optional relative path to a directory within the workspace. ' +
295
+ 'If no path is specified, the function lists contents directly in the workspace root. ' +
296
+ 'Paths are resolved within workspace boundaries only; paths outside the workspace or unvalidated paths will result in an error.'
294
297
  }
295
298
  },
296
299
  required: ['path']
297
300
  },
298
- description: `List files and directories within a specified workspace directory. Paths are relative to the workspace root, and only workspace-contained paths are
299
- allowed. If no path is provided, the root contents are listed. Paths outside the workspace will result in an error.`,
301
+ description: 'List files and directories within a specified workspace directory. ' +
302
+ 'Paths are relative to the workspace root, and only workspace-contained paths are allowed. ' +
303
+ 'If no path is provided, the root contents are listed. Paths outside the workspace will result in an error.',
300
304
  handler: (arg_string: string, ctx: MutableChatRequestModel) => {
301
305
  const args = JSON.parse(arg_string);
302
306
  const cancellationToken = ctx.response.cancellationToken;
@@ -363,7 +367,8 @@ export class GetWorkspaceFileList implements ToolProvider {
363
367
  if (await this.workspaceScope.shouldExclude(child)) {
364
368
  continue;
365
369
  }
366
- result.push(child.resource.path.base);
370
+ const itemName = child.resource.path.base;
371
+ result.push(child.isDirectory ? `${itemName}/` : itemName);
367
372
  }
368
373
  }
369
374
  }
@@ -393,15 +398,17 @@ export class FileDiagnosticProvider implements ToolProvider {
393
398
  id: FileDiagnosticProvider.ID,
394
399
  name: FileDiagnosticProvider.ID,
395
400
  description:
396
- 'A function to retrieve diagnostics associated with a specific file in the workspace. It will return a list of problems that includes the surrounding text \
397
- a message describing the problem, and optionally a code and a codeDescription field describing that code.',
401
+ 'A function to retrieve diagnostics associated with a specific file in the workspace. ' +
402
+ 'It will return a list of problems that includes the surrounding text a message describing the problem, ' +
403
+ 'and optionally a code and a codeDescription field describing that code.',
398
404
  parameters: {
399
405
  type: 'object',
400
406
  properties: {
401
407
  file: {
402
408
  type: 'string',
403
- description: `The relative path to the target file within the workspace. This path is resolved from the workspace root, and only files within the workspace
404
- boundaries are accessible. Attempting to access paths outside the workspace will result in an error.`
409
+ description: 'The relative path to the target file within the workspace. ' +
410
+ 'This path is resolved from the workspace root, and only files within the workspace ' +
411
+ 'boundaries are accessible. Attempting to access paths outside the workspace will result in an error.'
405
412
  }
406
413
  },
407
414
  required: ['file']
@@ -516,3 +523,178 @@ export class FileDiagnosticProvider implements ToolProvider {
516
523
  return { end: { character: Number.MAX_SAFE_INTEGER, line: endLine }, start: { character: 0, line: startLine } };
517
524
  }
518
525
  }
526
+
527
+ @injectable()
528
+ export class FindFilesByPattern implements ToolProvider {
529
+ static ID = FIND_FILES_BY_PATTERN_FUNCTION_ID;
530
+
531
+ @inject(WorkspaceFunctionScope)
532
+ protected readonly workspaceScope: WorkspaceFunctionScope;
533
+
534
+ @inject(PreferenceService)
535
+ protected readonly preferences: PreferenceService;
536
+
537
+ @inject(FileService)
538
+ protected readonly fileService: FileService;
539
+
540
+ getTool(): ToolRequest {
541
+ return {
542
+ id: FindFilesByPattern.ID,
543
+ name: FindFilesByPattern.ID,
544
+ description: 'Find files in the workspace that match a given glob pattern. ' +
545
+ 'This function allows efficient discovery of files using patterns like \'**/*.ts\' for all TypeScript files or ' +
546
+ '\'src/**/*.js\' for JavaScript files in the src directory. The function respects gitignore patterns and user exclusions, ' +
547
+ 'returns relative paths from the workspace root, and limits results to 200 files maximum.',
548
+ parameters: {
549
+ type: 'object',
550
+ properties: {
551
+ pattern: {
552
+ type: 'string',
553
+ description: 'Glob pattern to match files against. ' +
554
+ 'Examples: \'**/*.ts\' (all TypeScript files), \'src/**/*.js\' (JS files in src), ' +
555
+ '\'**/*.{js,ts}\' (JS or TS files), \'**/test/**\' (files in test directories). ' +
556
+ 'Patterns are matched against paths relative to the workspace root.'
557
+ },
558
+ exclude: {
559
+ type: 'array',
560
+ items: { type: 'string' },
561
+ description: 'Optional array of glob patterns to exclude from results. ' +
562
+ 'Examples: [\'**/*.spec.ts\', \'**/*.test.js\', \'node_modules/**\']. ' +
563
+ 'If not specified, common exclusions like node_modules, .git, and dist are applied automatically.'
564
+ }
565
+ },
566
+ required: ['pattern']
567
+ },
568
+ handler: (arg_string: string, ctx: MutableChatRequestModel) => {
569
+ const args = JSON.parse(arg_string);
570
+ const cancellationToken = ctx.response.cancellationToken;
571
+ return this.findFiles(args.pattern, args.exclude, cancellationToken);
572
+ },
573
+ };
574
+ }
575
+
576
+ private async findFiles(pattern: string, excludePatterns?: string[], cancellationToken?: CancellationToken): Promise<string> {
577
+ if (cancellationToken?.isCancellationRequested) {
578
+ return JSON.stringify({ error: 'Operation cancelled by user' });
579
+ }
580
+
581
+ let workspaceRoot;
582
+ try {
583
+ workspaceRoot = await this.workspaceScope.getWorkspaceRoot();
584
+ } catch (error) {
585
+ return JSON.stringify({ error: error.message });
586
+ }
587
+
588
+ try {
589
+ // Build ignore patterns from gitignore and user preferences
590
+ const ignorePatterns = await this.buildIgnorePatterns(workspaceRoot);
591
+
592
+ const allExcludes = [...ignorePatterns];
593
+ if (excludePatterns && excludePatterns.length > 0) {
594
+ allExcludes.push(...excludePatterns);
595
+ }
596
+
597
+ if (cancellationToken?.isCancellationRequested) {
598
+ return JSON.stringify({ error: 'Operation cancelled by user' });
599
+ }
600
+
601
+ const patternMatcher = new Minimatch(pattern, { dot: false });
602
+ const excludeMatchers = allExcludes.map(excludePattern => new Minimatch(excludePattern, { dot: true }));
603
+ const files: string[] = [];
604
+ const maxResults = 200;
605
+
606
+ await this.traverseDirectory(workspaceRoot, workspaceRoot, patternMatcher, excludeMatchers, files, maxResults, cancellationToken);
607
+
608
+ if (cancellationToken?.isCancellationRequested) {
609
+ return JSON.stringify({ error: 'Operation cancelled by user' });
610
+ }
611
+
612
+ const result: { files: string[]; totalFound?: number; truncated?: boolean } = {
613
+ files: files.slice(0, maxResults)
614
+ };
615
+
616
+ if (files.length > maxResults) {
617
+ result.totalFound = files.length;
618
+ result.truncated = true;
619
+ }
620
+
621
+ return JSON.stringify(result);
622
+
623
+ } catch (error) {
624
+ return JSON.stringify({ error: `Failed to find files: ${error.message}` });
625
+ }
626
+ }
627
+
628
+ private async buildIgnorePatterns(workspaceRoot: URI): Promise<string[]> {
629
+ const patterns: string[] = [];
630
+
631
+ // Get user exclude patterns from preferences
632
+ const userExcludePatterns = this.preferences.get<string[]>(USER_EXCLUDE_PATTERN_PREF, []);
633
+ patterns.push(...userExcludePatterns);
634
+
635
+ // Add gitignore patterns if enabled
636
+ const shouldConsiderGitIgnore = this.preferences.get(CONSIDER_GITIGNORE_PREF, false);
637
+ if (shouldConsiderGitIgnore) {
638
+ try {
639
+ const gitignoreUri = workspaceRoot.resolve('.gitignore');
640
+ const gitignoreContent = await this.fileService.read(gitignoreUri);
641
+ const gitignoreLines = gitignoreContent.value
642
+ .split('\n')
643
+ .map(line => line.trim())
644
+ .filter(line => line && !line.startsWith('#'));
645
+ patterns.push(...gitignoreLines);
646
+ } catch {
647
+ // Gitignore file doesn't exist or can't be read, continue without it
648
+ }
649
+ }
650
+
651
+ return patterns;
652
+ }
653
+
654
+ private async traverseDirectory(
655
+ currentUri: URI,
656
+ workspaceRoot: URI,
657
+ patternMatcher: Minimatch,
658
+ excludeMatchers: Minimatch[],
659
+ results: string[],
660
+ maxResults: number,
661
+ cancellationToken?: CancellationToken
662
+ ): Promise<void> {
663
+ if (cancellationToken?.isCancellationRequested || results.length >= maxResults) {
664
+ return;
665
+ }
666
+
667
+ try {
668
+ const stat = await this.fileService.resolve(currentUri);
669
+ if (!stat || !stat.isDirectory || !stat.children) {
670
+ return;
671
+ }
672
+
673
+ for (const child of stat.children) {
674
+ if (cancellationToken?.isCancellationRequested || results.length >= maxResults) {
675
+ break;
676
+ }
677
+
678
+ const relativePath = workspaceRoot.relative(child.resource)?.toString();
679
+ if (!relativePath) {
680
+ continue;
681
+ }
682
+
683
+ const shouldExclude = excludeMatchers.some(matcher => matcher.match(relativePath)) ||
684
+ (await this.workspaceScope.shouldExclude(child));
685
+
686
+ if (shouldExclude) {
687
+ continue;
688
+ }
689
+
690
+ if (child.isDirectory) {
691
+ await this.traverseDirectory(child.resource, workspaceRoot, patternMatcher, excludeMatchers, results, maxResults, cancellationToken);
692
+ } else if (patternMatcher.match(relativePath)) {
693
+ results.push(relativePath);
694
+ }
695
+ }
696
+ } catch {
697
+ // If we can't access a directory, skip it
698
+ }
699
+ }
700
+ }
@@ -15,13 +15,12 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { expect } from 'chai';
18
- import { CancellationTokenSource } from '@theia/core';
18
+ import { CancellationTokenSource, PreferenceService } from '@theia/core';
19
19
  import { WorkspaceSearchProvider } from './workspace-search-provider';
20
20
  import { MutableChatRequestModel, MutableChatResponseModel } from '@theia/ai-chat';
21
21
  import { Container } from '@theia/core/shared/inversify';
22
22
  import { SearchInWorkspaceService, SearchInWorkspaceCallbacks } from '@theia/search-in-workspace/lib/browser/search-in-workspace-service';
23
23
  import { WorkspaceFunctionScope } from './workspace-functions';
24
- import { PreferenceService } from '@theia/core/lib/browser';
25
24
  import { FileService } from '@theia/filesystem/lib/browser/file-service';
26
25
  import { URI } from '@theia/core/lib/common/uri';
27
26
  import { SearchInWorkspaceOptions } from '@theia/search-in-workspace/lib/common/search-in-workspace-interface';
@@ -17,14 +17,14 @@
17
17
  import { MutableChatRequestModel } from '@theia/ai-chat';
18
18
  import { ToolProvider, ToolRequest } from '@theia/ai-core';
19
19
  import { CancellationToken } from '@theia/core';
20
- import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service';
20
+ import { PreferenceService } from '@theia/core/lib/common/preferences/preference-service';
21
21
  import { inject, injectable } from '@theia/core/shared/inversify';
22
22
  import { FileService } from '@theia/filesystem/lib/browser/file-service';
23
23
  import { SearchInWorkspaceService, SearchInWorkspaceCallbacks } from '@theia/search-in-workspace/lib/browser/search-in-workspace-service';
24
24
  import { SearchInWorkspaceResult, SearchInWorkspaceOptions } from '@theia/search-in-workspace/lib/common/search-in-workspace-interface';
25
25
  import { SEARCH_IN_WORKSPACE_FUNCTION_ID } from '../common/workspace-functions';
26
26
  import { WorkspaceFunctionScope } from './workspace-functions';
27
- import { SEARCH_IN_WORKSPACE_MAX_RESULTS_PREF } from './workspace-preferences';
27
+ import { SEARCH_IN_WORKSPACE_MAX_RESULTS_PREF } from '../common/workspace-preferences';
28
28
  import { optimizeSearchResults } from '../common/workspace-search-provider-util';
29
29
 
30
30
  @injectable()
@@ -15,7 +15,7 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { nls } from '@theia/core';
18
- import { PreferenceSchema } from '@theia/core/lib/browser/preferences/preference-contribution';
18
+ import { PreferenceSchema } from '@theia/core/lib/common';
19
19
 
20
20
  /**
21
21
  * These preferences are not intended to reflect real settings.
@@ -23,7 +23,6 @@ import { PreferenceSchema } from '@theia/core/lib/browser/preferences/preference
23
23
  * in case the user looks in the preferences editor UI to find the configuration.
24
24
  */
25
25
  export const AiConfigurationPreferences: PreferenceSchema = {
26
- type: 'object',
27
26
  properties: {
28
27
  'ai-features.agentSettings.details': {
29
28
  type: 'null',
@@ -14,15 +14,13 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { AI_CORE_PREFERENCES_TITLE, ENABLE_AI_CONTEXT_KEY } from '@theia/ai-core/lib/browser';
18
- import { nls } from '@theia/core';
19
- import { PreferenceSchema } from '@theia/core/lib/browser';
17
+ import { AI_CORE_PREFERENCES_TITLE } from '@theia/ai-core/lib/common';
18
+ import { nls, PreferenceSchema } from '@theia/core';
20
19
 
21
20
  // We reuse the context key for the preference name
22
- export const PREFERENCE_NAME_ENABLE_AI = ENABLE_AI_CONTEXT_KEY;
21
+ export const PREFERENCE_NAME_ENABLE_AI = 'ai-features.AiEnable.enableAI';
23
22
 
24
23
  export const aiIdePreferenceSchema: PreferenceSchema = {
25
- type: 'object',
26
24
  properties: {
27
25
  [PREFERENCE_NAME_ENABLE_AI]: {
28
26
  title: AI_CORE_PREFERENCES_TITLE,
@@ -10,8 +10,8 @@
10
10
  // *****************************************************************************
11
11
  import { PromptVariantSet } from '@theia/ai-core/lib/common';
12
12
  import {
13
- GET_WORKSPACE_FILE_LIST_FUNCTION_ID, FILE_CONTENT_FUNCTION_ID, GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID, SEARCH_IN_WORKSPACE_FUNCTION_ID,
14
- GET_FILE_DIAGNOSTICS_ID
13
+ GET_WORKSPACE_FILE_LIST_FUNCTION_ID, FILE_CONTENT_FUNCTION_ID, SEARCH_IN_WORKSPACE_FUNCTION_ID,
14
+ GET_FILE_DIAGNOSTICS_ID, FIND_FILES_BY_PATTERN_FUNCTION_ID
15
15
  } from './workspace-functions';
16
16
  import { CONTEXT_FILES_VARIABLE_ID, TASK_CONTEXT_SUMMARY_VARIABLE_ID } from './context-variables';
17
17
  import { UPDATE_CONTEXT_FILES_FUNCTION_ID } from './context-functions';
@@ -36,11 +36,14 @@ implement the change plan. If you refer to files, always mention the workspace-r
36
36
 
37
37
  ## Context Retrieval
38
38
  Use the following functions to interact with the workspace files if you require context:
39
- - **~{${GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID}}**
40
39
  - **~{${GET_WORKSPACE_FILE_LIST_FUNCTION_ID}}**
41
40
  - **~{${FILE_CONTENT_FUNCTION_ID}}**
41
+ - **~{${FIND_FILES_BY_PATTERN_FUNCTION_ID}}** (find files by glob patterns like '**/*.ts')
42
42
  - **~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}}**
43
43
 
44
+ If you cannot find good search terms, navigate the directory structure.
45
+ **Confirm Paths**: Always verify paths by listing directories or files as you navigate. Avoid assumptions based on user input alone.
46
+ **Navigate Step-by-Step**: Move into subdirectories only as needed, confirming each directory level.
44
47
  Remember file locations that are relevant for completing your tasks using **~{${UPDATE_CONTEXT_FILES_FUNCTION_ID}}**
45
48
  Only add files that are really relevant to look at later. Only add files that are really relevant to look at later.
46
49
 
@@ -70,9 +73,9 @@ aware that there is another agent called 'Coder' that can suggest file changes.
70
73
  implement the change plan. If you refer to files, always mention the workspace-relative path.\
71
74
 
72
75
  Use the following functions to interact with the workspace files as needed:
73
- - **~{${GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID}}**: Returns the complete directory structure.
74
76
  - **~{${GET_WORKSPACE_FILE_LIST_FUNCTION_ID}}**: Lists files and directories in a specific directory.
75
77
  - **~{${FILE_CONTENT_FUNCTION_ID}}**: Retrieves the content of a specific file.
78
+ - **~{${FIND_FILES_BY_PATTERN_FUNCTION_ID}}**: Find files by glob patterns like '**/*.ts'.
76
79
 
77
80
  ### Workspace Navigation Guidelines
78
81
 
@@ -14,9 +14,9 @@ import { CHANGE_SET_SUMMARY_VARIABLE_ID } from '@theia/ai-chat';
14
14
  import {
15
15
  GET_WORKSPACE_FILE_LIST_FUNCTION_ID,
16
16
  FILE_CONTENT_FUNCTION_ID,
17
- GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID,
18
17
  GET_FILE_DIAGNOSTICS_ID,
19
18
  SEARCH_IN_WORKSPACE_FUNCTION_ID,
19
+ FIND_FILES_BY_PATTERN_FUNCTION_ID,
20
20
  LIST_TASKS_FUNCTION_ID,
21
21
  RUN_TASK_FUNCTION_ID
22
22
  } from './workspace-functions';
@@ -73,9 +73,9 @@ After each tool call:
73
73
  Never guess or hallucinate file content or structure. Use tools for all workspace interactions:
74
74
 
75
75
  ### Workspace Exploration
76
- - ~{${GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID}} — view overall structure
77
76
  - ~{${GET_WORKSPACE_FILE_LIST_FUNCTION_ID}} — list contents of a specific directory
78
77
  - ~{${FILE_CONTENT_FUNCTION_ID}} — retrieve the content of a file
78
+ - ~{${FIND_FILES_BY_PATTERN_FUNCTION_ID}} — find files matching glob patterns (e.g., '**/*.ts' for all TypeScript files)
79
79
  - ~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}}} — locate references or patterns (only search if you are missing information, always prefer examples that are explicitly provided, never \
80
80
  search for files you already know the path for)
81
81
  - ~{${UPDATE_CONTEXT_FILES_FUNCTION_ID}} — bookmark important files for context
@@ -168,12 +168,14 @@ which will be reviewed and accepted by the user.
168
168
 
169
169
  ## Context Retrieval
170
170
  Use the following functions to interact with the workspace files if you require context:
171
- - **~{${GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID}}**
172
171
  - **~{${GET_WORKSPACE_FILE_LIST_FUNCTION_ID}}**
173
172
  - **~{${FILE_CONTENT_FUNCTION_ID}}**
174
- - **~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}}** (only search if you are missing information, always prefer examples that are explicitly provided, never search for files \
175
- you already know the path for)
173
+ - **~{${FIND_FILES_BY_PATTERN_FUNCTION_ID}}** (find files by glob patterns like '**/*.ts')
174
+ - **~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}}**
176
175
 
176
+ If you cannot find good search terms, navigate the directory structure.
177
+ **Confirm Paths**: Always verify paths by listing directories or files as you navigate. Avoid assumptions based on user input alone.
178
+ **Navigate Step-by-Step**: Move into subdirectories only as needed, confirming each directory level.
177
179
  Remember file locations that are relevant for completing your tasks using **~{${UPDATE_CONTEXT_FILES_FUNCTION_ID}}**
178
180
  Only add files that are really relevant to look at later.
179
181
 
@@ -237,12 +239,14 @@ which will be reviewed and accepted by the user.
237
239
 
238
240
  ## Context Retrieval
239
241
  Use the following functions to interact with the workspace files if you require context:
240
- - **~{${GET_WORKSPACE_DIRECTORY_STRUCTURE_FUNCTION_ID}}**
241
242
  - **~{${GET_WORKSPACE_FILE_LIST_FUNCTION_ID}}**
242
243
  - **~{${FILE_CONTENT_FUNCTION_ID}}**
243
- - **~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}}** (only search if you are missing information, always prefer examples that are explicitly provided, never search for files \
244
- you already know the path for)
244
+ - **~{${FIND_FILES_BY_PATTERN_FUNCTION_ID}}** (find files by glob patterns like '**/*.ts')
245
+ - **~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}}**
245
246
 
247
+ If you cannot find good search terms, navigate the directory structure.
248
+ **Confirm Paths**: Always verify paths by listing directories or files as you navigate. Avoid assumptions based on user input alone.
249
+ **Navigate Step-by-Step**: Move into subdirectories only as needed, confirming each directory level.
246
250
  Remember file locations that are relevant for completing your tasks using **~{${UPDATE_CONTEXT_FILES_FUNCTION_ID}}**
247
251
  Only add files that are really relevant to look at later.
248
252
 
@@ -36,7 +36,6 @@ export class OrchestratorChatAgent extends AbstractStreamParsingChatAgent {
36
36
  }];
37
37
  protected defaultLanguageModelPurpose: string = 'agent-selection';
38
38
 
39
- override variables = ['chatAgents'];
40
39
  override prompts = [orchestratorTemplate];
41
40
  override description = nls.localize('theia/ai/chat/orchestrator/description',
42
41
  'This agent analyzes the user request against the description of all available chat agents and selects the best fitting agent to answer the request \