ticlawk 0.1.17-dev.17 → 0.1.17-dev.19
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 +3 -17
- package/bin/ticlawk.mjs +21 -245
- package/package.json +1 -1
- package/src/adapters/ticlawk/api.mjs +51 -327
- package/src/adapters/ticlawk/credentials.mjs +1 -41
- package/src/adapters/ticlawk/index.mjs +27 -249
- package/src/adapters/ticlawk/wake-client.mjs +1 -1
- package/src/cli/agent-commands.mjs +22 -703
- package/src/core/agent-cli-handlers.mjs +18 -519
- package/src/core/agent-home.mjs +1 -64
- package/src/core/events/worker-events.mjs +36 -32
- package/src/core/http.mjs +0 -138
- package/src/core/runtime-contract.mjs +1 -0
- package/src/core/runtime-env.mjs +0 -7
- package/src/core/runtime-support.mjs +78 -130
- package/src/runtimes/_shared/incoming-message-prompt.mjs +232 -0
- package/src/runtimes/_shared/runtime-base-instructions.mjs +34 -0
- package/src/runtimes/claude-code/index.mjs +48 -21
- package/src/runtimes/claude-code/session.mjs +7 -2
- package/src/runtimes/codex/index.mjs +64 -116
- package/src/runtimes/codex/session.mjs +12 -2
- package/src/runtimes/openclaw/index.mjs +30 -17
- package/src/runtimes/opencode/index.mjs +64 -42
- package/src/runtimes/opencode/session.mjs +14 -14
- package/src/runtimes/pi/index.mjs +64 -42
- package/src/runtimes/pi/session.mjs +8 -11
- package/ticlawk.mjs +30 -0
- package/src/runtimes/_shared/agent-handbook.mjs +0 -38
- package/src/runtimes/_shared/brand.mjs +0 -2
- package/src/runtimes/_shared/goal-step-prompt.mjs +0 -133
- package/src/runtimes/_shared/goal-task-protocol.mjs +0 -50
- package/src/runtimes/_shared/standing-prompt.mjs +0 -331
- package/src/runtimes/_shared/wake-prompt.mjs +0 -296
|
@@ -30,9 +30,8 @@ export function getConnectorWsUrl() {
|
|
|
30
30
|
return DEFAULT_CONNECTOR_WS_URL;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
// delivery lifecycle.
|
|
33
|
+
// Agent event writes must preserve per-agent order while still allowing
|
|
34
|
+
// different agents to proceed concurrently.
|
|
36
35
|
const agentEventQueues = new Map(); // agentId -> Promise
|
|
37
36
|
|
|
38
37
|
export class TiclawkUpdateRequiredError extends Error {
|
|
@@ -152,13 +151,13 @@ export async function updateChannel(id, updates) {
|
|
|
152
151
|
|
|
153
152
|
// ── Deliveries (replaces legacy message_jobs poll/ack) ──
|
|
154
153
|
|
|
155
|
-
export async function claimPendingDeliveries(hostId, limit = 5,
|
|
154
|
+
export async function claimPendingDeliveries(hostId, limit = 5, excludedAgentIds = []) {
|
|
156
155
|
const { data } = await apiFetch('/api/agent/deliveries/claim-pending', {
|
|
157
156
|
method: 'POST',
|
|
158
157
|
body: JSON.stringify(withTiclawkVersion({
|
|
159
158
|
runtime_host_id: hostId,
|
|
160
159
|
limit,
|
|
161
|
-
|
|
160
|
+
excluded_agent_ids: excludedAgentIds,
|
|
162
161
|
})),
|
|
163
162
|
});
|
|
164
163
|
return data || [];
|
|
@@ -189,7 +188,6 @@ export async function sendAgentMessage({
|
|
|
189
188
|
runtimeHostId,
|
|
190
189
|
visibility,
|
|
191
190
|
mediaAssetIds,
|
|
192
|
-
metadata,
|
|
193
191
|
}) {
|
|
194
192
|
const { data } = await apiFetch('/api/agent/messages/send', {
|
|
195
193
|
method: 'POST',
|
|
@@ -202,7 +200,6 @@ export async function sendAgentMessage({
|
|
|
202
200
|
runtime_host_id: runtimeHostId ?? null,
|
|
203
201
|
visibility: visibility || null,
|
|
204
202
|
media_asset_ids: Array.isArray(mediaAssetIds) && mediaAssetIds.length > 0 ? mediaAssetIds : undefined,
|
|
205
|
-
metadata: metadata ?? undefined,
|
|
206
203
|
}),
|
|
207
204
|
});
|
|
208
205
|
return data || null;
|
|
@@ -225,7 +222,7 @@ export async function readAgentMessages({
|
|
|
225
222
|
return data || [];
|
|
226
223
|
}
|
|
227
224
|
|
|
228
|
-
export async function createAgentTask({ actingAgentId, conversationId, text, title
|
|
225
|
+
export async function createAgentTask({ actingAgentId, conversationId, text, title }) {
|
|
229
226
|
return apiFetch('/api/agent/tasks/create', {
|
|
230
227
|
method: 'POST',
|
|
231
228
|
body: JSON.stringify({
|
|
@@ -233,7 +230,6 @@ export async function createAgentTask({ actingAgentId, conversationId, text, tit
|
|
|
233
230
|
conversation_id: conversationId,
|
|
234
231
|
text,
|
|
235
232
|
title: title ?? null,
|
|
236
|
-
assign_agent_id: assignAgentId ?? null,
|
|
237
233
|
}),
|
|
238
234
|
});
|
|
239
235
|
}
|
|
@@ -286,46 +282,6 @@ export async function updateAgentTask({ actingAgentId, taskId, status }) {
|
|
|
286
282
|
});
|
|
287
283
|
}
|
|
288
284
|
|
|
289
|
-
export async function reportGoalTransition({
|
|
290
|
-
actingAgentId, conversationId, transitionId, outcome, detail, currentTaskId,
|
|
291
|
-
}) {
|
|
292
|
-
return apiFetch('/api/agent/goal/report', {
|
|
293
|
-
method: 'POST',
|
|
294
|
-
body: JSON.stringify({
|
|
295
|
-
acting_as_agent_id: actingAgentId,
|
|
296
|
-
conversation_id: conversationId,
|
|
297
|
-
transition_id: transitionId,
|
|
298
|
-
outcome,
|
|
299
|
-
detail: detail ?? null,
|
|
300
|
-
current_task_id: currentTaskId ?? null,
|
|
301
|
-
}),
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
export async function listGoalApprovals({ actingAgentId, conversationId }) {
|
|
306
|
-
const params = new URLSearchParams();
|
|
307
|
-
params.set('acting_as_agent_id', actingAgentId);
|
|
308
|
-
params.set('conversation_id', conversationId);
|
|
309
|
-
const { data } = await apiFetch(`/api/agent/approval/list?${params}`);
|
|
310
|
-
return data || [];
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
export async function resolveGoalApproval({
|
|
314
|
-
actingAgentId, requestId, decision, originalText, confidence, sourceMessageId,
|
|
315
|
-
}) {
|
|
316
|
-
return apiFetch('/api/agent/approval/resolve', {
|
|
317
|
-
method: 'POST',
|
|
318
|
-
body: JSON.stringify({
|
|
319
|
-
acting_as_agent_id: actingAgentId,
|
|
320
|
-
request_id: requestId,
|
|
321
|
-
decision,
|
|
322
|
-
original_text: originalText ?? null,
|
|
323
|
-
confidence: confidence ?? null,
|
|
324
|
-
source_message_id: sourceMessageId ?? null,
|
|
325
|
-
}),
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
|
|
329
285
|
export async function listAgentTasks({ actingAgentId, conversationId }) {
|
|
330
286
|
const params = new URLSearchParams();
|
|
331
287
|
params.set('acting_as_agent_id', actingAgentId);
|
|
@@ -350,7 +306,7 @@ export async function getAgentServerInfo({ actingAgentId }) {
|
|
|
350
306
|
// ── Reminders ──
|
|
351
307
|
|
|
352
308
|
export async function scheduleAgentReminder({
|
|
353
|
-
actingAgentId, title, fireAt, anchorConversationId, anchorMessageId,
|
|
309
|
+
actingAgentId, title, fireAt, anchorConversationId, anchorMessageId,
|
|
354
310
|
}) {
|
|
355
311
|
return apiFetch('/api/agent/reminders', {
|
|
356
312
|
method: 'POST',
|
|
@@ -360,7 +316,6 @@ export async function scheduleAgentReminder({
|
|
|
360
316
|
fire_at: fireAt,
|
|
361
317
|
anchor_conversation_id: anchorConversationId,
|
|
362
318
|
anchor_message_id: anchorMessageId ?? null,
|
|
363
|
-
recurrence: recurrence ?? null,
|
|
364
319
|
}),
|
|
365
320
|
});
|
|
366
321
|
}
|
|
@@ -529,294 +484,63 @@ export async function removeAgentGroupMember({
|
|
|
529
484
|
);
|
|
530
485
|
}
|
|
531
486
|
|
|
532
|
-
// ── Workstreams (managed groups) ──
|
|
533
|
-
|
|
534
|
-
export async function createWorkstream({
|
|
535
|
-
actingAgentId, name, description, charter, memberAgentIds,
|
|
536
|
-
}) {
|
|
537
|
-
return apiFetch('/api/agent/workstreams', {
|
|
538
|
-
method: 'POST',
|
|
539
|
-
body: JSON.stringify({
|
|
540
|
-
acting_as_agent_id: actingAgentId,
|
|
541
|
-
name,
|
|
542
|
-
description: description ?? null,
|
|
543
|
-
charter: charter ?? null,
|
|
544
|
-
member_agent_ids: memberAgentIds || [],
|
|
545
|
-
}),
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
export async function deleteWorkstream({ actingAgentId, conversationId }) {
|
|
550
|
-
return apiFetch(
|
|
551
|
-
`/api/agent/workstreams/${encodeURIComponent(conversationId)}`,
|
|
552
|
-
{
|
|
553
|
-
method: 'DELETE',
|
|
554
|
-
body: JSON.stringify({ acting_as_agent_id: actingAgentId }),
|
|
555
|
-
},
|
|
556
|
-
);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
export async function listWorkstreams({ actingAgentId }) {
|
|
560
|
-
const params = new URLSearchParams();
|
|
561
|
-
params.set('acting_as_agent_id', actingAgentId);
|
|
562
|
-
const { data } = await apiFetch(`/api/agent/workstreams?${params}`);
|
|
563
|
-
return data || [];
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
// ── Agents ──
|
|
567
|
-
|
|
568
|
-
export async function listAgentSlots({ actingAgentId }) {
|
|
569
|
-
const params = new URLSearchParams();
|
|
570
|
-
params.set('acting_as_agent_id', actingAgentId);
|
|
571
|
-
const { data } = await apiFetch(`/api/agent/agents?${params}`);
|
|
572
|
-
return data || [];
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
export async function createAgentSlot({
|
|
576
|
-
actingAgentId, name, runtime, description, displayName, model,
|
|
577
|
-
}) {
|
|
578
|
-
return apiFetch('/api/agent/agents', {
|
|
579
|
-
method: 'POST',
|
|
580
|
-
body: JSON.stringify({
|
|
581
|
-
acting_as_agent_id: actingAgentId,
|
|
582
|
-
name,
|
|
583
|
-
runtime,
|
|
584
|
-
description: description ?? null,
|
|
585
|
-
display_name: displayName ?? null,
|
|
586
|
-
model: model ?? null,
|
|
587
|
-
}),
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
export async function archiveAgentSlot({ actingAgentId, agentId }) {
|
|
592
|
-
return apiFetch(
|
|
593
|
-
`/api/agent/agents/${encodeURIComponent(agentId)}`,
|
|
594
|
-
{
|
|
595
|
-
method: 'DELETE',
|
|
596
|
-
body: JSON.stringify({ acting_as_agent_id: actingAgentId }),
|
|
597
|
-
},
|
|
598
|
-
);
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// ── Services ──
|
|
602
|
-
|
|
603
|
-
export async function createService({
|
|
604
|
-
actingAgentId, name, description, contractSchema, endpointConfig,
|
|
605
|
-
}) {
|
|
606
|
-
return apiFetch('/api/agent/services', {
|
|
607
|
-
method: 'POST',
|
|
608
|
-
body: JSON.stringify({
|
|
609
|
-
acting_as_agent_id: actingAgentId,
|
|
610
|
-
name,
|
|
611
|
-
description: description ?? null,
|
|
612
|
-
contract_schema: contractSchema ?? null,
|
|
613
|
-
endpoint_config: endpointConfig,
|
|
614
|
-
}),
|
|
615
|
-
});
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
export async function updateService({ actingAgentId, serviceId, ...patch }) {
|
|
619
|
-
return apiFetch(
|
|
620
|
-
`/api/agent/services/${encodeURIComponent(serviceId)}`,
|
|
621
|
-
{
|
|
622
|
-
method: 'PATCH',
|
|
623
|
-
body: JSON.stringify({ acting_as_agent_id: actingAgentId, ...patch }),
|
|
624
|
-
},
|
|
625
|
-
);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
export async function deleteService({ actingAgentId, serviceId }) {
|
|
629
|
-
return apiFetch(
|
|
630
|
-
`/api/agent/services/${encodeURIComponent(serviceId)}`,
|
|
631
|
-
{
|
|
632
|
-
method: 'DELETE',
|
|
633
|
-
body: JSON.stringify({ acting_as_agent_id: actingAgentId }),
|
|
634
|
-
},
|
|
635
|
-
);
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
export async function listServices({ actingAgentId }) {
|
|
639
|
-
const params = new URLSearchParams();
|
|
640
|
-
params.set('acting_as_agent_id', actingAgentId);
|
|
641
|
-
const { data } = await apiFetch(`/api/agent/services?${params}`);
|
|
642
|
-
return data || [];
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
export async function getServiceInfo({ actingAgentId, name }) {
|
|
646
|
-
const params = new URLSearchParams();
|
|
647
|
-
params.set('acting_as_agent_id', actingAgentId);
|
|
648
|
-
return apiFetch(
|
|
649
|
-
`/api/agent/services/${encodeURIComponent(name)}/info?${params}`,
|
|
650
|
-
);
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
export async function callService({ actingAgentId, name, input }) {
|
|
654
|
-
return apiFetch(
|
|
655
|
-
`/api/agent/services/${encodeURIComponent(name)}/call`,
|
|
656
|
-
{
|
|
657
|
-
method: 'POST',
|
|
658
|
-
body: JSON.stringify({ acting_as_agent_id: actingAgentId, input }),
|
|
659
|
-
},
|
|
660
|
-
);
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
// ── Briefings ──
|
|
664
|
-
|
|
665
|
-
export async function getBriefing({actingAgentId, briefingId}) {
|
|
666
|
-
const params = new URLSearchParams();
|
|
667
|
-
params.set('acting_as_agent_id', actingAgentId);
|
|
668
|
-
return apiFetch(`/api/agent/briefings/${encodeURIComponent(briefingId)}?${params}`);
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
export async function publishBriefing({actingAgentId, bodyText, attachmentAssetId, currentConversationId, responseMode}) {
|
|
672
|
-
const body = { acting_as_agent_id: actingAgentId };
|
|
673
|
-
if (bodyText != null) body.body_text = bodyText;
|
|
674
|
-
if (attachmentAssetId != null) body.attachment_asset_id = attachmentAssetId;
|
|
675
|
-
if (currentConversationId != null) body.current_conversation_id = currentConversationId;
|
|
676
|
-
if (responseMode != null) body.response_mode = responseMode;
|
|
677
|
-
return apiFetch('/api/agent/briefings', {
|
|
678
|
-
method: 'POST',
|
|
679
|
-
body: JSON.stringify(body),
|
|
680
|
-
});
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
// ── Credentials (slot creation + daemon sync) ──
|
|
684
|
-
|
|
685
|
-
export async function fetchCredentials() {
|
|
686
|
-
return apiFetch('/api/agent/credentials', { method: 'GET' });
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
export async function requestCredential({
|
|
690
|
-
actingAgentId, name, description, workstreamId,
|
|
691
|
-
}) {
|
|
692
|
-
return apiFetch('/api/agent/credentials', {
|
|
693
|
-
method: 'POST',
|
|
694
|
-
body: JSON.stringify({
|
|
695
|
-
acting_as_agent_id: actingAgentId,
|
|
696
|
-
name,
|
|
697
|
-
description: description ?? null,
|
|
698
|
-
workstream_id: workstreamId ?? null,
|
|
699
|
-
}),
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
// ── Workstream dashboard ──
|
|
704
|
-
|
|
705
|
-
export async function setWorkstreamDashboard({
|
|
706
|
-
actingAgentId, conversationId, dataJson, htmlTemplate,
|
|
707
|
-
}) {
|
|
708
|
-
const body = { acting_as_agent_id: actingAgentId };
|
|
709
|
-
// Distinguish "omit" from "set to null" — only include keys the caller
|
|
710
|
-
// explicitly passed (including null clears the field).
|
|
711
|
-
if (dataJson !== undefined) body.data_json = dataJson;
|
|
712
|
-
if (htmlTemplate !== undefined) body.html_template = htmlTemplate;
|
|
713
|
-
return apiFetch(
|
|
714
|
-
`/api/agent/workstreams/${encodeURIComponent(conversationId)}/dashboard`,
|
|
715
|
-
{ method: 'POST', body: JSON.stringify(body) },
|
|
716
|
-
);
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
export async function getWorkstreamDashboard({ actingAgentId, conversationId }) {
|
|
720
|
-
const params = new URLSearchParams();
|
|
721
|
-
params.set('acting_as_agent_id', actingAgentId);
|
|
722
|
-
return apiFetch(
|
|
723
|
-
`/api/agent/workstreams/${encodeURIComponent(conversationId)}/dashboard?${params}`,
|
|
724
|
-
);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
// ── Workstream charter ──
|
|
728
|
-
|
|
729
|
-
export async function getWorkstreamCharter({ actingAgentId, conversationId }) {
|
|
730
|
-
const params = new URLSearchParams();
|
|
731
|
-
params.set('acting_as_agent_id', actingAgentId);
|
|
732
|
-
return apiFetch(
|
|
733
|
-
`/api/agent/workstreams/${encodeURIComponent(conversationId)}/charter?${params}`,
|
|
734
|
-
);
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
export async function setWorkstreamCharter({ actingAgentId, conversationId, charter }) {
|
|
738
|
-
return apiFetch(
|
|
739
|
-
`/api/agent/workstreams/${encodeURIComponent(conversationId)}/charter`,
|
|
740
|
-
{
|
|
741
|
-
method: 'POST',
|
|
742
|
-
body: JSON.stringify({
|
|
743
|
-
acting_as_agent_id: actingAgentId,
|
|
744
|
-
charter: charter ?? null,
|
|
745
|
-
}),
|
|
746
|
-
},
|
|
747
|
-
);
|
|
748
|
-
}
|
|
749
|
-
|
|
750
487
|
// ── Channel event pipe ──
|
|
751
488
|
|
|
752
489
|
export async function postEvent({ agent, agent_id, runtime_host_id, session_id, cwd, runtime_version, event, required = false }) {
|
|
753
490
|
const agentId = agent_id || null;
|
|
754
491
|
const queueKey = agentId || `${agent}:${session_id || ''}`;
|
|
492
|
+
const previous = agentEventQueues.get(queueKey) || Promise.resolve(null);
|
|
755
493
|
const eventName = event?.worker_event_name || event?.hook_event_name || event?.event_name || 'unknown';
|
|
756
494
|
const turnId = event?.turn_id || event?.reply_to_message_id || null;
|
|
757
495
|
const seq = event?.event_seq ?? null;
|
|
758
496
|
const deltaChars = typeof event?.delta === 'string' ? event.delta.length : null;
|
|
759
497
|
|
|
760
|
-
if (eventName === 'worker.message.delta') {
|
|
761
|
-
debugLog('events', 'delta.drop', {
|
|
762
|
-
agent,
|
|
763
|
-
agentId,
|
|
764
|
-
sessionId: shortId(session_id),
|
|
765
|
-
turnId: shortId(turnId),
|
|
766
|
-
deltaChars,
|
|
767
|
-
});
|
|
768
|
-
return null;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
const postOnce = async () => {
|
|
772
|
-
const startedAt = Date.now();
|
|
773
|
-
try {
|
|
774
|
-
const result = await apiFetch('/api/events', {
|
|
775
|
-
method: 'POST',
|
|
776
|
-
body: JSON.stringify({ agent, agent_id: agentId, runtime_host_id, session_id, cwd, runtime_version, event }),
|
|
777
|
-
timeout: 5000,
|
|
778
|
-
});
|
|
779
|
-
if (required && result?.matched === false) {
|
|
780
|
-
throw new Error(`event was not matched (${eventName})`);
|
|
781
|
-
}
|
|
782
|
-
debugLog('events', 'post.ok', {
|
|
783
|
-
agent,
|
|
784
|
-
agentId,
|
|
785
|
-
sessionId: shortId(session_id),
|
|
786
|
-
runtimeVersion: runtime_version ?? null,
|
|
787
|
-
turnId: shortId(turnId),
|
|
788
|
-
eventName,
|
|
789
|
-
seq,
|
|
790
|
-
durationMs: Date.now() - startedAt,
|
|
791
|
-
});
|
|
792
|
-
return result;
|
|
793
|
-
} catch (err) {
|
|
794
|
-
debugError('events', 'post.failed', {
|
|
795
|
-
agent,
|
|
796
|
-
agentId,
|
|
797
|
-
sessionId: shortId(session_id),
|
|
798
|
-
runtimeVersion: runtime_version ?? null,
|
|
799
|
-
turnId: shortId(turnId),
|
|
800
|
-
eventName,
|
|
801
|
-
seq,
|
|
802
|
-
durationMs: Date.now() - startedAt,
|
|
803
|
-
error: err?.message || 'unknown error',
|
|
804
|
-
});
|
|
805
|
-
if (required) {
|
|
806
|
-
throw err;
|
|
807
|
-
}
|
|
808
|
-
return null;
|
|
809
|
-
}
|
|
810
|
-
};
|
|
811
|
-
|
|
812
|
-
if (eventName === 'worker.turn.complete' || eventName === 'worker.turn.error') {
|
|
813
|
-
return postOnce();
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
const previous = agentEventQueues.get(queueKey) || Promise.resolve(null);
|
|
817
498
|
const queued = previous
|
|
818
499
|
.catch(() => null)
|
|
819
|
-
.then(
|
|
500
|
+
.then(async () => {
|
|
501
|
+
const startedAt = Date.now();
|
|
502
|
+
try {
|
|
503
|
+
const result = await apiFetch('/api/events', {
|
|
504
|
+
method: 'POST',
|
|
505
|
+
body: JSON.stringify({ agent, agent_id: agentId, runtime_host_id, session_id, cwd, runtime_version, event }),
|
|
506
|
+
timeout: 5000,
|
|
507
|
+
});
|
|
508
|
+
if (required && result?.matched === false) {
|
|
509
|
+
throw new Error(`event was not matched (${eventName})`);
|
|
510
|
+
}
|
|
511
|
+
debugLog('events', 'post.ok', {
|
|
512
|
+
agent,
|
|
513
|
+
agentId,
|
|
514
|
+
sessionId: shortId(session_id),
|
|
515
|
+
runtimeVersion: runtime_version ?? null,
|
|
516
|
+
turnId: shortId(turnId),
|
|
517
|
+
eventName,
|
|
518
|
+
seq,
|
|
519
|
+
deltaChars,
|
|
520
|
+
durationMs: Date.now() - startedAt,
|
|
521
|
+
});
|
|
522
|
+
return result;
|
|
523
|
+
} catch (err) {
|
|
524
|
+
debugError('events', 'post.failed', {
|
|
525
|
+
agent,
|
|
526
|
+
agentId,
|
|
527
|
+
sessionId: shortId(session_id),
|
|
528
|
+
runtimeVersion: runtime_version ?? null,
|
|
529
|
+
turnId: shortId(turnId),
|
|
530
|
+
eventName,
|
|
531
|
+
seq,
|
|
532
|
+
deltaChars,
|
|
533
|
+
durationMs: Date.now() - startedAt,
|
|
534
|
+
error: err?.message || 'unknown error',
|
|
535
|
+
});
|
|
536
|
+
if (required) {
|
|
537
|
+
throw err;
|
|
538
|
+
}
|
|
539
|
+
// Best-effort by default. Callers that need a hard failure set
|
|
540
|
+
// `required: true` (used for the final reply path).
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
});
|
|
820
544
|
|
|
821
545
|
agentEventQueues.set(queueKey, queued);
|
|
822
546
|
queued.finally(() => {
|
|
@@ -6,20 +6,7 @@
|
|
|
6
6
|
* using the connector-specific env name.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { AF_CONFIG_PATH,
|
|
10
|
-
|
|
11
|
-
export const TICLAWK_CREDENTIAL_NAMES = 'TICLAWK_CREDENTIAL_NAMES';
|
|
12
|
-
|
|
13
|
-
function isRuntimeCredentialName(value) {
|
|
14
|
-
return /^[A-Z][A-Z0-9_]*$/.test(String(value || '').trim());
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function parseCredentialNames(value) {
|
|
18
|
-
return String(value || '')
|
|
19
|
-
.split(',')
|
|
20
|
-
.map((name) => name.trim())
|
|
21
|
-
.filter(isRuntimeCredentialName);
|
|
22
|
-
}
|
|
9
|
+
import { AF_CONFIG_PATH, persistConfig, TICLAWK_CONNECTOR_API_KEY } from '../../core/config.mjs';
|
|
23
10
|
|
|
24
11
|
export function persistApiCredential(apiKey) {
|
|
25
12
|
if (!apiKey || !apiKey.startsWith('tk_')) return;
|
|
@@ -32,30 +19,3 @@ export function persistApiCredential(apiKey) {
|
|
|
32
19
|
delete process.env.TICLAWK_SETUP_CODE;
|
|
33
20
|
console.log(`[connect] saved ${TICLAWK_CONNECTOR_API_KEY} to ${AF_CONFIG_PATH}`);
|
|
34
21
|
}
|
|
35
|
-
|
|
36
|
-
export function persistRuntimeCredentials(credentials = []) {
|
|
37
|
-
const current = loadPersistentConfig();
|
|
38
|
-
const previousNames = new Set(parseCredentialNames(current[TICLAWK_CREDENTIAL_NAMES]));
|
|
39
|
-
const nextNames = [];
|
|
40
|
-
const updates = {};
|
|
41
|
-
|
|
42
|
-
for (const credential of Array.isArray(credentials) ? credentials : []) {
|
|
43
|
-
const name = String(credential?.name || '').trim();
|
|
44
|
-
const value = typeof credential?.value === 'string' ? credential.value : '';
|
|
45
|
-
if (!isRuntimeCredentialName(name) || !value) continue;
|
|
46
|
-
updates[name] = value;
|
|
47
|
-
nextNames.push(name);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const nextNameSet = new Set(nextNames);
|
|
51
|
-
for (const name of previousNames) {
|
|
52
|
-
if (!nextNameSet.has(name)) updates[name] = '';
|
|
53
|
-
}
|
|
54
|
-
updates[TICLAWK_CREDENTIAL_NAMES] = nextNames.join(',');
|
|
55
|
-
|
|
56
|
-
persistConfig(updates);
|
|
57
|
-
return {
|
|
58
|
-
saved: nextNames.length,
|
|
59
|
-
removed: [...previousNames].filter((name) => !nextNameSet.has(name)).length,
|
|
60
|
-
};
|
|
61
|
-
}
|