@openclaw-cloud/agent-controller 0.1.8 → 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.
@@ -121,3 +121,63 @@ describe('createAgentApi – post()', () => {
121
121
  await expect(api.post('/endpoint')).rejects.toThrow('timeout');
122
122
  });
123
123
  });
124
+
125
+ describe('createAgentApi – publishResponse()', () => {
126
+ it('POSTs to /api/internal/agent-response with agentId and data', async () => {
127
+ const api = createAgentApi('http://backend', 'tok');
128
+ mockFetch.mockResolvedValue(makeOkResponse(null));
129
+
130
+ await api.publishResponse('agent-1', { id: 'cmd-1', type: 'exec', success: true });
131
+
132
+ const [url, init] = mockFetch.mock.calls[0];
133
+ expect(url).toBe('http://backend/api/internal/agent-response');
134
+ expect(init.method).toBe('POST');
135
+ expect(JSON.parse(init.body)).toEqual({
136
+ agentId: 'agent-1',
137
+ data: { id: 'cmd-1', type: 'exec', success: true },
138
+ });
139
+ });
140
+
141
+ it('throws when response is not ok', async () => {
142
+ const api = createAgentApi('http://backend', 'tok');
143
+ mockFetch.mockResolvedValue(makeErrorResponse(503));
144
+
145
+ await expect(api.publishResponse('agent-1', {})).rejects.toThrow('HTTP 503');
146
+ });
147
+
148
+ it('propagates network errors', async () => {
149
+ const api = createAgentApi('http://backend', 'tok');
150
+ mockFetch.mockRejectedValue(new Error('ECONNREFUSED'));
151
+
152
+ await expect(api.publishResponse('agent-1', {})).rejects.toThrow('ECONNREFUSED');
153
+ });
154
+ });
155
+
156
+ describe('createAgentApi – publishHeartbeat()', () => {
157
+ it('POSTs to /api/internal/agent-heartbeat with agentId and payload', async () => {
158
+ const api = createAgentApi('http://backend', 'tok');
159
+ mockFetch.mockResolvedValue(makeOkResponse(null));
160
+
161
+ const payload = { type: 'heartbeat', agentId: 'agent-1', ts: 123, metrics: {} };
162
+ await api.publishHeartbeat('agent-1', payload);
163
+
164
+ const [url, init] = mockFetch.mock.calls[0];
165
+ expect(url).toBe('http://backend/api/internal/agent-heartbeat');
166
+ expect(init.method).toBe('POST');
167
+ expect(JSON.parse(init.body)).toEqual({ agentId: 'agent-1', payload });
168
+ });
169
+
170
+ it('throws when response is not ok', async () => {
171
+ const api = createAgentApi('http://backend', 'tok');
172
+ mockFetch.mockResolvedValue(makeErrorResponse(500));
173
+
174
+ await expect(api.publishHeartbeat('agent-1', {})).rejects.toThrow('HTTP 500');
175
+ });
176
+
177
+ it('propagates network errors', async () => {
178
+ const api = createAgentApi('http://backend', 'tok');
179
+ mockFetch.mockRejectedValue(new Error('timeout'));
180
+
181
+ await expect(api.publishHeartbeat('agent-1', {})).rejects.toThrow('timeout');
182
+ });
183
+ });
@@ -10,6 +10,8 @@ function mockApi(overrides: Partial<AgentApi> = {}): AgentApi {
10
10
  return {
11
11
  get: jest.fn(),
12
12
  post: jest.fn(),
13
+ publishResponse: jest.fn().mockResolvedValue(undefined),
14
+ publishHeartbeat: jest.fn().mockResolvedValue(undefined),
13
15
  ...overrides,
14
16
  };
15
17
  }
@@ -1,4 +1,5 @@
1
1
  import { Centrifuge } from 'centrifuge';
2
+ import type { AgentApi } from '../src/api';
2
3
 
3
4
  jest.mock('centrifuge');
4
5
  jest.mock('ws', () => jest.fn());
@@ -34,6 +35,15 @@ function createMockClient(mockSubs: ReturnType<typeof createMockSubscription>[])
34
35
  };
35
36
  }
36
37
 
38
+ function makeApi(): AgentApi & { publishResponse: jest.Mock } {
39
+ return {
40
+ get: jest.fn(),
41
+ post: jest.fn(),
42
+ publishResponse: jest.fn().mockResolvedValue(undefined),
43
+ publishHeartbeat: jest.fn().mockResolvedValue(undefined),
44
+ } as unknown as AgentApi & { publishResponse: jest.Mock };
45
+ }
46
+
37
47
  function mockFetchOk(token = JWT) {
38
48
  global.fetch = jest.fn().mockResolvedValue({
39
49
  ok: true,
@@ -59,6 +69,7 @@ describe('createConnection', () => {
59
69
  token: AGENT_TOKEN,
60
70
  agentId: AGENT_ID,
61
71
  backendUrl: BACKEND_URL,
72
+ api: makeApi(),
62
73
  });
63
74
 
64
75
  expect(MockCentrifuge).toHaveBeenCalledWith(
@@ -91,6 +102,7 @@ describe('createConnection', () => {
91
102
  token: AGENT_TOKEN,
92
103
  agentId: AGENT_ID,
93
104
  backendUrl: BACKEND_URL,
105
+ api: makeApi(),
94
106
  });
95
107
 
96
108
  expect(capturedGetToken).toBeDefined();
@@ -135,6 +147,7 @@ describe('createConnection', () => {
135
147
  token: AGENT_TOKEN,
136
148
  agentId: AGENT_ID,
137
149
  backendUrl: BACKEND_URL,
150
+ api: makeApi(),
138
151
  });
139
152
 
140
153
  const result = await capturedGetToken!();
@@ -167,6 +180,7 @@ describe('createConnection', () => {
167
180
  token: AGENT_TOKEN,
168
181
  agentId: AGENT_ID,
169
182
  backendUrl: BACKEND_URL,
183
+ api: makeApi(),
170
184
  });
171
185
 
172
186
  await expect(capturedGetToken!()).rejects.toThrow('network down');
@@ -197,6 +211,7 @@ describe('createConnection', () => {
197
211
  token: AGENT_TOKEN,
198
212
  agentId: AGENT_ID,
199
213
  backendUrl: BACKEND_URL,
214
+ api: makeApi(),
200
215
  });
201
216
 
202
217
  await expect(capturedGetToken!()).rejects.toThrow('HTTP 401');
@@ -205,7 +220,7 @@ describe('createConnection', () => {
205
220
  consoleSpy.mockRestore();
206
221
  });
207
222
 
208
- it('routes exec command to handler', async () => {
223
+ it('routes exec command to handler and publishes via api.publishResponse', async () => {
209
224
  const commandSub = createMockSubscription(`agent:${AGENT_ID}`);
210
225
  const mockClient = createMockClient([commandSub]);
211
226
  MockCentrifuge.mockImplementation(() => mockClient as any);
@@ -216,12 +231,14 @@ describe('createConnection', () => {
216
231
  }),
217
232
  }));
218
233
 
234
+ const api = makeApi();
219
235
  const { createConnection } = await import('../src/connection');
220
236
  createConnection({
221
237
  url: 'ws://localhost:8000/connection/websocket',
222
238
  token: AGENT_TOKEN,
223
239
  agentId: AGENT_ID,
224
240
  backendUrl: BACKEND_URL,
241
+ api,
225
242
  });
226
243
 
227
244
  // Simulate a publication on the command channel
@@ -233,9 +250,10 @@ describe('createConnection', () => {
233
250
  channel: `agent:${AGENT_ID}`,
234
251
  });
235
252
 
236
- // Should have published a response to the agent channel
237
- expect(mockClient.publish).toHaveBeenCalledWith(
238
- `agent:${AGENT_ID}`,
253
+ // Should have published a response via api, not client.publish
254
+ expect(mockClient.publish).not.toHaveBeenCalled();
255
+ expect(api.publishResponse).toHaveBeenCalledWith(
256
+ AGENT_ID,
239
257
  expect.objectContaining({ id: 'cmd-1', type: 'exec' })
240
258
  );
241
259
  });
@@ -247,12 +265,14 @@ describe('createConnection', () => {
247
265
 
248
266
  const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
249
267
 
268
+ const api = makeApi();
250
269
  const { createConnection } = await import('../src/connection');
251
270
  createConnection({
252
271
  url: 'ws://localhost:8000/connection/websocket',
253
272
  token: AGENT_TOKEN,
254
273
  agentId: AGENT_ID,
255
274
  backendUrl: BACKEND_URL,
275
+ api,
256
276
  });
257
277
 
258
278
  const publicationHandler = commandSub._handlers['publication'];
@@ -263,6 +283,7 @@ describe('createConnection', () => {
263
283
 
264
284
  expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Unknown command type'));
265
285
  expect(mockClient.publish).not.toHaveBeenCalled();
286
+ expect(api.publishResponse).not.toHaveBeenCalled();
266
287
  consoleSpy.mockRestore();
267
288
  });
268
289
  });
@@ -1,6 +1,7 @@
1
1
  import os from 'node:os';
2
2
 
3
3
  import { getMetrics, startHeartbeat } from '../src/heartbeat';
4
+ import type { AgentApi } from '../src/api';
4
5
 
5
6
  describe('getMetrics', () => {
6
7
  it('returns cpu, mem, uptime', () => {
@@ -18,60 +19,52 @@ describe('getMetrics', () => {
18
19
  });
19
20
  });
20
21
 
21
- describe('startHeartbeat', () => {
22
- let fetchSpy: jest.SpyInstance;
22
+ function makeApi(publishHeartbeat = jest.fn().mockResolvedValue(undefined)): AgentApi {
23
+ return {
24
+ get: jest.fn(),
25
+ post: jest.fn(),
26
+ publishResponse: jest.fn(),
27
+ publishHeartbeat,
28
+ } as unknown as AgentApi;
29
+ }
23
30
 
31
+ describe('startHeartbeat', () => {
24
32
  beforeEach(() => {
25
33
  jest.useFakeTimers();
26
- fetchSpy = jest.spyOn(globalThis, 'fetch').mockResolvedValue(
27
- new Response('{}', { status: 200 }),
28
- );
29
34
  });
30
35
 
31
36
  afterEach(() => {
32
37
  jest.useRealTimers();
33
- fetchSpy.mockRestore();
34
38
  });
35
39
 
36
- const opts = {
37
- centrifugoInternalUrl: 'http://centrifugo-internal:9000',
38
- centrifugoApiKey: 'test-key',
39
- agentId: 'agent-42',
40
- };
41
-
42
40
  it('publishes heartbeat immediately and at intervals', () => {
43
- const timer = startHeartbeat(opts);
41
+ const publishHeartbeat = jest.fn().mockResolvedValue(undefined);
42
+ const api = makeApi(publishHeartbeat);
43
+
44
+ const timer = startHeartbeat({ api, agentId: 'agent-42' });
44
45
 
45
46
  // Immediate call
46
- expect(fetchSpy).toHaveBeenCalledTimes(1);
47
- expect(fetchSpy).toHaveBeenCalledWith(
48
- 'http://centrifugo-internal:9000/api/publish',
47
+ expect(publishHeartbeat).toHaveBeenCalledTimes(1);
48
+ expect(publishHeartbeat).toHaveBeenCalledWith(
49
+ 'agent-42',
49
50
  expect.objectContaining({
50
- method: 'POST',
51
- headers: expect.objectContaining({
52
- 'Authorization': 'apikey test-key',
53
- }),
51
+ agentId: 'agent-42',
52
+ type: 'heartbeat',
54
53
  }),
55
54
  );
56
55
 
57
- // Check body contains correct channel and agent data
58
- const body = JSON.parse(fetchSpy.mock.calls[0][1].body);
59
- expect(body.channel).toBe('heartbeat:data');
60
- expect(body.data.agentId).toBe('agent-42');
61
- expect(body.data.type).toBe('heartbeat');
62
-
63
56
  // After 30s
64
57
  jest.advanceTimersByTime(30_000);
65
- expect(fetchSpy).toHaveBeenCalledTimes(2);
58
+ expect(publishHeartbeat).toHaveBeenCalledTimes(2);
66
59
 
67
60
  clearInterval(timer);
68
61
  });
69
62
 
70
63
  it('handles publish errors gracefully', () => {
71
64
  const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
72
- fetchSpy.mockRejectedValue(new Error('network fail'));
65
+ const api = makeApi(jest.fn().mockRejectedValue(new Error('network fail')));
73
66
 
74
- const timer = startHeartbeat(opts);
67
+ const timer = startHeartbeat({ api, agentId: 'agent-42' });
75
68
 
76
69
  // Should not throw
77
70
  clearInterval(timer);
package/dist/api.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export interface AgentApi {
2
2
  get(path: string): Promise<unknown>;
3
3
  post(path: string, body?: unknown): Promise<Response>;
4
+ publishResponse(agentId: string, data: unknown): Promise<void>;
5
+ publishHeartbeat(agentId: string, payload: unknown): Promise<void>;
4
6
  }
5
7
  export declare function createAgentApi(backendUrl: string, agentToken: string): AgentApi;
package/dist/api.js CHANGED
@@ -37,6 +37,18 @@ export function createAgentApi(backendUrl, agentToken) {
37
37
  async post(path, body) {
38
38
  return request('POST', path, body);
39
39
  },
40
+ async publishResponse(agentId, data) {
41
+ const res = await request('POST', '/api/internal/agent-response', { agentId, data });
42
+ if (!res.ok) {
43
+ throw new Error(`publishResponse failed: HTTP ${res.status}`);
44
+ }
45
+ },
46
+ async publishHeartbeat(agentId, payload) {
47
+ const res = await request('POST', '/api/internal/agent-heartbeat', { agentId, payload });
48
+ if (!res.ok) {
49
+ throw new Error(`publishHeartbeat failed: HTTP ${res.status}`);
50
+ }
51
+ },
40
52
  };
41
53
  }
42
54
  //# sourceMappingURL=api.js.map
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,OAAO,GAAG,MAAM,CAAC;AAOvB,MAAM,UAAU,cAAc,CAAC,UAAkB,EAAE,UAAkB;IACnE,KAAK,UAAU,OAAO,CAAC,MAAc,EAAE,IAAY,EAAE,IAAc;QACjE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC;YACH,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,UAAU,GAAG,IAAI,EAAE,EAAE;gBAC9C,MAAM;gBACN,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,UAAU,UAAU,EAAE;iBACxC;gBACD,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7D,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YACH,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACpD,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAC1E,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,IAAY;YACpB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACvC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,iBAAiB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,IAAc;YACrC,OAAO,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,OAAO,GAAG,MAAM,CAAC;AASvB,MAAM,UAAU,cAAc,CAAC,UAAkB,EAAE,UAAkB;IACnE,KAAK,UAAU,OAAO,CAAC,MAAc,EAAE,IAAY,EAAE,IAAc;QACjE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC;YACH,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,UAAU,GAAG,IAAI,EAAE,EAAE;gBAC9C,MAAM;gBACN,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,UAAU,UAAU,EAAE;iBACxC;gBACD,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7D,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YACH,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACpD,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAC1E,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,IAAY;YACpB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACvC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,iBAAiB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,IAAc;YACrC,OAAO,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,KAAK,CAAC,eAAe,CAAC,OAAe,EAAE,IAAa;YAClD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,8BAA8B,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACrF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QACD,KAAK,CAAC,gBAAgB,CAAC,OAAe,EAAE,OAAgB;YACtD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,+BAA+B,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YACzF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,9 +1,11 @@
1
+ import type { AgentApi } from './api.js';
1
2
  import { Centrifuge, Subscription } from 'centrifuge';
2
3
  export interface ConnectionOptions {
3
4
  url: string;
4
5
  token: string;
5
6
  agentId: string;
6
7
  backendUrl: string;
8
+ api: AgentApi;
7
9
  }
8
10
  export declare function createConnection(opts: ConnectionOptions): {
9
11
  client: Centrifuge;
@@ -92,7 +92,7 @@ export function createConnection(opts) {
92
92
  }
93
93
  // Chat commands — handle before generic dispatch
94
94
  if (command.type === 'chat_list_sessions' || command.type === 'chat_history' || command.type === 'chat_send') {
95
- const publishFn = async (data) => { await client.publish(commandChannel, data); };
95
+ const publishFn = async (data) => { await opts.api.publishResponse(opts.agentId, data); };
96
96
  console.log(`[WS] Handling chat command: type=${command.type} id=${command.id}`);
97
97
  switch (command.type) {
98
98
  case 'chat_list_sessions':
@@ -115,7 +115,7 @@ export function createConnection(opts) {
115
115
  console.log(`[WS] Handling command: type=${command.type} id=${command.id}`);
116
116
  try {
117
117
  const response = await handler(command);
118
- await client.publish(commandChannel, response);
118
+ await opts.api.publishResponse(opts.agentId, response);
119
119
  }
120
120
  catch (err) {
121
121
  const errorResponse = {
@@ -124,7 +124,7 @@ export function createConnection(opts) {
124
124
  success: false,
125
125
  error: err instanceof Error ? err.message : String(err),
126
126
  };
127
- await client.publish(commandChannel, errorResponse);
127
+ await opts.api.publishResponse(opts.agentId, errorResponse);
128
128
  }
129
129
  });
130
130
  client.on('connected', (ctx) => {
@@ -1 +1 @@
1
- {"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
+ import type { AgentApi } from './api.js';
1
2
  import type { BoardState, HeartbeatPayload } from './types.js';
2
3
  export interface HeartbeatOptions {
3
- centrifugoInternalUrl: string;
4
- centrifugoApiKey: string;
4
+ api: AgentApi;
5
5
  agentId: string;
6
6
  getBoardStatus?: () => BoardState;
7
7
  }
package/dist/heartbeat.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import os from 'node:os';
2
2
  import { debugLog } from './debug.js';
3
3
  const HEARTBEAT_INTERVAL = 30_000;
4
- const HEARTBEAT_CHANNEL = 'heartbeat:data';
5
4
  function getMetrics() {
6
5
  const cpus = os.cpus();
7
6
  const cpuUsage = cpus.reduce((acc, cpu) => {
@@ -24,38 +23,14 @@ async function publishHeartbeat(opts) {
24
23
  metrics: getMetrics(),
25
24
  ...(opts.getBoardStatus ? { boardStatus: opts.getBoardStatus() } : {}),
26
25
  };
27
- const controller = new AbortController();
28
- const timeout = setTimeout(() => controller.abort(), 5000);
29
26
  try {
30
27
  debugLog('heartbeat', '→ sending', opts.agentId, JSON.stringify(payload).slice(0, 500));
31
- const res = await fetch(`${opts.centrifugoInternalUrl}/api/publish`, {
32
- method: 'POST',
33
- headers: {
34
- 'Content-Type': 'application/json',
35
- 'Authorization': `apikey ${opts.centrifugoApiKey}`,
36
- },
37
- body: JSON.stringify({ channel: HEARTBEAT_CHANNEL, data: payload }),
38
- signal: controller.signal,
39
- });
40
- if (!res.ok) {
41
- const body = await res.text().catch(() => '');
42
- console.error(`Heartbeat publish failed (HTTP ${res.status}): ${body}`);
43
- debugLog('heartbeat', '← error', res.status, body);
44
- }
45
- else {
46
- debugLog('heartbeat', '← ok', res.status);
47
- }
28
+ await opts.api.publishHeartbeat(opts.agentId, payload);
29
+ debugLog('heartbeat', '← ok');
48
30
  }
49
31
  catch (err) {
50
- if (err.name === 'AbortError') {
51
- console.error('Heartbeat publish timed out');
52
- }
53
- else {
54
- console.error('Heartbeat publish failed:', err instanceof Error ? err.message : err);
55
- }
56
- }
57
- finally {
58
- clearTimeout(timeout);
32
+ console.error('Heartbeat publish failed:', err instanceof Error ? err.message : err);
33
+ debugLog('heartbeat', '← error', err);
59
34
  }
60
35
  }
61
36
  export function startHeartbeat(opts) {
@@ -1 +1 @@
1
- {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAQlC,SAAS,UAAU;IACjB,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,OAAO,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;IAC5C,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IAEpB,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAE7B,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,GAAG,GAAG;QACrC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,QAAQ,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG;QAC9D,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE;KACpB,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,IAAsB;IACpD,MAAM,OAAO,GAAqB;QAChC,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;QACd,OAAO,EAAE,UAAU,EAAE;QACrB,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAC;IAEF,IAAI,CAAC;QACH,QAAQ,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACxF,MAAM,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACrF,QAAQ,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAsB;IACnD,MAAM,IAAI,GAAG,GAAG,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,IAAI,EAAE,CAAC;IACP,OAAO,WAAW,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;AAC/C,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -19,13 +19,15 @@ export function main() {
19
19
  const token = requireEnv('AGENT_TOKEN');
20
20
  const agentId = requireEnv('AGENT_ID');
21
21
  const backendUrl = requireEnv('BACKEND_INTERNAL_URL');
22
- const centrifugoInternalUrl = process.env.CENTRIFUGO_INTERNAL_URL || '';
23
- const centrifugoApiKey = process.env.CENTRIFUGO_API_KEY || '';
22
+ // Read for backward compatibility but no longer used directly
23
+ void process.env.CENTRIFUGO_INTERNAL_URL;
24
+ void process.env.CENTRIFUGO_API_KEY;
24
25
  if (DEBUG)
25
26
  console.log('[debug] Debug mode enabled');
26
27
  console.log(`Starting agent-controller for agent: ${agentId}`);
27
28
  console.log(`Backend URL: ${backendUrl} (JWT mode)`);
28
- const { client } = createConnection({ url, token, agentId, backendUrl });
29
+ const api = createAgentApi(backendUrl, token);
30
+ const { client } = createConnection({ url, token, agentId, backendUrl, api });
29
31
  // Chat provider via OpenClaw Gateway WS
30
32
  const gatewayWsUrl = process.env.OPENCLAW_GATEWAY_WS || 'ws://localhost:18789';
31
33
  const gatewayToken = process.env.OPENCLAW_GATEWAY_TOKEN || '';
@@ -40,47 +42,35 @@ export function main() {
40
42
  else {
41
43
  console.warn('OPENCLAW_GATEWAY_TOKEN not set, chat provider disabled');
42
44
  }
43
- // Board handler (optional — requires BACKEND_URL and AGENT_TOKEN)
44
- let boardHandler = null;
45
- const apiBaseUrl = process.env.BACKEND_URL || backendUrl;
46
- if (apiBaseUrl && token) {
47
- const api = createAgentApi(apiBaseUrl, token);
48
- boardHandler = new BoardHandler(api);
49
- // Initialize board handler after connection is established
50
- boardHandler.initialize().then((workspaceId) => {
51
- if (!workspaceId) {
52
- console.log('No board found for this agent, board handler dormant');
45
+ // Board handler
46
+ const boardHandler = new BoardHandler(api);
47
+ // Initialize board handler after connection is established
48
+ boardHandler.initialize().then((workspaceId) => {
49
+ if (!workspaceId) {
50
+ console.log('No board found for this agent, board handler dormant');
51
+ return;
52
+ }
53
+ const boardChannel = `board:${workspaceId}`;
54
+ const boardSub = client.newSubscription(boardChannel);
55
+ boardSub.on('publication', (ctx) => {
56
+ const event = ctx.data;
57
+ if (!event || !event.event)
53
58
  return;
54
- }
55
- const boardChannel = `board:${workspaceId}`;
56
- const boardSub = client.newSubscription(boardChannel);
57
- boardSub.on('publication', (ctx) => {
58
- const event = ctx.data;
59
- if (!event || !event.event)
60
- return;
61
- boardHandler.onBoardEvent(event).catch((err) => {
62
- console.error('Board event handler error:', err instanceof Error ? err.message : err);
63
- });
59
+ boardHandler.onBoardEvent(event).catch((err) => {
60
+ console.error('Board event handler error:', err instanceof Error ? err.message : err);
64
61
  });
65
- boardSub.subscribe();
66
- console.log(`Subscribed to board channel: ${boardChannel}`);
67
- }).catch((err) => {
68
- console.error('Board handler init error:', err instanceof Error ? err.message : err);
69
62
  });
70
- }
71
- let heartbeatTimer;
72
- if (centrifugoInternalUrl && centrifugoApiKey) {
73
- console.log(`Heartbeat via Centrifugo internal API: ${centrifugoInternalUrl}`);
74
- heartbeatTimer = startHeartbeat({
75
- centrifugoInternalUrl,
76
- centrifugoApiKey,
77
- agentId,
78
- ...(boardHandler ? { getBoardStatus: () => boardHandler.getBoardStatus() } : {}),
79
- });
80
- }
81
- else {
82
- console.warn('CENTRIFUGO_INTERNAL_URL or CENTRIFUGO_API_KEY not set, heartbeat disabled');
83
- }
63
+ boardSub.subscribe();
64
+ console.log(`Subscribed to board channel: ${boardChannel}`);
65
+ }).catch((err) => {
66
+ console.error('Board handler init error:', err instanceof Error ? err.message : err);
67
+ });
68
+ console.log('Heartbeat via backend API');
69
+ const heartbeatTimer = startHeartbeat({
70
+ api,
71
+ agentId,
72
+ getBoardStatus: () => boardHandler.getBoardStatus(),
73
+ });
84
74
  const shutdown = () => {
85
75
  console.log('Shutting down...');
86
76
  if (heartbeatTimer)
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw-cloud/agent-controller",
3
- "version": "0.1.8",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/api.ts CHANGED
@@ -5,6 +5,8 @@ const TIMEOUT = 10_000;
5
5
  export interface AgentApi {
6
6
  get(path: string): Promise<unknown>;
7
7
  post(path: string, body?: unknown): Promise<Response>;
8
+ publishResponse(agentId: string, data: unknown): Promise<void>;
9
+ publishHeartbeat(agentId: string, payload: unknown): Promise<void>;
8
10
  }
9
11
 
10
12
  export function createAgentApi(backendUrl: string, agentToken: string): AgentApi {
@@ -44,5 +46,17 @@ export function createAgentApi(backendUrl: string, agentToken: string): AgentApi
44
46
  async post(path: string, body?: unknown): Promise<Response> {
45
47
  return request('POST', path, body);
46
48
  },
49
+ async publishResponse(agentId: string, data: unknown): Promise<void> {
50
+ const res = await request('POST', '/api/internal/agent-response', { agentId, data });
51
+ if (!res.ok) {
52
+ throw new Error(`publishResponse failed: HTTP ${res.status}`);
53
+ }
54
+ },
55
+ async publishHeartbeat(agentId: string, payload: unknown): Promise<void> {
56
+ const res = await request('POST', '/api/internal/agent-heartbeat', { agentId, payload });
57
+ if (!res.ok) {
58
+ throw new Error(`publishHeartbeat failed: HTTP ${res.status}`);
59
+ }
60
+ },
47
61
  };
48
62
  }
package/src/connection.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { debugLog } from './debug.js';
2
+ import type { AgentApi } from './api.js';
2
3
  import { Centrifuge, Subscription } from 'centrifuge';
3
4
  import WebSocket from 'ws';
4
5
  import type { AgentCommand, AgentResponse } from './types.js';
@@ -20,6 +21,7 @@ export interface ConnectionOptions {
20
21
  token: string;
21
22
  agentId: string;
22
23
  backendUrl: string;
24
+ api: AgentApi;
23
25
  }
24
26
 
25
27
  const handlers: Record<string, (cmd: AgentCommand) => Promise<AgentResponse>> = {
@@ -108,7 +110,7 @@ export function createConnection(opts: ConnectionOptions): {
108
110
 
109
111
  // Chat commands — handle before generic dispatch
110
112
  if (command.type === 'chat_list_sessions' || command.type === 'chat_history' || command.type === 'chat_send') {
111
- const publishFn = async (data: unknown): Promise<void> => { await client.publish(commandChannel, data); };
113
+ const publishFn = async (data: unknown): Promise<void> => { await opts.api.publishResponse(opts.agentId, data); };
112
114
  console.log(`[WS] Handling chat command: type=${command.type} id=${command.id}`);
113
115
  switch (command.type) {
114
116
  case 'chat_list_sessions':
@@ -133,7 +135,7 @@ export function createConnection(opts: ConnectionOptions): {
133
135
 
134
136
  try {
135
137
  const response = await handler(command);
136
- await client.publish(commandChannel, response);
138
+ await opts.api.publishResponse(opts.agentId, response);
137
139
  } catch (err) {
138
140
  const errorResponse: AgentResponse = {
139
141
  id: command.id,
@@ -141,7 +143,7 @@ export function createConnection(opts: ConnectionOptions): {
141
143
  success: false,
142
144
  error: err instanceof Error ? err.message : String(err),
143
145
  };
144
- await client.publish(commandChannel, errorResponse);
146
+ await opts.api.publishResponse(opts.agentId, errorResponse);
145
147
  }
146
148
  });
147
149
 
package/src/heartbeat.ts CHANGED
@@ -1,13 +1,12 @@
1
1
  import os from 'node:os';
2
2
  import { debugLog } from './debug.js';
3
+ import type { AgentApi } from './api.js';
3
4
  import type { BoardState, HeartbeatPayload } from './types.js';
4
5
 
5
6
  const HEARTBEAT_INTERVAL = 30_000;
6
- const HEARTBEAT_CHANNEL = 'heartbeat:data';
7
7
 
8
8
  export interface HeartbeatOptions {
9
- centrifugoInternalUrl: string;
10
- centrifugoApiKey: string;
9
+ api: AgentApi;
11
10
  agentId: string;
12
11
  getBoardStatus?: () => BoardState;
13
12
  }
@@ -38,36 +37,13 @@ async function publishHeartbeat(opts: HeartbeatOptions): Promise<void> {
38
37
  ...(opts.getBoardStatus ? { boardStatus: opts.getBoardStatus() } : {}),
39
38
  };
40
39
 
41
- const controller = new AbortController();
42
- const timeout = setTimeout(() => controller.abort(), 5000);
43
-
44
40
  try {
45
41
  debugLog('heartbeat', '→ sending', opts.agentId, JSON.stringify(payload).slice(0, 500));
46
- const res = await fetch(`${opts.centrifugoInternalUrl}/api/publish`, {
47
- method: 'POST',
48
- headers: {
49
- 'Content-Type': 'application/json',
50
- 'Authorization': `apikey ${opts.centrifugoApiKey}`,
51
- },
52
- body: JSON.stringify({ channel: HEARTBEAT_CHANNEL, data: payload }),
53
- signal: controller.signal,
54
- });
55
-
56
- if (!res.ok) {
57
- const body = await res.text().catch(() => '');
58
- console.error(`Heartbeat publish failed (HTTP ${res.status}): ${body}`);
59
- debugLog('heartbeat', '← error', res.status, body);
60
- } else {
61
- debugLog('heartbeat', '← ok', res.status);
62
- }
42
+ await opts.api.publishHeartbeat(opts.agentId, payload);
43
+ debugLog('heartbeat', '← ok');
63
44
  } catch (err) {
64
- if ((err as Error).name === 'AbortError') {
65
- console.error('Heartbeat publish timed out');
66
- } else {
67
- console.error('Heartbeat publish failed:', err instanceof Error ? err.message : err);
68
- }
69
- } finally {
70
- clearTimeout(timeout);
45
+ console.error('Heartbeat publish failed:', err instanceof Error ? err.message : err);
46
+ debugLog('heartbeat', '← error', err);
71
47
  }
72
48
  }
73
49
 
package/src/index.ts CHANGED
@@ -22,14 +22,16 @@ export function main(): void {
22
22
  const token = requireEnv('AGENT_TOKEN');
23
23
  const agentId = requireEnv('AGENT_ID');
24
24
  const backendUrl = requireEnv('BACKEND_INTERNAL_URL');
25
- const centrifugoInternalUrl = process.env.CENTRIFUGO_INTERNAL_URL || '';
26
- const centrifugoApiKey = process.env.CENTRIFUGO_API_KEY || '';
25
+ // Read for backward compatibility but no longer used directly
26
+ void process.env.CENTRIFUGO_INTERNAL_URL;
27
+ void process.env.CENTRIFUGO_API_KEY;
27
28
 
28
29
  if (DEBUG) console.log('[debug] Debug mode enabled');
29
30
  console.log(`Starting agent-controller for agent: ${agentId}`);
30
31
  console.log(`Backend URL: ${backendUrl} (JWT mode)`);
31
32
 
32
- const { client } = createConnection({ url, token, agentId, backendUrl });
33
+ const api = createAgentApi(backendUrl, token);
34
+ const { client } = createConnection({ url, token, agentId, backendUrl, api });
33
35
 
34
36
  // Chat provider via OpenClaw Gateway WS
35
37
  const gatewayWsUrl = process.env.OPENCLAW_GATEWAY_WS || 'ws://localhost:18789';
@@ -46,50 +48,39 @@ export function main(): void {
46
48
  console.warn('OPENCLAW_GATEWAY_TOKEN not set, chat provider disabled');
47
49
  }
48
50
 
49
- // Board handler (optional — requires BACKEND_URL and AGENT_TOKEN)
50
- let boardHandler: BoardHandler | null = null;
51
- const apiBaseUrl = process.env.BACKEND_URL || backendUrl;
52
- if (apiBaseUrl && token) {
53
- const api = createAgentApi(apiBaseUrl, token);
54
- boardHandler = new BoardHandler(api);
51
+ // Board handler
52
+ const boardHandler = new BoardHandler(api);
55
53
 
56
- // Initialize board handler after connection is established
57
- boardHandler.initialize().then((workspaceId) => {
58
- if (!workspaceId) {
59
- console.log('No board found for this agent, board handler dormant');
60
- return;
61
- }
54
+ // Initialize board handler after connection is established
55
+ boardHandler.initialize().then((workspaceId) => {
56
+ if (!workspaceId) {
57
+ console.log('No board found for this agent, board handler dormant');
58
+ return;
59
+ }
62
60
 
63
- const boardChannel = `board:${workspaceId}`;
64
- const boardSub = client.newSubscription(boardChannel);
61
+ const boardChannel = `board:${workspaceId}`;
62
+ const boardSub = client.newSubscription(boardChannel);
65
63
 
66
- boardSub.on('publication', (ctx) => {
67
- const event = ctx.data as BoardEvent;
68
- if (!event || !event.event) return;
69
- boardHandler!.onBoardEvent(event).catch((err) => {
70
- console.error('Board event handler error:', err instanceof Error ? err.message : err);
71
- });
64
+ boardSub.on('publication', (ctx) => {
65
+ const event = ctx.data as BoardEvent;
66
+ if (!event || !event.event) return;
67
+ boardHandler.onBoardEvent(event).catch((err) => {
68
+ console.error('Board event handler error:', err instanceof Error ? err.message : err);
72
69
  });
73
-
74
- boardSub.subscribe();
75
- console.log(`Subscribed to board channel: ${boardChannel}`);
76
- }).catch((err) => {
77
- console.error('Board handler init error:', err instanceof Error ? err.message : err);
78
70
  });
79
- }
80
71
 
81
- let heartbeatTimer: NodeJS.Timeout | undefined;
82
- if (centrifugoInternalUrl && centrifugoApiKey) {
83
- console.log(`Heartbeat via Centrifugo internal API: ${centrifugoInternalUrl}`);
84
- heartbeatTimer = startHeartbeat({
85
- centrifugoInternalUrl,
86
- centrifugoApiKey,
87
- agentId,
88
- ...(boardHandler ? { getBoardStatus: () => boardHandler!.getBoardStatus() } : {}),
89
- });
90
- } else {
91
- console.warn('CENTRIFUGO_INTERNAL_URL or CENTRIFUGO_API_KEY not set, heartbeat disabled');
92
- }
72
+ boardSub.subscribe();
73
+ console.log(`Subscribed to board channel: ${boardChannel}`);
74
+ }).catch((err) => {
75
+ console.error('Board handler init error:', err instanceof Error ? err.message : err);
76
+ });
77
+
78
+ console.log('Heartbeat via backend API');
79
+ const heartbeatTimer = startHeartbeat({
80
+ api,
81
+ agentId,
82
+ getBoardStatus: () => boardHandler.getBoardStatus(),
83
+ });
93
84
 
94
85
  const shutdown = () => {
95
86
  console.log('Shutting down...');