@sw4rm/js-sdk 0.3.0 → 0.5.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.
- package/README.md +13 -0
- package/dist/cjs/index.cjs +3576 -342
- package/dist/esm/index.js +3497 -336
- package/dist/types/agentConfig.d.ts +245 -0
- package/dist/types/audit.d.ts +214 -0
- package/dist/types/clients/handoff.d.ts +188 -0
- package/dist/types/clients/negotiationRoom.d.ts +423 -0
- package/dist/types/clients/negotiationRoomStore.d.ts +155 -0
- package/dist/types/clients/workflow.d.ts +316 -0
- package/dist/types/constants/index.d.ts +100 -0
- package/dist/types/index.d.ts +15 -4
- package/dist/types/internal/baseClient.d.ts +7 -1
- package/dist/types/internal/envelope.d.ts +16 -0
- package/dist/types/internal/errorMapping.d.ts +114 -0
- package/dist/types/internal/worktreeState.d.ts +60 -0
- package/dist/types/persistentActivityBuffer.d.ts +94 -0
- package/dist/types/runtime/agentState.d.ts +205 -0
- package/dist/types/runtime/policyStore.d.ts +391 -0
- package/dist/types/runtime/voting.d.ts +208 -0
- package/package.json +4 -2
- package/protos/activity.proto +24 -0
- package/protos/common.proto +134 -0
- package/protos/connector.proto +29 -0
- package/protos/handoff.proto +63 -0
- package/protos/hitl.proto +23 -0
- package/protos/logging.proto +20 -0
- package/protos/negotiation.proto +57 -0
- package/protos/negotiation_room.proto +220 -0
- package/protos/policy.proto +55 -0
- package/protos/reasoning.proto +41 -0
- package/protos/registry.proto +36 -0
- package/protos/router.proto +16 -0
- package/protos/scheduler.proto +52 -0
- package/protos/scheduler_policy.proto +36 -0
- package/protos/tool.proto +47 -0
- package/protos/workflow.proto +116 -0
- package/protos/worktree.proto +33 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Negotiation Room client for SW4RM.
|
|
3
|
+
*
|
|
4
|
+
* This module provides the NegotiationRoomClient for managing multi-agent
|
|
5
|
+
* artifact approval workflows using the Negotiation Room pattern. The client
|
|
6
|
+
* supports:
|
|
7
|
+
* - Submitting artifacts for review
|
|
8
|
+
* - Collecting votes from critics
|
|
9
|
+
* - Retrieving and waiting for decisions
|
|
10
|
+
* - Coordinating the review process
|
|
11
|
+
*
|
|
12
|
+
* Based on SPEC_REQUESTS.md section 6.1.
|
|
13
|
+
*
|
|
14
|
+
* ## Concurrency Fix (v0.5.0)
|
|
15
|
+
*
|
|
16
|
+
* The client now uses a pluggable storage backend (NegotiationRoomStore) instead
|
|
17
|
+
* of instance-local storage. This enables multiple client instances to share
|
|
18
|
+
* state, which is essential for multi-agent deployments where producer, critic,
|
|
19
|
+
* and coordinator agents run in different processes or workers.
|
|
20
|
+
*
|
|
21
|
+
* ### Usage patterns
|
|
22
|
+
*
|
|
23
|
+
* 1. Single-process with shared default store (recommended):
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const client1 = new NegotiationRoomClient(); // Uses shared default store
|
|
26
|
+
* const client2 = new NegotiationRoomClient(); // Same store, shared state
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* 2. Explicit store sharing:
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const store = new InMemoryNegotiationRoomStore();
|
|
32
|
+
* const producer = new NegotiationRoomClient({ store });
|
|
33
|
+
* const critic = new NegotiationRoomClient({ store });
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* 3. File-based persistence (multi-process, requires colony):
|
|
37
|
+
* ```typescript
|
|
38
|
+
* import { JsonFileNegotiationRoomStore } from 'colony/stores/typescript/jsonFileStore';
|
|
39
|
+
* const store = new JsonFileNegotiationRoomStore("/path/to/storage");
|
|
40
|
+
* const client = new NegotiationRoomClient({ store });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
import { NegotiationRoomStore } from './negotiationRoomStore.js';
|
|
44
|
+
/**
|
|
45
|
+
* Type of artifact being negotiated.
|
|
46
|
+
*
|
|
47
|
+
* Maps to the artifact_type field in negotiation proposals to categorize
|
|
48
|
+
* what stage of the workflow the artifact belongs to.
|
|
49
|
+
*/
|
|
50
|
+
export declare enum ArtifactType {
|
|
51
|
+
ARTIFACT_TYPE_UNSPECIFIED = 0,
|
|
52
|
+
REQUIREMENTS = 1,
|
|
53
|
+
PLAN = 2,
|
|
54
|
+
CODE = 3,
|
|
55
|
+
DEPLOYMENT = 4
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Outcome of a negotiation decision.
|
|
59
|
+
*
|
|
60
|
+
* Represents the final decision made by the coordinator after aggregating
|
|
61
|
+
* critic votes and applying policy.
|
|
62
|
+
*/
|
|
63
|
+
export declare enum DecisionOutcome {
|
|
64
|
+
DECISION_OUTCOME_UNSPECIFIED = 0,
|
|
65
|
+
APPROVED = 1,
|
|
66
|
+
REVISION_REQUESTED = 2,
|
|
67
|
+
ESCALATED_TO_HITL = 3
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A proposal for artifact evaluation in a negotiation room.
|
|
71
|
+
*
|
|
72
|
+
* Submitted by a producer agent to request multi-agent review of an artifact.
|
|
73
|
+
* The proposal specifies which critics should evaluate the artifact and
|
|
74
|
+
* includes the artifact content for review.
|
|
75
|
+
*/
|
|
76
|
+
export interface NegotiationProposal {
|
|
77
|
+
/** Category of artifact (requirements, plan, code, deployment) */
|
|
78
|
+
artifactType: ArtifactType;
|
|
79
|
+
/** Unique identifier for this artifact */
|
|
80
|
+
artifactId: string;
|
|
81
|
+
/** Agent ID of the producer submitting the artifact */
|
|
82
|
+
producerId: string;
|
|
83
|
+
/** Binary artifact content (e.g., serialized JSON, code files) */
|
|
84
|
+
artifact: Uint8Array;
|
|
85
|
+
/** MIME type or content type identifier */
|
|
86
|
+
artifactContentType: string;
|
|
87
|
+
/** List of critic agent IDs requested for evaluation */
|
|
88
|
+
requestedCritics: string[];
|
|
89
|
+
/** Identifier for the negotiation room session */
|
|
90
|
+
negotiationRoomId: string;
|
|
91
|
+
/** Timestamp when proposal was created (ISO-8601 string) */
|
|
92
|
+
createdAt?: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* A critic's evaluation of an artifact.
|
|
96
|
+
*
|
|
97
|
+
* Represents a single critic's assessment including numerical scoring,
|
|
98
|
+
* qualitative feedback, and confidence level based on POMDP uncertainty.
|
|
99
|
+
*/
|
|
100
|
+
export interface NegotiationVote {
|
|
101
|
+
/** Identifier of the artifact being evaluated */
|
|
102
|
+
artifactId: string;
|
|
103
|
+
/** Agent ID of the critic providing this vote */
|
|
104
|
+
criticId: string;
|
|
105
|
+
/** Numerical score from 0-10 (10 = excellent) */
|
|
106
|
+
score: number;
|
|
107
|
+
/** Confidence level from 0-1 (based on POMDP research) */
|
|
108
|
+
confidence: number;
|
|
109
|
+
/** Boolean indicating if artifact meets minimum criteria */
|
|
110
|
+
passed: boolean;
|
|
111
|
+
/** List of identified strengths in the artifact */
|
|
112
|
+
strengths: string[];
|
|
113
|
+
/** List of identified weaknesses or concerns */
|
|
114
|
+
weaknesses: string[];
|
|
115
|
+
/** List of suggestions for improvement */
|
|
116
|
+
recommendations: string[];
|
|
117
|
+
/** Identifier for the negotiation room session */
|
|
118
|
+
negotiationRoomId: string;
|
|
119
|
+
/** Timestamp when vote was cast (ISO-8601 string) */
|
|
120
|
+
votedAt?: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Statistical aggregation of multiple critic votes.
|
|
124
|
+
*
|
|
125
|
+
* Provides multiple views of the voting results including basic statistics
|
|
126
|
+
* and confidence-weighted metrics for decision making.
|
|
127
|
+
*/
|
|
128
|
+
export interface AggregatedScore {
|
|
129
|
+
/** Arithmetic mean of all scores */
|
|
130
|
+
mean: number;
|
|
131
|
+
/** Minimum score from any critic */
|
|
132
|
+
minScore: number;
|
|
133
|
+
/** Maximum score from any critic */
|
|
134
|
+
maxScore: number;
|
|
135
|
+
/** Standard deviation of scores (measures consensus) */
|
|
136
|
+
stdDev: number;
|
|
137
|
+
/** Confidence-weighted mean (higher confidence votes weighted more) */
|
|
138
|
+
weightedMean: number;
|
|
139
|
+
/** Number of votes included in aggregation */
|
|
140
|
+
voteCount: number;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Final decision on an artifact after critic evaluation.
|
|
144
|
+
*
|
|
145
|
+
* Represents the coordinator's decision after aggregating all critic votes
|
|
146
|
+
* and applying policy thresholds. Includes full audit trail of votes and
|
|
147
|
+
* reasoning.
|
|
148
|
+
*/
|
|
149
|
+
export interface NegotiationDecision {
|
|
150
|
+
/** Identifier of the artifact that was evaluated */
|
|
151
|
+
artifactId: string;
|
|
152
|
+
/** Final decision (approved, revision requested, escalated to HITL) */
|
|
153
|
+
outcome: DecisionOutcome;
|
|
154
|
+
/** Complete list of all critic votes considered */
|
|
155
|
+
votes: NegotiationVote[];
|
|
156
|
+
/** Statistical summary of the votes */
|
|
157
|
+
aggregatedScore: AggregatedScore;
|
|
158
|
+
/** Version identifier of the policy used for decision */
|
|
159
|
+
policyVersion: string;
|
|
160
|
+
/** Human-readable explanation of the decision */
|
|
161
|
+
reason: string;
|
|
162
|
+
/** Identifier for the negotiation room session */
|
|
163
|
+
negotiationRoomId: string;
|
|
164
|
+
/** Timestamp when decision was made (ISO-8601 string) */
|
|
165
|
+
decidedAt?: string;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Error thrown when a negotiation room operation times out.
|
|
169
|
+
*/
|
|
170
|
+
export declare class NegotiationTimeoutError extends Error {
|
|
171
|
+
constructor(message: string);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Error thrown when a negotiation room operation fails validation.
|
|
175
|
+
*/
|
|
176
|
+
export declare class NegotiationValidationError extends Error {
|
|
177
|
+
constructor(message: string);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Configuration options for NegotiationRoomClient.
|
|
181
|
+
*/
|
|
182
|
+
export interface NegotiationRoomClientOptions {
|
|
183
|
+
/**
|
|
184
|
+
* Storage backend for proposals, votes, and decisions.
|
|
185
|
+
* If not provided, uses the shared default in-memory store.
|
|
186
|
+
*/
|
|
187
|
+
store?: NegotiationRoomStore;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Client for interacting with negotiation rooms.
|
|
191
|
+
*
|
|
192
|
+
* Manages the lifecycle of artifact proposals through the multi-agent
|
|
193
|
+
* review process. Producers submit proposals, critics submit votes,
|
|
194
|
+
* and coordinators retrieve votes to make decisions.
|
|
195
|
+
*
|
|
196
|
+
* This client uses a pluggable storage backend, enabling state sharing
|
|
197
|
+
* across multiple client instances. By default, all clients within the
|
|
198
|
+
* same process share a common in-memory store.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* // Simple usage - all clients share default store
|
|
203
|
+
* const client = new NegotiationRoomClient();
|
|
204
|
+
*
|
|
205
|
+
* const proposal: NegotiationProposal = {
|
|
206
|
+
* artifactType: ArtifactType.CODE,
|
|
207
|
+
* artifactId: "code-123",
|
|
208
|
+
* producerId: "agent-producer",
|
|
209
|
+
* artifact: new TextEncoder().encode("def hello(): pass"),
|
|
210
|
+
* artifactContentType: "text/x-python",
|
|
211
|
+
* requestedCritics: ["critic-1", "critic-2"],
|
|
212
|
+
* negotiationRoomId: "room-1"
|
|
213
|
+
* };
|
|
214
|
+
* const artifactId = await client.submitProposal(proposal);
|
|
215
|
+
* console.log(artifactId); // "code-123"
|
|
216
|
+
* ```
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* // Explicit store sharing
|
|
221
|
+
* import { InMemoryNegotiationRoomStore } from './negotiationRoomStore';
|
|
222
|
+
*
|
|
223
|
+
* const store = new InMemoryNegotiationRoomStore();
|
|
224
|
+
* const producer = new NegotiationRoomClient({ store });
|
|
225
|
+
* const critic = new NegotiationRoomClient({ store });
|
|
226
|
+
*
|
|
227
|
+
* // Producer and critic now share state
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
export declare class NegotiationRoomClient {
|
|
231
|
+
private readonly store;
|
|
232
|
+
/**
|
|
233
|
+
* Create a new negotiation room client.
|
|
234
|
+
*
|
|
235
|
+
* @param options - Configuration options. If no store is provided,
|
|
236
|
+
* uses the shared default in-memory store.
|
|
237
|
+
*/
|
|
238
|
+
constructor(options?: NegotiationRoomClientOptions);
|
|
239
|
+
/**
|
|
240
|
+
* Submit an artifact proposal for multi-agent review.
|
|
241
|
+
*
|
|
242
|
+
* Stores the proposal and initializes empty vote tracking for the artifact.
|
|
243
|
+
* This method is typically called by producer agents.
|
|
244
|
+
*
|
|
245
|
+
* @param proposal - The negotiation proposal containing artifact details
|
|
246
|
+
* @returns The artifact_id of the submitted proposal
|
|
247
|
+
* @throws NegotiationValidationError if a proposal with the same artifact_id already exists
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* const client = new NegotiationRoomClient();
|
|
252
|
+
* const proposal: NegotiationProposal = {
|
|
253
|
+
* artifactType: ArtifactType.CODE,
|
|
254
|
+
* artifactId: "code-123",
|
|
255
|
+
* producerId: "agent-producer",
|
|
256
|
+
* artifact: new TextEncoder().encode("def hello(): pass"),
|
|
257
|
+
* artifactContentType: "text/x-python",
|
|
258
|
+
* requestedCritics: ["critic-1", "critic-2"],
|
|
259
|
+
* negotiationRoomId: "room-1"
|
|
260
|
+
* };
|
|
261
|
+
* const artifactId = await client.submitProposal(proposal);
|
|
262
|
+
* console.log(artifactId); // "code-123"
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
submitProposal(proposal: NegotiationProposal): Promise<string>;
|
|
266
|
+
/**
|
|
267
|
+
* Submit a critic's vote for an artifact.
|
|
268
|
+
*
|
|
269
|
+
* Adds the vote to the collection for the specified artifact.
|
|
270
|
+
* This method is typically called by critic agents after evaluating
|
|
271
|
+
* an artifact.
|
|
272
|
+
*
|
|
273
|
+
* @param vote - The negotiation vote containing the critic's evaluation
|
|
274
|
+
* @throws NegotiationValidationError if no proposal exists for the vote's artifact_id
|
|
275
|
+
* @throws NegotiationValidationError if the critic has already voted for this artifact
|
|
276
|
+
* @throws NegotiationValidationError if score or confidence are out of range
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```typescript
|
|
280
|
+
* const vote: NegotiationVote = {
|
|
281
|
+
* artifactId: "code-123",
|
|
282
|
+
* criticId: "critic-1",
|
|
283
|
+
* score: 8.5,
|
|
284
|
+
* confidence: 0.9,
|
|
285
|
+
* passed: true,
|
|
286
|
+
* strengths: ["Good structure"],
|
|
287
|
+
* weaknesses: ["Needs tests"],
|
|
288
|
+
* recommendations: ["Add unit tests"],
|
|
289
|
+
* negotiationRoomId: "room-1"
|
|
290
|
+
* };
|
|
291
|
+
* await client.submitVote(vote);
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
submitVote(vote: NegotiationVote): Promise<void>;
|
|
295
|
+
/**
|
|
296
|
+
* Retrieve all votes for a specific artifact.
|
|
297
|
+
*
|
|
298
|
+
* Returns all critic votes that have been submitted for the artifact.
|
|
299
|
+
* This method is typically called by coordinator agents to aggregate
|
|
300
|
+
* votes and make decisions.
|
|
301
|
+
*
|
|
302
|
+
* @param artifactId - The identifier of the artifact
|
|
303
|
+
* @returns List of all votes for the artifact (empty array if no votes yet)
|
|
304
|
+
* @throws NegotiationValidationError if no proposal exists for the artifact_id
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* const votes = await client.getVotes("code-123");
|
|
309
|
+
* console.log(votes.length); // 1
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
getVotes(artifactId: string): Promise<NegotiationVote[]>;
|
|
313
|
+
/**
|
|
314
|
+
* Retrieve the decision for a specific artifact if available.
|
|
315
|
+
*
|
|
316
|
+
* Returns the final decision if one has been made, or null if the
|
|
317
|
+
* artifact is still under review.
|
|
318
|
+
*
|
|
319
|
+
* @param artifactId - The identifier of the artifact
|
|
320
|
+
* @returns The negotiation decision if available, null otherwise
|
|
321
|
+
* @throws NegotiationValidationError if no proposal exists for the artifact_id
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```typescript
|
|
325
|
+
* const decision = await client.getDecision("code-123");
|
|
326
|
+
* if (decision === null) {
|
|
327
|
+
* console.log("Decision pending");
|
|
328
|
+
* }
|
|
329
|
+
* ```
|
|
330
|
+
*/
|
|
331
|
+
getDecision(artifactId: string): Promise<NegotiationDecision | null>;
|
|
332
|
+
/**
|
|
333
|
+
* Store a decision for an artifact.
|
|
334
|
+
*
|
|
335
|
+
* This is an internal method used by coordinators to record the
|
|
336
|
+
* final decision after evaluating votes. Once a decision is stored,
|
|
337
|
+
* it becomes available via getDecision() and waitForDecision().
|
|
338
|
+
*
|
|
339
|
+
* @param decision - The negotiation decision to store
|
|
340
|
+
* @throws NegotiationValidationError if no proposal exists for the decision's artifact_id
|
|
341
|
+
* @throws NegotiationValidationError if a decision already exists for this artifact
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```typescript
|
|
345
|
+
* const votes = await client.getVotes("code-123");
|
|
346
|
+
* const aggregated = aggregateVotes(votes);
|
|
347
|
+
* const decision: NegotiationDecision = {
|
|
348
|
+
* artifactId: "code-123",
|
|
349
|
+
* outcome: DecisionOutcome.APPROVED,
|
|
350
|
+
* votes: votes,
|
|
351
|
+
* aggregatedScore: aggregated,
|
|
352
|
+
* policyVersion: "1.0",
|
|
353
|
+
* reason: "Met all criteria",
|
|
354
|
+
* negotiationRoomId: "room-1"
|
|
355
|
+
* };
|
|
356
|
+
* await client.storeDecision(decision);
|
|
357
|
+
* ```
|
|
358
|
+
*/
|
|
359
|
+
storeDecision(decision: NegotiationDecision): Promise<void>;
|
|
360
|
+
/**
|
|
361
|
+
* Wait for a decision to be made on an artifact.
|
|
362
|
+
*
|
|
363
|
+
* Polls for a decision until one is available or the timeout is reached.
|
|
364
|
+
* This method is useful for producer agents waiting for the outcome
|
|
365
|
+
* of their artifact review.
|
|
366
|
+
*
|
|
367
|
+
* @param artifactId - The identifier of the artifact
|
|
368
|
+
* @param timeoutMs - Maximum time to wait in milliseconds (default: 30000)
|
|
369
|
+
* @param pollIntervalMs - Time between polling attempts in milliseconds (default: 100)
|
|
370
|
+
* @returns The negotiation decision once available
|
|
371
|
+
* @throws NegotiationValidationError if no proposal exists for the artifact_id
|
|
372
|
+
* @throws NegotiationTimeoutError if no decision is made within the timeout period
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```typescript
|
|
376
|
+
* // In a separate thread/process, a coordinator makes a decision
|
|
377
|
+
* const decision = await client.waitForDecision("code-123", 10000);
|
|
378
|
+
* console.log(decision.outcome); // DecisionOutcome.APPROVED
|
|
379
|
+
* ```
|
|
380
|
+
*/
|
|
381
|
+
waitForDecision(artifactId: string, timeoutMs?: number, pollIntervalMs?: number): Promise<NegotiationDecision>;
|
|
382
|
+
/**
|
|
383
|
+
* Retrieve the original proposal for an artifact.
|
|
384
|
+
*
|
|
385
|
+
* Useful for critics that need to review the original artifact
|
|
386
|
+
* before submitting a vote.
|
|
387
|
+
*
|
|
388
|
+
* @param artifactId - The identifier of the artifact
|
|
389
|
+
* @returns The negotiation proposal if it exists, null otherwise
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```typescript
|
|
393
|
+
* const proposal = await client.getProposal("code-123");
|
|
394
|
+
* console.log(proposal?.artifactType); // ArtifactType.CODE
|
|
395
|
+
* ```
|
|
396
|
+
*/
|
|
397
|
+
getProposal(artifactId: string): Promise<NegotiationProposal | null>;
|
|
398
|
+
/**
|
|
399
|
+
* List all proposals, optionally filtered by negotiation room.
|
|
400
|
+
*
|
|
401
|
+
* @param negotiationRoomId - If provided, only return proposals for this room
|
|
402
|
+
* @returns List of proposals matching the filter criteria
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```typescript
|
|
406
|
+
* const proposals = await client.listProposals("room-1");
|
|
407
|
+
* console.log(proposals.length); // 1
|
|
408
|
+
* ```
|
|
409
|
+
*/
|
|
410
|
+
listProposals(negotiationRoomId?: string): Promise<NegotiationProposal[]>;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Aggregate multiple critic votes into statistical summary.
|
|
414
|
+
*
|
|
415
|
+
* Computes both basic statistics (mean, min, max, std dev) and a
|
|
416
|
+
* confidence-weighted mean that gives more weight to votes from critics
|
|
417
|
+
* with higher confidence levels.
|
|
418
|
+
*
|
|
419
|
+
* @param votes - List of critic votes to aggregate
|
|
420
|
+
* @returns AggregatedScore with statistical summary of votes
|
|
421
|
+
* @throws NegotiationValidationError if votes list is empty
|
|
422
|
+
*/
|
|
423
|
+
export declare function aggregateVotes(votes: NegotiationVote[]): AggregatedScore;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Negotiation Room storage backend abstraction.
|
|
3
|
+
*
|
|
4
|
+
* This module provides a pluggable storage layer for NegotiationRoomClient,
|
|
5
|
+
* enabling shared state across multiple client instances.
|
|
6
|
+
*
|
|
7
|
+
* The key insight is that NegotiationRoomClient previously used instance-local
|
|
8
|
+
* storage (private Maps), which broke multi-instance deployments. By extracting
|
|
9
|
+
* storage into a separate abstraction that can be shared, we enable:
|
|
10
|
+
*
|
|
11
|
+
* 1. Multiple client instances sharing the same storage
|
|
12
|
+
* 2. Producer/Critic/Coordinator agents in different processes sharing state
|
|
13
|
+
* 3. Future gRPC integration where the server becomes the source of truth
|
|
14
|
+
*
|
|
15
|
+
* For persistent storage backends (JSON file, Redis, PostgreSQL), see the
|
|
16
|
+
* colony/stores module which provides optional persistence implementations.
|
|
17
|
+
*
|
|
18
|
+
* Based on the PolicyStore pattern established in policyStore.ts.
|
|
19
|
+
*/
|
|
20
|
+
import { NegotiationProposal, NegotiationVote, NegotiationDecision } from './negotiationRoom.js';
|
|
21
|
+
/**
|
|
22
|
+
* Error thrown when a negotiation room store operation fails.
|
|
23
|
+
*/
|
|
24
|
+
export declare class NegotiationRoomStoreError extends Error {
|
|
25
|
+
constructor(message: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Interface defining the contract for negotiation room storage backends.
|
|
29
|
+
*
|
|
30
|
+
* All storage implementations must support these operations for proposals,
|
|
31
|
+
* votes, and decisions. This follows the same pattern as PolicyStore,
|
|
32
|
+
* enabling pluggable backends ranging from in-memory to file-based to gRPC-based.
|
|
33
|
+
*/
|
|
34
|
+
export interface NegotiationRoomStore {
|
|
35
|
+
/**
|
|
36
|
+
* Check if a proposal exists for the given artifact_id.
|
|
37
|
+
*
|
|
38
|
+
* @param artifactId - Unique identifier for the artifact
|
|
39
|
+
* @returns True if a proposal exists, false otherwise
|
|
40
|
+
*/
|
|
41
|
+
hasProposal(artifactId: string): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Retrieve a proposal by artifact_id.
|
|
44
|
+
*
|
|
45
|
+
* @param artifactId - Unique identifier for the artifact
|
|
46
|
+
* @returns The proposal if found, null otherwise
|
|
47
|
+
*/
|
|
48
|
+
getProposal(artifactId: string): Promise<NegotiationProposal | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Save a proposal to storage.
|
|
51
|
+
*
|
|
52
|
+
* @param proposal - The proposal to save
|
|
53
|
+
* @throws NegotiationRoomStoreError if a proposal with the same artifact_id already exists
|
|
54
|
+
*/
|
|
55
|
+
saveProposal(proposal: NegotiationProposal): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* List all proposals, optionally filtered by negotiation room.
|
|
58
|
+
*
|
|
59
|
+
* @param negotiationRoomId - If provided, only return proposals for this room
|
|
60
|
+
* @returns List of proposals matching the filter criteria
|
|
61
|
+
*/
|
|
62
|
+
listProposals(negotiationRoomId?: string): Promise<NegotiationProposal[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Retrieve all votes for a specific artifact.
|
|
65
|
+
*
|
|
66
|
+
* @param artifactId - The identifier of the artifact
|
|
67
|
+
* @returns List of all votes for the artifact (empty array if no votes)
|
|
68
|
+
*/
|
|
69
|
+
getVotes(artifactId: string): Promise<NegotiationVote[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Add a vote for an artifact.
|
|
72
|
+
*
|
|
73
|
+
* @param vote - The vote to add
|
|
74
|
+
* @throws NegotiationRoomStoreError if the critic has already voted for this artifact
|
|
75
|
+
*/
|
|
76
|
+
addVote(vote: NegotiationVote): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Retrieve the decision for an artifact.
|
|
79
|
+
*
|
|
80
|
+
* @param artifactId - The identifier of the artifact
|
|
81
|
+
* @returns The decision if available, null otherwise
|
|
82
|
+
*/
|
|
83
|
+
getDecision(artifactId: string): Promise<NegotiationDecision | null>;
|
|
84
|
+
/**
|
|
85
|
+
* Save a decision for an artifact.
|
|
86
|
+
*
|
|
87
|
+
* @param decision - The decision to save
|
|
88
|
+
* @throws NegotiationRoomStoreError if a decision already exists for this artifact
|
|
89
|
+
*/
|
|
90
|
+
saveDecision(decision: NegotiationDecision): Promise<void>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* In-memory implementation of NegotiationRoomStore.
|
|
94
|
+
*
|
|
95
|
+
* Stores proposals, votes, and decisions in memory. Data is lost when the
|
|
96
|
+
* process terminates. Suitable for testing and single-process deployments.
|
|
97
|
+
*
|
|
98
|
+
* Thread-safety: JavaScript is single-threaded, but async operations are
|
|
99
|
+
* properly sequenced.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* // Create a single shared store
|
|
104
|
+
* const sharedStore = new InMemoryNegotiationRoomStore();
|
|
105
|
+
*
|
|
106
|
+
* // Pass to multiple clients
|
|
107
|
+
* const producerClient = new NegotiationRoomClient({ store: sharedStore });
|
|
108
|
+
* const criticClient = new NegotiationRoomClient({ store: sharedStore });
|
|
109
|
+
* const coordinatorClient = new NegotiationRoomClient({ store: sharedStore });
|
|
110
|
+
*
|
|
111
|
+
* // Now all clients share the same state
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare class InMemoryNegotiationRoomStore implements NegotiationRoomStore {
|
|
115
|
+
private proposals;
|
|
116
|
+
private votes;
|
|
117
|
+
private decisions;
|
|
118
|
+
hasProposal(artifactId: string): Promise<boolean>;
|
|
119
|
+
getProposal(artifactId: string): Promise<NegotiationProposal | null>;
|
|
120
|
+
saveProposal(proposal: NegotiationProposal): Promise<void>;
|
|
121
|
+
listProposals(negotiationRoomId?: string): Promise<NegotiationProposal[]>;
|
|
122
|
+
getVotes(artifactId: string): Promise<NegotiationVote[]>;
|
|
123
|
+
addVote(vote: NegotiationVote): Promise<void>;
|
|
124
|
+
getDecision(artifactId: string): Promise<NegotiationDecision | null>;
|
|
125
|
+
saveDecision(decision: NegotiationDecision): Promise<void>;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get the default shared in-memory store.
|
|
129
|
+
*
|
|
130
|
+
* This provides a convenient way to share state across multiple
|
|
131
|
+
* NegotiationRoomClient instances within the same process without
|
|
132
|
+
* explicitly passing a store instance.
|
|
133
|
+
*
|
|
134
|
+
* @returns The default shared InMemoryNegotiationRoomStore instance
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* // All clients automatically share the same store
|
|
139
|
+
* const client1 = new NegotiationRoomClient(); // Uses default store
|
|
140
|
+
* const client2 = new NegotiationRoomClient(); // Uses same default store
|
|
141
|
+
*
|
|
142
|
+
* // Equivalent to:
|
|
143
|
+
* const store = getDefaultStore();
|
|
144
|
+
* const client1 = new NegotiationRoomClient({ store });
|
|
145
|
+
* const client2 = new NegotiationRoomClient({ store });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export declare function getDefaultStore(): InMemoryNegotiationRoomStore;
|
|
149
|
+
/**
|
|
150
|
+
* Reset the default store (primarily for testing).
|
|
151
|
+
*
|
|
152
|
+
* This clears the default store singleton, causing a new store
|
|
153
|
+
* to be created on the next call to getDefaultStore().
|
|
154
|
+
*/
|
|
155
|
+
export declare function resetDefaultStore(): void;
|