@komputer-ai/sdk 0.11.7 → 0.11.8

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 CHANGED
@@ -127,6 +127,23 @@ for await (const event of stream) {
127
127
  }
128
128
  ```
129
129
 
130
+ #### Distributed consumers — `{ group }`
131
+
132
+ By default, `watchAgent` opens a **broadcast** subscription: every connected client receives every event. If you run multiple instances of your service (e.g. 3 replicas of a Slack bot) and they all call `client.watchAgent("my-agent")` without further options, **each instance will process every event** — duplicate work.
133
+
134
+ To get queue-style delivery (each event handled by exactly one instance across your fleet), pass `{ group }`:
135
+
136
+ ```ts
137
+ const stream = await client.watchAgent("my-agent", { group: "my-bot" });
138
+ ```
139
+
140
+ The API uses Redis-coordinated routing to deliver each event to exactly one client per group, regardless of how many replicas connect or which API replica they hit. Pick any string for the group name (`my-bot`, `audit-pipeline`, `prod-webhook-fwd`).
141
+
142
+ **Use broadcast** for: dashboards, debugging, single-instance workers, anywhere "see everything" is the goal.
143
+ **Use `{ group }`** for: distributed services, webhook forwarders, anywhere you'd otherwise dedupe events yourself.
144
+
145
+ On write failure, the API retries delivery to other group members on the same replica before giving up — an event is only lost when all members on the routing replica fail simultaneously. Use `client.getAgentEvents({ name, limit: ... })` to backfill on reconnect if you need strict exactly-once guarantees.
146
+
130
147
  ### Direct API access
131
148
 
132
149
  For advanced use cases, the underlying generated API clients are available:
package/dist/client.d.ts CHANGED
@@ -171,5 +171,17 @@ export declare class KomputerClient {
171
171
  listTemplates(): Promise<{
172
172
  [key: string]: any;
173
173
  }>;
174
- watchAgent(name: string): Promise<AgentEventStream>;
174
+ /**
175
+ * Stream live agent events.
176
+ *
177
+ * @param name Agent name.
178
+ * @param options.group Optional consumer group name. When set, this watcher joins
179
+ * a group and each event is delivered to exactly one client per group across all
180
+ * API replicas — useful when running multiple SDK instances in a distributed system
181
+ * that should not each process the same event. Without `group`, every connected
182
+ * client receives every event (broadcast).
183
+ */
184
+ watchAgent(name: string, options?: {
185
+ group?: string;
186
+ }): Promise<AgentEventStream>;
175
187
  }
package/dist/client.js CHANGED
@@ -268,7 +268,17 @@ class KomputerClient {
268
268
  });
269
269
  }
270
270
  // --- WebSocket ---
271
- watchAgent(name) {
271
+ /**
272
+ * Stream live agent events.
273
+ *
274
+ * @param name Agent name.
275
+ * @param options.group Optional consumer group name. When set, this watcher joins
276
+ * a group and each event is delivered to exactly one client per group across all
277
+ * API replicas — useful when running multiple SDK instances in a distributed system
278
+ * that should not each process the same event. Without `group`, every connected
279
+ * client receives every event (broadcast).
280
+ */
281
+ watchAgent(name, options) {
272
282
  return __awaiter(this, void 0, void 0, function* () {
273
283
  const wsUrl = this._baseUrl.replace("http://", "ws://").replace("https://", "wss://");
274
284
  let history = [];
@@ -286,7 +296,7 @@ class KomputerClient {
286
296
  catch (_a) {
287
297
  // History fetch failed — proceed with live-only.
288
298
  }
289
- return new watch_1.AgentEventStream(wsUrl, name, history);
299
+ return new watch_1.AgentEventStream(wsUrl, name, history, options === null || options === void 0 ? void 0 : options.group);
290
300
  });
291
301
  }
292
302
  }
@@ -171,5 +171,17 @@ export declare class KomputerClient {
171
171
  listTemplates(): Promise<{
172
172
  [key: string]: any;
173
173
  }>;
174
- watchAgent(name: string): Promise<AgentEventStream>;
174
+ /**
175
+ * Stream live agent events.
176
+ *
177
+ * @param name Agent name.
178
+ * @param options.group Optional consumer group name. When set, this watcher joins
179
+ * a group and each event is delivered to exactly one client per group across all
180
+ * API replicas — useful when running multiple SDK instances in a distributed system
181
+ * that should not each process the same event. Without `group`, every connected
182
+ * client receives every event (broadcast).
183
+ */
184
+ watchAgent(name: string, options?: {
185
+ group?: string;
186
+ }): Promise<AgentEventStream>;
175
187
  }
@@ -265,7 +265,17 @@ export class KomputerClient {
265
265
  });
266
266
  }
267
267
  // --- WebSocket ---
268
- watchAgent(name) {
268
+ /**
269
+ * Stream live agent events.
270
+ *
271
+ * @param name Agent name.
272
+ * @param options.group Optional consumer group name. When set, this watcher joins
273
+ * a group and each event is delivered to exactly one client per group across all
274
+ * API replicas — useful when running multiple SDK instances in a distributed system
275
+ * that should not each process the same event. Without `group`, every connected
276
+ * client receives every event (broadcast).
277
+ */
278
+ watchAgent(name, options) {
269
279
  return __awaiter(this, void 0, void 0, function* () {
270
280
  const wsUrl = this._baseUrl.replace("http://", "ws://").replace("https://", "wss://");
271
281
  let history = [];
@@ -283,7 +293,7 @@ export class KomputerClient {
283
293
  catch (_a) {
284
294
  // History fetch failed — proceed with live-only.
285
295
  }
286
- return new AgentEventStream(wsUrl, name, history);
296
+ return new AgentEventStream(wsUrl, name, history, options === null || options === void 0 ? void 0 : options.group);
287
297
  });
288
298
  }
289
299
  }
@@ -25,7 +25,7 @@ export declare class AgentEventStream implements AsyncIterable<AgentEvent> {
25
25
  private resolve;
26
26
  private done;
27
27
  private seen;
28
- constructor(wsUrl: string, agentName: string, historyEvents?: AgentEvent[]);
28
+ constructor(wsUrl: string, agentName: string, historyEvents?: AgentEvent[], group?: string);
29
29
  private dedupKey;
30
30
  [Symbol.asyncIterator](): AsyncIterator<AgentEvent>;
31
31
  close(): void;
package/dist/esm/watch.js CHANGED
@@ -13,7 +13,7 @@
13
13
  * }
14
14
  */
15
15
  export class AgentEventStream {
16
- constructor(wsUrl, agentName, historyEvents) {
16
+ constructor(wsUrl, agentName, historyEvents, group) {
17
17
  this.queue = [];
18
18
  this.resolve = null;
19
19
  this.done = false;
@@ -27,7 +27,11 @@ export class AgentEventStream {
27
27
  this.queue.push(e);
28
28
  }
29
29
  }
30
- this.ws = new WebSocket(`${wsUrl}/api/v1/agents/${agentName}/ws`);
30
+ let endpoint = `${wsUrl}/api/v1/agents/${agentName}/ws`;
31
+ if (group) {
32
+ endpoint += `?group=${encodeURIComponent(group)}`;
33
+ }
34
+ this.ws = new WebSocket(endpoint);
31
35
  this.ws.onmessage = (event) => {
32
36
  const data = JSON.parse(event.data);
33
37
  const agentEvent = {
package/dist/watch.d.ts CHANGED
@@ -25,7 +25,7 @@ export declare class AgentEventStream implements AsyncIterable<AgentEvent> {
25
25
  private resolve;
26
26
  private done;
27
27
  private seen;
28
- constructor(wsUrl: string, agentName: string, historyEvents?: AgentEvent[]);
28
+ constructor(wsUrl: string, agentName: string, historyEvents?: AgentEvent[], group?: string);
29
29
  private dedupKey;
30
30
  [Symbol.asyncIterator](): AsyncIterator<AgentEvent>;
31
31
  close(): void;
package/dist/watch.js CHANGED
@@ -16,7 +16,7 @@ exports.AgentEventStream = void 0;
16
16
  * }
17
17
  */
18
18
  class AgentEventStream {
19
- constructor(wsUrl, agentName, historyEvents) {
19
+ constructor(wsUrl, agentName, historyEvents, group) {
20
20
  this.queue = [];
21
21
  this.resolve = null;
22
22
  this.done = false;
@@ -30,7 +30,11 @@ class AgentEventStream {
30
30
  this.queue.push(e);
31
31
  }
32
32
  }
33
- this.ws = new WebSocket(`${wsUrl}/api/v1/agents/${agentName}/ws`);
33
+ let endpoint = `${wsUrl}/api/v1/agents/${agentName}/ws`;
34
+ if (group) {
35
+ endpoint += `?group=${encodeURIComponent(group)}`;
36
+ }
37
+ this.ws = new WebSocket(endpoint);
34
38
  this.ws.onmessage = (event) => {
35
39
  const data = JSON.parse(event.data);
36
40
  const agentEvent = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@komputer-ai/sdk",
3
- "version": "0.11.7",
3
+ "version": "0.11.8",
4
4
  "description": "TypeScript SDK for the komputer.ai platform",
5
5
  "author": "komputer-ai",
6
6
  "license": "MIT",