@cadreen/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/README.md +127 -0
- package/dist/client.d.ts +35 -0
- package/dist/client.js +205 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +62 -0
- package/dist/intelligence_helpers.d.ts +11 -0
- package/dist/intelligence_helpers.js +107 -0
- package/dist/resources/connections.d.ts +14 -0
- package/dist/resources/connections.js +37 -0
- package/dist/resources/executions.d.ts +8 -0
- package/dist/resources/executions.js +17 -0
- package/dist/resources/failures.d.ts +33 -0
- package/dist/resources/failures.js +51 -0
- package/dist/resources/guardrails.d.ts +12 -0
- package/dist/resources/guardrails.js +23 -0
- package/dist/resources/intent.d.ts +7 -0
- package/dist/resources/intent.js +77 -0
- package/dist/resources/memory.d.ts +9 -0
- package/dist/resources/memory.js +30 -0
- package/dist/resources/policies.d.ts +12 -0
- package/dist/resources/policies.js +26 -0
- package/dist/resources/skills.d.ts +41 -0
- package/dist/resources/skills.js +56 -0
- package/dist/resources/traces.d.ts +18 -0
- package/dist/resources/traces.js +58 -0
- package/dist/telemetry.d.ts +56 -0
- package/dist/telemetry.js +125 -0
- package/dist/types.d.ts +573 -0
- package/dist/types.js +38 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# @cadreen/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for Cadreen — Intelligence as a Service.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @cadreen/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { Cadreen } from "@cadreen/sdk";
|
|
15
|
+
|
|
16
|
+
const cadreen = new Cadreen({ apiKey: process.env.CADREEN_API_KEY });
|
|
17
|
+
|
|
18
|
+
// Intent — the primary door
|
|
19
|
+
const result = await cadreen.intent.invoke({
|
|
20
|
+
messages: [{ role: "user", content: "Handle refund for invoice inv_123" }],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
switch (result.type) {
|
|
24
|
+
case "direct":
|
|
25
|
+
console.log(result.message.content);
|
|
26
|
+
break;
|
|
27
|
+
case "clarify":
|
|
28
|
+
for (const q of result.questions) console.log(q);
|
|
29
|
+
break;
|
|
30
|
+
case "execution":
|
|
31
|
+
for await (const event of cadreen.executions.stream(result.execution.id)) {
|
|
32
|
+
console.log(event.type, event.data);
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
case "blocked":
|
|
36
|
+
console.log(result.policy.reason);
|
|
37
|
+
break;
|
|
38
|
+
case "connect_required":
|
|
39
|
+
console.log(result.connection.endpoint);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Memory — remember things
|
|
44
|
+
await cadreen.memory.remember({
|
|
45
|
+
type: "reference",
|
|
46
|
+
content: { text: "GDPR Article 17...", title: "GDPR Art. 17" },
|
|
47
|
+
authority: 10,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Policies — require approval
|
|
51
|
+
await cadreen.policies.requireApproval("Refunds over $500 require human approval");
|
|
52
|
+
|
|
53
|
+
// Traces — inspect what happened
|
|
54
|
+
const trace = await cadreen.traces.get(result.traceId);
|
|
55
|
+
console.log(trace.explain());
|
|
56
|
+
|
|
57
|
+
// Connections — connect tools
|
|
58
|
+
await cadreen.connections.registerOpenAPI({
|
|
59
|
+
name: "internal-erp",
|
|
60
|
+
specUrl: "https://erp.example.com/openapi.json",
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Configuration
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const cadreen = new Cadreen({
|
|
68
|
+
apiKey: "cadreen_...", // required
|
|
69
|
+
baseUrl: "https://accomplishanything.today", // optional, default shown
|
|
70
|
+
maxRetries: 2, // optional, default 2
|
|
71
|
+
timeout: 30000, // optional, default 30s
|
|
72
|
+
profile: "lean", // optional: "lean" | "audit" | "full" (default "full")
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Response Profiles
|
|
77
|
+
|
|
78
|
+
Control how much intelligence metadata you get back:
|
|
79
|
+
|
|
80
|
+
| Profile | What you get | Use when |
|
|
81
|
+
|---------|-------------|----------|
|
|
82
|
+
| `"full"` (default) | Full intelligence envelope with capability, reasoning, memory, governance, humility, process | You want full transparency |
|
|
83
|
+
| `"audit"` | Only governance decision + confidence + blocking gaps | You need to react to gates, not inspect internals |
|
|
84
|
+
| `"lean"` | No envelope. `trace_id` in body + `X-Cadreen-Trace-ID` header | Hot-looping, minimal payload |
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
// Lean: skip the envelope entirely
|
|
88
|
+
const lean = new Cadreen({ apiKey: "...", profile: "lean" });
|
|
89
|
+
|
|
90
|
+
// Audit: just the action-bearing fields
|
|
91
|
+
const audit = new Cadreen({ apiKey: "...", profile: "audit" });
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Error Handling
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { CadreenError } from "@cadreen/sdk";
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const result = await cadreen.intent.invoke({ messages: [...] });
|
|
101
|
+
} catch (err) {
|
|
102
|
+
if (err instanceof CadreenError) {
|
|
103
|
+
console.log(err.status); // HTTP status
|
|
104
|
+
console.log(err.code); // machine-readable code
|
|
105
|
+
console.log(err.intelligence); // trace context when available
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Resources
|
|
111
|
+
|
|
112
|
+
| Resource | Methods |
|
|
113
|
+
|----------|---------|
|
|
114
|
+
| `cadreen.intent` | `invoke(request)` |
|
|
115
|
+
| `cadreen.memory` | `remember(request)`, `search(request)`, `get(id)` |
|
|
116
|
+
| `cadreen.policies` | `create(request)`, `evaluate(request)`, `confirm(id)`, `list()`, `get(id)`, `requireApproval(desc)` |
|
|
117
|
+
| `cadreen.connections` | `registerOpenAPI(request)`, `registerMCP(request)`, `installComposio(request)`, `searchComposio(query)`, `composioStatus(...)`, `list()`, `delete(id)` |
|
|
118
|
+
| `cadreen.traces` | `get(id)`, `list(options?)`, `stats()` |
|
|
119
|
+
| `cadreen.executions` | `stream(id)`, `getStatus(id)` |
|
|
120
|
+
|
|
121
|
+
## Shorthand
|
|
122
|
+
|
|
123
|
+
`cadreen.invoke(request)` is an alias for `cadreen.intent.invoke(request)`.
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CadreenConfig, RequestOptions } from "./types";
|
|
2
|
+
export declare class CadreenError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly code: string;
|
|
5
|
+
readonly errorType: string;
|
|
6
|
+
readonly details?: Array<{
|
|
7
|
+
field: string;
|
|
8
|
+
message: string;
|
|
9
|
+
}>;
|
|
10
|
+
readonly intelligence?: unknown;
|
|
11
|
+
constructor(status: number, code: string, errorType: string, message: string, details?: Array<{
|
|
12
|
+
field: string;
|
|
13
|
+
message: string;
|
|
14
|
+
}>, intelligence?: unknown);
|
|
15
|
+
}
|
|
16
|
+
export declare class HttpClient {
|
|
17
|
+
private readonly baseUrl;
|
|
18
|
+
private readonly apiKey;
|
|
19
|
+
private readonly maxRetries;
|
|
20
|
+
private readonly timeout;
|
|
21
|
+
private readonly telemetry;
|
|
22
|
+
private readonly sandbox;
|
|
23
|
+
private readonly fixtures;
|
|
24
|
+
private readonly profile;
|
|
25
|
+
constructor(config: CadreenConfig);
|
|
26
|
+
private request;
|
|
27
|
+
get<T>(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<T>;
|
|
28
|
+
post<T>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
|
|
29
|
+
put<T>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
|
|
30
|
+
delete<T>(path: string): Promise<T>;
|
|
31
|
+
stream(path: string): AsyncGenerator<{
|
|
32
|
+
type: string;
|
|
33
|
+
data: Record<string, unknown>;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { NoOpProvider, wrapWithTelemetry } from "./telemetry";
|
|
2
|
+
export class CadreenError extends Error {
|
|
3
|
+
constructor(status, code, errorType, message, details, intelligence) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "CadreenError";
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.errorType = errorType;
|
|
9
|
+
this.details = details;
|
|
10
|
+
this.intelligence = intelligence;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const DEFAULT_BASE_URL = "https://accomplishanything.today";
|
|
14
|
+
const DEFAULT_MAX_RETRIES = 2;
|
|
15
|
+
const DEFAULT_TIMEOUT = 30000;
|
|
16
|
+
const RETRYABLE_STATUS_CODES = new Set([408, 429, 502, 503, 504]);
|
|
17
|
+
const IDEMPOTENT_METHODS = new Set(["GET", "PUT"]);
|
|
18
|
+
function generateIdempotencyKey() {
|
|
19
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
20
|
+
return crypto.randomUUID();
|
|
21
|
+
}
|
|
22
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
23
|
+
const r = (Math.random() * 16) | 0;
|
|
24
|
+
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
25
|
+
return v.toString(16);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function buildQueryString(params) {
|
|
29
|
+
const parts = [];
|
|
30
|
+
for (const [key, value] of Object.entries(params)) {
|
|
31
|
+
if (value !== undefined && value !== "") {
|
|
32
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return parts.length > 0 ? `?${parts.join("&")}` : "";
|
|
36
|
+
}
|
|
37
|
+
function parseSSELine(line) {
|
|
38
|
+
if (line.startsWith("event:")) {
|
|
39
|
+
return { event: line.slice(6).trim() };
|
|
40
|
+
}
|
|
41
|
+
if (line.startsWith("data:")) {
|
|
42
|
+
return { data: line.slice(5).trim() };
|
|
43
|
+
}
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
46
|
+
export class HttpClient {
|
|
47
|
+
constructor(config) {
|
|
48
|
+
this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
49
|
+
this.apiKey = config.apiKey;
|
|
50
|
+
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
51
|
+
this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
52
|
+
this.sandbox = config.sandbox ?? false;
|
|
53
|
+
this.fixtures = config.fixtures ?? {};
|
|
54
|
+
this.profile = config.profile ?? "full";
|
|
55
|
+
const provider = config.telemetry ?? new NoOpProvider();
|
|
56
|
+
this.telemetry = wrapWithTelemetry(provider);
|
|
57
|
+
}
|
|
58
|
+
async request(method, path, body, options) {
|
|
59
|
+
if (this.sandbox) {
|
|
60
|
+
const fixtureKey = `${method} ${path}`;
|
|
61
|
+
if (fixtureKey in this.fixtures) {
|
|
62
|
+
return this.fixtures[fixtureKey];
|
|
63
|
+
}
|
|
64
|
+
if (path in this.fixtures) {
|
|
65
|
+
return this.fixtures[path];
|
|
66
|
+
}
|
|
67
|
+
throw new CadreenError(404, "not_found", "not_found", `No fixture for ${fixtureKey}. Provide fixtures via CadreenConfig.fixtures keyed by "METHOD /path" or "/path".`);
|
|
68
|
+
}
|
|
69
|
+
const url = `${this.baseUrl}${path}`;
|
|
70
|
+
const span = this.telemetry.onRequestStart(method, path);
|
|
71
|
+
const startTime = Date.now();
|
|
72
|
+
const headers = {
|
|
73
|
+
"Content-Type": "application/json",
|
|
74
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
75
|
+
Accept: `application/json; profile="${this.profile}"`,
|
|
76
|
+
...(options?.headers || {}),
|
|
77
|
+
};
|
|
78
|
+
if (method === "POST" || method === "PUT" || method === "PATCH") {
|
|
79
|
+
headers["Idempotency-Key"] = options?.idempotencyKey || generateIdempotencyKey();
|
|
80
|
+
}
|
|
81
|
+
const isIdempotent = IDEMPOTENT_METHODS.has(method) || !!headers["Idempotency-Key"];
|
|
82
|
+
const maxAttempts = isIdempotent ? this.maxRetries + 1 : 1;
|
|
83
|
+
let lastError = null;
|
|
84
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
85
|
+
if (attempt > 0) {
|
|
86
|
+
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
|
|
87
|
+
this.telemetry.onRetry(method, path, attempt);
|
|
88
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const controller = new AbortController();
|
|
92
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
93
|
+
const response = await fetch(url, {
|
|
94
|
+
method,
|
|
95
|
+
headers,
|
|
96
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
97
|
+
signal: controller.signal,
|
|
98
|
+
});
|
|
99
|
+
clearTimeout(timeoutId);
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
let errorBody = null;
|
|
102
|
+
try {
|
|
103
|
+
errorBody = await response.json();
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// not JSON
|
|
107
|
+
}
|
|
108
|
+
const err = new CadreenError(response.status, errorBody?.error?.code || "unknown", errorBody?.error?.type || "error", errorBody?.error?.message || response.statusText, errorBody?.error?.details, errorBody?.intelligence);
|
|
109
|
+
if (RETRYABLE_STATUS_CODES.has(response.status) && isIdempotent && attempt < maxAttempts - 1) {
|
|
110
|
+
lastError = err;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
this.telemetry.onError(span, err);
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
if (response.status === 204) {
|
|
117
|
+
this.telemetry.onRequestEnd(span, method, path, 204, Date.now() - startTime);
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
const result = (await response.json());
|
|
121
|
+
this.telemetry.onRequestEnd(span, method, path, response.status, Date.now() - startTime);
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (error instanceof CadreenError) {
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
129
|
+
throw new CadreenError(408, "timeout", "timeout", "Request timed out");
|
|
130
|
+
}
|
|
131
|
+
if (isIdempotent && attempt < maxAttempts - 1) {
|
|
132
|
+
lastError = new CadreenError(0, "network_error", "network", error.message);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
throw new CadreenError(0, "network_error", "network", error.message);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
throw lastError || new CadreenError(0, "network_error", "network", "Request failed after retries");
|
|
139
|
+
}
|
|
140
|
+
async get(path, params) {
|
|
141
|
+
const qs = params ? buildQueryString(params) : "";
|
|
142
|
+
return this.request("GET", `${path}${qs}`);
|
|
143
|
+
}
|
|
144
|
+
async post(path, body, options) {
|
|
145
|
+
return this.request("POST", path, body, options);
|
|
146
|
+
}
|
|
147
|
+
async put(path, body, options) {
|
|
148
|
+
return this.request("PUT", path, body, options);
|
|
149
|
+
}
|
|
150
|
+
async delete(path) {
|
|
151
|
+
return this.request("DELETE", path);
|
|
152
|
+
}
|
|
153
|
+
async *stream(path) {
|
|
154
|
+
const url = `${this.baseUrl}${path}`;
|
|
155
|
+
const headers = {
|
|
156
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
157
|
+
Accept: "text/event-stream",
|
|
158
|
+
};
|
|
159
|
+
const response = await fetch(url, {
|
|
160
|
+
method: "GET",
|
|
161
|
+
headers,
|
|
162
|
+
});
|
|
163
|
+
if (!response.ok) {
|
|
164
|
+
let errorBody = null;
|
|
165
|
+
try {
|
|
166
|
+
errorBody = await response.json();
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// not JSON
|
|
170
|
+
}
|
|
171
|
+
throw new CadreenError(response.status, errorBody?.error?.code || "unknown", errorBody?.error?.type || "error", errorBody?.error?.message || response.statusText, errorBody?.error?.details, errorBody?.intelligence);
|
|
172
|
+
}
|
|
173
|
+
const reader = response.body?.getReader();
|
|
174
|
+
if (!reader) {
|
|
175
|
+
throw new CadreenError(0, "stream_error", "network", "Response body is not readable");
|
|
176
|
+
}
|
|
177
|
+
const decoder = new TextDecoder();
|
|
178
|
+
let buffer = "";
|
|
179
|
+
let currentEvent = "message";
|
|
180
|
+
while (true) {
|
|
181
|
+
const { done, value } = await reader.read();
|
|
182
|
+
if (done)
|
|
183
|
+
break;
|
|
184
|
+
buffer += decoder.decode(value, { stream: true });
|
|
185
|
+
const lines = buffer.split("\n");
|
|
186
|
+
buffer = lines.pop() || "";
|
|
187
|
+
for (const line of lines) {
|
|
188
|
+
const parsed = parseSSELine(line);
|
|
189
|
+
if (parsed.event) {
|
|
190
|
+
currentEvent = parsed.event;
|
|
191
|
+
}
|
|
192
|
+
if (parsed.data) {
|
|
193
|
+
try {
|
|
194
|
+
const data = JSON.parse(parsed.data);
|
|
195
|
+
yield { type: currentEvent, data };
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
yield { type: currentEvent, data: { raw: parsed.data } };
|
|
199
|
+
}
|
|
200
|
+
currentEvent = "message";
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { IntentResource } from "./resources/intent";
|
|
2
|
+
import { MemoryResource } from "./resources/memory";
|
|
3
|
+
import { PoliciesResource } from "./resources/policies";
|
|
4
|
+
import { ConnectionsResource } from "./resources/connections";
|
|
5
|
+
import { TracesResource } from "./resources/traces";
|
|
6
|
+
import { ExecutionsResource } from "./resources/executions";
|
|
7
|
+
import { GuardrailsResource } from "./resources/guardrails";
|
|
8
|
+
import { SkillsResource } from "./resources/skills";
|
|
9
|
+
import { FailuresResource } from "./resources/failures";
|
|
10
|
+
import type { CadreenConfig, IntentRequest, IntentResult, IntentContext, RememberRequest, CreateMemoryResponse, SearchMemoryRequest, SearchMemoryResponse, ConnectResult, SetupRequest, SetupResult } from "./types";
|
|
11
|
+
export { CadreenError } from "./client";
|
|
12
|
+
export { requiresHuman, handoffReason, explainTrace, redactTrace, redactMessages, redactResult } from "./intelligence_helpers";
|
|
13
|
+
export { intentStatus } from "./types";
|
|
14
|
+
export type { RedactOptions } from "./intelligence_helpers";
|
|
15
|
+
export type { TelemetryProvider, TelemetrySpan, TelemetryMeter } from "./telemetry";
|
|
16
|
+
export { OpenTelemetryAdapter, NoOpProvider, NoOpSpan, NoOpMeter } from "./telemetry";
|
|
17
|
+
export declare class Cadreen {
|
|
18
|
+
readonly intent: IntentResource;
|
|
19
|
+
readonly memory: MemoryResource;
|
|
20
|
+
readonly policies: PoliciesResource;
|
|
21
|
+
readonly connections: ConnectionsResource;
|
|
22
|
+
readonly traces: TracesResource;
|
|
23
|
+
readonly executions: ExecutionsResource;
|
|
24
|
+
readonly guardrails: GuardrailsResource;
|
|
25
|
+
readonly skills: SkillsResource;
|
|
26
|
+
readonly failures: FailuresResource;
|
|
27
|
+
private readonly client;
|
|
28
|
+
constructor(config: CadreenConfig);
|
|
29
|
+
invoke(request: IntentRequest): Promise<IntentResult>;
|
|
30
|
+
ask(prompt: string, options?: {
|
|
31
|
+
conversation_id?: string;
|
|
32
|
+
context?: IntentContext;
|
|
33
|
+
stream?: boolean;
|
|
34
|
+
}): Promise<IntentResult>;
|
|
35
|
+
act(prompt: string, options?: {
|
|
36
|
+
conversation_id?: string;
|
|
37
|
+
context?: IntentContext;
|
|
38
|
+
stream?: boolean;
|
|
39
|
+
}): Promise<IntentResult>;
|
|
40
|
+
remember(request: RememberRequest): Promise<CreateMemoryResponse>;
|
|
41
|
+
context(request: SearchMemoryRequest): Promise<SearchMemoryResponse>;
|
|
42
|
+
connect(capability: string): Promise<ConnectResult>;
|
|
43
|
+
setup(request: SetupRequest): Promise<SetupResult>;
|
|
44
|
+
}
|
|
45
|
+
export type { CadreenConfig, HealthStatus, ConnectorType, CapabilitySource, TransportType, EscalationStatus, CredentialType, AtomScope, AtomType, ErrorCategory, RecoveryStrategyType, StackItemSource, StackItemStatus, GovernanceDecisionType, RecoveryStatus, IntentMode, Pagination, Pathway, ConnectionGroup, ListConnectionsResponse, AtomContent, Atom, CreateMemoryResponse, SearchMemoryResponse, Policy, PolicyBundle, GovernanceDecision, EvaluatePolicyResponse, CreatePolicyResponse, ConfirmPolicyResponse, Escalation, ListEscalationsResponse, CredentialMetadata, ListCredentialsResponse, CapabilityMatch, ListCapabilitiesResponse, ListPoliciesResponse, Gap, Outcome, Assessment, PolicyRecommendation, StackItem, StackBreakdown, CapabilityTrace, ReasoningTrace, MemoryTrace, GovernanceTrace, HumilityTrace, ProcessTrace, IntelligenceMeta, IntelligenceTraceEntry, ListIntelligenceResponse, IntelligenceStats, IntentMessage, IntentContext, IntentRequest, ResponseMessage, ResponseExecution, IntentResult, IntentStatus, RegisterOpenAPIRequest, RegisterOpenAPIResponse, RegisterMCPRequest, RegisterMCPResponse, InstallComposioRequest, SearchMemoryRequest, RememberRequest, CreatePolicyRequest, EvaluatePolicyRequest, ExecutionEvent, ExecutionStatus, TraceExplain, RequestOptions, NextAction, IntelligenceStage, FieldStability, ClarificationQuestion, ConnectResult, ConnectResultType, ConnectPrebuiltDetail, ConnectSchemaRequiredDetail, ConnectManualDetail, ConnectPathway, ConnectUnknownDetail, SetupRequest, SetupResult, SetupConnectionResult, SetupCredentialResult, SetupMemoryResult, SetupPolicyResult, } from "./types";
|
|
46
|
+
export { GuardrailsResource } from "./resources/guardrails";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { HttpClient } from "./client";
|
|
2
|
+
import { IntentResource } from "./resources/intent";
|
|
3
|
+
import { MemoryResource } from "./resources/memory";
|
|
4
|
+
import { PoliciesResource } from "./resources/policies";
|
|
5
|
+
import { ConnectionsResource } from "./resources/connections";
|
|
6
|
+
import { TracesResource } from "./resources/traces";
|
|
7
|
+
import { ExecutionsResource } from "./resources/executions";
|
|
8
|
+
import { GuardrailsResource } from "./resources/guardrails";
|
|
9
|
+
import { SkillsResource } from "./resources/skills";
|
|
10
|
+
import { FailuresResource } from "./resources/failures";
|
|
11
|
+
export { CadreenError } from "./client";
|
|
12
|
+
export { requiresHuman, handoffReason, explainTrace, redactTrace, redactMessages, redactResult } from "./intelligence_helpers";
|
|
13
|
+
export { intentStatus } from "./types";
|
|
14
|
+
export { OpenTelemetryAdapter, NoOpProvider, NoOpSpan, NoOpMeter } from "./telemetry";
|
|
15
|
+
export class Cadreen {
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.client = new HttpClient(config);
|
|
18
|
+
this.intent = new IntentResource(this.client);
|
|
19
|
+
this.memory = new MemoryResource(this.client);
|
|
20
|
+
this.policies = new PoliciesResource(this.client);
|
|
21
|
+
this.connections = new ConnectionsResource(this.client);
|
|
22
|
+
this.traces = new TracesResource(this.client);
|
|
23
|
+
this.executions = new ExecutionsResource(this.client);
|
|
24
|
+
this.guardrails = new GuardrailsResource(this.policies);
|
|
25
|
+
this.skills = new SkillsResource(this.intent, this.memory, this.connections);
|
|
26
|
+
this.failures = new FailuresResource(this.traces);
|
|
27
|
+
}
|
|
28
|
+
async invoke(request) {
|
|
29
|
+
return this.intent.invoke(request);
|
|
30
|
+
}
|
|
31
|
+
async ask(prompt, options) {
|
|
32
|
+
return this.intent.invoke({
|
|
33
|
+
messages: [{ role: "user", content: prompt }],
|
|
34
|
+
mode: "chat",
|
|
35
|
+
conversation_id: options?.conversation_id,
|
|
36
|
+
context: options?.context,
|
|
37
|
+
stream: options?.stream,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async act(prompt, options) {
|
|
41
|
+
return this.intent.invoke({
|
|
42
|
+
messages: [{ role: "user", content: prompt }],
|
|
43
|
+
mode: "execution",
|
|
44
|
+
conversation_id: options?.conversation_id,
|
|
45
|
+
context: options?.context,
|
|
46
|
+
stream: options?.stream,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async remember(request) {
|
|
50
|
+
return this.memory.remember(request);
|
|
51
|
+
}
|
|
52
|
+
async context(request) {
|
|
53
|
+
return this.memory.search(request);
|
|
54
|
+
}
|
|
55
|
+
async connect(capability) {
|
|
56
|
+
return this.connections.connect(capability);
|
|
57
|
+
}
|
|
58
|
+
async setup(request) {
|
|
59
|
+
return this.client.post("/api/v1/cadreen/setup", request);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export { GuardrailsResource } from "./resources/guardrails";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IntelligenceMeta, IntentResult, IntentMessage } from "./types";
|
|
2
|
+
export declare function requiresHuman(intel: IntelligenceMeta): boolean;
|
|
3
|
+
export declare function handoffReason(intel: IntelligenceMeta): string | null;
|
|
4
|
+
export declare function explainTrace(intel: IntelligenceMeta): string;
|
|
5
|
+
export interface RedactOptions {
|
|
6
|
+
preserveUUIDs?: boolean;
|
|
7
|
+
keysToRedact?: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function redactTrace(intel: IntelligenceMeta, options?: RedactOptions): IntelligenceMeta;
|
|
10
|
+
export declare function redactMessages(messages: IntentMessage[], options?: RedactOptions): IntentMessage[];
|
|
11
|
+
export declare function redactResult(result: IntentResult, options?: RedactOptions): IntentResult;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export function requiresHuman(intel) {
|
|
2
|
+
if (intel.governance.decision === "blocked" && (intel.humility.blocking ?? 0) > 0) {
|
|
3
|
+
return true;
|
|
4
|
+
}
|
|
5
|
+
if (intel.stages) {
|
|
6
|
+
for (const stage of intel.stages) {
|
|
7
|
+
if ((stage.name === "escalation" || stage.name === "human_handoff") && stage.status !== "skipped") {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
export function handoffReason(intel) {
|
|
15
|
+
if (intel.stages) {
|
|
16
|
+
for (const stage of intel.stages) {
|
|
17
|
+
if ((stage.name === "escalation" || stage.name === "human_handoff") && stage.status !== "skipped") {
|
|
18
|
+
return stage.detail ?? null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (intel.next_action?.reason) {
|
|
23
|
+
return intel.next_action.reason;
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
export function explainTrace(intel) {
|
|
28
|
+
const parts = [];
|
|
29
|
+
if (intel.summary) {
|
|
30
|
+
parts.push(intel.summary);
|
|
31
|
+
}
|
|
32
|
+
if (intel.stages && intel.stages.length > 0) {
|
|
33
|
+
const stageParts = intel.stages.map((s) => {
|
|
34
|
+
let line = `${s.name}: ${s.status}`;
|
|
35
|
+
if (s.detail) {
|
|
36
|
+
line += ` — ${s.detail}`;
|
|
37
|
+
}
|
|
38
|
+
return line;
|
|
39
|
+
});
|
|
40
|
+
parts.push(stageParts.join("; "));
|
|
41
|
+
}
|
|
42
|
+
if (requiresHuman(intel)) {
|
|
43
|
+
parts.push("Requires human intervention");
|
|
44
|
+
}
|
|
45
|
+
return parts.length > 0 ? parts.join("\n") : "No intelligence trace available";
|
|
46
|
+
}
|
|
47
|
+
const EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
|
|
48
|
+
const PHONE_RE = /(?:\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}/g;
|
|
49
|
+
const UUID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi;
|
|
50
|
+
const API_KEY_RE = /sk_[a-zA-Z]+_[a-zA-Z0-9]{8,}/g;
|
|
51
|
+
const IP_RE = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g;
|
|
52
|
+
function redactString(text, options) {
|
|
53
|
+
let result = text;
|
|
54
|
+
result = result.replace(EMAIL_RE, "[email]");
|
|
55
|
+
result = result.replace(PHONE_RE, "[phone]");
|
|
56
|
+
result = result.replace(API_KEY_RE, "[api_key]");
|
|
57
|
+
result = result.replace(IP_RE, "[ip]");
|
|
58
|
+
if (!options?.preserveUUIDs) {
|
|
59
|
+
result = result.replace(UUID_RE, "[id]");
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
function redactValue(value, options) {
|
|
64
|
+
if (typeof value === "string") {
|
|
65
|
+
return redactString(value, options);
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(value)) {
|
|
68
|
+
return value.map((v) => redactValue(v, options));
|
|
69
|
+
}
|
|
70
|
+
if (value && typeof value === "object") {
|
|
71
|
+
const result = {};
|
|
72
|
+
for (const [key, val] of Object.entries(value)) {
|
|
73
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const keysToRedact = options?.keysToRedact ?? ["content", "message", "text", "body", "email", "phone", "address", "name"];
|
|
77
|
+
if (keysToRedact.includes(key.toLowerCase()) && typeof val === "string") {
|
|
78
|
+
result[key] = redactString(val, options);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
result[key] = redactValue(val, options);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
export function redactTrace(intel, options) {
|
|
89
|
+
return redactValue(intel, options);
|
|
90
|
+
}
|
|
91
|
+
export function redactMessages(messages, options) {
|
|
92
|
+
return messages.map((msg) => ({
|
|
93
|
+
role: msg.role,
|
|
94
|
+
content: redactString(msg.content, options),
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
export function redactResult(result, options) {
|
|
98
|
+
const redacted = { ...result };
|
|
99
|
+
if ("intelligence" in redacted && redacted.intelligence) {
|
|
100
|
+
redacted.intelligence = redactTrace(redacted.intelligence, options);
|
|
101
|
+
}
|
|
102
|
+
if ("message" in redacted && redacted.message && typeof redacted.message === "object" && "content" in redacted.message) {
|
|
103
|
+
const msg = redacted.message;
|
|
104
|
+
redacted.message = { ...msg, content: redactString(msg.content, options) };
|
|
105
|
+
}
|
|
106
|
+
return redacted;
|
|
107
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RegisterOpenAPIRequest, RegisterOpenAPIResponse, RegisterMCPRequest, RegisterMCPResponse, ListConnectionsResponse, InstallComposioRequest, ConnectResult } from "../types";
|
|
2
|
+
import { HttpClient } from "../client";
|
|
3
|
+
export declare class ConnectionsResource {
|
|
4
|
+
private client;
|
|
5
|
+
constructor(client: HttpClient);
|
|
6
|
+
connect(capability: string): Promise<ConnectResult>;
|
|
7
|
+
registerOpenAPI(request: RegisterOpenAPIRequest): Promise<RegisterOpenAPIResponse>;
|
|
8
|
+
registerMCP(request: RegisterMCPRequest): Promise<RegisterMCPResponse>;
|
|
9
|
+
installComposio(request: InstallComposioRequest): Promise<Record<string, unknown>>;
|
|
10
|
+
searchComposio(query: string): Promise<Record<string, unknown>>;
|
|
11
|
+
composioStatus(toolkit?: string, userId?: string): Promise<Record<string, unknown>>;
|
|
12
|
+
list(): Promise<ListConnectionsResponse>;
|
|
13
|
+
delete(id: string): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class ConnectionsResource {
|
|
2
|
+
constructor(client) {
|
|
3
|
+
this.client = client;
|
|
4
|
+
}
|
|
5
|
+
async connect(capability) {
|
|
6
|
+
return this.client.post("/api/v1/cadreen/connections", { capability });
|
|
7
|
+
}
|
|
8
|
+
async registerOpenAPI(request) {
|
|
9
|
+
return this.client.post("/api/v1/cadreen/connections/openapi", request);
|
|
10
|
+
}
|
|
11
|
+
async registerMCP(request) {
|
|
12
|
+
return this.client.post("/api/v1/cadreen/connections/mcp", request);
|
|
13
|
+
}
|
|
14
|
+
async installComposio(request) {
|
|
15
|
+
return this.client.post("/api/v1/cadreen/connections/composio/install", {
|
|
16
|
+
toolkit: request.toolkit,
|
|
17
|
+
user_id: request.user_id,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
async searchComposio(query) {
|
|
21
|
+
return this.client.post("/api/v1/cadreen/connections/composio/search", { query });
|
|
22
|
+
}
|
|
23
|
+
async composioStatus(toolkit, userId) {
|
|
24
|
+
const params = {};
|
|
25
|
+
if (toolkit)
|
|
26
|
+
params.toolkit = toolkit;
|
|
27
|
+
if (userId)
|
|
28
|
+
params.user_id = userId;
|
|
29
|
+
return this.client.get("/api/v1/cadreen/connections/composio/status", params);
|
|
30
|
+
}
|
|
31
|
+
async list() {
|
|
32
|
+
return this.client.get("/api/v1/cadreen/connections");
|
|
33
|
+
}
|
|
34
|
+
async delete(id) {
|
|
35
|
+
return this.client.delete(`/api/v1/cadreen/connections/${encodeURIComponent(id)}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ExecutionEvent, ExecutionStatus } from "../types";
|
|
2
|
+
import { HttpClient } from "../client";
|
|
3
|
+
export declare class ExecutionsResource {
|
|
4
|
+
private client;
|
|
5
|
+
constructor(client: HttpClient);
|
|
6
|
+
stream(executionId: string): AsyncGenerator<ExecutionEvent>;
|
|
7
|
+
getStatus(executionId: string): Promise<ExecutionStatus>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class ExecutionsResource {
|
|
2
|
+
constructor(client) {
|
|
3
|
+
this.client = client;
|
|
4
|
+
}
|
|
5
|
+
async *stream(executionId) {
|
|
6
|
+
const path = `/api/v1/cadreen/executions/${encodeURIComponent(executionId)}/stream`;
|
|
7
|
+
for await (const event of this.client.stream(path)) {
|
|
8
|
+
yield {
|
|
9
|
+
type: event.type,
|
|
10
|
+
data: event.data,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async getStatus(executionId) {
|
|
15
|
+
return this.client.get(`/api/v1/cadreen/executions/${encodeURIComponent(executionId)}`);
|
|
16
|
+
}
|
|
17
|
+
}
|