@nelsonlongxiang/dsh-open-a2a-net 0.6.25 → 0.6.27
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/README.md +15 -11
- package/README_zh.md +3 -2
- package/assets/nexusDist/assets/index-DszoLz8i.js +5 -0
- package/assets/nexusDist/assets/index-uQf7NwjF.css +1 -0
- package/assets/nexusDist/index.html +2 -2
- package/cli/a2a.mjs +612 -0
- package/lib/card.js +17 -0
- package/lib/cli-deposit.js +141 -0
- package/lib/index.js +636 -25
- package/lib/owner-settings.js +100 -0
- package/lib/peer-store.js +65 -9
- package/lib/task-ledger.js +44 -3
- package/lib/types/cli-deposit.d.ts +53 -0
- package/lib/types/owner-settings.d.ts +19 -0
- package/lib/types/peer-store.d.ts +22 -3
- package/lib/types/task-ledger.d.ts +18 -0
- package/lib/types/types.d.ts +10 -0
- package/nexus-stage/src/canvas-ops.ts +2 -2
- package/nexus-stage/src/federation.ts +6 -0
- package/nexus-stage/src/main.ts +97 -4
- package/nexus-stage/src/planning-menus.ts +16 -4
- package/nexus-stage/src/planning-types.ts +3 -0
- package/nexus-stage/src/planning-view.ts +208 -18
- package/nexus-stage/src/planning.css +4 -0
- package/nexus-stage/src/wb-chat.ts +670 -0
- package/nexus-stage/src/wb-directory.ts +222 -0
- package/nexus-stage/src/wb-ledger.ts +266 -0
- package/nexus-stage/src/wb-rail.ts +147 -0
- package/nexus-stage/src/workbench.css +190 -84
- package/nexus-stage/src/workbench.ts +385 -721
- package/nexus-stage/src/world.ts +5 -1
- package/package.json +214 -218
- package/assets/nexusDist/assets/index-034h1cNc.js +0 -3
- package/assets/nexusDist/assets/index-PG9EieGX.css +0 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI 户口登记处 (gh#45, owner rulings 2026-10-24):
|
|
3
|
+
* ① handle = <agent-name>/<uuid·8B (16 hex)> — the name is custom, the
|
|
4
|
+
* suffix is forced 16-hex by shape gate;
|
|
5
|
+
* ② one key, multiple registrations — v1: the local home host;
|
|
6
|
+
* ③ deposit TTL: default AND max 4h — expiry auto-deregisters (the CLI
|
|
7
|
+
* vanishes from the card face and the directory; re-publish returns).
|
|
8
|
+
*
|
|
9
|
+
* The deposit is the CLI's "household registration": the home host serves
|
|
10
|
+
* the CLI's SIGNED card at /a2a/cli/<handle>/.well-known/agent-card.json
|
|
11
|
+
* (an OriginClaim fetch of the CLI envelope lands exactly there), lists
|
|
12
|
+
* the handle in its own card's sessionTeams (so the whole fleet sees the
|
|
13
|
+
* CLI as a member card — draggable into canvas teams = the operator link),
|
|
14
|
+
* and holds a mailbox for inbound deliveries (receipts land here; the CLI
|
|
15
|
+
* polls while alive).
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
import { verifyCard } from "./card.js";
|
|
20
|
+
/** Owner ruling ③: the default AND maximum online window. */
|
|
21
|
+
export const CLI_DEPOSIT_TTL_MS = 4 * 60 * 60 * 1000;
|
|
22
|
+
/** Owner ruling ①: <agent-name>/<uuid·8B>. The name is [a-z0-9-]{1,32}. */
|
|
23
|
+
export const CLI_HANDLE_RE = /^([a-z0-9-]{1,32})\/([0-9a-f]{16})$/;
|
|
24
|
+
const MAILBOX_CAP = 64;
|
|
25
|
+
export class CliDepositStore {
|
|
26
|
+
path;
|
|
27
|
+
deposits = new Map();
|
|
28
|
+
mailbox = new Map();
|
|
29
|
+
now;
|
|
30
|
+
constructor(path, options) {
|
|
31
|
+
this.path = path;
|
|
32
|
+
this.now = options?.now ?? (() => Date.now());
|
|
33
|
+
this.restore();
|
|
34
|
+
}
|
|
35
|
+
/** Deposit (or refresh) one CLI card. TTL is clamped to the 4h ruling. */
|
|
36
|
+
deposit(cardJson) {
|
|
37
|
+
let parsed;
|
|
38
|
+
try {
|
|
39
|
+
parsed = JSON.parse(cardJson);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return { ok: false, error: 'card is not JSON' };
|
|
43
|
+
}
|
|
44
|
+
const verdict = verifyCard(parsed, this.now());
|
|
45
|
+
if (!verdict.ok)
|
|
46
|
+
return { ok: false, error: `card verification failed (${verdict.reason})` };
|
|
47
|
+
if (typeof verdict.card.team !== 'string' || !CLI_HANDLE_RE.test(verdict.card.team)) {
|
|
48
|
+
return { ok: false, error: `card.team must be the CLI handle <agent-name>/<uuid16hex>, got "${String(verdict.card.team)}"` };
|
|
49
|
+
}
|
|
50
|
+
const handle = verdict.card.team;
|
|
51
|
+
const name = CLI_HANDLE_RE.exec(handle)[1];
|
|
52
|
+
if (verdict.card.team !== `${name}/${CLI_HANDLE_RE.exec(handle)[2]}`)
|
|
53
|
+
return { ok: false, error: 'handle mismatch' };
|
|
54
|
+
const ttl = Math.min(CLI_DEPOSIT_TTL_MS, CLI_DEPOSIT_TTL_MS);
|
|
55
|
+
const at = this.now();
|
|
56
|
+
const row = { handle, name, cardJson, depositedAt: at, expiresAt: at + ttl };
|
|
57
|
+
this.deposits.set(handle, row);
|
|
58
|
+
this.persist();
|
|
59
|
+
return { ok: true, handle, expiresAt: row.expiresAt };
|
|
60
|
+
}
|
|
61
|
+
revoke(handle) {
|
|
62
|
+
const had = this.deposits.delete(handle);
|
|
63
|
+
if (had)
|
|
64
|
+
this.persist();
|
|
65
|
+
return had;
|
|
66
|
+
}
|
|
67
|
+
/** Active deposits (sweeping expired ones — ruling ③ auto-deregister). */
|
|
68
|
+
list() {
|
|
69
|
+
this.sweep();
|
|
70
|
+
return [...this.deposits.values()];
|
|
71
|
+
}
|
|
72
|
+
get(handle) {
|
|
73
|
+
const row = this.deposits.get(handle);
|
|
74
|
+
if (row === undefined)
|
|
75
|
+
return undefined;
|
|
76
|
+
if (row.expiresAt <= this.now()) {
|
|
77
|
+
this.deposits.delete(handle);
|
|
78
|
+
this.persist();
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
return row;
|
|
82
|
+
}
|
|
83
|
+
/** Card-serve rows: the handle + display name, marked cli (no wake). */
|
|
84
|
+
cardRows() {
|
|
85
|
+
return this.list().map(row => ({ team: row.handle, name: row.name, description: 'cli — deposited identity (no wake; mailbox)' }));
|
|
86
|
+
}
|
|
87
|
+
mail(handle, from, text) {
|
|
88
|
+
const list = this.mailbox.get(handle) ?? [];
|
|
89
|
+
list.unshift({ at: this.now(), from, text: text.slice(0, 4000) });
|
|
90
|
+
this.mailbox.set(handle, list.slice(0, MAILBOX_CAP));
|
|
91
|
+
this.persist();
|
|
92
|
+
}
|
|
93
|
+
readMail(handle) {
|
|
94
|
+
return [...(this.mailbox.get(handle) ?? [])];
|
|
95
|
+
}
|
|
96
|
+
sweep() {
|
|
97
|
+
const now = this.now();
|
|
98
|
+
let changed = false;
|
|
99
|
+
for (const [handle, row] of this.deposits) {
|
|
100
|
+
if (row.expiresAt <= now) {
|
|
101
|
+
this.deposits.delete(handle);
|
|
102
|
+
changed = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (changed)
|
|
106
|
+
this.persist();
|
|
107
|
+
}
|
|
108
|
+
persist() {
|
|
109
|
+
const mailbox = {};
|
|
110
|
+
for (const [handle, list] of this.mailbox)
|
|
111
|
+
mailbox[handle] = [...list];
|
|
112
|
+
const snapshot = { deposits: [...this.deposits.values()], mailbox };
|
|
113
|
+
try {
|
|
114
|
+
mkdirSync(join(this.path, '..'), { recursive: true });
|
|
115
|
+
writeFileSync(this.path, JSON.stringify(snapshot), 'utf8');
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// persistence best-effort; the deposit re-publishes self-heal
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
restore() {
|
|
122
|
+
if (this.path === '' || !existsSync(this.path))
|
|
123
|
+
return;
|
|
124
|
+
try {
|
|
125
|
+
const snapshot = JSON.parse(readFileSync(this.path, 'utf8'));
|
|
126
|
+
for (const row of snapshot.deposits ?? []) {
|
|
127
|
+
if (typeof row?.handle === 'string' && typeof row.cardJson === 'string' && typeof row.expiresAt === 'number') {
|
|
128
|
+
this.deposits.set(row.handle, row);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
for (const [handle, list] of Object.entries(snapshot.mailbox ?? {})) {
|
|
132
|
+
if (Array.isArray(list))
|
|
133
|
+
this.mailbox.set(handle, list.filter(m => m !== null && typeof m === 'object'));
|
|
134
|
+
}
|
|
135
|
+
this.sweep();
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// corrupt file: start empty (re-publish heals)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|