@nelsonlongxiang/dsh-open-a2a-net 0.6.28 → 0.6.30

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.
Files changed (69) hide show
  1. package/README.md +87 -14
  2. package/README_zh.md +83 -7
  3. package/assets/nexusDist/assets/index-C_x3iAth.js +9 -0
  4. package/assets/nexusDist/assets/index-Dz8N80tI.css +1 -0
  5. package/assets/nexusDist/index.html +2 -2
  6. package/cli/a2a.mjs +0 -0
  7. package/cordis.patch.yml +21 -21
  8. package/lib/canvas-store.js +21 -1
  9. package/lib/client.js +64 -64
  10. package/lib/client.js.map +1 -1
  11. package/lib/faces/admin.js +755 -0
  12. package/lib/faces/canvas-notify.js +138 -0
  13. package/lib/faces/wire.js +669 -0
  14. package/lib/flood-guard.js +106 -0
  15. package/lib/index.js +200 -1392
  16. package/lib/recursion-guard.js +78 -0
  17. package/lib/runtime.js +1 -0
  18. package/lib/skill/SKILL.md +35 -9
  19. package/lib/skill/references/cli.md +24 -7
  20. package/lib/skill/references/collaboration.md +355 -0
  21. package/lib/skill/references/discovery.md +5 -2
  22. package/lib/skill/references/pitfalls.md +2 -1
  23. package/lib/skill/references/routing.md +18 -8
  24. package/lib/skill/references/setup.md +152 -0
  25. package/lib/task-ledger.js +40 -4
  26. package/lib/types/canvas-store.d.ts +10 -1
  27. package/lib/types/faces/admin.d.ts +133 -0
  28. package/lib/types/faces/canvas-notify.d.ts +74 -0
  29. package/lib/types/faces/wire.d.ts +171 -0
  30. package/lib/types/flood-guard.d.ts +29 -0
  31. package/lib/types/index.d.ts +11 -3
  32. package/lib/types/recursion-guard.d.ts +56 -0
  33. package/lib/types/runtime.d.ts +35 -0
  34. package/lib/types/task-ledger.d.ts +15 -1
  35. package/nexus-stage/package-lock.json +2262 -2262
  36. package/nexus-stage/src/canvas-ops.ts +175 -175
  37. package/nexus-stage/src/canvas-wire.ts +156 -156
  38. package/nexus-stage/src/edges.ts +72 -72
  39. package/nexus-stage/src/federation-overlay.ts +103 -103
  40. package/nexus-stage/src/federation.ts +240 -240
  41. package/nexus-stage/src/layout-doc.ts +143 -143
  42. package/nexus-stage/src/layout-wire.ts +158 -158
  43. package/nexus-stage/src/main.ts +5 -1
  44. package/nexus-stage/src/planning-card-text.ts +73 -0
  45. package/nexus-stage/src/planning-edges.ts +26 -0
  46. package/nexus-stage/src/planning-fit.ts +45 -0
  47. package/nexus-stage/src/planning-legend.ts +38 -0
  48. package/nexus-stage/src/planning-mirror.ts +31 -0
  49. package/nexus-stage/src/planning-overlap.ts +159 -0
  50. package/nexus-stage/src/planning-relayout.ts +121 -0
  51. package/nexus-stage/src/planning-search.ts +168 -0
  52. package/nexus-stage/src/planning-types.ts +1 -0
  53. package/nexus-stage/src/planning-undo.ts +68 -0
  54. package/nexus-stage/src/planning-view.ts +120 -121
  55. package/nexus-stage/src/planning.css +41 -8
  56. package/nexus-stage/src/seat.ts +35 -35
  57. package/nexus-stage/src/stage-name.ts +13 -13
  58. package/nexus-stage/src/tokens.ts +31 -31
  59. package/nexus-stage/src/viewport.ts +24 -1
  60. package/nexus-stage/src/wb-chat.ts +20 -6
  61. package/nexus-stage/src/wb-ledger.ts +20 -7
  62. package/nexus-stage/src/wb-names.ts +43 -0
  63. package/nexus-stage/src/workbench.css +8 -2
  64. package/nexus-stage/src/workbench.ts +55 -17
  65. package/nexus-stage/src/world.ts +13 -21
  66. package/package.json +216 -214
  67. package/assets/nexusDist/assets/index-1niOBYxp.js +0 -5
  68. package/assets/nexusDist/assets/index-uQf7NwjF.css +0 -1
  69. package/nexus-stage/scripts/__pycache__/mockhost.cpython-312.pyc +0 -0
@@ -0,0 +1,106 @@
1
+ export const WIRE_ERROR_RATE_LIMITED = -32008;
2
+ export const MAX_PARTS_PER_TRANSFER = 16;
3
+ // Matches the current L9 threshold; per-sender across ALL targets is stricter.
4
+ export const DEFAULT_RATE_PER_MINUTE = 16;
5
+ const WINDOW_MS = 60_000;
6
+ const TRANSFER_TTL_MS = 24 * 60 * 60_000;
7
+ const STATE_CAP = 1024;
8
+ function parsePart(message) {
9
+ const pos = message.indexOf('[JPFILE-PART');
10
+ if (pos === -1)
11
+ return null;
12
+ const match = /^\[JPFILE-PART v1\]\s*/.exec(message.slice(pos));
13
+ if (match === null)
14
+ return 'invalid';
15
+ try {
16
+ const p = JSON.parse(message.slice(pos + match[0].length));
17
+ if (p === null || typeof p !== 'object')
18
+ return 'invalid';
19
+ const e = p;
20
+ if (typeof e.transfer_id !== 'string' || e.transfer_id.length === 0 || e.transfer_id.length > 256 ||
21
+ typeof e.file_id !== 'string' || e.file_id.length === 0 || e.file_id.length > 256 ||
22
+ !Number.isSafeInteger(e.part_i) || !Number.isSafeInteger(e.part_n))
23
+ return 'invalid';
24
+ const i = e.part_i;
25
+ const n = e.part_n;
26
+ // Accept either zero- or one-based indexes; the UNIQUE accepted-parts
27
+ // count below is authoritative even when declared totals are dishonest.
28
+ if (n < 1 || i < 0 || i > n)
29
+ return 'invalid';
30
+ return { transferId: e.transfer_id, fileId: e.file_id, i, n };
31
+ }
32
+ catch {
33
+ return 'invalid';
34
+ }
35
+ }
36
+ export class FloodGuard {
37
+ now;
38
+ senders = new Map();
39
+ transfers = new Map();
40
+ constructor(now = Date.now) {
41
+ this.now = now;
42
+ }
43
+ /** Check/admit one fresh task. No timer; maps and per-key sets are bounded.
44
+ * Active transfer entries NEVER evict to make space (which would reset a
45
+ * transfer's allowance); capacity exhaustion refuses visibly instead.
46
+ * Counts are boot-local: restart resets them, disclosed in the guide.
47
+ */
48
+ check(caller, message) {
49
+ const now = this.now();
50
+ for (const [k, hits] of this.senders) {
51
+ const fresh = hits.filter(t => t > now - WINDOW_MS);
52
+ if (fresh.length === 0)
53
+ this.senders.delete(k);
54
+ else
55
+ this.senders.set(k, fresh);
56
+ }
57
+ for (const [k, value] of this.transfers)
58
+ if (now - value.since >= TRANSFER_TTL_MS)
59
+ this.transfers.delete(k);
60
+ const part = parsePart(message);
61
+ if (part === 'invalid')
62
+ return 'file-part-invalid';
63
+ const key = part === null ? '' : JSON.stringify([caller, part.transferId]);
64
+ const transfer = this.transfers.get(key);
65
+ const coordinate = part === null ? '' : JSON.stringify([part.fileId, part.i]);
66
+ if (part !== null) {
67
+ if (part.n > MAX_PARTS_PER_TRANSFER || (transfer?.parts.size ?? 0) >= MAX_PARTS_PER_TRANSFER)
68
+ return 'file-parts-exceeded';
69
+ if (transfer?.parts.has(coordinate))
70
+ return 'file-part-duplicate';
71
+ if (transfer === undefined && this.transfers.size >= STATE_CAP)
72
+ return 'flood-state-full';
73
+ }
74
+ const hits = this.senders.get(caller) ?? [];
75
+ if (hits.length >= DEFAULT_RATE_PER_MINUTE)
76
+ return 'sender-rate-limited';
77
+ if (hits.length === 0 && this.senders.size >= STATE_CAP)
78
+ return 'flood-state-full';
79
+ hits.push(now);
80
+ this.senders.set(caller, hits);
81
+ if (part !== null) {
82
+ const row = transfer ?? { since: now, parts: new Set() };
83
+ row.parts.add(coordinate);
84
+ this.transfers.set(key, row);
85
+ }
86
+ return undefined;
87
+ }
88
+ }
89
+ /** Host-scoped adapter; rejected fresh keys are FAILED, not stranded pending.
90
+ * HTTP 200 retains the existing client's structured peer-error path.
91
+ */
92
+ export function createFloodGuard(outcomes, recordActivity) {
93
+ const guard = new FloodGuard();
94
+ return (caller, message, team, taskId, res) => {
95
+ const reason = guard.check(caller, message);
96
+ if (reason === undefined)
97
+ return false;
98
+ const error = 'flood-guard: ' + reason + ' (gh#91): file data must use an independent channel; no delivery occurred';
99
+ outcomes.recordOutcome(taskId, { status: 'failed', error });
100
+ recordActivity('in', team, caller, false);
101
+ const payload = JSON.stringify({ error, reason, code: WIRE_ERROR_RATE_LIMITED, task_id: taskId, team, delivered: false, task_status: 'TASK_STATE_FAILED' });
102
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) });
103
+ res.end(payload);
104
+ return true;
105
+ };
106
+ }