a2acalling 0.6.34 → 0.6.35

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/cli.js CHANGED
@@ -1123,6 +1123,22 @@ a2a add "${inviteUrl}" "${ownerText || 'friend'}" && a2a call "${ownerText || 'f
1123
1123
  const minTurns = parseInt(args.flags['min-turns']) || 8;
1124
1124
  const maxTurns = parseInt(args.flags['max-turns']) || 25;
1125
1125
 
1126
+ // Build owner context from config for summarizer
1127
+ let ownerContext = {};
1128
+ try {
1129
+ const { A2AConfig } = require('../src/lib/config');
1130
+ const config = new A2AConfig();
1131
+ const configAll = config.getAll();
1132
+ const tierGoals = configAll.tiers?.public?.goals || [];
1133
+ ownerContext = {
1134
+ goals: tierGoals,
1135
+ agentName: agentContext.name,
1136
+ ownerName: agentContext.owner
1137
+ };
1138
+ } catch (err) {
1139
+ // Best effort
1140
+ }
1141
+
1126
1142
  const driver = new ConversationDriver({
1127
1143
  runtime,
1128
1144
  agentContext,
@@ -1132,6 +1148,7 @@ a2a add "${inviteUrl}" "${ownerText || 'friend'}" && a2a call "${ownerText || 'f
1132
1148
  disclosure,
1133
1149
  minTurns,
1134
1150
  maxTurns,
1151
+ ownerContext,
1135
1152
  onTurn: (info) => {
1136
1153
  const preview = info.messagePreview.length >= 80
1137
1154
  ? info.messagePreview + '...'
@@ -1158,6 +1175,9 @@ a2a add "${inviteUrl}" "${ownerText || 'friend'}" && a2a call "${ownerText || 'f
1158
1175
  console.log(` Collaborations: ${result.collabState.candidateCollaborations.join(', ')}`);
1159
1176
  }
1160
1177
  console.log(` Conversation ID: ${result.conversationId}`);
1178
+ if (result.summary) {
1179
+ console.log(`\nšŸ“‹ Summary:\n${result.summary}`);
1180
+ }
1161
1181
  } catch (err) {
1162
1182
  if (contactName) {
1163
1183
  store.updateContactStatus(contactName, 'offline', err.message);
@@ -1755,6 +1775,8 @@ a2a add "${inviteUrl}" "${ownerText || 'friend'}" && a2a call "${ownerText || 'f
1755
1775
  const configFile = path.join(configDir, 'a2a-config.json');
1756
1776
  const disclosureFile = path.join(configDir, 'a2a-disclosure.json');
1757
1777
  const tokensFile = path.join(configDir, 'a2a-tokens.json');
1778
+ const tokenStoreFile = path.join(configDir, 'a2a.json');
1779
+ const externalIpFile = path.join(configDir, 'a2a-external-ip.json');
1758
1780
  const dbFile = path.join(configDir, 'a2a-conversations.db');
1759
1781
  const logsDbFile = path.join(configDir, 'a2a-logs.db');
1760
1782
  const callbookDbFile = path.join(configDir, 'a2a-callbook.db');
@@ -1768,7 +1790,7 @@ a2a add "${inviteUrl}" "${ownerText || 'friend'}" && a2a call "${ownerText || 'f
1768
1790
  process.exit(1);
1769
1791
  }
1770
1792
 
1771
- const existing = [configFile, disclosureFile, tokensFile, dbFile, logsDbFile, callbookDbFile].filter(f => fs.existsSync(f));
1793
+ const existing = [configFile, disclosureFile, tokensFile, tokenStoreFile, externalIpFile, dbFile, logsDbFile, callbookDbFile].filter(f => fs.existsSync(f));
1772
1794
  const list = existing.length ? existing.map(f => ` - ${f}`).join('\n') : ' (no local config/database files found)';
1773
1795
  const ok = await promptYesNo(
1774
1796
  `This will stop the pm2 process "a2a" and delete:\n${list}\nProceed? (y/N) `
@@ -1836,12 +1858,16 @@ a2a add "${inviteUrl}" "${ownerText || 'friend'}" && a2a call "${ownerText || 'f
1836
1858
  const c1 = rmFileSafe(configFile);
1837
1859
  const c2 = rmFileSafe(disclosureFile);
1838
1860
  const c3 = rmFileSafe(tokensFile);
1839
- configOk = Boolean(c1.ok && c2.ok && c3.ok);
1861
+ const c4 = rmFileSafe(tokenStoreFile);
1862
+ const c5 = rmFileSafe(externalIpFile);
1863
+ configOk = Boolean(c1.ok && c2.ok && c3.ok && c4.ok && c5.ok);
1840
1864
  console.log(configOk ? 'āœ…' : 'āŒ');
1841
1865
  if (!configOk) {
1842
1866
  if (!c1.ok) console.error(` ${configFile}: ${c1.error}`);
1843
1867
  if (!c2.ok) console.error(` ${disclosureFile}: ${c2.error}`);
1844
1868
  if (!c3.ok) console.error(` ${tokensFile}: ${c3.error}`);
1869
+ if (!c4.ok) console.error(` ${tokenStoreFile}: ${c4.error}`);
1870
+ if (!c5.ok) console.error(` ${externalIpFile}: ${c5.error}`);
1845
1871
  }
1846
1872
 
1847
1873
  process.stdout.write('Removing database... ');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "a2acalling",
3
- "version": "0.6.34",
3
+ "version": "0.6.35",
4
4
  "description": "Agent-to-agent calling for OpenClaw - A2A agent communication",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -36,6 +36,8 @@ class ConversationDriver {
36
36
  * @param {number} [options.maxTurns=30] - Maximum turns
37
37
  * @param {function} [options.onTurn] - Callback per turn: (turnInfo) => void
38
38
  * @param {string} [options.tier='public'] - Access tier
39
+ * @param {function} [options.summarizer] - async (messages, ownerContext) => summary result
40
+ * @param {object} [options.ownerContext] - Owner context for summarizer (goals, interests, etc.)
39
41
  */
40
42
  constructor(options) {
41
43
  this.runtime = options.runtime;
@@ -48,10 +50,75 @@ class ConversationDriver {
48
50
  this.maxTurns = options.maxTurns || 30;
49
51
  this.onTurn = options.onTurn || null;
50
52
  this.tier = options.tier || 'public';
53
+ this.summarizer = options.summarizer || null;
54
+ this.ownerContext = options.ownerContext || {};
51
55
 
52
56
  this.client = new A2AClient({ caller: this.caller, timeout: 65000 });
53
57
  }
54
58
 
59
+ /**
60
+ * Build a summarizer function from the runtime adapter.
61
+ * Mirrors server.js generateSummary — uses runtime.summarize when available,
62
+ * falls back to defaultSummarizer otherwise.
63
+ */
64
+ _buildSummarizer() {
65
+ const runtime = this.runtime;
66
+ const agentContext = this.agentContext;
67
+
68
+ return async (messages, ownerContext) => {
69
+ if (!messages || messages.length === 0) {
70
+ return { summary: null };
71
+ }
72
+
73
+ // Build the summary prompt (same structure as server.js generateSummary)
74
+ const messageText = messages.map(m => {
75
+ const role = m.direction === 'inbound' ? '[Them]' : '[You]';
76
+ return `${role}: ${m.content}`;
77
+ }).join('\n');
78
+
79
+ const prompt = `Summarize this A2A call for the owner. Write from the owner's perspective.
80
+
81
+ You initiated this call.
82
+
83
+ Conversation:
84
+ ${messageText}
85
+
86
+ Structure your summary with these sections:
87
+
88
+ **Who:** Who you called, who they represent, key facts about them.
89
+ **Key Discoveries:** What was learned about the other side — capabilities, interests, blind spots.
90
+ **Collaboration Potential:** Rate HIGH/MEDIUM/LOW. List specific opportunities identified.
91
+ **What We Learned vs Shared:** Brief information exchange audit — what did we get, what did we give.
92
+ **Recommended Follow-Up:**
93
+ - [ ] Actionable item 1
94
+ - [ ] Actionable item 2
95
+ **Assessment:** One-sentence strategic value judgment.
96
+
97
+ Be concise but specific. No filler.`;
98
+
99
+ // Try runtime.summarize if available (OpenClaw path)
100
+ if (typeof runtime.summarize === 'function') {
101
+ try {
102
+ return await runtime.summarize({
103
+ sessionId: `summary-${Date.now()}`,
104
+ prompt,
105
+ messages,
106
+ callerInfo: { name: agentContext.name, owner: agentContext.owner }
107
+ });
108
+ } catch (err) {
109
+ logger.warn('Runtime summarizer failed, using default', {
110
+ event: 'driver_runtime_summarize_failed',
111
+ error: err
112
+ });
113
+ }
114
+ }
115
+
116
+ // Fallback: use defaultSummarizer
117
+ const { defaultSummarizer } = require('./summarizer');
118
+ return defaultSummarizer(messages, ownerContext);
119
+ };
120
+ }
121
+
55
122
  /**
56
123
  * Run the full multi-turn conversation
57
124
  *
@@ -253,12 +320,22 @@ class ConversationDriver {
253
320
  });
254
321
  }
255
322
 
256
- // Conclude locally
323
+ // Conclude locally with summarizer
324
+ let summary = null;
257
325
  if (this.convStore) {
258
326
  try {
259
- await this.convStore.concludeConversation(conversationId);
327
+ const summarizer = this.summarizer || this._buildSummarizer();
328
+ const result = await this.convStore.concludeConversation(conversationId, {
329
+ summarizer,
330
+ ownerContext: this.ownerContext
331
+ });
332
+ summary = result.summary || null;
260
333
  } catch (err) {
261
- // Best effort
334
+ logger.warn('Failed to conclude local conversation', {
335
+ event: 'driver_conclude_failed',
336
+ error: err,
337
+ data: { conversationId }
338
+ });
262
339
  }
263
340
  }
264
341
 
@@ -266,7 +343,8 @@ class ConversationDriver {
266
343
  conversationId,
267
344
  turnCount: collabState.turnCount,
268
345
  collabState,
269
- transcript
346
+ transcript,
347
+ summary
270
348
  };
271
349
  }
272
350
  }