propr-cli 0.8.3

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 (64) hide show
  1. package/README.md +549 -0
  2. package/dist/api/agentTank.js +27 -0
  3. package/dist/api/agents.js +201 -0
  4. package/dist/api/client.js +284 -0
  5. package/dist/api/errors.js +145 -0
  6. package/dist/api/implement.js +147 -0
  7. package/dist/api/index.js +26 -0
  8. package/dist/api/logs.js +59 -0
  9. package/dist/api/plans.js +160 -0
  10. package/dist/api/relay.js +73 -0
  11. package/dist/api/repos.js +243 -0
  12. package/dist/api/settings.js +219 -0
  13. package/dist/api/system.js +53 -0
  14. package/dist/api/tasks.js +140 -0
  15. package/dist/api/todos.js +77 -0
  16. package/dist/api/types.js +6 -0
  17. package/dist/assets/.env.example +183 -0
  18. package/dist/assets/env.example.txt +198 -0
  19. package/dist/commands/agentCommands.js +405 -0
  20. package/dist/commands/checkCommands.js +384 -0
  21. package/dist/commands/implementCommands.js +178 -0
  22. package/dist/commands/index.js +22 -0
  23. package/dist/commands/initCommands.js +167 -0
  24. package/dist/commands/initStack.js +193 -0
  25. package/dist/commands/logCommands.js +170 -0
  26. package/dist/commands/planCommands.js +552 -0
  27. package/dist/commands/relayCommands.js +149 -0
  28. package/dist/commands/repoCommands.js +526 -0
  29. package/dist/commands/settingCommands.js +237 -0
  30. package/dist/commands/stackCommands.js +86 -0
  31. package/dist/commands/startCommand.js +36 -0
  32. package/dist/commands/systemCommands.js +221 -0
  33. package/dist/commands/tankCommands.js +55 -0
  34. package/dist/commands/taskCommands.js +554 -0
  35. package/dist/commands/todoCommands.js +620 -0
  36. package/dist/commands/uiDocsCommands.js +69 -0
  37. package/dist/config/ConfigManager.js +360 -0
  38. package/dist/config/index.js +8 -0
  39. package/dist/config/types.js +16 -0
  40. package/dist/index.js +276 -0
  41. package/dist/orchestrator/format.js +31 -0
  42. package/dist/orchestrator/index.js +102 -0
  43. package/dist/orchestrator/manifest.json +16 -0
  44. package/dist/orchestrator/orchestrator.mjs +798 -0
  45. package/dist/orchestrator/types.js +10 -0
  46. package/dist/tui/StartApp.js +175 -0
  47. package/dist/tui/app.js +9 -0
  48. package/dist/tui/render.js +87 -0
  49. package/dist/utils/envFile.js +65 -0
  50. package/dist/utils/index.js +8 -0
  51. package/dist/utils/io.js +186 -0
  52. package/dist/utils/parseState.js +14 -0
  53. package/dist/utils/resolveProject.js +50 -0
  54. package/dist/vendor/shared/demoMode.js +6 -0
  55. package/dist/vendor/shared/events.js +30 -0
  56. package/dist/vendor/shared/githubAuthMode.js +35 -0
  57. package/dist/vendor/shared/index.js +15 -0
  58. package/dist/vendor/shared/labelUtils.js +32 -0
  59. package/dist/vendor/shared/modelDefinitions.js +146 -0
  60. package/dist/vendor/shared/reviewPrompt.js +18 -0
  61. package/dist/vendor/shared/usageTypes.js +13 -0
  62. package/dist/vendor/shared/userWhitelist.js +30 -0
  63. package/dist/vendor/shared/validateRelayUrl.js +21 -0
  64. package/package.json +31 -0
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Repository Configuration API
3
+ *
4
+ * Functions for interacting with the ProPR backend repository configuration endpoints.
5
+ * These functions provide a typed interface to list, add, update, and remove monitored repositories.
6
+ */
7
+ import { createApiClient } from "./index.js";
8
+ /**
9
+ * Fetches the list of monitored repositories.
10
+ *
11
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
12
+ * @returns A promise resolving to the list of monitored repositories.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const result = await getRepos();
17
+ * console.log(`Monitoring ${result.repos_to_monitor.length} repositories`);
18
+ * for (const repo of result.repos_to_monitor) {
19
+ * console.log(`- ${repo.name} (${repo.enabled ? 'enabled' : 'disabled'})`);
20
+ * }
21
+ * ```
22
+ */
23
+ export async function getRepos(client) {
24
+ const apiClient = client ?? (await createApiClient());
25
+ const response = await apiClient.get("/api/config/repos");
26
+ return response.data;
27
+ }
28
+ /**
29
+ * Adds a new repository to the monitored list.
30
+ *
31
+ * @param fullName - The full repository name in "owner/repo" format.
32
+ * @param options - Optional configuration for the repository.
33
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
34
+ * @returns A promise resolving to the updated repository configuration.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * // Add a repository with default settings
39
+ * const result = await addRepo("owner/repo");
40
+ *
41
+ * // Add a repository with custom settings
42
+ * const result = await addRepo("owner/repo", {
43
+ * alias: "my-project",
44
+ * baseBranch: "develop"
45
+ * });
46
+ * ```
47
+ */
48
+ export async function addRepo(fullName, options = {}, client) {
49
+ const apiClient = client ?? (await createApiClient());
50
+ // First, fetch the current list of repos
51
+ const currentRepos = await getRepos(apiClient);
52
+ // Check if repo already exists
53
+ const existingRepo = currentRepos.repos_to_monitor.find((r) => r.name.toLowerCase() === fullName.toLowerCase());
54
+ if (existingRepo) {
55
+ throw new Error(`Repository "${fullName}" is already being monitored`);
56
+ }
57
+ // Create new repo entry
58
+ const newRepo = {
59
+ id: crypto.randomUUID(),
60
+ name: fullName,
61
+ enabled: options.enabled ?? true,
62
+ alias: options.alias?.trim() || undefined,
63
+ baseBranch: options.baseBranch?.trim() || undefined,
64
+ };
65
+ // Add to list and save
66
+ const updatedRepos = [...currentRepos.repos_to_monitor, newRepo];
67
+ const response = await apiClient.post("/api/config/repos", {
68
+ body: { repos_to_monitor: updatedRepos },
69
+ });
70
+ return response.data;
71
+ }
72
+ /**
73
+ * Updates an existing monitored repository.
74
+ *
75
+ * @param fullName - The full repository name in "owner/repo" format.
76
+ * @param updates - The fields to update.
77
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
78
+ * @returns A promise resolving to the updated repository configuration.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * // Enable a repository
83
+ * const result = await updateRepo("owner/repo", { enabled: true });
84
+ *
85
+ * // Update multiple fields
86
+ * const result = await updateRepo("owner/repo", {
87
+ * alias: "new-alias",
88
+ * baseBranch: "main"
89
+ * });
90
+ * ```
91
+ */
92
+ export async function updateRepo(fullName, updates, client) {
93
+ const apiClient = client ?? (await createApiClient());
94
+ // Fetch current repos
95
+ const currentRepos = await getRepos(apiClient);
96
+ // Find the repo to update
97
+ const repoIndex = currentRepos.repos_to_monitor.findIndex((r) => r.name.toLowerCase() === fullName.toLowerCase());
98
+ if (repoIndex === -1) {
99
+ throw new Error(`Repository "${fullName}" is not being monitored`);
100
+ }
101
+ // Apply updates
102
+ const existingRepo = currentRepos.repos_to_monitor[repoIndex];
103
+ const updatedRepo = {
104
+ ...existingRepo,
105
+ ...(updates.enabled !== undefined && { enabled: updates.enabled }),
106
+ ...(updates.alias !== undefined && { alias: updates.alias?.trim() || undefined }),
107
+ ...(updates.baseBranch !== undefined && { baseBranch: updates.baseBranch?.trim() || undefined }),
108
+ };
109
+ // Replace in list
110
+ const updatedRepos = [...currentRepos.repos_to_monitor];
111
+ updatedRepos[repoIndex] = updatedRepo;
112
+ const response = await apiClient.post("/api/config/repos", {
113
+ body: { repos_to_monitor: updatedRepos },
114
+ });
115
+ return response.data;
116
+ }
117
+ /**
118
+ * Removes a repository from the monitored list.
119
+ *
120
+ * @param fullName - The full repository name in "owner/repo" format.
121
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
122
+ * @returns A promise resolving to the updated repository configuration.
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * const result = await removeRepo("owner/repo");
127
+ * console.log(`Now monitoring ${result.repos_to_monitor.length} repositories`);
128
+ * ```
129
+ */
130
+ export async function removeRepo(fullName, client) {
131
+ const apiClient = client ?? (await createApiClient());
132
+ // Fetch current repos
133
+ const currentRepos = await getRepos(apiClient);
134
+ // Find the repo to remove
135
+ const repoIndex = currentRepos.repos_to_monitor.findIndex((r) => r.name.toLowerCase() === fullName.toLowerCase());
136
+ if (repoIndex === -1) {
137
+ throw new Error(`Repository "${fullName}" is not being monitored`);
138
+ }
139
+ // Remove from list
140
+ const updatedRepos = currentRepos.repos_to_monitor.filter((_, index) => index !== repoIndex);
141
+ const response = await apiClient.post("/api/config/repos", {
142
+ body: { repos_to_monitor: updatedRepos },
143
+ });
144
+ return response.data;
145
+ }
146
+ /**
147
+ * Triggers indexing for a repository.
148
+ *
149
+ * @param fullName - The full repository name in "owner/repo" format.
150
+ * @param options - Optional indexing options.
151
+ * @param options.fullReindex - Whether to perform a full reindex. Defaults to true.
152
+ * @param options.baseBranch - The base branch to index.
153
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
154
+ * @returns A promise resolving to the trigger indexing response.
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * // Trigger full reindexing for a repository
159
+ * const result = await triggerIndexing("owner/repo");
160
+ * console.log(`Indexing started with job ID: ${result.jobId}`);
161
+ *
162
+ * // Trigger indexing for a specific branch
163
+ * const result = await triggerIndexing("owner/repo", { baseBranch: "develop" });
164
+ * ```
165
+ */
166
+ export async function triggerIndexing(fullName, options = {}, client) {
167
+ const apiClient = client ?? (await createApiClient());
168
+ const response = await apiClient.post("/api/config/repos/trigger-indexing", {
169
+ body: {
170
+ repository: fullName,
171
+ fullReindex: options.fullReindex ?? true,
172
+ baseBranch: options.baseBranch,
173
+ },
174
+ });
175
+ return response.data;
176
+ }
177
+ /**
178
+ * Gets the indexing status for all repositories or filters for a specific repository.
179
+ *
180
+ * @param fullName - Optional. The full repository name in "owner/repo" format to filter by.
181
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
182
+ * @returns A promise resolving to the indexing status response.
183
+ *
184
+ * @example
185
+ * ```typescript
186
+ * // Get indexing status for all repositories
187
+ * const result = await getIndexingStatus();
188
+ * for (const repo of result.repositories) {
189
+ * console.log(`${repo.full_name}: ${repo.indexing_status}`);
190
+ * }
191
+ *
192
+ * // Get indexing status for a specific repository
193
+ * const result = await getIndexingStatus("owner/repo");
194
+ * const status = result.repositories[0];
195
+ * if (status?.progress) {
196
+ * console.log(`Progress: ${status.progress.percentComplete}%`);
197
+ * }
198
+ * ```
199
+ */
200
+ export async function getIndexingStatus(fullName, client) {
201
+ const apiClient = client ?? (await createApiClient());
202
+ const response = await apiClient.get("/api/config/repos/indexing-status");
203
+ // Filter by fullName if provided
204
+ if (fullName) {
205
+ const filtered = response.data.repositories.filter((repo) => repo.full_name.toLowerCase() === fullName.toLowerCase());
206
+ return { repositories: filtered };
207
+ }
208
+ return response.data;
209
+ }
210
+ /**
211
+ * Repository API namespace providing all repository configuration operations.
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * import { reposApi } from "@propr/cli/api";
216
+ *
217
+ * // List all monitored repos
218
+ * const { repos_to_monitor } = await reposApi.getRepos();
219
+ *
220
+ * // Add a new repo
221
+ * await reposApi.addRepo("owner/repo", { alias: "my-project" });
222
+ *
223
+ * // Update a repo
224
+ * await reposApi.updateRepo("owner/repo", { enabled: false });
225
+ *
226
+ * // Remove a repo
227
+ * await reposApi.removeRepo("owner/repo");
228
+ *
229
+ * // Trigger indexing
230
+ * await reposApi.triggerIndexing("owner/repo");
231
+ *
232
+ * // Get indexing status
233
+ * const status = await reposApi.getIndexingStatus("owner/repo");
234
+ * ```
235
+ */
236
+ export const reposApi = {
237
+ getRepos,
238
+ addRepo,
239
+ updateRepo,
240
+ removeRepo,
241
+ triggerIndexing,
242
+ getIndexingStatus,
243
+ };
@@ -0,0 +1,219 @@
1
+ /**
2
+ * System Settings API
3
+ *
4
+ * Functions for interacting with the ProPR backend system settings endpoints.
5
+ * These functions provide a typed interface to view and update global system configuration
6
+ * like worker concurrency, auto-followup thresholds, and model settings.
7
+ */
8
+ import { createApiClient } from "./index.js";
9
+ /**
10
+ * Maximum allowed length for the free-form `pr_review_prompt` setting.
11
+ * Mirrors the server-side limit enforced in the config routes.
12
+ */
13
+ const MAX_PR_REVIEW_PROMPT_LENGTH = 20000;
14
+ /**
15
+ * List of valid setting keys for validation.
16
+ */
17
+ export const VALID_SETTING_KEYS = [
18
+ "default_agent_alias",
19
+ "worker_concurrency",
20
+ "github_user_whitelist",
21
+ "analysis_model_fast",
22
+ "planner_context_model",
23
+ "planner_generation_model",
24
+ "auto_followup_score_threshold",
25
+ "auto_resolve_merge_conflicts",
26
+ "pr_review_model",
27
+ "pr_review_prompt",
28
+ "ultrafix_rating_goal",
29
+ "ultrafix_max_cycles",
30
+ "ultrafix_pause_seconds",
31
+ ];
32
+ /**
33
+ * Validates if a string is a valid setting key.
34
+ *
35
+ * @param key - The key to validate.
36
+ * @returns True if the key is valid, false otherwise.
37
+ */
38
+ export function isValidSettingKey(key) {
39
+ return VALID_SETTING_KEYS.includes(key);
40
+ }
41
+ /**
42
+ * Parses a value string to the appropriate type for the given setting key.
43
+ *
44
+ * @param key - The setting key.
45
+ * @param value - The value string to parse.
46
+ * @returns The parsed value.
47
+ * @throws Error if the value cannot be parsed for the given key.
48
+ */
49
+ export function parseSettingValue(key, value) {
50
+ switch (key) {
51
+ case "worker_concurrency":
52
+ case "auto_followup_score_threshold": {
53
+ if (!/^-?\d+$/.test(value)) {
54
+ throw new Error(`Invalid value for ${key}: must be an integer`);
55
+ }
56
+ const parsed = Number(value);
57
+ if (!Number.isSafeInteger(parsed)) {
58
+ throw new Error(`Invalid value for ${key}: must be an integer up to ${Number.MAX_SAFE_INTEGER}`);
59
+ }
60
+ if (key === "auto_followup_score_threshold" && (parsed < 0 || parsed > 9)) {
61
+ throw new Error(`Invalid value for ${key}: must be between 0 and 9`);
62
+ }
63
+ if (key === "worker_concurrency" && parsed < 1) {
64
+ throw new Error(`Invalid value for ${key}: must be at least 1`);
65
+ }
66
+ return parsed;
67
+ }
68
+ case "ultrafix_rating_goal": {
69
+ if (!/^\d+$/.test(value)) {
70
+ throw new Error(`Invalid value for ${key}: must be a positive integer between 1 and 10`);
71
+ }
72
+ const parsed = Number(value);
73
+ if (parsed < 1 || parsed > 10) {
74
+ throw new Error(`Invalid value for ${key}: must be a number between 1 and 10`);
75
+ }
76
+ return parsed;
77
+ }
78
+ case "ultrafix_max_cycles": {
79
+ if (!/^\d+$/.test(value)) {
80
+ throw new Error(`Invalid value for ${key}: must be a positive integer`);
81
+ }
82
+ const parsed = Number(value);
83
+ if (parsed < 1 || !Number.isSafeInteger(parsed)) {
84
+ throw new Error(`Invalid value for ${key}: must be a positive integer up to ${Number.MAX_SAFE_INTEGER}`);
85
+ }
86
+ return parsed;
87
+ }
88
+ case "ultrafix_pause_seconds": {
89
+ if (!/^\d+$/.test(value)) {
90
+ throw new Error(`Invalid value for ${key}: must be a non-negative integer`);
91
+ }
92
+ const parsed = Number(value);
93
+ if (parsed < 0 || !Number.isSafeInteger(parsed)) {
94
+ throw new Error(`Invalid value for ${key}: must be a non-negative integer up to ${Number.MAX_SAFE_INTEGER}`);
95
+ }
96
+ return parsed;
97
+ }
98
+ case "auto_resolve_merge_conflicts": {
99
+ const lower = value.toLowerCase();
100
+ if (lower !== "true" && lower !== "false") {
101
+ throw new Error(`Invalid value for ${key}: must be "true" or "false"`);
102
+ }
103
+ return lower === "true";
104
+ }
105
+ case "github_user_whitelist":
106
+ // Parse comma-separated list
107
+ return value.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
108
+ case "analysis_model_fast":
109
+ case "default_agent_alias":
110
+ case "planner_context_model":
111
+ case "planner_generation_model":
112
+ return value;
113
+ case "pr_review_model": {
114
+ const trimmed = value.trim();
115
+ if (trimmed === '' && value.length > 0) {
116
+ throw new Error(`Invalid value for ${key}: must not be whitespace-only; use an empty string to clear`);
117
+ }
118
+ return trimmed;
119
+ }
120
+ case "pr_review_prompt": {
121
+ if (value.length > MAX_PR_REVIEW_PROMPT_LENGTH) {
122
+ throw new Error(`Invalid value for ${key}: must be at most ${MAX_PR_REVIEW_PROMPT_LENGTH} characters`);
123
+ }
124
+ return value;
125
+ }
126
+ default:
127
+ return value;
128
+ }
129
+ }
130
+ /**
131
+ * Fetches the current system settings.
132
+ *
133
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
134
+ * @returns A promise resolving to the current system settings.
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const settings = await getSettings();
139
+ * console.log(`Worker concurrency: ${settings.worker_concurrency}`);
140
+ * console.log(`Auto-followup threshold: ${settings.auto_followup_score_threshold}`);
141
+ * ```
142
+ */
143
+ export async function getSettings(client) {
144
+ const apiClient = client ?? (await createApiClient());
145
+ const response = await apiClient.get("/api/config/settings");
146
+ return response.data;
147
+ }
148
+ /**
149
+ * Updates one or more system settings.
150
+ *
151
+ * @param settings - Object containing settings to update.
152
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
153
+ * @returns A promise resolving to the update response.
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * // Update a single setting
158
+ * await updateSettings({ worker_concurrency: 10 });
159
+ *
160
+ * // Update multiple settings
161
+ * await updateSettings({
162
+ * worker_concurrency: 10,
163
+ * auto_followup_score_threshold: 7
164
+ * });
165
+ * ```
166
+ */
167
+ export async function updateSettings(settings, client) {
168
+ const apiClient = client ?? (await createApiClient());
169
+ const response = await apiClient.post("/api/config/settings", {
170
+ body: { settings },
171
+ });
172
+ return response.data;
173
+ }
174
+ /**
175
+ * Updates a single system setting by key.
176
+ *
177
+ * @param key - The setting key to update.
178
+ * @param value - The new value for the setting.
179
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
180
+ * @returns A promise resolving to the update response.
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * // Update worker concurrency
185
+ * await updateSetting("worker_concurrency", 10);
186
+ *
187
+ * // Update auto-followup threshold
188
+ * await updateSetting("auto_followup_score_threshold", 7);
189
+ * ```
190
+ */
191
+ export async function updateSetting(key, value, client) {
192
+ const settings = { [key]: value };
193
+ return updateSettings(settings, client);
194
+ }
195
+ /**
196
+ * Settings API namespace providing all system settings operations.
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * import { settingsApi } from "@propr/cli/api";
201
+ *
202
+ * // Get current settings
203
+ * const settings = await settingsApi.getSettings();
204
+ *
205
+ * // Update settings
206
+ * await settingsApi.updateSettings({ worker_concurrency: 10 });
207
+ *
208
+ * // Update a single setting
209
+ * await settingsApi.updateSetting("auto_followup_score_threshold", 7);
210
+ * ```
211
+ */
212
+ export const settingsApi = {
213
+ getSettings,
214
+ updateSettings,
215
+ updateSetting,
216
+ isValidSettingKey,
217
+ parseSettingValue,
218
+ VALID_SETTING_KEYS,
219
+ };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * System Status API
3
+ *
4
+ * Functions for interacting with the ProPR backend system status and queue endpoints.
5
+ * These functions provide a typed interface to check system health and queue statistics.
6
+ */
7
+ import { createApiClient } from "./index.js";
8
+ /**
9
+ * Fetches the current system status from the backend.
10
+ *
11
+ * This function retrieves health information about various backend components
12
+ * including the API, Redis, daemon, workers, and authentication status.
13
+ *
14
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
15
+ * @returns A promise resolving to the system status.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * // Get system status
20
+ * const status = await getSystemStatus();
21
+ * console.log(`API: ${status.api}`);
22
+ * console.log(`Redis: ${status.redis}`);
23
+ * console.log(`Workers: ${status.workerCount}`);
24
+ * ```
25
+ */
26
+ export async function getSystemStatus(client) {
27
+ const apiClient = client ?? (await createApiClient());
28
+ const response = await apiClient.get("/api/status");
29
+ return response.data;
30
+ }
31
+ /**
32
+ * Fetches queue statistics from the backend.
33
+ *
34
+ * This function retrieves information about the current state of the task queue
35
+ * including counts of waiting, active, completed, failed, and delayed jobs.
36
+ *
37
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
38
+ * @returns A promise resolving to the queue statistics.
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * // Get queue stats
43
+ * const stats = await getQueueStats();
44
+ * console.log(`Active: ${stats.active}`);
45
+ * console.log(`Completed: ${stats.completed}`);
46
+ * console.log(`Failed: ${stats.failed}`);
47
+ * ```
48
+ */
49
+ export async function getQueueStats(client) {
50
+ const apiClient = client ?? (await createApiClient());
51
+ const response = await apiClient.get("/api/queue/stats");
52
+ return response.data;
53
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Tasks API
3
+ *
4
+ * Functions for interacting with the ProPR backend task management endpoints.
5
+ * These functions provide a typed interface to list, get, stop, and delete tasks.
6
+ */
7
+ import { createApiClient } from "./index.js";
8
+ /**
9
+ * Lists tasks from the backend with optional filtering.
10
+ *
11
+ * @param options - Optional filtering and pagination options.
12
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
13
+ * @returns A promise resolving to the list of tasks with pagination info.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // List all tasks
18
+ * const result = await listTasks();
19
+ * console.log(`Found ${result.total} tasks`);
20
+ *
21
+ * // List tasks for a specific project
22
+ * const result = await listTasks({ repository: "owner/repo" });
23
+ *
24
+ * // List tasks with a specific status
25
+ * const result = await listTasks({ status: "completed" });
26
+ * ```
27
+ */
28
+ export async function listTasks(options = {}, client) {
29
+ const apiClient = client ?? (await createApiClient());
30
+ const params = {};
31
+ if (options.status !== undefined) {
32
+ params.status = options.status;
33
+ }
34
+ if (options.repository !== undefined) {
35
+ params.repository = options.repository;
36
+ }
37
+ if (options.limit !== undefined) {
38
+ params.limit = String(options.limit);
39
+ }
40
+ if (options.offset !== undefined) {
41
+ params.offset = String(options.offset);
42
+ }
43
+ if (options.search !== undefined) {
44
+ params.search = options.search;
45
+ }
46
+ const response = await apiClient.get("/api/tasks", {
47
+ params,
48
+ });
49
+ return response.data;
50
+ }
51
+ /**
52
+ * Stops a running task by cancelling it.
53
+ *
54
+ * This function sends a cancellation request to the backend to stop
55
+ * a task that is currently in progress.
56
+ *
57
+ * @param taskId - The unique identifier of the task to stop.
58
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
59
+ * @returns A promise resolving to the stop response.
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * // Stop a running task
64
+ * const result = await stopTask("task-abc123");
65
+ * if (result.success) {
66
+ * console.log("Task stopped successfully");
67
+ * }
68
+ * ```
69
+ */
70
+ export async function stopTask(taskId, client) {
71
+ const apiClient = client ?? (await createApiClient());
72
+ const endpoint = `/api/task/${encodeURIComponent(taskId)}/cancel`;
73
+ const response = await apiClient.post(endpoint);
74
+ return response.data;
75
+ }
76
+ /**
77
+ * Deletes a task from the system.
78
+ *
79
+ * This function removes a task and its associated data from the backend.
80
+ * By default, it will not delete tasks that are in an active state.
81
+ * Use the force option to override this check.
82
+ *
83
+ * @param taskId - The unique identifier of the task to delete.
84
+ * @param force - If true, force deletion even for active tasks.
85
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
86
+ * @returns A promise that resolves when the task is deleted.
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * // Delete a completed task
91
+ * await deleteTask("task-abc123");
92
+ *
93
+ * // Force delete an active task
94
+ * await deleteTask("task-abc123", true);
95
+ * ```
96
+ */
97
+ export async function deleteTask(taskId, force = false, client) {
98
+ const apiClient = client ?? (await createApiClient());
99
+ const endpoint = `/api/task/${encodeURIComponent(taskId)}`;
100
+ const params = {};
101
+ if (force) {
102
+ params.force = "true";
103
+ }
104
+ await apiClient.delete(endpoint, { params });
105
+ }
106
+ /**
107
+ * Queues a revert task to revert changes from a specific commit in a PR.
108
+ *
109
+ * This function sends a revert request to the backend to queue a background
110
+ * job that will revert the specified commit from the PR.
111
+ *
112
+ * @param owner - The repository owner.
113
+ * @param repo - The repository name.
114
+ * @param prNumber - The PR number.
115
+ * @param commitHash - The commit hash to revert.
116
+ * @param commentId - The comment ID that triggered the revert.
117
+ * @param client - Optional ApiClient instance. If not provided, one will be created.
118
+ * @returns A promise resolving to the revert task response.
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * // Revert a commit from a PR
123
+ * const result = await revertTask("owner", "repo", 42, "abc1234", 12345);
124
+ * if (result.success) {
125
+ * console.log(`Revert task queued: ${result.jobId}`);
126
+ * }
127
+ * ```
128
+ */
129
+ export async function revertTask(owner, repo, prNumber, commitHash, commentId, client) {
130
+ const apiClient = client ?? (await createApiClient());
131
+ const body = {
132
+ owner,
133
+ repo,
134
+ pr: String(prNumber),
135
+ commit: commitHash,
136
+ commentId: String(commentId),
137
+ };
138
+ const response = await apiClient.post("/api/tasks/revert", { body });
139
+ return response.data;
140
+ }