a2acalling 0.2.1 โ 0.3.0
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 +30 -38
- package/package.json +1 -1
- package/src/dashboard/public/app.js +1 -1
- package/src/lib/config.js +4 -4
- package/src/lib/tokens.js +39 -21
- package/src/routes/a2a.js +1 -0
- package/src/routes/dashboard.js +1 -13
package/bin/cli.js
CHANGED
|
@@ -99,7 +99,7 @@ const commands = {
|
|
|
99
99
|
name: args.flags.name || args.flags.n || 'unnamed',
|
|
100
100
|
owner: args.flags.owner || args.flags.o || null,
|
|
101
101
|
expires: args.flags.expires || args.flags.e || 'never',
|
|
102
|
-
permissions: args.flags.permissions || args.flags.p || '
|
|
102
|
+
permissions: args.flags.permissions || args.flags.p || 'public',
|
|
103
103
|
disclosure: args.flags.disclosure || args.flags.d || 'minimal',
|
|
104
104
|
notify: args.flags.notify || 'all',
|
|
105
105
|
maxCalls,
|
|
@@ -141,25 +141,23 @@ const commands = {
|
|
|
141
141
|
console.log(`${'โ'.repeat(50)}\n`);
|
|
142
142
|
|
|
143
143
|
// Generate shareable invite block
|
|
144
|
-
//
|
|
144
|
+
// Special invitation above the fold, agent setup below
|
|
145
145
|
const ownerText = record.owner || 'Someone';
|
|
146
146
|
const agentName = record.name;
|
|
147
|
-
const topicsList = record.allowed_topics.join('
|
|
148
|
-
|
|
149
|
-
const invite = `๐ค **${ownerText}** is inviting you to connect agents!
|
|
147
|
+
const topicsList = record.allowed_topics.join(' ยท ');
|
|
148
|
+
const goalsList = (record.allowed_goals || []).join(' ยท ');
|
|
150
149
|
|
|
151
|
-
|
|
150
|
+
const invite = `๐๐ฃ๏ธ **Agent-to-Agent Call Invite**
|
|
152
151
|
|
|
153
|
-
|
|
152
|
+
๐ค **${ownerText}** would like your agent to call **${agentName}** and explore where our owners might collaborate.
|
|
154
153
|
|
|
155
|
-
${
|
|
156
|
-
โโโ For your agent โโโ
|
|
154
|
+
๐ฌ ${topicsList}${goalsList ? `\n๐ฏ ${goalsList}` : ''}
|
|
157
155
|
|
|
158
|
-
|
|
159
|
-
a2a add "${inviteUrl}" "${agentName}"
|
|
160
|
-
a2a call "${agentName}" "Hello!"
|
|
156
|
+
${inviteUrl}${expiresText === 'never' ? '' : `\nโฐ ${expiresText}`}
|
|
161
157
|
|
|
162
|
-
|
|
158
|
+
โโ setup โโ
|
|
159
|
+
npm i -g a2acalling && a2a add "${inviteUrl}" "${agentName}" && a2a call "${agentName}" "Hello from my owner!"
|
|
160
|
+
https://github.com/onthegonow/a2a_calling`;
|
|
163
161
|
|
|
164
162
|
console.log(invite);
|
|
165
163
|
console.log(`\n${'โ'.repeat(50)}`);
|
|
@@ -258,7 +256,7 @@ a2a call "${agentName}" "Hello!"
|
|
|
258
256
|
let permBadge = '';
|
|
259
257
|
if (r.linked_token) {
|
|
260
258
|
const tier = r.linked_token.tier || r.linked_token.permissions;
|
|
261
|
-
permBadge = tier === '
|
|
259
|
+
permBadge = tier === 'family' ? ' โก' : tier === 'friends' ? ' ๐ง' : ' ๐';
|
|
262
260
|
}
|
|
263
261
|
|
|
264
262
|
console.log(`${statusIcon} ${r.name}${ownerText}${permBadge}`);
|
|
@@ -272,7 +270,7 @@ a2a call "${agentName}" "Hello!"
|
|
|
272
270
|
console.log();
|
|
273
271
|
}
|
|
274
272
|
|
|
275
|
-
console.log('Legend: ๐
|
|
273
|
+
console.log('Legend: ๐ public ๐ง friends โก family');
|
|
276
274
|
},
|
|
277
275
|
|
|
278
276
|
'contacts:add': (args) => {
|
|
@@ -345,7 +343,7 @@ a2a call "${agentName}" "Hello!"
|
|
|
345
343
|
const t = remote.linked_token;
|
|
346
344
|
const tier = t.tier || t.permissions;
|
|
347
345
|
const topics = t.allowed_topics || ['chat'];
|
|
348
|
-
const tierIcon = tier === '
|
|
346
|
+
const tierIcon = tier === 'family' ? 'โก' : tier === 'friends' ? '๐ง' : '๐';
|
|
349
347
|
console.log(`๐ Your token to them: ${t.id}`);
|
|
350
348
|
console.log(` Tier: ${tierIcon} ${tier}`);
|
|
351
349
|
console.log(` Topics: ${topics.join(', ')}`);
|
|
@@ -434,8 +432,8 @@ a2a call "${agentName}" "Hello!"
|
|
|
434
432
|
process.exit(1);
|
|
435
433
|
}
|
|
436
434
|
|
|
437
|
-
const permLabel = result.token.
|
|
438
|
-
result.token.
|
|
435
|
+
const permLabel = result.token.tier === 'family' ? 'โก family' :
|
|
436
|
+
result.token.tier === 'friends' ? '๐ง friends' : '๐ public';
|
|
439
437
|
|
|
440
438
|
console.log(`โ
Linked token to contact`);
|
|
441
439
|
console.log(` Contact: ${result.remote.name}`);
|
|
@@ -772,7 +770,7 @@ a2a call "${agentName}" "Hello!"
|
|
|
772
770
|
name,
|
|
773
771
|
owner,
|
|
774
772
|
expires: '7d',
|
|
775
|
-
permissions: '
|
|
773
|
+
permissions: 'public',
|
|
776
774
|
maxCalls: 100
|
|
777
775
|
});
|
|
778
776
|
|
|
@@ -782,30 +780,24 @@ a2a call "${agentName}" "Hello!"
|
|
|
782
780
|
});
|
|
783
781
|
|
|
784
782
|
// Step 3: Show the invite
|
|
785
|
-
const ownerText = owner ? `${owner}
|
|
783
|
+
const ownerText = owner ? `${owner}` : 'Someone';
|
|
784
|
+
const topicsList = record.allowed_topics.join(' ยท ');
|
|
785
|
+
const goalsList = (record.allowed_goals || []).join(' ยท ');
|
|
786
786
|
console.log('3๏ธโฃ Share this invite:\n');
|
|
787
787
|
console.log('โ'.repeat(50));
|
|
788
788
|
console.log(`
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
${ownerText} is inviting your agent to connect!
|
|
792
|
-
|
|
793
|
-
๐ก Connection URL:
|
|
794
|
-
${inviteUrl}
|
|
795
|
-
|
|
796
|
-
โฐ Expires: ${expiresText}
|
|
797
|
-
๐ Permissions: chat-only
|
|
798
|
-
๐ Limits: 100 calls, 10/min rate limit
|
|
789
|
+
๐๐ฃ๏ธ **Agent-to-Agent Call Invite**
|
|
799
790
|
|
|
800
|
-
|
|
791
|
+
๐ค **${ownerText}** would like your agent to call **${name}** and explore where our owners might collaborate.
|
|
801
792
|
|
|
802
|
-
|
|
793
|
+
๐ฌ ${topicsList}${goalsList ? `\n๐ฏ ${goalsList}` : ''}
|
|
803
794
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
3. Call: a2a call "${inviteUrl}" "Hello!"
|
|
795
|
+
${inviteUrl}
|
|
796
|
+
โฐ ${expiresText}
|
|
807
797
|
|
|
808
|
-
|
|
798
|
+
โโ setup โโ
|
|
799
|
+
npm i -g a2acalling && a2a add "${inviteUrl}" "${name}" && a2a call "${name}" "Hello from my owner!"
|
|
800
|
+
https://github.com/onthegonow/a2a_calling
|
|
809
801
|
`);
|
|
810
802
|
console.log('โ'.repeat(50));
|
|
811
803
|
console.log(`\nโ
Done! Share the invite above with other agents.\n`);
|
|
@@ -831,7 +823,7 @@ Commands:
|
|
|
831
823
|
--name, -n Token/agent name
|
|
832
824
|
--owner, -o Owner name (human behind the agent)
|
|
833
825
|
--expires, -e Expiration (1h, 1d, 7d, 30d, never)
|
|
834
|
-
--permissions, -p Tier (
|
|
826
|
+
--permissions, -p Tier (public, friends, family)
|
|
835
827
|
--topics Custom topics (comma-separated, overrides tier defaults)
|
|
836
828
|
--disclosure, -d Disclosure level (public, minimal, none)
|
|
837
829
|
--notify Owner notification (all, summary, none)
|
|
@@ -855,7 +847,7 @@ Contacts:
|
|
|
855
847
|
contacts ping <n> Ping contact, update status
|
|
856
848
|
contacts rm <n> Remove contact
|
|
857
849
|
|
|
858
|
-
Permission badges: ๐
|
|
850
|
+
Permission badges: ๐ public ๐ง friends โก family
|
|
859
851
|
|
|
860
852
|
Conversations:
|
|
861
853
|
conversations List all conversations
|
package/package.json
CHANGED
|
@@ -272,7 +272,7 @@ function renderInvites() {
|
|
|
272
272
|
tr.innerHTML = `
|
|
273
273
|
<td>${invite.id}</td>
|
|
274
274
|
<td>${invite.name || '-'}</td>
|
|
275
|
-
<td>${invite.
|
|
275
|
+
<td>${invite.tier || '-'}</td>
|
|
276
276
|
<td>${invite.calls_made || 0}${invite.max_calls ? `/${invite.max_calls}` : ''}</td>
|
|
277
277
|
<td>${fmtDate(invite.expires_at)}</td>
|
|
278
278
|
<td>${invite.revoked ? 'revoked' : 'active'}</td>
|
package/src/lib/config.js
CHANGED
|
@@ -22,7 +22,7 @@ const DEFAULT_CONFIG = {
|
|
|
22
22
|
public: {
|
|
23
23
|
name: 'Public',
|
|
24
24
|
description: 'Basic networking - safe for anyone',
|
|
25
|
-
capabilities: [],
|
|
25
|
+
capabilities: ['context-read'],
|
|
26
26
|
topics: [],
|
|
27
27
|
goals: [],
|
|
28
28
|
disclosure: 'minimal',
|
|
@@ -31,7 +31,7 @@ const DEFAULT_CONFIG = {
|
|
|
31
31
|
friends: {
|
|
32
32
|
name: 'Friends',
|
|
33
33
|
description: 'Most capabilities, no sensitive financial data',
|
|
34
|
-
capabilities: [],
|
|
34
|
+
capabilities: ['context-read', 'calendar.read', 'email.read', 'search'],
|
|
35
35
|
topics: [],
|
|
36
36
|
goals: [],
|
|
37
37
|
disclosure: 'public',
|
|
@@ -40,7 +40,7 @@ const DEFAULT_CONFIG = {
|
|
|
40
40
|
private: {
|
|
41
41
|
name: 'Private',
|
|
42
42
|
description: 'Full access - only for you',
|
|
43
|
-
capabilities: [],
|
|
43
|
+
capabilities: ['context-read', 'calendar', 'email', 'search', 'tools', 'memory'],
|
|
44
44
|
topics: [],
|
|
45
45
|
goals: [],
|
|
46
46
|
disclosure: 'public',
|
|
@@ -49,7 +49,7 @@ const DEFAULT_CONFIG = {
|
|
|
49
49
|
custom: {
|
|
50
50
|
name: 'Custom',
|
|
51
51
|
description: 'User-defined permissions',
|
|
52
|
-
capabilities: [],
|
|
52
|
+
capabilities: ['context-read'],
|
|
53
53
|
topics: [],
|
|
54
54
|
goals: [],
|
|
55
55
|
disclosure: 'minimal',
|
package/src/lib/tokens.js
CHANGED
|
@@ -90,16 +90,20 @@ class TokenStore {
|
|
|
90
90
|
name = 'unnamed',
|
|
91
91
|
owner = null,
|
|
92
92
|
expires = '1d',
|
|
93
|
-
permissions = '
|
|
93
|
+
permissions = 'public',
|
|
94
94
|
disclosure = 'minimal',
|
|
95
95
|
notify = 'all',
|
|
96
96
|
maxCalls = 100, // Default limit, not unlimited
|
|
97
|
+
capabilities = null, // Array of capability strings, snapshotted at creation
|
|
97
98
|
// Snapshot of actual capabilities at creation time
|
|
98
99
|
allowedTopics = null, // Array of topic strings, e.g. ['chat', 'calendar.read']
|
|
99
100
|
allowedGoals = null, // Array of goal strings, e.g. ['grow-network', 'find-collaborators']
|
|
100
101
|
tierSettings = null // Object with tier-specific settings
|
|
101
102
|
} = options;
|
|
102
103
|
|
|
104
|
+
// Map legacy tier values to labels
|
|
105
|
+
const tier = TokenStore.LEGACY_TIER_MAP[permissions] || permissions;
|
|
106
|
+
|
|
103
107
|
const token = TokenStore.generateToken();
|
|
104
108
|
const tokenHash = TokenStore.hashToken(token);
|
|
105
109
|
const durationMs = TokenStore.parseDuration(expires);
|
|
@@ -119,34 +123,25 @@ class TokenStore {
|
|
|
119
123
|
// Config not available, use defaults
|
|
120
124
|
}
|
|
121
125
|
|
|
122
|
-
// Default topics based on
|
|
126
|
+
// Default topics based on tier label (snapshot at creation)
|
|
123
127
|
// User config overrides these defaults
|
|
124
128
|
const defaultTopics = {
|
|
125
|
-
'chat-only': ['chat'],
|
|
126
129
|
'public': configTiers.public?.topics || ['chat'],
|
|
127
|
-
'tools-read': ['chat', 'calendar.read', 'email.read', 'search'],
|
|
128
130
|
'friends': configTiers.friends?.topics || ['chat', 'calendar.read', 'email.read', 'search'],
|
|
129
|
-
'tools-write': ['chat', 'calendar', 'email', 'search', 'tools'],
|
|
130
131
|
'family': configTiers.family?.topics || ['chat', 'calendar', 'email', 'search', 'tools']
|
|
131
132
|
};
|
|
132
133
|
|
|
133
|
-
// Default goals based on
|
|
134
|
+
// Default goals based on tier label (snapshot at creation)
|
|
134
135
|
const defaultGoals = {
|
|
135
|
-
'chat-only': [],
|
|
136
136
|
'public': configTiers.public?.goals || [],
|
|
137
|
-
'tools-read': [],
|
|
138
137
|
'friends': configTiers.friends?.goals || [],
|
|
139
|
-
'tools-write': [],
|
|
140
138
|
'family': configTiers.family?.goals || []
|
|
141
139
|
};
|
|
142
140
|
|
|
143
|
-
//
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
'family': 'tools-write'
|
|
148
|
-
};
|
|
149
|
-
const normalizedTier = tierAliases[permissions] || permissions;
|
|
141
|
+
// Resolve capabilities: explicit > config > defaults
|
|
142
|
+
const defaultCapabilities = (configTiers[tier]?.capabilities?.length)
|
|
143
|
+
? configTiers[tier].capabilities
|
|
144
|
+
: (TokenStore.DEFAULT_CAPABILITIES[tier] || ['context-read']);
|
|
150
145
|
|
|
151
146
|
// Use separate random ID (not derived from token) to prevent prefix attacks
|
|
152
147
|
const record = {
|
|
@@ -154,10 +149,10 @@ class TokenStore {
|
|
|
154
149
|
token_hash: tokenHash,
|
|
155
150
|
name,
|
|
156
151
|
owner,
|
|
157
|
-
tier
|
|
158
|
-
|
|
159
|
-
allowed_topics: allowedTopics || defaultTopics[
|
|
160
|
-
allowed_goals: allowedGoals || defaultGoals[
|
|
152
|
+
tier,
|
|
153
|
+
capabilities: capabilities || defaultCapabilities,
|
|
154
|
+
allowed_topics: allowedTopics || defaultTopics[tier] || ['chat'],
|
|
155
|
+
allowed_goals: allowedGoals || defaultGoals[tier] || [],
|
|
161
156
|
tier_settings: tierSettings || {}, // Snapshot of settings at creation
|
|
162
157
|
disclosure,
|
|
163
158
|
notify,
|
|
@@ -220,11 +215,20 @@ class TokenStore {
|
|
|
220
215
|
record.last_used = new Date().toISOString();
|
|
221
216
|
this._save(db);
|
|
222
217
|
|
|
218
|
+
// Map legacy tier values to labels for old records
|
|
219
|
+
const tier = TokenStore.LEGACY_TIER_MAP[record.tier] || record.tier || record.permissions || 'public';
|
|
220
|
+
|
|
221
|
+
// Resolve capabilities: stored > defaults
|
|
222
|
+
const capabilities = record.capabilities
|
|
223
|
+
|| TokenStore.DEFAULT_CAPABILITIES[tier]
|
|
224
|
+
|| ['context-read'];
|
|
225
|
+
|
|
223
226
|
return {
|
|
224
227
|
valid: true,
|
|
225
228
|
id: record.id,
|
|
226
229
|
name: record.name,
|
|
227
|
-
tier
|
|
230
|
+
tier,
|
|
231
|
+
capabilities,
|
|
228
232
|
allowed_topics: record.allowed_topics || ['chat'],
|
|
229
233
|
allowed_goals: record.allowed_goals || [],
|
|
230
234
|
tier_settings: record.tier_settings || {},
|
|
@@ -458,4 +462,18 @@ class TokenStore {
|
|
|
458
462
|
}
|
|
459
463
|
}
|
|
460
464
|
|
|
465
|
+
// Legacy tier values from old records โ label mapping
|
|
466
|
+
TokenStore.LEGACY_TIER_MAP = {
|
|
467
|
+
'chat-only': 'public',
|
|
468
|
+
'tools-read': 'friends',
|
|
469
|
+
'tools-write': 'family'
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// Default capabilities per tier label (used when config has none)
|
|
473
|
+
TokenStore.DEFAULT_CAPABILITIES = {
|
|
474
|
+
'public': ['context-read'],
|
|
475
|
+
'friends': ['context-read', 'calendar.read', 'email.read', 'search'],
|
|
476
|
+
'family': ['context-read', 'calendar', 'email', 'search', 'tools', 'memory']
|
|
477
|
+
};
|
|
478
|
+
|
|
461
479
|
module.exports = { TokenStore };
|
package/src/routes/a2a.js
CHANGED
|
@@ -229,6 +229,7 @@ function createRoutes(options = {}) {
|
|
|
229
229
|
token_id: validation.id,
|
|
230
230
|
token_name: validation.name,
|
|
231
231
|
tier: validation.tier,
|
|
232
|
+
capabilities: validation.capabilities,
|
|
232
233
|
allowed_topics: validation.allowed_topics,
|
|
233
234
|
disclosure: validation.disclosure,
|
|
234
235
|
caller: sanitizedCaller,
|
package/src/routes/dashboard.js
CHANGED
|
@@ -84,16 +84,6 @@ function parseTopicObjects(values) {
|
|
|
84
84
|
return cleaned;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
function inferPermissionForTier(tierId) {
|
|
88
|
-
const alias = {
|
|
89
|
-
public: 'chat-only',
|
|
90
|
-
friends: 'tools-read',
|
|
91
|
-
family: 'tools-write',
|
|
92
|
-
private: 'tools-write'
|
|
93
|
-
};
|
|
94
|
-
return alias[tierId] || tierId;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
87
|
function formatInviteMessage({ owner, agentName, inviteUrl, topics, expiresText }) {
|
|
98
88
|
const ownerText = owner || 'Someone';
|
|
99
89
|
const topicsText = topics.length > 0 ? topics.join(', ') : 'chat';
|
|
@@ -485,13 +475,11 @@ function createDashboardApiRouter(options = {}) {
|
|
|
485
475
|
|
|
486
476
|
const allowedTopics = sanitizeStringArray(body.topics || tier.topics || []);
|
|
487
477
|
const allowedGoals = sanitizeStringArray(body.goals || tier.goals || []);
|
|
488
|
-
const permission = inferPermissionForTier(tierId);
|
|
489
|
-
|
|
490
478
|
const { token, record } = context.tokenStore.create({
|
|
491
479
|
name,
|
|
492
480
|
owner,
|
|
493
481
|
expires,
|
|
494
|
-
permissions:
|
|
482
|
+
permissions: tierId,
|
|
495
483
|
disclosure,
|
|
496
484
|
notify,
|
|
497
485
|
maxCalls,
|