ticlawk 0.1.16-dev.1 → 0.1.16-dev.3

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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ticlawk",
3
- "version": "0.1.16-dev.1",
3
+ "version": "0.1.16-dev.3",
4
4
  "description": "Local connector that links agent harnesses (Claude Code, Codex, OpenClaw, opencode, Pi) to the Ticlawk mobile app.",
5
5
  "type": "module",
6
6
  "main": "ticlawk.mjs",
@@ -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 claimAgentTask({ actingAgentId, sourceMessageId, leaseSeconds }) {
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
- // ── Transcript history ──
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 syncMessages(rows) {
279
- return apiFetch('/api/messages/sync', {
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({ rows }),
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
+ }