@sw4rm/js-sdk 0.4.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.
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Addresses for SW4RM services.
3
+ *
4
+ * All service endpoints with their default ports. Individual addresses
5
+ * can be overridden via environment variables or programmatic configuration.
6
+ */
7
+ export interface Endpoints {
8
+ /** Router service address (default: http://localhost:50051) */
9
+ router: string;
10
+ /** Registry service address (default: http://localhost:50052) */
11
+ registry: string;
12
+ /** Scheduler service address (default: http://localhost:50053) */
13
+ scheduler: string;
14
+ /** Human-in-the-loop service address (default: http://localhost:50054) */
15
+ hitl: string;
16
+ /** Worktree service address (default: http://localhost:50055) */
17
+ worktree: string;
18
+ /** Tool execution service address (default: http://localhost:50056) */
19
+ tool: string;
20
+ /** Connector service address (default: http://localhost:50057) */
21
+ connector: string;
22
+ /** Negotiation service address (default: http://localhost:50058) */
23
+ negotiation: string;
24
+ /** Reasoning service address (default: http://localhost:50059) */
25
+ reasoning: string;
26
+ /** Logging service address (default: http://localhost:50060) */
27
+ logging: string;
28
+ }
29
+ /**
30
+ * Retry policy for unary gRPC calls.
31
+ *
32
+ * Controls exponential backoff behavior for transient failures.
33
+ */
34
+ export interface RetryPolicy {
35
+ /** Maximum number of retry attempts (default: 3) */
36
+ maxAttempts: number;
37
+ /** Initial backoff delay in milliseconds (default: 200) */
38
+ initialBackoffMs: number;
39
+ /** Maximum backoff delay in milliseconds (default: 2000) */
40
+ maxBackoffMs: number;
41
+ /** Backoff multiplier for exponential backoff (default: 2) */
42
+ multiplier: number;
43
+ }
44
+ /**
45
+ * Agent runtime configuration.
46
+ *
47
+ * Complete configuration object for an SW4RM agent including:
48
+ * - Identity (agent_id, name, description)
49
+ * - Service endpoints
50
+ * - Timeouts and retry policies
51
+ * - Capabilities and metadata
52
+ */
53
+ export interface AgentConfig {
54
+ /** Unique agent identifier */
55
+ agentId: string;
56
+ /** Human-readable agent name */
57
+ name: string;
58
+ /** Optional agent description */
59
+ description?: string;
60
+ /** Agent version (default: "0.1.0") */
61
+ version: string;
62
+ /** List of agent capabilities */
63
+ capabilities: string[];
64
+ /** Service endpoints configuration */
65
+ endpoints: Endpoints;
66
+ /** Request timeout in milliseconds (default: 30000) */
67
+ timeoutMs: number;
68
+ /** Stream keepalive interval in milliseconds (default: 60000) */
69
+ streamKeepaliveMs: number;
70
+ /** Retry policy for unary calls */
71
+ retry: RetryPolicy;
72
+ /** Additional metadata key-value pairs */
73
+ metadata: Record<string, string>;
74
+ /** Communication class (0=UNSPECIFIED, 1=PRIVILEGED, 2=STANDARD, 3=BULK) */
75
+ communicationClass: number;
76
+ /** Supported modalities (e.g., ["application/json", "text/plain"]) */
77
+ modalitiesSupported: string[];
78
+ /** Reasoning connectors this agent can use */
79
+ reasoningConnectors: string[];
80
+ /** Optional public key for cryptographic operations */
81
+ publicKey?: Uint8Array;
82
+ }
83
+ /**
84
+ * Comprehensive SW4RM SDK configuration.
85
+ *
86
+ * Extended configuration object that includes all SDK settings:
87
+ * - Service endpoints
88
+ * - Timeouts and retry policies
89
+ * - Observability flags (metrics, tracing)
90
+ * - Feature flags
91
+ * - Logging configuration
92
+ */
93
+ export interface SW4RMConfig {
94
+ /** Router service address */
95
+ routerAddr: string;
96
+ /** Registry service address */
97
+ registryAddr: string;
98
+ /** Default timeout for operations in milliseconds (default: 30000) */
99
+ defaultTimeoutMs: number;
100
+ /** Maximum number of retry attempts (default: 3) */
101
+ maxRetries: number;
102
+ /** Enable metrics collection and export (default: true) */
103
+ enableMetrics: boolean;
104
+ /** Enable distributed tracing (default: true) */
105
+ enableTracing: boolean;
106
+ /** Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL (default: INFO) */
107
+ logLevel: string;
108
+ /** Feature flag mappings (name -> value) */
109
+ featureFlags: Record<string, any>;
110
+ }
111
+ /**
112
+ * Get default endpoints with environment variable overrides.
113
+ *
114
+ * Environment variables supported:
115
+ * - SW4RM_ROUTER_ADDR
116
+ * - SW4RM_REGISTRY_ADDR
117
+ * - SW4RM_SCHEDULER_ADDR
118
+ * - SW4RM_HITL_ADDR
119
+ * - SW4RM_WORKTREE_ADDR
120
+ * - SW4RM_TOOL_ADDR
121
+ * - SW4RM_CONNECTOR_ADDR
122
+ * - SW4RM_NEGOTIATION_ADDR
123
+ * - SW4RM_REASONING_ADDR
124
+ * - SW4RM_LOGGING_ADDR
125
+ *
126
+ * @returns Endpoints configuration with env overrides applied
127
+ */
128
+ export declare function defaultEndpoints(): Endpoints;
129
+ /**
130
+ * Get default retry policy.
131
+ *
132
+ * @returns RetryPolicy with standard exponential backoff settings
133
+ */
134
+ export declare function defaultRetryPolicy(): RetryPolicy;
135
+ /**
136
+ * Create a default agent configuration.
137
+ *
138
+ * Provides sensible defaults for all fields. Applications should override
139
+ * at least agentId and name for production use.
140
+ *
141
+ * @param agentId - Optional agent ID (default: "agent-1")
142
+ * @param name - Optional agent name (default: "Agent")
143
+ * @returns AgentConfig with defaults populated
144
+ */
145
+ export declare function defaultAgentConfig(agentId?: string, name?: string): AgentConfig;
146
+ /**
147
+ * Load agent configuration from environment variables.
148
+ *
149
+ * Environment variables supported:
150
+ * - AGENT_ID: Agent identifier
151
+ * - AGENT_NAME: Agent name
152
+ * - AGENT_DESCRIPTION: Agent description
153
+ * - AGENT_VERSION: Agent version
154
+ * - AGENT_CAPABILITIES: Comma-separated list of capabilities
155
+ * - SW4RM_TIMEOUT_MS: Request timeout in milliseconds
156
+ * - SW4RM_STREAM_KEEPALIVE_MS: Stream keepalive in milliseconds
157
+ * - SW4RM_RETRY_MAX_ATTEMPTS: Maximum retry attempts
158
+ * - SW4RM_COMMUNICATION_CLASS: Communication class (0-3)
159
+ * - All endpoint environment variables (SW4RM_*_ADDR)
160
+ *
161
+ * @returns AgentConfig populated from environment
162
+ */
163
+ export declare function loadConfigFromEnv(): AgentConfig;
164
+ /**
165
+ * Create default SW4RMConfig with environment overrides.
166
+ *
167
+ * @returns SW4RMConfig with defaults and env overrides
168
+ */
169
+ export declare function defaultSW4RMConfig(): SW4RMConfig;
170
+ /**
171
+ * Load SW4RM configuration from file or environment.
172
+ *
173
+ * Configuration loading order (later sources override earlier ones):
174
+ * 1. Default values
175
+ * 2. Configuration file (if path provided)
176
+ * 3. Environment variables (SW4RM_* prefix)
177
+ *
178
+ * Supported file formats:
179
+ * - JSON (.json)
180
+ *
181
+ * @param configPath - Optional path to configuration file
182
+ * @returns SW4RMConfig instance
183
+ * @throws Error if file doesn't exist or is invalid JSON
184
+ *
185
+ * @example
186
+ * // Load from file and environment
187
+ * const config = loadConfig('/etc/sw4rm/config.json');
188
+ *
189
+ * @example
190
+ * // Load from environment only
191
+ * const config = loadConfig();
192
+ *
193
+ * Environment variables:
194
+ * - SW4RM_ROUTER_ADDR: Router service address
195
+ * - SW4RM_REGISTRY_ADDR: Registry service address
196
+ * - SW4RM_DEFAULT_TIMEOUT_MS: Default timeout in milliseconds
197
+ * - SW4RM_MAX_RETRIES: Maximum retry attempts
198
+ * - SW4RM_ENABLE_METRICS: Enable metrics collection (true/false)
199
+ * - SW4RM_ENABLE_TRACING: Enable tracing (true/false)
200
+ * - SW4RM_LOG_LEVEL: Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
201
+ */
202
+ export declare function loadConfig(configPath?: string): SW4RMConfig;
203
+ /**
204
+ * Get the global SW4RM configuration.
205
+ *
206
+ * Returns the singleton configuration instance. If no configuration has been
207
+ * loaded yet, creates a new one using environment variables.
208
+ *
209
+ * @returns Global SW4RMConfig instance
210
+ *
211
+ * @example
212
+ * const config = getConfig();
213
+ * console.log(`Router: ${config.routerAddr}`);
214
+ * console.log(`Metrics enabled: ${config.enableMetrics}`);
215
+ */
216
+ export declare function getConfig(): SW4RMConfig;
217
+ /**
218
+ * Set the global SW4RM configuration.
219
+ *
220
+ * This allows applications to programmatically configure the SDK
221
+ * instead of using files or environment variables.
222
+ *
223
+ * @param config - SW4RMConfig instance to set as global
224
+ *
225
+ * @example
226
+ * const config: SW4RMConfig = {
227
+ * routerAddr: 'localhost:50051',
228
+ * registryAddr: 'localhost:50052',
229
+ * defaultTimeoutMs: 30000,
230
+ * maxRetries: 3,
231
+ * enableMetrics: false,
232
+ * enableTracing: true,
233
+ * logLevel: 'DEBUG',
234
+ * featureFlags: {}
235
+ * };
236
+ * setConfig(config);
237
+ */
238
+ export declare function setConfig(config: SW4RMConfig): void;
239
+ /**
240
+ * Reset the global configuration (primarily for testing).
241
+ *
242
+ * Clears the singleton instance, forcing the next getConfig() call
243
+ * to reload from environment/defaults.
244
+ */
245
+ export declare function resetConfig(): void;
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Represents a cryptographic or logical proof for an audit event.
3
+ */
4
+ export interface AuditProof {
5
+ /** Unique identifier for this proof */
6
+ proof_id: string;
7
+ /** Type of proof (e.g., "simple_hash", "zk_proof", "signature") */
8
+ proof_type: string;
9
+ /** The actual proof data as bytes */
10
+ proof_data: Uint8Array;
11
+ /** Timestamp when the proof was created (HLC or unix ms) */
12
+ created_at: string;
13
+ /** Whether this proof has been verified */
14
+ verified: boolean;
15
+ }
16
+ /**
17
+ * Defines audit requirements for envelope processing.
18
+ */
19
+ export interface AuditPolicy {
20
+ /** Unique identifier for this policy */
21
+ policy_id: string;
22
+ /** Whether proof is required for this policy */
23
+ require_proof: boolean;
24
+ /** Level of verification required (e.g., "none", "basic", "strict") */
25
+ verification_level: string;
26
+ /** How many days to retain audit records */
27
+ retention_days: number;
28
+ }
29
+ /**
30
+ * Represents a complete audit record for an envelope action.
31
+ */
32
+ export interface AuditRecord {
33
+ /** Unique identifier for this audit record */
34
+ record_id: string;
35
+ /** The message_id of the envelope being audited */
36
+ envelope_id: string;
37
+ /** The action performed (e.g., "send", "receive", "process") */
38
+ action: string;
39
+ /** ID of the agent/component that performed the action */
40
+ actor_id: string;
41
+ /** When the action occurred (HLC or unix ms) */
42
+ timestamp: string;
43
+ /** Optional proof associated with this action */
44
+ proof?: AuditProof;
45
+ }
46
+ /**
47
+ * Envelope-like object for audit operations.
48
+ * This is a minimal interface that matches the expected envelope structure.
49
+ */
50
+ export interface EnvelopeAuditable {
51
+ message_id?: string;
52
+ producer_id?: string;
53
+ payload?: Uint8Array;
54
+ audit_proof?: Uint8Array;
55
+ [key: string]: any;
56
+ }
57
+ /**
58
+ * Protocol defining the interface for audit implementations.
59
+ *
60
+ * Implementations can range from no-op (for development) to full
61
+ * ZK-proof based systems (for production).
62
+ */
63
+ export interface Auditor {
64
+ /**
65
+ * Create a proof for an envelope action.
66
+ *
67
+ * @param envelope - The envelope to create proof for
68
+ * @param action - The action being performed (e.g., "send", "receive")
69
+ * @returns An AuditProof instance
70
+ */
71
+ createProof(envelope: EnvelopeAuditable, action: string): AuditProof;
72
+ /**
73
+ * Verify the validity of a proof.
74
+ *
75
+ * @param proof - The proof to verify
76
+ * @returns True if proof is valid, false otherwise
77
+ */
78
+ verifyProof(proof: AuditProof): boolean;
79
+ /**
80
+ * Record an audit event.
81
+ *
82
+ * @param envelope - The envelope being audited
83
+ * @param action - The action being performed
84
+ * @param proof - Optional proof to attach to the record
85
+ * @returns The created AuditRecord
86
+ */
87
+ record(envelope: EnvelopeAuditable, action: string, proof?: AuditProof): AuditRecord;
88
+ /**
89
+ * Query audit records for a specific envelope.
90
+ *
91
+ * @param envelope_id - The message_id of the envelope to query
92
+ * @returns List of AuditRecords for this envelope
93
+ */
94
+ query(envelope_id: string): AuditRecord[];
95
+ }
96
+ /**
97
+ * Compute SHA256 hash of an envelope.
98
+ *
99
+ * @param envelope - The envelope to hash
100
+ * @returns Hex-encoded SHA256 hash of the envelope
101
+ */
102
+ export declare function computeEnvelopeHash(envelope: EnvelopeAuditable): string;
103
+ /**
104
+ * Create a simple hash-based proof for an envelope.
105
+ *
106
+ * This is a basic proof mechanism suitable for testing and development.
107
+ * Production systems should use more sophisticated proof mechanisms
108
+ * (e.g., ZK-proofs, digital signatures).
109
+ *
110
+ * @param envelope - The envelope to create proof for
111
+ * @param actor_id - ID of the actor creating the proof
112
+ * @returns An AuditProof with simple hash-based proof
113
+ */
114
+ export declare function createSimpleProof(envelope: EnvelopeAuditable, actor_id: string): AuditProof;
115
+ /**
116
+ * Verify an audit proof against an envelope.
117
+ *
118
+ * @param envelope - The envelope to verify against
119
+ * @param proof - The proof to verify
120
+ * @returns True if proof is valid, false otherwise
121
+ */
122
+ export declare function verifyAuditProof(envelope: EnvelopeAuditable, proof: AuditProof): boolean;
123
+ /**
124
+ * No-op auditor that does nothing.
125
+ *
126
+ * Useful for development and when audit trail is not required.
127
+ */
128
+ export declare class NoOpAuditor implements Auditor {
129
+ /**
130
+ * Create a minimal no-op proof.
131
+ *
132
+ * @param envelope - The envelope (ignored)
133
+ * @param action - The action (ignored)
134
+ * @returns A minimal no-op proof
135
+ */
136
+ createProof(envelope: EnvelopeAuditable, action: string): AuditProof;
137
+ /**
138
+ * Always returns true for no-op proofs.
139
+ *
140
+ * @param proof - The proof (ignored)
141
+ * @returns Always true
142
+ */
143
+ verifyProof(proof: AuditProof): boolean;
144
+ /**
145
+ * Create a minimal audit record without storing it.
146
+ *
147
+ * @param envelope - The envelope being audited
148
+ * @param action - The action being performed
149
+ * @param proof - Optional proof to attach
150
+ * @returns A minimal audit record
151
+ */
152
+ record(envelope: EnvelopeAuditable, action: string, proof?: AuditProof): AuditRecord;
153
+ /**
154
+ * Always returns empty array.
155
+ *
156
+ * @param envelope_id - The envelope ID (ignored)
157
+ * @returns Empty array
158
+ */
159
+ query(envelope_id: string): AuditRecord[];
160
+ }
161
+ /**
162
+ * In-memory auditor for testing and development.
163
+ *
164
+ * Stores audit records in memory and supports basic querying.
165
+ * Not suitable for production use.
166
+ */
167
+ export declare class InMemoryAuditor implements Auditor {
168
+ private _records;
169
+ /**
170
+ * Initialize with empty record storage.
171
+ */
172
+ constructor();
173
+ /**
174
+ * Create a simple hash-based proof.
175
+ *
176
+ * @param envelope - The envelope to create proof for
177
+ * @param action - The action being performed
178
+ * @returns A simple hash-based proof
179
+ */
180
+ createProof(envelope: EnvelopeAuditable, action: string): AuditProof;
181
+ /**
182
+ * Verify a proof using the verification module.
183
+ *
184
+ * @param proof - The proof to verify
185
+ * @returns True if proof is valid, false otherwise
186
+ */
187
+ verifyProof(proof: AuditProof): boolean;
188
+ /**
189
+ * Create and store an audit record.
190
+ *
191
+ * @param envelope - The envelope being audited
192
+ * @param action - The action being performed
193
+ * @param proof - Optional proof to attach
194
+ * @returns The created audit record
195
+ */
196
+ record(envelope: EnvelopeAuditable, action: string, proof?: AuditProof): AuditRecord;
197
+ /**
198
+ * Query all audit records for a specific envelope.
199
+ *
200
+ * @param envelope_id - The message_id of the envelope to query
201
+ * @returns List of audit records for this envelope
202
+ */
203
+ query(envelope_id: string): AuditRecord[];
204
+ /**
205
+ * Get all audit records (useful for testing).
206
+ *
207
+ * @returns All audit records across all envelopes
208
+ */
209
+ getAllRecords(): AuditRecord[];
210
+ /**
211
+ * Clear all stored records (useful for testing).
212
+ */
213
+ clear(): void;
214
+ }
@@ -10,7 +10,37 @@
10
10
  * - Coordinating the review process
11
11
  *
12
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
+ * ```
13
42
  */
43
+ import { NegotiationRoomStore } from './negotiationRoomStore.js';
14
44
  /**
15
45
  * Type of artifact being negotiated.
16
46
  *
@@ -146,6 +176,16 @@ export declare class NegotiationTimeoutError extends Error {
146
176
  export declare class NegotiationValidationError extends Error {
147
177
  constructor(message: string);
148
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
+ }
149
189
  /**
150
190
  * Client for interacting with negotiation rooms.
151
191
  *
@@ -153,13 +193,49 @@ export declare class NegotiationValidationError extends Error {
153
193
  * review process. Producers submit proposals, critics submit votes,
154
194
  * and coordinators retrieve votes to make decisions.
155
195
  *
156
- * This is an in-memory implementation for Phase 2. Future phases
157
- * will integrate with persistent storage and gRPC services.
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
+ * ```
158
229
  */
159
230
  export declare class NegotiationRoomClient {
160
- private proposals;
161
- private votes;
162
- private decisions;
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);
163
239
  /**
164
240
  * Submit an artifact proposal for multi-agent review.
165
241
  *