ticlawk 0.1.16-dev.1 → 0.1.16-dev.2
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/README.md +13 -0
- package/bin/ticlawk.mjs +121 -0
- package/package.json +1 -1
- package/src/adapters/ticlawk/api.mjs +216 -6
- package/src/adapters/ticlawk/index.mjs +221 -71
- package/src/cli/agent-commands.mjs +545 -6
- package/src/core/agent-cli-handlers.mjs +416 -3
- package/src/core/agent-home.mjs +89 -0
- package/src/core/http.mjs +114 -0
- package/src/core/reminder-ticker.mjs +70 -0
- package/src/core/runtime-contract.mjs +1 -1
- package/src/core/runtime-support.mjs +31 -29
- package/src/core/ticlawk-control.mjs +3 -3
- package/src/migrate/write-initial-memory.mjs +101 -0
- package/src/runtimes/_shared/standing-prompt.mjs +277 -76
- package/src/runtimes/claude-code/index.mjs +8 -27
- package/src/runtimes/codex/index.mjs +15 -32
- package/src/runtimes/openclaw/index.mjs +34 -13
- package/src/runtimes/openclaw/target.mjs +0 -30
- package/src/runtimes/opencode/index.mjs +13 -31
- package/src/runtimes/pi/index.mjs +13 -32
- package/ticlawk.mjs +31 -6
package/README.md
CHANGED
|
@@ -211,10 +211,23 @@ Usage:
|
|
|
211
211
|
ticlawk uninstall [-y]
|
|
212
212
|
ticlawk version
|
|
213
213
|
|
|
214
|
+
Agent CLI (run inside an agent runtime; requires TICLAWK_RUNTIME_AGENT_ID):
|
|
215
|
+
ticlawk message send --target <t> # body on stdin
|
|
216
|
+
ticlawk message read --target <t> [opts]
|
|
217
|
+
ticlawk task claim --message-id <id>
|
|
218
|
+
ticlawk task update --task-id <id> --status <s>
|
|
219
|
+
ticlawk task list [--target <t>]
|
|
220
|
+
ticlawk group members --target <t>
|
|
221
|
+
ticlawk server info [--refresh]
|
|
222
|
+
|
|
214
223
|
Commands:
|
|
215
224
|
auth store the ticlawk app pairing code locally
|
|
216
225
|
connect connect ticlawk to a local runtime
|
|
217
226
|
profile list or switch saved local identities
|
|
227
|
+
message send/read chat messages (agent CLI surface)
|
|
228
|
+
task claim/update/list tasks (agent CLI surface)
|
|
229
|
+
group list members of a group conversation (agent CLI surface)
|
|
230
|
+
server server-info introspection (agent CLI surface)
|
|
218
231
|
install-daemon install or refresh the background daemon
|
|
219
232
|
update update the npm package and refresh the daemon
|
|
220
233
|
uninstall remove service and managed install files, preserving ~/.ticlawk
|
package/bin/ticlawk.mjs
CHANGED
|
@@ -30,12 +30,30 @@ import { getInstallDaemonHelp, runInstallDaemon } from '../src/core/daemon-insta
|
|
|
30
30
|
import { runSetupReadiness } from '../src/core/setup-readiness.mjs';
|
|
31
31
|
import {
|
|
32
32
|
AGENT_COMMAND_HELP,
|
|
33
|
+
runAttachmentUploadCommand,
|
|
34
|
+
runAttachmentViewCommand,
|
|
35
|
+
runGroupCreateCommand,
|
|
36
|
+
runGroupMembersAddCommand,
|
|
33
37
|
runGroupMembersCommand,
|
|
38
|
+
runGroupMembersRemoveCommand,
|
|
39
|
+
runMessageCheckCommand,
|
|
40
|
+
runMessageReactCommand,
|
|
34
41
|
runMessageReadCommand,
|
|
42
|
+
runMessageSearchCommand,
|
|
35
43
|
runMessageSendCommand,
|
|
44
|
+
runProfileShowCommand,
|
|
45
|
+
runProfileUpdateCommand,
|
|
46
|
+
runReminderCancelCommand,
|
|
47
|
+
runReminderListCommand,
|
|
48
|
+
runReminderLogCommand,
|
|
49
|
+
runReminderScheduleCommand,
|
|
50
|
+
runReminderSnoozeCommand,
|
|
51
|
+
runReminderUpdateCommand,
|
|
36
52
|
runServerInfoCommand,
|
|
37
53
|
runTaskClaimCommand,
|
|
54
|
+
runTaskCreateCommand,
|
|
38
55
|
runTaskListCommand,
|
|
56
|
+
runTaskUnclaimCommand,
|
|
39
57
|
runTaskUpdateCommand,
|
|
40
58
|
} from '../src/cli/agent-commands.mjs';
|
|
41
59
|
|
|
@@ -324,20 +342,110 @@ async function main() {
|
|
|
324
342
|
process.exitCode = await runMessageReadCommand(args);
|
|
325
343
|
return;
|
|
326
344
|
}
|
|
345
|
+
if (sub === 'react') {
|
|
346
|
+
process.exitCode = await runMessageReactCommand(args);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (sub === 'check') {
|
|
350
|
+
process.exitCode = await runMessageCheckCommand(args);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
if (sub === 'search') {
|
|
354
|
+
process.exitCode = await runMessageSearchCommand(args);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
327
357
|
console.error(`unknown message subcommand: ${sub}`);
|
|
328
358
|
process.exit(1);
|
|
329
359
|
}
|
|
330
360
|
|
|
361
|
+
if (command === 'profile') {
|
|
362
|
+
const sub = args._[1];
|
|
363
|
+
if (args.help || args.h || !sub) {
|
|
364
|
+
console.log(AGENT_COMMAND_HELP.profile);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
if (sub === 'show') {
|
|
368
|
+
process.exitCode = await runProfileShowCommand(args);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
if (sub === 'update') {
|
|
372
|
+
process.exitCode = await runProfileUpdateCommand(args);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
console.error(`unknown profile subcommand: ${sub}`);
|
|
376
|
+
process.exit(1);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (command === 'reminder') {
|
|
380
|
+
const sub = args._[1];
|
|
381
|
+
if (args.help || args.h || !sub) {
|
|
382
|
+
console.log(AGENT_COMMAND_HELP.reminder);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
if (sub === 'schedule') {
|
|
386
|
+
process.exitCode = await runReminderScheduleCommand(args);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (sub === 'list') {
|
|
390
|
+
process.exitCode = await runReminderListCommand(args);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
if (sub === 'snooze') {
|
|
394
|
+
process.exitCode = await runReminderSnoozeCommand(args);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
if (sub === 'update') {
|
|
398
|
+
process.exitCode = await runReminderUpdateCommand(args);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (sub === 'cancel') {
|
|
402
|
+
process.exitCode = await runReminderCancelCommand(args);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
if (sub === 'log') {
|
|
406
|
+
process.exitCode = await runReminderLogCommand(args);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
console.error(`unknown reminder subcommand: ${sub}`);
|
|
410
|
+
process.exit(1);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (command === 'attachment') {
|
|
414
|
+
const sub = args._[1];
|
|
415
|
+
if (args.help || args.h || !sub) {
|
|
416
|
+
console.log(AGENT_COMMAND_HELP.attachment);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
if (sub === 'upload') {
|
|
420
|
+
process.exitCode = await runAttachmentUploadCommand(args);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
if (sub === 'view') {
|
|
424
|
+
process.exitCode = await runAttachmentViewCommand(args);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
console.error(`unknown attachment subcommand: ${sub}`);
|
|
428
|
+
process.exit(1);
|
|
429
|
+
}
|
|
430
|
+
|
|
331
431
|
if (command === 'task') {
|
|
332
432
|
const sub = args._[1];
|
|
333
433
|
if (args.help || args.h || !sub) {
|
|
334
434
|
console.log(AGENT_COMMAND_HELP.task);
|
|
335
435
|
return;
|
|
336
436
|
}
|
|
437
|
+
if (sub === 'create') {
|
|
438
|
+
process.exitCode = await runTaskCreateCommand(args);
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
337
441
|
if (sub === 'claim') {
|
|
338
442
|
process.exitCode = await runTaskClaimCommand(args);
|
|
339
443
|
return;
|
|
340
444
|
}
|
|
445
|
+
if (sub === 'unclaim') {
|
|
446
|
+
process.exitCode = await runTaskUnclaimCommand(args);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
341
449
|
if (sub === 'update') {
|
|
342
450
|
process.exitCode = await runTaskUpdateCommand(args);
|
|
343
451
|
return;
|
|
@@ -356,7 +464,20 @@ async function main() {
|
|
|
356
464
|
console.log(AGENT_COMMAND_HELP.group);
|
|
357
465
|
return;
|
|
358
466
|
}
|
|
467
|
+
if (sub === 'create') {
|
|
468
|
+
process.exitCode = await runGroupCreateCommand(args);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
359
471
|
if (sub === 'members') {
|
|
472
|
+
// Same subcommand handles list / add / remove based on flags.
|
|
473
|
+
if (args.add) {
|
|
474
|
+
process.exitCode = await runGroupMembersAddCommand(args);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
if (args.remove) {
|
|
478
|
+
process.exitCode = await runGroupMembersRemoveCommand(args);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
360
481
|
process.exitCode = await runGroupMembersCommand(args);
|
|
361
482
|
return;
|
|
362
483
|
}
|
package/package.json
CHANGED
|
@@ -198,6 +198,7 @@ export async function sendAgentMessage({
|
|
|
198
198
|
seenUpToSeq,
|
|
199
199
|
replyToMessageId,
|
|
200
200
|
runtimeHostId,
|
|
201
|
+
visibility,
|
|
201
202
|
}) {
|
|
202
203
|
const { data } = await apiFetch('/api/agent/messages/send', {
|
|
203
204
|
method: 'POST',
|
|
@@ -208,6 +209,7 @@ export async function sendAgentMessage({
|
|
|
208
209
|
seen_up_to_seq: seenUpToSeq ?? null,
|
|
209
210
|
reply_to_message_id: replyToMessageId ?? null,
|
|
210
211
|
runtime_host_id: runtimeHostId ?? null,
|
|
212
|
+
visibility: visibility || null,
|
|
211
213
|
}),
|
|
212
214
|
});
|
|
213
215
|
return data || null;
|
|
@@ -230,17 +232,55 @@ export async function readAgentMessages({
|
|
|
230
232
|
return data || [];
|
|
231
233
|
}
|
|
232
234
|
|
|
233
|
-
export async function
|
|
235
|
+
export async function createAgentTask({ actingAgentId, conversationId, text, title }) {
|
|
236
|
+
return apiFetch('/api/agent/tasks/create', {
|
|
237
|
+
method: 'POST',
|
|
238
|
+
body: JSON.stringify({
|
|
239
|
+
acting_as_agent_id: actingAgentId,
|
|
240
|
+
conversation_id: conversationId,
|
|
241
|
+
text,
|
|
242
|
+
title: title ?? null,
|
|
243
|
+
}),
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export async function claimAgentTask({
|
|
248
|
+
actingAgentId, sourceMessageId, conversationId, number, leaseSeconds,
|
|
249
|
+
}) {
|
|
234
250
|
return apiFetch('/api/agent/tasks/claim', {
|
|
235
251
|
method: 'POST',
|
|
236
252
|
body: JSON.stringify({
|
|
237
253
|
acting_as_agent_id: actingAgentId,
|
|
238
|
-
source_message_id: sourceMessageId,
|
|
254
|
+
source_message_id: sourceMessageId ?? null,
|
|
255
|
+
conversation_id: conversationId ?? null,
|
|
256
|
+
number: number ?? null,
|
|
239
257
|
lease_seconds: leaseSeconds ?? null,
|
|
240
258
|
}),
|
|
241
259
|
});
|
|
242
260
|
}
|
|
243
261
|
|
|
262
|
+
export async function unclaimAgentTask({ actingAgentId, taskId }) {
|
|
263
|
+
return apiFetch('/api/agent/tasks/unclaim', {
|
|
264
|
+
method: 'POST',
|
|
265
|
+
body: JSON.stringify({
|
|
266
|
+
acting_as_agent_id: actingAgentId,
|
|
267
|
+
task_id: taskId,
|
|
268
|
+
}),
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export async function reactToMessage({
|
|
273
|
+
actingAgentId, messageId, emoji, remove,
|
|
274
|
+
}) {
|
|
275
|
+
return apiFetch(`/api/agent/messages/${encodeURIComponent(messageId)}/reactions`, {
|
|
276
|
+
method: remove ? 'DELETE' : 'POST',
|
|
277
|
+
body: JSON.stringify({
|
|
278
|
+
acting_as_agent_id: actingAgentId,
|
|
279
|
+
emoji,
|
|
280
|
+
}),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
244
284
|
export async function updateAgentTask({ actingAgentId, taskId, status }) {
|
|
245
285
|
return apiFetch('/api/agent/tasks/update', {
|
|
246
286
|
method: 'POST',
|
|
@@ -273,15 +313,173 @@ export async function getAgentServerInfo({ actingAgentId }) {
|
|
|
273
313
|
return apiFetch(`/api/agent/server-info?${params}`);
|
|
274
314
|
}
|
|
275
315
|
|
|
276
|
-
// ──
|
|
316
|
+
// ── Reminders ──
|
|
317
|
+
|
|
318
|
+
export async function scheduleAgentReminder({
|
|
319
|
+
actingAgentId, title, fireAt, anchorConversationId, anchorMessageId,
|
|
320
|
+
}) {
|
|
321
|
+
return apiFetch('/api/agent/reminders', {
|
|
322
|
+
method: 'POST',
|
|
323
|
+
body: JSON.stringify({
|
|
324
|
+
acting_as_agent_id: actingAgentId,
|
|
325
|
+
title,
|
|
326
|
+
fire_at: fireAt,
|
|
327
|
+
anchor_conversation_id: anchorConversationId,
|
|
328
|
+
anchor_message_id: anchorMessageId ?? null,
|
|
329
|
+
}),
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export async function listAgentReminders({ actingAgentId, status }) {
|
|
334
|
+
const params = new URLSearchParams();
|
|
335
|
+
params.set('acting_as_agent_id', actingAgentId);
|
|
336
|
+
if (status) params.set('status', status);
|
|
337
|
+
const { data } = await apiFetch(`/api/agent/reminders?${params}`);
|
|
338
|
+
return data || [];
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export async function snoozeAgentReminder({ actingAgentId, reminderId, fireAt }) {
|
|
342
|
+
return apiFetch(`/api/agent/reminders/${encodeURIComponent(reminderId)}/snooze`, {
|
|
343
|
+
method: 'POST',
|
|
344
|
+
body: JSON.stringify({
|
|
345
|
+
acting_as_agent_id: actingAgentId,
|
|
346
|
+
fire_at: fireAt,
|
|
347
|
+
}),
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export async function updateAgentReminder({
|
|
352
|
+
actingAgentId, reminderId, title, fireAt,
|
|
353
|
+
}) {
|
|
354
|
+
return apiFetch(`/api/agent/reminders/${encodeURIComponent(reminderId)}`, {
|
|
355
|
+
method: 'PATCH',
|
|
356
|
+
body: JSON.stringify({
|
|
357
|
+
acting_as_agent_id: actingAgentId,
|
|
358
|
+
title: title ?? null,
|
|
359
|
+
fire_at: fireAt ?? null,
|
|
360
|
+
}),
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export async function cancelAgentReminder({ actingAgentId, reminderId }) {
|
|
365
|
+
return apiFetch(`/api/agent/reminders/${encodeURIComponent(reminderId)}/cancel`, {
|
|
366
|
+
method: 'POST',
|
|
367
|
+
body: JSON.stringify({ acting_as_agent_id: actingAgentId }),
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export async function getAgentReminderLog({ actingAgentId, reminderId }) {
|
|
372
|
+
const params = new URLSearchParams();
|
|
373
|
+
params.set('acting_as_agent_id', actingAgentId);
|
|
374
|
+
const { data } = await apiFetch(`/api/agent/reminders/${encodeURIComponent(reminderId)}/log?${params}`);
|
|
375
|
+
return data || [];
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export async function fireDueReminders() {
|
|
379
|
+
// System call: no acting agent. Used by the daemon's tick.
|
|
380
|
+
return apiFetch('/api/agent/reminders/fire-due', {
|
|
381
|
+
method: 'POST',
|
|
382
|
+
body: '{}',
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export async function checkAgentMessages({ actingAgentId, conversationId }) {
|
|
387
|
+
const params = new URLSearchParams();
|
|
388
|
+
params.set('acting_as_agent_id', actingAgentId);
|
|
389
|
+
if (conversationId) params.set('conversation_id', conversationId);
|
|
390
|
+
return apiFetch(`/api/agent/messages/check?${params}`);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export async function searchAgentMessages({
|
|
394
|
+
actingAgentId, query, conversationId, limit,
|
|
395
|
+
}) {
|
|
396
|
+
const params = new URLSearchParams();
|
|
397
|
+
params.set('acting_as_agent_id', actingAgentId);
|
|
398
|
+
params.set('q', query);
|
|
399
|
+
if (conversationId) params.set('conversation_id', conversationId);
|
|
400
|
+
if (limit != null) params.set('limit', String(limit));
|
|
401
|
+
const { data } = await apiFetch(`/api/agent/messages/search?${params}`);
|
|
402
|
+
return data || [];
|
|
403
|
+
}
|
|
277
404
|
|
|
278
|
-
export async function
|
|
279
|
-
|
|
405
|
+
export async function getAgentProfile({ actingAgentId, idOrHandle }) {
|
|
406
|
+
const params = new URLSearchParams();
|
|
407
|
+
params.set('acting_as_agent_id', actingAgentId);
|
|
408
|
+
return apiFetch(`/api/agent/profile/${encodeURIComponent(idOrHandle)}?${params}`);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export async function patchAgentProfile({
|
|
412
|
+
actingAgentId, displayName, description, avatarUrl,
|
|
413
|
+
}) {
|
|
414
|
+
return apiFetch('/api/agent/profile', {
|
|
415
|
+
method: 'PATCH',
|
|
416
|
+
body: JSON.stringify({
|
|
417
|
+
acting_as_agent_id: actingAgentId,
|
|
418
|
+
display_name: displayName ?? null,
|
|
419
|
+
description: description ?? null,
|
|
420
|
+
avatar_url: avatarUrl ?? null,
|
|
421
|
+
}),
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export async function uploadAgentAttachment({
|
|
426
|
+
actingAgentId, filename, contentType, dataBase64,
|
|
427
|
+
}) {
|
|
428
|
+
return apiFetch('/api/agent/attachments', {
|
|
280
429
|
method: 'POST',
|
|
281
|
-
body: JSON.stringify({
|
|
430
|
+
body: JSON.stringify({
|
|
431
|
+
acting_as_agent_id: actingAgentId,
|
|
432
|
+
filename,
|
|
433
|
+
content_type: contentType,
|
|
434
|
+
data_base64: dataBase64,
|
|
435
|
+
}),
|
|
282
436
|
});
|
|
283
437
|
}
|
|
284
438
|
|
|
439
|
+
export async function viewAgentAttachment({ actingAgentId, assetId }) {
|
|
440
|
+
const params = new URLSearchParams();
|
|
441
|
+
params.set('acting_as_agent_id', actingAgentId);
|
|
442
|
+
return apiFetch(`/api/agent/attachments/${encodeURIComponent(assetId)}?${params}`);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export async function createAgentGroup({
|
|
446
|
+
actingAgentId, name, description, memberAgentIds,
|
|
447
|
+
}) {
|
|
448
|
+
return apiFetch('/api/agent/groups', {
|
|
449
|
+
method: 'POST',
|
|
450
|
+
body: JSON.stringify({
|
|
451
|
+
acting_as_agent_id: actingAgentId,
|
|
452
|
+
name,
|
|
453
|
+
description: description ?? null,
|
|
454
|
+
member_agent_ids: memberAgentIds || [],
|
|
455
|
+
}),
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export async function addAgentGroupMembers({
|
|
460
|
+
actingAgentId, conversationId, agentIds,
|
|
461
|
+
}) {
|
|
462
|
+
return apiFetch(`/api/agent/groups/${encodeURIComponent(conversationId)}/members`, {
|
|
463
|
+
method: 'POST',
|
|
464
|
+
body: JSON.stringify({
|
|
465
|
+
acting_as_agent_id: actingAgentId,
|
|
466
|
+
agent_ids: agentIds,
|
|
467
|
+
}),
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export async function removeAgentGroupMember({
|
|
472
|
+
actingAgentId, conversationId, agentId,
|
|
473
|
+
}) {
|
|
474
|
+
return apiFetch(
|
|
475
|
+
`/api/agent/groups/${encodeURIComponent(conversationId)}/members/${encodeURIComponent(agentId)}`,
|
|
476
|
+
{
|
|
477
|
+
method: 'DELETE',
|
|
478
|
+
body: JSON.stringify({ acting_as_agent_id: actingAgentId }),
|
|
479
|
+
},
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
|
|
285
483
|
// ── Upload ──
|
|
286
484
|
|
|
287
485
|
export async function uploadAsset(fileName, fileData, contentType, kind = 'chat_media') {
|
|
@@ -425,3 +623,15 @@ export async function getMe() {
|
|
|
425
623
|
const { data } = await apiFetch('/api/me');
|
|
426
624
|
return data || null;
|
|
427
625
|
}
|
|
626
|
+
|
|
627
|
+
export async function reportHostCapabilities({ hostId, hostLabel, runtimesHealth, daemonVersion }) {
|
|
628
|
+
return apiFetch('/api/hosts/capabilities', {
|
|
629
|
+
method: 'POST',
|
|
630
|
+
body: JSON.stringify({
|
|
631
|
+
host_id: hostId,
|
|
632
|
+
host_label: hostLabel || null,
|
|
633
|
+
runtimes_health: runtimesHealth || {},
|
|
634
|
+
daemon_version: daemonVersion || null,
|
|
635
|
+
}),
|
|
636
|
+
});
|
|
637
|
+
}
|