@simonfestl/husky-cli 1.25.3 → 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.
@@ -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(apiUrl, apiKey, repoIdentifier) {
93
+ async function findProjectByRepo(repoIdentifier) {
93
94
  try {
94
- const res = await fetch(`${apiUrl}/api/projects`, {
95
- headers: apiKey ? { "x-api-key": apiKey } : {},
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 && config.apiUrl) {
148
- autoDetectedProject = await findProjectByRepo(config.apiUrl, config.apiKey, repoIdentifier);
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 res = await fetch(url.toString(), {
160
- headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
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 res = await fetch(`${config.apiUrl}/api/tasks/${id}/start`, {
263
- method: "POST",
264
- headers: {
265
- "Content-Type": "application/json",
266
- ...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
267
- },
268
- body: JSON.stringify({
269
- agent: "claude-code",
270
- workerId,
271
- sessionId,
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 res = await fetch(`${config.apiUrl}/api/tasks/${id}/done`, {
314
- method: "POST",
315
- headers: {
316
- "Content-Type": "application/json",
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 res = await fetch(`${config.apiUrl}/api/tasks/${id}/assign`, {
388
- method: "POST",
389
- headers: {
390
- "Content-Type": "application/json",
391
- ...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
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 res = await fetch(`${config.apiUrl}/api/tasks`, {
461
- method: "POST",
462
- headers: {
463
- "Content-Type": "application/json",
464
- ...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
465
- },
466
- body: JSON.stringify({
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 res = await fetch(`${config.apiUrl}/api/tasks/${id}`, {
546
- method: "PATCH",
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 getRes = await fetch(`${config.apiUrl}/api/tasks/${id}`, {
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
- const res = await fetch(`${config.apiUrl}/api/tasks/${id}`, {
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}`, {
655
- headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/status`, {
700
- method: "POST",
701
- headers: {
702
- "Content-Type": "application/json",
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/status`, {
739
- method: "POST",
740
- headers: {
741
- "Content-Type": "application/json",
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/plan`, {
800
- method: "POST",
801
- headers: {
802
- "Content-Type": "application/json",
803
- ...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/approval`, {
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/complete`, {
879
- method: "POST",
880
- headers: {
881
- "Content-Type": "application/json",
882
- ...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/qa/start`, {
923
- method: "POST",
924
- headers: {
925
- "Content-Type": "application/json",
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/qa/status`, {
957
- headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/qa/approve`, {
1006
- method: "POST",
1007
- headers: {
1008
- "Content-Type": "application/json",
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/qa/reject`, {
1048
- method: "POST",
1049
- headers: {
1050
- "Content-Type": "application/json",
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/qa/iteration`, {
1105
- method: "POST",
1106
- headers: {
1107
- "Content-Type": "application/json",
1108
- ...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
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 res = await fetch(`${config.apiUrl}/api/tasks/${taskId}/qa/approve`, {
1141
- method: "PUT", // PUT for escalation
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 res = await fetch(`${config.apiUrl}/api/merge-conflict/resolve`, {
1208
- method: "POST",
1209
- headers: {
1210
- "Content-Type": "application/json",
1211
- ...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
1212
- },
1213
- body: JSON.stringify({
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();
@@ -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(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>;
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 {};