@layerinfinite/sdk 0.1.1

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 ADDED
@@ -0,0 +1,121 @@
1
+ # Layerinfinite TypeScript SDK (`@layerinfinite/sdk`)
2
+
3
+ Layerinfinite is a decision intelligence middleware for AI agents — it records action outcomes, computes composite trust scores, and recommends the highest-performing next action so your agents learn from every decision. Drop it into any TypeScript or JavaScript project with zero runtime dependencies.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @layerinfinite/sdk
9
+ # or
10
+ yarn add @layerinfinite/sdk
11
+ # or
12
+ pnpm add @layerinfinite/sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { LayerinfiniteClient } from '@layerinfinite/sdk';
19
+
20
+ const client = new LayerinfiniteClient({ apiKey: 'layerinfinite_your_key' });
21
+
22
+ // Ask Layerinfinite which action to take
23
+ const scores = await client.getScores({
24
+ agentId: 'my-agent',
25
+ issueType: 'billing_dispute',
26
+ });
27
+ console.log(scores.top_action?.action_name); // e.g. "escalate_to_senior"
28
+ console.log(`Policy: ${scores.policy}`); // exploit | explore | escalate
29
+
30
+ // Log the outcome after the action runs
31
+ await client.logOutcome({
32
+ agent_id: 'my-agent',
33
+ action_id: scores.top_action!.action_id,
34
+ context_id: scores.context_id,
35
+ issue_type: 'billing_dispute',
36
+ success: true,
37
+ outcome_score: 0.9,
38
+ business_outcome: 'resolved',
39
+ });
40
+ ```
41
+
42
+ ## LangChain Integration
43
+
44
+ ```typescript
45
+ import { LayerinfiniteClient } from '@layerinfinite/sdk';
46
+ import { tool } from '@langchain/core/tools';
47
+
48
+ const layerinfinite = new LayerinfiniteClient({ apiKey: process.env.LAYERINFINITE_API_KEY! });
49
+
50
+ const resolveTicket = tool(
51
+ async ({ agentId, issueType }: { agentId: string; issueType: string }) => {
52
+ const scores = await layerinfinite.getScores({ agentId, issueType });
53
+ const action = scores.top_action!;
54
+ // ... run the action ...
55
+ await layerinfinite.logOutcome({
56
+ agent_id: agentId, action_id: action.action_id,
57
+ context_id: scores.context_id, issue_type: issueType,
58
+ success: true, outcome_score: 0.85, business_outcome: 'resolved',
59
+ });
60
+ return action.action_name;
61
+ },
62
+ { name: 'resolve_ticket', description: 'Resolve a support ticket guided by Layerinfinite' }
63
+ );
64
+ ```
65
+
66
+ ## CrewAI-style Integration
67
+
68
+ ```typescript
69
+ import { LayerinfiniteClient } from '@layerinfinite/sdk';
70
+
71
+ const layerinfinite = new LayerinfiniteClient({ apiKey: process.env.LAYERINFINITE_API_KEY! });
72
+
73
+ export async function agentDecide(agentId: string, issue: string) {
74
+ const { top_action, context_id, policy } = await layerinfinite.getScores({
75
+ agentId, issueType: issue,
76
+ });
77
+ console.log(`[Layerinfinite] Policy: ${policy}, Action: ${top_action?.action_name}`);
78
+ return { action: top_action, contextId: context_id };
79
+ }
80
+ ```
81
+
82
+ ## Error Handling
83
+
84
+ ```typescript
85
+ import {
86
+ LayerinfiniteClient,
87
+ LayerinfiniteAuthError,
88
+ LayerinfiniteRateLimitError,
89
+ LayerinfiniteServerError,
90
+ } from '@layerinfinite/sdk';
91
+
92
+ const client = new LayerinfiniteClient({ apiKey: 'layerinfinite_key' });
93
+
94
+ try {
95
+ const scores = await client.getScores({ agentId: 'agent-1', issueType: 'billing' });
96
+ } catch (err) {
97
+ if (err instanceof LayerinfiniteAuthError) {
98
+ console.error('Invalid API key');
99
+ } else if (err instanceof LayerinfiniteRateLimitError) {
100
+ console.error(`Rate limited — retry after ${err.retryAfter}s`);
101
+ await new Promise(r => setTimeout(r, err.retryAfter * 1000));
102
+ } else if (err instanceof LayerinfiniteServerError) {
103
+ console.error(`Server error: ${err.statusCode}`);
104
+ }
105
+ }
106
+ ```
107
+
108
+ ## Configuration
109
+
110
+ | Option | Default | Description |
111
+ |--------|---------|-------------|
112
+ | `apiKey` | required | Your Layerinfinite API key |
113
+ | `baseUrl` | `https://your-app.railway.app` | API base URL |
114
+ | `timeout` | `10000` | Request timeout in ms |
115
+ | `maxRetries` | `3` | Max retries on 429/5xx |
116
+
117
+ ## Links
118
+
119
+ - **npm**: [@layerinfinite/sdk](https://www.npmjs.com/package/@layerinfinite/sdk)
120
+ - **Docs**: [docs.layerinfinite.ai](https://docs.layerinfinite.ai)
121
+ - **GitHub**: [github.com/hari08varma/Outcome](https://github.com/hari08varma/Outcome)
@@ -0,0 +1,115 @@
1
+ interface ScoredAction {
2
+ action_id: string;
3
+ action_name: string;
4
+ action_category: string;
5
+ composite_score: number;
6
+ confidence: number;
7
+ total_attempts: number;
8
+ policy_reason?: string;
9
+ is_cold_start?: boolean;
10
+ is_low_sample?: boolean;
11
+ }
12
+ interface GetScoresResponse {
13
+ ranked_actions: ScoredAction[];
14
+ top_action: ScoredAction | null;
15
+ policy: 'exploit' | 'explore' | 'escalate';
16
+ cold_start: boolean;
17
+ context_id: string;
18
+ agent_id: string;
19
+ served_from_cache?: boolean;
20
+ }
21
+ interface LogOutcomeRequest {
22
+ agent_id: string;
23
+ action_id: string;
24
+ context_id: string;
25
+ issue_type: string;
26
+ success: boolean;
27
+ /** Must be between 0.0 and 1.0 */
28
+ outcome_score: number;
29
+ business_outcome: 'resolved' | 'failed' | 'pending';
30
+ episode_id?: string;
31
+ response_ms?: number;
32
+ feedback_signal?: 'immediate' | 'delayed' | 'none';
33
+ }
34
+ interface LogOutcomeResponse {
35
+ logged: boolean;
36
+ outcome_id: string;
37
+ agent_trust_score: number;
38
+ trust_status: string;
39
+ policy: string;
40
+ }
41
+ interface LayerinfiniteConfig {
42
+ apiKey: string;
43
+ /** Default: https://your-app.railway.app */
44
+ baseUrl?: string;
45
+ /** Request timeout in ms. Default: 10000 */
46
+ timeout?: number;
47
+ /** Max retries on 429/5xx. Default: 3 */
48
+ maxRetries?: number;
49
+ }
50
+
51
+ declare class LayerinfiniteClient {
52
+ private readonly apiKey;
53
+ private readonly baseUrl;
54
+ private readonly timeout;
55
+ private readonly maxRetries;
56
+ constructor(config: LayerinfiniteConfig);
57
+ private raiseForStatus;
58
+ private fetchWithRetry;
59
+ /**
60
+ * Fetch ranked action scores for the given agent and context.
61
+ *
62
+ * @throws {LayerinfiniteAuthError} on 401
63
+ * @throws {LayerinfiniteRateLimitError} on 429
64
+ * @throws {LayerinfiniteServerError} on 5xx
65
+ */
66
+ getScores(params: {
67
+ agentId: string;
68
+ issueType: string;
69
+ environment?: string;
70
+ }): Promise<GetScoresResponse>;
71
+ /**
72
+ * Log the outcome of an action taken by the agent.
73
+ *
74
+ * @throws {LayerinfiniteAuthError} on 401
75
+ * @throws {LayerinfiniteRateLimitError} on 429
76
+ * @throws {LayerinfiniteServerError} on 5xx
77
+ */
78
+ logOutcome(request: LogOutcomeRequest): Promise<LogOutcomeResponse>;
79
+ /**
80
+ * Check API health (no auth required).
81
+ */
82
+ health(): Promise<{
83
+ status: string;
84
+ version: string;
85
+ }>;
86
+ }
87
+
88
+ declare class LayerinfiniteError extends Error {
89
+ readonly statusCode?: number;
90
+ readonly responseBody?: unknown;
91
+ constructor(message: string, statusCode?: number, responseBody?: unknown);
92
+ }
93
+ /** Raised on HTTP 401 — invalid or missing API key. */
94
+ declare class LayerinfiniteAuthError extends LayerinfiniteError {
95
+ name: string;
96
+ constructor(message: string, responseBody?: unknown);
97
+ }
98
+ /** Raised on HTTP 429 — rate limit exceeded. */
99
+ declare class LayerinfiniteRateLimitError extends LayerinfiniteError {
100
+ name: string;
101
+ readonly retryAfter: number;
102
+ constructor(message: string, retryAfter: number);
103
+ }
104
+ /** Raised on HTTP 404 — resource not found. */
105
+ declare class LayerinfiniteNotFoundError extends LayerinfiniteError {
106
+ name: string;
107
+ constructor(message: string, responseBody?: unknown);
108
+ }
109
+ /** Raised on HTTP 5xx — server-side error. */
110
+ declare class LayerinfiniteServerError extends LayerinfiniteError {
111
+ name: string;
112
+ constructor(message: string, statusCode: number, responseBody?: unknown);
113
+ }
114
+
115
+ export { type GetScoresResponse, LayerinfiniteAuthError, LayerinfiniteClient, type LayerinfiniteConfig, LayerinfiniteError, LayerinfiniteNotFoundError, LayerinfiniteRateLimitError, LayerinfiniteServerError, type LogOutcomeRequest, type LogOutcomeResponse, type ScoredAction };
@@ -0,0 +1,115 @@
1
+ interface ScoredAction {
2
+ action_id: string;
3
+ action_name: string;
4
+ action_category: string;
5
+ composite_score: number;
6
+ confidence: number;
7
+ total_attempts: number;
8
+ policy_reason?: string;
9
+ is_cold_start?: boolean;
10
+ is_low_sample?: boolean;
11
+ }
12
+ interface GetScoresResponse {
13
+ ranked_actions: ScoredAction[];
14
+ top_action: ScoredAction | null;
15
+ policy: 'exploit' | 'explore' | 'escalate';
16
+ cold_start: boolean;
17
+ context_id: string;
18
+ agent_id: string;
19
+ served_from_cache?: boolean;
20
+ }
21
+ interface LogOutcomeRequest {
22
+ agent_id: string;
23
+ action_id: string;
24
+ context_id: string;
25
+ issue_type: string;
26
+ success: boolean;
27
+ /** Must be between 0.0 and 1.0 */
28
+ outcome_score: number;
29
+ business_outcome: 'resolved' | 'failed' | 'pending';
30
+ episode_id?: string;
31
+ response_ms?: number;
32
+ feedback_signal?: 'immediate' | 'delayed' | 'none';
33
+ }
34
+ interface LogOutcomeResponse {
35
+ logged: boolean;
36
+ outcome_id: string;
37
+ agent_trust_score: number;
38
+ trust_status: string;
39
+ policy: string;
40
+ }
41
+ interface LayerinfiniteConfig {
42
+ apiKey: string;
43
+ /** Default: https://your-app.railway.app */
44
+ baseUrl?: string;
45
+ /** Request timeout in ms. Default: 10000 */
46
+ timeout?: number;
47
+ /** Max retries on 429/5xx. Default: 3 */
48
+ maxRetries?: number;
49
+ }
50
+
51
+ declare class LayerinfiniteClient {
52
+ private readonly apiKey;
53
+ private readonly baseUrl;
54
+ private readonly timeout;
55
+ private readonly maxRetries;
56
+ constructor(config: LayerinfiniteConfig);
57
+ private raiseForStatus;
58
+ private fetchWithRetry;
59
+ /**
60
+ * Fetch ranked action scores for the given agent and context.
61
+ *
62
+ * @throws {LayerinfiniteAuthError} on 401
63
+ * @throws {LayerinfiniteRateLimitError} on 429
64
+ * @throws {LayerinfiniteServerError} on 5xx
65
+ */
66
+ getScores(params: {
67
+ agentId: string;
68
+ issueType: string;
69
+ environment?: string;
70
+ }): Promise<GetScoresResponse>;
71
+ /**
72
+ * Log the outcome of an action taken by the agent.
73
+ *
74
+ * @throws {LayerinfiniteAuthError} on 401
75
+ * @throws {LayerinfiniteRateLimitError} on 429
76
+ * @throws {LayerinfiniteServerError} on 5xx
77
+ */
78
+ logOutcome(request: LogOutcomeRequest): Promise<LogOutcomeResponse>;
79
+ /**
80
+ * Check API health (no auth required).
81
+ */
82
+ health(): Promise<{
83
+ status: string;
84
+ version: string;
85
+ }>;
86
+ }
87
+
88
+ declare class LayerinfiniteError extends Error {
89
+ readonly statusCode?: number;
90
+ readonly responseBody?: unknown;
91
+ constructor(message: string, statusCode?: number, responseBody?: unknown);
92
+ }
93
+ /** Raised on HTTP 401 — invalid or missing API key. */
94
+ declare class LayerinfiniteAuthError extends LayerinfiniteError {
95
+ name: string;
96
+ constructor(message: string, responseBody?: unknown);
97
+ }
98
+ /** Raised on HTTP 429 — rate limit exceeded. */
99
+ declare class LayerinfiniteRateLimitError extends LayerinfiniteError {
100
+ name: string;
101
+ readonly retryAfter: number;
102
+ constructor(message: string, retryAfter: number);
103
+ }
104
+ /** Raised on HTTP 404 — resource not found. */
105
+ declare class LayerinfiniteNotFoundError extends LayerinfiniteError {
106
+ name: string;
107
+ constructor(message: string, responseBody?: unknown);
108
+ }
109
+ /** Raised on HTTP 5xx — server-side error. */
110
+ declare class LayerinfiniteServerError extends LayerinfiniteError {
111
+ name: string;
112
+ constructor(message: string, statusCode: number, responseBody?: unknown);
113
+ }
114
+
115
+ export { type GetScoresResponse, LayerinfiniteAuthError, LayerinfiniteClient, type LayerinfiniteConfig, LayerinfiniteError, LayerinfiniteNotFoundError, LayerinfiniteRateLimitError, LayerinfiniteServerError, type LogOutcomeRequest, type LogOutcomeResponse, type ScoredAction };
package/dist/index.js ADDED
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ LayerinfiniteAuthError: () => LayerinfiniteAuthError,
24
+ LayerinfiniteClient: () => LayerinfiniteClient,
25
+ LayerinfiniteError: () => LayerinfiniteError,
26
+ LayerinfiniteNotFoundError: () => LayerinfiniteNotFoundError,
27
+ LayerinfiniteRateLimitError: () => LayerinfiniteRateLimitError,
28
+ LayerinfiniteServerError: () => LayerinfiniteServerError
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+
32
+ // src/errors.ts
33
+ var LayerinfiniteError = class extends Error {
34
+ constructor(message, statusCode, responseBody) {
35
+ super(message);
36
+ this.name = "LayerinfiniteError";
37
+ this.statusCode = statusCode;
38
+ this.responseBody = responseBody;
39
+ Object.setPrototypeOf(this, new.target.prototype);
40
+ }
41
+ };
42
+ var LayerinfiniteAuthError = class extends LayerinfiniteError {
43
+ constructor(message, responseBody) {
44
+ super(message, 401, responseBody);
45
+ this.name = "LayerinfiniteAuthError";
46
+ Object.setPrototypeOf(this, new.target.prototype);
47
+ }
48
+ };
49
+ var LayerinfiniteRateLimitError = class extends LayerinfiniteError {
50
+ constructor(message, retryAfter) {
51
+ super(message, 429);
52
+ this.name = "LayerinfiniteRateLimitError";
53
+ this.retryAfter = retryAfter;
54
+ Object.setPrototypeOf(this, new.target.prototype);
55
+ }
56
+ };
57
+ var LayerinfiniteNotFoundError = class extends LayerinfiniteError {
58
+ constructor(message, responseBody) {
59
+ super(message, 404, responseBody);
60
+ this.name = "LayerinfiniteNotFoundError";
61
+ Object.setPrototypeOf(this, new.target.prototype);
62
+ }
63
+ };
64
+ var LayerinfiniteServerError = class extends LayerinfiniteError {
65
+ constructor(message, statusCode, responseBody) {
66
+ super(message, statusCode, responseBody);
67
+ this.name = "LayerinfiniteServerError";
68
+ Object.setPrototypeOf(this, new.target.prototype);
69
+ }
70
+ };
71
+
72
+ // src/client.ts
73
+ var DEFAULT_BASE_URL = "https://your-app.railway.app";
74
+ var DEFAULT_TIMEOUT_MS = 1e4;
75
+ var DEFAULT_MAX_RETRIES = 3;
76
+ function sleep(ms) {
77
+ return new Promise((resolve) => setTimeout(resolve, ms));
78
+ }
79
+ var LayerinfiniteClient = class {
80
+ constructor(config) {
81
+ if (!config.apiKey) throw new LayerinfiniteError("apiKey is required");
82
+ this.apiKey = config.apiKey;
83
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
84
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT_MS;
85
+ this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
86
+ }
87
+ // ── Internal: parse and raise typed errors ─────────────────
88
+ async raiseForStatus(response) {
89
+ let body;
90
+ try {
91
+ body = await response.json();
92
+ } catch {
93
+ body = {};
94
+ }
95
+ const code = response.status;
96
+ if (code === 401) throw new LayerinfiniteAuthError(
97
+ "Invalid or missing API key. Verify your X-API-Key.",
98
+ body
99
+ );
100
+ if (code === 404) throw new LayerinfiniteNotFoundError("Resource not found.", body);
101
+ if (code === 429) {
102
+ const retryAfter = parseInt(response.headers.get("Retry-After") ?? "60", 10);
103
+ throw new LayerinfiniteRateLimitError(
104
+ `Rate limit exceeded. Retry after ${retryAfter}s.`,
105
+ retryAfter
106
+ );
107
+ }
108
+ if (code >= 500) {
109
+ const msg = body?.error ?? "unknown server error";
110
+ throw new LayerinfiniteServerError(`Layerinfinite server error [${code}]: ${msg}`, code, body);
111
+ }
112
+ throw new LayerinfiniteError(`Request error [${code}]`, code, body);
113
+ }
114
+ // ── Internal: fetch with timeout + retry ───────────────────
115
+ async fetchWithRetry(url, init, isRetryableStatus) {
116
+ let lastErr;
117
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
118
+ const controller = new AbortController();
119
+ const timer = setTimeout(() => controller.abort(), this.timeout);
120
+ try {
121
+ const response = await fetch(url, { ...init, signal: controller.signal });
122
+ if (response.status === 429 && attempt < this.maxRetries) {
123
+ const retryAfter = parseInt(response.headers.get("Retry-After") ?? "60", 10);
124
+ await sleep(retryAfter * 1e3);
125
+ continue;
126
+ }
127
+ if (response.status >= 500 && attempt < this.maxRetries) {
128
+ await sleep(1e3 * Math.pow(2, attempt));
129
+ continue;
130
+ }
131
+ if (!response.ok) await this.raiseForStatus(response);
132
+ return response;
133
+ } catch (err) {
134
+ if (err instanceof LayerinfiniteError) throw err;
135
+ if (err instanceof Error && err.name === "AbortError") {
136
+ lastErr = new LayerinfiniteError(`Request timed out after ${this.timeout}ms`);
137
+ } else {
138
+ lastErr = new LayerinfiniteError(`Network error: ${String(err)}`);
139
+ }
140
+ if (attempt >= this.maxRetries) throw lastErr;
141
+ } finally {
142
+ clearTimeout(timer);
143
+ }
144
+ }
145
+ throw lastErr ?? new LayerinfiniteError("Max retries exceeded");
146
+ }
147
+ // ── Public API ──────────────────────────────────────────────
148
+ /**
149
+ * Fetch ranked action scores for the given agent and context.
150
+ *
151
+ * @throws {LayerinfiniteAuthError} on 401
152
+ * @throws {LayerinfiniteRateLimitError} on 429
153
+ * @throws {LayerinfiniteServerError} on 5xx
154
+ */
155
+ async getScores(params) {
156
+ const qs = new URLSearchParams({
157
+ agent_id: params.agentId,
158
+ issue_type: params.issueType,
159
+ environment: params.environment ?? "production"
160
+ });
161
+ const url = `${this.baseUrl}/v1/get-scores?${qs.toString()}`;
162
+ const response = await this.fetchWithRetry(
163
+ url,
164
+ {
165
+ method: "GET",
166
+ headers: {
167
+ "X-API-Key": this.apiKey,
168
+ "Accept": "application/json"
169
+ }
170
+ },
171
+ (code) => code === 429 || code >= 500
172
+ );
173
+ const data = await response.json();
174
+ if (!data.agent_id) data.agent_id = params.agentId;
175
+ return data;
176
+ }
177
+ /**
178
+ * Log the outcome of an action taken by the agent.
179
+ *
180
+ * @throws {LayerinfiniteAuthError} on 401
181
+ * @throws {LayerinfiniteRateLimitError} on 429
182
+ * @throws {LayerinfiniteServerError} on 5xx
183
+ */
184
+ async logOutcome(request) {
185
+ const url = `${this.baseUrl}/v1/log-outcome`;
186
+ const response = await this.fetchWithRetry(
187
+ url,
188
+ {
189
+ method: "POST",
190
+ headers: {
191
+ "X-API-Key": this.apiKey,
192
+ "Content-Type": "application/json",
193
+ "Accept": "application/json"
194
+ },
195
+ body: JSON.stringify(request)
196
+ },
197
+ (code) => code === 429 || code >= 500
198
+ );
199
+ return response.json();
200
+ }
201
+ /**
202
+ * Check API health (no auth required).
203
+ */
204
+ async health() {
205
+ const controller = new AbortController();
206
+ const timer = setTimeout(() => controller.abort(), 5e3);
207
+ try {
208
+ const response = await fetch(`${this.baseUrl}/v1/health`, {
209
+ method: "GET",
210
+ headers: { "Accept": "application/json" },
211
+ signal: controller.signal
212
+ });
213
+ if (!response.ok) {
214
+ throw new LayerinfiniteError(`Health check failed [${response.status}]`);
215
+ }
216
+ return response.json();
217
+ } finally {
218
+ clearTimeout(timer);
219
+ }
220
+ }
221
+ };
222
+ // Annotate the CommonJS export names for ESM import in node:
223
+ 0 && (module.exports = {
224
+ LayerinfiniteAuthError,
225
+ LayerinfiniteClient,
226
+ LayerinfiniteError,
227
+ LayerinfiniteNotFoundError,
228
+ LayerinfiniteRateLimitError,
229
+ LayerinfiniteServerError
230
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,198 @@
1
+ // src/errors.ts
2
+ var LayerinfiniteError = class extends Error {
3
+ constructor(message, statusCode, responseBody) {
4
+ super(message);
5
+ this.name = "LayerinfiniteError";
6
+ this.statusCode = statusCode;
7
+ this.responseBody = responseBody;
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ };
11
+ var LayerinfiniteAuthError = class extends LayerinfiniteError {
12
+ constructor(message, responseBody) {
13
+ super(message, 401, responseBody);
14
+ this.name = "LayerinfiniteAuthError";
15
+ Object.setPrototypeOf(this, new.target.prototype);
16
+ }
17
+ };
18
+ var LayerinfiniteRateLimitError = class extends LayerinfiniteError {
19
+ constructor(message, retryAfter) {
20
+ super(message, 429);
21
+ this.name = "LayerinfiniteRateLimitError";
22
+ this.retryAfter = retryAfter;
23
+ Object.setPrototypeOf(this, new.target.prototype);
24
+ }
25
+ };
26
+ var LayerinfiniteNotFoundError = class extends LayerinfiniteError {
27
+ constructor(message, responseBody) {
28
+ super(message, 404, responseBody);
29
+ this.name = "LayerinfiniteNotFoundError";
30
+ Object.setPrototypeOf(this, new.target.prototype);
31
+ }
32
+ };
33
+ var LayerinfiniteServerError = class extends LayerinfiniteError {
34
+ constructor(message, statusCode, responseBody) {
35
+ super(message, statusCode, responseBody);
36
+ this.name = "LayerinfiniteServerError";
37
+ Object.setPrototypeOf(this, new.target.prototype);
38
+ }
39
+ };
40
+
41
+ // src/client.ts
42
+ var DEFAULT_BASE_URL = "https://your-app.railway.app";
43
+ var DEFAULT_TIMEOUT_MS = 1e4;
44
+ var DEFAULT_MAX_RETRIES = 3;
45
+ function sleep(ms) {
46
+ return new Promise((resolve) => setTimeout(resolve, ms));
47
+ }
48
+ var LayerinfiniteClient = class {
49
+ constructor(config) {
50
+ if (!config.apiKey) throw new LayerinfiniteError("apiKey is required");
51
+ this.apiKey = config.apiKey;
52
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
53
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT_MS;
54
+ this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
55
+ }
56
+ // ── Internal: parse and raise typed errors ─────────────────
57
+ async raiseForStatus(response) {
58
+ let body;
59
+ try {
60
+ body = await response.json();
61
+ } catch {
62
+ body = {};
63
+ }
64
+ const code = response.status;
65
+ if (code === 401) throw new LayerinfiniteAuthError(
66
+ "Invalid or missing API key. Verify your X-API-Key.",
67
+ body
68
+ );
69
+ if (code === 404) throw new LayerinfiniteNotFoundError("Resource not found.", body);
70
+ if (code === 429) {
71
+ const retryAfter = parseInt(response.headers.get("Retry-After") ?? "60", 10);
72
+ throw new LayerinfiniteRateLimitError(
73
+ `Rate limit exceeded. Retry after ${retryAfter}s.`,
74
+ retryAfter
75
+ );
76
+ }
77
+ if (code >= 500) {
78
+ const msg = body?.error ?? "unknown server error";
79
+ throw new LayerinfiniteServerError(`Layerinfinite server error [${code}]: ${msg}`, code, body);
80
+ }
81
+ throw new LayerinfiniteError(`Request error [${code}]`, code, body);
82
+ }
83
+ // ── Internal: fetch with timeout + retry ───────────────────
84
+ async fetchWithRetry(url, init, isRetryableStatus) {
85
+ let lastErr;
86
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
87
+ const controller = new AbortController();
88
+ const timer = setTimeout(() => controller.abort(), this.timeout);
89
+ try {
90
+ const response = await fetch(url, { ...init, signal: controller.signal });
91
+ if (response.status === 429 && attempt < this.maxRetries) {
92
+ const retryAfter = parseInt(response.headers.get("Retry-After") ?? "60", 10);
93
+ await sleep(retryAfter * 1e3);
94
+ continue;
95
+ }
96
+ if (response.status >= 500 && attempt < this.maxRetries) {
97
+ await sleep(1e3 * Math.pow(2, attempt));
98
+ continue;
99
+ }
100
+ if (!response.ok) await this.raiseForStatus(response);
101
+ return response;
102
+ } catch (err) {
103
+ if (err instanceof LayerinfiniteError) throw err;
104
+ if (err instanceof Error && err.name === "AbortError") {
105
+ lastErr = new LayerinfiniteError(`Request timed out after ${this.timeout}ms`);
106
+ } else {
107
+ lastErr = new LayerinfiniteError(`Network error: ${String(err)}`);
108
+ }
109
+ if (attempt >= this.maxRetries) throw lastErr;
110
+ } finally {
111
+ clearTimeout(timer);
112
+ }
113
+ }
114
+ throw lastErr ?? new LayerinfiniteError("Max retries exceeded");
115
+ }
116
+ // ── Public API ──────────────────────────────────────────────
117
+ /**
118
+ * Fetch ranked action scores for the given agent and context.
119
+ *
120
+ * @throws {LayerinfiniteAuthError} on 401
121
+ * @throws {LayerinfiniteRateLimitError} on 429
122
+ * @throws {LayerinfiniteServerError} on 5xx
123
+ */
124
+ async getScores(params) {
125
+ const qs = new URLSearchParams({
126
+ agent_id: params.agentId,
127
+ issue_type: params.issueType,
128
+ environment: params.environment ?? "production"
129
+ });
130
+ const url = `${this.baseUrl}/v1/get-scores?${qs.toString()}`;
131
+ const response = await this.fetchWithRetry(
132
+ url,
133
+ {
134
+ method: "GET",
135
+ headers: {
136
+ "X-API-Key": this.apiKey,
137
+ "Accept": "application/json"
138
+ }
139
+ },
140
+ (code) => code === 429 || code >= 500
141
+ );
142
+ const data = await response.json();
143
+ if (!data.agent_id) data.agent_id = params.agentId;
144
+ return data;
145
+ }
146
+ /**
147
+ * Log the outcome of an action taken by the agent.
148
+ *
149
+ * @throws {LayerinfiniteAuthError} on 401
150
+ * @throws {LayerinfiniteRateLimitError} on 429
151
+ * @throws {LayerinfiniteServerError} on 5xx
152
+ */
153
+ async logOutcome(request) {
154
+ const url = `${this.baseUrl}/v1/log-outcome`;
155
+ const response = await this.fetchWithRetry(
156
+ url,
157
+ {
158
+ method: "POST",
159
+ headers: {
160
+ "X-API-Key": this.apiKey,
161
+ "Content-Type": "application/json",
162
+ "Accept": "application/json"
163
+ },
164
+ body: JSON.stringify(request)
165
+ },
166
+ (code) => code === 429 || code >= 500
167
+ );
168
+ return response.json();
169
+ }
170
+ /**
171
+ * Check API health (no auth required).
172
+ */
173
+ async health() {
174
+ const controller = new AbortController();
175
+ const timer = setTimeout(() => controller.abort(), 5e3);
176
+ try {
177
+ const response = await fetch(`${this.baseUrl}/v1/health`, {
178
+ method: "GET",
179
+ headers: { "Accept": "application/json" },
180
+ signal: controller.signal
181
+ });
182
+ if (!response.ok) {
183
+ throw new LayerinfiniteError(`Health check failed [${response.status}]`);
184
+ }
185
+ return response.json();
186
+ } finally {
187
+ clearTimeout(timer);
188
+ }
189
+ }
190
+ };
191
+ export {
192
+ LayerinfiniteAuthError,
193
+ LayerinfiniteClient,
194
+ LayerinfiniteError,
195
+ LayerinfiniteNotFoundError,
196
+ LayerinfiniteRateLimitError,
197
+ LayerinfiniteServerError
198
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@layerinfinite/sdk",
3
+ "version": "0.1.1",
4
+ "description": "Decision intelligence layer for AI agents",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsup src/index.ts --format cjs,esm --dts",
17
+ "test": "vitest run",
18
+ "typecheck": "tsc --noEmit",
19
+ "prepublishOnly": "npm run build && npm run typecheck"
20
+ },
21
+ "keywords": [
22
+ "ai",
23
+ "agents",
24
+ "llm",
25
+ "decision-intelligence",
26
+ "layerinfinite",
27
+ "mlops"
28
+ ],
29
+ "author": "Layerinfinite",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/hari08varma/Outcome"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md"
38
+ ],
39
+ "dependencies": {},
40
+ "devDependencies": {
41
+ "tsup": "^8.0.0",
42
+ "typescript": "^5.4.0",
43
+ "vitest": "^1.4.0",
44
+ "@vitest/coverage-v8": "^1.4.0"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ }
49
+ }