tarsk 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -7
- package/dist/index.d.ts +3 -0
- package/dist/index.js +92 -32
- package/dist/lib/response-builder.d.ts +50 -0
- package/dist/lib/response-builder.js +56 -0
- package/dist/lib/stream-helper.d.ts +39 -0
- package/dist/lib/stream-helper.js +43 -0
- package/dist/managers/ConversationManager.d.ts +83 -0
- package/dist/managers/ConversationManager.js +129 -0
- package/dist/managers/GitManager.d.ts +133 -0
- package/dist/managers/GitManager.js +330 -0
- package/dist/managers/MetadataManager.d.ts +139 -0
- package/dist/managers/MetadataManager.js +309 -0
- package/dist/managers/ModelManager.d.ts +57 -0
- package/dist/managers/ModelManager.js +129 -0
- package/dist/managers/NeovateExecutor.d.ts +40 -0
- package/dist/managers/NeovateExecutor.js +138 -0
- package/dist/managers/ProjectManager.d.ts +162 -0
- package/dist/managers/ProjectManager.js +353 -0
- package/dist/managers/ThreadManager.d.ts +181 -0
- package/dist/managers/ThreadManager.js +325 -0
- package/dist/managers/conversation-manager.d.ts +83 -0
- package/dist/managers/conversation-manager.js +129 -0
- package/dist/managers/git-manager.d.ts +133 -0
- package/dist/managers/git-manager.js +330 -0
- package/dist/managers/metadata-manager.d.ts +139 -0
- package/dist/managers/metadata-manager.js +305 -0
- package/dist/managers/model-manager.d.ts +59 -0
- package/dist/managers/model-manager.js +144 -0
- package/dist/managers/neovate-executor.d.ts +43 -0
- package/dist/managers/neovate-executor.js +205 -0
- package/dist/managers/processing-state-manager.d.ts +40 -0
- package/dist/managers/processing-state-manager.js +27 -0
- package/dist/managers/project-manager.d.ts +199 -0
- package/dist/managers/project-manager.js +465 -0
- package/dist/managers/thread-manager.d.ts +193 -0
- package/dist/managers/thread-manager.js +368 -0
- package/dist/model-info-aihubmix.d.ts +25 -0
- package/dist/model-info-aihubmix.js +117 -0
- package/dist/model-info-openai.d.ts +17 -0
- package/dist/model-info-openai.js +59 -0
- package/dist/model-info-openrouter.d.ts +25 -0
- package/dist/model-info-openrouter.js +101 -0
- package/dist/model-info.d.ts +37 -0
- package/dist/model-info.js +39 -0
- package/dist/provider-data.d.ts +101 -0
- package/dist/provider-data.js +471 -0
- package/dist/provider.d.ts +10 -0
- package/dist/provider.js +192 -0
- package/dist/public/android-chrome-192x192.png +0 -0
- package/dist/public/android-chrome-512x512.png +0 -0
- package/dist/public/apple-touch-icon.png +0 -0
- package/dist/public/assets/index-B443aj9k.js +8506 -0
- package/dist/public/assets/index-CjXGVbI7.css +1 -0
- package/dist/public/assets/index-DJC-p914.js +8506 -0
- package/dist/public/favicon-16x16.png +0 -0
- package/dist/public/favicon-32x32.png +0 -0
- package/dist/public/favicon.ico +0 -0
- package/dist/public/index.html +28 -0
- package/dist/public/manifest.json +82 -0
- package/dist/public/placeholder-logo.svg +1 -0
- package/dist/public/placeholder.svg +1 -0
- package/dist/public/snpro.woff2 +0 -0
- package/dist/public/tarsk-color.svg +12 -0
- package/dist/public/tarsk.png +0 -0
- package/dist/public/tarsk.svg +12 -0
- package/dist/public/zalando-sans.woff2 +0 -0
- package/dist/routes/chat-old.d.ts +21 -0
- package/dist/routes/chat-old.js +251 -0
- package/dist/routes/chat.d.ts +21 -0
- package/dist/routes/chat.js +217 -0
- package/dist/routes/git.d.ts +4 -0
- package/dist/routes/git.js +668 -0
- package/dist/routes/models.d.ts +18 -0
- package/dist/routes/models.js +128 -0
- package/dist/routes/projects-old.d.ts +20 -0
- package/dist/routes/projects-old.js +297 -0
- package/dist/routes/projects.d.ts +20 -0
- package/dist/routes/projects.js +365 -0
- package/dist/routes/providers.d.ts +15 -0
- package/dist/routes/providers.js +130 -0
- package/dist/routes/threads-old.d.ts +14 -0
- package/dist/routes/threads-old.js +393 -0
- package/dist/routes/threads.d.ts +14 -0
- package/dist/routes/threads.js +352 -0
- package/dist/types/models.d.ts +315 -0
- package/dist/types/models.js +11 -0
- package/dist/utils/env-manager.d.ts +3 -0
- package/dist/utils/env-manager.js +60 -0
- package/dist/utils/open-router-models.d.ts +45 -0
- package/dist/utils/open-router-models.js +103 -0
- package/dist/utils/openai-models.d.ts +63 -0
- package/dist/utils/openai-models.js +152 -0
- package/dist/utils/openai-pricing-scraper.d.ts +17 -0
- package/dist/utils/openai-pricing-scraper.js +185 -0
- package/dist/utils/validation.d.ts +10 -0
- package/dist/utils/validation.js +20 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +12 -0
- package/package.json +36 -22
- package/LICENSE.md +0 -7
- package/dist/agent/agent.js +0 -131
- package/dist/agent/interfaces.js +0 -1
- package/dist/api/encryption.js +0 -41
- package/dist/api/models.js +0 -169
- package/dist/api/prompt.js +0 -12
- package/dist/api/settings.js +0 -43
- package/dist/api/test.js +0 -29
- package/dist/api/tools.js +0 -287
- package/dist/api/utils.js +0 -18
- package/dist/interfaces/meta.js +0 -1
- package/dist/interfaces/model.js +0 -1
- package/dist/interfaces/settings.js +0 -1
- package/dist/log/log.js +0 -33
- package/dist/prompt.js +0 -49
- package/dist/tools.js +0 -84
- package/dist/utils/files.js +0 -14
- package/dist/utils/json-file.js +0 -28
- package/dist/utils/strip-markdown.js +0 -5
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitManager handles git operations including URL validation and repository cloning
|
|
3
|
+
*
|
|
4
|
+
* This manager is responsible for:
|
|
5
|
+
* - Validating git URLs in various formats
|
|
6
|
+
* - Cloning repositories with streaming output
|
|
7
|
+
* - Handling git operation errors
|
|
8
|
+
*/
|
|
9
|
+
import { GitEvent } from '../types/models.js';
|
|
10
|
+
/**
|
|
11
|
+
* GitManager interface defines the contract for git operations
|
|
12
|
+
*/
|
|
13
|
+
export interface GitManager {
|
|
14
|
+
/**
|
|
15
|
+
* Validates a git URL format
|
|
16
|
+
* @param url - The git URL to validate
|
|
17
|
+
* @returns true if the URL is a valid git URL, false otherwise
|
|
18
|
+
*/
|
|
19
|
+
validateGitUrl(url: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Clones a git repository to the specified target path
|
|
22
|
+
* @param gitUrl - The git repository URL to clone
|
|
23
|
+
* @param targetPath - The local path where the repository should be cloned
|
|
24
|
+
* @yields GitEvent objects for stdout, stderr, complete, and error events
|
|
25
|
+
*/
|
|
26
|
+
cloneRepository(gitUrl: string, targetPath: string): AsyncGenerator<GitEvent>;
|
|
27
|
+
/**
|
|
28
|
+
* Sanitizes a branch name to ensure it only contains valid git branch characters
|
|
29
|
+
* Replaces spaces with dashes and removes invalid characters
|
|
30
|
+
* @param name - The branch name to sanitize
|
|
31
|
+
* @returns The sanitized branch name
|
|
32
|
+
*/
|
|
33
|
+
sanitizeBranchName(name: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Checks if a branch exists in a git repository
|
|
36
|
+
* @param repoPath - The path to the git repository
|
|
37
|
+
* @param branchName - The branch name to check
|
|
38
|
+
* @returns true if the branch exists, false otherwise
|
|
39
|
+
*/
|
|
40
|
+
checkBranchExists(repoPath: string, branchName: string): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* Creates and checks out a new branch in a git repository
|
|
43
|
+
* @param repoPath - The path to the git repository
|
|
44
|
+
* @param branchName - The branch name to create
|
|
45
|
+
* @yields GitEvent objects for stdout, stderr, complete, and error events
|
|
46
|
+
*/
|
|
47
|
+
createAndCheckoutBranch(repoPath: string, branchName: string): AsyncGenerator<GitEvent>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* GitManagerImpl provides the implementation for git operations
|
|
51
|
+
*/
|
|
52
|
+
export declare class GitManagerImpl implements GitManager {
|
|
53
|
+
/**
|
|
54
|
+
* Regular expressions for validating different git URL formats
|
|
55
|
+
*/
|
|
56
|
+
private readonly gitUrlPatterns;
|
|
57
|
+
/**
|
|
58
|
+
* Validates a git URL against common git URL formats
|
|
59
|
+
*
|
|
60
|
+
* Supports the following formats:
|
|
61
|
+
* - HTTPS: https://github.com/user/repo.git
|
|
62
|
+
* - Git protocol: git://github.com/user/repo.git
|
|
63
|
+
* - SSH (git@): git@github.com:user/repo.git
|
|
64
|
+
* - SSH (ssh://): ssh://git@github.com/user/repo.git
|
|
65
|
+
*
|
|
66
|
+
* @param url - The URL to validate
|
|
67
|
+
* @returns true if the URL matches a valid git URL format, false otherwise
|
|
68
|
+
*
|
|
69
|
+
* Requirements: 7.1 - WHEN cloning a git repository, THE CLI SHALL validate the git URL format
|
|
70
|
+
*/
|
|
71
|
+
validateGitUrl(url: string): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Clones a git repository to the specified target path with streaming output
|
|
74
|
+
*
|
|
75
|
+
* This method:
|
|
76
|
+
* 1. Validates the git URL
|
|
77
|
+
* 2. Creates the target directory if needed
|
|
78
|
+
* 3. Spawns a git clone process
|
|
79
|
+
* 4. Streams stdout and stderr output
|
|
80
|
+
* 5. Handles completion and errors
|
|
81
|
+
*
|
|
82
|
+
* @param gitUrl - The git repository URL to clone
|
|
83
|
+
* @param targetPath - The local path where the repository should be cloned
|
|
84
|
+
* @yields GitEvent objects during the clone operation
|
|
85
|
+
*
|
|
86
|
+
* Requirements:
|
|
87
|
+
* - 1.1 - WHEN a user provides a git URL to create a new Project, THE CLI SHALL clone the repository
|
|
88
|
+
* - 1.3 - WHEN the clone operation executes, THE CLI SHALL stream the git clone output back to the App
|
|
89
|
+
* - 7.1 - WHEN cloning a git repository, THE CLI SHALL validate the git URL format
|
|
90
|
+
* - 7.2 - IF a git clone operation fails, THEN THE CLI SHALL return a descriptive error message
|
|
91
|
+
* - 7.3 - WHEN a clone operation is in progress, THE CLI SHALL stream git output to provide progress feedback
|
|
92
|
+
*/
|
|
93
|
+
cloneRepository(gitUrl: string, targetPath: string): AsyncGenerator<GitEvent>;
|
|
94
|
+
/**
|
|
95
|
+
* Sanitizes a branch name to ensure it only contains valid git branch characters
|
|
96
|
+
*
|
|
97
|
+
* This method:
|
|
98
|
+
* 1. Trims whitespace
|
|
99
|
+
* 2. Converts to lowercase
|
|
100
|
+
* 3. Replaces spaces with dashes
|
|
101
|
+
* 4. Removes invalid characters (only allows alphanumeric, dash, underscore, slash, dot)
|
|
102
|
+
* 5. Removes leading/trailing slashes and dots
|
|
103
|
+
* 6. Collapses multiple consecutive dashes into one
|
|
104
|
+
*
|
|
105
|
+
* @param name - The branch name to sanitize
|
|
106
|
+
* @returns The sanitized branch name (all lowercase)
|
|
107
|
+
*/
|
|
108
|
+
sanitizeBranchName(name: string): string;
|
|
109
|
+
/**
|
|
110
|
+
* Checks if a branch exists in a git repository
|
|
111
|
+
*
|
|
112
|
+
* Uses `git show-ref` to check for the branch without checking out
|
|
113
|
+
*
|
|
114
|
+
* @param repoPath - The path to the git repository
|
|
115
|
+
* @param branchName - The branch name to check
|
|
116
|
+
* @returns true if the branch exists, false otherwise
|
|
117
|
+
*/
|
|
118
|
+
checkBranchExists(repoPath: string, branchName: string): Promise<boolean>;
|
|
119
|
+
/**
|
|
120
|
+
* Creates and checks out a new branch in a git repository with streaming output
|
|
121
|
+
*
|
|
122
|
+
* This method:
|
|
123
|
+
* 1. Creates a new branch from the current HEAD
|
|
124
|
+
* 2. Checks out the new branch
|
|
125
|
+
* 3. Streams output during the operation
|
|
126
|
+
*
|
|
127
|
+
* @param repoPath - The path to the git repository
|
|
128
|
+
* @param branchName - The branch name to create
|
|
129
|
+
* @yields GitEvent objects during the branch creation
|
|
130
|
+
*/
|
|
131
|
+
createAndCheckoutBranch(repoPath: string, branchName: string): AsyncGenerator<GitEvent>;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=GitManager.d.ts.map
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitManager handles git operations including URL validation and repository cloning
|
|
3
|
+
*
|
|
4
|
+
* This manager is responsible for:
|
|
5
|
+
* - Validating git URLs in various formats
|
|
6
|
+
* - Cloning repositories with streaming output
|
|
7
|
+
* - Handling git operation errors
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from 'child_process';
|
|
10
|
+
import { mkdir } from 'fs/promises';
|
|
11
|
+
import { dirname } from 'path';
|
|
12
|
+
/**
|
|
13
|
+
* GitManagerImpl provides the implementation for git operations
|
|
14
|
+
*/
|
|
15
|
+
export class GitManagerImpl {
|
|
16
|
+
/**
|
|
17
|
+
* Regular expressions for validating different git URL formats
|
|
18
|
+
*/
|
|
19
|
+
gitUrlPatterns = [
|
|
20
|
+
// HTTPS URLs: https://github.com/user/repo.git or https://github.com/user/repo
|
|
21
|
+
/^https:\/\/[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(:[0-9]+)?\/[a-zA-Z0-9._/-]+(\.git)?$/,
|
|
22
|
+
// Git protocol URLs: git://github.com/user/repo.git or git://github.com/user/repo
|
|
23
|
+
/^git:\/\/[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(:[0-9]+)?\/[a-zA-Z0-9._/-]+(\.git)?$/,
|
|
24
|
+
// SSH URLs with git@ prefix: git@github.com:user/repo.git or git@github.com:user/repo
|
|
25
|
+
/^git@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}:[a-zA-Z0-9._/-]+(\.git)?$/,
|
|
26
|
+
// SSH URLs with ssh:// prefix: ssh://git@github.com/user/repo.git
|
|
27
|
+
/^ssh:\/\/(git@)?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(:[0-9]+)?\/[a-zA-Z0-9._/-]+(\.git)?$/,
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Validates a git URL against common git URL formats
|
|
31
|
+
*
|
|
32
|
+
* Supports the following formats:
|
|
33
|
+
* - HTTPS: https://github.com/user/repo.git
|
|
34
|
+
* - Git protocol: git://github.com/user/repo.git
|
|
35
|
+
* - SSH (git@): git@github.com:user/repo.git
|
|
36
|
+
* - SSH (ssh://): ssh://git@github.com/user/repo.git
|
|
37
|
+
*
|
|
38
|
+
* @param url - The URL to validate
|
|
39
|
+
* @returns true if the URL matches a valid git URL format, false otherwise
|
|
40
|
+
*
|
|
41
|
+
* Requirements: 7.1 - WHEN cloning a git repository, THE CLI SHALL validate the git URL format
|
|
42
|
+
*/
|
|
43
|
+
validateGitUrl(url) {
|
|
44
|
+
// Check if URL is empty or not a string
|
|
45
|
+
if (!url || typeof url !== 'string') {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
// Trim whitespace
|
|
49
|
+
const trimmedUrl = url.trim();
|
|
50
|
+
// Check if URL is empty after trimming
|
|
51
|
+
if (trimmedUrl.length === 0) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
// Test against all supported patterns
|
|
55
|
+
return this.gitUrlPatterns.some(pattern => pattern.test(trimmedUrl));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Clones a git repository to the specified target path with streaming output
|
|
59
|
+
*
|
|
60
|
+
* This method:
|
|
61
|
+
* 1. Validates the git URL
|
|
62
|
+
* 2. Creates the target directory if needed
|
|
63
|
+
* 3. Spawns a git clone process
|
|
64
|
+
* 4. Streams stdout and stderr output
|
|
65
|
+
* 5. Handles completion and errors
|
|
66
|
+
*
|
|
67
|
+
* @param gitUrl - The git repository URL to clone
|
|
68
|
+
* @param targetPath - The local path where the repository should be cloned
|
|
69
|
+
* @yields GitEvent objects during the clone operation
|
|
70
|
+
*
|
|
71
|
+
* Requirements:
|
|
72
|
+
* - 1.1 - WHEN a user provides a git URL to create a new Project, THE CLI SHALL clone the repository
|
|
73
|
+
* - 1.3 - WHEN the clone operation executes, THE CLI SHALL stream the git clone output back to the App
|
|
74
|
+
* - 7.1 - WHEN cloning a git repository, THE CLI SHALL validate the git URL format
|
|
75
|
+
* - 7.2 - IF a git clone operation fails, THEN THE CLI SHALL return a descriptive error message
|
|
76
|
+
* - 7.3 - WHEN a clone operation is in progress, THE CLI SHALL stream git output to provide progress feedback
|
|
77
|
+
*/
|
|
78
|
+
async *cloneRepository(gitUrl, targetPath) {
|
|
79
|
+
// Validate the git URL first
|
|
80
|
+
if (!this.validateGitUrl(gitUrl)) {
|
|
81
|
+
yield {
|
|
82
|
+
type: 'error',
|
|
83
|
+
message: `Invalid git URL format: ${gitUrl}`,
|
|
84
|
+
error: new Error(`Invalid git URL format: ${gitUrl}`)
|
|
85
|
+
};
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
// Create the parent directory if it doesn't exist
|
|
90
|
+
const parentDir = dirname(targetPath);
|
|
91
|
+
await mkdir(parentDir, { recursive: true });
|
|
92
|
+
// Spawn git clone process
|
|
93
|
+
// Use --progress to get progress output on stderr
|
|
94
|
+
const gitProcess = spawn('git', ['clone', '--progress', gitUrl, targetPath]);
|
|
95
|
+
// Create a queue for events
|
|
96
|
+
const eventQueue = [];
|
|
97
|
+
let processExited = false;
|
|
98
|
+
let exitCode = null;
|
|
99
|
+
let processError = null;
|
|
100
|
+
// Handle stdout data
|
|
101
|
+
gitProcess.stdout.on('data', (data) => {
|
|
102
|
+
const output = data.toString();
|
|
103
|
+
eventQueue.push({
|
|
104
|
+
type: 'stdout',
|
|
105
|
+
data: output
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
// Handle stderr data (git clone progress goes to stderr)
|
|
109
|
+
gitProcess.stderr.on('data', (data) => {
|
|
110
|
+
const output = data.toString();
|
|
111
|
+
eventQueue.push({
|
|
112
|
+
type: 'stderr',
|
|
113
|
+
data: output
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
// Handle process exit
|
|
117
|
+
gitProcess.on('close', (code) => {
|
|
118
|
+
exitCode = code;
|
|
119
|
+
processExited = true;
|
|
120
|
+
});
|
|
121
|
+
// Handle process errors
|
|
122
|
+
gitProcess.on('error', (err) => {
|
|
123
|
+
processError = err;
|
|
124
|
+
processExited = true;
|
|
125
|
+
});
|
|
126
|
+
// Yield events as they come in
|
|
127
|
+
while (!processExited || eventQueue.length > 0) {
|
|
128
|
+
if (eventQueue.length > 0) {
|
|
129
|
+
const event = eventQueue.shift();
|
|
130
|
+
if (event) {
|
|
131
|
+
yield event;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Wait a bit before checking again
|
|
136
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Check for process errors
|
|
140
|
+
if (processError) {
|
|
141
|
+
const errorMessage = processError instanceof Error
|
|
142
|
+
? processError.message
|
|
143
|
+
: String(processError);
|
|
144
|
+
yield {
|
|
145
|
+
type: 'error',
|
|
146
|
+
message: errorMessage,
|
|
147
|
+
error: processError
|
|
148
|
+
};
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// Check exit code
|
|
152
|
+
if (exitCode !== 0) {
|
|
153
|
+
const errorMsg = `Git clone failed with exit code ${exitCode}`;
|
|
154
|
+
yield {
|
|
155
|
+
type: 'error',
|
|
156
|
+
message: errorMsg,
|
|
157
|
+
error: new Error(errorMsg)
|
|
158
|
+
};
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// Yield complete event
|
|
162
|
+
yield {
|
|
163
|
+
type: 'complete'
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
// Handle any errors during the process
|
|
168
|
+
yield {
|
|
169
|
+
type: 'error',
|
|
170
|
+
message: error instanceof Error ? error.message : String(error),
|
|
171
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Sanitizes a branch name to ensure it only contains valid git branch characters
|
|
177
|
+
*
|
|
178
|
+
* This method:
|
|
179
|
+
* 1. Trims whitespace
|
|
180
|
+
* 2. Converts to lowercase
|
|
181
|
+
* 3. Replaces spaces with dashes
|
|
182
|
+
* 4. Removes invalid characters (only allows alphanumeric, dash, underscore, slash, dot)
|
|
183
|
+
* 5. Removes leading/trailing slashes and dots
|
|
184
|
+
* 6. Collapses multiple consecutive dashes into one
|
|
185
|
+
*
|
|
186
|
+
* @param name - The branch name to sanitize
|
|
187
|
+
* @returns The sanitized branch name (all lowercase)
|
|
188
|
+
*/
|
|
189
|
+
sanitizeBranchName(name) {
|
|
190
|
+
if (!name || typeof name !== 'string') {
|
|
191
|
+
return 'branch';
|
|
192
|
+
}
|
|
193
|
+
return name
|
|
194
|
+
.trim()
|
|
195
|
+
// Convert to lowercase
|
|
196
|
+
.toLowerCase()
|
|
197
|
+
// Replace spaces with dashes
|
|
198
|
+
.replace(/\s+/g, '-')
|
|
199
|
+
// Remove invalid characters (keep alphanumeric, dash, underscore, slash, dot)
|
|
200
|
+
.replace(/[^a-zA-Z0-9\-_/.]/g, '')
|
|
201
|
+
// Remove leading/trailing slashes and dots
|
|
202
|
+
.replace(/^[/.]+|[/.]+$/g, '')
|
|
203
|
+
// Collapse multiple consecutive dashes
|
|
204
|
+
.replace(/-+/g, '-')
|
|
205
|
+
// Ensure we have something left
|
|
206
|
+
|| 'branch';
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Checks if a branch exists in a git repository
|
|
210
|
+
*
|
|
211
|
+
* Uses `git show-ref` to check for the branch without checking out
|
|
212
|
+
*
|
|
213
|
+
* @param repoPath - The path to the git repository
|
|
214
|
+
* @param branchName - The branch name to check
|
|
215
|
+
* @returns true if the branch exists, false otherwise
|
|
216
|
+
*/
|
|
217
|
+
async checkBranchExists(repoPath, branchName) {
|
|
218
|
+
return new Promise((resolve) => {
|
|
219
|
+
const gitProcess = spawn('git', ['show-ref', '--verify', '--quiet', `refs/heads/${branchName}`], {
|
|
220
|
+
cwd: repoPath
|
|
221
|
+
});
|
|
222
|
+
gitProcess.on('close', (code) => {
|
|
223
|
+
// Exit code 0 means the branch exists
|
|
224
|
+
resolve(code === 0);
|
|
225
|
+
});
|
|
226
|
+
gitProcess.on('error', () => {
|
|
227
|
+
// If there's an error running git, assume branch doesn't exist
|
|
228
|
+
resolve(false);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Creates and checks out a new branch in a git repository with streaming output
|
|
234
|
+
*
|
|
235
|
+
* This method:
|
|
236
|
+
* 1. Creates a new branch from the current HEAD
|
|
237
|
+
* 2. Checks out the new branch
|
|
238
|
+
* 3. Streams output during the operation
|
|
239
|
+
*
|
|
240
|
+
* @param repoPath - The path to the git repository
|
|
241
|
+
* @param branchName - The branch name to create
|
|
242
|
+
* @yields GitEvent objects during the branch creation
|
|
243
|
+
*/
|
|
244
|
+
async *createAndCheckoutBranch(repoPath, branchName) {
|
|
245
|
+
try {
|
|
246
|
+
// Spawn git checkout process with -b flag to create new branch
|
|
247
|
+
const gitProcess = spawn('git', ['checkout', '-b', branchName], {
|
|
248
|
+
cwd: repoPath
|
|
249
|
+
});
|
|
250
|
+
// Create a queue for events
|
|
251
|
+
const eventQueue = [];
|
|
252
|
+
let processExited = false;
|
|
253
|
+
let exitCode = null;
|
|
254
|
+
let processError = null;
|
|
255
|
+
// Handle stdout data
|
|
256
|
+
gitProcess.stdout.on('data', (data) => {
|
|
257
|
+
const output = data.toString();
|
|
258
|
+
eventQueue.push({
|
|
259
|
+
type: 'stdout',
|
|
260
|
+
data: output
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
// Handle stderr data
|
|
264
|
+
gitProcess.stderr.on('data', (data) => {
|
|
265
|
+
const output = data.toString();
|
|
266
|
+
eventQueue.push({
|
|
267
|
+
type: 'stderr',
|
|
268
|
+
data: output
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
// Handle process exit
|
|
272
|
+
gitProcess.on('close', (code) => {
|
|
273
|
+
exitCode = code;
|
|
274
|
+
processExited = true;
|
|
275
|
+
});
|
|
276
|
+
// Handle process errors
|
|
277
|
+
gitProcess.on('error', (err) => {
|
|
278
|
+
processError = err;
|
|
279
|
+
processExited = true;
|
|
280
|
+
});
|
|
281
|
+
// Yield events as they come in
|
|
282
|
+
while (!processExited || eventQueue.length > 0) {
|
|
283
|
+
if (eventQueue.length > 0) {
|
|
284
|
+
const event = eventQueue.shift();
|
|
285
|
+
if (event) {
|
|
286
|
+
yield event;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
// Wait a bit before checking again
|
|
291
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Check for process errors
|
|
295
|
+
if (processError) {
|
|
296
|
+
const errorMessage = processError instanceof Error
|
|
297
|
+
? processError.message
|
|
298
|
+
: String(processError);
|
|
299
|
+
yield {
|
|
300
|
+
type: 'error',
|
|
301
|
+
message: errorMessage,
|
|
302
|
+
error: processError
|
|
303
|
+
};
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
// Check exit code
|
|
307
|
+
if (exitCode !== 0) {
|
|
308
|
+
const errorMsg = `Failed to create and checkout branch '${branchName}' with exit code ${exitCode}`;
|
|
309
|
+
yield {
|
|
310
|
+
type: 'error',
|
|
311
|
+
message: errorMsg,
|
|
312
|
+
error: new Error(errorMsg)
|
|
313
|
+
};
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
// Yield complete event
|
|
317
|
+
yield {
|
|
318
|
+
type: 'complete'
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
yield {
|
|
323
|
+
type: 'error',
|
|
324
|
+
message: error instanceof Error ? error.message : String(error),
|
|
325
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=GitManager.js.map
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetadataManager handles persistence of project and thread metadata
|
|
3
|
+
*
|
|
4
|
+
* This manager provides JSON file-based storage with atomic writes
|
|
5
|
+
* to ensure data consistency even if the process crashes during write operations.
|
|
6
|
+
*/
|
|
7
|
+
import { Project, Thread } from '../types/models.js';
|
|
8
|
+
/**
|
|
9
|
+
* MetadataManager manages persistence of projects and threads
|
|
10
|
+
*/
|
|
11
|
+
interface AppState {
|
|
12
|
+
selectedThreadId: string | null;
|
|
13
|
+
providerKeys: Record<string, string>;
|
|
14
|
+
enabledModels: Record<string, string[]>;
|
|
15
|
+
}
|
|
16
|
+
export declare class MetadataManager {
|
|
17
|
+
private projectsFile;
|
|
18
|
+
private threadsFile;
|
|
19
|
+
private stateFile;
|
|
20
|
+
private metadataDir;
|
|
21
|
+
/**
|
|
22
|
+
* Create a new MetadataManager
|
|
23
|
+
* @param rootFolder - Base directory where metadata will be stored
|
|
24
|
+
*/
|
|
25
|
+
constructor(rootFolder: string);
|
|
26
|
+
/**
|
|
27
|
+
* Initialize metadata directory if it doesn't exist
|
|
28
|
+
*/
|
|
29
|
+
initialize(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Save projects to disk using atomic write
|
|
32
|
+
* @param projects - Array of projects to save
|
|
33
|
+
*/
|
|
34
|
+
saveProjects(projects: Project[]): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Load projects from disk
|
|
37
|
+
* @returns Array of projects
|
|
38
|
+
*/
|
|
39
|
+
loadProjects(): Promise<Project[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Save threads to disk using atomic write
|
|
42
|
+
* @param threads - Array of threads to save
|
|
43
|
+
*/
|
|
44
|
+
saveThreads(threads: Thread[]): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Load threads from disk
|
|
47
|
+
* @returns Array of threads
|
|
48
|
+
*/
|
|
49
|
+
loadThreads(): Promise<Thread[]>;
|
|
50
|
+
/**
|
|
51
|
+
* Perform atomic write using temp file
|
|
52
|
+
*
|
|
53
|
+
* This ensures that if the process crashes during write,
|
|
54
|
+
* we don't end up with corrupted or partial data.
|
|
55
|
+
*
|
|
56
|
+
* @param filePath - Target file path
|
|
57
|
+
* @param data - Data to write
|
|
58
|
+
*/
|
|
59
|
+
private atomicWrite;
|
|
60
|
+
/**
|
|
61
|
+
* Get the metadata directory path
|
|
62
|
+
*/
|
|
63
|
+
getMetadataDir(): string;
|
|
64
|
+
/**
|
|
65
|
+
* Get the projects file path
|
|
66
|
+
*/
|
|
67
|
+
getProjectsFile(): string;
|
|
68
|
+
/**
|
|
69
|
+
* Get the threads file path
|
|
70
|
+
*/
|
|
71
|
+
getThreadsFile(): string;
|
|
72
|
+
/**
|
|
73
|
+
* Save application state to disk
|
|
74
|
+
* @param state - Application state to save
|
|
75
|
+
*/
|
|
76
|
+
saveState(state: AppState): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Load application state from disk
|
|
79
|
+
* @returns Application state
|
|
80
|
+
*/
|
|
81
|
+
loadState(): Promise<AppState>;
|
|
82
|
+
/**
|
|
83
|
+
* Update all provider keys at once
|
|
84
|
+
* @param keys - Object mapping provider names to API keys
|
|
85
|
+
*/
|
|
86
|
+
saveAllProviderKeys(keys: Record<string, string>): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Update provider keys
|
|
89
|
+
* @param providerName - Name of the provider
|
|
90
|
+
* @param apiKey - API key to save
|
|
91
|
+
*/
|
|
92
|
+
saveProviderKey(providerName: string, apiKey: string): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Get all provider keys
|
|
95
|
+
* @returns Record of provider names to API keys
|
|
96
|
+
*/
|
|
97
|
+
getProviderKeys(): Promise<Record<string, string>>;
|
|
98
|
+
/**
|
|
99
|
+
* Set the selected thread ID
|
|
100
|
+
* @param threadId - Thread ID to select (or null to deselect)
|
|
101
|
+
*/
|
|
102
|
+
setSelectedThread(threadId: string | null): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Get the selected thread ID
|
|
105
|
+
* @returns The selected thread ID or null
|
|
106
|
+
*/
|
|
107
|
+
getSelectedThread(): Promise<string | null>;
|
|
108
|
+
/**
|
|
109
|
+
* Enable a model for a provider
|
|
110
|
+
* @param provider - Provider name
|
|
111
|
+
* @param modelId - Model ID to enable
|
|
112
|
+
*/
|
|
113
|
+
enableModel(provider: string, modelId: string): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Disable a model for a provider
|
|
116
|
+
* @param provider - Provider name
|
|
117
|
+
* @param modelId - Model ID to disable
|
|
118
|
+
*/
|
|
119
|
+
disableModel(provider: string, modelId: string): Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Get enabled models for a provider
|
|
122
|
+
* @param provider - Provider name
|
|
123
|
+
* @returns Array of enabled model IDs
|
|
124
|
+
*/
|
|
125
|
+
getEnabledModels(provider: string): Promise<string[]>;
|
|
126
|
+
/**
|
|
127
|
+
* Get all enabled models across all providers
|
|
128
|
+
* @returns Object mapping provider to array of model IDs
|
|
129
|
+
*/
|
|
130
|
+
getAllEnabledModels(): Promise<Record<string, string[]>>;
|
|
131
|
+
/**
|
|
132
|
+
* Set enabled models for a provider
|
|
133
|
+
* @param provider - Provider name
|
|
134
|
+
* @param modelIds - Array of model IDs to enable
|
|
135
|
+
*/
|
|
136
|
+
setEnabledModels(provider: string, modelIds: string[]): Promise<void>;
|
|
137
|
+
}
|
|
138
|
+
export {};
|
|
139
|
+
//# sourceMappingURL=MetadataManager.d.ts.map
|