@forgehive/hive-sdk 0.1.5 → 0.2.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.
@@ -4,19 +4,56 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const axios_1 = __importDefault(require("axios"));
7
+ const fs_1 = __importDefault(require("fs"));
7
8
  const index_1 = require("../index");
8
- // Mock axios
9
+ // Mock axios and fs
9
10
  jest.mock('axios');
11
+ jest.mock('fs');
10
12
  const mockedAxios = axios_1.default;
13
+ const mockedFs = fs_1.default;
11
14
  describe('HiveLogClient sendLog with ExecutionRecord', () => {
12
15
  let client;
13
16
  const testConfig = {
14
17
  projectName: 'test-project',
18
+ projectUuid: '550e8400-e29b-41d4-a716-446655440000',
15
19
  apiKey: 'test-api-key',
16
20
  apiSecret: 'test-api-secret',
17
- host: 'https://test-host.com'
21
+ host: 'https://test-host.com',
22
+ forgeConfigPath: './forge.json'
23
+ };
24
+ const mockForgeConfig = {
25
+ project: {
26
+ name: 'test-project',
27
+ uuid: '550e8400-e29b-41d4-a716-446655440000'
28
+ },
29
+ tasks: {
30
+ 'test-task': {
31
+ path: 'src/tasks/test.ts',
32
+ handler: 'testTask',
33
+ uuid: 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
34
+ },
35
+ 'complex-task': {
36
+ path: 'src/tasks/complex.ts',
37
+ handler: 'complexTask',
38
+ uuid: 'a45aafe3-8b01-4b58-b15d-9a96274858ee'
39
+ },
40
+ 'error-task': {
41
+ path: 'src/tasks/error.ts',
42
+ handler: 'errorTask',
43
+ uuid: '8879271f-7e84-4748-bd11-4d81acf29fb6'
44
+ },
45
+ 'metadata-task': {
46
+ path: 'src/tasks/metadata.ts',
47
+ handler: 'metadataTask',
48
+ uuid: 'fad2f735-ca09-4b8b-9c44-597de3641d28'
49
+ }
50
+ }
18
51
  };
19
52
  beforeEach(() => {
53
+ // Mock fs.existsSync to return true
54
+ mockedFs.existsSync.mockReturnValue(true);
55
+ // Mock fs.readFileSync to return forge.json content
56
+ mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockForgeConfig));
20
57
  // Create client instance with config
21
58
  client = new index_1.HiveLogClient(testConfig);
22
59
  // Clear all mocks
@@ -37,23 +74,21 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
37
74
  const result = await client.sendLog(executionRecord);
38
75
  expect(result).toBe('success');
39
76
  expect(mockedAxios.post).toHaveBeenCalledTimes(1);
40
- expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
41
- projectName: 'test-project',
42
- taskName: 'test-task',
43
- logItem: JSON.stringify({
44
- input: { value: 'test-input' },
45
- output: { result: 'test-output' },
46
- taskName: 'test-task',
47
- type: 'success',
48
- boundaries: {},
49
- metadata: {}
50
- })
51
- }, {
52
- headers: {
53
- Authorization: 'Bearer test-api-key:test-api-secret',
54
- 'Content-Type': 'application/json'
55
- }
56
- });
77
+ // Verify it uses the UUID endpoint
78
+ const callArgs = mockedAxios.post.mock.calls[0];
79
+ expect(callArgs[0]).toBe('https://test-host.com/api/log-ingest');
80
+ // Verify request body structure
81
+ const requestBody = callArgs[1];
82
+ expect(requestBody.projectUuid).toBe(testConfig.projectUuid);
83
+ expect(requestBody.taskUuid).toBe('f47ac10b-58cc-4372-a567-0e02b2c3d479');
84
+ // Verify logItem has UUID generated
85
+ const logItem = JSON.parse(requestBody.logItem);
86
+ expect(logItem.uuid).toBeDefined();
87
+ expect(typeof logItem.uuid).toBe('string');
88
+ expect(logItem.input).toEqual({ value: 'test-input' });
89
+ expect(logItem.output).toEqual({ result: 'test-output' });
90
+ expect(logItem.taskName).toBe('test-task');
91
+ expect(logItem.type).toBe('success');
57
92
  });
58
93
  it('should handle ExecutionRecord with complex boundaries', async () => {
59
94
  mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
@@ -78,34 +113,15 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
78
113
  };
79
114
  const result = await client.sendLog(executionRecord);
80
115
  expect(result).toBe('success');
81
- expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
82
- projectName: 'test-project',
83
- taskName: 'complex-task',
84
- logItem: JSON.stringify({
85
- input: { userId: 123, action: 'login' },
86
- output: { success: true, sessionId: 'abc123' },
87
- taskName: 'complex-task',
88
- type: 'success',
89
- boundaries: {
90
- database: [{
91
- input: ['SELECT * FROM users'],
92
- output: [{ id: 123 }],
93
- timing: { startTime: 1000, endTime: 1100, duration: 100 }
94
- }],
95
- api: [{
96
- input: [{ endpoint: '/auth' }],
97
- output: { token: 'jwt123' },
98
- timing: { startTime: 1200, endTime: 1250, duration: 50 }
99
- }]
100
- },
101
- metadata: { environment: 'test' }
102
- })
103
- }, {
104
- headers: {
105
- Authorization: 'Bearer test-api-key:test-api-secret',
106
- 'Content-Type': 'application/json'
107
- }
108
- });
116
+ // Verify request structure
117
+ const callArgs = mockedAxios.post.mock.calls[0];
118
+ expect(callArgs[0]).toBe('https://test-host.com/api/log-ingest');
119
+ const requestBody = callArgs[1];
120
+ expect(requestBody.projectUuid).toBe(testConfig.projectUuid);
121
+ expect(requestBody.taskUuid).toBe('a45aafe3-8b01-4b58-b15d-9a96274858ee');
122
+ const logItem = JSON.parse(requestBody.logItem);
123
+ expect(logItem.uuid).toBeDefined();
124
+ expect(logItem.boundaries).toEqual(executionRecord.boundaries);
109
125
  });
110
126
  it('should handle ExecutionRecord with error', async () => {
111
127
  mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
@@ -120,44 +136,51 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
120
136
  };
121
137
  const result = await client.sendLog(executionRecord);
122
138
  expect(result).toBe('success');
123
- expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
124
- projectName: 'test-project',
125
- taskName: 'error-task',
126
- logItem: JSON.stringify({
127
- input: { value: 'test-input' },
128
- output: undefined,
129
- error: 'Task execution failed',
130
- taskName: 'error-task',
131
- type: 'error',
132
- boundaries: {},
133
- metadata: {}
134
- })
135
- }, expect.any(Object));
139
+ const callArgs = mockedAxios.post.mock.calls[0];
140
+ const requestBody = callArgs[1];
141
+ expect(requestBody.taskUuid).toBe('8879271f-7e84-4748-bd11-4d81acf29fb6');
142
+ const logItem = JSON.parse(requestBody.logItem);
143
+ expect(logItem.error).toBe('Task execution failed');
144
+ expect(logItem.type).toBe('error');
136
145
  });
137
- it('should use "unknown-task" when taskName is missing', async () => {
146
+ it('should preserve existing UUID when execution record already has one', async () => {
138
147
  mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
148
+ const existingUuid = '01234567-89ab-7def-8123-456789abcdef';
139
149
  const executionRecord = {
150
+ uuid: existingUuid,
140
151
  input: { value: 'test-input' },
141
152
  output: { result: 'test-output' },
142
- // taskName is missing
153
+ taskName: 'test-task',
143
154
  type: 'success',
144
155
  boundaries: {},
145
156
  metadata: {}
146
157
  };
147
158
  const result = await client.sendLog(executionRecord);
148
159
  expect(result).toBe('success');
149
- expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
150
- projectName: 'test-project',
151
- taskName: 'unknown-task',
152
- logItem: JSON.stringify({
153
- input: { value: 'test-input' },
154
- output: { result: 'test-output' },
155
- type: 'success',
156
- boundaries: {},
157
- metadata: {},
158
- taskName: 'unknown-task'
159
- })
160
- }, expect.any(Object));
160
+ const callArgs = mockedAxios.post.mock.calls[0];
161
+ const requestBody = callArgs[1];
162
+ const logItem = JSON.parse(requestBody.logItem);
163
+ expect(logItem.uuid).toBe(existingUuid);
164
+ });
165
+ it('should generate UUID v7 when execution record has no UUID', async () => {
166
+ mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
167
+ const executionRecord = {
168
+ input: { value: 'test-input' },
169
+ output: { result: 'test-output' },
170
+ taskName: 'test-task',
171
+ type: 'success',
172
+ boundaries: {},
173
+ metadata: {}
174
+ };
175
+ const result = await client.sendLog(executionRecord);
176
+ expect(result).toBe('success');
177
+ const callArgs = mockedAxios.post.mock.calls[0];
178
+ const requestBody = callArgs[1];
179
+ const logItem = JSON.parse(requestBody.logItem);
180
+ expect(logItem.uuid).toBeDefined();
181
+ expect(typeof logItem.uuid).toBe('string');
182
+ // UUID v7 pattern
183
+ expect(logItem.uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
161
184
  });
162
185
  });
163
186
  describe('sendLog with additional metadata', () => {
@@ -180,22 +203,14 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
180
203
  };
181
204
  const result = await client.sendLog(executionRecord, sendLogMetadata);
182
205
  expect(result).toBe('success');
183
- expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
184
- projectName: 'test-project',
185
- taskName: 'metadata-task',
186
- logItem: JSON.stringify({
187
- input: { value: 'test-input' },
188
- output: { result: 'test-output' },
189
- taskName: 'metadata-task',
190
- type: 'success',
191
- boundaries: {},
192
- metadata: {
193
- recordMeta: 'from-record',
194
- sharedKey: 'sendlog-value', // sendLog metadata takes priority
195
- sendLogMeta: 'from-sendlog'
196
- }
197
- })
198
- }, expect.any(Object));
206
+ const callArgs = mockedAxios.post.mock.calls[0];
207
+ const requestBody = callArgs[1];
208
+ const logItem = JSON.parse(requestBody.logItem);
209
+ expect(logItem.metadata).toEqual({
210
+ recordMeta: 'from-record',
211
+ sharedKey: 'sendlog-value', // sendLog metadata takes priority
212
+ sendLogMeta: 'from-sendlog'
213
+ });
199
214
  });
200
215
  });
201
216
  describe('failed sendLog', () => {
@@ -226,6 +241,37 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
226
241
  const result = await client.sendLog(executionRecord);
227
242
  expect(result).toBe('error');
228
243
  });
244
+ it('should return error when task is not found in forge.json', async () => {
245
+ const executionRecord = {
246
+ input: { value: 'test-input' },
247
+ taskName: 'nonexistent-task',
248
+ type: 'success',
249
+ boundaries: {},
250
+ metadata: {}
251
+ };
252
+ const result = await client.sendLog(executionRecord);
253
+ expect(result).toBe('error');
254
+ expect(mockedAxios.post).not.toHaveBeenCalled();
255
+ });
256
+ it('should return error when projectUuid is not set', async () => {
257
+ // Create client without projectUuid
258
+ const clientWithoutUuid = new index_1.HiveLogClient({
259
+ projectName: 'test-project',
260
+ apiKey: 'test-key',
261
+ apiSecret: 'test-secret',
262
+ host: 'https://test-host.com'
263
+ });
264
+ const executionRecord = {
265
+ input: { value: 'test-input' },
266
+ taskName: 'test-task',
267
+ type: 'success',
268
+ boundaries: {},
269
+ metadata: {}
270
+ };
271
+ const result = await clientWithoutUuid.sendLog(executionRecord);
272
+ expect(result).toBe('error');
273
+ expect(mockedAxios.post).not.toHaveBeenCalled();
274
+ });
229
275
  });
230
276
  describe('sendLog in silent mode', () => {
231
277
  it('should return silent when client is not initialized', async () => {
@@ -245,16 +291,71 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
245
291
  expect(mockedAxios.post).not.toHaveBeenCalled();
246
292
  });
247
293
  });
294
+ describe('sendLog with unknown task name', () => {
295
+ it('should return error when taskName is missing and defaults to unknown-task', async () => {
296
+ const executionRecord = {
297
+ input: { value: 'test-input' },
298
+ output: { result: 'test-output' },
299
+ // taskName is missing - will default to 'unknown-task'
300
+ type: 'success',
301
+ boundaries: {},
302
+ metadata: {}
303
+ };
304
+ const result = await client.sendLog(executionRecord);
305
+ // Should return error because 'unknown-task' is not in forge.json
306
+ expect(result).toBe('error');
307
+ expect(mockedAxios.post).not.toHaveBeenCalled();
308
+ });
309
+ });
310
+ describe('sendLog response handling', () => {
311
+ it('should return response data when API returns object with uuid', async () => {
312
+ const responseData = {
313
+ uuid: 'log-uuid-123',
314
+ taskName: 'test-task',
315
+ projectName: 'test-project',
316
+ logItem: {},
317
+ createdAt: '2024-01-01T00:00:00Z'
318
+ };
319
+ mockedAxios.post.mockResolvedValueOnce({ data: responseData });
320
+ const executionRecord = {
321
+ input: { value: 'test' },
322
+ taskName: 'test-task',
323
+ type: 'success',
324
+ boundaries: {},
325
+ metadata: {}
326
+ };
327
+ const result = await client.sendLog(executionRecord);
328
+ expect(result).toEqual(responseData);
329
+ });
330
+ });
248
331
  });
249
332
  describe('HiveLogClient getListener', () => {
250
333
  let client;
251
334
  const testConfig = {
252
335
  projectName: 'test-project',
336
+ projectUuid: '550e8400-e29b-41d4-a716-446655440000',
253
337
  apiKey: 'test-api-key',
254
338
  apiSecret: 'test-api-secret',
255
- host: 'https://test-host.com'
339
+ host: 'https://test-host.com',
340
+ forgeConfigPath: './forge.json'
341
+ };
342
+ const mockForgeConfig = {
343
+ project: {
344
+ name: 'test-project',
345
+ uuid: '550e8400-e29b-41d4-a716-446655440000'
346
+ },
347
+ tasks: {
348
+ 'test-task': {
349
+ path: 'src/tasks/test.ts',
350
+ handler: 'testTask',
351
+ uuid: 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
352
+ }
353
+ }
256
354
  };
257
355
  beforeEach(() => {
356
+ // Mock fs
357
+ mockedFs.existsSync.mockReturnValue(true);
358
+ mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockForgeConfig));
258
359
  client = new index_1.HiveLogClient(testConfig);
259
360
  jest.clearAllMocks();
260
361
  });
@@ -273,18 +374,9 @@ describe('HiveLogClient getListener', () => {
273
374
  };
274
375
  await listener(executionRecord);
275
376
  expect(mockedAxios.post).toHaveBeenCalledTimes(1);
276
- expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
277
- projectName: 'test-project',
278
- taskName: 'test-task',
279
- logItem: JSON.stringify({
280
- input: { value: 'test-input' },
281
- output: { result: 'test-output' },
282
- taskName: 'test-task',
283
- type: 'success',
284
- boundaries: {},
285
- metadata: {}
286
- })
287
- }, expect.any(Object));
377
+ // Verify it uses the UUID endpoint
378
+ const callArgs = mockedAxios.post.mock.calls[0];
379
+ expect(callArgs[0]).toBe('https://test-host.com/api/log-ingest');
288
380
  });
289
381
  it('should return a function that calls sendLog with provided metadata', async () => {
290
382
  mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
@@ -298,20 +390,10 @@ describe('HiveLogClient getListener', () => {
298
390
  metadata: { recordMeta: 'from-record' }
299
391
  };
300
392
  await listener(executionRecord);
301
- expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
302
- projectName: 'test-project',
303
- taskName: 'test-task',
304
- logItem: JSON.stringify({
305
- input: { value: 'test-input' },
306
- output: { result: 'test-output' },
307
- taskName: 'test-task',
308
- type: 'success',
309
- boundaries: {},
310
- metadata: {
311
- recordMeta: 'from-record'
312
- }
313
- })
314
- }, expect.any(Object));
393
+ const callArgs = mockedAxios.post.mock.calls[0];
394
+ const requestBody = callArgs[1];
395
+ const logItem = JSON.parse(requestBody.logItem);
396
+ expect(logItem.metadata).toEqual({ recordMeta: 'from-record' });
315
397
  });
316
398
  it('should handle listener errors gracefully', async () => {
317
399
  mockedAxios.post.mockRejectedValueOnce(new Error('Network error'));
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@forgehive/hive-sdk",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "publishConfig": {
8
8
  "access": "public",
9
9
  "dependencies": {
10
- "@forgehive/task": "^0.2.6"
10
+ "@forgehive/task": "^0.2.7"
11
11
  }
12
12
  },
13
13
  "devDependencies": {
@@ -24,7 +24,7 @@
24
24
  "axios": "^1.8.4",
25
25
  "debug": "^4.4.1",
26
26
  "uuid": "^11.1.0",
27
- "@forgehive/task": "0.2.6"
27
+ "@forgehive/task": "0.2.7"
28
28
  },
29
29
  "scripts": {
30
30
  "build": "tsc",
package/src/index.ts CHANGED
@@ -266,65 +266,21 @@ export class HiveLogClient {
266
266
  return 'silent'
267
267
  }
268
268
 
269
- // Deprecation warning for legacy endpoint
270
- log('DEPRECATION WARNING: sendLog() is deprecated. Use sendLogByUuid() with project and task UUIDs for enhanced features and better performance.')
271
-
272
- try {
273
- const logsUrl = `${this.host}/api/tasks/log-ingest`
274
- log('Sending log for task "%s" to %s', taskName, logsUrl)
275
-
276
- const authToken = `${this.apiKey}:${this.apiSecret}`
277
-
278
- // Merge metadata with priority: sendLog > record.metadata > client
279
- const finalMetadata = this.mergeMetadata(record, metadata)
280
-
281
- // Create logItem with merged metadata (no UUID generation for legacy method)
282
- const logItem = {
283
- ...record,
284
- taskName,
285
- metadata: finalMetadata
286
- }
287
-
288
- const response = await axios.post(logsUrl, {
289
- projectName: this.projectName,
290
- taskName,
291
- logItem: JSON.stringify(logItem)
292
- }, {
293
- headers: {
294
- Authorization: `Bearer ${authToken}`,
295
- 'Content-Type': 'application/json'
296
- }
297
- })
298
-
299
- log('Success: Sent log for task "%s"', taskName)
300
-
301
- // Return the full response data if available
302
- if (response.data && typeof response.data === 'object' && 'uuid' in response.data) {
303
- return response.data as LogApiSuccess
304
- }
305
-
306
- return 'success'
307
- } catch (e) {
308
- const error = e as Error
309
- log('Error: Failed to send log for task "%s": %s', taskName, error.message)
269
+ if (!this.projectUuid) {
270
+ log('Error: sendLog requires projectUuid to be set in client config')
310
271
  return 'error'
311
272
  }
312
- }
313
-
314
- async sendLogByUuid(record: ExecutionRecord, taskUuid: string, metadata?: Metadata): Promise<'success' | 'error' | 'silent' | LogApiSuccess> {
315
- if (!this.isInitialized) {
316
- log('Silent mode: Skipping sendLogByUuid for task UUID "%s" - client not initialized', taskUuid)
317
- return 'silent'
318
- }
319
273
 
320
- if (!this.projectUuid) {
321
- log('Error: sendLogByUuid requires projectUuid to be set in client config')
274
+ // Look up task UUID from forge.json
275
+ const taskUuid = this.getTaskUUID(taskName)
276
+ if (!taskUuid) {
277
+ log('Error: Cannot find UUID for task "%s" in forge.json', taskName)
322
278
  return 'error'
323
279
  }
324
280
 
325
281
  try {
326
282
  const logsUrl = `${this.host}/api/log-ingest`
327
- log('Sending log for task UUID "%s" to %s', taskUuid, logsUrl)
283
+ log('Sending log for task "%s" (UUID: %s) to %s', taskName, taskUuid, logsUrl)
328
284
 
329
285
  const authToken = `${this.apiKey}:${this.apiSecret}`
330
286
 
@@ -338,13 +294,10 @@ export class HiveLogClient {
338
294
  metadata: finalMetadata
339
295
  }
340
296
 
341
- // Create logItem with merged metadata and UUID
342
- const logItem = recordWithUuid
343
-
344
297
  const response = await axios.post(logsUrl, {
345
298
  projectUuid: this.projectUuid,
346
299
  taskUuid,
347
- logItem: JSON.stringify(logItem)
300
+ logItem: JSON.stringify(recordWithUuid)
348
301
  }, {
349
302
  headers: {
350
303
  Authorization: `Bearer ${authToken}`,
@@ -352,7 +305,7 @@ export class HiveLogClient {
352
305
  }
353
306
  })
354
307
 
355
- log('Success: Sent log for task UUID "%s"', taskUuid)
308
+ log('Success: Sent log for task "%s" (UUID: %s)', taskName, taskUuid)
356
309
 
357
310
  // Return the full response data if available
358
311
  if (response.data && typeof response.data === 'object' && 'uuid' in response.data) {
@@ -362,11 +315,12 @@ export class HiveLogClient {
362
315
  return 'success'
363
316
  } catch (e) {
364
317
  const error = e as Error
365
- log('Error: Failed to send log for task UUID "%s": %s', taskUuid, error.message)
318
+ log('Error: Failed to send log for task "%s": %s', taskName, error.message)
366
319
  return 'error'
367
320
  }
368
321
  }
369
322
 
323
+
370
324
  getListener(): (record: ExecutionRecord) => Promise<void> {
371
325
  return async (record: ExecutionRecord) => {
372
326
  await this.sendLog(record)
@@ -461,27 +415,6 @@ export class HiveLogClient {
461
415
  return task.uuid
462
416
  }
463
417
 
464
- async sendLogByName(taskName: string, record: ExecutionRecord, metadata?: Metadata): Promise<'success' | 'error' | 'silent' | LogApiSuccess> {
465
- if (!this.isInitialized) {
466
- log('Silent mode: Skipping sendLogByName for task "%s" - client not initialized', taskName)
467
- return 'silent'
468
- }
469
-
470
- if (!this.projectUuid) {
471
- log('Error: sendLogByName requires projectUuid to be set in client config')
472
- return 'error'
473
- }
474
-
475
- const taskUuid = this.getTaskUUID(taskName)
476
- if (!taskUuid) {
477
- log('Error: Cannot find UUID for task "%s" in forge.json', taskName)
478
- return 'error'
479
- }
480
-
481
- // Use the existing sendLogByUuid method
482
- log('Sending log for task "%s" with uuid "%s"', taskName, taskUuid)
483
- return await this.sendLogByUuid(record, taskUuid, metadata)
484
- }
485
418
  }
486
419
 
487
420
  export const createHiveLogClient = (config: HiveLogClientConfig): HiveLogClient => {