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 +28 -2
- package/package.json +1 -1
- package/src/lib/conversation-driver.js +82 -4
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
|
-
|
|
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
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
}
|