@theia/ai-ide 1.66.0-next.67 → 1.66.0-next.80

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 (36) hide show
  1. package/lib/browser/frontend-module.d.ts.map +1 -1
  2. package/lib/browser/frontend-module.js +9 -0
  3. package/lib/browser/frontend-module.js.map +1 -1
  4. package/lib/browser/github-repo-variable-contribution.d.ts +8 -10
  5. package/lib/browser/github-repo-variable-contribution.d.ts.map +1 -1
  6. package/lib/browser/github-repo-variable-contribution.js +22 -41
  7. package/lib/browser/github-repo-variable-contribution.js.map +1 -1
  8. package/lib/browser/project-info-agent.d.ts +13 -0
  9. package/lib/browser/project-info-agent.d.ts.map +1 -0
  10. package/lib/browser/project-info-agent.js +45 -0
  11. package/lib/browser/project-info-agent.js.map +1 -0
  12. package/lib/browser/workspace-functions.js +1 -1
  13. package/lib/common/github-repo-protocol.d.ts +15 -0
  14. package/lib/common/github-repo-protocol.d.ts.map +1 -0
  15. package/lib/common/github-repo-protocol.js +21 -0
  16. package/lib/common/github-repo-protocol.js.map +1 -0
  17. package/lib/common/project-info-prompt-template.d.ts +6 -0
  18. package/lib/common/project-info-prompt-template.d.ts.map +1 -0
  19. package/lib/common/project-info-prompt-template.js +145 -0
  20. package/lib/common/project-info-prompt-template.js.map +1 -0
  21. package/lib/node/backend-module.d.ts.map +1 -1
  22. package/lib/node/backend-module.js +4 -0
  23. package/lib/node/backend-module.js.map +1 -1
  24. package/lib/node/github-repo-service-impl.d.ts +7 -0
  25. package/lib/node/github-repo-service-impl.d.ts.map +1 -0
  26. package/lib/node/github-repo-service-impl.js +86 -0
  27. package/lib/node/github-repo-service-impl.js.map +1 -0
  28. package/package.json +23 -23
  29. package/src/browser/frontend-module.ts +10 -0
  30. package/src/browser/github-repo-variable-contribution.ts +23 -50
  31. package/src/browser/project-info-agent.ts +42 -0
  32. package/src/browser/workspace-functions.ts +1 -1
  33. package/src/common/github-repo-protocol.ts +32 -0
  34. package/src/common/project-info-prompt-template.ts +163 -0
  35. package/src/node/backend-module.ts +7 -0
  36. package/src/node/github-repo-service-impl.ts +98 -0
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2025 EclipseSource GmbH.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.GitHubRepoServiceImpl = void 0;
19
+ const tslib_1 = require("tslib");
20
+ const inversify_1 = require("@theia/core/shared/inversify");
21
+ const simple_git_1 = require("simple-git");
22
+ let GitHubRepoServiceImpl = class GitHubRepoServiceImpl {
23
+ async getGitHubRepoInfo(workspacePath) {
24
+ try {
25
+ // Initialize simple-git with the workspace path
26
+ const git = (0, simple_git_1.simpleGit)(workspacePath);
27
+ // Check if this is a git repository
28
+ const isRepo = await git.checkIsRepo();
29
+ if (!isRepo) {
30
+ return undefined;
31
+ }
32
+ // Get all remotes with their URLs
33
+ const remotes = await git.getRemotes(true);
34
+ if (remotes.length === 0) {
35
+ return undefined;
36
+ }
37
+ // Find GitHub remote (prefer 'origin', then any GitHub remote)
38
+ const githubRemote = remotes.find(remote => remote.name === 'origin' && this.isGitHubRemote(remote.refs.fetch || remote.refs.push || '')) || remotes.find(remote => this.isGitHubRemote(remote.refs.fetch || remote.refs.push || ''));
39
+ if (!githubRemote) {
40
+ return undefined;
41
+ }
42
+ const remoteUrl = githubRemote.refs.fetch || githubRemote.refs.push || '';
43
+ const repoInfo = this.extractRepoInfoFromGitHubUrl(remoteUrl);
44
+ return repoInfo;
45
+ }
46
+ catch (error) {
47
+ console.warn('Failed to get GitHub repository info:', error);
48
+ return undefined;
49
+ }
50
+ }
51
+ isGitHubRemote(remoteUrl) {
52
+ return remoteUrl.includes('github.com');
53
+ }
54
+ extractRepoInfoFromGitHubUrl(url) {
55
+ // Handle HTTPS URLs: https://github.com/owner/repo or https://github.com/owner/repo.git
56
+ const httpsMatch = url.match(/https:\/\/github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
57
+ if (httpsMatch) {
58
+ return {
59
+ owner: httpsMatch[1],
60
+ repo: httpsMatch[2]
61
+ };
62
+ }
63
+ // Handle SSH URLs: git@github.com:owner/repo or git@github.com:owner/repo.git
64
+ const sshMatch = url.match(/git@github\.com:([^\/]+)\/([^\/]+?)(?:\.git)?$/);
65
+ if (sshMatch) {
66
+ return {
67
+ owner: sshMatch[1],
68
+ repo: sshMatch[2]
69
+ };
70
+ }
71
+ // Handle alternative SSH format: ssh://git@github.com/owner/repo or ssh://git@github.com/owner/repo.git
72
+ const sshAltMatch = url.match(/ssh:\/\/git@github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
73
+ if (sshAltMatch) {
74
+ return {
75
+ owner: sshAltMatch[1],
76
+ repo: sshAltMatch[2]
77
+ };
78
+ }
79
+ return undefined;
80
+ }
81
+ };
82
+ exports.GitHubRepoServiceImpl = GitHubRepoServiceImpl;
83
+ exports.GitHubRepoServiceImpl = GitHubRepoServiceImpl = tslib_1.__decorate([
84
+ (0, inversify_1.injectable)()
85
+ ], GitHubRepoServiceImpl);
86
+ //# sourceMappingURL=github-repo-service-impl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-repo-service-impl.js","sourceRoot":"","sources":["../../src/node/github-repo-service-impl.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theia/ai-ide",
3
- "version": "1.66.0-next.67+6fae23c43",
3
+ "version": "1.66.0-next.80+623c098dc",
4
4
  "description": "AI IDE Agents Extension",
5
5
  "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0",
6
6
  "repository": {
@@ -15,36 +15,36 @@
15
15
  "theia-extension"
16
16
  ],
17
17
  "dependencies": {
18
- "@theia/ai-chat": "1.66.0-next.67+6fae23c43",
19
- "@theia/ai-chat-ui": "1.66.0-next.67+6fae23c43",
20
- "@theia/ai-core": "1.66.0-next.67+6fae23c43",
21
- "@theia/ai-mcp": "1.66.0-next.67+6fae23c43",
22
- "@theia/core": "1.66.0-next.67+6fae23c43",
23
- "@theia/debug": "1.66.0-next.67+6fae23c43",
24
- "@theia/editor": "1.66.0-next.67+6fae23c43",
25
- "@theia/filesystem": "1.66.0-next.67+6fae23c43",
26
- "@theia/git": "1.65.0",
27
- "@theia/markers": "1.66.0-next.67+6fae23c43",
28
- "@theia/monaco": "1.66.0-next.67+6fae23c43",
29
- "@theia/navigator": "1.66.0-next.67+6fae23c43",
30
- "@theia/preferences": "1.66.0-next.67+6fae23c43",
31
- "@theia/scm": "1.66.0-next.67+6fae23c43",
32
- "@theia/search-in-workspace": "1.66.0-next.67+6fae23c43",
33
- "@theia/task": "1.66.0-next.67+6fae23c43",
34
- "@theia/terminal": "1.66.0-next.67+6fae23c43",
35
- "@theia/workspace": "1.66.0-next.67+6fae23c43",
18
+ "@theia/ai-chat": "1.66.0-next.80+623c098dc",
19
+ "@theia/ai-chat-ui": "1.66.0-next.80+623c098dc",
20
+ "@theia/ai-core": "1.66.0-next.80+623c098dc",
21
+ "@theia/ai-mcp": "1.66.0-next.80+623c098dc",
22
+ "@theia/core": "1.66.0-next.80+623c098dc",
23
+ "@theia/debug": "1.66.0-next.80+623c098dc",
24
+ "@theia/editor": "1.66.0-next.80+623c098dc",
25
+ "@theia/filesystem": "1.66.0-next.80+623c098dc",
26
+ "@theia/markers": "1.66.0-next.80+623c098dc",
27
+ "@theia/monaco": "1.66.0-next.80+623c098dc",
28
+ "@theia/navigator": "1.66.0-next.80+623c098dc",
29
+ "@theia/preferences": "1.66.0-next.80+623c098dc",
30
+ "@theia/scm": "1.66.0-next.80+623c098dc",
31
+ "@theia/search-in-workspace": "1.66.0-next.80+623c098dc",
32
+ "@theia/task": "1.66.0-next.80+623c098dc",
33
+ "@theia/terminal": "1.66.0-next.80+623c098dc",
34
+ "@theia/workspace": "1.66.0-next.80+623c098dc",
36
35
  "date-fns": "^4.1.0",
37
36
  "ignore": "^6.0.0",
38
37
  "js-yaml": "^4.1.0",
39
38
  "minimatch": "^10.0.3",
40
- "puppeteer-core": "^24.10.0"
39
+ "puppeteer-core": "^24.10.0",
40
+ "simple-git": "^3.25.0"
41
41
  },
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
45
  "devDependencies": {
46
- "@theia/cli": "1.66.0-next.67+6fae23c43",
47
- "@theia/test": "1.66.0-next.67+6fae23c43"
46
+ "@theia/cli": "1.66.0-next.80+623c098dc",
47
+ "@theia/test": "1.66.0-next.80+623c098dc"
48
48
  },
49
49
  "theiaExtensions": [
50
50
  {
@@ -68,5 +68,5 @@
68
68
  "nyc": {
69
69
  "extends": "../../configs/nyc.json"
70
70
  },
71
- "gitHead": "6fae23c43f4e850ef4dd6f7c85aa0422077f70e2"
71
+ "gitHead": "623c098dc2e331499458d2bdcc67792919335d9c"
72
72
  }
@@ -86,6 +86,7 @@ import { TaskContextStorageService } from '@theia/ai-chat/lib/browser/task-conte
86
86
  import { CommandContribution, PreferenceContribution } from '@theia/core';
87
87
  import { AIPromptFragmentsConfigurationWidget } from './ai-configuration/prompt-fragments-configuration-widget';
88
88
  import { BrowserAutomation, browserAutomationPath } from '../common/browser-automation-protocol';
89
+ import { GitHubRepoService, githubRepoServicePath } from '../common/github-repo-protocol';
89
90
  import { CloseBrowserProvider, IsBrowserRunningProvider, LaunchBrowserProvider, QueryDomProvider } from './app-tester-chat-functions';
90
91
  import { ModelAliasesConfigurationWidget } from './ai-configuration/model-aliases-configuration-widget';
91
92
  import { aiIdePreferenceSchema } from '../common/ai-ide-preferences';
@@ -93,6 +94,7 @@ import { AIActivationService } from '@theia/ai-core/lib/browser';
93
94
  import { AIIdeActivationServiceImpl } from './ai-ide-activation-service';
94
95
  import { AiConfigurationPreferences } from '../common/ai-configuration-preferences';
95
96
  import { TaskContextAgent } from './task-context-agent';
97
+ import { ProjectInfoAgent } from './project-info-agent';
96
98
 
97
99
  export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
98
100
  bind(PreferenceContribution).toConstantValue({ schema: aiIdePreferenceSchema });
@@ -112,6 +114,9 @@ export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
112
114
 
113
115
  bind(TaskContextAgent).toSelf().inSingletonScope();
114
116
  bind(Agent).toService(TaskContextAgent);
117
+ bind(ProjectInfoAgent).toSelf().inSingletonScope();
118
+ bind(Agent).toService(ProjectInfoAgent);
119
+ bind(ChatAgent).toService(ProjectInfoAgent);
115
120
 
116
121
  bind(OrchestratorChatAgent).toSelf().inSingletonScope();
117
122
  bind(Agent).toService(OrchestratorChatAgent);
@@ -244,6 +249,11 @@ export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
244
249
  bind(TaskContextSummaryVariableContribution).toSelf().inSingletonScope();
245
250
  bind(AIVariableContribution).toService(TaskContextSummaryVariableContribution);
246
251
 
252
+ bind(GitHubRepoService).toDynamicValue(ctx => {
253
+ const provider = ctx.container.get<ServiceConnectionProvider>(RemoteConnectionProvider);
254
+ return provider.createProxy<GitHubRepoService>(githubRepoServicePath);
255
+ }).inSingletonScope();
256
+
247
257
  bind(GitHubRepoVariableContribution).toSelf().inSingletonScope();
248
258
  bind(AIVariableContribution).toService(GitHubRepoVariableContribution);
249
259
  bind(TaskContextFileStorageService).toSelf().inSingletonScope();
@@ -25,9 +25,10 @@ import {
25
25
  ResolvedAIVariable,
26
26
  AIVariable
27
27
  } from '@theia/ai-core/lib/common';
28
- import { ScmService } from '@theia/scm/lib/browser/scm-service';
29
- import { GitRepositoryProvider } from '@theia/git/lib/browser/git-repository-provider';
30
- import { Git } from '@theia/git/lib/common';
28
+ import { WorkspaceService } from '@theia/workspace/lib/browser';
29
+ import { FileService } from '@theia/filesystem/lib/browser/file-service';
30
+
31
+ import { GitHubRepoService } from '../common/github-repo-protocol';
31
32
 
32
33
  export const GITHUB_REPO_NAME_VARIABLE: AIVariable = {
33
34
  id: 'github-repo-name-provider',
@@ -38,59 +39,50 @@ export const GITHUB_REPO_NAME_VARIABLE: AIVariable = {
38
39
  @injectable()
39
40
  export class GitHubRepoVariableContribution implements AIVariableContribution, AIVariableResolver {
40
41
 
41
- @inject(ScmService)
42
- protected readonly scmService: ScmService;
42
+ @inject(WorkspaceService)
43
+ protected readonly workspaceService: WorkspaceService;
43
44
 
44
- @inject(GitRepositoryProvider)
45
- protected readonly repositoryProvider: GitRepositoryProvider;
45
+ @inject(FileService)
46
+ protected readonly fileService: FileService;
46
47
 
47
- @inject(Git)
48
- protected readonly git: Git;
48
+ @inject(GitHubRepoService)
49
+ protected readonly gitHubRepoService: GitHubRepoService;
49
50
 
50
51
  registerVariables(service: AIVariableService): void {
51
52
  service.registerResolver(GITHUB_REPO_NAME_VARIABLE, this);
52
53
  }
53
54
 
54
- canResolve(request: AIVariableResolutionRequest, context: AIVariableContext): MaybePromise<number> {
55
+ canResolve(request: AIVariableResolutionRequest, _context: AIVariableContext): MaybePromise<number> {
55
56
  if (request.variable.name !== GITHUB_REPO_NAME_VARIABLE.name) {
56
57
  return 0;
57
58
  }
58
59
 
59
- const selectedRepo = this.repositoryProvider.selectedRepository;
60
- if (!selectedRepo) {
61
- return 0;
62
- }
63
-
64
60
  return 1;
65
61
  }
66
62
 
67
- async resolve(request: AIVariableResolutionRequest, context: AIVariableContext): Promise<ResolvedAIVariable | undefined> {
63
+ async resolve(request: AIVariableResolutionRequest, _context: AIVariableContext): Promise<ResolvedAIVariable | undefined> {
68
64
  if (request.variable.name !== GITHUB_REPO_NAME_VARIABLE.name) {
69
65
  return undefined;
70
66
  }
71
67
 
72
- const repository = this.repositoryProvider.selectedRepository;
73
- if (!repository) {
74
- return { variable: request.variable, value: 'No GitHub repository is currently selected or detected.' };
75
- }
76
-
77
68
  try {
78
- const remotes = await this.git.remote(repository, { verbose: true });
79
-
80
- // Find GitHub remote (prefer 'origin', then any GitHub remote)
81
- const githubRemote = remotes.find(remote =>
82
- remote.name === 'origin' && this.isGitHubRemote(remote.fetch)
83
- ) || remotes.find(remote => this.isGitHubRemote(remote.fetch));
84
-
85
- if (!githubRemote) {
69
+ const workspaceRoots = await this.workspaceService.roots;
70
+ if (workspaceRoots.length === 0) {
86
71
  return { variable: request.variable, value: 'No GitHub repository is currently selected or detected.' };
87
72
  }
88
73
 
89
- const repoName = this.extractRepoNameFromGitHubUrl(githubRemote.fetch);
90
- if (!repoName) {
74
+ // Get the filesystem path from the workspace root URI
75
+ const workspaceRoot = workspaceRoots[0].resource;
76
+ const workspacePath = workspaceRoot.path.fsPath();
77
+
78
+ // Use the backend service to get GitHub repository information
79
+ const repoInfo = await this.gitHubRepoService.getGitHubRepoInfo(workspacePath);
80
+
81
+ if (!repoInfo) {
91
82
  return { variable: request.variable, value: 'No GitHub repository is currently selected or detected.' };
92
83
  }
93
84
 
85
+ const repoName = `${repoInfo.owner}/${repoInfo.repo}`;
94
86
  return { variable: request.variable, value: `You are currently working with the GitHub repository: **${repoName}**` };
95
87
 
96
88
  } catch (error) {
@@ -98,23 +90,4 @@ export class GitHubRepoVariableContribution implements AIVariableContribution, A
98
90
  return { variable: request.variable, value: 'No GitHub repository is currently selected or detected.' };
99
91
  }
100
92
  }
101
-
102
- private isGitHubRemote(remoteUrl: string): boolean {
103
- return remoteUrl.includes('github.com');
104
- }
105
-
106
- private extractRepoNameFromGitHubUrl(url: string): string | undefined {
107
-
108
- const httpsMatch = url.match(/https:\/\/github\.com\/([^\/]+\/[^\/]+?)(?:\.git)?$/);
109
- if (httpsMatch) {
110
- return httpsMatch[1];
111
- }
112
-
113
- const sshMatch = url.match(/git@github\.com:([^\/]+\/[^\/]+?)(?:\.git)?$/);
114
- if (sshMatch) {
115
- return sshMatch[1];
116
- }
117
-
118
- return undefined;
119
- }
120
93
  }
@@ -0,0 +1,42 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 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
+ import { AbstractStreamParsingChatAgent } from '@theia/ai-chat';
17
+ import { LanguageModelRequirement } from '@theia/ai-core';
18
+ import { injectable } from '@theia/core/shared/inversify';
19
+ import { projectInfoSystemVariants, projectInfoTemplateVariants } from '../common/project-info-prompt-template';
20
+ import { nls } from '@theia/core';
21
+
22
+ @injectable()
23
+ export class ProjectInfoAgent extends AbstractStreamParsingChatAgent {
24
+
25
+ name = 'ProjectInfo';
26
+ id = 'ProjectInfo';
27
+ languageModelRequirements: LanguageModelRequirement[] = [{
28
+ purpose: 'chat',
29
+ identifier: 'default/code',
30
+ }];
31
+ protected defaultLanguageModelPurpose: string = 'chat';
32
+
33
+ override description = nls.localize('theia/ai/workspace/projectInfoAgent/description',
34
+ 'An AI assistant for managing project information templates. This agent helps create, update, and review the .prompts/project-info.prompttemplate file which provides ' +
35
+ 'context about your project to other AI agents. It can analyze your workspace to suggest project information or update existing templates based on your requirements.');
36
+
37
+ override tags: string[] = [...this.tags, 'Alpha'];
38
+
39
+ override prompts = [projectInfoSystemVariants, projectInfoTemplateVariants];
40
+ protected override systemPromptId: string | undefined = projectInfoSystemVariants.id;
41
+
42
+ }
@@ -145,7 +145,7 @@ export class GetWorkspaceDirectoryStructure implements ToolProvider {
145
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
- properties: {}
148
+ properties: {},
149
149
  },
150
150
  handler: (_: string, ctx: MutableChatRequestModel) => {
151
151
  const cancellationToken = ctx.response.cancellationToken;
@@ -0,0 +1,32 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 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
+ export const GitHubRepoService = Symbol('GitHubRepoService');
18
+ export const githubRepoServicePath = '/services/github-repo';
19
+
20
+ export interface GitHubRepoInfo {
21
+ owner: string;
22
+ repo: string;
23
+ }
24
+
25
+ export interface GitHubRepoService {
26
+ /**
27
+ * Gets the GitHub repository information for the given workspace path.
28
+ * @param workspacePath The absolute path to the workspace directory
29
+ * @returns GitHub repository info (owner/repo) or undefined if not a GitHub repository
30
+ */
31
+ getGitHubRepoInfo(workspacePath: string): Promise<GitHubRepoInfo | undefined>;
32
+ }
@@ -0,0 +1,163 @@
1
+ /* eslint-disable @typescript-eslint/tslint/config */
2
+ // *****************************************************************************
3
+ // Copyright (C) 2025 EclipseSource GmbH and others.
4
+ //
5
+ // This file is licensed under the MIT License.
6
+ // See LICENSE-MIT.txt in the project root for license information.
7
+ // https://opensource.org/license/mit.
8
+ //
9
+ // SPDX-License-Identifier: MIT
10
+ // *****************************************************************************
11
+ import { PromptVariantSet } from '@theia/ai-core/lib/common';
12
+ import {
13
+ GET_WORKSPACE_FILE_LIST_FUNCTION_ID, FILE_CONTENT_FUNCTION_ID, SEARCH_IN_WORKSPACE_FUNCTION_ID,
14
+ FIND_FILES_BY_PATTERN_FUNCTION_ID
15
+ } from './workspace-functions';
16
+ import { CONTEXT_FILES_VARIABLE_ID } from './context-variables';
17
+ import { UPDATE_CONTEXT_FILES_FUNCTION_ID } from './context-functions';
18
+ import {
19
+ SUGGEST_FILE_CONTENT_ID,
20
+ SUGGEST_FILE_REPLACEMENTS_ID,
21
+ GET_PROPOSED_CHANGES_ID,
22
+ CLEAR_FILE_CHANGES_ID
23
+ } from './file-changeset-function-ids';
24
+
25
+ export const PROJECT_INFO_SYSTEM_PROMPT_TEMPLATE_ID = 'project-info-system';
26
+ export const PROJECT_INFO_TEMPLATE_PROMPT_ID = 'project-info-template';
27
+
28
+ export const projectInfoTemplateVariants = <PromptVariantSet>{
29
+ id: PROJECT_INFO_TEMPLATE_PROMPT_ID,
30
+ defaultVariant: {
31
+ id: 'project-info-template-default',
32
+ template: `## Project Info Template Structure
33
+
34
+ ### Architecture Overview
35
+ [Brief description of what the project does, Key architectural decisions, patterns, and structure.]
36
+
37
+ ### Key Technologies
38
+ [List of main technologies, frameworks, libraries]
39
+
40
+ ### Essential Development Patterns
41
+ Examples for key patterns (refer via relative file paths)
42
+
43
+ ### File Structure
44
+ [Important directories/packages and their contents]
45
+
46
+ ### Build & Development
47
+ [How to build and run the project.]
48
+
49
+ ### Testing
50
+ [What kind of tests exist, test organization and test patterns. Examples for different types of tests (as relative file paths)]
51
+
52
+ ### Coding Guidelines
53
+ [Coding standards, conventions, practices. Examples for key practices (as relative file paths), rules for imports, indentation]
54
+
55
+ ### Additional Notes
56
+ [Any other important information for agents to understand the project and write code for it. Important files with more information (as relative file paths)]
57
+ \`\`\`
58
+ `
59
+ }
60
+ };
61
+
62
+ export const projectInfoSystemVariants = <PromptVariantSet>{
63
+ id: PROJECT_INFO_SYSTEM_PROMPT_TEMPLATE_ID,
64
+ defaultVariant: {
65
+ id: 'project-info-system-default',
66
+ template: `{{!-- This prompt is licensed under the MIT License (https://opensource.org/license/mit).
67
+ Made improvements or adaptations to this prompt template? We'd love for you to share it with the community! Contribute back here:
68
+ https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}
69
+ # Instructions
70
+
71
+ You are the ProjectInfo agent, an AI assistant specialized in managing project information files. Your role is to help users create, update,
72
+ and maintain the \`.prompts/project-info.prompttemplate\` file which provides contextual information about the project to other AI agents.
73
+
74
+ ## Project Info Guidelines
75
+ The project info is an artifact that will be handed over to agents to understand the current workspace, project and codebase.
76
+ Do not include obvious instructions, generic information, generic development practices or things that can be very easily discovered.
77
+ Focus on non-obvious and project-specific facts as well as specific guidelines and patterns.
78
+ Try to keep the project info minimal and avoid duplicates.
79
+
80
+ ## Your Capabilities
81
+
82
+ ### Initially Create Project Info
83
+ For initial project info creation, start by determining the user's preferred working mode:
84
+
85
+ **Step 1: Define mode of working**
86
+ Ask the user about the preferred working mode:
87
+
88
+ 1. "Auto-exploration - Agent explores and creates an initial suggestion",
89
+ 2. "Manual - User provides all necessary input with your guidance"
90
+
91
+ IMPORTANT: Remember the chosen mode and stick to it until the user requests otherwise!
92
+
93
+ - In automatic mode, create an initial version of the project info yourself by exploring the workspace
94
+ - In manual mode, guide the user section by section and ask for additional information.
95
+ Whenever you ask a question to the user, offer the option that you answer the question for them.
96
+
97
+ **Step 2: Final tasks**
98
+ After completing all sections or if you feel the user is done, offer the user to do an automatic refinement:
99
+ "Would you like me to review and finalize the project information?",
100
+ - In this final refinement, particularly focus on relevance and potential duplications and the "Project Info Guidelines"
101
+ - Then, ask for final user review. Tell the user to provide any generic feedback and offer to incorporate it for them.
102
+ - Finally remind them to accept the final version in the change set
103
+
104
+ ### Complete Project Info
105
+ - If a project info is incomplete, offer the user to complete it
106
+
107
+ ### Update Project Info
108
+ - Modify existing project info based on user requirements
109
+ - Do not use a specific workflow for this
110
+
111
+ ## Workspace Analysis Guidelines
112
+
113
+ **Auto-Discovery File Patterns**
114
+ When auto-discovering project information or exploring the workspace structure, ALWAYS prioritize examining these file patterns that commonly contain agent instructions
115
+ and project documentation:
116
+ - .github/copilot-instructions.md
117
+ - AGENT.md
118
+ - AGENTS.md
119
+ - CLAUDE.md
120
+ - .cursorrules
121
+ - .windsurfrules
122
+ - .clinerules
123
+ - .cursor
124
+ - rules/**
125
+ - .windsurf/rules/**
126
+ - .clinerules/**
127
+ - README.md
128
+ - .md files in the root level if they contain documentation
129
+
130
+ Use the **~{${FIND_FILES_BY_PATTERN_FUNCTION_ID}}** function with these patterns to discover relevant configuration and documentation files.
131
+
132
+ ## Context Retrieval
133
+ Use the following functions to interact with the workspace files when needed:
134
+ - **~{${GET_WORKSPACE_FILE_LIST_FUNCTION_ID}}**: List files and directories
135
+ - **~{${FILE_CONTENT_FUNCTION_ID}}**: Get content of specific files
136
+ - **~{${FIND_FILES_BY_PATTERN_FUNCTION_ID}}**: Find files by glob patterns like '**/*.json'
137
+ - **~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}}**: Search file contents
138
+
139
+ Navigate step-by-step and confirm paths. Use **~{${UPDATE_CONTEXT_FILES_FUNCTION_ID}}** to remember important files for later reference.
140
+
141
+ ## File Modification - SUGGEST ONLY
142
+ Use these functions liberally to suggest file changes. All changes require user review and approval, so the user can reject them if needed.
143
+
144
+ - **~{${SUGGEST_FILE_CONTENT_ID}}**: Propose complete file content (for creating new templates or complete rewrites)
145
+ - **~{${SUGGEST_FILE_REPLACEMENTS_ID}}**: Propose targeted replacements of specific text sections
146
+ - **~{${GET_PROPOSED_CHANGES_ID}}**: View current proposed changes before making additional ones
147
+ - **~{${CLEAR_FILE_CHANGES_ID}}**: Clear all pending changes for a file to start fresh
148
+
149
+ {{prompt:${PROJECT_INFO_TEMPLATE_PROMPT_ID}}}
150
+
151
+ ## Additional Context
152
+ {{${CONTEXT_FILES_VARIABLE_ID}}}
153
+
154
+ ## Workflow Guidelines
155
+
156
+ When creating project info for the first time:
157
+ 1. **Always start by asking about the user's preferred mode** (auto-exploration or manual) and stick to it
158
+ 2. **After initial suggestions or provided content**: Always ask for refinement and additional information
159
+
160
+ Remember: Proactively help users maintain accurate project information for better AI assistance.
161
+ `
162
+ }
163
+ };
@@ -22,6 +22,8 @@ import { ConnectionContainerModule } from '@theia/core/lib/node/messaging/connec
22
22
  import { WorkspacePreferencesSchema } from '../common/workspace-preferences';
23
23
  import { AiConfigurationPreferences } from '../common/ai-configuration-preferences';
24
24
  import { aiIdePreferenceSchema } from '../common/ai-ide-preferences';
25
+ import { GitHubRepoService, githubRepoServicePath } from '../common/github-repo-protocol';
26
+ import { GitHubRepoServiceImpl } from './github-repo-service-impl';
25
27
 
26
28
  const browserAutomationModule = ConnectionContainerModule.create(({ bind, bindBackendService, bindFrontendService }) => {
27
29
  bind(BrowserAutomation).to(BrowserAutomationImpl).inSingletonScope();
@@ -42,4 +44,9 @@ export default new ContainerModule(bind => {
42
44
 
43
45
  bind(ConnectionContainerModule).toConstantValue(browserAutomationModule);
44
46
 
47
+ bind(GitHubRepoService).to(GitHubRepoServiceImpl).inSingletonScope();
48
+ bind(ConnectionHandler).toDynamicValue(ctx =>
49
+ new RpcConnectionHandler(githubRepoServicePath, () => ctx.container.get<GitHubRepoService>(GitHubRepoService))
50
+ ).inSingletonScope();
51
+
45
52
  });