@balchemyai/agent-sdk 0.1.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 (78) hide show
  1. package/README.md +282 -0
  2. package/dist/agent-loop/agent-loop.d.ts +54 -0
  3. package/dist/agent-loop/agent-loop.d.ts.map +1 -0
  4. package/dist/agent-loop/agent-loop.js +328 -0
  5. package/dist/agent-loop/agent-loop.js.map +1 -0
  6. package/dist/agent-loop/decision-handler.d.ts +37 -0
  7. package/dist/agent-loop/decision-handler.d.ts.map +1 -0
  8. package/dist/agent-loop/decision-handler.js +91 -0
  9. package/dist/agent-loop/decision-handler.js.map +1 -0
  10. package/dist/agent-loop/llm-adapters/anthropic.d.ts +10 -0
  11. package/dist/agent-loop/llm-adapters/anthropic.d.ts.map +1 -0
  12. package/dist/agent-loop/llm-adapters/anthropic.js +60 -0
  13. package/dist/agent-loop/llm-adapters/anthropic.js.map +1 -0
  14. package/dist/agent-loop/llm-adapters/openai.d.ts +11 -0
  15. package/dist/agent-loop/llm-adapters/openai.d.ts.map +1 -0
  16. package/dist/agent-loop/llm-adapters/openai.js +54 -0
  17. package/dist/agent-loop/llm-adapters/openai.js.map +1 -0
  18. package/dist/agent-loop/llm-cost-tracker.d.ts +21 -0
  19. package/dist/agent-loop/llm-cost-tracker.d.ts.map +1 -0
  20. package/dist/agent-loop/llm-cost-tracker.js +63 -0
  21. package/dist/agent-loop/llm-cost-tracker.js.map +1 -0
  22. package/dist/agent-loop/model-router.d.ts +35 -0
  23. package/dist/agent-loop/model-router.d.ts.map +1 -0
  24. package/dist/agent-loop/model-router.js +55 -0
  25. package/dist/agent-loop/model-router.js.map +1 -0
  26. package/dist/agent-loop/telemetry-reporter.d.ts +60 -0
  27. package/dist/agent-loop/telemetry-reporter.d.ts.map +1 -0
  28. package/dist/agent-loop/telemetry-reporter.js +78 -0
  29. package/dist/agent-loop/telemetry-reporter.js.map +1 -0
  30. package/dist/agent-loop/types.d.ts +125 -0
  31. package/dist/agent-loop/types.d.ts.map +1 -0
  32. package/dist/agent-loop/types.js +10 -0
  33. package/dist/agent-loop/types.js.map +1 -0
  34. package/dist/agent-loop/webhook-receiver.d.ts +22 -0
  35. package/dist/agent-loop/webhook-receiver.d.ts.map +1 -0
  36. package/dist/agent-loop/webhook-receiver.js +145 -0
  37. package/dist/agent-loop/webhook-receiver.js.map +1 -0
  38. package/dist/auth/onboarding.d.ts +12 -0
  39. package/dist/auth/onboarding.d.ts.map +1 -0
  40. package/dist/auth/onboarding.js +51 -0
  41. package/dist/auth/onboarding.js.map +1 -0
  42. package/dist/auth/token-store.d.ts +44 -0
  43. package/dist/auth/token-store.d.ts.map +1 -0
  44. package/dist/auth/token-store.js +67 -0
  45. package/dist/auth/token-store.js.map +1 -0
  46. package/dist/client/http-client.d.ts +22 -0
  47. package/dist/client/http-client.d.ts.map +1 -0
  48. package/dist/client/http-client.js +127 -0
  49. package/dist/client/http-client.js.map +1 -0
  50. package/dist/errors/agent-sdk-error.d.ts +13 -0
  51. package/dist/errors/agent-sdk-error.d.ts.map +1 -0
  52. package/dist/errors/agent-sdk-error.js +17 -0
  53. package/dist/errors/agent-sdk-error.js.map +1 -0
  54. package/dist/errors/error-codes.d.ts +2 -0
  55. package/dist/errors/error-codes.d.ts.map +1 -0
  56. package/dist/errors/error-codes.js +3 -0
  57. package/dist/errors/error-codes.js.map +1 -0
  58. package/dist/index.d.ts +34 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +63 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/mcp/mcp-client.d.ts +184 -0
  63. package/dist/mcp/mcp-client.d.ts.map +1 -0
  64. package/dist/mcp/mcp-client.js +469 -0
  65. package/dist/mcp/mcp-client.js.map +1 -0
  66. package/dist/streaming/sse-event-stream.d.ts +58 -0
  67. package/dist/streaming/sse-event-stream.d.ts.map +1 -0
  68. package/dist/streaming/sse-event-stream.js +263 -0
  69. package/dist/streaming/sse-event-stream.js.map +1 -0
  70. package/dist/types.d.ts +151 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +3 -0
  73. package/dist/types.js.map +1 -0
  74. package/dist/utils/retry.d.ts +30 -0
  75. package/dist/utils/retry.d.ts.map +1 -0
  76. package/dist/utils/retry.js +85 -0
  77. package/dist/utils/retry.js.map +1 -0
  78. package/package.json +68 -0
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /**
3
+ * TelemetryReporter
4
+ *
5
+ * Reports SDK-side agent activity (LLM calls, decisions, model routing) to
6
+ * the Balchemy server for ClickHouse analytics.
7
+ *
8
+ * Design principles:
9
+ * - All sends are fire-and-forget — errors are silently swallowed.
10
+ * - Events are batched; the flush runs every flushIntervalMs (default 30 s).
11
+ * - A final flush is triggered synchronously on stop().
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.TelemetryReporter = void 0;
15
+ class TelemetryReporter {
16
+ endpoint;
17
+ apiKey;
18
+ flushIntervalMs;
19
+ buffer = [];
20
+ timer = null;
21
+ constructor(
22
+ /** Full URL: e.g. https://api.balchemy.ai/api/agent-telemetry/abc123 */
23
+ endpoint, apiKey, flushIntervalMs = 30_000) {
24
+ this.endpoint = endpoint;
25
+ this.apiKey = apiKey;
26
+ this.flushIntervalMs = flushIntervalMs;
27
+ }
28
+ start() {
29
+ if (this.timer !== null)
30
+ return;
31
+ this.timer = setInterval(() => {
32
+ void this.flush();
33
+ }, this.flushIntervalMs);
34
+ // Allow the process to exit even if this timer is still active
35
+ if (this.timer.unref) {
36
+ this.timer.unref();
37
+ }
38
+ }
39
+ stop() {
40
+ if (this.timer !== null) {
41
+ clearInterval(this.timer);
42
+ this.timer = null;
43
+ }
44
+ // Best-effort final flush — do not await; caller should not block on telemetry
45
+ void this.flush();
46
+ }
47
+ reportLlmCall(data) {
48
+ this.buffer.push({ type: 'llm_call', timestamp: Date.now(), ...data });
49
+ }
50
+ reportDecision(data) {
51
+ this.buffer.push({ type: 'decision', timestamp: Date.now(), ...data });
52
+ }
53
+ reportModelRoute(data) {
54
+ this.buffer.push({ type: 'model_route', timestamp: Date.now(), ...data });
55
+ }
56
+ async flush() {
57
+ if (this.buffer.length === 0)
58
+ return;
59
+ // Drain atomically — if fetch throws, events are lost (intentional: telemetry
60
+ // must never block the agent loop or accumulate indefinitely on a dead server).
61
+ const batch = this.buffer.splice(0);
62
+ try {
63
+ await fetch(this.endpoint, {
64
+ method: 'POST',
65
+ headers: {
66
+ Authorization: `Bearer ${this.apiKey}`,
67
+ 'Content-Type': 'application/json',
68
+ },
69
+ body: JSON.stringify({ events: batch }),
70
+ });
71
+ }
72
+ catch {
73
+ // Fire-and-forget — telemetry failures must not propagate to the agent loop
74
+ }
75
+ }
76
+ }
77
+ exports.TelemetryReporter = TelemetryReporter;
78
+ //# sourceMappingURL=telemetry-reporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-reporter.js","sourceRoot":"","sources":["../../src/agent-loop/telemetry-reporter.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAgCH,MAAa,iBAAiB;IAMT;IACA;IACA;IAPF,MAAM,GAAqB,EAAE,CAAC;IACvC,KAAK,GAA0C,IAAI,CAAC;IAE5D;IACE,wEAAwE;IACvD,QAAgB,EAChB,MAAc,EACd,kBAA0B,MAAM;QAFhC,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAQ;QACd,oBAAe,GAAf,eAAe,CAAiB;IAChD,CAAC;IAEJ,KAAK;QACH,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;YAAE,OAAO;QAChC,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QACzB,+DAA+D;QAC/D,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACxB,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,+EAA+E;QAC/E,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;IAED,aAAa,CAAC,IAAiB;QAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,cAAc,CAAC,IAAkB;QAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,gBAAgB,CAAC,IAAoB;QACnC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IAEO,KAAK,CAAC,KAAK;QACjB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACrC,8EAA8E;QAC9E,gFAAgF;QAChF,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;gBACzB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;oBACtC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;aACxC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,4EAA4E;QAC9E,CAAC;IACH,CAAC;CACF;AA7DD,8CA6DC"}
@@ -0,0 +1,125 @@
1
+ export type LlmProvider = 'anthropic' | 'openai' | 'custom';
2
+ export interface LlmMessage {
3
+ role: 'system' | 'user' | 'assistant';
4
+ content: string;
5
+ }
6
+ export interface LlmResponse {
7
+ text: string;
8
+ model: string;
9
+ inputTokens: number;
10
+ outputTokens: number;
11
+ }
12
+ export interface LlmAdapter {
13
+ chat(messages: LlmMessage[], maxTokens?: number): Promise<LlmResponse>;
14
+ /** Override the active model for the next call(s). Used by ModelRouter. */
15
+ setModel(model: string): void;
16
+ }
17
+ export interface AgentLoopConfig {
18
+ /** Balchemy MCP endpoint (e.g., https://api.balchemy.ai/mcp/abc123) */
19
+ mcpEndpoint: string;
20
+ /** Balchemy MCP API key */
21
+ apiKey: string;
22
+ /** LLM provider */
23
+ llmProvider: LlmProvider;
24
+ /** LLM API key */
25
+ llmApiKey: string;
26
+ /** LLM model name (e.g., claude-haiku-4-5, gpt-4o-mini) */
27
+ llmModel?: string;
28
+ /** Custom LLM API base URL (for Gemini, Grok, OpenRouter, or self-hosted). Defaults to provider's official URL. */
29
+ llmBaseUrl?: string;
30
+ /**
31
+ * Cheap model for low-significance events (score < 60).
32
+ * E.g. claude-haiku-4-5, gpt-5-nano. Defaults to llmModel.
33
+ */
34
+ cheapModel?: string;
35
+ /**
36
+ * Full model for high-significance events (score >= 60).
37
+ * E.g. claude-sonnet-4, gpt-5.4-mini. Defaults to llmModel.
38
+ */
39
+ fullModel?: string;
40
+ /** Path to behavior rules YAML file */
41
+ behaviorRulesPath?: string;
42
+ /** Inline behavior rules (alternative to file path) */
43
+ behaviorRules?: Record<string, unknown>;
44
+ /** Max daily LLM spend in USD. Default: 5 */
45
+ maxDailyLlmCost?: number;
46
+ /** SSE event stream endpoint. Derived from mcpEndpoint if omitted. */
47
+ sseEndpoint?: string;
48
+ /** Webhook server port. 0 = disabled. Default: 0 (disabled) */
49
+ webhookPort?: number;
50
+ /** Webhook HMAC secret (from Balchemy dashboard) */
51
+ webhookSecret?: string;
52
+ /** Custom fetch function for MCP requests (e.g., to inject replay protection headers). */
53
+ mcpFetchFn?: typeof fetch;
54
+ /** LLM call timeout in ms. Default: 10000 */
55
+ llmTimeoutMs?: number;
56
+ /** Max consecutive LLM failures before pausing. Default: 3 */
57
+ maxConsecutiveFailures?: number;
58
+ /** Callback: event received */
59
+ onEvent?: (event: AgentEvent) => void;
60
+ /** Callback: decision made */
61
+ onDecision?: (decision: AgentDecision) => void;
62
+ /** Callback: error */
63
+ onError?: (error: Error) => void;
64
+ /** Callback: status changed */
65
+ onStatusChange?: (status: AgentStatus) => void;
66
+ /** Callback: trade result (after trade_command executes) */
67
+ onTradeResult?: (result: {
68
+ action: string;
69
+ token?: string;
70
+ amount?: string;
71
+ response: string;
72
+ }) => void;
73
+ }
74
+ /** Lightweight portfolio snapshot returned by agent_portfolio MCP tool. */
75
+ export interface AgentPortfolioSnapshot {
76
+ /** Total portfolio value in SOL */
77
+ totalValueSol?: number;
78
+ /** Total portfolio value in USD */
79
+ totalValueUsd?: number;
80
+ /** Summary description for LLM context */
81
+ summary?: string;
82
+ [key: string]: unknown;
83
+ }
84
+ export interface AgentEvent {
85
+ id?: string;
86
+ type: string;
87
+ data: unknown;
88
+ timestamp: number;
89
+ source: 'sse' | 'webhook';
90
+ }
91
+ export interface AgentDecision {
92
+ action: string;
93
+ token?: string;
94
+ amount?: string;
95
+ reasoning?: string;
96
+ confidence?: number;
97
+ ruleCorrection?: {
98
+ original: string;
99
+ corrected: string;
100
+ reason: string;
101
+ };
102
+ }
103
+ export type AgentLoopStatus = 'starting' | 'running' | 'paused' | 'budget_exhausted' | 'llm_failing' | 'stopped' | 'error';
104
+ export interface AgentStatus {
105
+ status: AgentLoopStatus;
106
+ uptime: number;
107
+ eventsReceived: number;
108
+ decisionsExecuted: number;
109
+ tradesExecuted: number;
110
+ llmCallsToday: number;
111
+ llmCostToday: number;
112
+ maxDailyLlmCost: number;
113
+ consecutiveLlmFailures: number;
114
+ lastEventAt?: number;
115
+ lastTradeAt?: number;
116
+ sseConnected: boolean;
117
+ webhookActive: boolean;
118
+ }
119
+ export declare const DEFAULT_AGENT_LOOP_CONFIG: {
120
+ readonly maxDailyLlmCost: 5;
121
+ readonly llmTimeoutMs: 10000;
122
+ readonly maxConsecutiveFailures: 3;
123
+ readonly webhookPort: 0;
124
+ };
125
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agent-loop/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_AGENT_LOOP_CONFIG = void 0;
4
+ exports.DEFAULT_AGENT_LOOP_CONFIG = {
5
+ maxDailyLlmCost: 5,
6
+ llmTimeoutMs: 10_000,
7
+ maxConsecutiveFailures: 3,
8
+ webhookPort: 0,
9
+ };
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agent-loop/types.ts"],"names":[],"mappings":";;;AAkIa,QAAA,yBAAyB,GAAG;IACvC,eAAe,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM;IACpB,sBAAsB,EAAE,CAAC;IACzB,WAAW,EAAE,CAAC;CACN,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { AgentEvent } from './types';
2
+ export interface WebhookReceiverConfig {
3
+ secret: string;
4
+ port: number;
5
+ dedupTtlMs?: number;
6
+ }
7
+ export declare class WebhookReceiver {
8
+ private readonly secret;
9
+ private readonly port;
10
+ private readonly dedupTtlMs;
11
+ private readonly seen;
12
+ private server;
13
+ private onEvent;
14
+ private cleanupTimer;
15
+ constructor(config: WebhookReceiverConfig);
16
+ verifySignature(body: string, signature: string): boolean;
17
+ isDuplicate(traceId: string): boolean;
18
+ cleanup(): void;
19
+ start(handler: (event: AgentEvent) => void): Promise<void>;
20
+ stop(): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=webhook-receiver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-receiver.d.ts","sourceRoot":"","sources":["../../src/agent-loop/webhook-receiver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,OAAO,CAA8C;IAC7D,OAAO,CAAC,YAAY,CAA+C;gBAEvD,MAAM,EAAE,qBAAqB;IAMzC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAezD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAMrC,OAAO,IAAI,IAAI;IAOT,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA8D1D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAU5B"}
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.WebhookReceiver = void 0;
37
+ const crypto = __importStar(require("node:crypto"));
38
+ const http = __importStar(require("node:http"));
39
+ class WebhookReceiver {
40
+ secret;
41
+ port;
42
+ dedupTtlMs;
43
+ seen = new Map();
44
+ server = null;
45
+ onEvent = null;
46
+ cleanupTimer = null;
47
+ constructor(config) {
48
+ this.secret = config.secret;
49
+ this.port = config.port;
50
+ this.dedupTtlMs = config.dedupTtlMs ?? 300_000; // 5 minutes
51
+ }
52
+ verifySignature(body, signature) {
53
+ const expected = crypto
54
+ .createHmac('sha256', this.secret)
55
+ .update(body)
56
+ .digest('hex');
57
+ try {
58
+ return crypto.timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(signature, 'hex'));
59
+ }
60
+ catch {
61
+ return false;
62
+ }
63
+ }
64
+ isDuplicate(traceId) {
65
+ if (this.seen.has(traceId))
66
+ return true;
67
+ this.seen.set(traceId, Date.now());
68
+ return false;
69
+ }
70
+ cleanup() {
71
+ const cutoff = Date.now() - this.dedupTtlMs;
72
+ for (const [id, ts] of this.seen) {
73
+ if (ts < cutoff)
74
+ this.seen.delete(id);
75
+ }
76
+ }
77
+ async start(handler) {
78
+ if (this.port === 0)
79
+ return;
80
+ this.onEvent = handler;
81
+ this.server = http.createServer((req, res) => {
82
+ if (req.method === 'GET' && req.url === '/health') {
83
+ res.writeHead(200, { 'Content-Type': 'application/json' });
84
+ res.end(JSON.stringify({ ok: true }));
85
+ return;
86
+ }
87
+ if (req.method !== 'POST' || req.url !== '/webhook') {
88
+ res.writeHead(404);
89
+ res.end();
90
+ return;
91
+ }
92
+ let body = '';
93
+ req.on('data', (chunk) => { body += chunk.toString(); });
94
+ req.on('end', () => {
95
+ const signature = req.headers['x-balchemy-signature'];
96
+ if (!signature || !this.verifySignature(body, signature)) {
97
+ res.writeHead(401);
98
+ res.end('Invalid signature');
99
+ return;
100
+ }
101
+ try {
102
+ const parsed = JSON.parse(body);
103
+ const traceId = parsed.trace_id;
104
+ if (traceId && this.isDuplicate(traceId)) {
105
+ res.writeHead(200);
106
+ res.end('Duplicate');
107
+ return;
108
+ }
109
+ const event = {
110
+ id: traceId,
111
+ type: parsed.type ?? 'unknown',
112
+ data: parsed,
113
+ timestamp: Date.now(),
114
+ source: 'webhook',
115
+ };
116
+ this.onEvent?.(event);
117
+ res.writeHead(200);
118
+ res.end('OK');
119
+ }
120
+ catch {
121
+ res.writeHead(400);
122
+ res.end('Invalid JSON');
123
+ }
124
+ });
125
+ });
126
+ this.cleanupTimer = setInterval(() => this.cleanup(), 60_000);
127
+ return new Promise((resolve) => {
128
+ this.server.listen(this.port, () => resolve());
129
+ });
130
+ }
131
+ async stop() {
132
+ if (this.cleanupTimer)
133
+ clearInterval(this.cleanupTimer);
134
+ return new Promise((resolve) => {
135
+ if (this.server) {
136
+ this.server.close(() => resolve());
137
+ }
138
+ else {
139
+ resolve();
140
+ }
141
+ });
142
+ }
143
+ }
144
+ exports.WebhookReceiver = WebhookReceiver;
145
+ //# sourceMappingURL=webhook-receiver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-receiver.js","sourceRoot":"","sources":["../../src/agent-loop/webhook-receiver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { HttpClient } from "../client/http-client";
2
+ import type { IdentityTokenRevokeResponse, IdentityTokenRevokeStatusInput, OnboardWithIdentityInput, OnboardWithSiweInput, OnboardingResponse, RevokeIdentityTokenInput, RequestSiweNonceInput, SiweNonceResponse } from "../types";
3
+ export declare class AgentOnboardingClient {
4
+ private readonly http;
5
+ constructor(http: HttpClient);
6
+ requestSiweNonce(input: RequestSiweNonceInput): Promise<SiweNonceResponse>;
7
+ onboardWithSiwe(input: OnboardWithSiweInput): Promise<OnboardingResponse>;
8
+ onboardWithIdentity(input: OnboardWithIdentityInput): Promise<OnboardingResponse>;
9
+ revokeIdentityToken(input: RevokeIdentityTokenInput): Promise<IdentityTokenRevokeResponse>;
10
+ getIdentityTokenRevokeStatus(input: IdentityTokenRevokeStatusInput): Promise<IdentityTokenRevokeResponse>;
11
+ }
12
+ //# sourceMappingURL=onboarding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/auth/onboarding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EACV,2BAA2B,EAC3B,8BAA8B,EAC9B,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAElB,qBAAa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAEvC,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAY1E,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAazE,mBAAmB,CACvB,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,kBAAkB,CAAC;IAcxB,mBAAmB,CACvB,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,2BAA2B,CAAC;IAUjC,4BAA4B,CAChC,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,2BAA2B,CAAC;CAQxC"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AgentOnboardingClient = void 0;
4
+ class AgentOnboardingClient {
5
+ http;
6
+ constructor(http) {
7
+ this.http = http;
8
+ }
9
+ async requestSiweNonce(input) {
10
+ return this.http.post("/nest/auth/evm/nonce", {
11
+ address: input.address,
12
+ chainId: input.chainId,
13
+ domain: input.domain,
14
+ uri: input.uri,
15
+ statement: input.statement ??
16
+ "Sign in to Balchemy external agent onboarding",
17
+ });
18
+ }
19
+ async onboardWithSiwe(input) {
20
+ return this.http.post("/public/erc8004/onboarding/siwe", {
21
+ message: input.message,
22
+ signature: input.signature,
23
+ agentId: input.agentId,
24
+ ...(input.botId !== undefined ? { botId: input.botId } : {}),
25
+ ...(input.scope !== undefined ? { scope: input.scope } : {}),
26
+ });
27
+ }
28
+ async onboardWithIdentity(input) {
29
+ return this.http.post("/public/erc8004/onboarding/identity", {
30
+ provider: input.provider,
31
+ identityToken: input.identityToken,
32
+ agentId: input.agentId,
33
+ ...(input.botId !== undefined ? { botId: input.botId } : {}),
34
+ chainId: input.chainId ?? 8453,
35
+ ...(input.scope !== undefined ? { scope: input.scope } : {}),
36
+ });
37
+ }
38
+ async revokeIdentityToken(input) {
39
+ return this.http.post("/public/erc8004/onboarding/tokens/revoke", {
40
+ jti: input.jti,
41
+ ...(input.ttlSeconds !== undefined ? { ttlSeconds: input.ttlSeconds } : {}),
42
+ });
43
+ }
44
+ async getIdentityTokenRevokeStatus(input) {
45
+ return this.http.post("/public/erc8004/onboarding/tokens/revoke-status", {
46
+ jti: input.jti,
47
+ });
48
+ }
49
+ }
50
+ exports.AgentOnboardingClient = AgentOnboardingClient;
51
+ //# sourceMappingURL=onboarding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../src/auth/onboarding.ts"],"names":[],"mappings":";;;AAYA,MAAa,qBAAqB;IACH;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,KAAK,CAAC,gBAAgB,CAAC,KAA4B;QACjD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAoB,sBAAsB,EAAE;YAC/D,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EACP,KAAK,CAAC,SAAS;gBACf,+CAA+C;SAClD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,KAA2B;QAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CACnB,iCAAiC,EACjC;YACE,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7D,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,mBAAmB,CACvB,KAA+B;QAE/B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CACnB,qCAAqC,EACrC;YACE,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;YAC9B,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7D,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,mBAAmB,CACvB,KAA+B;QAE/B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CACnB,0CAA0C,EAC1C;YACE,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,4BAA4B,CAChC,KAAqC;QAErC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CACnB,iDAAiD,EACjD;YACE,GAAG,EAAE,KAAK,CAAC,GAAG;SACf,CACF,CAAC;IACJ,CAAC;CACF;AAlED,sDAkEC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * TokenStore — in-memory token lifecycle manager.
3
+ *
4
+ * Holds the current identityAccess token and refreshes it automatically
5
+ * before expiry. The refresh callback is provided by the consumer
6
+ * (typically AgentOnboardingClient.onboardWithIdentity / onboardWithSiwe).
7
+ *
8
+ * Token is considered stale when less than `refreshBufferSec` seconds remain.
9
+ * Default buffer: 30 seconds.
10
+ */
11
+ export type StoredToken = {
12
+ token: string;
13
+ tokenType: "Bearer";
14
+ expiresAt: Date;
15
+ kid: string;
16
+ issuer: string;
17
+ scope: "read" | "trade";
18
+ };
19
+ export type TokenRefreshFn = () => Promise<StoredToken>;
20
+ export type TokenStoreOptions = {
21
+ /** Seconds before expiry to proactively refresh. Default: 30 */
22
+ refreshBufferSec?: number;
23
+ };
24
+ export declare class TokenStore {
25
+ private readonly refreshFn;
26
+ private current;
27
+ private refreshing;
28
+ private readonly refreshBufferMs;
29
+ constructor(refreshFn: TokenRefreshFn, options?: TokenStoreOptions);
30
+ /**
31
+ * Returns the current valid token, refreshing if necessary.
32
+ * Concurrent calls during an in-flight refresh share the same Promise.
33
+ */
34
+ getToken(): Promise<string>;
35
+ /** Returns the full stored token object (or null if never set). */
36
+ getCurrent(): StoredToken | null;
37
+ /** Forcefully sets the current token (e.g. from an onboarding response). */
38
+ set(token: StoredToken): void;
39
+ /** Invalidates the current token, forcing the next call to refresh. */
40
+ invalidate(): void;
41
+ private isStale;
42
+ private ensureRefresh;
43
+ }
44
+ //# sourceMappingURL=token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,QAAQ,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;AAExD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,qBAAa,UAAU;IAMnB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAL5B,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAGtB,SAAS,EAAE,cAAc,EAC1C,OAAO,CAAC,EAAE,iBAAiB;IAK7B;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAOjC,mEAAmE;IACnE,UAAU,IAAI,WAAW,GAAG,IAAI;IAIhC,4EAA4E;IAC5E,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAI7B,uEAAuE;IACvE,UAAU,IAAI,IAAI;IAMlB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,aAAa;CAgBtB"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ /**
3
+ * TokenStore — in-memory token lifecycle manager.
4
+ *
5
+ * Holds the current identityAccess token and refreshes it automatically
6
+ * before expiry. The refresh callback is provided by the consumer
7
+ * (typically AgentOnboardingClient.onboardWithIdentity / onboardWithSiwe).
8
+ *
9
+ * Token is considered stale when less than `refreshBufferSec` seconds remain.
10
+ * Default buffer: 30 seconds.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.TokenStore = void 0;
14
+ class TokenStore {
15
+ refreshFn;
16
+ current = null;
17
+ refreshing = null;
18
+ refreshBufferMs;
19
+ constructor(refreshFn, options) {
20
+ this.refreshFn = refreshFn;
21
+ this.refreshBufferMs = (options?.refreshBufferSec ?? 30) * 1000;
22
+ }
23
+ /**
24
+ * Returns the current valid token, refreshing if necessary.
25
+ * Concurrent calls during an in-flight refresh share the same Promise.
26
+ */
27
+ async getToken() {
28
+ if (this.current && !this.isStale(this.current)) {
29
+ return this.current.token;
30
+ }
31
+ return (await this.ensureRefresh()).token;
32
+ }
33
+ /** Returns the full stored token object (or null if never set). */
34
+ getCurrent() {
35
+ return this.current;
36
+ }
37
+ /** Forcefully sets the current token (e.g. from an onboarding response). */
38
+ set(token) {
39
+ this.current = token;
40
+ }
41
+ /** Invalidates the current token, forcing the next call to refresh. */
42
+ invalidate() {
43
+ this.current = null;
44
+ }
45
+ // ── private ──────────────────────────────────────────────────────────────
46
+ isStale(token) {
47
+ return token.expiresAt.getTime() - Date.now() < this.refreshBufferMs;
48
+ }
49
+ ensureRefresh() {
50
+ if (this.refreshing) {
51
+ return this.refreshing;
52
+ }
53
+ this.refreshing = this.refreshFn()
54
+ .then((token) => {
55
+ this.current = token;
56
+ this.refreshing = null;
57
+ return token;
58
+ })
59
+ .catch((err) => {
60
+ this.refreshing = null;
61
+ throw err;
62
+ });
63
+ return this.refreshing;
64
+ }
65
+ }
66
+ exports.TokenStore = TokenStore;
67
+ //# sourceMappingURL=token-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAkBH,MAAa,UAAU;IAMF;IALX,OAAO,GAAuB,IAAI,CAAC;IACnC,UAAU,GAAgC,IAAI,CAAC;IACtC,eAAe,CAAS;IAEzC,YACmB,SAAyB,EAC1C,OAA2B;QADV,cAAS,GAAT,SAAS,CAAgB;QAG1C,IAAI,CAAC,eAAe,GAAG,CAAC,OAAO,EAAE,gBAAgB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IAClE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAQ;QACZ,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAChD,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QAC5B,CAAC;QACD,OAAO,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC;IAC5C,CAAC;IAED,mEAAmE;IACnE,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,4EAA4E;IAC5E,GAAG,CAAC,KAAkB;QACpB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,uEAAuE;IACvE,UAAU;QACR,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,4EAA4E;IAEpE,OAAO,CAAC,KAAkB;QAChC,OAAO,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC;IACvE,CAAC;IAEO,aAAa;QACnB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,UAAU,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE;aAC/B,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACd,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;QACL,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;CACF;AA5DD,gCA4DC"}
@@ -0,0 +1,22 @@
1
+ import { type RetryOptions } from "../utils/retry";
2
+ export type HttpClientConfig = {
3
+ baseUrl: string;
4
+ timeoutMs: number;
5
+ fetchFn?: typeof fetch;
6
+ /** Retry options. Set maxAttempts=1 to disable retries. Default: 3 attempts. */
7
+ retry?: RetryOptions;
8
+ };
9
+ export declare class HttpClient {
10
+ private readonly baseUrl;
11
+ private readonly timeoutMs;
12
+ private readonly fetchFn;
13
+ private readonly retryOptions;
14
+ constructor(config: HttpClientConfig);
15
+ get<T>(path: string, headers?: Record<string, string>): Promise<T>;
16
+ post<T>(path: string, body: Record<string, unknown>, headers?: Record<string, string>): Promise<T>;
17
+ private request;
18
+ private safeJsonParse;
19
+ private unwrapCanonicalEnvelope;
20
+ private mapHttpError;
21
+ }
22
+ //# sourceMappingURL=http-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../src/client/http-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,gFAAgF;IAChF,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB,CAAC;AAEF,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAEhC,MAAM,EAAE,gBAAgB;IAO9B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAOlE,IAAI,CAAC,CAAC,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;YAYC,OAAO;YAsDP,aAAa;IAY3B,OAAO,CAAC,uBAAuB;IA+B/B,OAAO,CAAC,YAAY;CAmBrB"}