agent-relay 2.2.24 → 2.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.
Files changed (116) hide show
  1. package/package.json +64 -21
  2. package/packages/acp-bridge/package.json +2 -2
  3. package/packages/api-types/package.json +1 -1
  4. package/packages/benchmark/package.json +5 -5
  5. package/packages/bridge/package.json +7 -7
  6. package/packages/cli-tester/package.json +1 -1
  7. package/packages/config/package.json +2 -2
  8. package/packages/continuity/package.json +2 -2
  9. package/packages/daemon/package.json +12 -12
  10. package/packages/hooks/package.json +4 -4
  11. package/packages/mcp/package.json +5 -5
  12. package/packages/memory/package.json +2 -2
  13. package/packages/policy/package.json +2 -2
  14. package/packages/protocol/package.json +1 -1
  15. package/packages/resiliency/package.json +1 -1
  16. package/packages/sdk/package.json +3 -3
  17. package/packages/sdk-ts/README.md +65 -0
  18. package/packages/sdk-ts/dist/__tests__/integration.test.d.ts +2 -0
  19. package/packages/sdk-ts/dist/__tests__/integration.test.d.ts.map +1 -0
  20. package/packages/sdk-ts/dist/__tests__/integration.test.js +139 -0
  21. package/packages/sdk-ts/dist/__tests__/integration.test.js.map +1 -0
  22. package/packages/sdk-ts/dist/__tests__/quickstart.test.d.ts +2 -0
  23. package/packages/sdk-ts/dist/__tests__/quickstart.test.d.ts.map +1 -0
  24. package/packages/sdk-ts/dist/__tests__/quickstart.test.js +176 -0
  25. package/packages/sdk-ts/dist/__tests__/quickstart.test.js.map +1 -0
  26. package/packages/sdk-ts/dist/browser.d.ts +16 -0
  27. package/packages/sdk-ts/dist/browser.d.ts.map +1 -0
  28. package/packages/sdk-ts/dist/browser.js +19 -0
  29. package/packages/sdk-ts/dist/browser.js.map +1 -0
  30. package/packages/sdk-ts/dist/client.d.ts +91 -0
  31. package/packages/sdk-ts/dist/client.d.ts.map +1 -0
  32. package/packages/sdk-ts/dist/client.js +360 -0
  33. package/packages/sdk-ts/dist/client.js.map +1 -0
  34. package/packages/sdk-ts/dist/consensus-helpers.d.ts +103 -0
  35. package/packages/sdk-ts/dist/consensus-helpers.d.ts.map +1 -0
  36. package/packages/sdk-ts/dist/consensus-helpers.js +147 -0
  37. package/packages/sdk-ts/dist/consensus-helpers.js.map +1 -0
  38. package/packages/sdk-ts/dist/consensus.d.ts +72 -0
  39. package/packages/sdk-ts/dist/consensus.d.ts.map +1 -0
  40. package/packages/sdk-ts/dist/consensus.js +378 -0
  41. package/packages/sdk-ts/dist/consensus.js.map +1 -0
  42. package/packages/sdk-ts/dist/examples/demo.d.ts +2 -0
  43. package/packages/sdk-ts/dist/examples/demo.d.ts.map +1 -0
  44. package/packages/sdk-ts/dist/examples/demo.js +63 -0
  45. package/packages/sdk-ts/dist/examples/demo.js.map +1 -0
  46. package/packages/sdk-ts/dist/examples/example.d.ts +2 -0
  47. package/packages/sdk-ts/dist/examples/example.d.ts.map +1 -0
  48. package/packages/sdk-ts/dist/examples/example.js +80 -0
  49. package/packages/sdk-ts/dist/examples/example.js.map +1 -0
  50. package/packages/sdk-ts/dist/examples/quickstart.d.ts +2 -0
  51. package/packages/sdk-ts/dist/examples/quickstart.d.ts.map +1 -0
  52. package/packages/sdk-ts/dist/examples/quickstart.js +56 -0
  53. package/packages/sdk-ts/dist/examples/quickstart.js.map +1 -0
  54. package/packages/sdk-ts/dist/examples/ralph-loop.d.ts +2 -0
  55. package/packages/sdk-ts/dist/examples/ralph-loop.d.ts.map +1 -0
  56. package/packages/sdk-ts/dist/examples/ralph-loop.js +281 -0
  57. package/packages/sdk-ts/dist/examples/ralph-loop.js.map +1 -0
  58. package/packages/sdk-ts/dist/index.d.ts +9 -0
  59. package/packages/sdk-ts/dist/index.d.ts.map +1 -0
  60. package/packages/sdk-ts/dist/index.js +9 -0
  61. package/packages/sdk-ts/dist/index.js.map +1 -0
  62. package/packages/sdk-ts/dist/logs.d.ts +47 -0
  63. package/packages/sdk-ts/dist/logs.d.ts.map +1 -0
  64. package/packages/sdk-ts/dist/logs.js +137 -0
  65. package/packages/sdk-ts/dist/logs.js.map +1 -0
  66. package/packages/sdk-ts/dist/protocol.d.ts +249 -0
  67. package/packages/sdk-ts/dist/protocol.d.ts.map +1 -0
  68. package/packages/sdk-ts/dist/protocol.js +2 -0
  69. package/packages/sdk-ts/dist/protocol.js.map +1 -0
  70. package/packages/sdk-ts/dist/pty.d.ts +8 -0
  71. package/packages/sdk-ts/dist/pty.d.ts.map +1 -0
  72. package/packages/sdk-ts/dist/pty.js +14 -0
  73. package/packages/sdk-ts/dist/pty.js.map +1 -0
  74. package/packages/sdk-ts/dist/relay.d.ts +118 -0
  75. package/packages/sdk-ts/dist/relay.d.ts.map +1 -0
  76. package/packages/sdk-ts/dist/relay.js +355 -0
  77. package/packages/sdk-ts/dist/relay.js.map +1 -0
  78. package/packages/sdk-ts/dist/relaycast.d.ts +57 -0
  79. package/packages/sdk-ts/dist/relaycast.d.ts.map +1 -0
  80. package/packages/sdk-ts/dist/relaycast.js +110 -0
  81. package/packages/sdk-ts/dist/relaycast.js.map +1 -0
  82. package/packages/sdk-ts/dist/shadow.d.ts +100 -0
  83. package/packages/sdk-ts/dist/shadow.d.ts.map +1 -0
  84. package/packages/sdk-ts/dist/shadow.js +174 -0
  85. package/packages/sdk-ts/dist/shadow.js.map +1 -0
  86. package/packages/sdk-ts/package.json +75 -0
  87. package/packages/sdk-ts/scripts/bundle-agent-relay.mjs +53 -0
  88. package/packages/sdk-ts/src/__tests__/integration.test.ts +170 -0
  89. package/packages/sdk-ts/src/__tests__/quickstart.test.ts +198 -0
  90. package/packages/sdk-ts/src/browser.ts +57 -0
  91. package/packages/sdk-ts/src/client.ts +491 -0
  92. package/packages/sdk-ts/src/consensus-helpers.ts +253 -0
  93. package/packages/sdk-ts/src/consensus.ts +506 -0
  94. package/packages/sdk-ts/src/examples/demo.ts +88 -0
  95. package/packages/sdk-ts/src/examples/example.ts +91 -0
  96. package/packages/sdk-ts/src/examples/quickstart.ts +72 -0
  97. package/packages/sdk-ts/src/examples/ralph-loop.ts +352 -0
  98. package/packages/sdk-ts/src/examples/sample-prd.json +37 -0
  99. package/packages/sdk-ts/src/index.ts +8 -0
  100. package/packages/sdk-ts/src/logs.ts +163 -0
  101. package/packages/sdk-ts/src/protocol.ts +266 -0
  102. package/packages/sdk-ts/src/pty.ts +16 -0
  103. package/packages/sdk-ts/src/relay.ts +454 -0
  104. package/packages/sdk-ts/src/relaycast.ts +143 -0
  105. package/packages/sdk-ts/src/shadow.ts +230 -0
  106. package/packages/sdk-ts/tsconfig.json +16 -0
  107. package/packages/spawner/package.json +1 -1
  108. package/packages/state/package.json +1 -1
  109. package/packages/storage/package.json +2 -2
  110. package/packages/telemetry/package.json +1 -1
  111. package/packages/trajectory/package.json +2 -2
  112. package/packages/user-directory/package.json +2 -2
  113. package/packages/utils/package.json +3 -3
  114. package/packages/wrapper/package.json +6 -6
  115. package/packages/mcp/SPEC.md +0 -1922
  116. package/packages/mcp/STAFFING_PLAN.md +0 -294
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Consensus types and pure helper functions.
3
+ *
4
+ * This module has ZERO Node.js dependencies — safe for browser use.
5
+ * The ConsensusEngine class (which needs node:crypto and node:events)
6
+ * lives in consensus.ts.
7
+ */
8
+
9
+ // ── Types ────────────────────────────────────────────────────────────────────
10
+
11
+ export type ConsensusType =
12
+ | "majority"
13
+ | "supermajority"
14
+ | "unanimous"
15
+ | "weighted"
16
+ | "quorum";
17
+
18
+ export type VoteValue = "approve" | "reject" | "abstain";
19
+
20
+ export type ProposalStatus =
21
+ | "pending"
22
+ | "approved"
23
+ | "rejected"
24
+ | "expired"
25
+ | "cancelled";
26
+
27
+ export interface AgentWeight {
28
+ agent: string;
29
+ weight: number;
30
+ role?: string;
31
+ }
32
+
33
+ export interface Vote {
34
+ agent: string;
35
+ value: VoteValue;
36
+ weight: number;
37
+ reason?: string;
38
+ timestamp: number;
39
+ }
40
+
41
+ export interface Proposal {
42
+ id: string;
43
+ title: string;
44
+ description: string;
45
+ proposer: string;
46
+ consensusType: ConsensusType;
47
+ participants: string[];
48
+ quorum?: number;
49
+ threshold?: number;
50
+ weights?: AgentWeight[];
51
+ createdAt: number;
52
+ expiresAt: number;
53
+ status: ProposalStatus;
54
+ votes: Vote[];
55
+ result?: ConsensusResult;
56
+ metadata?: Record<string, unknown>;
57
+ thread?: string;
58
+ }
59
+
60
+ export interface ConsensusResult {
61
+ decision: "approved" | "rejected" | "no_consensus";
62
+ approveWeight: number;
63
+ rejectWeight: number;
64
+ abstainWeight: number;
65
+ participation: number;
66
+ quorumMet: boolean;
67
+ resolvedAt: number;
68
+ nonVoters: string[];
69
+ }
70
+
71
+ export interface ConsensusConfig {
72
+ /** Default proposal timeout in ms (default: 5 min) */
73
+ defaultTimeoutMs: number;
74
+ defaultConsensusType: ConsensusType;
75
+ /** Supermajority threshold (0–1, default 0.67) */
76
+ defaultThreshold: number;
77
+ allowVoteChange: boolean;
78
+ /** Auto-resolve when outcome is mathematically certain */
79
+ autoResolve: boolean;
80
+ /** Max resolved/expired/cancelled proposals to retain. Oldest are evicted
81
+ * when this limit is exceeded. 0 = unlimited. Default: 100. */
82
+ maxRetainedProposals: number;
83
+ }
84
+
85
+ export interface ConsensusEvents {
86
+ "proposal:created": (proposal: Proposal) => void;
87
+ "proposal:voted": (proposal: Proposal, vote: Vote) => void;
88
+ "proposal:resolved": (
89
+ proposal: Proposal,
90
+ result: ConsensusResult,
91
+ ) => void;
92
+ "proposal:expired": (proposal: Proposal) => void;
93
+ "proposal:cancelled": (proposal: Proposal) => void;
94
+ }
95
+
96
+ export interface ParsedProposalCommand {
97
+ title: string;
98
+ description: string;
99
+ participants: string[];
100
+ consensusType: ConsensusType;
101
+ timeoutMs?: number;
102
+ quorum?: number;
103
+ threshold?: number;
104
+ }
105
+
106
+ // ── Pure helper functions (no Node.js deps) ──────────────────────────────────
107
+
108
+ export function formatProposalMessage(proposal: Proposal): string {
109
+ return [
110
+ `PROPOSAL: ${proposal.title}`,
111
+ `ID: ${proposal.id}`,
112
+ `From: ${proposal.proposer}`,
113
+ `Type: ${proposal.consensusType}`,
114
+ `Expires: ${new Date(proposal.expiresAt).toISOString()}`,
115
+ "",
116
+ proposal.description,
117
+ "",
118
+ `Participants: ${proposal.participants.join(", ")}`,
119
+ "",
120
+ "Reply with: VOTE <proposal-id> <approve|reject|abstain> [reason]",
121
+ ].join("\n");
122
+ }
123
+
124
+ export function formatResultMessage(
125
+ proposal: Proposal,
126
+ result: ConsensusResult,
127
+ ): string {
128
+ const lines = [
129
+ `CONSENSUS RESULT: ${proposal.title}`,
130
+ `Decision: ${result.decision.toUpperCase()}`,
131
+ `Participation: ${(result.participation * 100).toFixed(1)}%`,
132
+ "",
133
+ `Approve: ${result.approveWeight} | Reject: ${result.rejectWeight} | Abstain: ${result.abstainWeight}`,
134
+ ];
135
+ if (result.nonVoters.length > 0) {
136
+ lines.push(`Non-voters: ${result.nonVoters.join(", ")}`);
137
+ }
138
+ return lines.join("\n");
139
+ }
140
+
141
+ export function parseVoteCommand(
142
+ message: string,
143
+ ): { proposalId: string; value: VoteValue; reason?: string } | null {
144
+ const trimmed = message.trim();
145
+ if (!trimmed.toUpperCase().startsWith("VOTE ")) return null;
146
+
147
+ // Split into at most 4 parts: "VOTE", proposalId, value, reason...
148
+ const parts = trimmed.split(/\s+/);
149
+ if (parts.length < 3) return null;
150
+
151
+ const proposalId = parts[1];
152
+ const rawValue = parts[2].toLowerCase();
153
+ if (rawValue !== "approve" && rawValue !== "reject" && rawValue !== "abstain") {
154
+ return null;
155
+ }
156
+
157
+ const reason = parts.length > 3 ? parts.slice(3).join(" ") : undefined;
158
+ return { proposalId, value: rawValue, reason };
159
+ }
160
+
161
+ export function isConsensusCommand(message: string): boolean {
162
+ const trimmed = message.trim();
163
+ return trimmed.startsWith("PROPOSE:") || trimmed.toUpperCase().startsWith("VOTE ");
164
+ }
165
+
166
+ /**
167
+ * Parse a PROPOSE command from a relay message.
168
+ *
169
+ * Format:
170
+ * ```
171
+ * PROPOSE: Title of the proposal
172
+ * TYPE: majority|supermajority|unanimous|weighted|quorum
173
+ * PARTICIPANTS: Agent1, Agent2, Agent3
174
+ * DESCRIPTION: Detailed description
175
+ * TIMEOUT: 3600000 (optional, ms)
176
+ * QUORUM: 3 (optional)
177
+ * THRESHOLD: 0.67 (optional)
178
+ * ```
179
+ */
180
+ export function parseProposalCommand(
181
+ message: string,
182
+ ): ParsedProposalCommand | null {
183
+ if (!message.trim().startsWith("PROPOSE:")) return null;
184
+
185
+ const lines = message.split("\n").map((l) => l.trim());
186
+
187
+ let title: string | undefined;
188
+ let description: string | undefined;
189
+ let participants: string[] | undefined;
190
+ let consensusType: ConsensusType = "majority";
191
+ let timeoutMs: number | undefined;
192
+ let quorum: number | undefined;
193
+ let threshold: number | undefined;
194
+
195
+ let inDescription = false;
196
+ const descriptionLines: string[] = [];
197
+
198
+ for (const line of lines) {
199
+ if (line.startsWith("PROPOSE:")) {
200
+ title = line.substring("PROPOSE:".length).trim();
201
+ inDescription = false;
202
+ } else if (line.startsWith("TYPE:")) {
203
+ const type = line.substring("TYPE:".length).trim().toLowerCase();
204
+ if (
205
+ ["majority", "supermajority", "unanimous", "weighted", "quorum"].includes(type)
206
+ ) {
207
+ consensusType = type as ConsensusType;
208
+ }
209
+ inDescription = false;
210
+ } else if (line.startsWith("PARTICIPANTS:")) {
211
+ const str = line.substring("PARTICIPANTS:".length).trim();
212
+ participants = str
213
+ .split(",")
214
+ .map((p) => p.trim())
215
+ .filter((p) => p.length > 0);
216
+ inDescription = false;
217
+ } else if (line.startsWith("DESCRIPTION:")) {
218
+ description = line.substring("DESCRIPTION:".length).trim();
219
+ inDescription = true;
220
+ } else if (line.startsWith("TIMEOUT:")) {
221
+ const val = parseInt(line.substring("TIMEOUT:".length).trim(), 10);
222
+ if (!isNaN(val) && val > 0) timeoutMs = val;
223
+ inDescription = false;
224
+ } else if (line.startsWith("QUORUM:")) {
225
+ const val = parseInt(line.substring("QUORUM:".length).trim(), 10);
226
+ if (!isNaN(val) && val > 0) quorum = val;
227
+ inDescription = false;
228
+ } else if (line.startsWith("THRESHOLD:")) {
229
+ const val = parseFloat(line.substring("THRESHOLD:".length).trim());
230
+ if (!isNaN(val) && val > 0 && val <= 1) threshold = val;
231
+ inDescription = false;
232
+ } else if (inDescription && line.length > 0) {
233
+ descriptionLines.push(line);
234
+ }
235
+ }
236
+
237
+ if (descriptionLines.length > 0 && description) {
238
+ description = description + "\n" + descriptionLines.join("\n");
239
+ }
240
+
241
+ if (!title || !participants || participants.length === 0) return null;
242
+ if (!description) description = title;
243
+
244
+ return {
245
+ title,
246
+ description,
247
+ participants,
248
+ consensusType,
249
+ timeoutMs,
250
+ quorum,
251
+ threshold,
252
+ };
253
+ }