@volter/teams 0.1.50 → 0.1.52
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/browser-channel.d.ts +1 -1
- package/machine-core.mjs +1 -1
- package/package.json +1 -1
- package/server/delegated.mjs +2 -1
- package/server/machine-link.mjs +2 -2
- package/session-follow.mjs +1 -1
package/browser-channel.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export function sendBrowserTurn(channel: BrowserChannel, text: string, options?:
|
|
|
54
54
|
|
|
55
55
|
export interface MailHistoryEntry {
|
|
56
56
|
id: string; from: string; fromName: string; to: string; text: string; at: number;
|
|
57
|
-
direction: 'in' | 'out'; inReplyTo: string | null; delivery: string;
|
|
57
|
+
subject?: string | null; direction: 'in' | 'out'; inReplyTo: string | null; delivery: string;
|
|
58
58
|
fromActor?: MailActor; toActor?: MailActor;
|
|
59
59
|
}
|
|
60
60
|
/** The existing native identity resolved by supercode, not the return mailbox. */
|
package/machine-core.mjs
CHANGED
|
@@ -244,7 +244,7 @@ export class MachineCore extends EventEmitter {
|
|
|
244
244
|
}
|
|
245
245
|
const index = this.nextConnection++;
|
|
246
246
|
// A delegated caller's claim also carries the name its workplace signed for it (who typed a turn).
|
|
247
|
-
const entry = { channel, admitted, principal: claim.principal, name: typeof claim.name === 'string' ? claim.name : null, verify: () => this.#admitClaim(claim), localAdmission: () => admitFromGrants(claim, { custodianId: this.custodianId, grants: this.linkGrants }) };
|
|
247
|
+
const entry = { channel, admitted, principal: claim.principal, name: typeof claim.name === 'string' ? claim.name : null, roomContext: claim.roomContext ?? null, verify: () => this.#admitClaim(claim), localAdmission: () => admitFromGrants(claim, { custodianId: this.custodianId, grants: this.linkGrants }) };
|
|
248
248
|
this.connections.set(index, entry);
|
|
249
249
|
stream.on('close', () => { this.connections.delete(index); this.connectionClosed(index); });
|
|
250
250
|
this.log.append({ principal: entry.principal, cap: 'connect', target: '*', outcome: admitted.class, detail: 'server' });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/teams",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.52",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Volter Teams, the neutral team plane: machine identity and daemon core, the local door and server link, admission from machine grants, product doors, and the Teams server's neutral routes (company RFC 0008).",
|
|
6
6
|
"license": "MIT",
|
package/server/delegated.mjs
CHANGED
|
@@ -102,7 +102,8 @@ export async function delegatedSessionOf(api, token) {
|
|
|
102
102
|
// The member's name as the workplace knows it: who the session is told typed a turn. From the signed token, never
|
|
103
103
|
// from what the browser sends.
|
|
104
104
|
const name = typeof claims.name === 'string' && claims.name.trim() ? claims.name.trim().slice(0, 80) : null;
|
|
105
|
-
|
|
105
|
+
const roomContext = claims.roomContext === false ? null : { id: claims.room, name: typeof claims.roomName === 'string' ? claims.roomName.slice(0, 120) : claims.room, sender: claims.sub };
|
|
106
|
+
return { roomContext, conversation: claims.conversation, expiresAt: claims.exp * 1000, issuer: claims.iss, name, room: claims.room, scope: claims.scope, sessionRef: session.id, subject: claims.sub, teamId: session.team };
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
/** A token's claims when it is one this server trusts: signed by the issuer's key, for this server, in its lifetime. */
|
package/server/machine-link.mjs
CHANGED
|
@@ -56,7 +56,7 @@ export async function machineGrantRows(api, teamId, machineId) {
|
|
|
56
56
|
async function claimFor(api, auth, machineId) {
|
|
57
57
|
if (auth.kind === 'delegated') {
|
|
58
58
|
const row = await api.store.one('SELECT id, revision FROM machine_grants WHERE team_id=? AND machine_id=? AND id=? AND expires_at>?', [auth.team_id, machineId, auth.grant_id, api.clock.nowMs()]);
|
|
59
|
-
return row ? { principal: auth.principal_id, groups: [], grants: [row.id], revisions: { [row.id]: row.revision }, ...(auth.name ? { name: auth.name } : {}) } : null;
|
|
59
|
+
return row ? { principal: auth.principal_id, groups: [], grants: [row.id], revisions: { [row.id]: row.revision }, ...(auth.name ? { name: auth.name } : {}), ...(auth.roomContext ? { roomContext: auth.roomContext } : {}) } : null;
|
|
60
60
|
}
|
|
61
61
|
const machine = await api.store.one('SELECT custodian_id FROM machines WHERE team_id=? AND id=? AND revoked_at IS NULL', [auth.team_id, machineId]);
|
|
62
62
|
if (!machine) return null;
|
|
@@ -231,7 +231,7 @@ async function delegatedSessionChannel(api, teamId, sessionRef, token) {
|
|
|
231
231
|
{ sql: "DELETE FROM machine_grants WHERE team_id=? AND issuer_id LIKE 'delegated:%' AND expires_at<=?", params: [teamId, now] },
|
|
232
232
|
{ sql: 'INSERT INTO machine_grants(team_id,id,machine_id,subject_id,caps_json,targets_json,issuer_id,created_at,expires_at) VALUES (?,?,?,?,?,?,?,?,?)', params: [teamId, id, target.machineId, principal, JSON.stringify(access.scope === 'control' ? ['observe', 'interact'] : ['observe']), JSON.stringify([`session:${target.harness}/${target.nativeId}`]), issuer, now, access.expiresAt] },
|
|
233
233
|
]).catch((error) => { if (error.code !== 'not_found') throw error; return null; });
|
|
234
|
-
return { door: 'channel', teamId, machineId: target.machineId, auth: { kind: 'delegated', team_id: teamId, principal_id: principal, group_ids: [], grant_id: id, grant_issuer: issuer, expires_at: access.expiresAt, name: access.name } };
|
|
234
|
+
return { door: 'channel', teamId, machineId: target.machineId, auth: { kind: 'delegated', team_id: teamId, principal_id: principal, group_ids: [], grant_id: id, grant_issuer: issuer, expires_at: access.expiresAt, name: access.name, roomContext: access.roomContext } };
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
/**
|
package/session-follow.mjs
CHANGED
|
@@ -151,7 +151,7 @@ export function withMail(transcript, rows, { agentName = 'This session', agentId
|
|
|
151
151
|
const mail = rows.map(row => ({ id: `mail:${row.id}`, role: 'notice', text: row.text, ts: row.at, truncated: false,
|
|
152
152
|
mail: { id: row.id, from: nameOf(row.fromActor), to: row.toActor ? nameOf(row.toActor) : row.direction === 'in' ? agentName : 'Another session',
|
|
153
153
|
image: row.fromActor?.kind === 'agent' ? picture(row.fromActor.self ? agentId : row.fromActor.id) : `https://brand.volter.ai/bot/svg?seed=${encodeURIComponent(row.fromActor?.id || row.from)}&size=24&radius=4`,
|
|
154
|
-
via: row.fromActor?.via, direction: row.direction, inReplyTo: row.inReplyTo } }));
|
|
154
|
+
subject: row.subject || undefined, via: row.fromActor?.via, direction: row.direction, inReplyTo: row.inReplyTo } }));
|
|
155
155
|
const result = transcript.filter(entry => !entry.mail || !rows.some(row => row.id === entry.mail.id || row.id.startsWith(entry.mail.id)));
|
|
156
156
|
// Keep native tool/result ordering intact (some native entries have no time).
|
|
157
157
|
for (const entry of mail.sort((a, b) => a.ts - b.ts)) {
|