@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 +121 -0
- package/dist/index.d.mts +115 -0
- package/dist/index.d.ts +115 -0
- package/dist/index.js +230 -0
- package/dist/index.mjs +198 -0
- package/package.json +49 -0
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)
|
package/dist/index.d.mts
ADDED
|
@@ -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.d.ts
ADDED
|
@@ -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
|
+
}
|