ticlawk 0.1.15 → 0.1.16-dev.10

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.
Files changed (34) hide show
  1. package/README.md +96 -212
  2. package/bin/ticlawk.mjs +223 -46
  3. package/package.json +2 -5
  4. package/src/adapters/ticlawk/api.mjs +308 -43
  5. package/src/adapters/ticlawk/credentials.mjs +1 -2
  6. package/src/adapters/ticlawk/index.mjs +310 -119
  7. package/src/cli/agent-commands.mjs +876 -0
  8. package/src/core/adapter-registry.mjs +12 -28
  9. package/src/core/agent-cli-handlers.mjs +731 -0
  10. package/src/core/agent-home.mjs +85 -0
  11. package/src/core/config.mjs +0 -15
  12. package/src/core/http.mjs +211 -18
  13. package/src/core/reminder-ticker.mjs +70 -0
  14. package/src/core/runtime-contract.mjs +1 -1
  15. package/src/core/runtime-env.mjs +41 -5
  16. package/src/core/runtime-support.mjs +31 -44
  17. package/src/core/ticlawk-control.mjs +7 -6
  18. package/src/migrate/write-initial-memory.mjs +101 -0
  19. package/src/runtimes/_shared/standing-prompt.mjs +308 -0
  20. package/src/runtimes/claude-code/index.mjs +49 -133
  21. package/src/runtimes/claude-code/session.mjs +15 -7
  22. package/src/runtimes/codex/index.mjs +29 -41
  23. package/src/runtimes/codex/session.mjs +9 -5
  24. package/src/runtimes/openclaw/index.mjs +59 -31
  25. package/src/runtimes/openclaw/target.mjs +0 -30
  26. package/src/runtimes/opencode/index.mjs +34 -56
  27. package/src/runtimes/opencode/session.mjs +11 -2
  28. package/src/runtimes/pi/index.mjs +31 -51
  29. package/src/runtimes/pi/session.mjs +8 -2
  30. package/ticlawk.mjs +37 -10
  31. package/assets/ticlawk-concept.svg +0 -137
  32. package/src/adapters/telegram/index.mjs +0 -359
  33. package/src/adapters/ticlawk/cards.mjs +0 -149
  34. package/src/core/media/outbound.mjs +0 -163
@@ -149,86 +149,339 @@ export async function updateChannel(id, updates) {
149
149
  return updateAgent(id, updates);
150
150
  }
151
151
 
152
- export async function postRuntimeResult(body) {
153
- const result = await apiFetch('/api/runtime-results', {
152
+ // ── Deliveries (replaces legacy message_jobs poll/ack) ──
153
+
154
+ export async function claimPendingDeliveries(hostId, limit = 5, excludedAgentIds = []) {
155
+ const { data } = await apiFetch('/api/agent/deliveries/claim-pending', {
154
156
  method: 'POST',
155
- body: JSON.stringify(body),
156
- timeout: 30000,
157
+ body: JSON.stringify(withTiclawkVersion({
158
+ runtime_host_id: hostId,
159
+ limit,
160
+ excluded_agent_ids: excludedAgentIds,
161
+ })),
157
162
  });
158
- if (result?.matched === false) {
159
- throw new Error('runtime result was not matched');
160
- }
161
- return result;
163
+ return data || [];
162
164
  }
163
165
 
164
- // ── Messages ──
166
+ export async function completeDelivery(deliveryId, hostId) {
167
+ return apiFetch(`/api/agent/deliveries/${deliveryId}/complete`, {
168
+ method: 'POST',
169
+ body: JSON.stringify({ runtime_host_id: hostId }),
170
+ });
171
+ }
165
172
 
166
- export async function getPendingMessages() {
167
- const { data } = await apiFetch('/api/messages/pending');
173
+ export async function releaseDelivery(deliveryId, hostId, reason = null) {
174
+ return apiFetch(`/api/agent/deliveries/${deliveryId}/release`, {
175
+ method: 'POST',
176
+ body: JSON.stringify({ runtime_host_id: hostId, reason }),
177
+ });
178
+ }
179
+
180
+ // ── Agent-facing CLI surface (group chat tool path) ──
181
+
182
+ export async function sendAgentMessage({
183
+ actingAgentId,
184
+ conversationId,
185
+ text,
186
+ seenUpToSeq,
187
+ replyToMessageId,
188
+ runtimeHostId,
189
+ visibility,
190
+ mediaAssetIds,
191
+ }) {
192
+ const { data } = await apiFetch('/api/agent/messages/send', {
193
+ method: 'POST',
194
+ body: JSON.stringify({
195
+ acting_as_agent_id: actingAgentId,
196
+ conversation_id: conversationId,
197
+ text,
198
+ seen_up_to_seq: seenUpToSeq ?? null,
199
+ reply_to_message_id: replyToMessageId ?? null,
200
+ runtime_host_id: runtimeHostId ?? null,
201
+ visibility: visibility || null,
202
+ media_asset_ids: Array.isArray(mediaAssetIds) && mediaAssetIds.length > 0 ? mediaAssetIds : undefined,
203
+ }),
204
+ });
205
+ return data || null;
206
+ }
207
+
208
+ export async function readAgentMessages({
209
+ actingAgentId,
210
+ conversationId,
211
+ aroundMessageId,
212
+ beforeSeq,
213
+ limit,
214
+ }) {
215
+ const params = new URLSearchParams();
216
+ params.set('acting_as_agent_id', actingAgentId);
217
+ params.set('conversation_id', conversationId);
218
+ if (aroundMessageId) params.set('around_message_id', aroundMessageId);
219
+ if (beforeSeq != null) params.set('before_seq', String(beforeSeq));
220
+ if (limit != null) params.set('limit', String(limit));
221
+ const { data } = await apiFetch(`/api/agent/messages/read?${params}`);
168
222
  return data || [];
169
223
  }
170
224
 
171
- export async function claimPendingMessages(hostId, limit = 5, excludedAgentIds = []) {
172
- const { data } = await apiFetch('/api/messages/claim-pending', {
225
+ export async function createAgentTask({ actingAgentId, conversationId, text, title }) {
226
+ return apiFetch('/api/agent/tasks/create', {
173
227
  method: 'POST',
174
- body: JSON.stringify(withTiclawkVersion({
175
- runtime_host_id: hostId,
176
- limit,
177
- excluded_agent_ids: excludedAgentIds,
178
- })),
228
+ body: JSON.stringify({
229
+ acting_as_agent_id: actingAgentId,
230
+ conversation_id: conversationId,
231
+ text,
232
+ title: title ?? null,
233
+ }),
234
+ });
235
+ }
236
+
237
+ export async function claimAgentTask({
238
+ actingAgentId, sourceMessageId, conversationId, number, leaseSeconds,
239
+ }) {
240
+ return apiFetch('/api/agent/tasks/claim', {
241
+ method: 'POST',
242
+ body: JSON.stringify({
243
+ acting_as_agent_id: actingAgentId,
244
+ source_message_id: sourceMessageId ?? null,
245
+ conversation_id: conversationId ?? null,
246
+ number: number ?? null,
247
+ lease_seconds: leaseSeconds ?? null,
248
+ }),
249
+ });
250
+ }
251
+
252
+ export async function unclaimAgentTask({ actingAgentId, taskId }) {
253
+ return apiFetch('/api/agent/tasks/unclaim', {
254
+ method: 'POST',
255
+ body: JSON.stringify({
256
+ acting_as_agent_id: actingAgentId,
257
+ task_id: taskId,
258
+ }),
259
+ });
260
+ }
261
+
262
+ export async function reactToMessage({
263
+ actingAgentId, messageId, emoji, remove,
264
+ }) {
265
+ return apiFetch(`/api/agent/messages/${encodeURIComponent(messageId)}/reactions`, {
266
+ method: remove ? 'DELETE' : 'POST',
267
+ body: JSON.stringify({
268
+ acting_as_agent_id: actingAgentId,
269
+ emoji,
270
+ }),
179
271
  });
272
+ }
273
+
274
+ export async function updateAgentTask({ actingAgentId, taskId, status }) {
275
+ return apiFetch('/api/agent/tasks/update', {
276
+ method: 'POST',
277
+ body: JSON.stringify({
278
+ acting_as_agent_id: actingAgentId,
279
+ task_id: taskId,
280
+ status,
281
+ }),
282
+ });
283
+ }
284
+
285
+ export async function listAgentTasks({ actingAgentId, conversationId }) {
286
+ const params = new URLSearchParams();
287
+ params.set('acting_as_agent_id', actingAgentId);
288
+ if (conversationId) params.set('conversation_id', conversationId);
289
+ const { data } = await apiFetch(`/api/agent/tasks/list?${params}`);
180
290
  return data || [];
181
291
  }
182
292
 
183
- export async function syncMessages(rows) {
184
- return apiFetch('/api/messages/sync', {
293
+ export async function getConversationMembers({ actingAgentId, conversationId }) {
294
+ const params = new URLSearchParams();
295
+ params.set('acting_as_agent_id', actingAgentId);
296
+ const res = await apiFetch(`/api/agent/conversations/${conversationId}/members?${params}`);
297
+ return res || { data: [], conversation: null };
298
+ }
299
+
300
+ export async function getAgentServerInfo({ actingAgentId }) {
301
+ const params = new URLSearchParams();
302
+ params.set('acting_as_agent_id', actingAgentId);
303
+ return apiFetch(`/api/agent/server-info?${params}`);
304
+ }
305
+
306
+ // ── Reminders ──
307
+
308
+ export async function scheduleAgentReminder({
309
+ actingAgentId, title, fireAt, anchorConversationId, anchorMessageId,
310
+ }) {
311
+ return apiFetch('/api/agent/reminders', {
185
312
  method: 'POST',
186
- body: JSON.stringify({ rows }),
313
+ body: JSON.stringify({
314
+ acting_as_agent_id: actingAgentId,
315
+ title,
316
+ fire_at: fireAt,
317
+ anchor_conversation_id: anchorConversationId,
318
+ anchor_message_id: anchorMessageId ?? null,
319
+ }),
187
320
  });
188
321
  }
189
322
 
190
- export async function claimMessage(id, hostId) {
191
- return apiFetch(`/api/messages/${id}/claim`, {
323
+ export async function listAgentReminders({ actingAgentId, status }) {
324
+ const params = new URLSearchParams();
325
+ params.set('acting_as_agent_id', actingAgentId);
326
+ if (status) params.set('status', status);
327
+ const { data } = await apiFetch(`/api/agent/reminders?${params}`);
328
+ return data || [];
329
+ }
330
+
331
+ export async function snoozeAgentReminder({ actingAgentId, reminderId, fireAt }) {
332
+ return apiFetch(`/api/agent/reminders/${encodeURIComponent(reminderId)}/snooze`, {
192
333
  method: 'POST',
193
- body: JSON.stringify(withTiclawkVersion({ runtime_host_id: hostId })),
334
+ body: JSON.stringify({
335
+ acting_as_agent_id: actingAgentId,
336
+ fire_at: fireAt,
337
+ }),
338
+ });
339
+ }
340
+
341
+ export async function updateAgentReminder({
342
+ actingAgentId, reminderId, title, fireAt,
343
+ }) {
344
+ return apiFetch(`/api/agent/reminders/${encodeURIComponent(reminderId)}`, {
345
+ method: 'PATCH',
346
+ body: JSON.stringify({
347
+ acting_as_agent_id: actingAgentId,
348
+ title: title ?? null,
349
+ fire_at: fireAt ?? null,
350
+ }),
194
351
  });
195
352
  }
196
353
 
197
- export async function releaseMessage(id, hostId) {
198
- return apiFetch(`/api/messages/${id}/release`, {
354
+ export async function cancelAgentReminder({ actingAgentId, reminderId }) {
355
+ return apiFetch(`/api/agent/reminders/${encodeURIComponent(reminderId)}/cancel`, {
199
356
  method: 'POST',
200
- body: JSON.stringify({ runtime_host_id: hostId }),
357
+ body: JSON.stringify({ acting_as_agent_id: actingAgentId }),
201
358
  });
202
359
  }
203
360
 
204
- export async function completeMessage(id, hostId) {
205
- return apiFetch(`/api/messages/${id}/complete`, {
361
+ export async function getAgentReminderLog({ actingAgentId, reminderId }) {
362
+ const params = new URLSearchParams();
363
+ params.set('acting_as_agent_id', actingAgentId);
364
+ const { data } = await apiFetch(`/api/agent/reminders/${encodeURIComponent(reminderId)}/log?${params}`);
365
+ return data || [];
366
+ }
367
+
368
+ export async function fireDueReminders() {
369
+ // System call: no acting agent. Used by the daemon's tick.
370
+ return apiFetch('/api/agent/reminders/fire-due', {
206
371
  method: 'POST',
207
- body: JSON.stringify({ runtime_host_id: hostId }),
372
+ body: '{}',
373
+ });
374
+ }
375
+
376
+ export async function checkAgentMessages({ actingAgentId, conversationId }) {
377
+ const params = new URLSearchParams();
378
+ params.set('acting_as_agent_id', actingAgentId);
379
+ if (conversationId) params.set('conversation_id', conversationId);
380
+ return apiFetch(`/api/agent/messages/check?${params}`);
381
+ }
382
+
383
+ export async function searchAgentMessages({
384
+ actingAgentId, query, conversationId, limit,
385
+ }) {
386
+ const params = new URLSearchParams();
387
+ params.set('acting_as_agent_id', actingAgentId);
388
+ params.set('q', query);
389
+ if (conversationId) params.set('conversation_id', conversationId);
390
+ if (limit != null) params.set('limit', String(limit));
391
+ const { data } = await apiFetch(`/api/agent/messages/search?${params}`);
392
+ return data || [];
393
+ }
394
+
395
+ export async function getAgentProfile({ actingAgentId, idOrHandle }) {
396
+ const params = new URLSearchParams();
397
+ params.set('acting_as_agent_id', actingAgentId);
398
+ return apiFetch(`/api/agent/profile/${encodeURIComponent(idOrHandle)}?${params}`);
399
+ }
400
+
401
+ export async function patchAgentProfile({
402
+ actingAgentId, displayName, description, avatarUrl,
403
+ }) {
404
+ return apiFetch('/api/agent/profile', {
405
+ method: 'PATCH',
406
+ body: JSON.stringify({
407
+ acting_as_agent_id: actingAgentId,
408
+ display_name: displayName ?? null,
409
+ description: description ?? null,
410
+ avatar_url: avatarUrl ?? null,
411
+ }),
208
412
  });
209
413
  }
210
414
 
211
- export async function recoverClaimedMessages(hostId) {
212
- return apiFetch('/api/messages/recover', {
415
+ export async function uploadAgentAttachment({
416
+ actingAgentId, filename, contentType, dataBase64,
417
+ }) {
418
+ return apiFetch('/api/agent/attachments', {
213
419
  method: 'POST',
214
- body: JSON.stringify(withTiclawkVersion({ runtime_host_id: hostId })),
420
+ body: JSON.stringify({
421
+ acting_as_agent_id: actingAgentId,
422
+ filename,
423
+ content_type: contentType,
424
+ data_base64: dataBase64,
425
+ }),
215
426
  });
216
427
  }
217
428
 
218
- // ── Upload ──
429
+ export async function uploadAgentAvatar({
430
+ actingAgentId, filename, contentType, dataBase64,
431
+ }) {
432
+ return apiFetch('/api/agent/profile/avatar', {
433
+ method: 'POST',
434
+ body: JSON.stringify({
435
+ acting_as_agent_id: actingAgentId,
436
+ filename,
437
+ content_type: contentType,
438
+ data_base64: dataBase64,
439
+ }),
440
+ });
441
+ }
219
442
 
220
- export async function uploadAsset(fileName, fileData, contentType, kind = 'chat_media') {
221
- const formData = new FormData();
222
- formData.append('file', new Blob([fileData], { type: contentType }), fileName);
223
- formData.append('kind', kind);
224
- if (contentType) formData.append('content_type', contentType);
443
+ export async function viewAgentAttachment({ actingAgentId, assetId }) {
444
+ const params = new URLSearchParams();
445
+ params.set('acting_as_agent_id', actingAgentId);
446
+ return apiFetch(`/api/agent/attachments/${encodeURIComponent(assetId)}?${params}`);
447
+ }
225
448
 
226
- const { data } = await apiFetch('/api/assets/upload', {
449
+ export async function createAgentGroup({
450
+ actingAgentId, name, description, memberAgentIds,
451
+ }) {
452
+ return apiFetch('/api/agent/groups', {
227
453
  method: 'POST',
228
- body: formData,
229
- timeout: 30000,
454
+ body: JSON.stringify({
455
+ acting_as_agent_id: actingAgentId,
456
+ name,
457
+ description: description ?? null,
458
+ member_agent_ids: memberAgentIds || [],
459
+ }),
460
+ });
461
+ }
462
+
463
+ export async function addAgentGroupMembers({
464
+ actingAgentId, conversationId, agentIds,
465
+ }) {
466
+ return apiFetch(`/api/agent/groups/${encodeURIComponent(conversationId)}/members`, {
467
+ method: 'POST',
468
+ body: JSON.stringify({
469
+ acting_as_agent_id: actingAgentId,
470
+ agent_ids: agentIds,
471
+ }),
230
472
  });
231
- return data;
473
+ }
474
+
475
+ export async function removeAgentGroupMember({
476
+ actingAgentId, conversationId, agentId,
477
+ }) {
478
+ return apiFetch(
479
+ `/api/agent/groups/${encodeURIComponent(conversationId)}/members/${encodeURIComponent(agentId)}`,
480
+ {
481
+ method: 'DELETE',
482
+ body: JSON.stringify({ acting_as_agent_id: actingAgentId }),
483
+ },
484
+ );
232
485
  }
233
486
 
234
487
  // ── Channel event pipe ──
@@ -358,3 +611,15 @@ export async function getMe() {
358
611
  const { data } = await apiFetch('/api/me');
359
612
  return data || null;
360
613
  }
614
+
615
+ export async function reportHostCapabilities({ hostId, hostLabel, runtimesHealth, daemonVersion }) {
616
+ return apiFetch('/api/hosts/capabilities', {
617
+ method: 'POST',
618
+ body: JSON.stringify({
619
+ host_id: hostId,
620
+ host_label: hostLabel || null,
621
+ runtimes_health: runtimesHealth || {},
622
+ daemon_version: daemonVersion || null,
623
+ }),
624
+ });
625
+ }
@@ -6,13 +6,12 @@
6
6
  * using the connector-specific env name.
7
7
  */
8
8
 
9
- import { AF_ADAPTER_KEY, AF_CONFIG_PATH, persistConfig, TICLAWK_CONNECTOR_API_KEY } from '../../core/config.mjs';
9
+ import { AF_CONFIG_PATH, persistConfig, TICLAWK_CONNECTOR_API_KEY } from '../../core/config.mjs';
10
10
 
11
11
  export function persistApiCredential(apiKey) {
12
12
  if (!apiKey || !apiKey.startsWith('tk_')) return;
13
13
 
14
14
  persistConfig({
15
- [AF_ADAPTER_KEY]: 'ticlawk',
16
15
  [TICLAWK_CONNECTOR_API_KEY]: apiKey,
17
16
  TICLAWK_SETUP_CODE: '',
18
17
  });