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.
Files changed (119) hide show
  1. package/README.md +1 -7
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.js +92 -32
  4. package/dist/lib/response-builder.d.ts +50 -0
  5. package/dist/lib/response-builder.js +56 -0
  6. package/dist/lib/stream-helper.d.ts +39 -0
  7. package/dist/lib/stream-helper.js +43 -0
  8. package/dist/managers/ConversationManager.d.ts +83 -0
  9. package/dist/managers/ConversationManager.js +129 -0
  10. package/dist/managers/GitManager.d.ts +133 -0
  11. package/dist/managers/GitManager.js +330 -0
  12. package/dist/managers/MetadataManager.d.ts +139 -0
  13. package/dist/managers/MetadataManager.js +309 -0
  14. package/dist/managers/ModelManager.d.ts +57 -0
  15. package/dist/managers/ModelManager.js +129 -0
  16. package/dist/managers/NeovateExecutor.d.ts +40 -0
  17. package/dist/managers/NeovateExecutor.js +138 -0
  18. package/dist/managers/ProjectManager.d.ts +162 -0
  19. package/dist/managers/ProjectManager.js +353 -0
  20. package/dist/managers/ThreadManager.d.ts +181 -0
  21. package/dist/managers/ThreadManager.js +325 -0
  22. package/dist/managers/conversation-manager.d.ts +83 -0
  23. package/dist/managers/conversation-manager.js +129 -0
  24. package/dist/managers/git-manager.d.ts +133 -0
  25. package/dist/managers/git-manager.js +330 -0
  26. package/dist/managers/metadata-manager.d.ts +139 -0
  27. package/dist/managers/metadata-manager.js +305 -0
  28. package/dist/managers/model-manager.d.ts +59 -0
  29. package/dist/managers/model-manager.js +144 -0
  30. package/dist/managers/neovate-executor.d.ts +43 -0
  31. package/dist/managers/neovate-executor.js +205 -0
  32. package/dist/managers/processing-state-manager.d.ts +40 -0
  33. package/dist/managers/processing-state-manager.js +27 -0
  34. package/dist/managers/project-manager.d.ts +199 -0
  35. package/dist/managers/project-manager.js +465 -0
  36. package/dist/managers/thread-manager.d.ts +193 -0
  37. package/dist/managers/thread-manager.js +368 -0
  38. package/dist/model-info-aihubmix.d.ts +25 -0
  39. package/dist/model-info-aihubmix.js +117 -0
  40. package/dist/model-info-openai.d.ts +17 -0
  41. package/dist/model-info-openai.js +59 -0
  42. package/dist/model-info-openrouter.d.ts +25 -0
  43. package/dist/model-info-openrouter.js +101 -0
  44. package/dist/model-info.d.ts +37 -0
  45. package/dist/model-info.js +39 -0
  46. package/dist/provider-data.d.ts +101 -0
  47. package/dist/provider-data.js +471 -0
  48. package/dist/provider.d.ts +10 -0
  49. package/dist/provider.js +192 -0
  50. package/dist/public/android-chrome-192x192.png +0 -0
  51. package/dist/public/android-chrome-512x512.png +0 -0
  52. package/dist/public/apple-touch-icon.png +0 -0
  53. package/dist/public/assets/index-B443aj9k.js +8506 -0
  54. package/dist/public/assets/index-CjXGVbI7.css +1 -0
  55. package/dist/public/assets/index-DJC-p914.js +8506 -0
  56. package/dist/public/favicon-16x16.png +0 -0
  57. package/dist/public/favicon-32x32.png +0 -0
  58. package/dist/public/favicon.ico +0 -0
  59. package/dist/public/index.html +28 -0
  60. package/dist/public/manifest.json +82 -0
  61. package/dist/public/placeholder-logo.svg +1 -0
  62. package/dist/public/placeholder.svg +1 -0
  63. package/dist/public/snpro.woff2 +0 -0
  64. package/dist/public/tarsk-color.svg +12 -0
  65. package/dist/public/tarsk.png +0 -0
  66. package/dist/public/tarsk.svg +12 -0
  67. package/dist/public/zalando-sans.woff2 +0 -0
  68. package/dist/routes/chat-old.d.ts +21 -0
  69. package/dist/routes/chat-old.js +251 -0
  70. package/dist/routes/chat.d.ts +21 -0
  71. package/dist/routes/chat.js +217 -0
  72. package/dist/routes/git.d.ts +4 -0
  73. package/dist/routes/git.js +668 -0
  74. package/dist/routes/models.d.ts +18 -0
  75. package/dist/routes/models.js +128 -0
  76. package/dist/routes/projects-old.d.ts +20 -0
  77. package/dist/routes/projects-old.js +297 -0
  78. package/dist/routes/projects.d.ts +20 -0
  79. package/dist/routes/projects.js +365 -0
  80. package/dist/routes/providers.d.ts +15 -0
  81. package/dist/routes/providers.js +130 -0
  82. package/dist/routes/threads-old.d.ts +14 -0
  83. package/dist/routes/threads-old.js +393 -0
  84. package/dist/routes/threads.d.ts +14 -0
  85. package/dist/routes/threads.js +352 -0
  86. package/dist/types/models.d.ts +315 -0
  87. package/dist/types/models.js +11 -0
  88. package/dist/utils/env-manager.d.ts +3 -0
  89. package/dist/utils/env-manager.js +60 -0
  90. package/dist/utils/open-router-models.d.ts +45 -0
  91. package/dist/utils/open-router-models.js +103 -0
  92. package/dist/utils/openai-models.d.ts +63 -0
  93. package/dist/utils/openai-models.js +152 -0
  94. package/dist/utils/openai-pricing-scraper.d.ts +17 -0
  95. package/dist/utils/openai-pricing-scraper.js +185 -0
  96. package/dist/utils/validation.d.ts +10 -0
  97. package/dist/utils/validation.js +20 -0
  98. package/dist/utils.d.ts +10 -0
  99. package/dist/utils.js +12 -0
  100. package/package.json +36 -22
  101. package/LICENSE.md +0 -7
  102. package/dist/agent/agent.js +0 -131
  103. package/dist/agent/interfaces.js +0 -1
  104. package/dist/api/encryption.js +0 -41
  105. package/dist/api/models.js +0 -169
  106. package/dist/api/prompt.js +0 -12
  107. package/dist/api/settings.js +0 -43
  108. package/dist/api/test.js +0 -29
  109. package/dist/api/tools.js +0 -287
  110. package/dist/api/utils.js +0 -18
  111. package/dist/interfaces/meta.js +0 -1
  112. package/dist/interfaces/model.js +0 -1
  113. package/dist/interfaces/settings.js +0 -1
  114. package/dist/log/log.js +0 -33
  115. package/dist/prompt.js +0 -49
  116. package/dist/tools.js +0 -84
  117. package/dist/utils/files.js +0 -14
  118. package/dist/utils/json-file.js +0 -28
  119. package/dist/utils/strip-markdown.js +0 -5
@@ -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=git-manager.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=metadata-manager.d.ts.map