nemoflow 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/README.md +84 -0
- package/dist/client.d.ts +31 -0
- package/dist/client.js +248 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.js +13 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# NemoFlow TypeScript SDK
|
|
2
|
+
|
|
3
|
+
TypeScript client for the [NemoFlow API](https://api.nemoflow.ai) — the reliability oracle for AI agents. Requires Node.js 18+ (uses native `fetch`).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install nemoflow
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start — one line with guard()
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { NemoFlow } from "nemoflow";
|
|
15
|
+
|
|
16
|
+
const nemo = new NemoFlow("nf_live_...");
|
|
17
|
+
|
|
18
|
+
// Wrap any tool call — assess, execute, report, auto-fallback
|
|
19
|
+
const result = await nemo.guard(
|
|
20
|
+
"https://api.openai.com/v1/chat/completions",
|
|
21
|
+
() => openai.chat.completions.create({ model: "gpt-4", messages }),
|
|
22
|
+
);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Auto-fallback
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
const result = await nemo.guard(
|
|
29
|
+
"https://api.openai.com/v1/chat/completions",
|
|
30
|
+
() => openai.chat.completions.create({ model: "gpt-4", messages }),
|
|
31
|
+
{
|
|
32
|
+
minScore: 50,
|
|
33
|
+
fallbacks: [
|
|
34
|
+
{
|
|
35
|
+
toolIdentifier: "https://api.anthropic.com/v1/messages",
|
|
36
|
+
fn: () => anthropic.messages.create({ model: "claude-sonnet-4-20250514", messages }),
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Journey tracking
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// First attempt fails
|
|
47
|
+
await nemo.report({
|
|
48
|
+
toolIdentifier: "https://api.sendgrid.com/v3/mail/send",
|
|
49
|
+
success: false, errorCategory: "rate_limit",
|
|
50
|
+
sessionId: "session-123", attemptNumber: 1,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Fallback succeeds
|
|
54
|
+
await nemo.report({
|
|
55
|
+
toolIdentifier: "https://api.resend.com/emails",
|
|
56
|
+
success: true, latencyMs: 180,
|
|
57
|
+
sessionId: "session-123", attemptNumber: 2,
|
|
58
|
+
previousTool: "https://api.sendgrid.com/v3/mail/send",
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Discovery
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
const gems = await nemo.discoverHiddenGems({ category: "email" });
|
|
66
|
+
const chain = await nemo.discoverFallbackChain("https://api.sendgrid.com/v3/mail/send");
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Direct API usage
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
const result = await nemo.assess({
|
|
73
|
+
toolIdentifier: "https://api.openai.com/v1/chat/completions",
|
|
74
|
+
context: "customer support chatbot",
|
|
75
|
+
});
|
|
76
|
+
console.log(result.reliabilityScore); // 89.0
|
|
77
|
+
console.log(result.predictedFailureRisk); // "low"
|
|
78
|
+
console.log(result.topAlternatives); // [{ tool: "...", score: 90 }]
|
|
79
|
+
|
|
80
|
+
await nemo.report({
|
|
81
|
+
toolIdentifier: "https://api.openai.com/v1/chat/completions",
|
|
82
|
+
success: true, latencyMs: 2500,
|
|
83
|
+
});
|
|
84
|
+
```
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type NemoFlowOptions, type AssessParams, type AssessResponse, type ReportParams, type ReportResponse, type HiddenGemsResponse, type FallbackChainResponse, type GuardOptions } from "./types.js";
|
|
2
|
+
export declare class NemoFlow {
|
|
3
|
+
private readonly apiKey;
|
|
4
|
+
private readonly baseUrl;
|
|
5
|
+
constructor(apiKey: string, options?: NemoFlowOptions);
|
|
6
|
+
/** Assess a tool's reliability and get recommendations. */
|
|
7
|
+
assess(params: AssessParams): Promise<AssessResponse>;
|
|
8
|
+
/** Report an outcome for a tool invocation. */
|
|
9
|
+
report(params: ReportParams): Promise<ReportResponse>;
|
|
10
|
+
/** Find hidden gem tools that shine as fallbacks. */
|
|
11
|
+
discoverHiddenGems(options?: {
|
|
12
|
+
category?: string;
|
|
13
|
+
limit?: number;
|
|
14
|
+
}): Promise<HiddenGemsResponse>;
|
|
15
|
+
/** Get the best fallback tools when a specific tool fails. */
|
|
16
|
+
discoverFallbackChain(toolIdentifier: string, options?: {
|
|
17
|
+
limit?: number;
|
|
18
|
+
}): Promise<FallbackChainResponse>;
|
|
19
|
+
/**
|
|
20
|
+
* Execute a tool call with automatic reliability guard.
|
|
21
|
+
*
|
|
22
|
+
* 1. Assesses the tool's reliability score
|
|
23
|
+
* 2. If score < minScore and fallbacks exist, skips to next
|
|
24
|
+
* 3. Executes the tool call
|
|
25
|
+
* 4. Reports success/failure back to NemoFlow
|
|
26
|
+
* 5. On failure with fallbacks, tries the next option
|
|
27
|
+
*/
|
|
28
|
+
guard<T>(toolIdentifier: string, fn: () => Promise<T>, options?: GuardOptions<T>): Promise<T>;
|
|
29
|
+
private post;
|
|
30
|
+
private get;
|
|
31
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NemoFlow = void 0;
|
|
4
|
+
const types_js_1 = require("./types.js");
|
|
5
|
+
const DEFAULT_BASE_URL = "https://api.nemoflow.ai";
|
|
6
|
+
class NemoFlow {
|
|
7
|
+
constructor(apiKey, options) {
|
|
8
|
+
if (!apiKey) {
|
|
9
|
+
throw new Error("An API key is required to create a NemoFlow client.");
|
|
10
|
+
}
|
|
11
|
+
this.apiKey = apiKey;
|
|
12
|
+
this.baseUrl = (options?.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
13
|
+
}
|
|
14
|
+
// ── Core endpoints ─────────────────────────────────────────────
|
|
15
|
+
/** Assess a tool's reliability and get recommendations. */
|
|
16
|
+
async assess(params) {
|
|
17
|
+
const raw = await this.post("/v1/assess", {
|
|
18
|
+
tool_identifier: params.toolIdentifier,
|
|
19
|
+
context: params.context,
|
|
20
|
+
sample_payload: params.samplePayload,
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
reliabilityScore: raw.reliability_score,
|
|
24
|
+
confidence: raw.confidence,
|
|
25
|
+
historicalSuccessRate: raw.historical_success_rate,
|
|
26
|
+
predictedFailureRisk: raw.predicted_failure_risk,
|
|
27
|
+
commonPitfalls: raw.common_pitfalls,
|
|
28
|
+
recommendedMitigations: raw.recommended_mitigations,
|
|
29
|
+
topAlternatives: raw.top_alternatives.map((a) => ({
|
|
30
|
+
tool: a.tool,
|
|
31
|
+
score: a.score,
|
|
32
|
+
reason: a.reason,
|
|
33
|
+
})),
|
|
34
|
+
estimatedLatencyMs: raw.estimated_latency_ms,
|
|
35
|
+
lastUpdated: raw.last_updated,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Report an outcome for a tool invocation. */
|
|
39
|
+
async report(params) {
|
|
40
|
+
const raw = await this.post("/v1/report", {
|
|
41
|
+
tool_identifier: params.toolIdentifier,
|
|
42
|
+
success: params.success,
|
|
43
|
+
error_category: params.errorCategory,
|
|
44
|
+
latency_ms: params.latencyMs,
|
|
45
|
+
context: params.context,
|
|
46
|
+
session_id: params.sessionId,
|
|
47
|
+
attempt_number: params.attemptNumber,
|
|
48
|
+
previous_tool: params.previousTool,
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
status: raw.status,
|
|
52
|
+
toolId: raw.tool_id,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// ── Discovery endpoints ────────────────────────────────────────
|
|
56
|
+
/** Find hidden gem tools that shine as fallbacks. */
|
|
57
|
+
async discoverHiddenGems(options) {
|
|
58
|
+
const params = new URLSearchParams();
|
|
59
|
+
if (options?.category)
|
|
60
|
+
params.set("category", options.category);
|
|
61
|
+
if (options?.limit)
|
|
62
|
+
params.set("limit", String(options.limit));
|
|
63
|
+
const raw = await this.get(`/v1/discover/hidden-gems?${params}`);
|
|
64
|
+
return {
|
|
65
|
+
hiddenGems: raw.hidden_gems.map((g) => ({
|
|
66
|
+
tool: g.tool,
|
|
67
|
+
displayName: g.display_name,
|
|
68
|
+
category: g.category,
|
|
69
|
+
fallbackSuccessRate: g.fallback_success_rate,
|
|
70
|
+
timesUsedAsFallback: g.times_used_as_fallback,
|
|
71
|
+
avgLatencyMs: g.avg_latency_ms,
|
|
72
|
+
})),
|
|
73
|
+
count: raw.count,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** Get the best fallback tools when a specific tool fails. */
|
|
77
|
+
async discoverFallbackChain(toolIdentifier, options) {
|
|
78
|
+
const params = new URLSearchParams({
|
|
79
|
+
tool_identifier: toolIdentifier,
|
|
80
|
+
});
|
|
81
|
+
if (options?.limit)
|
|
82
|
+
params.set("limit", String(options.limit));
|
|
83
|
+
const raw = await this.get(`/v1/discover/fallback-chain?${params}`);
|
|
84
|
+
return {
|
|
85
|
+
tool: raw.tool,
|
|
86
|
+
fallbackChain: raw.fallback_chain.map((f) => ({
|
|
87
|
+
fallbackTool: f.fallback_tool,
|
|
88
|
+
displayName: f.display_name,
|
|
89
|
+
timesChosenAfterFailure: f.times_chosen_after_failure,
|
|
90
|
+
successRate: f.success_rate,
|
|
91
|
+
avgLatencyMs: f.avg_latency_ms,
|
|
92
|
+
})),
|
|
93
|
+
count: raw.count,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// ── Guard ──────────────────────────────────────────────────────
|
|
97
|
+
/**
|
|
98
|
+
* Execute a tool call with automatic reliability guard.
|
|
99
|
+
*
|
|
100
|
+
* 1. Assesses the tool's reliability score
|
|
101
|
+
* 2. If score < minScore and fallbacks exist, skips to next
|
|
102
|
+
* 3. Executes the tool call
|
|
103
|
+
* 4. Reports success/failure back to NemoFlow
|
|
104
|
+
* 5. On failure with fallbacks, tries the next option
|
|
105
|
+
*/
|
|
106
|
+
async guard(toolIdentifier, fn, options) {
|
|
107
|
+
const context = options?.context ?? "";
|
|
108
|
+
const minScore = options?.minScore ?? 0;
|
|
109
|
+
const sessionId = crypto.randomUUID().replace(/-/g, "").slice(0, 16);
|
|
110
|
+
const allTools = [
|
|
111
|
+
{ toolIdentifier, fn },
|
|
112
|
+
...(options?.fallbacks ?? []),
|
|
113
|
+
];
|
|
114
|
+
let lastError;
|
|
115
|
+
for (let i = 0; i < allTools.length; i++) {
|
|
116
|
+
const attempt = i + 1;
|
|
117
|
+
const tool = allTools[i];
|
|
118
|
+
const previousTool = i > 0 ? allTools[i - 1].toolIdentifier : undefined;
|
|
119
|
+
// Assess
|
|
120
|
+
let score = 100;
|
|
121
|
+
try {
|
|
122
|
+
const assessment = await this.assess({
|
|
123
|
+
toolIdentifier: tool.toolIdentifier,
|
|
124
|
+
context,
|
|
125
|
+
});
|
|
126
|
+
score = assessment.reliabilityScore;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// If assess fails, don't block the tool call
|
|
130
|
+
}
|
|
131
|
+
// Skip if score too low and we have more options
|
|
132
|
+
if (score < minScore && attempt < allTools.length) {
|
|
133
|
+
try {
|
|
134
|
+
await this.report({
|
|
135
|
+
toolIdentifier: tool.toolIdentifier,
|
|
136
|
+
success: false,
|
|
137
|
+
errorCategory: "skipped_low_score",
|
|
138
|
+
context,
|
|
139
|
+
sessionId,
|
|
140
|
+
attemptNumber: attempt,
|
|
141
|
+
previousTool,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Best-effort reporting
|
|
146
|
+
}
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
// Execute
|
|
150
|
+
const start = performance.now();
|
|
151
|
+
try {
|
|
152
|
+
const result = await tool.fn();
|
|
153
|
+
const latencyMs = Math.round(performance.now() - start);
|
|
154
|
+
// Report success (best-effort)
|
|
155
|
+
try {
|
|
156
|
+
await this.report({
|
|
157
|
+
toolIdentifier: tool.toolIdentifier,
|
|
158
|
+
success: true,
|
|
159
|
+
latencyMs,
|
|
160
|
+
context,
|
|
161
|
+
sessionId,
|
|
162
|
+
attemptNumber: attempt,
|
|
163
|
+
previousTool,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// Don't fail the call if reporting fails
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
catch (e) {
|
|
172
|
+
const latencyMs = Math.round(performance.now() - start);
|
|
173
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
174
|
+
// Report failure (best-effort)
|
|
175
|
+
try {
|
|
176
|
+
await this.report({
|
|
177
|
+
toolIdentifier: tool.toolIdentifier,
|
|
178
|
+
success: false,
|
|
179
|
+
errorCategory: classifyError(lastError),
|
|
180
|
+
latencyMs,
|
|
181
|
+
context,
|
|
182
|
+
sessionId,
|
|
183
|
+
attemptNumber: attempt,
|
|
184
|
+
previousTool,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Best-effort reporting
|
|
189
|
+
}
|
|
190
|
+
// If no more fallbacks, throw
|
|
191
|
+
if (attempt >= allTools.length) {
|
|
192
|
+
throw lastError;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
throw lastError;
|
|
197
|
+
}
|
|
198
|
+
// ── Internals ──────────────────────────────────────────────────
|
|
199
|
+
async post(path, body) {
|
|
200
|
+
// Strip undefined values
|
|
201
|
+
const clean = Object.fromEntries(Object.entries(body).filter(([, v]) => v !== undefined));
|
|
202
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
203
|
+
method: "POST",
|
|
204
|
+
headers: {
|
|
205
|
+
"Content-Type": "application/json",
|
|
206
|
+
"X-Api-Key": this.apiKey,
|
|
207
|
+
},
|
|
208
|
+
body: JSON.stringify(clean),
|
|
209
|
+
});
|
|
210
|
+
const responseBody = await response.json();
|
|
211
|
+
if (!response.ok) {
|
|
212
|
+
throw new types_js_1.NemoFlowError(`NemoFlow API error: ${response.status} ${response.statusText}`, response.status, responseBody);
|
|
213
|
+
}
|
|
214
|
+
return responseBody;
|
|
215
|
+
}
|
|
216
|
+
async get(path) {
|
|
217
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
218
|
+
method: "GET",
|
|
219
|
+
headers: { "X-Api-Key": this.apiKey },
|
|
220
|
+
});
|
|
221
|
+
const responseBody = await response.json();
|
|
222
|
+
if (!response.ok) {
|
|
223
|
+
throw new types_js_1.NemoFlowError(`NemoFlow API error: ${response.status} ${response.statusText}`, response.status, responseBody);
|
|
224
|
+
}
|
|
225
|
+
return responseBody;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
exports.NemoFlow = NemoFlow;
|
|
229
|
+
// ── Error classification ─────────────────────────────────────────
|
|
230
|
+
function classifyError(error) {
|
|
231
|
+
const name = error.name.toLowerCase();
|
|
232
|
+
const msg = error.message.toLowerCase();
|
|
233
|
+
if (name.includes("timeout") || msg.includes("timeout") || msg.includes("timed out"))
|
|
234
|
+
return "timeout";
|
|
235
|
+
if (name.includes("ratelimit") || msg.includes("rate") || msg.includes("429") || msg.includes("too many"))
|
|
236
|
+
return "rate_limit";
|
|
237
|
+
if (name.includes("auth") || msg.includes("unauthorized") || msg.includes("401") || msg.includes("403"))
|
|
238
|
+
return "auth_failure";
|
|
239
|
+
if (name.includes("validation") || msg.includes("invalid") || msg.includes("422"))
|
|
240
|
+
return "validation_error";
|
|
241
|
+
if (msg.includes("not found") || msg.includes("404"))
|
|
242
|
+
return "not_found";
|
|
243
|
+
if (msg.includes("permission") || msg.includes("forbidden"))
|
|
244
|
+
return "permission_denied";
|
|
245
|
+
if (name.includes("connect") || msg.includes("connection") || msg.includes("econnrefused"))
|
|
246
|
+
return "connection_error";
|
|
247
|
+
return "server_error";
|
|
248
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { NemoFlow } from "./client.js";
|
|
2
|
+
export { type NemoFlowOptions, type AssessParams, type AssessResponse, type AlternativeTool, type ReportParams, type ReportResponse, type HiddenGem, type HiddenGemsResponse, type FallbackTool, type FallbackChainResponse, type GuardOptions, NemoFlowError, } from "./types.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NemoFlowError = exports.NemoFlow = void 0;
|
|
4
|
+
var client_js_1 = require("./client.js");
|
|
5
|
+
Object.defineProperty(exports, "NemoFlow", { enumerable: true, get: function () { return client_js_1.NemoFlow; } });
|
|
6
|
+
var types_js_1 = require("./types.js");
|
|
7
|
+
Object.defineProperty(exports, "NemoFlowError", { enumerable: true, get: function () { return types_js_1.NemoFlowError; } });
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** Options for configuring the NemoFlow client. */
|
|
2
|
+
export interface NemoFlowOptions {
|
|
3
|
+
/** Override the default API base URL. */
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface AssessParams {
|
|
7
|
+
toolIdentifier: string;
|
|
8
|
+
context?: string;
|
|
9
|
+
samplePayload?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
export interface AlternativeTool {
|
|
12
|
+
tool: string;
|
|
13
|
+
score: number;
|
|
14
|
+
reason: string;
|
|
15
|
+
}
|
|
16
|
+
export interface AssessResponse {
|
|
17
|
+
reliabilityScore: number;
|
|
18
|
+
confidence: number;
|
|
19
|
+
historicalSuccessRate: string;
|
|
20
|
+
predictedFailureRisk: string;
|
|
21
|
+
commonPitfalls: string[];
|
|
22
|
+
recommendedMitigations: string[];
|
|
23
|
+
topAlternatives: AlternativeTool[];
|
|
24
|
+
estimatedLatencyMs: number;
|
|
25
|
+
lastUpdated: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ReportParams {
|
|
28
|
+
toolIdentifier: string;
|
|
29
|
+
success: boolean;
|
|
30
|
+
errorCategory?: string;
|
|
31
|
+
latencyMs?: number;
|
|
32
|
+
context?: string;
|
|
33
|
+
/** Groups related tool calls in the same workflow. */
|
|
34
|
+
sessionId?: string;
|
|
35
|
+
/** Which attempt is this? 1 = first try, 2 = fallback, etc. */
|
|
36
|
+
attemptNumber?: number;
|
|
37
|
+
/** Tool identifier that was tried before this one. */
|
|
38
|
+
previousTool?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface ReportResponse {
|
|
41
|
+
status: string;
|
|
42
|
+
toolId: string;
|
|
43
|
+
}
|
|
44
|
+
export interface HiddenGem {
|
|
45
|
+
tool: string;
|
|
46
|
+
displayName: string;
|
|
47
|
+
category: string;
|
|
48
|
+
fallbackSuccessRate: number;
|
|
49
|
+
timesUsedAsFallback: number;
|
|
50
|
+
avgLatencyMs: number | null;
|
|
51
|
+
}
|
|
52
|
+
export interface HiddenGemsResponse {
|
|
53
|
+
hiddenGems: HiddenGem[];
|
|
54
|
+
count: number;
|
|
55
|
+
}
|
|
56
|
+
export interface FallbackTool {
|
|
57
|
+
fallbackTool: string;
|
|
58
|
+
displayName: string;
|
|
59
|
+
timesChosenAfterFailure: number;
|
|
60
|
+
successRate: number;
|
|
61
|
+
avgLatencyMs: number | null;
|
|
62
|
+
}
|
|
63
|
+
export interface FallbackChainResponse {
|
|
64
|
+
tool: string;
|
|
65
|
+
fallbackChain: FallbackTool[];
|
|
66
|
+
count: number;
|
|
67
|
+
}
|
|
68
|
+
export interface GuardOptions<T> {
|
|
69
|
+
/** Workflow context for context-bucketed scoring. */
|
|
70
|
+
context?: string;
|
|
71
|
+
/** Minimum reliability score to proceed (0-100). Default 0 = always try. */
|
|
72
|
+
minScore?: number;
|
|
73
|
+
/** Fallback tools to try on failure, in order. */
|
|
74
|
+
fallbacks?: Array<{
|
|
75
|
+
toolIdentifier: string;
|
|
76
|
+
fn: () => Promise<T>;
|
|
77
|
+
}>;
|
|
78
|
+
}
|
|
79
|
+
export declare class NemoFlowError extends Error {
|
|
80
|
+
readonly status: number;
|
|
81
|
+
readonly body: unknown;
|
|
82
|
+
constructor(message: string, status: number, body: unknown);
|
|
83
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NemoFlowError = void 0;
|
|
4
|
+
// ── Errors ──────────────────────────────────────────────────────────
|
|
5
|
+
class NemoFlowError extends Error {
|
|
6
|
+
constructor(message, status, body) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "NemoFlowError";
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.body = body;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.NemoFlowError = NemoFlowError;
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nemoflow",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Reliability oracle for AI agents — pick the right tool from the start",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"prepublishOnly": "npm run build"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"nemoflow",
|
|
16
|
+
"ai",
|
|
17
|
+
"agents",
|
|
18
|
+
"reliability",
|
|
19
|
+
"tools",
|
|
20
|
+
"llm",
|
|
21
|
+
"api",
|
|
22
|
+
"fallback"
|
|
23
|
+
],
|
|
24
|
+
"author": "NemoFlow <hello@nemoflow.ai>",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"homepage": "https://nemoflow.ai",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/netvistamedia/nemoflow"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.0.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"typescript": "^6.0.2"
|
|
36
|
+
}
|
|
37
|
+
}
|