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,205 @@
1
+ /**
2
+ * NeovateExecutor handles execution of neovate commands via the @neovate/code SDK
3
+ *
4
+ * This manager is responsible for:
5
+ * - Executing streaming sessions via the SDK
6
+ * - Streaming result messages back to the caller
7
+ * - Handling execution errors
8
+ */
9
+ import { createSession, } from "@neovate/code";
10
+ import { resolve } from "path";
11
+ import { PROVIDERS } from "../provider.js";
12
+ const getErrorCode = (error) => {
13
+ if (error && typeof error === "object" && "code" in error) {
14
+ const code = error.code;
15
+ if (typeof code === "string") {
16
+ return code;
17
+ }
18
+ }
19
+ return undefined;
20
+ };
21
+ /**
22
+ * NeovateExecutorImpl provides the implementation for neovate command execution
23
+ * using the @neovate/code SDK with streaming sessions.
24
+ */
25
+ export class NeovateExecutorImpl {
26
+ metadataManager;
27
+ constructor(metadataManager) {
28
+ this.metadataManager = metadataManager;
29
+ }
30
+ /**
31
+ * Executes a neovate prompt using the SDK via streaming sessions
32
+ *
33
+ * @param userPrompt - The user's message/prompt to send to neovate
34
+ * @param context - ExecutionContext with threadId, threadPath, model, and attachments
35
+ * @yields NeovateEvent objects for message, result, and error events
36
+ *
37
+ * Requirements:
38
+ * - 5.2 - WHEN the CLI receives a chat message, THE CLI SHALL execute the Neovate command
39
+ * - 5.4 - WHEN the Neovate command executes, THE CLI SHALL stream the output back to the App
40
+ */
41
+ async *execute(userPrompt, context) {
42
+ let session = null;
43
+ try {
44
+ // Get the provider name from context (defaults to 'openrouter')
45
+ const providerName = context.provider;
46
+ if (!providerName) {
47
+ console.error(`[ai] No provider specified in context`);
48
+ throw new Error("No provider specified in execution context");
49
+ }
50
+ // Ensure model is always defined
51
+ // The model is passed from the frontend (e.g., "openrouter/minimax/minimax-m2.1")
52
+ // We'll validate and ensure it's properly formatted for the SDK
53
+ let model = context.model?.trim();
54
+ if (!model) {
55
+ console.warn("[ai] No model provided in context, using default");
56
+ throw new Error("No model specified in execution context");
57
+ }
58
+ model = model.replace(`${providerName.toLowerCase()}/`, ""); // Remove provider prefix if present
59
+ const cwd = resolve(context.threadPath);
60
+ console.log("[ai] Execution context:", {
61
+ model,
62
+ cwd,
63
+ providerName,
64
+ promptLength: userPrompt.length,
65
+ });
66
+ // Get the provider configuration first to access environment variable name
67
+ const providerConfig = PROVIDERS.find((p) => p.name.toLowerCase() === providerName.toLowerCase());
68
+ if (!providerConfig) {
69
+ throw new Error(`Unknown provider: ${providerName}`);
70
+ }
71
+ // Try to get API key from environment variables first (takes precedence)
72
+ let apiKey = providerConfig.keyName ? process.env[providerConfig.keyName] : undefined;
73
+ let apiKeySource = 'environment';
74
+ // Fall back to metadata manager if not in environment
75
+ if (!apiKey) {
76
+ const providerKeys = await this.metadataManager.getProviderKeys();
77
+ apiKey = providerKeys[providerConfig.name];
78
+ apiKeySource = 'configuration';
79
+ }
80
+ if (!apiKey) {
81
+ throw new Error(`No API key found for provider: ${providerName}. ` +
82
+ `Set ${providerConfig.keyName || 'an API key'} in environment variables or configuration.`);
83
+ }
84
+ console.log(`[ai] API key source for ${providerName}: ${apiKeySource}`);
85
+ const api = providerConfig.api;
86
+ if (!api) {
87
+ throw new Error(`No API URL configured for provider: ${providerName}`);
88
+ }
89
+ const providers = {
90
+ tarsk: {
91
+ api,
92
+ options: { apiKey: apiKey },
93
+ models: { [model]: model },
94
+ },
95
+ };
96
+ const sessionConfig = {
97
+ model: `tarsk/${model}`,
98
+ cwd,
99
+ productName: "Tarsk.io",
100
+ providers,
101
+ };
102
+ console.log("[ai] Creating session:", JSON.stringify(sessionConfig));
103
+ console.log("[ai] Creating session with model:", model);
104
+ console.log("[ai] Session config has model:", !!sessionConfig.model);
105
+ // Create a streaming session - MUST have model defined
106
+ session = await createSession(sessionConfig);
107
+ if (!session) {
108
+ throw new Error("Failed to create session: createSession returned falsy value");
109
+ }
110
+ console.log("[ai] Session created:", session.sessionId);
111
+ // Send the user prompt to the session
112
+ console.log("[ai] Sending prompt to session...");
113
+ await session.send(userPrompt);
114
+ console.log("[ai] Prompt sent, waiting for responses...");
115
+ // Stream messages from the session
116
+ let lastMessageContent = null;
117
+ for await (const msg of session.receive()) {
118
+ const contentLength = typeof msg?.content === "string" ? msg.content.length : undefined;
119
+ console.log("[ai] Received msg:", { type: msg?.type, contentLength });
120
+ console.log("[ai] Msg:", msg);
121
+ if (msg?.type === "message") {
122
+ // Yield conversation messages (assistant responses)
123
+ // Use .text property if available (SDK provides both .content and .text)
124
+ const messageContent = typeof msg.text === "string"
125
+ ? msg.text
126
+ : typeof msg.content === "string"
127
+ ? msg.content
128
+ : JSON.stringify(msg.content);
129
+ lastMessageContent = messageContent;
130
+ yield {
131
+ type: "message",
132
+ role: msg.role || "assistant",
133
+ content: messageContent,
134
+ };
135
+ }
136
+ else if (msg?.type === "result") {
137
+ // Check if result content is a duplicate of the last message
138
+ const resultContent = typeof msg.content === "string"
139
+ ? msg.content
140
+ : JSON.stringify(msg.content);
141
+ // Skip result if it's identical to the last message (avoid duplicate)
142
+ if (resultContent !== lastMessageContent) {
143
+ // Yield the final result only if it's different from the message
144
+ yield {
145
+ type: "result",
146
+ content: resultContent,
147
+ };
148
+ }
149
+ else {
150
+ console.log("[ai] Skipping duplicate result event (same as message)");
151
+ }
152
+ break; // Exit the loop after receiving the result
153
+ }
154
+ }
155
+ }
156
+ catch (error) {
157
+ console.error("[ai] Error during execution:", error);
158
+ let errCode;
159
+ let errMessage;
160
+ let errStack;
161
+ let errDetails;
162
+ if (error instanceof Error) {
163
+ errMessage = error.message || "Unknown error";
164
+ errStack = error.stack;
165
+ errCode = getErrorCode(error);
166
+ }
167
+ else if (typeof error === "object" && error !== null) {
168
+ errMessage = error.message
169
+ ? String(error.message)
170
+ : JSON.stringify(error);
171
+ errCode = getErrorCode(error);
172
+ errDetails = error;
173
+ }
174
+ else if (typeof error === "string") {
175
+ errMessage = error;
176
+ }
177
+ else {
178
+ errMessage = String(error);
179
+ }
180
+ console.error("[ai] Error details:", { errCode, errMessage, errStack });
181
+ yield {
182
+ type: "error",
183
+ content: errMessage,
184
+ error: {
185
+ code: errCode || "EXECUTION_ERROR",
186
+ message: errMessage || "An error occurred during execution",
187
+ details: { stack: errStack, originalError: errDetails },
188
+ },
189
+ };
190
+ }
191
+ finally {
192
+ // Ensure the session is properly closed
193
+ if (session) {
194
+ try {
195
+ await session.close?.();
196
+ console.log("[ai] Session closed");
197
+ }
198
+ catch (closeError) {
199
+ console.error("[ai] Error closing session:", closeError);
200
+ }
201
+ }
202
+ }
203
+ }
204
+ }
205
+ //# sourceMappingURL=neovate-executor.js.map
@@ -0,0 +1,40 @@
1
+ /**
2
+ * ProcessingStateManager tracks which threads currently have active chat processing
3
+ *
4
+ * This is an in-memory store that tracks thread IDs that are currently
5
+ * processing chat messages. The frontend can poll this to show/hide spinners.
6
+ */
7
+ export interface ProcessingStateManager {
8
+ /**
9
+ * Mark a thread as currently processing
10
+ * @param threadId - The thread ID that started processing
11
+ */
12
+ setProcessing(threadId: string): void;
13
+ /**
14
+ * Mark a thread as no longer processing
15
+ * @param threadId - The thread ID that finished processing
16
+ */
17
+ clearProcessing(threadId: string): void;
18
+ /**
19
+ * Check if a thread is currently processing
20
+ * @param threadId - The thread ID to check
21
+ * @returns true if the thread is processing
22
+ */
23
+ isProcessing(threadId: string): boolean;
24
+ /**
25
+ * Get all thread IDs that are currently processing
26
+ * @returns Array of thread IDs
27
+ */
28
+ getProcessingThreadIds(): string[];
29
+ }
30
+ /**
31
+ * Implementation of ProcessingStateManager using an in-memory Set
32
+ */
33
+ export declare class ProcessingStateManagerImpl implements ProcessingStateManager {
34
+ private processingThreads;
35
+ setProcessing(threadId: string): void;
36
+ clearProcessing(threadId: string): void;
37
+ isProcessing(threadId: string): boolean;
38
+ getProcessingThreadIds(): string[];
39
+ }
40
+ //# sourceMappingURL=processing-state-manager.d.ts.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * ProcessingStateManager tracks which threads currently have active chat processing
3
+ *
4
+ * This is an in-memory store that tracks thread IDs that are currently
5
+ * processing chat messages. The frontend can poll this to show/hide spinners.
6
+ */
7
+ /**
8
+ * Implementation of ProcessingStateManager using an in-memory Set
9
+ */
10
+ export class ProcessingStateManagerImpl {
11
+ processingThreads = new Set();
12
+ setProcessing(threadId) {
13
+ this.processingThreads.add(threadId);
14
+ console.log(`[ProcessingState] Thread ${threadId} started processing. Active: ${this.processingThreads.size}`);
15
+ }
16
+ clearProcessing(threadId) {
17
+ this.processingThreads.delete(threadId);
18
+ console.log(`[ProcessingState] Thread ${threadId} finished processing. Active: ${this.processingThreads.size}`);
19
+ }
20
+ isProcessing(threadId) {
21
+ return this.processingThreads.has(threadId);
22
+ }
23
+ getProcessingThreadIds() {
24
+ return Array.from(this.processingThreads);
25
+ }
26
+ }
27
+ //# sourceMappingURL=processing-state-manager.js.map
@@ -0,0 +1,199 @@
1
+ /**
2
+ * ProjectManager handles project lifecycle and metadata management
3
+ *
4
+ * This manager is responsible for:
5
+ * - Creating new projects from git URLs
6
+ * - Managing project metadata
7
+ * - Coordinating with GitManager for repository cloning
8
+ * - Providing CRUD operations for projects
9
+ */
10
+ import { Project, ProjectEvent, Command } from '../types/models.js';
11
+ import { MetadataManager } from './metadata-manager.js';
12
+ import { GitManager } from './git-manager.js';
13
+ /**
14
+ * ProjectManager interface defines the contract for project operations
15
+ */
16
+ export interface ProjectManager {
17
+ /**
18
+ * Creates a new project from a git URL
19
+ * @param gitUrl - The git repository URL
20
+ * @yields ProjectEvent objects during the creation process
21
+ */
22
+ createProject(gitUrl: string): AsyncGenerator<ProjectEvent>;
23
+ /**
24
+ * Gets a project by ID
25
+ * @param projectId - The project ID
26
+ * @returns The project or null if not found
27
+ */
28
+ getProject(projectId: string): Promise<Project | null>;
29
+ /**
30
+ * Lists all projects
31
+ * @returns Array of all projects
32
+ */
33
+ listProjects(): Promise<Project[]>;
34
+ /**
35
+ * Deletes a project and all its threads
36
+ * @param projectId - The project ID to delete
37
+ */
38
+ deleteProject(projectId: string): Promise<void>;
39
+ /**
40
+ * Opens a project in the specified program
41
+ * @param projectId - The project ID
42
+ * @param program - The program to open the project in
43
+ */
44
+ openWith(projectId: string, program: string): Promise<void>;
45
+ /**
46
+ * Updates the project's open-with program preference
47
+ * @param projectId - The project ID
48
+ * @param program - The program name to set
49
+ */
50
+ updateOpenWith(projectId: string, program: string): Promise<void>;
51
+ /**
52
+ * Saves (adds or updates) a command for a project
53
+ * @param projectId - The project ID
54
+ * @param command - The command to save
55
+ */
56
+ saveCommand(projectId: string, command: Command): Promise<void>;
57
+ /**
58
+ * Deletes a command from a project
59
+ * @param projectId - The project ID
60
+ * @param commandId - The ID of the command to delete
61
+ */
62
+ deleteCommand(projectId: string, commandId: string): Promise<void>;
63
+ /**
64
+ * Runs a command in a thread's directory
65
+ * @param threadId - The thread ID where to run the command
66
+ * @param commandLine - The command line to execute
67
+ * @param cwd - Optional working directory relative to thread path
68
+ */
69
+ runCommand(threadId: string, commandLine: string, cwd?: string): AsyncGenerator<unknown>;
70
+ }
71
+ /**
72
+ * ProjectManagerImpl provides the implementation for project operations
73
+ */
74
+ export declare class ProjectManagerImpl implements ProjectManager {
75
+ private rootFolder;
76
+ private metadataManager;
77
+ private gitManager;
78
+ /**
79
+ * Create a new ProjectManager
80
+ * @param rootFolder - Base directory where projects will be stored
81
+ * @param metadataManager - Manager for persisting metadata
82
+ * @param gitManager - Manager for git operations
83
+ *
84
+ * Requirements:
85
+ * - 1.1 - WHEN a user provides a git URL to create a new Project, THE CLI SHALL clone the repository into a folder under the Root_Folder
86
+ * - 1.4 - THE CLI SHALL determine the storage path for each Project folder
87
+ */
88
+ constructor(rootFolder: string, metadataManager: MetadataManager, gitManager: GitManager);
89
+ /**
90
+ * Creates a new project from a git URL
91
+ *
92
+ * This method:
93
+ * 1. Validates the git URL
94
+ * 2. Generates a unique project ID
95
+ * 3. Derives the project name from the git URL
96
+ * 4. Generates the project path
97
+ * 5. Delegates to GitManager for cloning
98
+ * 6. Saves project metadata
99
+ * 7. Yields progress events during the operation
100
+ * 8. Creates an initial thread automatically
101
+ *
102
+ * @param gitUrl - The git repository URL
103
+ * @yields ProjectEvent objects during the creation process
104
+ *
105
+ * Requirements:
106
+ * - 1.1 - WHEN a user provides a git URL to create a new Project, THE CLI SHALL clone the repository into a folder under the Root_Folder
107
+ * - 1.2 - WHEN a Project is created, THE App SHALL display the Project in the Side_Panel with its associated Thread
108
+ * - 1.4 - THE CLI SHALL determine the storage path for each Project folder
109
+ * - 1.5 - WHEN a Project folder is created, THE System SHALL associate it with the provided git URL
110
+ */
111
+ createProject(gitUrl: string): AsyncGenerator<ProjectEvent>;
112
+ /**
113
+ * Gets a project by ID
114
+ * @param projectId - The project ID
115
+ * @returns The project or null if not found
116
+ */
117
+ getProject(projectId: string): Promise<Project | null>;
118
+ /**
119
+ * Lists all projects
120
+ * @returns Array of all projects
121
+ */
122
+ listProjects(): Promise<Project[]>;
123
+ /**
124
+ * Deletes a project and all its threads (cascade delete)
125
+ *
126
+ * This method:
127
+ * 1. Finds the project by ID
128
+ * 2. Removes all associated threads from metadata
129
+ * 3. Removes the project directory from filesystem
130
+ * 4. Removes the project from metadata
131
+ *
132
+ * @param projectId - The project ID to delete
133
+ * @throws Error if project not found
134
+ *
135
+ * Requirements:
136
+ * - 1.1 - Cascade delete for projects (remove all threads)
137
+ */
138
+ deleteProject(projectId: string): Promise<void>;
139
+ /**
140
+ * Derives a project name from a git URL
141
+ *
142
+ * Examples:
143
+ * - https://github.com/user/repo.git -> repo
144
+ * - https://github.com/user/repo -> repo
145
+ * - git@github.com:user/repo.git -> repo
146
+ *
147
+ * @param gitUrl - The git URL
148
+ * @returns The derived project name
149
+ */
150
+ private deriveProjectName;
151
+ /**
152
+ * Generates a project path under the root folder
153
+ *
154
+ * @param projectName - The project name
155
+ * @returns The absolute path to the project folder
156
+ *
157
+ * Requirements:
158
+ * - 1.4 - THE CLI SHALL determine the storage path for each Project folder
159
+ */
160
+ private generateProjectPath;
161
+ /**
162
+ * Gets the root folder path
163
+ * @returns The root folder path
164
+ */
165
+ getRootFolder(): string;
166
+ /**
167
+ * Opens a project in the specified program
168
+ *
169
+ * @param projectId - The project ID
170
+ * @param program - The program to open the project in (VS Code, Cursor, Windsurf, Xcode, Android Studio, Kiro)
171
+ */
172
+ openWith(projectId: string, program: string): Promise<void>;
173
+ /**
174
+ * Updates the project's open-with program preference
175
+ *
176
+ * @param projectId - The project ID
177
+ * @param program - The program name to set
178
+ */
179
+ updateOpenWith(projectId: string, program: string): Promise<void>;
180
+ /**
181
+ * Saves (adds or updates) a command for a project
182
+ * @param projectId - The project ID
183
+ * @param command - The command to save
184
+ */
185
+ saveCommand(projectId: string, command: Command): Promise<void>;
186
+ /**
187
+ * Deletes a command from a project
188
+ * @param projectId - The project ID
189
+ * @param commandId - The ID of the command to delete
190
+ */
191
+ deleteCommand(projectId: string, commandId: string): Promise<void>;
192
+ /**
193
+ * Runs a command in a thread's directory
194
+ * @param threadId - The thread ID where to run the command
195
+ * @param commandLine - The command line to execute
196
+ */
197
+ runCommand(threadId: string, commandLine: string, cwd?: string): AsyncGenerator<unknown>;
198
+ }
199
+ //# sourceMappingURL=project-manager.d.ts.map