@simonfestl/husky-cli 1.25.4 → 1.26.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/dist/commands/auth.js +9 -47
- package/dist/commands/business.d.ts +2 -0
- package/dist/commands/business.js +865 -0
- package/dist/commands/config.js +33 -45
- package/dist/commands/task.js +90 -293
- package/dist/index.js +2 -0
- package/dist/lib/worker.d.ts +3 -3
- package/dist/lib/worker.js +37 -39
- package/package.json +3 -1
package/dist/commands/task.js
CHANGED
|
@@ -10,6 +10,7 @@ import { resolveProject, fetchProjects, formatProjectList } from "../lib/project
|
|
|
10
10
|
import { requirePermission } from "../lib/permissions.js";
|
|
11
11
|
import { ErrorHelpers, errorWithHint, ExplainTopic } from "../lib/error-hints.js";
|
|
12
12
|
import { AgentLock, AgentLockError } from "../lib/agent-lock.js";
|
|
13
|
+
import { getApiClient } from "../lib/api-client.js";
|
|
13
14
|
export const taskCommand = new Command("task")
|
|
14
15
|
.description("Manage tasks");
|
|
15
16
|
// Helper: Get task ID from --id flag or HUSKY_TASK_ID env var
|
|
@@ -89,14 +90,10 @@ function createWorktreeForTask(taskId) {
|
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
92
|
// Helper: Find project ID by GitHub repo identifier
|
|
92
|
-
async function findProjectByRepo(
|
|
93
|
+
async function findProjectByRepo(repoIdentifier) {
|
|
93
94
|
try {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
});
|
|
97
|
-
if (!res.ok)
|
|
98
|
-
return null;
|
|
99
|
-
const projects = await res.json();
|
|
95
|
+
const api = getApiClient();
|
|
96
|
+
const projects = await api.get("/api/projects");
|
|
100
97
|
// Extract repo name (e.g., "huskyv0" from "simon-sfxecom/huskyv0")
|
|
101
98
|
const repoName = repoIdentifier.split("/").pop()?.toLowerCase() || "";
|
|
102
99
|
// Try to match by:
|
|
@@ -144,8 +141,8 @@ taskCommand
|
|
|
144
141
|
let filterProjectId = null;
|
|
145
142
|
if (!options.all && !options.project) {
|
|
146
143
|
const repoIdentifier = getGitRepoIdentifier();
|
|
147
|
-
if (repoIdentifier
|
|
148
|
-
autoDetectedProject = await findProjectByRepo(
|
|
144
|
+
if (repoIdentifier) {
|
|
145
|
+
autoDetectedProject = await findProjectByRepo(repoIdentifier);
|
|
149
146
|
if (autoDetectedProject) {
|
|
150
147
|
filterProjectId = autoDetectedProject.id;
|
|
151
148
|
}
|
|
@@ -156,13 +153,8 @@ taskCommand
|
|
|
156
153
|
}
|
|
157
154
|
// Note: We don't pass projectId to API to avoid Firestore index requirement
|
|
158
155
|
// Instead, we filter client-side which is fine for reasonable task counts
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
});
|
|
162
|
-
if (!res.ok) {
|
|
163
|
-
throw new Error(`API error: ${res.status}`);
|
|
164
|
-
}
|
|
165
|
-
let tasks = await res.json();
|
|
156
|
+
const api = getApiClient();
|
|
157
|
+
let tasks = await api.get(url.pathname + url.search);
|
|
166
158
|
// Client-side filtering by projectId (avoids Firestore composite index)
|
|
167
159
|
if (filterProjectId) {
|
|
168
160
|
tasks = tasks.filter(t => t.projectId === filterProjectId);
|
|
@@ -259,27 +251,17 @@ taskCommand
|
|
|
259
251
|
}
|
|
260
252
|
}
|
|
261
253
|
}
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
// Include worktree info if created
|
|
273
|
-
...(worktreeInfo ? {
|
|
274
|
-
worktreePath: worktreeInfo.path,
|
|
275
|
-
worktreeBranch: worktreeInfo.branch,
|
|
276
|
-
} : {}),
|
|
277
|
-
}),
|
|
254
|
+
const api = getApiClient();
|
|
255
|
+
const task = await api.post(`/api/tasks/${id}/start`, {
|
|
256
|
+
agent: "claude-code",
|
|
257
|
+
workerId,
|
|
258
|
+
sessionId,
|
|
259
|
+
// Include worktree info if created
|
|
260
|
+
...(worktreeInfo ? {
|
|
261
|
+
worktreePath: worktreeInfo.path,
|
|
262
|
+
worktreeBranch: worktreeInfo.branch,
|
|
263
|
+
} : {}),
|
|
278
264
|
});
|
|
279
|
-
if (!res.ok) {
|
|
280
|
-
throw new Error(`API error: ${res.status}`);
|
|
281
|
-
}
|
|
282
|
-
const task = await res.json();
|
|
283
265
|
console.log(`✓ Started: ${task.title}`);
|
|
284
266
|
console.log(` Worker: ${workerId}`);
|
|
285
267
|
console.log(` Session: ${sessionId}`);
|
|
@@ -310,21 +292,11 @@ taskCommand
|
|
|
310
292
|
process.exit(1);
|
|
311
293
|
}
|
|
312
294
|
try {
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
|
|
318
|
-
},
|
|
319
|
-
body: JSON.stringify({
|
|
320
|
-
prUrl: options.pr,
|
|
321
|
-
skipQA: options.skipQa === true,
|
|
322
|
-
}),
|
|
295
|
+
const api = getApiClient();
|
|
296
|
+
const task = await api.post(`/api/tasks/${id}/done`, {
|
|
297
|
+
prUrl: options.pr,
|
|
298
|
+
skipQA: options.skipQa === true,
|
|
323
299
|
});
|
|
324
|
-
if (!res.ok) {
|
|
325
|
-
throw new Error(`API error: ${res.status}`);
|
|
326
|
-
}
|
|
327
|
-
const task = await res.json();
|
|
328
300
|
if (task.qaTriggered) {
|
|
329
301
|
console.log(`✓ Task moved to review: ${task.title}`);
|
|
330
302
|
console.log(` QA pipeline triggered - awaiting verification`);
|
|
@@ -384,23 +356,12 @@ taskCommand
|
|
|
384
356
|
process.exit(1);
|
|
385
357
|
}
|
|
386
358
|
try {
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
},
|
|
393
|
-
body: JSON.stringify({
|
|
394
|
-
targetHostname: options.worker,
|
|
395
|
-
priority: options.priority,
|
|
396
|
-
instructions: options.instructions,
|
|
397
|
-
}),
|
|
359
|
+
const api = getApiClient();
|
|
360
|
+
const result = await api.post(`/api/tasks/${id}/assign`, {
|
|
361
|
+
targetHostname: options.worker,
|
|
362
|
+
priority: options.priority,
|
|
363
|
+
instructions: options.instructions,
|
|
398
364
|
});
|
|
399
|
-
if (!res.ok) {
|
|
400
|
-
const errorData = await res.json().catch(() => ({}));
|
|
401
|
-
throw new Error(errorData.error || `API error: ${res.status}`);
|
|
402
|
-
}
|
|
403
|
-
const result = await res.json();
|
|
404
365
|
if (options.json) {
|
|
405
366
|
console.log(JSON.stringify(result, null, 2));
|
|
406
367
|
}
|
|
@@ -457,25 +418,14 @@ taskCommand
|
|
|
457
418
|
resolvedProjectId = resolved.projectId;
|
|
458
419
|
}
|
|
459
420
|
try {
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
title,
|
|
468
|
-
description: options.description,
|
|
469
|
-
projectId: resolvedProjectId,
|
|
470
|
-
linkedPath: options.path,
|
|
471
|
-
priority: options.priority,
|
|
472
|
-
}),
|
|
421
|
+
const api = getApiClient();
|
|
422
|
+
const task = await api.post("/api/tasks", {
|
|
423
|
+
title,
|
|
424
|
+
description: options.description,
|
|
425
|
+
projectId: resolvedProjectId,
|
|
426
|
+
linkedPath: options.path,
|
|
427
|
+
priority: options.priority,
|
|
473
428
|
});
|
|
474
|
-
if (!res.ok) {
|
|
475
|
-
const errorData = await res.json().catch(() => ({}));
|
|
476
|
-
throw new Error(errorData.error || `API error: ${res.status}`);
|
|
477
|
-
}
|
|
478
|
-
const task = await res.json();
|
|
479
429
|
console.log(`✓ Created: #${task.id} ${task.title}`);
|
|
480
430
|
}
|
|
481
431
|
catch (error) {
|
|
@@ -542,24 +492,8 @@ taskCommand
|
|
|
542
492
|
}
|
|
543
493
|
}
|
|
544
494
|
try {
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
headers: {
|
|
548
|
-
"Content-Type": "application/json",
|
|
549
|
-
...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
|
|
550
|
-
},
|
|
551
|
-
body: JSON.stringify(updates),
|
|
552
|
-
});
|
|
553
|
-
if (!res.ok) {
|
|
554
|
-
if (res.status === 404) {
|
|
555
|
-
console.error(`Error: Task ${id} not found`);
|
|
556
|
-
}
|
|
557
|
-
else {
|
|
558
|
-
console.error(`Error: API returned ${res.status}`);
|
|
559
|
-
}
|
|
560
|
-
process.exit(1);
|
|
561
|
-
}
|
|
562
|
-
const task = await res.json();
|
|
495
|
+
const api = getApiClient();
|
|
496
|
+
const task = await api.patch(`/api/tasks/${id}`, updates);
|
|
563
497
|
if (options.json) {
|
|
564
498
|
console.log(JSON.stringify(task, null, 2));
|
|
565
499
|
}
|
|
@@ -587,23 +521,12 @@ taskCommand
|
|
|
587
521
|
.option("--json", "Output as JSON")
|
|
588
522
|
.action(async (id, options) => {
|
|
589
523
|
const config = ensureConfig();
|
|
524
|
+
const api = getApiClient();
|
|
590
525
|
// Confirm deletion unless --force is provided
|
|
591
526
|
if (!options.force) {
|
|
592
527
|
// First fetch task details to show what will be deleted
|
|
593
528
|
try {
|
|
594
|
-
const
|
|
595
|
-
headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
|
|
596
|
-
});
|
|
597
|
-
if (!getRes.ok) {
|
|
598
|
-
if (getRes.status === 404) {
|
|
599
|
-
console.error(`Error: Task ${id} not found`);
|
|
600
|
-
}
|
|
601
|
-
else {
|
|
602
|
-
console.error(`Error: API returned ${getRes.status}`);
|
|
603
|
-
}
|
|
604
|
-
process.exit(1);
|
|
605
|
-
}
|
|
606
|
-
const task = await getRes.json();
|
|
529
|
+
const task = await api.get(`/api/tasks/${id}`);
|
|
607
530
|
const confirmed = await confirm(`Delete task "${task.title}" (${id})?`);
|
|
608
531
|
if (!confirmed) {
|
|
609
532
|
console.log("Deletion cancelled.");
|
|
@@ -616,19 +539,7 @@ taskCommand
|
|
|
616
539
|
}
|
|
617
540
|
}
|
|
618
541
|
try {
|
|
619
|
-
|
|
620
|
-
method: "DELETE",
|
|
621
|
-
headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
|
|
622
|
-
});
|
|
623
|
-
if (!res.ok) {
|
|
624
|
-
if (res.status === 404) {
|
|
625
|
-
console.error(`Error: Task ${id} not found`);
|
|
626
|
-
}
|
|
627
|
-
else {
|
|
628
|
-
console.error(`Error: API returned ${res.status}`);
|
|
629
|
-
}
|
|
630
|
-
process.exit(1);
|
|
631
|
-
}
|
|
542
|
+
await api.delete(`/api/tasks/${id}`);
|
|
632
543
|
if (options.json) {
|
|
633
544
|
console.log(JSON.stringify({ deleted: true, id }, null, 2));
|
|
634
545
|
}
|
|
@@ -651,19 +562,8 @@ taskCommand
|
|
|
651
562
|
const config = ensureConfig();
|
|
652
563
|
const taskId = getTaskId(options);
|
|
653
564
|
try {
|
|
654
|
-
const
|
|
655
|
-
|
|
656
|
-
});
|
|
657
|
-
if (!res.ok) {
|
|
658
|
-
if (res.status === 404) {
|
|
659
|
-
console.error(`Error: Task ${taskId} not found`);
|
|
660
|
-
}
|
|
661
|
-
else {
|
|
662
|
-
console.error(`Error: API returned ${res.status}`);
|
|
663
|
-
}
|
|
664
|
-
process.exit(1);
|
|
665
|
-
}
|
|
666
|
-
const task = await res.json();
|
|
565
|
+
const api = getApiClient();
|
|
566
|
+
const task = await api.get(`/api/tasks/${taskId}`);
|
|
667
567
|
if (options.json) {
|
|
668
568
|
console.log(JSON.stringify(task, null, 2));
|
|
669
569
|
}
|
|
@@ -696,20 +596,11 @@ taskCommand
|
|
|
696
596
|
const config = ensureConfig();
|
|
697
597
|
const taskId = getTaskId(options);
|
|
698
598
|
try {
|
|
699
|
-
const
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
|
|
704
|
-
},
|
|
705
|
-
body: JSON.stringify({
|
|
706
|
-
message,
|
|
707
|
-
timestamp: new Date().toISOString(),
|
|
708
|
-
}),
|
|
599
|
+
const api = getApiClient();
|
|
600
|
+
await api.post(`/api/tasks/${taskId}/status`, {
|
|
601
|
+
message,
|
|
602
|
+
timestamp: new Date().toISOString(),
|
|
709
603
|
});
|
|
710
|
-
if (!res.ok) {
|
|
711
|
-
throw new Error(`API error: ${res.status}`);
|
|
712
|
-
}
|
|
713
604
|
console.log(`✓ Status updated: ${message}`);
|
|
714
605
|
}
|
|
715
606
|
catch (error) {
|
|
@@ -735,20 +626,11 @@ taskCommand
|
|
|
735
626
|
errorWithHint("Message required. Use positional arg or -m/--message", ExplainTopic.TASK, "See message command examples");
|
|
736
627
|
}
|
|
737
628
|
try {
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
|
|
743
|
-
},
|
|
744
|
-
body: JSON.stringify({
|
|
745
|
-
message,
|
|
746
|
-
timestamp: new Date().toISOString(),
|
|
747
|
-
}),
|
|
629
|
+
const api = getApiClient();
|
|
630
|
+
await api.post(`/api/tasks/${taskId}/status`, {
|
|
631
|
+
message,
|
|
632
|
+
timestamp: new Date().toISOString(),
|
|
748
633
|
});
|
|
749
|
-
if (!res.ok) {
|
|
750
|
-
throw new Error(`API error: ${res.status}`);
|
|
751
|
-
}
|
|
752
634
|
console.log("✓ Status message posted");
|
|
753
635
|
}
|
|
754
636
|
catch (error) {
|
|
@@ -796,21 +678,12 @@ taskCommand
|
|
|
796
678
|
}
|
|
797
679
|
const steps = options.steps ? options.steps.split(",").map((s) => s.trim()) : undefined;
|
|
798
680
|
try {
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
},
|
|
805
|
-
body: JSON.stringify({
|
|
806
|
-
summary: summary || "Execution plan",
|
|
807
|
-
steps,
|
|
808
|
-
content,
|
|
809
|
-
}),
|
|
681
|
+
const api = getApiClient();
|
|
682
|
+
await api.post(`/api/tasks/${taskId}/plan`, {
|
|
683
|
+
summary: summary || "Execution plan",
|
|
684
|
+
steps,
|
|
685
|
+
content,
|
|
810
686
|
});
|
|
811
|
-
if (!res.ok) {
|
|
812
|
-
throw new Error(`API error: ${res.status}`);
|
|
813
|
-
}
|
|
814
687
|
console.log(`✓ Plan submitted for task ${taskId}`);
|
|
815
688
|
console.log(" Waiting for approval...");
|
|
816
689
|
}
|
|
@@ -832,15 +705,10 @@ taskCommand
|
|
|
832
705
|
const pollInterval = 5000; // 5 seconds
|
|
833
706
|
const startTime = Date.now();
|
|
834
707
|
console.log(`Waiting for approval on task ${taskId}...`);
|
|
708
|
+
const api = getApiClient();
|
|
835
709
|
while (Date.now() - startTime < timeout) {
|
|
836
710
|
try {
|
|
837
|
-
const
|
|
838
|
-
headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
|
|
839
|
-
});
|
|
840
|
-
if (!res.ok) {
|
|
841
|
-
throw new Error(`API error: ${res.status}`);
|
|
842
|
-
}
|
|
843
|
-
const data = await res.json();
|
|
711
|
+
const data = await api.get(`/api/tasks/${taskId}/approval`);
|
|
844
712
|
if (data.approved === true && data.pending === false) {
|
|
845
713
|
console.log("✓ Plan approved!");
|
|
846
714
|
process.exit(0);
|
|
@@ -875,21 +743,12 @@ taskCommand
|
|
|
875
743
|
const config = ensureConfig();
|
|
876
744
|
const taskId = getTaskId(options);
|
|
877
745
|
try {
|
|
878
|
-
const
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
},
|
|
884
|
-
body: JSON.stringify({
|
|
885
|
-
output: options.output,
|
|
886
|
-
prUrl: options.pr,
|
|
887
|
-
error: options.error,
|
|
888
|
-
}),
|
|
746
|
+
const api = getApiClient();
|
|
747
|
+
await api.post(`/api/tasks/${taskId}/complete`, {
|
|
748
|
+
output: options.output,
|
|
749
|
+
prUrl: options.pr,
|
|
750
|
+
error: options.error,
|
|
889
751
|
});
|
|
890
|
-
if (!res.ok) {
|
|
891
|
-
throw new Error(`API error: ${res.status}`);
|
|
892
|
-
}
|
|
893
752
|
if (options.error) {
|
|
894
753
|
console.log(`✗ Task ${taskId} marked as failed`);
|
|
895
754
|
}
|
|
@@ -919,21 +778,11 @@ taskCommand
|
|
|
919
778
|
const config = ensureConfig();
|
|
920
779
|
const taskId = getTaskId(options);
|
|
921
780
|
try {
|
|
922
|
-
const
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
|
|
927
|
-
},
|
|
928
|
-
body: JSON.stringify({
|
|
929
|
-
maxIterations: parseInt(options.maxIterations, 10),
|
|
930
|
-
autoFix: options.autoFix !== false,
|
|
931
|
-
}),
|
|
781
|
+
const api = getApiClient();
|
|
782
|
+
const data = await api.post(`/api/tasks/${taskId}/qa/start`, {
|
|
783
|
+
maxIterations: parseInt(options.maxIterations, 10),
|
|
784
|
+
autoFix: options.autoFix !== false,
|
|
932
785
|
});
|
|
933
|
-
if (!res.ok) {
|
|
934
|
-
throw new Error(`API error: ${res.status}`);
|
|
935
|
-
}
|
|
936
|
-
const data = await res.json();
|
|
937
786
|
console.log(`✓ QA validation started for task ${taskId}`);
|
|
938
787
|
console.log(` Max iterations: ${data.maxIterations}`);
|
|
939
788
|
console.log(` Status: ${data.qaStatus}`);
|
|
@@ -953,13 +802,8 @@ taskCommand
|
|
|
953
802
|
const config = ensureConfig();
|
|
954
803
|
const taskId = getTaskId(options);
|
|
955
804
|
try {
|
|
956
|
-
const
|
|
957
|
-
|
|
958
|
-
});
|
|
959
|
-
if (!res.ok) {
|
|
960
|
-
throw new Error(`API error: ${res.status}`);
|
|
961
|
-
}
|
|
962
|
-
const data = await res.json();
|
|
805
|
+
const api = getApiClient();
|
|
806
|
+
const data = await api.get(`/api/tasks/${taskId}/qa/status`);
|
|
963
807
|
if (options.json) {
|
|
964
808
|
console.log(JSON.stringify(data, null, 2));
|
|
965
809
|
}
|
|
@@ -1002,20 +846,11 @@ taskCommand
|
|
|
1002
846
|
const config = ensureConfig();
|
|
1003
847
|
const taskId = getTaskId(options);
|
|
1004
848
|
try {
|
|
1005
|
-
const
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
|
|
1010
|
-
},
|
|
1011
|
-
body: JSON.stringify({
|
|
1012
|
-
approved: true,
|
|
1013
|
-
notes: options.notes,
|
|
1014
|
-
}),
|
|
849
|
+
const api = getApiClient();
|
|
850
|
+
await api.post(`/api/tasks/${taskId}/qa/approve`, {
|
|
851
|
+
approved: true,
|
|
852
|
+
notes: options.notes,
|
|
1015
853
|
});
|
|
1016
|
-
if (!res.ok) {
|
|
1017
|
-
throw new Error(`API error: ${res.status}`);
|
|
1018
|
-
}
|
|
1019
854
|
console.log(`✓ QA manually approved for task ${taskId}`);
|
|
1020
855
|
}
|
|
1021
856
|
catch (error) {
|
|
@@ -1044,20 +879,11 @@ taskCommand
|
|
|
1044
879
|
}
|
|
1045
880
|
}
|
|
1046
881
|
try {
|
|
1047
|
-
const
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
|
|
1052
|
-
},
|
|
1053
|
-
body: JSON.stringify({
|
|
1054
|
-
notes: options.notes,
|
|
1055
|
-
issues,
|
|
1056
|
-
}),
|
|
882
|
+
const api = getApiClient();
|
|
883
|
+
await api.post(`/api/tasks/${taskId}/qa/reject`, {
|
|
884
|
+
notes: options.notes,
|
|
885
|
+
issues,
|
|
1057
886
|
});
|
|
1058
|
-
if (!res.ok) {
|
|
1059
|
-
throw new Error(`API error: ${res.status}`);
|
|
1060
|
-
}
|
|
1061
887
|
console.log(`✗ QA rejected for task ${taskId}`);
|
|
1062
888
|
console.log(` Task returned to worker for fixes`);
|
|
1063
889
|
}
|
|
@@ -1101,23 +927,13 @@ taskCommand
|
|
|
1101
927
|
}
|
|
1102
928
|
}
|
|
1103
929
|
try {
|
|
1104
|
-
const
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
body: JSON.stringify({
|
|
1111
|
-
iteration: parseInt(options.iteration, 10),
|
|
1112
|
-
status: options.status,
|
|
1113
|
-
issues,
|
|
1114
|
-
duration: parseFloat(options.duration),
|
|
1115
|
-
}),
|
|
930
|
+
const api = getApiClient();
|
|
931
|
+
const data = await api.post(`/api/tasks/${taskId}/qa/iteration`, {
|
|
932
|
+
iteration: parseInt(options.iteration, 10),
|
|
933
|
+
status: options.status,
|
|
934
|
+
issues,
|
|
935
|
+
duration: parseFloat(options.duration),
|
|
1116
936
|
});
|
|
1117
|
-
if (!res.ok) {
|
|
1118
|
-
throw new Error(`API error: ${res.status}`);
|
|
1119
|
-
}
|
|
1120
|
-
const data = await res.json();
|
|
1121
937
|
console.log(`✓ QA iteration ${options.iteration} recorded`);
|
|
1122
938
|
console.log(` Status: ${data.qaStatus}`);
|
|
1123
939
|
console.log(` Issues: ${data.issuesCount}`);
|
|
@@ -1137,16 +953,8 @@ taskCommand
|
|
|
1137
953
|
const config = ensureConfig();
|
|
1138
954
|
const taskId = getTaskId(options);
|
|
1139
955
|
try {
|
|
1140
|
-
const
|
|
1141
|
-
|
|
1142
|
-
headers: {
|
|
1143
|
-
"Content-Type": "application/json",
|
|
1144
|
-
...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
|
|
1145
|
-
},
|
|
1146
|
-
});
|
|
1147
|
-
if (!res.ok) {
|
|
1148
|
-
throw new Error(`API error: ${res.status}`);
|
|
1149
|
-
}
|
|
956
|
+
const api = getApiClient();
|
|
957
|
+
await api.put(`/api/tasks/${taskId}/qa/approve`, {});
|
|
1150
958
|
console.log(`⚠ QA escalated to human review for task ${taskId}`);
|
|
1151
959
|
}
|
|
1152
960
|
catch (error) {
|
|
@@ -1204,25 +1012,14 @@ taskCommand
|
|
|
1204
1012
|
}
|
|
1205
1013
|
}
|
|
1206
1014
|
try {
|
|
1207
|
-
const
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
filePath: options.file,
|
|
1215
|
-
oursContent,
|
|
1216
|
-
theirsContent,
|
|
1217
|
-
baseContent,
|
|
1218
|
-
context: options.context,
|
|
1219
|
-
}),
|
|
1015
|
+
const api = getApiClient();
|
|
1016
|
+
const result = await api.post("/api/merge-conflict/resolve", {
|
|
1017
|
+
filePath: options.file,
|
|
1018
|
+
oursContent,
|
|
1019
|
+
theirsContent,
|
|
1020
|
+
baseContent,
|
|
1021
|
+
context: options.context,
|
|
1220
1022
|
});
|
|
1221
|
-
if (!res.ok) {
|
|
1222
|
-
const errorData = await res.json().catch(() => ({ error: `API error: ${res.status}` }));
|
|
1223
|
-
throw new Error(errorData.error || `API error: ${res.status}`);
|
|
1224
|
-
}
|
|
1225
|
-
const result = await res.json();
|
|
1226
1023
|
if (options.json) {
|
|
1227
1024
|
console.log(JSON.stringify(result, null, 2));
|
|
1228
1025
|
}
|
package/dist/index.js
CHANGED
|
@@ -35,6 +35,7 @@ import { prCommand } from "./commands/pr.js";
|
|
|
35
35
|
import { youtubeCommand } from "./commands/youtube.js";
|
|
36
36
|
import { imageCommand } from "./commands/image.js";
|
|
37
37
|
import { authCommand } from "./commands/auth.js";
|
|
38
|
+
import { businessCommand } from "./commands/business.js";
|
|
38
39
|
// Read version from package.json
|
|
39
40
|
const require = createRequire(import.meta.url);
|
|
40
41
|
const packageJson = require("../package.json");
|
|
@@ -77,6 +78,7 @@ program.addCommand(prCommand);
|
|
|
77
78
|
program.addCommand(youtubeCommand);
|
|
78
79
|
program.addCommand(imageCommand);
|
|
79
80
|
program.addCommand(authCommand);
|
|
81
|
+
program.addCommand(businessCommand);
|
|
80
82
|
// Handle --llm flag specially
|
|
81
83
|
if (process.argv.includes("--llm")) {
|
|
82
84
|
printLLMContext();
|
package/dist/lib/worker.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ interface WorkerIdentity {
|
|
|
8
8
|
}
|
|
9
9
|
export declare function getWorkerIdentity(): WorkerIdentity;
|
|
10
10
|
export declare function generateSessionId(): string;
|
|
11
|
-
export declare function ensureWorkerRegistered(
|
|
12
|
-
export declare function registerSession(
|
|
13
|
-
export declare function sessionHeartbeat(
|
|
11
|
+
export declare function ensureWorkerRegistered(_apiUrl?: string, _apiKey?: string): Promise<string>;
|
|
12
|
+
export declare function registerSession(_apiUrl: string, _apiKey: string, workerId: string, sessionId: string): Promise<void>;
|
|
13
|
+
export declare function sessionHeartbeat(_apiUrl: string, _apiKey: string, sessionId: string, currentTaskId?: string | null): Promise<void>;
|
|
14
14
|
export {};
|