@buildaureon/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.
package/dist/index.js ADDED
@@ -0,0 +1,1030 @@
1
+ // src/adapters/fetch-adapter.ts
2
+ function resolveFetch(custom) {
3
+ if (custom) return custom.bind(custom);
4
+ if (typeof globalThis.fetch !== "function") {
5
+ throw new Error("No fetch implementation available in this runtime");
6
+ }
7
+ return globalThis.fetch.bind(globalThis);
8
+ }
9
+ function userAgentHeader(version) {
10
+ return { "X-Aureon-SDK": `@buildaureon/sdk/${version}` };
11
+ }
12
+
13
+ // src/constants/defaults.ts
14
+ var DEFAULT_API_BASE_URL = "https://api.aureonlabs.network";
15
+ var LOCAL_API_BASE_URL = "http://127.0.0.1:8787";
16
+ var DEFAULT_TIMEOUT_MS = 3e4;
17
+ var SDK_VERSION = "0.1.0";
18
+ var SDK_NAME = "@buildaureon/sdk";
19
+ var PRODUCT_NAME = "AUREON";
20
+ var PRODUCT_TAGLINE = "Financial Compass for Robinhood Chain";
21
+ var API_KEY_HEADER = "X-Aureon-Api-Key";
22
+
23
+ // src/constants/endpoints.ts
24
+ var ENDPOINTS = {
25
+ healthz: "/healthz",
26
+ overview: "/overview",
27
+ portfolio: "/portfolio",
28
+ portfolioClear: "/portfolio/clear",
29
+ portfolioSync: "/portfolio/sync",
30
+ watchdogRefresh: "/watchdog/refresh",
31
+ objectives: "/objectives",
32
+ health: "/health",
33
+ timeline: "/timeline",
34
+ executions: "/executions",
35
+ executionsRun: "/executions/run",
36
+ marketEvents: "/market/events",
37
+ marketPresets: "/market/presets",
38
+ vault: "/vault",
39
+ vaultStatus: "/vault/status",
40
+ vaultPrepareDeposit: "/vault/prepare-deposit",
41
+ vaultPrepareWithdraw: "/vault/prepare-withdraw",
42
+ authNonce: "/auth/nonce",
43
+ authVerify: "/auth/verify",
44
+ authLogout: "/auth/logout",
45
+ authDevLogin: "/auth/dev-login",
46
+ authMe: "/auth/me",
47
+ developerApiKeys: "/developer/api-keys"
48
+ };
49
+ function objectivePath(id) {
50
+ return `${ENDPOINTS.objectives}/${encodeURIComponent(id)}`;
51
+ }
52
+ function objectivePausePath(id) {
53
+ return `${objectivePath(id)}/pause`;
54
+ }
55
+ function objectiveResumePath(id) {
56
+ return `${objectivePath(id)}/resume`;
57
+ }
58
+ function objectiveRestorePlanPath(id) {
59
+ return `${objectivePath(id)}/restore-plan`;
60
+ }
61
+ function objectiveRestorePath(id) {
62
+ return `${objectivePath(id)}/restore`;
63
+ }
64
+ function developerApiKeyPath(id) {
65
+ return `${ENDPOINTS.developerApiKeys}/${encodeURIComponent(id)}`;
66
+ }
67
+
68
+ // src/errors/codes.ts
69
+ var RETRYABLE_CODES = [
70
+ "NETWORK_ERROR",
71
+ "TIMEOUT",
72
+ "RATE_LIMITED",
73
+ "SERVER_ERROR"
74
+ ];
75
+ function isRetryableCode(code) {
76
+ return RETRYABLE_CODES.includes(code);
77
+ }
78
+ function defaultMessageForStatus(status) {
79
+ switch (status) {
80
+ case 400:
81
+ return "The request failed validation";
82
+ case 401:
83
+ return "Authentication is required";
84
+ case 403:
85
+ return "Access is forbidden for this resource";
86
+ case 404:
87
+ return "The requested resource was not found";
88
+ case 409:
89
+ return "The request conflicts with the current resource state";
90
+ case 429:
91
+ return "Rate limit exceeded";
92
+ default:
93
+ if (status >= 500) return "The server encountered an error";
94
+ return `Unexpected HTTP status ${status}`;
95
+ }
96
+ }
97
+
98
+ // src/errors/base.ts
99
+ var AureonError = class extends Error {
100
+ code;
101
+ status;
102
+ details;
103
+ constructor(message, code, status = null, details = null) {
104
+ super(message);
105
+ this.name = "AureonError";
106
+ this.code = code;
107
+ this.status = status;
108
+ this.details = details;
109
+ Object.setPrototypeOf(this, new.target.prototype);
110
+ }
111
+ get retryable() {
112
+ return isRetryableCode(this.code);
113
+ }
114
+ toJSON() {
115
+ return {
116
+ name: this.name,
117
+ message: this.message,
118
+ code: this.code,
119
+ status: this.status,
120
+ details: this.details,
121
+ retryable: this.retryable
122
+ };
123
+ }
124
+ };
125
+ var AureonValidationError = class extends AureonError {
126
+ constructor(message, details = null) {
127
+ super(message, "VALIDATION_ERROR", 400, details);
128
+ this.name = "AureonValidationError";
129
+ Object.setPrototypeOf(this, new.target.prototype);
130
+ }
131
+ };
132
+ var AureonNotFoundError = class extends AureonError {
133
+ constructor(message, details = null) {
134
+ super(message, "NOT_FOUND", 404, details);
135
+ this.name = "AureonNotFoundError";
136
+ Object.setPrototypeOf(this, new.target.prototype);
137
+ }
138
+ };
139
+ var AureonConflictError = class extends AureonError {
140
+ constructor(message, details = null) {
141
+ super(message, "CONFLICT", 409, details);
142
+ this.name = "AureonConflictError";
143
+ Object.setPrototypeOf(this, new.target.prototype);
144
+ }
145
+ };
146
+ var AureonNetworkError = class extends AureonError {
147
+ constructor(message, details = null) {
148
+ super(message, "NETWORK_ERROR", null, details);
149
+ this.name = "AureonNetworkError";
150
+ Object.setPrototypeOf(this, new.target.prototype);
151
+ }
152
+ };
153
+ var AureonTimeoutError = class extends AureonError {
154
+ constructor(message = "Request timed out", details = null) {
155
+ super(message, "TIMEOUT", null, details);
156
+ this.name = "AureonTimeoutError";
157
+ Object.setPrototypeOf(this, new.target.prototype);
158
+ }
159
+ };
160
+
161
+ // src/errors/http.ts
162
+ function isRecord(value) {
163
+ return typeof value === "object" && value !== null && !Array.isArray(value);
164
+ }
165
+ function extractMessage(body) {
166
+ if (!isRecord(body)) return null;
167
+ if (typeof body.message === "string") return body.message;
168
+ if (typeof body.error === "string") return body.error;
169
+ if (isRecord(body.error) && typeof body.error.message === "string") {
170
+ return body.error.message;
171
+ }
172
+ return null;
173
+ }
174
+ function errorFromHttpStatus(status, body) {
175
+ const message = extractMessage(body) ?? defaultMessageForStatus(status);
176
+ const details = isRecord(body) ? body : { body };
177
+ if (status === 400) return new AureonValidationError(message, details);
178
+ if (status === 404) return new AureonNotFoundError(message, details);
179
+ if (status === 409) return new AureonConflictError(message, details);
180
+ if (status === 401 || status === 403) {
181
+ return new AureonError(message, "UNAUTHORIZED", status, details);
182
+ }
183
+ if (status === 429) {
184
+ return new AureonError(message, "RATE_LIMITED", status, details);
185
+ }
186
+ if (status >= 500) {
187
+ return new AureonError(message, "SERVER_ERROR", status, details);
188
+ }
189
+ return new AureonError(message, "UNEXPECTED_RESPONSE", status, details);
190
+ }
191
+ function isAureonError(value) {
192
+ return value instanceof AureonError;
193
+ }
194
+
195
+ // src/transport/url.ts
196
+ function joinUrl(baseUrl, path) {
197
+ const base = baseUrl.replace(/\/+$/, "");
198
+ const suffix = path.startsWith("/") ? path : `/${path}`;
199
+ return `${base}${suffix}`;
200
+ }
201
+ function assertBaseUrl(baseUrl) {
202
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
203
+ if (!/^https?:\/\//i.test(trimmed)) {
204
+ throw new AureonError(
205
+ "baseUrl must be an absolute http(s) URL",
206
+ "VALIDATION_ERROR",
207
+ 400,
208
+ { baseUrl }
209
+ );
210
+ }
211
+ return trimmed;
212
+ }
213
+ function withQuery(path, query) {
214
+ const params = new URLSearchParams();
215
+ for (const [key, value] of Object.entries(query)) {
216
+ if (value !== void 0 && value !== "") params.set(key, value);
217
+ }
218
+ const qs = params.toString();
219
+ if (!qs) return path;
220
+ return path.includes("?") ? `${path}&${qs}` : `${path}?${qs}`;
221
+ }
222
+
223
+ // src/transport/http.ts
224
+ function safeParseJson(text) {
225
+ try {
226
+ return JSON.parse(text);
227
+ } catch {
228
+ return { message: text };
229
+ }
230
+ }
231
+ function isAbortError(error) {
232
+ return error instanceof DOMException && error.name === "AbortError" || error instanceof Error && error.name === "AbortError";
233
+ }
234
+ function isRetryableError(error) {
235
+ if (error instanceof AureonNetworkError || error instanceof AureonTimeoutError) {
236
+ return true;
237
+ }
238
+ if (error instanceof AureonError) {
239
+ return typeof error.status === "number" && (error.status >= 500 || error.status === 429);
240
+ }
241
+ return false;
242
+ }
243
+ function sleep(ms) {
244
+ return new Promise((resolve) => setTimeout(resolve, ms));
245
+ }
246
+ async function requestJson(transport, path, options = {}) {
247
+ const url = joinUrl(transport.baseUrl, path);
248
+ const maxRetries = transport.maxRetries ?? 0;
249
+ const retryDelayMs = transport.retryDelayMs ?? 250;
250
+ let attempt = 0;
251
+ while (true) {
252
+ attempt += 1;
253
+ const controller = new AbortController();
254
+ const timeout = setTimeout(() => controller.abort(), transport.timeoutMs);
255
+ const onAbort = () => controller.abort();
256
+ if (options.signal) {
257
+ if (options.signal.aborted) {
258
+ clearTimeout(timeout);
259
+ throw new AureonError("Request aborted", "ABORTED");
260
+ }
261
+ options.signal.addEventListener("abort", onAbort, { once: true });
262
+ }
263
+ try {
264
+ const token = transport.getAccessToken ? await transport.getAccessToken() : null;
265
+ const authHeaders = {};
266
+ if (typeof token === "string" && token.trim().length > 0) {
267
+ authHeaders.Authorization = `Bearer ${token.trim()}`;
268
+ }
269
+ const apiKey = transport.getApiKey ? await transport.getApiKey() : null;
270
+ if (typeof apiKey === "string" && apiKey.trim().length > 0) {
271
+ authHeaders["X-Aureon-Api-Key"] = apiKey.trim();
272
+ }
273
+ transport.logger?.debug("aureon.request", {
274
+ method: options.method ?? (options.body !== void 0 ? "POST" : "GET"),
275
+ path,
276
+ attempt
277
+ });
278
+ const response = await transport.fetchImpl(url, {
279
+ method: options.method ?? (options.body !== void 0 ? "POST" : "GET"),
280
+ headers: {
281
+ Accept: "application/json",
282
+ "Content-Type": "application/json",
283
+ ...transport.headers,
284
+ ...authHeaders,
285
+ ...options.headers
286
+ },
287
+ body: options.body !== void 0 ? JSON.stringify(options.body) : void 0,
288
+ signal: controller.signal
289
+ });
290
+ const text = await response.text();
291
+ const parsed = text.length > 0 ? safeParseJson(text) : null;
292
+ if (!response.ok) {
293
+ throw errorFromHttpStatus(response.status, parsed ?? { message: text });
294
+ }
295
+ return parsed;
296
+ } catch (error) {
297
+ if (error instanceof AureonError && !isRetryableError(error)) {
298
+ throw error;
299
+ }
300
+ if (isAbortError(error)) {
301
+ const timeoutError = new AureonTimeoutError(
302
+ "Request timed out or was aborted",
303
+ { url, timeoutMs: transport.timeoutMs }
304
+ );
305
+ if (attempt <= maxRetries) {
306
+ transport.logger?.warn("aureon.retry", {
307
+ path,
308
+ attempt,
309
+ reason: "timeout"
310
+ });
311
+ await sleep(retryDelayMs);
312
+ continue;
313
+ }
314
+ throw timeoutError;
315
+ }
316
+ if (error instanceof AureonError) {
317
+ if (attempt <= maxRetries && isRetryableError(error)) {
318
+ transport.logger?.warn("aureon.retry", {
319
+ path,
320
+ attempt,
321
+ code: error.code,
322
+ status: error.status
323
+ });
324
+ await sleep(retryDelayMs);
325
+ continue;
326
+ }
327
+ throw error;
328
+ }
329
+ const networkError = new AureonNetworkError(
330
+ error instanceof Error ? error.message : "Network request failed",
331
+ { url }
332
+ );
333
+ if (attempt <= maxRetries) {
334
+ transport.logger?.warn("aureon.retry", {
335
+ path,
336
+ attempt,
337
+ reason: "network"
338
+ });
339
+ await sleep(retryDelayMs);
340
+ continue;
341
+ }
342
+ throw networkError;
343
+ } finally {
344
+ clearTimeout(timeout);
345
+ if (options.signal) options.signal.removeEventListener("abort", onAbort);
346
+ }
347
+ }
348
+ }
349
+
350
+ // src/types/client-options.ts
351
+ var DEFAULT_TIMEOUT_MS2 = 3e4;
352
+ function resolveTimeoutMs(options) {
353
+ const value = options.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
354
+ if (!Number.isFinite(value) || value <= 0) {
355
+ throw new Error("timeoutMs must be a positive finite number");
356
+ }
357
+ return value;
358
+ }
359
+ function resolveHeaders(options) {
360
+ const headers = { ...options.headers ?? {} };
361
+ return headers;
362
+ }
363
+ function resolveMaxRetries(options) {
364
+ const value = options.maxRetries ?? 0;
365
+ if (!Number.isInteger(value) || value < 0) {
366
+ throw new Error("maxRetries must be a non-negative integer");
367
+ }
368
+ return value;
369
+ }
370
+ function resolveRetryDelayMs(options) {
371
+ const value = options.retryDelayMs ?? 250;
372
+ if (!Number.isFinite(value) || value < 0) {
373
+ throw new Error("retryDelayMs must be a non-negative finite number");
374
+ }
375
+ return value;
376
+ }
377
+
378
+ // src/types/market.ts
379
+ function normalizeSymbol(symbol) {
380
+ return symbol.trim().toUpperCase();
381
+ }
382
+
383
+ // src/validation/market-input.ts
384
+ function normalizeApplyMarketEventInput(input) {
385
+ const symbol = normalizeSymbol(input.symbol ?? "");
386
+ if (!symbol) throw new AureonValidationError("symbol is required");
387
+ if (!Number.isFinite(input.priceChangeRatio)) {
388
+ throw new AureonValidationError("priceChangeRatio must be a finite number");
389
+ }
390
+ if (input.priceChangeRatio <= -0.95) {
391
+ throw new AureonValidationError(
392
+ "priceChangeRatio is too extreme for preview runtime"
393
+ );
394
+ }
395
+ return {
396
+ ...input,
397
+ symbol,
398
+ autoRestore: input.autoRestore !== false,
399
+ name: input.name?.trim() || void 0,
400
+ description: input.description?.trim() || void 0
401
+ };
402
+ }
403
+
404
+ // src/types/objective.ts
405
+ var OBJECTIVE_KINDS = [
406
+ "stable_allocation",
407
+ "balanced_portfolio",
408
+ "risk_ceiling",
409
+ "reward_reinvestment"
410
+ ];
411
+ var OBJECTIVE_PRIORITIES = [
412
+ "low",
413
+ "medium",
414
+ "high",
415
+ "critical"
416
+ ];
417
+ function isObjectiveKind(value) {
418
+ return OBJECTIVE_KINDS.includes(value);
419
+ }
420
+ function isObjectivePriority(value) {
421
+ return OBJECTIVE_PRIORITIES.includes(value);
422
+ }
423
+
424
+ // src/validation/objective-input.ts
425
+ function buildPolicySummary(kind, targetWeight, tolerance) {
426
+ const targetPct = (targetWeight * 100).toFixed(1);
427
+ const tolPct = (tolerance * 100).toFixed(1);
428
+ switch (kind) {
429
+ case "stable_allocation":
430
+ return `Maintain ${targetPct}% stable allocation within \xB1${tolPct}%`;
431
+ case "balanced_portfolio":
432
+ return `Hold balanced weights near ${targetPct}% primary sleeve within \xB1${tolPct}%`;
433
+ case "risk_ceiling":
434
+ return `Keep portfolio risk at or below configured ceiling with ${tolPct}% buffer`;
435
+ case "reward_reinvestment":
436
+ return `Reinvest available rewards toward ${targetPct}% target sleeve`;
437
+ default:
438
+ return `Objective policy target ${targetPct}% \xB1${tolPct}%`;
439
+ }
440
+ }
441
+ function normalizeCreateObjectiveInput(input) {
442
+ const name = input.name?.trim();
443
+ if (!name || name.length < 3) {
444
+ throw new AureonValidationError("Objective name must be at least 3 characters");
445
+ }
446
+ if (!isObjectiveKind(input.kind)) {
447
+ throw new AureonValidationError(`Unsupported objective kind: ${input.kind}`);
448
+ }
449
+ if (input.targetWeight < 0 || input.targetWeight > 1) {
450
+ throw new AureonValidationError("targetWeight must be between 0 and 1");
451
+ }
452
+ if (input.tolerance < 0 || input.tolerance > 0.5) {
453
+ throw new AureonValidationError("tolerance must be between 0 and 0.5");
454
+ }
455
+ const priority = input.priority ?? "high";
456
+ if (!isObjectivePriority(priority)) {
457
+ throw new AureonValidationError(`Unsupported priority: ${priority}`);
458
+ }
459
+ if (input.kind === "balanced_portfolio") {
460
+ const symbol = input.targetSymbol?.trim().toUpperCase();
461
+ if (!symbol) {
462
+ throw new AureonValidationError(
463
+ "balanced_portfolio requires targetSymbol"
464
+ );
465
+ }
466
+ return {
467
+ ...input,
468
+ name,
469
+ priority,
470
+ targetSymbol: symbol,
471
+ // SDK / agent path defaults to Automatic. Explicit "manual" is reserved
472
+ // for the operator utility Approve UX; not recommended for integrations.
473
+ automationMode: input.automationMode === "manual" ? "manual" : "auto"
474
+ };
475
+ }
476
+ return {
477
+ ...input,
478
+ name,
479
+ priority,
480
+ targetSymbol: null,
481
+ automationMode: input.automationMode === "manual" ? "manual" : "auto"
482
+ };
483
+ }
484
+ function normalizeUpdateObjectiveInput(input) {
485
+ const next = { ...input };
486
+ if (next.name !== void 0) {
487
+ const name = next.name.trim();
488
+ if (name.length < 3) {
489
+ throw new AureonValidationError("Objective name must be at least 3 characters");
490
+ }
491
+ next.name = name;
492
+ }
493
+ if (next.targetWeight !== void 0) {
494
+ if (next.targetWeight < 0 || next.targetWeight > 1) {
495
+ throw new AureonValidationError("targetWeight must be between 0 and 1");
496
+ }
497
+ }
498
+ if (next.tolerance !== void 0) {
499
+ if (next.tolerance < 0 || next.tolerance > 0.5) {
500
+ throw new AureonValidationError("tolerance must be between 0 and 0.5");
501
+ }
502
+ }
503
+ if (next.priority !== void 0 && !isObjectivePriority(next.priority)) {
504
+ throw new AureonValidationError(`Unsupported priority: ${next.priority}`);
505
+ }
506
+ if (next.automationMode !== void 0) {
507
+ throw new AureonValidationError(
508
+ "automationMode cannot be changed after create: recreate the objective instead"
509
+ );
510
+ }
511
+ return next;
512
+ }
513
+ function assertId(value, label) {
514
+ if (!value || typeof value !== "string" || value.trim().length < 8) {
515
+ throw new AureonValidationError(`Invalid ${label}`);
516
+ }
517
+ }
518
+
519
+ // src/client/aureon-client.ts
520
+ var AureonClient = class {
521
+ transport;
522
+ constructor(options = {}) {
523
+ const baseUrl = options.baseUrl ?? DEFAULT_API_BASE_URL;
524
+ const staticToken = options.authToken;
525
+ const getAccessToken = options.getAccessToken ?? (staticToken ? () => staticToken : void 0);
526
+ const staticApiKey = options.apiKey;
527
+ const getApiKey = options.getApiKey ?? (staticApiKey ? () => staticApiKey : void 0);
528
+ this.transport = {
529
+ baseUrl: assertBaseUrl(baseUrl),
530
+ fetchImpl: resolveFetch(options.fetch),
531
+ headers: {
532
+ ...userAgentHeader(SDK_VERSION),
533
+ ...resolveHeaders({ ...options})
534
+ },
535
+ timeoutMs: resolveTimeoutMs(options),
536
+ maxRetries: resolveMaxRetries(options),
537
+ retryDelayMs: resolveRetryDelayMs(options),
538
+ logger: options.logger,
539
+ getAccessToken,
540
+ getApiKey
541
+ };
542
+ }
543
+ /** Returns the resolved API base URL. */
544
+ get baseUrl() {
545
+ return this.transport.baseUrl;
546
+ }
547
+ /** Health probe for connectivity checks. No auth required. */
548
+ async ping() {
549
+ return requestJson(this.transport, ENDPOINTS.healthz);
550
+ }
551
+ /**
552
+ * Requests a single-use wallet auth nonce/message for the given address.
553
+ * No Bearer token required.
554
+ */
555
+ async getAuthNonce(address) {
556
+ const trimmed = address?.trim();
557
+ if (!trimmed) {
558
+ throw new AureonValidationError("address is required");
559
+ }
560
+ return requestJson(
561
+ this.transport,
562
+ withQuery(ENDPOINTS.authNonce, { address: trimmed })
563
+ );
564
+ }
565
+ /**
566
+ * Verifies a wallet signature and returns a Bearer session.
567
+ * No Bearer token required on the request itself.
568
+ */
569
+ async verifyWallet(input) {
570
+ const address = input.address?.trim();
571
+ const message = input.message?.trim();
572
+ const signature = input.signature?.trim();
573
+ if (!address || !message || !signature) {
574
+ throw new AureonValidationError(
575
+ "address, message, and signature are required"
576
+ );
577
+ }
578
+ return requestJson(this.transport, ENDPOINTS.authVerify, {
579
+ method: "POST",
580
+ body: { address, message, signature }
581
+ });
582
+ }
583
+ /**
584
+ * Local preview login without a wallet signature.
585
+ * Only succeeds when the backend has `AUREON_ALLOW_DEV_LOGIN=1`.
586
+ */
587
+ async devLogin() {
588
+ return requestJson(this.transport, ENDPOINTS.authDevLogin, {
589
+ method: "POST"
590
+ });
591
+ }
592
+ /** Revokes the current Bearer session on the server. */
593
+ async logout() {
594
+ return requestJson(this.transport, ENDPOINTS.authLogout, {
595
+ method: "POST"
596
+ });
597
+ }
598
+ /** Returns the wallet bound to the current Bearer session. Auth required. */
599
+ async me() {
600
+ return requestJson(this.transport, ENDPOINTS.authMe);
601
+ }
602
+ /**
603
+ * Creates and activates a Financial Compass Objective (FCO).
604
+ * SDK / agent path always prefers Automatic (`automationMode` omitted → `"auto"`).
605
+ * Mode cannot be changed later via `updateObjective`; recreate instead.
606
+ * Passing `"manual"` is reserved for the operator utility Approve UX.
607
+ * Auth required.
608
+ */
609
+ async createObjective(input) {
610
+ const body = normalizeCreateObjectiveInput(input);
611
+ return requestJson(this.transport, ENDPOINTS.objectives, {
612
+ method: "POST",
613
+ body
614
+ });
615
+ }
616
+ /** Lists objectives for the authenticated wallet. Auth required. */
617
+ async listObjectives() {
618
+ const result = await requestJson(
619
+ this.transport,
620
+ ENDPOINTS.objectives
621
+ );
622
+ return result.objectives;
623
+ }
624
+ /** Fetches a single objective by id. Auth required. */
625
+ async getObjective(id) {
626
+ assertId(id, "objective id");
627
+ return requestJson(this.transport, objectivePath(id));
628
+ }
629
+ /**
630
+ * Applies a partial update to an objective policy or metadata.
631
+ * Does **not** accept `automationMode` (mode is locked at create).
632
+ * Auth required.
633
+ */
634
+ async updateObjective(id, input) {
635
+ assertId(id, "objective id");
636
+ const body = normalizeUpdateObjectiveInput(input);
637
+ return requestJson(this.transport, objectivePath(id), {
638
+ method: "PATCH",
639
+ body
640
+ });
641
+ }
642
+ /** Pauses continuous evaluation for an objective. Auth required. */
643
+ async pauseObjective(id) {
644
+ assertId(id, "objective id");
645
+ return requestJson(this.transport, objectivePausePath(id), {
646
+ method: "POST"
647
+ });
648
+ }
649
+ /** Resumes evaluation for a paused objective. Auth required. */
650
+ async resumeObjective(id) {
651
+ assertId(id, "objective id");
652
+ return requestJson(this.transport, objectiveResumePath(id), {
653
+ method: "POST"
654
+ });
655
+ }
656
+ /** Returns health for one objective or all objectives when id is omitted. Auth required. */
657
+ async getHealth(objectiveId) {
658
+ const path = withQuery(ENDPOINTS.health, { objectiveId });
659
+ const result = await requestJson(
660
+ this.transport,
661
+ path
662
+ );
663
+ return result.health;
664
+ }
665
+ /** Returns timeline events, optionally filtered by objective. Auth required. */
666
+ async getTimeline(objectiveId) {
667
+ const path = withQuery(ENDPOINTS.timeline, { objectiveId });
668
+ const result = await requestJson(
669
+ this.transport,
670
+ path
671
+ );
672
+ return result.events;
673
+ }
674
+ /** Returns the current portfolio snapshot for the wallet. Auth required. */
675
+ async getPortfolio() {
676
+ return requestJson(this.transport, ENDPOINTS.portfolio);
677
+ }
678
+ /**
679
+ * Replaces the wallet capital book with the provided positions.
680
+ * Auth required. Does not invent holdings: every row must be supplied.
681
+ */
682
+ async setPortfolio(positions) {
683
+ if (!Array.isArray(positions) || positions.length === 0) {
684
+ throw new AureonValidationError("positions must be a non-empty array");
685
+ }
686
+ const result = await requestJson(
687
+ this.transport,
688
+ ENDPOINTS.portfolio,
689
+ { method: "PUT", body: { positions } }
690
+ );
691
+ return result.portfolio;
692
+ }
693
+ /**
694
+ * Clears all capital-book positions for the authenticated wallet.
695
+ * Auth required. Does not invent seeded holdings.
696
+ */
697
+ async clearPortfolio() {
698
+ const result = await requestJson(
699
+ this.transport,
700
+ ENDPOINTS.portfolioClear,
701
+ { method: "POST" }
702
+ );
703
+ return result.portfolio;
704
+ }
705
+ /**
706
+ * Replaces the capital book with on-chain balances for the session wallet
707
+ * (Robinhood Chain via the AUREON API). Vault balances merge into the book.
708
+ * Requires a wallet Bearer session; SDK clients should also send an API key
709
+ * when keys are enforced. Does not invent holdings; only positive balances
710
+ * returned by the API.
711
+ */
712
+ async syncPortfolio() {
713
+ return requestJson(this.transport, ENDPOINTS.portfolioSync, {
714
+ method: "POST"
715
+ });
716
+ }
717
+ /**
718
+ * Refreshes portfolio marks from live public market data, re-evaluates
719
+ * objectives, optionally fires breach webhooks, and returns restore suggestions.
720
+ * Auth required.
721
+ */
722
+ async refreshWatchdog() {
723
+ return requestJson(this.transport, ENDPOINTS.watchdogRefresh, {
724
+ method: "POST"
725
+ });
726
+ }
727
+ /** Returns dashboard overview aggregates. Auth required. */
728
+ async getOverview() {
729
+ return requestJson(this.transport, ENDPOINTS.overview);
730
+ }
731
+ /**
732
+ * Applies a controlled market event to portfolio marks.
733
+ * When autoRestore is true, the API evaluates health and may run staged restorative execution.
734
+ * Auth required.
735
+ */
736
+ async applyMarketEvent(input) {
737
+ const body = normalizeApplyMarketEventInput(input);
738
+ return requestJson(this.transport, ENDPOINTS.marketEvents, {
739
+ method: "POST",
740
+ body
741
+ });
742
+ }
743
+ /** Lists controlled market event presets. Auth required. */
744
+ async listMarketPresets() {
745
+ const result = await requestJson(
746
+ this.transport,
747
+ ENDPOINTS.marketPresets
748
+ );
749
+ return result.presets;
750
+ }
751
+ /**
752
+ * Returns the restore plan for an objective (wrap ETH, unwrap WETH, or vault swap).
753
+ * Auth required.
754
+ */
755
+ async getRestorePlan(objectiveId) {
756
+ assertId(objectiveId, "objective id");
757
+ const result = await requestJson(
758
+ this.transport,
759
+ objectiveRestorePlanPath(objectiveId)
760
+ );
761
+ return result.plan;
762
+ }
763
+ /**
764
+ * Runs restorative execution for an objective currently outside policy.
765
+ * Vault Sell A→Buy B when configured. ETH↔WETH wrap/unwrap is client-side
766
+ * via getRestorePlan; this endpoint rejects those with action details.
767
+ * Auth required.
768
+ */
769
+ async runExecution(objectiveId) {
770
+ assertId(objectiveId, "objective id");
771
+ return requestJson(this.transport, ENDPOINTS.executionsRun, {
772
+ method: "POST",
773
+ body: { objectiveId }
774
+ });
775
+ }
776
+ /**
777
+ * Runs vault-backed restorative execution for an objective outside policy.
778
+ * Auth required.
779
+ */
780
+ async restoreObjective(objectiveId) {
781
+ assertId(objectiveId, "objective id");
782
+ return requestJson(this.transport, objectiveRestorePath(objectiveId), {
783
+ method: "POST"
784
+ });
785
+ }
786
+ /** Lists recent execution receipts. Auth required. */
787
+ async listExecutions(objectiveId) {
788
+ const path = withQuery(ENDPOINTS.executions, { objectiveId });
789
+ const result = await requestJson(
790
+ this.transport,
791
+ path
792
+ );
793
+ return result.executions;
794
+ }
795
+ /** Returns the vault overview for the authenticated wallet. Auth required. */
796
+ async getVault() {
797
+ return requestJson(this.transport, ENDPOINTS.vault);
798
+ }
799
+ /** Returns compact vault funding status before restore. Auth required. */
800
+ async getVaultStatus() {
801
+ return requestJson(this.transport, ENDPOINTS.vaultStatus);
802
+ }
803
+ /**
804
+ * Prepares wallet-signed calldata steps for a vault deposit.
805
+ * Auth required.
806
+ */
807
+ async prepareVaultDeposit(input) {
808
+ const symbol = input.symbol?.trim();
809
+ const amount = input.amount?.trim();
810
+ if (!symbol) {
811
+ throw new AureonValidationError(
812
+ "symbol is required (ETH or an allowlisted ERC-20)"
813
+ );
814
+ }
815
+ if (!amount) {
816
+ throw new AureonValidationError("amount is required");
817
+ }
818
+ return requestJson(this.transport, ENDPOINTS.vaultPrepareDeposit, {
819
+ method: "POST",
820
+ body: { symbol: symbol.toUpperCase(), amount }
821
+ });
822
+ }
823
+ /**
824
+ * Prepares wallet-signed calldata steps for a vault withdraw (any allowlisted ERC-20).
825
+ * Auth required.
826
+ */
827
+ async prepareVaultWithdraw(input) {
828
+ const symbol = (input.symbol?.trim() || "WETH").toUpperCase();
829
+ const amount = input.amount?.trim();
830
+ if (!amount) {
831
+ throw new AureonValidationError("amount is required");
832
+ }
833
+ if (symbol === "ETH") {
834
+ throw new AureonValidationError(
835
+ 'withdraw symbol cannot be "ETH", use WETH'
836
+ );
837
+ }
838
+ return requestJson(this.transport, ENDPOINTS.vaultPrepareWithdraw, {
839
+ method: "POST",
840
+ body: { symbol, amount }
841
+ });
842
+ }
843
+ /**
844
+ * Lists SDK API keys for the authenticated wallet.
845
+ * Used by the operator utility Developer page.
846
+ */
847
+ async listApiKeys() {
848
+ const result = await requestJson(
849
+ this.transport,
850
+ ENDPOINTS.developerApiKeys
851
+ );
852
+ return result.keys;
853
+ }
854
+ /**
855
+ * Creates an SDK API key. `secret` is returned once; store it immediately.
856
+ */
857
+ async createApiKey(name) {
858
+ const trimmed = name.trim();
859
+ if (trimmed.length < 2) {
860
+ throw new AureonValidationError("name must be at least 2 characters");
861
+ }
862
+ return requestJson(this.transport, ENDPOINTS.developerApiKeys, {
863
+ method: "POST",
864
+ body: { name: trimmed }
865
+ });
866
+ }
867
+ /** Revokes (deletes) an SDK API key owned by this wallet. */
868
+ async revokeApiKey(keyId) {
869
+ assertId(keyId, "api key id");
870
+ return requestJson(this.transport, developerApiKeyPath(keyId), {
871
+ method: "DELETE"
872
+ });
873
+ }
874
+ /** Toggles the status (active/paused) of an SDK API key owned by this wallet. */
875
+ async toggleApiKey(keyId) {
876
+ assertId(keyId, "api key id");
877
+ return requestJson(this.transport, `${developerApiKeyPath(keyId)}/toggle`, {
878
+ method: "POST"
879
+ });
880
+ }
881
+ };
882
+
883
+ // src/client/factory.ts
884
+ function createAureonClient(options = {}) {
885
+ return new AureonClient({
886
+ baseUrl: options.baseUrl ?? DEFAULT_API_BASE_URL,
887
+ ...options
888
+ });
889
+ }
890
+ function createLocalAureonClient(overrides = {}) {
891
+ return new AureonClient({
892
+ ...overrides,
893
+ baseUrl: overrides.baseUrl ?? LOCAL_API_BASE_URL
894
+ });
895
+ }
896
+
897
+ // src/auth/session.ts
898
+ function createSessionTokenProvider(initialToken) {
899
+ let token = initialToken ?? null;
900
+ return {
901
+ getAccessToken: () => token,
902
+ setToken: (next) => {
903
+ token = next;
904
+ },
905
+ clear: () => {
906
+ token = null;
907
+ }
908
+ };
909
+ }
910
+
911
+ // src/formatting/display.ts
912
+ function formatUsd(value) {
913
+ return new Intl.NumberFormat("en-US", {
914
+ style: "currency",
915
+ currency: "USD",
916
+ maximumFractionDigits: 2
917
+ }).format(value);
918
+ }
919
+ function formatWeight(weight) {
920
+ return `${(weight * 100).toFixed(1)}%`;
921
+ }
922
+ function healthTone(state) {
923
+ switch (state) {
924
+ case "healthy":
925
+ return "positive";
926
+ case "warning":
927
+ return "caution";
928
+ case "violation":
929
+ return "critical";
930
+ case "paused":
931
+ return "neutral";
932
+ default:
933
+ return "neutral";
934
+ }
935
+ }
936
+ function formatSignedPercent(ratio) {
937
+ const pct = ratio * 100;
938
+ const sign = pct > 0 ? "+" : "";
939
+ return `${sign}${pct.toFixed(1)}%`;
940
+ }
941
+ function formatIsoTime(iso) {
942
+ try {
943
+ return new Intl.DateTimeFormat("en-US", {
944
+ hour: "2-digit",
945
+ minute: "2-digit",
946
+ second: "2-digit"
947
+ }).format(new Date(iso));
948
+ } catch {
949
+ return iso;
950
+ }
951
+ }
952
+
953
+ // src/types/health.ts
954
+ function isHealthState(value) {
955
+ return ["healthy", "warning", "violation", "paused"].includes(value);
956
+ }
957
+ function healthRank(state) {
958
+ switch (state) {
959
+ case "healthy":
960
+ return 0;
961
+ case "warning":
962
+ return 1;
963
+ case "paused":
964
+ return 2;
965
+ case "violation":
966
+ return 3;
967
+ default:
968
+ return 99;
969
+ }
970
+ }
971
+ function pickWorstHealth(records) {
972
+ if (records.length === 0) return null;
973
+ return [...records].sort((a, b) => healthRank(b.state) - healthRank(a.state))[0] ?? null;
974
+ }
975
+
976
+ // src/types/timeline.ts
977
+ var TIMELINE_EVENT_TYPES = [
978
+ "objective_created",
979
+ "objective_updated",
980
+ "objective_paused",
981
+ "objective_resumed",
982
+ "health_changed",
983
+ "violation_detected",
984
+ "evaluation_started",
985
+ "execution_started",
986
+ "execution_completed",
987
+ "market_event_applied",
988
+ "objective_restored",
989
+ "capital_provisioned",
990
+ "capital_cleared",
991
+ "capital_synced"
992
+ ];
993
+ function isTimelineEventType(value) {
994
+ return TIMELINE_EVENT_TYPES.includes(value);
995
+ }
996
+
997
+ // src/types/execution.ts
998
+ function isVaultSettlement(receipt) {
999
+ return receipt.settlement === "vault";
1000
+ }
1001
+
1002
+ // src/adapters/logging-adapter.ts
1003
+ var silentLogger = {
1004
+ debug() {
1005
+ },
1006
+ info() {
1007
+ },
1008
+ warn() {
1009
+ },
1010
+ error() {
1011
+ }
1012
+ };
1013
+ function createConsoleLogger(prefix = "aureon-sdk") {
1014
+ const write = (level, message, context) => {
1015
+ const line = `[${prefix}] ${message}`;
1016
+ if (level === "error") console.error(line, context ?? "");
1017
+ else if (level === "warn") console.warn(line, context ?? "");
1018
+ else console.log(line, context ?? "");
1019
+ };
1020
+ return {
1021
+ debug: (m, c) => write("debug", m, c),
1022
+ info: (m, c) => write("info", m, c),
1023
+ warn: (m, c) => write("warn", m, c),
1024
+ error: (m, c) => write("error", m, c)
1025
+ };
1026
+ }
1027
+
1028
+ export { API_KEY_HEADER, AureonClient, AureonConflictError, AureonError, AureonNetworkError, AureonNotFoundError, AureonTimeoutError, AureonValidationError, DEFAULT_API_BASE_URL, DEFAULT_TIMEOUT_MS, ENDPOINTS, LOCAL_API_BASE_URL, OBJECTIVE_KINDS, OBJECTIVE_PRIORITIES, PRODUCT_NAME, PRODUCT_TAGLINE, SDK_NAME, SDK_VERSION, TIMELINE_EVENT_TYPES, assertBaseUrl, buildPolicySummary, createAureonClient, createConsoleLogger, createLocalAureonClient, createSessionTokenProvider, errorFromHttpStatus, formatIsoTime, formatSignedPercent, formatUsd, formatWeight, healthTone, isAureonError, isHealthState, isObjectiveKind, isObjectivePriority, isTimelineEventType, isVaultSettlement, joinUrl, normalizeCreateObjectiveInput, normalizeUpdateObjectiveInput, pickWorstHealth, requestJson, resolveFetch, silentLogger, withQuery };
1029
+ //# sourceMappingURL=index.js.map
1030
+ //# sourceMappingURL=index.js.map