@pingagent/sdk 0.1.9 → 0.1.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.
package/dist/index.d.ts CHANGED
@@ -947,4 +947,40 @@ declare class WsSubscription {
947
947
  private syncConnections;
948
948
  }
949
949
 
950
- export { A2AAdapter, type A2AAdapterOptions, type A2ATaskResult, type AgentEncryptionCard, type AgentProfile, type ClientOptions, type Contact, ContactManager, type ContactPolicyAction, type ContactPolicyDecision, type ConversationEntry, type ConversationListResponse, type DirectoryBrowseResponse, type DirectorySelfResponse, type EncryptedPayloadWrapper, type EncryptionIdentityFields, type EncryptionPrivateKeyJwk, type EncryptionPublicKeyJwk, type FeedByDidResponse, type FeedPost, type FeedPublicResponse, type FetchResponse, HistoryManager, HttpTransport, LocalStore, PingAgentClient, type RecommendationSummary, type ReplyTarget, type RuntimeMode, type SendResponse, SessionManager, type SessionMessageInput, type SessionState, type StoredMessage, type StoredTrustRecommendation, type SubscriptionResponse, type SubscriptionUsage, type SyncTrustRecommendationsInput, type TaskPolicyAction, type TaskPolicyDecision, type TaskResult, type TaskThread, TaskThreadManager, type TaskThreadStatus, type TaskThreadUpsert, type TransportOptions, type TrustPolicyAuditEvent, type TrustPolicyAuditEventType, type TrustPolicyAuditInput, TrustPolicyAuditManager, type TrustPolicyAuditSummary, type TrustPolicyContext, type TrustPolicyDoc, type TrustPolicyLearningSummary, type TrustPolicyRecommendation, TrustRecommendationManager, type TrustRecommendationStatus, type TrustState, WsSubscription, type WsSubscriptionOptions, buildSessionKey, buildTrustPolicyRecommendations, decideContactPolicy, decideTaskPolicy, decryptPayloadForIdentity, defaultTrustPolicyDoc, encryptPayloadForRecipients, ensureIdentityEncryptionKeys, ensureTokenValid, generateIdentity, getIdentityPath, getProfile, getRootDir, getStorePath, identityExists, isEncryptedPayload, loadIdentity, matchesTrustPolicyRule, normalizeTrustPolicyDoc, previewFromPayload, saveIdentity, shouldEncryptConversationPayload, summarizeTrustPolicyAudit, updateStoredToken, upsertTrustPolicyRecommendation };
950
+ declare function getActiveSessionFilePath(): string;
951
+ declare function getSessionMapFilePath(): string;
952
+ declare function getSessionBindingAlertsFilePath(): string;
953
+ declare function readCurrentActiveSessionKey(filePath?: string): string | null;
954
+ interface SessionBindingEntry {
955
+ conversation_id: string;
956
+ session_key: string;
957
+ }
958
+ interface SessionBindingAlert {
959
+ conversation_id: string;
960
+ session_key: string;
961
+ status: 'missing_session';
962
+ message: string;
963
+ detected_at: string;
964
+ }
965
+ declare function readSessionBindings(filePath?: string): SessionBindingEntry[];
966
+ declare function writeSessionBindings(entries: SessionBindingEntry[], filePath?: string): string;
967
+ declare function setSessionBinding(conversationId: string, sessionKey: string, filePath?: string): {
968
+ path: string;
969
+ binding: SessionBindingEntry;
970
+ };
971
+ declare function removeSessionBinding(conversationId: string, filePath?: string): {
972
+ path: string;
973
+ removed: boolean;
974
+ };
975
+ declare function readSessionBindingAlerts(filePath?: string): SessionBindingAlert[];
976
+ declare function writeSessionBindingAlerts(entries: SessionBindingAlert[], filePath?: string): string;
977
+ declare function upsertSessionBindingAlert(alert: SessionBindingAlert, filePath?: string): {
978
+ path: string;
979
+ alert: SessionBindingAlert;
980
+ };
981
+ declare function clearSessionBindingAlert(conversationId: string, filePath?: string): {
982
+ path: string;
983
+ removed: boolean;
984
+ };
985
+
986
+ export { A2AAdapter, type A2AAdapterOptions, type A2ATaskResult, type AgentEncryptionCard, type AgentProfile, type ClientOptions, type Contact, ContactManager, type ContactPolicyAction, type ContactPolicyDecision, type ConversationEntry, type ConversationListResponse, type DirectoryBrowseResponse, type DirectorySelfResponse, type EncryptedPayloadWrapper, type EncryptionIdentityFields, type EncryptionPrivateKeyJwk, type EncryptionPublicKeyJwk, type FeedByDidResponse, type FeedPost, type FeedPublicResponse, type FetchResponse, HistoryManager, HttpTransport, LocalStore, PingAgentClient, type RecommendationSummary, type ReplyTarget, type RuntimeMode, type SendResponse, type SessionBindingAlert, type SessionBindingEntry, SessionManager, type SessionMessageInput, type SessionState, type StoredMessage, type StoredTrustRecommendation, type SubscriptionResponse, type SubscriptionUsage, type SyncTrustRecommendationsInput, type TaskPolicyAction, type TaskPolicyDecision, type TaskResult, type TaskThread, TaskThreadManager, type TaskThreadStatus, type TaskThreadUpsert, type TransportOptions, type TrustPolicyAuditEvent, type TrustPolicyAuditEventType, type TrustPolicyAuditInput, TrustPolicyAuditManager, type TrustPolicyAuditSummary, type TrustPolicyContext, type TrustPolicyDoc, type TrustPolicyLearningSummary, type TrustPolicyRecommendation, TrustRecommendationManager, type TrustRecommendationStatus, type TrustState, WsSubscription, type WsSubscriptionOptions, buildSessionKey, buildTrustPolicyRecommendations, clearSessionBindingAlert, decideContactPolicy, decideTaskPolicy, decryptPayloadForIdentity, defaultTrustPolicyDoc, encryptPayloadForRecipients, ensureIdentityEncryptionKeys, ensureTokenValid, generateIdentity, getActiveSessionFilePath, getIdentityPath, getProfile, getRootDir, getSessionBindingAlertsFilePath, getSessionMapFilePath, getStorePath, identityExists, isEncryptedPayload, loadIdentity, matchesTrustPolicyRule, normalizeTrustPolicyDoc, previewFromPayload, readCurrentActiveSessionKey, readSessionBindingAlerts, readSessionBindings, removeSessionBinding, saveIdentity, setSessionBinding, shouldEncryptConversationPayload, summarizeTrustPolicyAudit, updateStoredToken, upsertSessionBindingAlert, upsertTrustPolicyRecommendation, writeSessionBindingAlerts, writeSessionBindings };
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  WsSubscription,
13
13
  buildSessionKey,
14
14
  buildTrustPolicyRecommendations,
15
+ clearSessionBindingAlert,
15
16
  decideContactPolicy,
16
17
  decideTaskPolicy,
17
18
  decryptPayloadForIdentity,
@@ -20,9 +21,12 @@ import {
20
21
  ensureIdentityEncryptionKeys,
21
22
  ensureTokenValid,
22
23
  generateIdentity,
24
+ getActiveSessionFilePath,
23
25
  getIdentityPath,
24
26
  getProfile,
25
27
  getRootDir,
28
+ getSessionBindingAlertsFilePath,
29
+ getSessionMapFilePath,
26
30
  getStorePath,
27
31
  identityExists,
28
32
  isEncryptedPayload,
@@ -30,12 +34,20 @@ import {
30
34
  matchesTrustPolicyRule,
31
35
  normalizeTrustPolicyDoc,
32
36
  previewFromPayload,
37
+ readCurrentActiveSessionKey,
38
+ readSessionBindingAlerts,
39
+ readSessionBindings,
40
+ removeSessionBinding,
33
41
  saveIdentity,
42
+ setSessionBinding,
34
43
  shouldEncryptConversationPayload,
35
44
  summarizeTrustPolicyAudit,
36
45
  updateStoredToken,
37
- upsertTrustPolicyRecommendation
38
- } from "./chunk-PFABO4C7.js";
46
+ upsertSessionBindingAlert,
47
+ upsertTrustPolicyRecommendation,
48
+ writeSessionBindingAlerts,
49
+ writeSessionBindings
50
+ } from "./chunk-2Y6YRKTO.js";
39
51
  export {
40
52
  A2AAdapter,
41
53
  ContactManager,
@@ -50,6 +62,7 @@ export {
50
62
  WsSubscription,
51
63
  buildSessionKey,
52
64
  buildTrustPolicyRecommendations,
65
+ clearSessionBindingAlert,
53
66
  decideContactPolicy,
54
67
  decideTaskPolicy,
55
68
  decryptPayloadForIdentity,
@@ -58,9 +71,12 @@ export {
58
71
  ensureIdentityEncryptionKeys,
59
72
  ensureTokenValid,
60
73
  generateIdentity,
74
+ getActiveSessionFilePath,
61
75
  getIdentityPath,
62
76
  getProfile,
63
77
  getRootDir,
78
+ getSessionBindingAlertsFilePath,
79
+ getSessionMapFilePath,
64
80
  getStorePath,
65
81
  identityExists,
66
82
  isEncryptedPayload,
@@ -68,9 +84,17 @@ export {
68
84
  matchesTrustPolicyRule,
69
85
  normalizeTrustPolicyDoc,
70
86
  previewFromPayload,
87
+ readCurrentActiveSessionKey,
88
+ readSessionBindingAlerts,
89
+ readSessionBindings,
90
+ removeSessionBinding,
71
91
  saveIdentity,
92
+ setSessionBinding,
72
93
  shouldEncryptConversationPayload,
73
94
  summarizeTrustPolicyAudit,
74
95
  updateStoredToken,
75
- upsertTrustPolicyRecommendation
96
+ upsertSessionBindingAlert,
97
+ upsertTrustPolicyRecommendation,
98
+ writeSessionBindingAlerts,
99
+ writeSessionBindings
76
100
  };
@@ -8,12 +8,20 @@ import {
8
8
  decideTaskPolicy,
9
9
  defaultTrustPolicyDoc,
10
10
  ensureTokenValid,
11
+ getActiveSessionFilePath,
12
+ getSessionBindingAlertsFilePath,
13
+ getSessionMapFilePath,
11
14
  loadIdentity,
12
15
  normalizeTrustPolicyDoc,
16
+ readCurrentActiveSessionKey,
17
+ readSessionBindingAlerts,
18
+ readSessionBindings,
19
+ removeSessionBinding,
20
+ setSessionBinding,
13
21
  summarizeTrustPolicyAudit,
14
22
  updateStoredToken,
15
23
  upsertTrustPolicyRecommendation
16
- } from "./chunk-PFABO4C7.js";
24
+ } from "./chunk-2Y6YRKTO.js";
17
25
 
18
26
  // src/web-server.ts
19
27
  import * as fs from "fs";
@@ -81,10 +89,12 @@ function getHostPanelHtml() {
81
89
  .session-row .top, .task-row .top, .recommendation-row .top { display: flex; justify-content: space-between; gap: 12px; align-items: center; }
82
90
  .label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: #94a3b8; }
83
91
  .badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px; font-size: 11px; border: 1px solid #334155; }
92
+ button.badge { cursor: pointer; font: inherit; }
84
93
  .badge.trusted { background: rgba(34, 197, 94, 0.12); color: #86efac; border-color: rgba(34, 197, 94, 0.35); }
85
94
  .badge.pending { background: rgba(250, 204, 21, 0.12); color: #fde68a; border-color: rgba(250, 204, 21, 0.35); }
86
95
  .badge.blocked, .badge.revoked { background: rgba(248, 113, 113, 0.12); color: #fca5a5; border-color: rgba(248, 113, 113, 0.35); }
87
96
  .badge.stranger { background: rgba(148, 163, 184, 0.12); color: #cbd5e1; border-color: rgba(148, 163, 184, 0.35); }
97
+ .badge.alert { background: rgba(248, 113, 113, 0.14); color: #fecaca; border-color: rgba(248, 113, 113, 0.45); }
88
98
  .policy-grid { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); align-items: start; }
89
99
  .two-col { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; }
90
100
  .panel { display: none; }
@@ -361,11 +371,17 @@ function getHostPanelHtml() {
361
371
  if (!state.selectedSessionKey) state.selectedSessionKey = sessions[0].session_key;
362
372
  document.getElementById('sessionList').innerHTML = sessions.map(function (session) {
363
373
  const active = session.session_key === state.selectedSessionKey ? ' active' : '';
364
- const badge = '<span class="badge ' + esc(session.trust_state) + '">' + esc(session.trust_state) + '</span>';
374
+ const badges = [
375
+ '<span class="badge ' + esc(session.trust_state) + '">' + esc(session.trust_state) + '</span>',
376
+ session.binding_alert
377
+ ? '<button type="button" class="badge alert rebind-badge-btn" data-session="' + esc(session.session_key) + '" data-conversation="' + esc(session.conversation_id || '') + '" data-bound-session="' + esc(session.mapped_work_session || '') + '" data-remote-did="' + esc(session.remote_did || '') + '" title="' + esc(session.binding_alert.message || 'Rebind this conversation to the current chat session') + '">Needs rebind</button>'
378
+ : '',
379
+ ].filter(Boolean).join('');
365
380
  return '<div class="session-row' + active + '" data-session="' + esc(session.session_key) + '">' +
366
- '<div class="top"><strong>' + esc(session.remote_did || session.conversation_id || 'unknown') + '</strong>' + badge + '</div>' +
381
+ '<div class="top"><strong>' + esc(session.remote_did || session.conversation_id || 'unknown') + '</strong><div style="display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end">' + badges + '</div></div>' +
367
382
  '<div class="muted small" style="margin-top:6px">conversation=' + esc(session.conversation_id || '(none)') + '</div>' +
368
383
  '<div class="muted small">unread=' + esc(session.unread_count) + ' \xB7 last=' + esc(fmtTs(session.last_remote_activity_at || session.updated_at)) + '</div>' +
384
+ '<div class="muted small">work_session=' + esc(session.mapped_work_session || '(unbound)') + (session.is_active_work_session ? ' \xB7 active_chat=true' : '') + '</div>' +
369
385
  '<div class="muted small" style="margin-top:6px">' + esc(session.last_message_preview || '(no preview)') + '</div>' +
370
386
  '</div>';
371
387
  }).join('');
@@ -376,6 +392,20 @@ function getHostPanelHtml() {
376
392
  loadSession(state.selectedSessionKey);
377
393
  });
378
394
  });
395
+ document.getElementById('sessionList').querySelectorAll('.rebind-badge-btn').forEach(function (btn) {
396
+ btn.addEventListener('click', async function (event) {
397
+ event.stopPropagation();
398
+ const sessionKey = btn.getAttribute('data-session');
399
+ const conversationId = btn.getAttribute('data-conversation');
400
+ const previousBinding = btn.getAttribute('data-bound-session');
401
+ const remoteDid = btn.getAttribute('data-remote-did');
402
+ if (!sessionKey || !conversationId) return;
403
+ state.selectedSessionKey = sessionKey;
404
+ renderOverview();
405
+ await loadSession(sessionKey);
406
+ await promptBindCurrentChat(conversationId, previousBinding, remoteDid);
407
+ });
408
+ });
379
409
  }
380
410
 
381
411
  const tasks = Array.isArray(overview.tasks) ? overview.tasks : [];
@@ -419,6 +449,9 @@ function getHostPanelHtml() {
419
449
  const messages = Array.isArray(detail.messages) ? detail.messages : [];
420
450
  const auditEvents = Array.isArray(detail.auditEvents) ? detail.auditEvents : [];
421
451
  const recommendations = Array.isArray(detail.recommendations) ? detail.recommendations : [];
452
+ const binding = detail.binding || null;
453
+ const bindingAlert = detail.bindingAlert || null;
454
+ const activeWorkSession = detail.activeWorkSession || null;
422
455
 
423
456
  el.innerHTML = '' +
424
457
  '<div class="two-col">' +
@@ -429,6 +462,15 @@ function getHostPanelHtml() {
429
462
  '<div class="muted small">conversation=' + esc(session.conversation_id || '(none)') + '</div>' +
430
463
  '<div class="muted small">trust=' + esc(session.trust_state) + ' \xB7 unread=' + esc(session.unread_count) + '</div>' +
431
464
  '<div class="muted small">last activity=' + esc(fmtTs(session.last_remote_activity_at || session.updated_at)) + '</div>' +
465
+ '<div class="muted small" style="margin-top:8px">active_chat_session=' + esc(activeWorkSession || '(none)') + '</div>' +
466
+ '<div class="muted small">binding=' + esc(binding ? binding.session_key : '(unbound)') + '</div>' +
467
+ (bindingAlert
468
+ ? '<div style="margin-top:10px;padding:10px 12px;border:1px solid #ef4444;border-radius:10px;background:rgba(127,29,29,0.25);color:#fecaca"><strong>Needs rebind</strong><div class="small" style="margin-top:6px">' + esc(bindingAlert.message || 'Bound work session is missing. Rebind this PingAgent conversation to the current chat session.') + '</div></div>'
469
+ : '') +
470
+ '<div class="row-actions">' +
471
+ '<button class="action-btn bind-current-btn" data-conversation="' + esc(session.conversation_id || '') + '">Bind Current Chat</button>' +
472
+ '<button class="danger-btn clear-binding-btn" data-conversation="' + esc(session.conversation_id || '') + '">Clear Binding</button>' +
473
+ '</div>' +
432
474
  '</div>' +
433
475
  '<div>' +
434
476
  '<div class="label">Policy Decisions</div>' +
@@ -473,6 +515,54 @@ function getHostPanelHtml() {
473
515
  }).join('') : '<div class="empty">No audit events for this session.</div>') +
474
516
  '</div></div>' +
475
517
  '</div>';
518
+
519
+ el.querySelectorAll('.bind-current-btn').forEach(function (btn) {
520
+ btn.addEventListener('click', async function () {
521
+ const conversationId = btn.getAttribute('data-conversation');
522
+ if (!conversationId) return;
523
+ await promptBindCurrentChat(conversationId);
524
+ });
525
+ });
526
+ el.querySelectorAll('.clear-binding-btn').forEach(function (btn) {
527
+ btn.addEventListener('click', async function () {
528
+ await api('/api/runtime/session-bindings/clear', {
529
+ method: 'POST',
530
+ headers: { 'Content-Type': 'application/json' },
531
+ body: JSON.stringify({ conversation_id: btn.getAttribute('data-conversation') }),
532
+ });
533
+ await refreshAll();
534
+ setTab('runtime');
535
+ });
536
+ });
537
+ }
538
+
539
+ async function promptBindCurrentChat(conversationId, previousBinding, remoteDid) {
540
+ const current = state.session && state.session.activeWorkSession
541
+ ? state.session.activeWorkSession
542
+ : (state.overview && state.overview.activeWorkSession ? state.overview.activeWorkSession : null);
543
+ const previous = previousBinding || (state.session && state.session.binding ? state.session.binding.session_key : null) || '(unbound)';
544
+ const targetRemoteDid = remoteDid || (state.session && state.session.session ? state.session.session.remote_did : null) || '(unknown)';
545
+ const confirmed = window.confirm(
546
+ 'Rebind this PingAgent conversation to the current chat session?' +
547
+ '
548
+
549
+ Conversation: ' + conversationId +
550
+ '
551
+ Remote DID: ' + targetRemoteDid +
552
+ '
553
+
554
+ Current chat: ' + (current || '(none)') +
555
+ '
556
+ Previous binding: ' + previous
557
+ );
558
+ if (!confirmed) return;
559
+ await api('/api/runtime/session-bindings/bind-current', {
560
+ method: 'POST',
561
+ headers: { 'Content-Type': 'application/json' },
562
+ body: JSON.stringify({ conversation_id: conversationId }),
563
+ });
564
+ await refreshAll();
565
+ setTab('runtime');
476
566
  }
477
567
 
478
568
  function renderPolicy() {
@@ -990,6 +1080,11 @@ async function buildRuntimeOverviewPayload(ctx) {
990
1080
  limit: 12
991
1081
  });
992
1082
  const unreadTotal = sessions.reduce((sum, session) => sum + session.unread_count, 0);
1083
+ const sessionBindings = readSessionBindings();
1084
+ const sessionBindingAlerts = readSessionBindingAlerts();
1085
+ const activeWorkSession = readCurrentActiveSessionKey();
1086
+ const bindingByConversation = new Map(sessionBindings.map((row) => [row.conversation_id, row.session_key]));
1087
+ const bindingAlertByConversation = new Map(sessionBindingAlerts.map((row) => [row.conversation_id, row]));
993
1088
  const trustCounts = sessions.reduce((acc, session) => {
994
1089
  acc[session.trust_state] = (acc[session.trust_state] ?? 0) + 1;
995
1090
  return acc;
@@ -999,6 +1094,12 @@ async function buildRuntimeOverviewPayload(ctx) {
999
1094
  serverUrl: ctx.serverUrl,
1000
1095
  runtimeMode,
1001
1096
  trustPolicyPath: getTrustPolicyPath(ctx.identityPath),
1097
+ activeWorkSessionFile: getActiveSessionFilePath(),
1098
+ activeWorkSession,
1099
+ sessionMapPath: getSessionMapFilePath(),
1100
+ sessionBindingAlertsPath: getSessionBindingAlertsFilePath(),
1101
+ sessionBindings,
1102
+ sessionBindingAlerts,
1002
1103
  subscription: subscription ? {
1003
1104
  tier: subscription.tier,
1004
1105
  summary: describeHostedTier(subscription.tier),
@@ -1021,6 +1122,9 @@ async function buildRuntimeOverviewPayload(ctx) {
1021
1122
  recommendationSummary: recommendationState.summary,
1022
1123
  sessions: sessions.map((session) => ({
1023
1124
  ...session,
1125
+ mapped_work_session: session.conversation_id ? bindingByConversation.get(session.conversation_id) ?? null : null,
1126
+ binding_alert: session.conversation_id ? bindingAlertByConversation.get(session.conversation_id) ?? null : null,
1127
+ is_active_work_session: session.session_key === activeWorkSession,
1024
1128
  latest_messages: session.conversation_id ? historyManager.listRecent(session.conversation_id, 3) : []
1025
1129
  })),
1026
1130
  tasks: refreshedTasks,
@@ -1054,6 +1158,11 @@ async function buildSessionOverviewPayload(ctx, sessionKey) {
1054
1158
  auditStore.close();
1055
1159
  }
1056
1160
  const policy = readTrustPolicyDoc(ctx.identityPath);
1161
+ const bindings = readSessionBindings();
1162
+ const bindingAlerts = readSessionBindingAlerts();
1163
+ const binding = session.conversation_id ? bindings.find((row) => row.conversation_id === session.conversation_id) ?? null : null;
1164
+ const bindingAlert = session.conversation_id ? bindingAlerts.find((row) => row.conversation_id === session.conversation_id) ?? null : null;
1165
+ const activeWorkSession = readCurrentActiveSessionKey();
1057
1166
  const recommendationState = syncTrustRecommendations(ctx.storePath, {
1058
1167
  policyDoc: policy,
1059
1168
  sessions: sessionManager.listRecentSessions(50),
@@ -1064,6 +1173,12 @@ async function buildSessionOverviewPayload(ctx, sessionKey) {
1064
1173
  });
1065
1174
  return {
1066
1175
  session,
1176
+ binding,
1177
+ bindingAlert,
1178
+ activeWorkSession,
1179
+ activeWorkSessionFile: getActiveSessionFilePath(),
1180
+ sessionMapPath: getSessionMapFilePath(),
1181
+ sessionBindingAlertsPath: getSessionBindingAlertsFilePath(),
1067
1182
  policyExplain: buildPolicyDecisionShape(ctx.identityPath, session.remote_did, { runtimeMode: getRuntimeMode() }),
1068
1183
  tasks,
1069
1184
  messages,
@@ -1089,6 +1204,63 @@ async function handleApi(pathname, req, ctx) {
1089
1204
  const sessionKey = url.searchParams.get("session_key");
1090
1205
  return buildSessionOverviewPayload(ctx, sessionKey);
1091
1206
  }
1207
+ if (parts[1] === "session-bindings") {
1208
+ if ((!parts[2] || parts[2] === "list") && req.method === "GET") {
1209
+ const url = new URL(req.url || "", "http://x");
1210
+ const conversationId = url.searchParams.get("conversation_id");
1211
+ const rows = conversationId ? readSessionBindings().filter((row) => row.conversation_id === conversationId) : readSessionBindings();
1212
+ return {
1213
+ activeWorkSessionFile: getActiveSessionFilePath(),
1214
+ activeWorkSession: readCurrentActiveSessionKey(),
1215
+ sessionMapPath: getSessionMapFilePath(),
1216
+ sessionBindingAlertsPath: getSessionBindingAlertsFilePath(),
1217
+ alerts: conversationId ? readSessionBindingAlerts().filter((row) => row.conversation_id === conversationId) : readSessionBindingAlerts(),
1218
+ bindings: rows
1219
+ };
1220
+ }
1221
+ if (parts[2] === "bind-current" && req.method === "POST") {
1222
+ const body = await readBody(req);
1223
+ const conversationId = String(body?.conversation_id ?? "").trim();
1224
+ if (!conversationId) throw new Error("conversation_id is required");
1225
+ const current = readCurrentActiveSessionKey();
1226
+ if (!current) {
1227
+ throw new Error(`No active OpenClaw chat session found in ${getActiveSessionFilePath()}`);
1228
+ }
1229
+ const result = setSessionBinding(conversationId, current);
1230
+ return {
1231
+ ok: true,
1232
+ activeWorkSessionFile: getActiveSessionFilePath(),
1233
+ activeWorkSession: current,
1234
+ sessionMapPath: result.path,
1235
+ binding: result.binding
1236
+ };
1237
+ }
1238
+ if (parts[2] === "set" && req.method === "POST") {
1239
+ const body = await readBody(req);
1240
+ const conversationId = String(body?.conversation_id ?? "").trim();
1241
+ const sessionKey = String(body?.session_key ?? "").trim();
1242
+ if (!conversationId || !sessionKey) throw new Error("conversation_id and session_key are required");
1243
+ const result = setSessionBinding(conversationId, sessionKey);
1244
+ return {
1245
+ ok: true,
1246
+ activeWorkSessionFile: getActiveSessionFilePath(),
1247
+ activeWorkSession: readCurrentActiveSessionKey(),
1248
+ sessionMapPath: result.path,
1249
+ binding: result.binding
1250
+ };
1251
+ }
1252
+ if (parts[2] === "clear" && req.method === "POST") {
1253
+ const body = await readBody(req);
1254
+ const conversationId = String(body?.conversation_id ?? "").trim();
1255
+ if (!conversationId) throw new Error("conversation_id is required");
1256
+ const result = removeSessionBinding(conversationId);
1257
+ return {
1258
+ ok: true,
1259
+ removed: result.removed,
1260
+ sessionMapPath: result.path
1261
+ };
1262
+ }
1263
+ }
1092
1264
  if (parts[1] === "policy") {
1093
1265
  const policyPath = getTrustPolicyPath(ctx.identityPath);
1094
1266
  const runtimeMode = getRuntimeMode();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pingagent/sdk",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"