@pingagent/sdk 0.1.1 → 0.1.2

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
@@ -756,15 +756,118 @@ program
756
756
  }
757
757
  });
758
758
 
759
- // === Conversations (local history management) ===
760
- const conversations = program.command('conversations').description('Manage conversation local history');
759
+ // === Conversations (local history management + server view) ===
760
+ const conversations = program.command('conversations').description('Manage conversations (local history and server-side metadata)');
761
+
762
+ conversations
763
+ .command('list')
764
+ .description('List server conversations for the current identity (optionally by profile). Use --type pending_dm to see only pending contact requests.')
765
+ .option('--profile <name>', 'Use profile from ~/.pingagent/<name>')
766
+ .option('--type <dm|pending_dm|all>', 'Filter: dm (established only), pending_dm (waiting for approval), or all (default)', 'all')
767
+ .option('--json', 'Output as JSON')
768
+ .action(async (opts = {}) => {
769
+ const identityPath = getIdentityPathForCommand(opts);
770
+ if (!identityExists(identityPath)) {
771
+ console.error('No identity found. Run: pingagent init (or use --identity-dir / --profile / PINGAGENT_IDENTITY_PATH)');
772
+ process.exit(1);
773
+ }
774
+ const client = await getClient(identityPath);
775
+ const typeArg = opts.type === 'pending_dm' ? 'pending_dm' : opts.type === 'dm' ? 'dm' : undefined;
776
+ const res = await client.listConversations(typeArg ? { type: typeArg } : undefined);
777
+ const convos = res.ok && res.data?.conversations ? res.data.conversations : [];
778
+ const raw = program.opts().raw;
779
+ if (opts.json) {
780
+ console.log(JSON.stringify({ ok: res.ok, conversations: convos }, null, 2));
781
+ } else if (!res.ok) {
782
+ if (res.error) printError(res.error);
783
+ else console.error('Failed to list conversations');
784
+ process.exit(1);
785
+ } else if (convos.length === 0) {
786
+ const hint = typeArg === 'pending_dm'
787
+ ? 'No pending contact requests.'
788
+ : 'No conversations. Send a message (pingagent chat --to <did>) or approve a contact request first.';
789
+ console.log(hint);
790
+ } else {
791
+ for (const c of convos) {
792
+ const ts = c.last_message_ts_ms != null ? formatTs(c.last_message_ts_ms, raw) : '-';
793
+ const target = c.target_did?.slice(0, 30) ?? '?';
794
+ console.log(` ${c.conversation_id} ${c.trusted ? 'ready' : 'pending'} last: ${ts} target: ${target}`);
795
+ }
796
+ console.log(`\n${convos.length} conversation(s)`);
797
+ }
798
+ });
799
+
800
+ conversations
801
+ .command('show')
802
+ .description('Show details and recent messages for a conversation')
803
+ .option('--profile <name>', 'Use profile from ~/.pingagent/<name>')
804
+ .argument('<conversation_id>', 'Conversation ID')
805
+ .option('--limit <n>', 'Number of recent messages to fetch', '20')
806
+ .option('--json', 'Output as JSON')
807
+ .action(async (conversationId, opts = {}) => {
808
+ const identityPath = getIdentityPathForCommand(opts);
809
+ if (!identityExists(identityPath)) {
810
+ console.error('No identity found. Run: pingagent init (or use --identity-dir / --profile / PINGAGENT_IDENTITY_PATH)');
811
+ process.exit(1);
812
+ }
813
+ const client = await getClient(identityPath);
814
+ const metaRes = await client.listConversations({ type: 'dm' });
815
+ const convo = metaRes.ok && metaRes.data?.conversations
816
+ ? metaRes.data.conversations.find(c => c.conversation_id === conversationId)
817
+ : null;
818
+ const limit = parseInt(opts.limit, 10) || 20;
819
+ const inboxRes = await client.fetchInbox(conversationId, { sinceSeq: 0, limit, box: 'all' });
820
+ const messages = inboxRes.ok && inboxRes.data?.messages ? inboxRes.data.messages : [];
821
+ const raw = program.opts().raw;
822
+
823
+ if (opts.json) {
824
+ console.log(JSON.stringify({
825
+ ok: metaRes.ok && inboxRes.ok,
826
+ conversation: convo ?? null,
827
+ messages,
828
+ }, null, 2));
829
+ return;
830
+ }
831
+
832
+ if (!inboxRes.ok) {
833
+ if (inboxRes.error) printError(inboxRes.error);
834
+ else console.error('Failed to fetch messages for conversation');
835
+ process.exit(1);
836
+ }
837
+
838
+ if (convo) {
839
+ console.log(`Conversation: ${convo.conversation_id}`);
840
+ console.log(`Type: ${convo.type}`);
841
+ console.log(`Trusted: ${convo.trusted}`);
842
+ console.log(`Target DID: ${convo.target_did ?? '-'}`);
843
+ if (convo.last_message_ts_ms != null) {
844
+ console.log(`Last message: ${formatTs(convo.last_message_ts_ms, raw)}`);
845
+ }
846
+ console.log('');
847
+ }
848
+
849
+ if (messages.length === 0) {
850
+ console.log('No messages found for this conversation.');
851
+ return;
852
+ }
853
+
854
+ for (const msg of messages) {
855
+ const ts = formatTs(msg.ts_ms, raw);
856
+ const from = msg.sender_did?.slice(0, 20) ?? '?';
857
+ const text = msg.payload?.text ?? msg.payload?.title ?? msg.schema;
858
+ console.log(` ${ts} [${msg.seq}] ${msg.schema} from ${from}... ${text}`);
859
+ }
860
+ console.log(`\n${messages.length} message(s)`);
861
+ });
761
862
 
762
863
  conversations
763
864
  .command('delete')
764
865
  .description('Delete local history for a conversation (server conversation unchanged)')
866
+ .option('--profile <name>', 'Use profile from ~/.pingagent/<name>')
765
867
  .argument('<conversation_id>', 'Conversation ID')
766
- .action((conversationId) => {
767
- const store = openStore();
868
+ .action((conversationId, opts = {}) => {
869
+ const identityPath = getIdentityPathForCommand(opts);
870
+ const store = openStore(identityPath);
768
871
  const mgr = new HistoryManager(store);
769
872
  const count = mgr.delete(conversationId);
770
873
  console.log(`Deleted ${count} message(s) for conversation ${conversationId}`);
@@ -774,9 +877,11 @@ conversations
774
877
  conversations
775
878
  .command('clear')
776
879
  .description('Clear all local history (use --force to skip confirmation)')
880
+ .option('--profile <name>', 'Use profile from ~/.pingagent/<name>')
777
881
  .option('--force', 'Skip confirmation')
778
- .action((opts) => {
779
- const store = openStore();
882
+ .action((opts = {}) => {
883
+ const identityPath = getIdentityPathForCommand(opts);
884
+ const store = openStore(identityPath);
780
885
  const mgr = new HistoryManager(store);
781
886
  const convos = mgr.listConversations();
782
887
  if (convos.length === 0) {