@pingagent/sdk 0.1.16 → 0.1.17

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/bin/pingagent.js CHANGED
@@ -40,6 +40,7 @@ import {
40
40
  listPendingDecisionViews,
41
41
  summarizeHumanDelivery,
42
42
  listRecentBindingsForSession,
43
+ deriveOpenClawAgentState,
43
44
  deriveTransportHealth,
44
45
  readTransportPreference,
45
46
  switchTransportPreference,
@@ -208,15 +209,16 @@ function getHostPanelSurfaceUrl() {
208
209
 
209
210
  function getSurfaceRecommendationLines(primaryCommandPrefix = 'npx @pingagent/sdk', secondaryCommandPrefix = 'pingagent') {
210
211
  return [
211
- 'With GUI: Host Panel',
212
+ 'GUI repair / approvals / audit: Host Panel',
212
213
  ` Start locally: ${primaryCommandPrefix} web`,
213
214
  ...(secondaryCommandPrefix && secondaryCommandPrefix !== primaryCommandPrefix ? [` Or via local bin: ${secondaryCommandPrefix} web`] : []),
214
215
  ` URL when running: ${getHostPanelSurfaceUrl()}`,
215
- 'Headless / low-token: TUI',
216
+ 'Headless repair surface: TUI',
216
217
  ` ${primaryCommandPrefix} host tui`,
217
218
  ...(secondaryCommandPrefix && secondaryCommandPrefix !== primaryCommandPrefix ? [` ${secondaryCommandPrefix} host tui`] : []),
218
219
  ` ${primaryCommandPrefix} host tui --once`,
219
- 'MCP: agent/runtime control surface, not the default human operator UI',
220
+ 'Agent default loop: pingagent_recent_sessions -> pingagent_focus_session -> pingagent_reply',
221
+ 'MCP: agent/runtime control surface',
220
222
  ];
221
223
  }
222
224
 
@@ -457,6 +459,13 @@ function buildHostState(identityPath, selectedSessionKey = null, historyPageInde
457
459
  ? buildProjectionPreview(store, selectedSession.session_key, policy.doc.collaboration_projection?.preset || 'balanced', 5)
458
460
  : null;
459
461
  const humanDelivery = summarizeHumanDelivery(store, 20);
462
+ const agentState = deriveOpenClawAgentState({
463
+ runtime_status: ingressRuntime,
464
+ sessions,
465
+ pending_decisions: pendingCollaborationEventsGlobal.length,
466
+ human_delivery: humanDelivery,
467
+ transport_health: transportHealth,
468
+ });
460
469
  const selectedRecentBindings = selectedSession
461
470
  ? listRecentBindingsForSession(store, selectedSession.session_key, selectedSession.conversation_id, 12)
462
471
  : [];
@@ -470,6 +479,7 @@ function buildHostState(identityPath, selectedSessionKey = null, historyPageInde
470
479
  ingressRuntime,
471
480
  transportPreference,
472
481
  transportHealth,
482
+ agentState,
473
483
  activeChatSessionFile: getActiveSessionFilePath(),
474
484
  sessionMapPath: getSessionMapFilePath(),
475
485
  sessionBindingAlertsPath: getSessionBindingAlertsFilePath(),
@@ -556,22 +566,29 @@ function renderHostTuiScreen(hostState, uiState) {
556
566
  last_canary_ok: null,
557
567
  last_canary_at: null,
558
568
  };
569
+ const agentState = hostState.agentState || {
570
+ state: 'activating',
571
+ summary: 'Activation is still in progress.',
572
+ next_action: 'Wait for activation to finish.',
573
+ reason: null,
574
+ };
559
575
  const sinceLastSeenGlobal = hostState.sinceLastSeenGlobal || {};
560
576
  const lines = [
561
577
  'PingAgent Host TUI',
562
578
  `DID: ${hostState.identity.did}`,
563
579
  `status=${formatStatusLine(uiState?.statusLevel || 'info', uiState?.statusMessage || '(ready)')}${statusTs}${statusCountdown}`,
564
- `runtime_mode=${hostState.runtimeMode} receive_mode=${hostState.ingressRuntime?.receive_mode || 'webhook'} current_openclaw_chat=${hostState.activeChatSession || '(none)'}`,
580
+ `agent_state=${agentState.state} runtime_mode=${hostState.runtimeMode} receive_mode=${hostState.ingressRuntime?.receive_mode || 'webhook'}`,
581
+ `agent_summary=${agentState.summary}`,
582
+ `agent_next_action=${agentState.next_action}`,
565
583
  `ingress=${ingressLabel}${degraded ? ' action=[f] fix-now' : ''}`,
566
584
  `transport=${transportHealth.transport_mode} preferred=${transportHealth.preferred_transport_mode} state=${transportHealth.state} retry_queue=${transportHealth.retry_queue_length} failures=${transportHealth.consecutive_failures}`,
567
585
  `human_delivery mode=${humanDelivery.mode || 'projection_outbox'} active_bindings=${humanDelivery.active_bindings ?? 0} pending=${humanDelivery.pending_intents ?? 0} unresolved=${humanDelivery.unresolved_intents ?? 0} failed=${humanDelivery.failed_intents ?? 0} acked=${humanDelivery.acknowledged_intents ?? 0}`,
568
586
  `human_delivery_channels supported=${(humanDelivery.supported_channels || []).join(',') || '(none)'} unsupported=${(humanDelivery.unsupported_channels || []).join(',') || '(none)'} canary_ok=${typeof humanDelivery.last_canary_ok === 'boolean' ? String(humanDelivery.last_canary_ok) : '(unknown)'} at=${humanDelivery.last_canary_at || '(none)'}`,
569
587
  uiState?.publicLinkUrl ? `public_link=${uiState.publicLinkUrl}` : null,
570
- `sessions=${sessions.length} unread_total=${hostState.unreadTotal ?? 0} alert_sessions=${hostState.alertSessions ?? 0} view=${view} projection=${hostState.projectionPreset || 'balanced'}`,
588
+ `sessions=${sessions.length} unread_total=${hostState.unreadTotal ?? 0} repair_alert_sessions=${hostState.alertSessions ?? 0} view=${view} projection=${hostState.projectionPreset || 'balanced'}`,
571
589
  `since_last_seen external=${sinceLastSeenGlobal.new_external_messages ?? 0} conclusions=${sinceLastSeenGlobal.new_conclusions ?? 0} decisions=${sinceLastSeenGlobal.new_decisions ?? 0} failures=${sinceLastSeenGlobal.new_failures ?? 0}`,
572
590
  `policy=${hostState.policyPath}`,
573
- `chat_link_map=${hostState.sessionMapPath}`,
574
- `chat_link_alerts=${hostState.sessionBindingAlertsPath}`,
591
+ agentState.reason ? `agent_reason=${truncateLine(agentState.reason, 120)}` : null,
575
592
  hostState.ingressRuntime?.hooks_last_error ? `hooks_error=${truncateLine(hostState.ingressRuntime.hooks_last_error, 120)}` : null,
576
593
  '',
577
594
  ].filter(Boolean);
@@ -590,7 +607,6 @@ function renderHostTuiScreen(hostState, uiState) {
590
607
  lines.push('- x: cancel selected task (in task views)');
591
608
  lines.push('- p: multiline reply prompt (detail view)');
592
609
  lines.push('- S: edit carry-forward summary (detail view)');
593
- lines.push('- d: try demo agent preset');
594
610
  lines.push('- o: open local history paging (detail view)');
595
611
  lines.push('- n / p: older / newer history page (history view)');
596
612
  lines.push('- s or /: search local history (history view)');
@@ -603,8 +619,6 @@ function renderHostTuiScreen(hostState, uiState) {
603
619
  lines.push('- A: apply first open trust recommendation for selected session');
604
620
  lines.push('- D: dismiss current open recommendation');
605
621
  lines.push('- R: reopen dismissed/superseded recommendation');
606
- lines.push('- B: attach selected session to the current OpenClaw chat');
607
- lines.push('- C: detach the selected chat link');
608
622
  lines.push('- q: quit');
609
623
  } else if (view === 'history') {
610
624
  lines.push('Conversation History');
@@ -714,13 +728,12 @@ function renderHostTuiScreen(hostState, uiState) {
714
728
  lines.push(`remote=${selected.remote_did || '(unknown)'}`);
715
729
  lines.push(`trust=${selected.trust_state} unread=${selected.unread_count}`);
716
730
  lines.push(`last_preview=${selected.last_message_preview || '(none)'}`);
717
- lines.push(`chat_link=${selected.binding?.session_key || '(none)'}`);
718
- lines.push(`current_openclaw_chat=${hostState.activeChatSession || '(none)'}`);
731
+ lines.push(`compatibility_route=${selected.binding?.session_key || '(none)'}`);
719
732
  if (selected.binding_alert) {
720
- lines.push('needs_reconnect=true');
721
- lines.push(`warning=${selected.binding_alert.message}`);
733
+ lines.push('compatibility_route_stale=true');
734
+ lines.push(`repair_warning=${selected.binding_alert.message}`);
722
735
  } else {
723
- lines.push('needs_reconnect=false');
736
+ lines.push('compatibility_route_stale=false');
724
737
  }
725
738
  if (openRecommendation) {
726
739
  lines.push(`trust_action=${getTrustRecommendationActionLabel(openRecommendation)}`);
@@ -748,17 +761,17 @@ function renderHostTuiScreen(hostState, uiState) {
748
761
  '[D] dismiss-rec',
749
762
  '[R] reopen-rec',
750
763
  '[m] mark-read',
751
- '[d] demo',
752
764
  '[p] reply',
753
765
  '[S] summary',
754
766
  pendingCollaborationEvents.length ? '[u] approve-decision' : null,
755
767
  pendingCollaborationEvents.length ? '[U] reject-decision' : null,
756
768
  '[o] history',
757
769
  '[t] tasks',
758
- '[B] attach-chat',
759
- '[C] detach-chat',
760
770
  ].filter(Boolean).join(' ');
761
771
  lines.push(`actions=${actionBar}`);
772
+ if (selected.binding || selected.binding_alert) {
773
+ lines.push('compatibility_note=Legacy current-thread routing is available for repair only; the default human-delivery path uses bindings + notification intents.');
774
+ }
762
775
  lines.push('');
763
776
  lines.push('Carry-Forward Summary');
764
777
  if (selectedSummary) {
@@ -827,7 +840,7 @@ function renderHostTuiScreen(hostState, uiState) {
827
840
  }
828
841
 
829
842
  lines.push('');
830
- lines.push('Keys: ↑/↓ or j/k select Enter/l open Esc/h back g/G jump r refresh a approve u/U decide A apply-rec D dismiss-rec R reopen-rec d demo m read p reply o history s search t tasks x cancel-task y dump f fix-hooks b transport->bridge c transport->channel B attach-chat C detach-chat ? help q quit');
843
+ lines.push('Keys: ↑/↓ or j/k select Enter/l open Esc/h back g/G jump r refresh a approve u/U decide A apply-rec D dismiss-rec R reopen-rec m read p reply o history s search t tasks x cancel-task y dump f fix-hooks b transport->bridge c transport->channel ? help q quit');
831
844
  return lines.join('\n');
832
845
  }
833
846
 
@@ -1548,17 +1561,17 @@ async function runHostTui(identityPath, opts) {
1548
1561
  if (!selected?.conversation_id) return;
1549
1562
  const current = latestState.activeChatSession || '(none)';
1550
1563
  const previous = selected.binding?.session_key || '(none)';
1551
- const confirmed = await confirmAction(`Attach chat link for conversation ${selected.conversation_id}\nRemote DID: ${selected.remote_did || '(unknown)'}\nCurrent OpenClaw chat: ${current}\nPrevious chat link: ${previous}\nProceed?`);
1564
+ const confirmed = await confirmAction(`Repair legacy compatibility route for conversation ${selected.conversation_id}\nRemote DID: ${selected.remote_did || '(unknown)'}\nCurrent compatibility target: ${current}\nPrevious compatibility route: ${previous}\nProceed?`);
1552
1565
  if (confirmed) {
1553
1566
  if (!latestState.activeChatSession) {
1554
- setStatus('Attach failed: no active OpenClaw chat.', 'err');
1567
+ setStatus('Compatibility repair failed: no active compatibility target.', 'err');
1555
1568
  latestState = redraw();
1556
1569
  return;
1557
1570
  }
1558
1571
  setSessionBinding(selected.conversation_id, latestState.activeChatSession);
1559
- setStatus(`Attached chat link ${selected.conversation_id} -> ${latestState.activeChatSession}`, 'ok');
1572
+ setStatus(`Compatibility route repaired ${selected.conversation_id} -> ${latestState.activeChatSession}`, 'ok');
1560
1573
  } else {
1561
- setStatus('Attach chat link cancelled.', 'warn');
1574
+ setStatus('Compatibility repair cancelled.', 'warn');
1562
1575
  }
1563
1576
  latestState = redraw();
1564
1577
  return;
@@ -1567,7 +1580,7 @@ async function runHostTui(identityPath, opts) {
1567
1580
  const selected = (latestState.sessions || []).find((session) => session.session_key === uiState.selectedSessionKey);
1568
1581
  if (!selected?.conversation_id) return;
1569
1582
  removeSessionBinding(selected.conversation_id);
1570
- setStatus(`Detached chat link for ${selected.conversation_id}`, 'ok');
1583
+ setStatus(`Cleared compatibility route for ${selected.conversation_id}`, 'ok');
1571
1584
  latestState = redraw();
1572
1585
  return;
1573
1586
  }
@@ -3520,88 +3533,52 @@ async function runHostBootstrap(opts) {
3520
3533
  process.exit(1);
3521
3534
  }
3522
3535
 
3523
- const steps = [];
3524
- const runStep = (label, args) => {
3525
- const result = runOpenClawInstall(args);
3526
- steps.push({ label, args, result });
3527
- return { label, args, result };
3528
- };
3529
-
3530
- const installStep = runStep('install', []);
3531
- const hooksStep = installStep.result.ok ? runStep('hooks repair', ['fix-hooks']) : null;
3532
- const verifyStep = installStep.result.ok && hooksStep?.result.ok
3533
- ? runStep('runtime verify', ['verify-runtime', '--fix-hooks'])
3534
- : null;
3535
-
3536
+ const installStep = runOpenClawInstall([]);
3537
+ const steps = [{ label: 'activate', result: installStep }];
3536
3538
  let runnerStep = null;
3537
- if (verifyStep?.result.ok && opts.write) {
3539
+ if (installStep.ok && opts.write) {
3538
3540
  const runnerArgs = ['init-runner', '--ingress', '--panel'];
3539
3541
  if (template) runnerArgs.push('--template', template);
3540
3542
  const supportsWrite = !template || template === 'launchd' || template === 'systemd';
3541
3543
  if (supportsWrite) runnerArgs.push('--write');
3542
- runnerStep = runStep(supportsWrite ? 'runner setup' : 'runner template', runnerArgs);
3544
+ const result = runOpenClawInstall(runnerArgs);
3545
+ steps.push({ label: supportsWrite ? 'runner setup' : 'runner template', result });
3546
+ runnerStep = { result };
3547
+ }
3548
+
3549
+ console.log('PingAgent Host Bootstrap (compatibility alias)');
3550
+ console.log('=============================================');
3551
+ console.log('bootstrap_role=compatibility_alias');
3552
+ console.log('preferred_entry=npx @pingagent/openclaw-install');
3553
+ console.log('');
3554
+
3555
+ if (installStep.stdout.trim()) {
3556
+ console.log(installStep.stdout.trim());
3557
+ }
3558
+ if (installStep.stderr.trim()) {
3559
+ console.error(installStep.stderr.trim());
3543
3560
  }
3544
3561
 
3545
3562
  if (runnerStep?.result.stdout && opts.write) {
3563
+ console.log('');
3546
3564
  console.log(runnerStep.result.stdout.trim());
3547
3565
  if (runnerStep.result.stderr.trim()) console.error(runnerStep.result.stderr.trim());
3548
- console.log('');
3549
3566
  }
3550
3567
 
3551
3568
  const failed = steps.find((step) => !step.result.ok) ?? null;
3552
- const formatStepStatus = (step, fallback = 'skipped') => (step ? (step.result.ok ? 'ok' : 'failed') : fallback);
3553
- const runnerStatus = !opts.write
3554
- ? 'not_written'
3555
- : !runnerStep
3556
- ? 'skipped'
3557
- : !runnerStep.result.ok
3558
- ? 'failed'
3559
- : (template && template !== 'launchd' && template !== 'systemd')
3560
- ? 'template_printed_not_started'
3561
- : 'written_not_started';
3562
- const installerSource = installStep.result.source || 'unknown';
3563
-
3564
- console.log('PingAgent Host Bootstrap');
3565
- console.log('========================');
3566
- console.log(`install=${formatStepStatus(installStep)}`);
3567
- console.log(`hooks_repair=${formatStepStatus(hooksStep)}`);
3568
- console.log(`runtime_verify=${formatStepStatus(verifyStep)}`);
3569
- console.log(`installer_source=${installerSource}`);
3570
- console.log(`runner=${runnerStatus}`);
3571
- console.log(`host_panel_url=${getHostPanelSurfaceUrl()}`);
3572
- console.log('host_panel_started_by_bootstrap=false');
3573
- console.log('host_panel_start=npx @pingagent/sdk web');
3574
- console.log('host_panel_start_local=pingagent web');
3575
- console.log('tui=npx @pingagent/sdk host tui');
3576
- console.log('tui_local=pingagent host tui');
3577
- console.log('');
3578
- console.log('Control surfaces:');
3579
- for (const line of getSurfaceRecommendationLines('npx @pingagent/sdk', 'pingagent')) console.log(line);
3580
- console.log('');
3581
- if (!opts.write) {
3582
- console.log('Next steps:');
3583
- console.log(' Bootstrap validates and repairs config, but it does not start long-lived daemons.');
3584
- console.log(' Start the Host Panel now with: npx @pingagent/sdk web (or pingagent web)');
3585
- console.log(' Use the headless surface now with: npx @pingagent/sdk host tui (or pingagent host tui)');
3586
- console.log(` Re-run with: npx @pingagent/sdk host bootstrap --write${template ? ` --template ${template}` : ''}`);
3587
- console.log(' Manual path: npx @pingagent/openclaw-install init-runner --ingress --panel');
3588
- } else if (runnerStep?.result.ok) {
3589
- console.log('Next steps:');
3590
- console.log(' Runner files/templates were generated, but bootstrap did not start those services.');
3591
- if (!template || template === 'launchd' || template === 'systemd') {
3592
- console.log(' Follow the printed launchctl/systemctl instructions to start them.');
3593
- } else {
3594
- console.log(' Start the generated runner with your chosen process manager.');
3569
+ if (!failed) {
3570
+ console.log('');
3571
+ console.log('Compatibility surfaces:');
3572
+ for (const line of getSurfaceRecommendationLines('npx @pingagent/sdk', 'pingagent')) console.log(line);
3573
+ if (opts.write && runnerStep?.result.ok) {
3574
+ console.log('');
3575
+ console.log('runner_files=written');
3595
3576
  }
3596
3577
  }
3597
3578
 
3598
3579
  if (failed) {
3599
- const stdout = failed.result.stdout.trim();
3600
- const stderr = failed.result.stderr.trim();
3601
3580
  console.error('');
3602
- console.error(`Bootstrap failed during ${failed.label}.`);
3603
- if (stdout) console.error(stdout);
3604
- if (stderr) console.error(stderr);
3581
+ console.error(`Bootstrap alias failed during ${failed.label}.`);
3605
3582
  process.exit(1);
3606
3583
  }
3607
3584
  }
@@ -3612,7 +3589,7 @@ const host = program
3612
3589
 
3613
3590
  host
3614
3591
  .command('bootstrap')
3615
- .description('Run the idempotent OpenClaw activation flow and print the recommended Host Panel / TUI surfaces')
3592
+ .description('Compatibility alias for the OpenClaw activation flow. Prefer npx @pingagent/openclaw-install.')
3616
3593
  .option('--write', 'Write launchd/systemd runner files when supported')
3617
3594
  .option('--template <name>', 'Runner template: launchd, systemd, docker, pm2, or supervisord')
3618
3595
  .action(async (opts) => {
@@ -3621,7 +3598,7 @@ host
3621
3598
 
3622
3599
  host
3623
3600
  .command('tui')
3624
- .description('Start the headless / low-token terminal UI for runtime, sessions, chat links, and repair actions')
3601
+ .description('Start the headless terminal repair / audit / approval surface for OpenClaw hosts')
3625
3602
  .option('--once', 'Print one snapshot and exit')
3626
3603
  .option('--refresh-ms <ms>', 'Refresh interval in interactive mode', '2000')
3627
3604
  .option('--profile <name>', 'Use profile from ~/.pingagent/<name>')
@@ -3636,7 +3613,7 @@ host
3636
3613
 
3637
3614
  program
3638
3615
  .command('web')
3639
- .description('Start the Host Panel, the primary GUI surface for runtime inspection, trust policy, and repair. Use pingagent host tui for headless or low-token operation.')
3616
+ .description('Start the Host Panel GUI for repair, audit, approvals, and advanced runtime inspection. Use pingagent host tui for headless operation.')
3640
3617
  .option('--port <port>', 'Port for the web server', '3846')
3641
3618
  .action(async (opts) => {
3642
3619
  const serverUrl = process.env.PINGAGENT_SERVER_URL || DEFAULT_SERVER;