@pingagent/sdk 0.1.19 → 0.1.20
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/dist/chunk-M6XDTSQA.js +8819 -0
- package/dist/index.d.ts +206 -5
- package/dist/index.js +17 -1
- package/dist/web-server.js +211 -10
- package/package.json +3 -3
package/dist/web-server.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ContactManager,
|
|
5
5
|
HumanDeliveryBindingManager,
|
|
6
6
|
LocalStore,
|
|
7
|
+
NotificationDeliveryAttemptManager,
|
|
7
8
|
NotificationIntentManager,
|
|
8
9
|
OpenClawExecutionAdapter,
|
|
9
10
|
OperatorSeenStateManager,
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
SessionManager,
|
|
12
13
|
TrustPolicyAuditManager,
|
|
13
14
|
TrustRecommendationManager,
|
|
15
|
+
VerifiedDeliveryTargetManager,
|
|
14
16
|
buildActionContract,
|
|
15
17
|
buildActionInboxSummary,
|
|
16
18
|
buildDeliveryTimeline,
|
|
@@ -25,11 +27,16 @@ import {
|
|
|
25
27
|
getSessionBindingAlertsFilePath,
|
|
26
28
|
getSessionMapFilePath,
|
|
27
29
|
getTrustRecommendationActionLabel,
|
|
30
|
+
importBindingCandidates,
|
|
31
|
+
listImportableBindingCandidates,
|
|
28
32
|
listPendingDecisionViews,
|
|
29
33
|
listRecentBindingsForSession,
|
|
30
34
|
listRuntimeAdapterDescriptors,
|
|
31
35
|
loadIdentity,
|
|
32
36
|
normalizeTrustPolicyDoc,
|
|
37
|
+
normalizeVerifiedDeliveryTargetInput,
|
|
38
|
+
normalizeVerifiedDeliveryTargetUpdateInput,
|
|
39
|
+
promoteBindingToVerifiedTarget,
|
|
33
40
|
readCurrentActiveSessionKey,
|
|
34
41
|
readIngressRuntimeStatus,
|
|
35
42
|
readSessionBindingAlerts,
|
|
@@ -43,7 +50,7 @@ import {
|
|
|
43
50
|
switchTransportPreference,
|
|
44
51
|
updateStoredToken,
|
|
45
52
|
upsertTrustPolicyRecommendation
|
|
46
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-M6XDTSQA.js";
|
|
47
54
|
|
|
48
55
|
// src/web-server.ts
|
|
49
56
|
import * as fs from "fs";
|
|
@@ -555,7 +562,9 @@ function getHostPanelHtml() {
|
|
|
555
562
|
return '<div class="empty">' + esc(emptyLabel || 'No notification intents yet.') + '</div>';
|
|
556
563
|
}
|
|
557
564
|
return intents.map(function (intent) {
|
|
558
|
-
const bindingLabel = intent.
|
|
565
|
+
const bindingLabel = intent.resolved_target_id
|
|
566
|
+
? ('target=' + intent.resolved_target_id)
|
|
567
|
+
: (intent.resolved_binding_id ? ('binding=' + intent.resolved_binding_id) : 'binding=(unresolved)');
|
|
559
568
|
const ackLabel = intent.acknowledged_at
|
|
560
569
|
? (' \xB7 ack=' + fmtTs(intent.acknowledged_at))
|
|
561
570
|
: '';
|
|
@@ -679,6 +688,63 @@ function getHostPanelHtml() {
|
|
|
679
688
|
}).join('');
|
|
680
689
|
}
|
|
681
690
|
|
|
691
|
+
function renderVerifiedTargets(targets) {
|
|
692
|
+
if (!Array.isArray(targets) || !targets.length) {
|
|
693
|
+
return '<div class="empty">No verified explicit delivery targets yet. Promote a filtered binding candidate or create one from MCP to make notifications reliable.</div>';
|
|
694
|
+
}
|
|
695
|
+
return targets.map(function (target) {
|
|
696
|
+
const actions = [];
|
|
697
|
+
if (target.status !== 'disabled') {
|
|
698
|
+
actions.push('<button class="secondary-btn human-delivery-action-btn" data-action="disable_verified_target" data-target-id="' + esc(target.id) + '">Disable</button>');
|
|
699
|
+
}
|
|
700
|
+
if (target.status === 'failing') {
|
|
701
|
+
actions.push('<button class="secondary-btn human-delivery-action-btn" data-action="retest_verified_target" data-target-id="' + esc(target.id) + '">Retest</button>');
|
|
702
|
+
}
|
|
703
|
+
if (target.scope_type !== 'workspace_default' && target.route_kind === 'group') {
|
|
704
|
+
actions.push('<button class="secondary-btn human-delivery-action-btn" data-action="set_workspace_default_target" data-target-id="' + esc(target.id) + '">Use As Group Fallback</button>');
|
|
705
|
+
}
|
|
706
|
+
return '<div class="audit-row"><div class="top"><strong>' + esc(target.channel + ' -> ' + target.to_target) + '</strong>' +
|
|
707
|
+
'<span class="badge">' + esc(target.status || 'active') + '</span></div>' +
|
|
708
|
+
'<div class="muted small">' + esc(target.scope_type || 'owner') + ':' + esc(target.scope_key || '(none)') + ' \xB7 route=' + esc(target.route_kind || 'dm') + ' \xB7 priority=' + esc(target.priority || 0) + '</div>' +
|
|
709
|
+
'<div class="muted small" style="margin-top:8px">account=' + esc(target.account_id || '(none)') + ' \xB7 thread=' + esc(target.thread_id || '(none)') + '</div>' +
|
|
710
|
+
(target.last_error ? '<div class="muted small" style="margin-top:8px;color:#fecaca">' + esc(target.last_error) + '</div>' : '') +
|
|
711
|
+
(actions.length ? '<div class="row-actions" style="margin-top:10px">' + actions.join('') + '</div>' : '') +
|
|
712
|
+
'</div>';
|
|
713
|
+
}).join('');
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function renderImportableBindingCandidates(candidates) {
|
|
717
|
+
if (!Array.isArray(candidates) || !candidates.length) {
|
|
718
|
+
return '<div class="empty">No importable binding candidates right now.</div>';
|
|
719
|
+
}
|
|
720
|
+
return candidates.map(function (candidate) {
|
|
721
|
+
const actions = candidate.already_verified_target_id
|
|
722
|
+
? []
|
|
723
|
+
: ['<button class="secondary-btn human-delivery-action-btn" data-action="promote_binding_to_verified_target" data-binding-id="' + esc(candidate.binding_id) + '" data-scope-type="' + esc(candidate.scope_type) + '" data-scope-key="' + esc(candidate.scope_key) + '" data-route-kind="' + esc(candidate.route_kind) + '">Promote</button>'];
|
|
724
|
+
return '<div class="audit-row"><div class="top"><strong>' + esc(candidate.channel + ' -> ' + candidate.to_target) + '</strong>' +
|
|
725
|
+
'<span class="badge">' + esc(candidate.route_kind || 'dm') + '</span></div>' +
|
|
726
|
+
'<div class="muted small">' + esc(candidate.scope_type || 'owner') + ':' + esc(candidate.scope_key || '(none)') + ' \xB7 binding=' + esc(candidate.binding_id) + '</div>' +
|
|
727
|
+
(candidate.already_verified_target_id
|
|
728
|
+
? '<div class="muted small" style="margin-top:8px">Already promoted as verified target #' + esc(candidate.already_verified_target_id) + '.</div>'
|
|
729
|
+
: '') +
|
|
730
|
+
(actions.length ? '<div class="row-actions" style="margin-top:10px">' + actions.join('') + '</div>' : '') +
|
|
731
|
+
'</div>';
|
|
732
|
+
}).join('');
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
function renderDeliveryAttempts(attempts) {
|
|
736
|
+
if (!Array.isArray(attempts) || !attempts.length) {
|
|
737
|
+
return '<div class="empty">No verified delivery attempts yet.</div>';
|
|
738
|
+
}
|
|
739
|
+
return attempts.map(function (attempt) {
|
|
740
|
+
return '<div class="audit-row"><div class="top"><strong>Intent #' + esc(attempt.intent_id) + ' -> Target #' + esc(attempt.target_id) + '</strong>' +
|
|
741
|
+
'<span class="badge">' + esc(attempt.status || 'pending') + '</span></div>' +
|
|
742
|
+
'<div class="muted small">attempt=' + esc(attempt.attempt_no || 0) + ' \xB7 updated=' + esc(fmtTs(attempt.updated_at || attempt.created_at)) + '</div>' +
|
|
743
|
+
(attempt.error_message ? '<div class="muted small" style="margin-top:8px;color:#fecaca">' + esc(attempt.error_message) + '</div>' : '') +
|
|
744
|
+
'</div>';
|
|
745
|
+
}).join('');
|
|
746
|
+
}
|
|
747
|
+
|
|
682
748
|
function renderHumanDeliveryCapabilities(humanDelivery) {
|
|
683
749
|
const capabilities = Array.isArray(humanDelivery && humanDelivery.channel_capabilities) ? humanDelivery.channel_capabilities : [];
|
|
684
750
|
if (!capabilities.length) {
|
|
@@ -712,9 +778,17 @@ function getHostPanelHtml() {
|
|
|
712
778
|
if (!action) return;
|
|
713
779
|
const intentId = btn.getAttribute('data-intent-id');
|
|
714
780
|
const bindingId = btn.getAttribute('data-binding-id');
|
|
781
|
+
const targetId = btn.getAttribute('data-target-id');
|
|
782
|
+
const scopeType = btn.getAttribute('data-scope-type');
|
|
783
|
+
const scopeKey = btn.getAttribute('data-scope-key');
|
|
784
|
+
const routeKind = btn.getAttribute('data-route-kind');
|
|
715
785
|
await runHumanDeliveryAction(action, {
|
|
716
786
|
intent_id: intentId ? Number(intentId) : undefined,
|
|
717
787
|
binding_id: bindingId ? Number(bindingId) : undefined,
|
|
788
|
+
target_id: targetId ? Number(targetId) : undefined,
|
|
789
|
+
scope_type: scopeType || undefined,
|
|
790
|
+
scope_key: scopeKey || undefined,
|
|
791
|
+
route_kind: routeKind || undefined,
|
|
718
792
|
});
|
|
719
793
|
await refreshAll();
|
|
720
794
|
if (state.selectedSessionKey) await loadSession(state.selectedSessionKey);
|
|
@@ -1036,7 +1110,7 @@ function getHostPanelHtml() {
|
|
|
1036
1110
|
const failedIntents = data && Array.isArray(data.notificationIntentsFailed) ? data.notificationIntentsFailed : [];
|
|
1037
1111
|
const humanDelivery = data && data.humanDelivery ? data.humanDelivery : null;
|
|
1038
1112
|
const openclawAdapter = data && data.openclawAdapter ? data.openclawAdapter : null;
|
|
1039
|
-
const
|
|
1113
|
+
const intentBasedHumanDelivery = !!(humanDelivery && (humanDelivery.mode === 'bound_channel_reply' || humanDelivery.mode === 'verified_explicit_notify'));
|
|
1040
1114
|
document.getElementById('decisionInboxSummary').textContent =
|
|
1041
1115
|
'total=' + (actionInbox.total || 0) +
|
|
1042
1116
|
' \xB7 approvals=' + (actionInbox.pending_approval || 0) +
|
|
@@ -1048,12 +1122,12 @@ function getHostPanelHtml() {
|
|
|
1048
1122
|
document.getElementById('decisionInboxList').innerHTML = renderActionInboxItems(actionInbox.items);
|
|
1049
1123
|
|
|
1050
1124
|
const combinedOutbox = pendingOutbox.concat(failedOutbox);
|
|
1051
|
-
document.getElementById('projectionOutboxSummary').textContent =
|
|
1052
|
-
? ('bound reply mode \xB7 pending=' + pendingIntents.length + ' \xB7 unresolved=' + unresolvedIntents.length + ' \xB7 failed=' + failedIntents.length)
|
|
1125
|
+
document.getElementById('projectionOutboxSummary').textContent = intentBasedHumanDelivery
|
|
1126
|
+
? ((humanDelivery && humanDelivery.mode === 'verified_explicit_notify' ? 'verified explicit notify' : 'bound reply mode') + ' \xB7 pending=' + pendingIntents.length + ' \xB7 unresolved=' + unresolvedIntents.length + ' \xB7 failed=' + failedIntents.length)
|
|
1053
1127
|
: (combinedOutbox.length
|
|
1054
1128
|
? 'Legacy projection outbox remains visible for audit and compatibility. Failed rows stay visible until delivery recovers.'
|
|
1055
1129
|
: 'No legacy projection-outbox rows need attention.');
|
|
1056
|
-
document.getElementById('projectionOutboxList').innerHTML =
|
|
1130
|
+
document.getElementById('projectionOutboxList').innerHTML = intentBasedHumanDelivery
|
|
1057
1131
|
? renderHumanDeliveryIntents(
|
|
1058
1132
|
pendingIntents.concat(unresolvedIntents).concat(failedIntents),
|
|
1059
1133
|
'No pending, unresolved, or failed human-delivery intents.',
|
|
@@ -1195,7 +1269,7 @@ function getHostPanelHtml() {
|
|
|
1195
1269
|
{ label: 'Tasks', value: overview.tasksTotal, sub: 'recent local task threads' },
|
|
1196
1270
|
{ label: 'Audit', value: overview.auditSummary.total_events, sub: 'policy / runtime audit events' },
|
|
1197
1271
|
{ label: 'Action Inbox', value: actionInbox.total || 0, sub: 'high_risk=' + (actionInbox.high_risk || 0) + ' timed_out=' + (actionInbox.timed_out || 0) },
|
|
1198
|
-
{ label: 'External Delivery', value: humanDelivery ? ((humanDelivery.pending_intents || 0) + '/' + (humanDelivery.active_bindings || 0)) : '-', sub: humanDelivery ? ('mode=' + (humanDelivery.mode || 'projection_outbox') + ' unresolved=' + (humanDelivery.unresolved_intents || 0) + ' failed=' + (humanDelivery.failed_intents || 0)) : 'binding-based callback delivery state' },
|
|
1272
|
+
{ label: 'External Delivery', value: humanDelivery ? ((humanDelivery.pending_intents || 0) + '/' + (humanDelivery.active_verified_targets || humanDelivery.active_bindings || 0)) : '-', sub: humanDelivery ? ('mode=' + (humanDelivery.mode || 'projection_outbox') + ' unresolved=' + (humanDelivery.unresolved_intents || 0) + ' failed=' + (humanDelivery.failed_intents || 0)) : 'binding-based callback delivery state' },
|
|
1199
1273
|
{ label: 'Recommendations', value: overview.recommendationSummary ? overview.recommendationSummary.total : overview.recommendations.length, sub: overview.recommendationSummary ? JSON.stringify(overview.recommendationSummary.by_status || {}) : 'learned policy suggestions' },
|
|
1200
1274
|
{ label: 'Public Link', value: overview.publicSelf && overview.publicSelf.public_url ? 'ready' : 'disabled', sub: overview.publicSelf && overview.publicSelf.public_url ? overview.publicSelf.public_url : 'create a hosted shareable profile link' },
|
|
1201
1275
|
];
|
|
@@ -1204,7 +1278,17 @@ function getHostPanelHtml() {
|
|
|
1204
1278
|
}).join('');
|
|
1205
1279
|
document.getElementById('taskList').innerHTML = '<div class="task-row"><div class="top"><strong>External Callback Channels</strong><span class="badge">' + esc((humanDelivery && humanDelivery.supported_channels ? humanDelivery.supported_channels.length : 0) + '/' + (humanDelivery && humanDelivery.channel_capabilities ? humanDelivery.channel_capabilities.length : 0)) + '</span></div>' +
|
|
1206
1280
|
'<div class="muted small">Capabilities and canary state for explicit external callback delivery.</div>' +
|
|
1207
|
-
'<div class="audit-list" style="margin-top:8px">' + renderHumanDeliveryCapabilities(humanDelivery) + '</div></div>'
|
|
1281
|
+
'<div class="audit-list" style="margin-top:8px">' + renderHumanDeliveryCapabilities(humanDelivery) + '</div></div>' +
|
|
1282
|
+
'<div class="task-row"><div class="top"><strong>Verified Explicit Targets</strong><span class="badge">' + esc(humanDelivery && humanDelivery.active_verified_targets != null ? humanDelivery.active_verified_targets : 0) + '</span></div>' +
|
|
1283
|
+
'<div class="muted small">Stable source of truth for reliable human notifications. DM-first, then group fallback.</div>' +
|
|
1284
|
+
'<div class="audit-list" style="margin-top:8px">' + renderVerifiedTargets(humanDelivery && humanDelivery.recent_verified_targets) + '</div></div>' +
|
|
1285
|
+
'<div class="task-row"><div class="top"><strong>Importable Binding Candidates</strong><span class="badge">' + esc(humanDelivery && humanDelivery.importable_binding_candidates ? humanDelivery.importable_binding_candidates.length : 0) + '</span></div>' +
|
|
1286
|
+
'<div class="muted small">Candidate addresses learned from real conversations. Promote only the targets you trust.</div>' +
|
|
1287
|
+
'<div class="row-actions" style="margin-top:10px"><button class="secondary-btn human-delivery-action-btn" data-action="import_binding_candidates">Import Candidates As Disabled</button></div>' +
|
|
1288
|
+
'<div class="audit-list" style="margin-top:8px">' + renderImportableBindingCandidates(humanDelivery && humanDelivery.importable_binding_candidates) + '</div></div>' +
|
|
1289
|
+
'<div class="task-row"><div class="top"><strong>Recent Delivery Attempts</strong><span class="badge">' + esc(humanDelivery && humanDelivery.recent_delivery_attempts ? humanDelivery.recent_delivery_attempts.length : 0) + '</span></div>' +
|
|
1290
|
+
'<div class="muted small">Audit trail for explicit notification attempts and fallback behavior.</div>' +
|
|
1291
|
+
'<div class="audit-list" style="margin-top:8px">' + renderDeliveryAttempts(humanDelivery && humanDelivery.recent_delivery_attempts) + '</div></div>';
|
|
1208
1292
|
|
|
1209
1293
|
const toggleUnreadBtn = document.getElementById('toggleUnreadBtn');
|
|
1210
1294
|
if (toggleUnreadBtn) toggleUnreadBtn.textContent = 'Unread only: ' + (state.showUnreadOnly ? 'on' : 'off');
|
|
@@ -1387,6 +1471,9 @@ conversation=' + result.conversation_id));
|
|
|
1387
1471
|
const projectionOutbox = Array.isArray(detail.projectionOutbox) ? detail.projectionOutbox : [];
|
|
1388
1472
|
const recentBindings = Array.isArray(detail.recentBindings) ? detail.recentBindings : [];
|
|
1389
1473
|
const recentNotificationIntents = Array.isArray(detail.recentNotificationIntents) ? detail.recentNotificationIntents : [];
|
|
1474
|
+
const recentVerifiedTargets = Array.isArray(detail.recentVerifiedTargets) ? detail.recentVerifiedTargets : [];
|
|
1475
|
+
const recentDeliveryAttempts = Array.isArray(detail.recentDeliveryAttempts) ? detail.recentDeliveryAttempts : [];
|
|
1476
|
+
const importableBindingCandidates = Array.isArray(detail.importableBindingCandidates) ? detail.importableBindingCandidates : [];
|
|
1390
1477
|
const sinceLastSeen = detail.sinceLastSeen || null;
|
|
1391
1478
|
const deliveryTimeline = Array.isArray(detail.deliveryTimeline) ? detail.deliveryTimeline : [];
|
|
1392
1479
|
const projectionPreview = detail.projectionPreview || null;
|
|
@@ -1588,6 +1675,27 @@ conversation=' + result.conversation_id));
|
|
|
1588
1675
|
'</div></div>' +
|
|
1589
1676
|
'</div>';
|
|
1590
1677
|
|
|
1678
|
+
el.innerHTML +=
|
|
1679
|
+
'<div class="grid two-col" style="margin-top:16px">' +
|
|
1680
|
+
'<div><div class="label">Verified Explicit Targets</div><div class="audit-list" style="margin-top:8px">' +
|
|
1681
|
+
renderVerifiedTargets(recentVerifiedTargets) +
|
|
1682
|
+
'</div></div>' +
|
|
1683
|
+
'<div><div class="label">Importable Binding Candidates</div><div class="audit-list" style="margin-top:8px">' +
|
|
1684
|
+
renderImportableBindingCandidates(importableBindingCandidates) +
|
|
1685
|
+
'</div></div>' +
|
|
1686
|
+
'</div>';
|
|
1687
|
+
|
|
1688
|
+
el.innerHTML +=
|
|
1689
|
+
'<div class="grid two-col" style="margin-top:16px">' +
|
|
1690
|
+
'<div><div class="label">Recent Delivery Attempts</div><div class="audit-list" style="margin-top:8px">' +
|
|
1691
|
+
renderDeliveryAttempts(recentDeliveryAttempts) +
|
|
1692
|
+
'</div></div>' +
|
|
1693
|
+
'<div><div class="label">Delivery Mode</div><div class="audit-list" style="margin-top:8px">' +
|
|
1694
|
+
'<div class="audit-row"><div class="top"><strong>Human delivery</strong><span class="badge">' + esc(humanDelivery && humanDelivery.mode ? humanDelivery.mode : 'projection_outbox') + '</span></div>' +
|
|
1695
|
+
'<div class="muted small">verified=' + esc(humanDelivery && humanDelivery.active_verified_targets != null ? humanDelivery.active_verified_targets : 0) + ' \xB7 unresolved=' + esc(humanDelivery && humanDelivery.unresolved_intents != null ? humanDelivery.unresolved_intents : 0) + ' \xB7 failed=' + esc(humanDelivery && humanDelivery.failed_intents != null ? humanDelivery.failed_intents : 0) + '</div></div>' +
|
|
1696
|
+
'</div></div>' +
|
|
1697
|
+
'</div>';
|
|
1698
|
+
|
|
1591
1699
|
el.querySelectorAll('.approve-session-btn').forEach(function (btn) {
|
|
1592
1700
|
btn.addEventListener('click', async function () {
|
|
1593
1701
|
const sessionKey = btn.getAttribute('data-session');
|
|
@@ -2590,11 +2698,16 @@ async function buildRuntimeOverviewPayload(ctx) {
|
|
|
2590
2698
|
decisionViews = listPendingDecisionViews(decisionStore, 100);
|
|
2591
2699
|
const bindingManager = new HumanDeliveryBindingManager(decisionStore);
|
|
2592
2700
|
const intentManager = new NotificationIntentManager(decisionStore);
|
|
2701
|
+
const targetManager = new VerifiedDeliveryTargetManager(decisionStore);
|
|
2702
|
+
const attemptManager = new NotificationDeliveryAttemptManager(decisionStore);
|
|
2593
2703
|
humanDeliveryDetails = {
|
|
2594
2704
|
unresolved_intents: intentManager.listByStatus("unresolved", 20),
|
|
2595
2705
|
failed_intents: intentManager.listByStatus("failed", 20),
|
|
2596
2706
|
acknowledged_intents: intentManager.listByStatus("acknowledged", 20),
|
|
2597
|
-
recent_bindings: bindingManager.listRecent(20)
|
|
2707
|
+
recent_bindings: bindingManager.listRecent(20),
|
|
2708
|
+
recent_verified_targets: targetManager.listRecent(20),
|
|
2709
|
+
recent_delivery_attempts: attemptManager.listRecent(20),
|
|
2710
|
+
importable_binding_candidates: listImportableBindingCandidates(decisionStore, 20)
|
|
2598
2711
|
};
|
|
2599
2712
|
} finally {
|
|
2600
2713
|
decisionStore.close();
|
|
@@ -2727,6 +2840,9 @@ async function buildSessionOverviewPayload(ctx, sessionKey) {
|
|
|
2727
2840
|
let projectionOutbox = [];
|
|
2728
2841
|
let notificationIntents = [];
|
|
2729
2842
|
let recentBindings = [];
|
|
2843
|
+
let recentVerifiedTargets = [];
|
|
2844
|
+
let recentDeliveryAttempts = [];
|
|
2845
|
+
let importableBindingCandidates = [];
|
|
2730
2846
|
let sinceLastSeen = null;
|
|
2731
2847
|
let deliveryTimeline = [];
|
|
2732
2848
|
let projectionPreview = null;
|
|
@@ -2738,6 +2854,9 @@ async function buildSessionOverviewPayload(ctx, sessionKey) {
|
|
|
2738
2854
|
projectionOutbox = new CollaborationProjectionOutboxManager(outboxStore).listBySession(session.session_key, 20);
|
|
2739
2855
|
notificationIntents = new NotificationIntentManager(outboxStore).listBySession(session.session_key, 20);
|
|
2740
2856
|
recentBindings = listRecentBindingsForSession(outboxStore, session.session_key, session.conversation_id, 20);
|
|
2857
|
+
recentVerifiedTargets = new VerifiedDeliveryTargetManager(outboxStore).listRecent(20);
|
|
2858
|
+
recentDeliveryAttempts = new NotificationDeliveryAttemptManager(outboxStore).listRecent(20);
|
|
2859
|
+
importableBindingCandidates = listImportableBindingCandidates(outboxStore, 20);
|
|
2741
2860
|
sinceLastSeen = summarizeSinceLastSeen(outboxStore, {
|
|
2742
2861
|
operator_id: "host_panel",
|
|
2743
2862
|
scope_type: "session",
|
|
@@ -2789,6 +2908,9 @@ async function buildSessionOverviewPayload(ctx, sessionKey) {
|
|
|
2789
2908
|
collaborationProjection: policy.collaboration_projection,
|
|
2790
2909
|
projectionOutbox,
|
|
2791
2910
|
recentBindings,
|
|
2911
|
+
recentVerifiedTargets,
|
|
2912
|
+
recentDeliveryAttempts,
|
|
2913
|
+
importableBindingCandidates,
|
|
2792
2914
|
recentNotificationIntents: notificationIntents,
|
|
2793
2915
|
sinceLastSeen,
|
|
2794
2916
|
deliveryTimeline,
|
|
@@ -2890,10 +3012,15 @@ async function handleApi(pathname, req, ctx) {
|
|
|
2890
3012
|
try {
|
|
2891
3013
|
const bindingManager = new HumanDeliveryBindingManager(store);
|
|
2892
3014
|
const intentManager = new NotificationIntentManager(store);
|
|
3015
|
+
const targetManager = new VerifiedDeliveryTargetManager(store);
|
|
3016
|
+
const attemptManager = new NotificationDeliveryAttemptManager(store);
|
|
2893
3017
|
if (req.method === "GET") {
|
|
2894
3018
|
return {
|
|
2895
3019
|
humanDelivery: summarizeHumanDelivery(store, 20),
|
|
2896
3020
|
recentBindings: bindingManager.listRecent(50),
|
|
3021
|
+
recentVerifiedTargets: targetManager.listRecent(50),
|
|
3022
|
+
recentDeliveryAttempts: attemptManager.listRecent(50),
|
|
3023
|
+
importableBindingCandidates: listImportableBindingCandidates(store, 50),
|
|
2897
3024
|
unresolvedIntents: intentManager.listByStatus("unresolved", 50),
|
|
2898
3025
|
failedIntents: intentManager.listByStatus("failed", 50),
|
|
2899
3026
|
acknowledgedIntents: intentManager.listByStatus("acknowledged", 50)
|
|
@@ -2904,8 +3031,11 @@ async function handleApi(pathname, req, ctx) {
|
|
|
2904
3031
|
const action = String(body?.action ?? "").trim();
|
|
2905
3032
|
const intentId = Number(body?.intent_id);
|
|
2906
3033
|
const bindingId = Number(body?.binding_id);
|
|
3034
|
+
const targetId = Number(body?.target_id);
|
|
2907
3035
|
let intent = null;
|
|
2908
3036
|
let binding = null;
|
|
3037
|
+
let target = null;
|
|
3038
|
+
let importedTargets = [];
|
|
2909
3039
|
if (action === "retry_intent") {
|
|
2910
3040
|
if (!Number.isInteger(intentId) || intentId <= 0) throw new Error("intent_id is required");
|
|
2911
3041
|
intent = intentManager.markPending(intentId, { clear_error: true, clear_ack: false, clear_binding: false });
|
|
@@ -2918,15 +3048,86 @@ async function handleApi(pathname, req, ctx) {
|
|
|
2918
3048
|
} else if (action === "mark_binding_stale") {
|
|
2919
3049
|
if (!Number.isInteger(bindingId) || bindingId <= 0) throw new Error("binding_id is required");
|
|
2920
3050
|
binding = bindingManager.markStale(bindingId);
|
|
3051
|
+
} else if (action === "promote_binding_to_verified_target") {
|
|
3052
|
+
if (!Number.isInteger(bindingId) || bindingId <= 0) throw new Error("binding_id is required");
|
|
3053
|
+
target = promoteBindingToVerifiedTarget(store, {
|
|
3054
|
+
binding_id: bindingId,
|
|
3055
|
+
scope_type: body?.scope_type === "workspace_default" ? "workspace_default" : body?.scope_type === "owner" ? "owner" : void 0,
|
|
3056
|
+
scope_key: typeof body?.scope_key === "string" ? body.scope_key : void 0,
|
|
3057
|
+
route_kind: body?.route_kind === "group" ? "group" : body?.route_kind === "dm" ? "dm" : void 0,
|
|
3058
|
+
priority: Number.isFinite(Number(body?.priority)) ? Number(body.priority) : void 0,
|
|
3059
|
+
status: body?.status === "disabled" ? "disabled" : body?.status === "failing" ? "failing" : "active"
|
|
3060
|
+
});
|
|
3061
|
+
} else if (action === "create_verified_target") {
|
|
3062
|
+
const normalized = normalizeVerifiedDeliveryTargetInput({
|
|
3063
|
+
scope_type: body?.scope_type === "workspace_default" ? "workspace_default" : "owner",
|
|
3064
|
+
scope_key: typeof body?.scope_key === "string" ? body.scope_key : void 0,
|
|
3065
|
+
owner_ref: body?.scope_type === "owner" && typeof body?.scope_key === "string" ? body.scope_key : void 0,
|
|
3066
|
+
channel: typeof body?.channel === "string" ? body.channel : void 0,
|
|
3067
|
+
to_target: typeof body?.to_target === "string" ? body.to_target : void 0,
|
|
3068
|
+
account_id: typeof body?.account_id === "string" ? body.account_id : void 0,
|
|
3069
|
+
thread_id: typeof body?.thread_id === "string" || typeof body?.thread_id === "number" ? body.thread_id : void 0,
|
|
3070
|
+
route_kind: body?.route_kind === "group" ? "group" : body?.route_kind === "dm" ? "dm" : void 0,
|
|
3071
|
+
priority: Number.isFinite(Number(body?.priority)) ? Number(body.priority) : void 0,
|
|
3072
|
+
status: body?.status === "disabled" ? "disabled" : body?.status === "failing" ? "failing" : "active",
|
|
3073
|
+
provenance: "manual_create"
|
|
3074
|
+
});
|
|
3075
|
+
if (!normalized) throw new Error("channel/to_target is invalid or unsupported");
|
|
3076
|
+
target = targetManager.upsert(normalized);
|
|
3077
|
+
} else if (action === "update_verified_target") {
|
|
3078
|
+
if (!Number.isInteger(targetId) || targetId <= 0) throw new Error("target_id is required");
|
|
3079
|
+
const existing = targetManager.get(targetId);
|
|
3080
|
+
if (!existing) throw new Error("verified target not found");
|
|
3081
|
+
const patch = normalizeVerifiedDeliveryTargetUpdateInput(existing, {
|
|
3082
|
+
scope_type: body?.scope_type === "workspace_default" ? "workspace_default" : body?.scope_type === "owner" ? "owner" : void 0,
|
|
3083
|
+
scope_key: typeof body?.scope_key === "string" ? body.scope_key : void 0,
|
|
3084
|
+
channel: typeof body?.channel === "string" ? body.channel : void 0,
|
|
3085
|
+
to_target: typeof body?.to_target === "string" ? body.to_target : void 0,
|
|
3086
|
+
account_id: typeof body?.account_id === "string" ? body.account_id : void 0,
|
|
3087
|
+
thread_id: typeof body?.thread_id === "string" ? body.thread_id : void 0,
|
|
3088
|
+
route_kind: body?.route_kind === "group" ? "group" : body?.route_kind === "dm" ? "dm" : void 0,
|
|
3089
|
+
priority: Number.isFinite(Number(body?.priority)) ? Number(body.priority) : void 0,
|
|
3090
|
+
status: body?.status === "active" || body?.status === "disabled" || body?.status === "failing" ? body.status : void 0
|
|
3091
|
+
});
|
|
3092
|
+
if (!patch) throw new Error("channel/to_target is invalid or unsupported");
|
|
3093
|
+
target = targetManager.update(targetId, patch);
|
|
3094
|
+
} else if (action === "disable_verified_target") {
|
|
3095
|
+
if (!Number.isInteger(targetId) || targetId <= 0) throw new Error("target_id is required");
|
|
3096
|
+
target = targetManager.markDisabled(targetId);
|
|
3097
|
+
} else if (action === "retest_verified_target") {
|
|
3098
|
+
if (!Number.isInteger(targetId) || targetId <= 0) throw new Error("target_id is required");
|
|
3099
|
+
target = targetManager.markVerified(targetId);
|
|
3100
|
+
} else if (action === "set_workspace_default_target") {
|
|
3101
|
+
if (!Number.isInteger(targetId) || targetId <= 0) throw new Error("target_id is required");
|
|
3102
|
+
target = targetManager.update(targetId, {
|
|
3103
|
+
scope_type: "workspace_default",
|
|
3104
|
+
scope_key: "default",
|
|
3105
|
+
route_kind: "group",
|
|
3106
|
+
status: "active",
|
|
3107
|
+
provenance: "workspace_default"
|
|
3108
|
+
});
|
|
3109
|
+
} else if (action === "import_binding_candidates") {
|
|
3110
|
+
importedTargets = importBindingCandidates(store, {
|
|
3111
|
+
limit: 100,
|
|
3112
|
+
status: body?.status === "active" ? "active" : body?.status === "failing" ? "failing" : "disabled",
|
|
3113
|
+
scope_type: body?.scope_type === "workspace_default" ? "workspace_default" : body?.scope_type === "owner" ? "owner" : void 0,
|
|
3114
|
+
route_kind: body?.route_kind === "group" ? "group" : body?.route_kind === "dm" ? "dm" : void 0,
|
|
3115
|
+
provenance: "binding_import_bulk"
|
|
3116
|
+
});
|
|
2921
3117
|
} else {
|
|
2922
|
-
throw new Error("
|
|
3118
|
+
throw new Error("unsupported human delivery action");
|
|
2923
3119
|
}
|
|
2924
3120
|
return {
|
|
2925
3121
|
ok: true,
|
|
2926
3122
|
action,
|
|
2927
3123
|
intent,
|
|
2928
3124
|
binding,
|
|
3125
|
+
target,
|
|
3126
|
+
importedTargets,
|
|
2929
3127
|
humanDelivery: summarizeHumanDelivery(store, 20),
|
|
3128
|
+
recentVerifiedTargets: targetManager.listRecent(50),
|
|
3129
|
+
recentDeliveryAttempts: attemptManager.listRecent(50),
|
|
3130
|
+
importableBindingCandidates: listImportableBindingCandidates(store, 50),
|
|
2930
3131
|
unresolvedIntents: intentManager.listByStatus("unresolved", 50),
|
|
2931
3132
|
failedIntents: intentManager.listByStatus("failed", 50),
|
|
2932
3133
|
acknowledgedIntents: intentManager.listByStatus("acknowledged", 50)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pingagent/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"uuid": "^11.0.0",
|
|
36
36
|
"ws": "^8.0.0",
|
|
37
37
|
"@pingagent/protocol": "0.1.1",
|
|
38
|
-
"@pingagent/
|
|
39
|
-
"@pingagent/
|
|
38
|
+
"@pingagent/a2a": "0.1.1",
|
|
39
|
+
"@pingagent/schemas": "0.1.4"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/better-sqlite3": "^7.6.0",
|