a2acalling 0.2.2 โ 0.3.1
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 +9 -9
- 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 +17 -17
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,
|
|
@@ -256,7 +256,7 @@ https://github.com/onthegonow/a2a_calling`;
|
|
|
256
256
|
let permBadge = '';
|
|
257
257
|
if (r.linked_token) {
|
|
258
258
|
const tier = r.linked_token.tier || r.linked_token.permissions;
|
|
259
|
-
permBadge = tier === '
|
|
259
|
+
permBadge = tier === 'family' ? ' โก' : tier === 'friends' ? ' ๐ง' : ' ๐';
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
console.log(`${statusIcon} ${r.name}${ownerText}${permBadge}`);
|
|
@@ -270,7 +270,7 @@ https://github.com/onthegonow/a2a_calling`;
|
|
|
270
270
|
console.log();
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
console.log('Legend: ๐
|
|
273
|
+
console.log('Legend: ๐ public ๐ง friends โก family');
|
|
274
274
|
},
|
|
275
275
|
|
|
276
276
|
'contacts:add': (args) => {
|
|
@@ -343,7 +343,7 @@ https://github.com/onthegonow/a2a_calling`;
|
|
|
343
343
|
const t = remote.linked_token;
|
|
344
344
|
const tier = t.tier || t.permissions;
|
|
345
345
|
const topics = t.allowed_topics || ['chat'];
|
|
346
|
-
const tierIcon = tier === '
|
|
346
|
+
const tierIcon = tier === 'family' ? 'โก' : tier === 'friends' ? '๐ง' : '๐';
|
|
347
347
|
console.log(`๐ Your token to them: ${t.id}`);
|
|
348
348
|
console.log(` Tier: ${tierIcon} ${tier}`);
|
|
349
349
|
console.log(` Topics: ${topics.join(', ')}`);
|
|
@@ -432,8 +432,8 @@ https://github.com/onthegonow/a2a_calling`;
|
|
|
432
432
|
process.exit(1);
|
|
433
433
|
}
|
|
434
434
|
|
|
435
|
-
const permLabel = result.token.
|
|
436
|
-
result.token.
|
|
435
|
+
const permLabel = result.token.tier === 'family' ? 'โก family' :
|
|
436
|
+
result.token.tier === 'friends' ? '๐ง friends' : '๐ public';
|
|
437
437
|
|
|
438
438
|
console.log(`โ
Linked token to contact`);
|
|
439
439
|
console.log(` Contact: ${result.remote.name}`);
|
|
@@ -770,7 +770,7 @@ https://github.com/onthegonow/a2a_calling`;
|
|
|
770
770
|
name,
|
|
771
771
|
owner,
|
|
772
772
|
expires: '7d',
|
|
773
|
-
permissions: '
|
|
773
|
+
permissions: 'public',
|
|
774
774
|
maxCalls: 100
|
|
775
775
|
});
|
|
776
776
|
|
|
@@ -823,7 +823,7 @@ Commands:
|
|
|
823
823
|
--name, -n Token/agent name
|
|
824
824
|
--owner, -o Owner name (human behind the agent)
|
|
825
825
|
--expires, -e Expiration (1h, 1d, 7d, 30d, never)
|
|
826
|
-
--permissions, -p Tier (
|
|
826
|
+
--permissions, -p Tier (public, friends, family)
|
|
827
827
|
--topics Custom topics (comma-separated, overrides tier defaults)
|
|
828
828
|
--disclosure, -d Disclosure level (public, minimal, none)
|
|
829
829
|
--notify Owner notification (all, summary, none)
|
|
@@ -847,7 +847,7 @@ Contacts:
|
|
|
847
847
|
contacts ping <n> Ping contact, update status
|
|
848
848
|
contacts rm <n> Remove contact
|
|
849
849
|
|
|
850
|
-
Permission badges: ๐
|
|
850
|
+
Permission badges: ๐ public ๐ง friends โก family
|
|
851
851
|
|
|
852
852
|
Conversations:
|
|
853
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,21 +84,22 @@ function parseTopicObjects(values) {
|
|
|
84
84
|
return cleaned;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
function
|
|
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
|
-
function formatInviteMessage({ owner, agentName, inviteUrl, topics, expiresText }) {
|
|
87
|
+
function formatInviteMessage({ owner, agentName, inviteUrl, topics, goals, expiresText }) {
|
|
98
88
|
const ownerText = owner || 'Someone';
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
|
|
89
|
+
const topicsList = topics.length > 0 ? topics.join(' ยท ') : 'chat';
|
|
90
|
+
const goalsList = (goals || []).join(' ยท ');
|
|
91
|
+
const expirationLine = expiresText === 'never' ? '' : `\nโฐ ${expiresText}`;
|
|
92
|
+
return `๐๐ฃ๏ธ **Agent-to-Agent Call Invite**
|
|
93
|
+
|
|
94
|
+
๐ค **${ownerText}** would like your agent to call **${agentName}** and explore where our owners might collaborate.
|
|
95
|
+
|
|
96
|
+
๐ฌ ${topicsList}${goalsList ? `\n๐ฏ ${goalsList}` : ''}
|
|
97
|
+
|
|
98
|
+
${inviteUrl}${expirationLine}
|
|
99
|
+
|
|
100
|
+
โโ setup โโ
|
|
101
|
+
npm i -g a2acalling && a2a add "${inviteUrl}" "${agentName}" && a2a call "${agentName}" "Hello from my owner!"
|
|
102
|
+
https://github.com/onthegonow/a2a_calling`;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
function buildContext(options = {}) {
|
|
@@ -485,13 +486,11 @@ function createDashboardApiRouter(options = {}) {
|
|
|
485
486
|
|
|
486
487
|
const allowedTopics = sanitizeStringArray(body.topics || tier.topics || []);
|
|
487
488
|
const allowedGoals = sanitizeStringArray(body.goals || tier.goals || []);
|
|
488
|
-
const permission = inferPermissionForTier(tierId);
|
|
489
|
-
|
|
490
489
|
const { token, record } = context.tokenStore.create({
|
|
491
490
|
name,
|
|
492
491
|
owner,
|
|
493
492
|
expires,
|
|
494
|
-
permissions:
|
|
493
|
+
permissions: tierId,
|
|
495
494
|
disclosure,
|
|
496
495
|
notify,
|
|
497
496
|
maxCalls,
|
|
@@ -511,6 +510,7 @@ function createDashboardApiRouter(options = {}) {
|
|
|
511
510
|
agentName: name,
|
|
512
511
|
inviteUrl,
|
|
513
512
|
topics: record.allowed_topics || [],
|
|
513
|
+
goals: record.allowed_goals || [],
|
|
514
514
|
expiresText
|
|
515
515
|
});
|
|
516
516
|
|