@xtrape/capsule-agent-node 0.3.0 → 0.4.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 CHANGED
@@ -458,3 +458,24 @@ safety guidance.
458
458
 
459
459
  Apache-2.0. "Xtrape", "Xtrape Capsule", and "Opstage" are trademarks of their
460
460
  respective owners; the open-source license does not grant trademark rights.
461
+
462
+ ## v0.4 Experimental Capsule Bus Hook
463
+
464
+ The SDK exposes a minimal experimental publish hook into CE's built-in SQLite-backed in-process event-to-command router:
465
+
466
+ ```ts
467
+ await agent.publishBusEvent({
468
+ eventType: "demo.item.created",
469
+ payload: { itemId: "item-1" },
470
+ });
471
+ ```
472
+
473
+ The hook posts to Opstage CE as the registered embedded agent and defaults `sourceServiceCode` to the configured service code.
474
+
475
+ Typed errors for Bus failure modes:
476
+
477
+ - `BusDisabledError` — `CAPSULE_BUS_DISABLED` (404)
478
+ - `BusRateLimitedError` — `BUS_RATE_LIMITED` (429)
479
+ - `BusDepthExceededError` — `BUS_DEPTH_EXCEEDED` (422)
480
+
481
+ Capsule Bus is experimental in v0.4: not a standalone Bus Server, external broker, workflow engine, or service mesh API.
package/dist/index.cjs CHANGED
@@ -23,6 +23,9 @@ __export(index_exports, {
23
23
  AgentApiClient: () => AgentApiClient,
24
24
  AgentApiError: () => AgentApiError,
25
25
  AgentAuthError: () => AgentAuthError,
26
+ BusDepthExceededError: () => BusDepthExceededError,
27
+ BusDisabledError: () => BusDisabledError,
28
+ BusRateLimitedError: () => BusRateLimitedError,
26
29
  CapsuleAgent: () => CapsuleAgent,
27
30
  FileTokenStore: () => FileTokenStore,
28
31
  NetworkError: () => NetworkError,
@@ -64,9 +67,30 @@ var NetworkError = class extends AgentApiError {
64
67
  }
65
68
  }
66
69
  };
70
+ var BusDisabledError = class extends AgentApiError {
71
+ constructor(message, status, body) {
72
+ super(status, message, body, "CAPSULE_BUS_DISABLED");
73
+ this.name = "BusDisabledError";
74
+ }
75
+ };
76
+ var BusRateLimitedError = class extends AgentApiError {
77
+ constructor(message, status, body) {
78
+ super(status, message, body, "BUS_RATE_LIMITED");
79
+ this.name = "BusRateLimitedError";
80
+ }
81
+ };
82
+ var BusDepthExceededError = class extends AgentApiError {
83
+ constructor(message, status, body) {
84
+ super(status, message, body, "BUS_DEPTH_EXCEEDED");
85
+ this.name = "BusDepthExceededError";
86
+ }
87
+ };
67
88
  function classifyAgentApiError(status, message, body, code, path) {
68
89
  if (status === 401 && path.endsWith("/register")) return new RegistrationError(message, status, body, code);
69
90
  if (status === 401 || status === 403) return new AgentAuthError(message, status, body, code);
91
+ if (code === "CAPSULE_BUS_DISABLED") return new BusDisabledError(message, status, body);
92
+ if (code === "BUS_RATE_LIMITED") return new BusRateLimitedError(message, status, body);
93
+ if (code === "BUS_DEPTH_EXCEEDED") return new BusDepthExceededError(message, status, body);
70
94
  return new AgentApiError(status, message, body, code);
71
95
  }
72
96
 
@@ -118,6 +142,10 @@ var AgentApiClient = class {
118
142
  reportResult(agentId, token, commandId, req) {
119
143
  return this.request(`/api/agents/${agentId}/commands/${commandId}/result`, { method: "POST", token, body: JSON.stringify(req) });
120
144
  }
145
+ /** Experimental v0.4 Capsule Bus publish hook. Subject to change before v1.0. */
146
+ publishBusEvent(agentId, token, req) {
147
+ return this.request(`/api/agents/${agentId}/bus/events`, { method: "POST", token, body: JSON.stringify({ ...req, experimental: req.experimental ?? "v0.4-experimental" }) });
148
+ }
121
149
  };
122
150
 
123
151
  // src/token-store/file-token-store.ts
@@ -272,6 +300,14 @@ var CapsuleAgent = class {
272
300
  async runHealth() {
273
301
  return this.healthProvider();
274
302
  }
303
+ /** Experimental v0.4 Capsule Bus publish hook. Subject to change before v1.0. */
304
+ async publishBusEvent(input) {
305
+ if (!this.agentId || !this.token) throw new Error("Agent must be started before publishing Capsule Bus events.");
306
+ const sourceServiceCode = input.sourceServiceCode ?? this.options.service.code;
307
+ const result = await this.retry(() => this.client.publishBusEvent(this.agentId, this.token, { ...input, sourceServiceCode }));
308
+ this.log("info", "experimental bus event published", { eventId: result.eventId, eventType: input.eventType, sourceServiceCode, routedCommands: result.routedCommands.length });
309
+ return result;
310
+ }
275
311
  async reportService() {
276
312
  if (!this.agentId || !this.token) return;
277
313
  const [health, configs] = await Promise.all([this.runHealth(), this.configProvider()]);
@@ -372,6 +408,9 @@ var CapsuleAgent = class {
372
408
  AgentApiClient,
373
409
  AgentApiError,
374
410
  AgentAuthError,
411
+ BusDepthExceededError,
412
+ BusDisabledError,
413
+ BusRateLimitedError,
375
414
  CapsuleAgent,
376
415
  FileTokenStore,
377
416
  NetworkError,
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { ActionPrepareResult, RuntimeKind, HealthReportInput, ConfigItemInput, ActionDefinitionInput, ReportedService, RegisterAgentRequest, AgentHeartbeatRequest, ServiceReportRequest, ReportCommandResultRequest } from '@xtrape/capsule-contracts-node';
1
+ import { ActionPrepareResult, PublishBusEventRequest, RuntimeKind, HealthReportInput, ConfigItemInput, ActionDefinitionInput, PublishBusEventResponse, ReportedService, RegisterAgentRequest, AgentHeartbeatRequest, ServiceReportRequest, ReportCommandResultRequest } from '@xtrape/capsule-contracts-node';
2
2
 
3
3
  type AgentMode = "embedded";
4
4
  type ActionHandler = (payload: Record<string, unknown>) => Promise<{
@@ -87,6 +87,11 @@ interface TokenStore {
87
87
  clear(): Promise<void>;
88
88
  }
89
89
  type ServiceSnapshot = ReportedService;
90
+ /** Experimental v0.4 Capsule Bus publish input. Subject to change before v1.0. */
91
+ type PublishBusEventInput = Omit<PublishBusEventRequest, "sourceServiceCode"> & {
92
+ sourceServiceCode?: string;
93
+ };
94
+ type PublishBusEventResult = PublishBusEventResponse;
90
95
 
91
96
  declare class CapsuleAgent {
92
97
  private readonly options;
@@ -111,6 +116,8 @@ declare class CapsuleAgent {
111
116
  private ensureRegistered;
112
117
  private serviceSnapshot;
113
118
  runHealth(): Promise<HealthReportInput>;
119
+ /** Experimental v0.4 Capsule Bus publish hook. Subject to change before v1.0. */
120
+ publishBusEvent(input: PublishBusEventInput): Promise<PublishBusEventResult>;
114
121
  private reportService;
115
122
  private heartbeat;
116
123
  private pollOnce;
@@ -171,6 +178,15 @@ declare class AgentAuthError extends AgentApiError {
171
178
  declare class NetworkError extends AgentApiError {
172
179
  constructor(message: string, cause?: unknown);
173
180
  }
181
+ declare class BusDisabledError extends AgentApiError {
182
+ constructor(message: string, status: number, body?: unknown);
183
+ }
184
+ declare class BusRateLimitedError extends AgentApiError {
185
+ constructor(message: string, status: number, body?: unknown);
186
+ }
187
+ declare class BusDepthExceededError extends AgentApiError {
188
+ constructor(message: string, status: number, body?: unknown);
189
+ }
174
190
 
175
191
  declare class AgentApiClient {
176
192
  private readonly backendUrl;
@@ -186,7 +202,7 @@ declare class AgentApiClient {
186
202
  heartbeat(agentId: string, token: string, req: AgentHeartbeatRequest): Promise<unknown>;
187
203
  reportServices(agentId: string, token: string, req: ServiceReportRequest): Promise<unknown>;
188
204
  pollCommands(agentId: string, token: string): Promise<{
189
- type: "ACTION_PREPARE" | "ACTION_EXECUTE";
205
+ type: "ACTION_EXECUTE" | "ACTION_PREPARE";
190
206
  id: string;
191
207
  createdAt: string;
192
208
  status: "PENDING" | "RUNNING" | "SUCCEEDED" | "FAILED" | "EXPIRED" | "CANCELLED";
@@ -200,6 +216,21 @@ declare class AgentApiClient {
200
216
  completedAt?: string | null | undefined;
201
217
  }[]>;
202
218
  reportResult(agentId: string, token: string, commandId: string, req: ReportCommandResultRequest): Promise<unknown>;
219
+ /** Experimental v0.4 Capsule Bus publish hook. Subject to change before v1.0. */
220
+ publishBusEvent(agentId: string, token: string, req: PublishBusEventInput): Promise<{
221
+ experimental: "v0.4-experimental";
222
+ eventId: string;
223
+ routedCommands: {
224
+ status: "FAILED" | "DRY_RUN" | "CREATED" | "SKIPPED";
225
+ dryRun: boolean;
226
+ actionName: string;
227
+ routeId: string;
228
+ targetServiceCode: string;
229
+ commandId?: string | undefined;
230
+ errorCode?: string | undefined;
231
+ errorMessage?: string | undefined;
232
+ }[];
233
+ }>;
203
234
  }
204
235
 
205
- export { type ActionHandler, type ActionPrepareHandler, AgentApiClient, AgentApiError, AgentAuthError, type AgentLogLevel, type AgentLogRecord, type AgentMode, CapsuleAgent, type CapsuleAgentOptions, type ConfigProvider, type ConsoleLogger, FileTokenStore, type HealthProvider, NetworkError, type RegisteredAction, RegistrationError, type ServiceSnapshot, type StructuredLogger, type TokenStore };
236
+ export { type ActionHandler, type ActionPrepareHandler, AgentApiClient, AgentApiError, AgentAuthError, type AgentLogLevel, type AgentLogRecord, type AgentMode, BusDepthExceededError, BusDisabledError, BusRateLimitedError, CapsuleAgent, type CapsuleAgentOptions, type ConfigProvider, type ConsoleLogger, FileTokenStore, type HealthProvider, NetworkError, type PublishBusEventInput, type PublishBusEventResult, type RegisteredAction, RegistrationError, type ServiceSnapshot, type StructuredLogger, type TokenStore };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ActionPrepareResult, RuntimeKind, HealthReportInput, ConfigItemInput, ActionDefinitionInput, ReportedService, RegisterAgentRequest, AgentHeartbeatRequest, ServiceReportRequest, ReportCommandResultRequest } from '@xtrape/capsule-contracts-node';
1
+ import { ActionPrepareResult, PublishBusEventRequest, RuntimeKind, HealthReportInput, ConfigItemInput, ActionDefinitionInput, PublishBusEventResponse, ReportedService, RegisterAgentRequest, AgentHeartbeatRequest, ServiceReportRequest, ReportCommandResultRequest } from '@xtrape/capsule-contracts-node';
2
2
 
3
3
  type AgentMode = "embedded";
4
4
  type ActionHandler = (payload: Record<string, unknown>) => Promise<{
@@ -87,6 +87,11 @@ interface TokenStore {
87
87
  clear(): Promise<void>;
88
88
  }
89
89
  type ServiceSnapshot = ReportedService;
90
+ /** Experimental v0.4 Capsule Bus publish input. Subject to change before v1.0. */
91
+ type PublishBusEventInput = Omit<PublishBusEventRequest, "sourceServiceCode"> & {
92
+ sourceServiceCode?: string;
93
+ };
94
+ type PublishBusEventResult = PublishBusEventResponse;
90
95
 
91
96
  declare class CapsuleAgent {
92
97
  private readonly options;
@@ -111,6 +116,8 @@ declare class CapsuleAgent {
111
116
  private ensureRegistered;
112
117
  private serviceSnapshot;
113
118
  runHealth(): Promise<HealthReportInput>;
119
+ /** Experimental v0.4 Capsule Bus publish hook. Subject to change before v1.0. */
120
+ publishBusEvent(input: PublishBusEventInput): Promise<PublishBusEventResult>;
114
121
  private reportService;
115
122
  private heartbeat;
116
123
  private pollOnce;
@@ -171,6 +178,15 @@ declare class AgentAuthError extends AgentApiError {
171
178
  declare class NetworkError extends AgentApiError {
172
179
  constructor(message: string, cause?: unknown);
173
180
  }
181
+ declare class BusDisabledError extends AgentApiError {
182
+ constructor(message: string, status: number, body?: unknown);
183
+ }
184
+ declare class BusRateLimitedError extends AgentApiError {
185
+ constructor(message: string, status: number, body?: unknown);
186
+ }
187
+ declare class BusDepthExceededError extends AgentApiError {
188
+ constructor(message: string, status: number, body?: unknown);
189
+ }
174
190
 
175
191
  declare class AgentApiClient {
176
192
  private readonly backendUrl;
@@ -186,7 +202,7 @@ declare class AgentApiClient {
186
202
  heartbeat(agentId: string, token: string, req: AgentHeartbeatRequest): Promise<unknown>;
187
203
  reportServices(agentId: string, token: string, req: ServiceReportRequest): Promise<unknown>;
188
204
  pollCommands(agentId: string, token: string): Promise<{
189
- type: "ACTION_PREPARE" | "ACTION_EXECUTE";
205
+ type: "ACTION_EXECUTE" | "ACTION_PREPARE";
190
206
  id: string;
191
207
  createdAt: string;
192
208
  status: "PENDING" | "RUNNING" | "SUCCEEDED" | "FAILED" | "EXPIRED" | "CANCELLED";
@@ -200,6 +216,21 @@ declare class AgentApiClient {
200
216
  completedAt?: string | null | undefined;
201
217
  }[]>;
202
218
  reportResult(agentId: string, token: string, commandId: string, req: ReportCommandResultRequest): Promise<unknown>;
219
+ /** Experimental v0.4 Capsule Bus publish hook. Subject to change before v1.0. */
220
+ publishBusEvent(agentId: string, token: string, req: PublishBusEventInput): Promise<{
221
+ experimental: "v0.4-experimental";
222
+ eventId: string;
223
+ routedCommands: {
224
+ status: "FAILED" | "DRY_RUN" | "CREATED" | "SKIPPED";
225
+ dryRun: boolean;
226
+ actionName: string;
227
+ routeId: string;
228
+ targetServiceCode: string;
229
+ commandId?: string | undefined;
230
+ errorCode?: string | undefined;
231
+ errorMessage?: string | undefined;
232
+ }[];
233
+ }>;
203
234
  }
204
235
 
205
- export { type ActionHandler, type ActionPrepareHandler, AgentApiClient, AgentApiError, AgentAuthError, type AgentLogLevel, type AgentLogRecord, type AgentMode, CapsuleAgent, type CapsuleAgentOptions, type ConfigProvider, type ConsoleLogger, FileTokenStore, type HealthProvider, NetworkError, type RegisteredAction, RegistrationError, type ServiceSnapshot, type StructuredLogger, type TokenStore };
236
+ export { type ActionHandler, type ActionPrepareHandler, AgentApiClient, AgentApiError, AgentAuthError, type AgentLogLevel, type AgentLogRecord, type AgentMode, BusDepthExceededError, BusDisabledError, BusRateLimitedError, CapsuleAgent, type CapsuleAgentOptions, type ConfigProvider, type ConsoleLogger, FileTokenStore, type HealthProvider, NetworkError, type PublishBusEventInput, type PublishBusEventResult, type RegisteredAction, RegistrationError, type ServiceSnapshot, type StructuredLogger, type TokenStore };
package/dist/index.js CHANGED
@@ -32,9 +32,30 @@ var NetworkError = class extends AgentApiError {
32
32
  }
33
33
  }
34
34
  };
35
+ var BusDisabledError = class extends AgentApiError {
36
+ constructor(message, status, body) {
37
+ super(status, message, body, "CAPSULE_BUS_DISABLED");
38
+ this.name = "BusDisabledError";
39
+ }
40
+ };
41
+ var BusRateLimitedError = class extends AgentApiError {
42
+ constructor(message, status, body) {
43
+ super(status, message, body, "BUS_RATE_LIMITED");
44
+ this.name = "BusRateLimitedError";
45
+ }
46
+ };
47
+ var BusDepthExceededError = class extends AgentApiError {
48
+ constructor(message, status, body) {
49
+ super(status, message, body, "BUS_DEPTH_EXCEEDED");
50
+ this.name = "BusDepthExceededError";
51
+ }
52
+ };
35
53
  function classifyAgentApiError(status, message, body, code, path) {
36
54
  if (status === 401 && path.endsWith("/register")) return new RegistrationError(message, status, body, code);
37
55
  if (status === 401 || status === 403) return new AgentAuthError(message, status, body, code);
56
+ if (code === "CAPSULE_BUS_DISABLED") return new BusDisabledError(message, status, body);
57
+ if (code === "BUS_RATE_LIMITED") return new BusRateLimitedError(message, status, body);
58
+ if (code === "BUS_DEPTH_EXCEEDED") return new BusDepthExceededError(message, status, body);
38
59
  return new AgentApiError(status, message, body, code);
39
60
  }
40
61
 
@@ -86,6 +107,10 @@ var AgentApiClient = class {
86
107
  reportResult(agentId, token, commandId, req) {
87
108
  return this.request(`/api/agents/${agentId}/commands/${commandId}/result`, { method: "POST", token, body: JSON.stringify(req) });
88
109
  }
110
+ /** Experimental v0.4 Capsule Bus publish hook. Subject to change before v1.0. */
111
+ publishBusEvent(agentId, token, req) {
112
+ return this.request(`/api/agents/${agentId}/bus/events`, { method: "POST", token, body: JSON.stringify({ ...req, experimental: req.experimental ?? "v0.4-experimental" }) });
113
+ }
89
114
  };
90
115
 
91
116
  // src/token-store/file-token-store.ts
@@ -240,6 +265,14 @@ var CapsuleAgent = class {
240
265
  async runHealth() {
241
266
  return this.healthProvider();
242
267
  }
268
+ /** Experimental v0.4 Capsule Bus publish hook. Subject to change before v1.0. */
269
+ async publishBusEvent(input) {
270
+ if (!this.agentId || !this.token) throw new Error("Agent must be started before publishing Capsule Bus events.");
271
+ const sourceServiceCode = input.sourceServiceCode ?? this.options.service.code;
272
+ const result = await this.retry(() => this.client.publishBusEvent(this.agentId, this.token, { ...input, sourceServiceCode }));
273
+ this.log("info", "experimental bus event published", { eventId: result.eventId, eventType: input.eventType, sourceServiceCode, routedCommands: result.routedCommands.length });
274
+ return result;
275
+ }
243
276
  async reportService() {
244
277
  if (!this.agentId || !this.token) return;
245
278
  const [health, configs] = await Promise.all([this.runHealth(), this.configProvider()]);
@@ -339,6 +372,9 @@ export {
339
372
  AgentApiClient,
340
373
  AgentApiError,
341
374
  AgentAuthError,
375
+ BusDepthExceededError,
376
+ BusDisabledError,
377
+ BusRateLimitedError,
342
378
  CapsuleAgent,
343
379
  FileTokenStore,
344
380
  NetworkError,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xtrape/capsule-agent-node",
3
- "version": "0.3.0",
4
- "description": "Node.js Embedded Agent SDK for embedding single Capsule Services into the Opstage governance loop. For multi-service OpHub functionality, use OpHub (Go runtime).",
3
+ "version": "0.4.0",
4
+ "description": "Node.js Agent SDK for embedding Capsule Services into the Opstage governance loop.",
5
5
  "keywords": [
6
6
  "xtrape",
7
7
  "capsule",
@@ -43,13 +43,13 @@
43
43
  "lint": "tsc --noEmit"
44
44
  },
45
45
  "dependencies": {
46
- "@xtrape/capsule-contracts-node": "0.3.0"
46
+ "@xtrape/capsule-contracts-node": "^0.4.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@types/node": "^22.10.2",
50
49
  "tsup": "^8.3.5",
51
50
  "typescript": "^5.6.3",
52
- "vitest": "^2.1.9"
51
+ "vitest": "^2.1.9",
52
+ "@types/node": "^22.10.2"
53
53
  },
54
54
  "engines": {
55
55
  "node": ">=20"