@genbounty/ailp 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 +193 -0
- package/dist/client.d.ts +21 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +72 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +16 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +37 -0
- package/dist/react.js.map +1 -0
- package/dist/types.d.ts +67 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/wrap.d.ts +86 -0
- package/dist/wrap.d.ts.map +1 -0
- package/dist/wrap.js +117 -0
- package/dist/wrap.js.map +1 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# ailp
|
|
2
|
+
|
|
3
|
+
TypeScript client for the [AILP (AI Log Protocol)](../README.md) LLM compliance risk assessment API.
|
|
4
|
+
|
|
5
|
+
Works in Node.js, browsers, and React — uses native `fetch`, no runtime dependencies.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install ailp
|
|
11
|
+
# peer dep only needed for React hook:
|
|
12
|
+
npm install react
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { AilpClient } from "ailp";
|
|
19
|
+
|
|
20
|
+
const client = new AilpClient({ baseUrl: "http://localhost:8000" });
|
|
21
|
+
|
|
22
|
+
const result = await client.assess({
|
|
23
|
+
timestamp: new Date().toISOString(),
|
|
24
|
+
function: "chat",
|
|
25
|
+
model: "gpt-4o-mini",
|
|
26
|
+
input: {
|
|
27
|
+
messages: [{ role: "user", content: "hello how are you" }],
|
|
28
|
+
endpoint: "/api/chat",
|
|
29
|
+
},
|
|
30
|
+
output: "Hello! I'm here to help.",
|
|
31
|
+
promptTokens: 11,
|
|
32
|
+
completionTokens: 14,
|
|
33
|
+
totalTokens: 25,
|
|
34
|
+
responseTime: 830,
|
|
35
|
+
endpoint: "/api/chat",
|
|
36
|
+
status: "success",
|
|
37
|
+
genbounty: {
|
|
38
|
+
apiKey: "your-genbounty-key",
|
|
39
|
+
programId: "your-program-id",
|
|
40
|
+
frameworks: ["eu-ai-act", "owasp-llm"],
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
console.log(result.risk_level); // "compliant"
|
|
45
|
+
console.log(result.frameworks); // ["EU AI Act", "OWASP LLM & Agent"]
|
|
46
|
+
console.log(result.experts); // [{ framework, risk_level, reasoning }, ...]
|
|
47
|
+
console.log(result.judge_reasoning); // "The interaction..."
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## OpenAI wrapper (auto-capture)
|
|
53
|
+
|
|
54
|
+
Wrap any OpenAI-compatible `chat.completions.create` call. Timing, model, and token
|
|
55
|
+
counts are captured automatically. Assessment runs **fire-and-forget** in the
|
|
56
|
+
background — your LLM call is never blocked or delayed.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import OpenAI from "openai";
|
|
60
|
+
import { AilpClient, wrapOpenAI } from "ailp";
|
|
61
|
+
|
|
62
|
+
const openai = new OpenAI();
|
|
63
|
+
const ailp = new AilpClient({ baseUrl: "http://localhost:8000" });
|
|
64
|
+
|
|
65
|
+
const messages = [{ role: "user" as const, content: "Explain quantum entanglement." }];
|
|
66
|
+
|
|
67
|
+
const response = await wrapOpenAI(
|
|
68
|
+
(params) => openai.chat.completions.create(params),
|
|
69
|
+
{ model: "gpt-4o-mini", messages },
|
|
70
|
+
{
|
|
71
|
+
client: ailp,
|
|
72
|
+
frameworks: ["eu-ai-act", "owasp-llm"],
|
|
73
|
+
functionName: "chat",
|
|
74
|
+
endpoint: "/api/chat",
|
|
75
|
+
genbounty: {
|
|
76
|
+
apiKey: "your-genbounty-key",
|
|
77
|
+
programId: "your-program-id",
|
|
78
|
+
},
|
|
79
|
+
onAssess: (result, entry) => {
|
|
80
|
+
console.log("Risk:", result.risk_level);
|
|
81
|
+
},
|
|
82
|
+
onAssessError: (err) => {
|
|
83
|
+
console.warn("AILP assess failed:", err);
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
console.log(response.choices[0].message.content);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Generic LLM wrapper
|
|
94
|
+
|
|
95
|
+
Use `wrapLlmCall` for any async LLM function (Anthropic, Gemini, custom, etc.).
|
|
96
|
+
You supply an `extractOutput` mapper to pull the text and token counts from
|
|
97
|
+
whatever response shape your LLM returns.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { wrapLlmCall } from "ailp";
|
|
101
|
+
|
|
102
|
+
const response = await wrapLlmCall(
|
|
103
|
+
(params) => anthropic.messages.create(params),
|
|
104
|
+
{ model: "claude-3-haiku-20240307", max_tokens: 256, messages },
|
|
105
|
+
{
|
|
106
|
+
client: ailp,
|
|
107
|
+
frameworks: ["nist-ai-rmf"],
|
|
108
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
109
|
+
functionName: "chat",
|
|
110
|
+
extractOutput: (res) => ({
|
|
111
|
+
output: res.content[0]?.text ?? "",
|
|
112
|
+
model: res.model,
|
|
113
|
+
promptTokens: res.usage?.input_tokens,
|
|
114
|
+
completionTokens: res.usage?.output_tokens,
|
|
115
|
+
totalTokens: (res.usage?.input_tokens ?? 0) + (res.usage?.output_tokens ?? 0),
|
|
116
|
+
}),
|
|
117
|
+
},
|
|
118
|
+
);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## React hook
|
|
124
|
+
|
|
125
|
+
Import from `ailp-client/react` to keep React out of the core bundle.
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
import { AilpClient } from "ailp";
|
|
129
|
+
import { useAssess } from "ailp/react";
|
|
130
|
+
|
|
131
|
+
const client = new AilpClient({ baseUrl: "http://localhost:8000" });
|
|
132
|
+
|
|
133
|
+
function ChatWidget() {
|
|
134
|
+
const { assess, result, loading, error, reset } = useAssess(client);
|
|
135
|
+
|
|
136
|
+
async function handleSend(userMessage: string, llmOutput: string) {
|
|
137
|
+
await assess({
|
|
138
|
+
timestamp: new Date().toISOString(),
|
|
139
|
+
function: "chat",
|
|
140
|
+
input: { messages: [{ role: "user", content: userMessage }] },
|
|
141
|
+
output: llmOutput,
|
|
142
|
+
status: "success",
|
|
143
|
+
genbounty: { frameworks: ["eu-ai-act"] },
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<div>
|
|
149
|
+
{loading && <p>Assessing…</p>}
|
|
150
|
+
{error && <p>Error: {error.message}</p>}
|
|
151
|
+
{result && (
|
|
152
|
+
<p>
|
|
153
|
+
Risk: <strong>{result.risk_level}</strong> — {result.judge_reasoning}
|
|
154
|
+
</p>
|
|
155
|
+
)}
|
|
156
|
+
<button onClick={() => handleSend("hello", "Hi there!")}>Send</button>
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Framework slugs
|
|
165
|
+
|
|
166
|
+
Pass any of these as `frameworks` (hyphen or underscore):
|
|
167
|
+
|
|
168
|
+
| Slug | Framework |
|
|
169
|
+
|------|-----------|
|
|
170
|
+
| `eu_ai_act` / `eu-ai-act` | EU AI Act |
|
|
171
|
+
| `oecd` | OECD AI Principles (default) |
|
|
172
|
+
| `owasp_llm` / `owasp-llm` | OWASP LLM & Agent |
|
|
173
|
+
| `nist_ai_rmf` / `nist-ai-rmf` | NIST AI RMF |
|
|
174
|
+
| `mitre_attack` / `mitre-attack` | MITRE ATT&CK |
|
|
175
|
+
| `pld` | EU PLD (AI) |
|
|
176
|
+
| `fria_core` / `fria-core` | FRIA Core |
|
|
177
|
+
| `fria_extended` / `fria-extended` | FRIA Extended |
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Risk levels
|
|
182
|
+
|
|
183
|
+
`critical` › `high` › `medium` › `low` › `informational` › `compliant` › `indeterminate`
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Build
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
npm install
|
|
191
|
+
npm run build # outputs to dist/
|
|
192
|
+
npm run dev # watch mode
|
|
193
|
+
```
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AilpAssessResponse, AilpClientOptions, AilpLogEntry } from "./types.js";
|
|
2
|
+
export declare class AilpClient {
|
|
3
|
+
private baseUrl;
|
|
4
|
+
private timeoutMs;
|
|
5
|
+
private headers;
|
|
6
|
+
constructor(options: AilpClientOptions);
|
|
7
|
+
/** Check server liveness. Returns true if the server responded with status "ok". */
|
|
8
|
+
health(): Promise<boolean>;
|
|
9
|
+
/**
|
|
10
|
+
* Submit an LLM log entry for compliance risk assessment.
|
|
11
|
+
* Throws an AilpError on non-2xx responses or network failures.
|
|
12
|
+
*/
|
|
13
|
+
assess(entry: AilpLogEntry): Promise<AilpAssessResponse>;
|
|
14
|
+
private _fetch;
|
|
15
|
+
}
|
|
16
|
+
export declare class AilpError extends Error {
|
|
17
|
+
readonly status: number;
|
|
18
|
+
readonly body: unknown;
|
|
19
|
+
constructor(message: string, status: number, body: unknown);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEtF,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,OAAO,CAAyB;gBAE5B,OAAO,EAAE,iBAAiB;IAStC,oFAAoF;IAC9E,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAUhC;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAmBhD,MAAM;CAuBrB;AAED,qBAAa,SAAU,SAAQ,KAAK;aAGhB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,OAAO;gBAF7B,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO;CAKhC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export class AilpClient {
|
|
2
|
+
constructor(options) {
|
|
3
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
4
|
+
this.timeoutMs = options.timeoutMs;
|
|
5
|
+
this.headers = {
|
|
6
|
+
"Content-Type": "application/json",
|
|
7
|
+
...options.headers,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** Check server liveness. Returns true if the server responded with status "ok". */
|
|
11
|
+
async health() {
|
|
12
|
+
try {
|
|
13
|
+
const res = await this._fetch("/health");
|
|
14
|
+
const data = (await res.json());
|
|
15
|
+
return data.status === "ok";
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Submit an LLM log entry for compliance risk assessment.
|
|
23
|
+
* Throws an AilpError on non-2xx responses or network failures.
|
|
24
|
+
*/
|
|
25
|
+
async assess(entry) {
|
|
26
|
+
const res = await this._fetch("/assess", {
|
|
27
|
+
method: "POST",
|
|
28
|
+
body: JSON.stringify(entry),
|
|
29
|
+
});
|
|
30
|
+
const data = await res.json();
|
|
31
|
+
if (!res.ok) {
|
|
32
|
+
const detail = typeof data === "object" && data !== null && "detail" in data
|
|
33
|
+
? String(data.detail)
|
|
34
|
+
: res.statusText;
|
|
35
|
+
throw new AilpError(`AILP assess failed (HTTP ${res.status}): ${detail}`, res.status, data);
|
|
36
|
+
}
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
async _fetch(path, init = {}) {
|
|
40
|
+
const url = `${this.baseUrl}${path}`;
|
|
41
|
+
const controller = this.timeoutMs != null ? new AbortController() : null;
|
|
42
|
+
const timer = controller != null
|
|
43
|
+
? setTimeout(() => controller.abort(), this.timeoutMs)
|
|
44
|
+
: null;
|
|
45
|
+
try {
|
|
46
|
+
return await fetch(url, {
|
|
47
|
+
...init,
|
|
48
|
+
headers: { ...this.headers, ...init.headers },
|
|
49
|
+
signal: controller?.signal,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
54
|
+
throw new AilpError(`Request to ${path} timed out after ${this.timeoutMs}ms`, 0, null);
|
|
55
|
+
}
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
if (timer != null)
|
|
60
|
+
clearTimeout(timer);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export class AilpError extends Error {
|
|
65
|
+
constructor(message, status, body) {
|
|
66
|
+
super(message);
|
|
67
|
+
this.status = status;
|
|
68
|
+
this.body = body;
|
|
69
|
+
this.name = "AilpError";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { AilpClient, AilpError } from "./client.js";
|
|
2
|
+
export { wrapLlmCall, wrapOpenAI } from "./wrap.js";
|
|
3
|
+
export type { AilpAssessResponse, AilpClientOptions, AilpExpertResult, AilpFrameworkSlug, AilpGenBounty, AilpLogEntry, AilpMessage, AilpRiskLevel, } from "./types.js";
|
|
4
|
+
export type { LlmWrapOptions, OpenAIWrapOptions, WrapOptions } from "./wrap.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACpD,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AilpClient } from "./client.js";
|
|
2
|
+
import type { AilpAssessResponse, AilpLogEntry } from "./types.js";
|
|
3
|
+
export interface UseAssessState {
|
|
4
|
+
/** Last successful response, or null if not yet assessed. */
|
|
5
|
+
result: AilpAssessResponse | null;
|
|
6
|
+
/** True while an assess request is in-flight. */
|
|
7
|
+
loading: boolean;
|
|
8
|
+
/** Last error thrown by assess, or null. */
|
|
9
|
+
error: Error | null;
|
|
10
|
+
/** Submit a log entry for assessment. Returns the response, or null on error. */
|
|
11
|
+
assess: (entry: AilpLogEntry) => Promise<AilpAssessResponse | null>;
|
|
12
|
+
/** Clear result and error back to initial state. */
|
|
13
|
+
reset: () => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function useAssess(client: AilpClient): UseAssessState;
|
|
16
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAClC,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,4CAA4C;IAC5C,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,iFAAiF;IACjF,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IACpE,oDAAoD;IACpD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CA8B5D"}
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for AILP assess.
|
|
3
|
+
* Import from "ailp/react" to keep React out of the main bundle.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* import { useAssess } from "ailp/react";
|
|
7
|
+
* const { assess, result, loading, error } = useAssess(client);
|
|
8
|
+
*/
|
|
9
|
+
import { useCallback, useState } from "react";
|
|
10
|
+
export function useAssess(client) {
|
|
11
|
+
const [result, setResult] = useState(null);
|
|
12
|
+
const [loading, setLoading] = useState(false);
|
|
13
|
+
const [error, setError] = useState(null);
|
|
14
|
+
const assess = useCallback(async (entry) => {
|
|
15
|
+
setLoading(true);
|
|
16
|
+
setError(null);
|
|
17
|
+
try {
|
|
18
|
+
const res = await client.assess(entry);
|
|
19
|
+
setResult(res);
|
|
20
|
+
return res;
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
24
|
+
setError(e);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
setLoading(false);
|
|
29
|
+
}
|
|
30
|
+
}, [client]);
|
|
31
|
+
const reset = useCallback(() => {
|
|
32
|
+
setResult(null);
|
|
33
|
+
setError(null);
|
|
34
|
+
}, []);
|
|
35
|
+
return { result, loading, error, assess, reset };
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAiB9C,MAAM,UAAU,SAAS,CAAC,MAAkB;IAC1C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAA4B,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,MAAM,GAAG,WAAW,CACxB,KAAK,EAAE,KAAmB,EAAsC,EAAE;QAChE,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvC,SAAS,CAAC,GAAG,CAAC,CAAC;YACf,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9D,QAAQ,CAAC,CAAC,CAAC,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EACD,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACnD,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export type AilpFrameworkSlug = "eu_ai_act" | "eu-ai-act" | "oecd" | "owasp_llm" | "owasp-llm" | "nist_ai_rmf" | "nist-ai-rmf" | "mitre_attack" | "mitre-attack" | "pld" | "fria_core" | "fria-core" | "fria_extended" | "fria-extended" | (string & {});
|
|
2
|
+
export type AilpRiskLevel = "critical" | "high" | "medium" | "low" | "informational" | "compliant" | "indeterminate";
|
|
3
|
+
export interface AilpMessage {
|
|
4
|
+
role: string;
|
|
5
|
+
content: string;
|
|
6
|
+
}
|
|
7
|
+
export interface AilpGenBounty {
|
|
8
|
+
/** Genbounty API key (returned as "***" in the echoed log). */
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
programId?: string;
|
|
11
|
+
/** One or more framework slugs. First entry wins over top-level framework. */
|
|
12
|
+
frameworks?: AilpFrameworkSlug | AilpFrameworkSlug[];
|
|
13
|
+
}
|
|
14
|
+
export interface AilpLogEntry {
|
|
15
|
+
/** ISO 8601 timestamp of the LLM interaction. */
|
|
16
|
+
timestamp: string;
|
|
17
|
+
/** Name of the calling function / route handler. */
|
|
18
|
+
function?: string;
|
|
19
|
+
/** Model identifier (e.g. "gpt-4o-mini"). */
|
|
20
|
+
model?: string;
|
|
21
|
+
input: {
|
|
22
|
+
messages: AilpMessage[];
|
|
23
|
+
endpoint?: string;
|
|
24
|
+
};
|
|
25
|
+
/** Raw text output from the LLM. */
|
|
26
|
+
output: string;
|
|
27
|
+
promptTokens?: number;
|
|
28
|
+
completionTokens?: number;
|
|
29
|
+
totalTokens?: number;
|
|
30
|
+
/** Total latency in milliseconds. */
|
|
31
|
+
responseTime?: number;
|
|
32
|
+
endpoint?: string;
|
|
33
|
+
/** HTTP or logical status (e.g. "success", "error"). */
|
|
34
|
+
status?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Framework slug(s) to assess against.
|
|
37
|
+
* If omitted, genbounty.frameworks is used; if both omitted, defaults to OECD.
|
|
38
|
+
*/
|
|
39
|
+
framework?: AilpFrameworkSlug | AilpFrameworkSlug[];
|
|
40
|
+
genbounty?: AilpGenBounty;
|
|
41
|
+
}
|
|
42
|
+
export interface AilpExpertResult {
|
|
43
|
+
framework: string;
|
|
44
|
+
risk_level: AilpRiskLevel;
|
|
45
|
+
reasoning: string;
|
|
46
|
+
}
|
|
47
|
+
export interface AilpAssessResponse {
|
|
48
|
+
/** Most severe risk level across all experts (judge's final verdict). */
|
|
49
|
+
risk_level: AilpRiskLevel;
|
|
50
|
+
/** Judge's chain-of-thought synthesis. */
|
|
51
|
+
judge_reasoning: string;
|
|
52
|
+
/** Resolved display names of all frameworks that ran. */
|
|
53
|
+
frameworks: string[];
|
|
54
|
+
/** One entry per framework expert, in the same order as frameworks. */
|
|
55
|
+
experts: AilpExpertResult[];
|
|
56
|
+
/** Echo of the submitted log entry (apiKey redacted). */
|
|
57
|
+
log: AilpLogEntry;
|
|
58
|
+
}
|
|
59
|
+
export interface AilpClientOptions {
|
|
60
|
+
/** Base URL of the AILP server (no trailing slash). */
|
|
61
|
+
baseUrl: string;
|
|
62
|
+
/** Optional request timeout in milliseconds (default: no timeout). */
|
|
63
|
+
timeoutMs?: number;
|
|
64
|
+
/** Extra headers sent with every request. */
|
|
65
|
+
headers?: Record<string, string>;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,iBAAiB,GACzB,WAAW,GAAK,WAAW,GAC3B,MAAM,GACN,WAAW,GAAK,WAAW,GAC3B,aAAa,GAAG,aAAa,GAC7B,cAAc,GAAE,cAAc,GAC9B,KAAK,GACL,WAAW,GAAK,WAAW,GAC3B,eAAe,GAAE,eAAe,GAChC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB,MAAM,MAAM,aAAa,GACrB,UAAU,GACV,MAAM,GACN,QAAQ,GACR,KAAK,GACL,eAAe,GACf,WAAW,GACX,eAAe,CAAC;AAMpB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;CACtD;AAED,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QACL,QAAQ,EAAE,WAAW,EAAE,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IACpD,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,aAAa,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,UAAU,EAAE,aAAa,CAAC;IAC1B,0CAA0C;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,uEAAuE;IACvE,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,yDAAyD;IACzD,GAAG,EAAE,YAAY,CAAC;CACnB;AAMD,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/wrap.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { AilpClient } from "./client.js";
|
|
2
|
+
import type { AilpAssessResponse, AilpFrameworkSlug, AilpGenBounty, AilpLogEntry, AilpMessage } from "./types.js";
|
|
3
|
+
interface OpenAIMessage {
|
|
4
|
+
role: string;
|
|
5
|
+
content: string | null;
|
|
6
|
+
}
|
|
7
|
+
interface OpenAIChoice {
|
|
8
|
+
message: OpenAIMessage;
|
|
9
|
+
finish_reason?: string;
|
|
10
|
+
}
|
|
11
|
+
interface OpenAIUsage {
|
|
12
|
+
prompt_tokens?: number;
|
|
13
|
+
completion_tokens?: number;
|
|
14
|
+
total_tokens?: number;
|
|
15
|
+
}
|
|
16
|
+
interface OpenAIChatResponse {
|
|
17
|
+
id?: string;
|
|
18
|
+
model?: string;
|
|
19
|
+
choices: OpenAIChoice[];
|
|
20
|
+
usage?: OpenAIUsage;
|
|
21
|
+
}
|
|
22
|
+
interface OpenAIChatParams {
|
|
23
|
+
model: string;
|
|
24
|
+
messages: OpenAIMessage[];
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
export interface WrapOptions {
|
|
28
|
+
client: AilpClient;
|
|
29
|
+
/** Framework slug(s) to assess against. */
|
|
30
|
+
frameworks?: AilpFrameworkSlug | AilpFrameworkSlug[];
|
|
31
|
+
/** Optional Genbounty routing block. */
|
|
32
|
+
genbounty?: AilpGenBounty;
|
|
33
|
+
/** Name of the calling function/route (logged as "function" in the entry). */
|
|
34
|
+
functionName?: string;
|
|
35
|
+
/** Endpoint path to record (e.g. "/api/chat"). */
|
|
36
|
+
endpoint?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Called after the assessment completes (fire-and-forget).
|
|
39
|
+
* Errors inside this callback are swallowed.
|
|
40
|
+
*/
|
|
41
|
+
onAssess?: (result: AilpAssessResponse, entry: AilpLogEntry) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Called if the AILP assess call itself throws.
|
|
44
|
+
* Defaults to console.warn so LLM errors are never blocked.
|
|
45
|
+
*/
|
|
46
|
+
onAssessError?: (err: unknown, entry: AilpLogEntry) => void;
|
|
47
|
+
}
|
|
48
|
+
export interface LlmWrapOptions<TResult> extends WrapOptions {
|
|
49
|
+
/**
|
|
50
|
+
* Map the LLM result to the fields AILP needs.
|
|
51
|
+
* Return null/undefined for any field you cannot extract — it will be omitted.
|
|
52
|
+
*/
|
|
53
|
+
extractOutput: (result: TResult) => {
|
|
54
|
+
output: string;
|
|
55
|
+
model?: string;
|
|
56
|
+
promptTokens?: number;
|
|
57
|
+
completionTokens?: number;
|
|
58
|
+
totalTokens?: number;
|
|
59
|
+
};
|
|
60
|
+
/** Input messages to log. */
|
|
61
|
+
messages: AilpMessage[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Generic wrapper: calls any async LLM function, auto-captures timing,
|
|
65
|
+
* and fires an AILP assess in the background. Never blocks or throws on
|
|
66
|
+
* assess failures — your LLM call result is always returned.
|
|
67
|
+
*/
|
|
68
|
+
export declare function wrapLlmCall<TParams, TResult>(fn: (params: TParams) => Promise<TResult>, params: TParams, options: LlmWrapOptions<TResult>): Promise<TResult>;
|
|
69
|
+
export interface OpenAIWrapOptions extends WrapOptions {
|
|
70
|
+
/** The endpoint path to log (default: "/v1/chat/completions"). */
|
|
71
|
+
endpoint?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Drop-in wrapper for `openai.chat.completions.create()` (or any compatible API).
|
|
75
|
+
* Auto-captures timing, model, token usage, and messages from the OpenAI request/response.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* const response = await wrapOpenAI(
|
|
79
|
+
* (p) => openai.chat.completions.create(p),
|
|
80
|
+
* { model: "gpt-4o-mini", messages },
|
|
81
|
+
* { client, frameworks: ["eu-ai-act", "owasp-llm"], genbounty: { apiKey, programId } }
|
|
82
|
+
* );
|
|
83
|
+
*/
|
|
84
|
+
export declare function wrapOpenAI<T extends OpenAIChatParams>(fn: (params: T) => Promise<OpenAIChatResponse>, params: T, options: OpenAIWrapOptions): Promise<OpenAIChatResponse>;
|
|
85
|
+
export {};
|
|
86
|
+
//# sourceMappingURL=wrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../src/wrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMlH,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,aAAa,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,WAAW;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAMD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IACrD,wCAAwC;IACxC,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACrE;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CAC7D;AAMD,MAAM,WAAW,cAAc,CAAC,OAAO,CAAE,SAAQ,WAAW;IAC1D;;;OAGG;IACH,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK;QAClC,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,6BAA6B;IAC7B,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAChD,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,EACzC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC,CAuDlB;AAMD,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,gBAAgB,EACzD,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,kBAAkB,CAAC,EAC9C,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CA0B7B"}
|
package/dist/wrap.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic wrapper: calls any async LLM function, auto-captures timing,
|
|
3
|
+
* and fires an AILP assess in the background. Never blocks or throws on
|
|
4
|
+
* assess failures — your LLM call result is always returned.
|
|
5
|
+
*/
|
|
6
|
+
export async function wrapLlmCall(fn, params, options) {
|
|
7
|
+
const start = Date.now();
|
|
8
|
+
let result;
|
|
9
|
+
let status = "success";
|
|
10
|
+
try {
|
|
11
|
+
result = await fn(params);
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
status = "error";
|
|
15
|
+
_fireAssess({
|
|
16
|
+
timestamp: new Date(start).toISOString(),
|
|
17
|
+
function: options.functionName,
|
|
18
|
+
model: undefined,
|
|
19
|
+
input: { messages: options.messages, endpoint: options.endpoint },
|
|
20
|
+
output: err instanceof Error ? err.message : String(err),
|
|
21
|
+
responseTime: Date.now() - start,
|
|
22
|
+
endpoint: options.endpoint,
|
|
23
|
+
status,
|
|
24
|
+
framework: options.frameworks,
|
|
25
|
+
genbounty: options.genbounty,
|
|
26
|
+
}, options);
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
const responseTime = Date.now() - start;
|
|
30
|
+
let extracted = { output: "" };
|
|
31
|
+
try {
|
|
32
|
+
extracted = options.extractOutput(result);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// extractOutput threw — log what we have
|
|
36
|
+
}
|
|
37
|
+
const entry = {
|
|
38
|
+
timestamp: new Date(start).toISOString(),
|
|
39
|
+
function: options.functionName,
|
|
40
|
+
model: extracted.model,
|
|
41
|
+
input: { messages: options.messages, endpoint: options.endpoint },
|
|
42
|
+
output: extracted.output ?? "",
|
|
43
|
+
promptTokens: extracted.promptTokens,
|
|
44
|
+
completionTokens: extracted.completionTokens,
|
|
45
|
+
totalTokens: extracted.totalTokens,
|
|
46
|
+
responseTime,
|
|
47
|
+
endpoint: options.endpoint,
|
|
48
|
+
status,
|
|
49
|
+
framework: options.frameworks,
|
|
50
|
+
genbounty: options.genbounty,
|
|
51
|
+
};
|
|
52
|
+
_fireAssess(entry, options);
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Drop-in wrapper for `openai.chat.completions.create()` (or any compatible API).
|
|
57
|
+
* Auto-captures timing, model, token usage, and messages from the OpenAI request/response.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const response = await wrapOpenAI(
|
|
61
|
+
* (p) => openai.chat.completions.create(p),
|
|
62
|
+
* { model: "gpt-4o-mini", messages },
|
|
63
|
+
* { client, frameworks: ["eu-ai-act", "owasp-llm"], genbounty: { apiKey, programId } }
|
|
64
|
+
* );
|
|
65
|
+
*/
|
|
66
|
+
export async function wrapOpenAI(fn, params, options) {
|
|
67
|
+
const messages = (params.messages ?? []).map((m) => ({
|
|
68
|
+
role: m.role,
|
|
69
|
+
content: typeof m.content === "string" ? m.content : "",
|
|
70
|
+
}));
|
|
71
|
+
return wrapLlmCall(fn, params, {
|
|
72
|
+
...options,
|
|
73
|
+
endpoint: options.endpoint ?? "/v1/chat/completions",
|
|
74
|
+
messages,
|
|
75
|
+
extractOutput: (res) => {
|
|
76
|
+
const firstChoice = res.choices?.[0];
|
|
77
|
+
const output = (typeof firstChoice?.message?.content === "string"
|
|
78
|
+
? firstChoice.message.content
|
|
79
|
+
: null) ?? "";
|
|
80
|
+
return {
|
|
81
|
+
output,
|
|
82
|
+
model: res.model ?? params.model,
|
|
83
|
+
promptTokens: res.usage?.prompt_tokens,
|
|
84
|
+
completionTokens: res.usage?.completion_tokens,
|
|
85
|
+
totalTokens: res.usage?.total_tokens,
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// -------------------------------------------------------------------------
|
|
91
|
+
// Internal: fire-and-forget assess
|
|
92
|
+
// -------------------------------------------------------------------------
|
|
93
|
+
function _fireAssess(entry, options) {
|
|
94
|
+
const onError = options.onAssessError ??
|
|
95
|
+
((err) => {
|
|
96
|
+
console.warn("[ailp-client] assess error (LLM call unaffected):", err);
|
|
97
|
+
});
|
|
98
|
+
options.client
|
|
99
|
+
.assess(entry)
|
|
100
|
+
.then((result) => {
|
|
101
|
+
try {
|
|
102
|
+
options.onAssess?.(result, entry);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// swallow errors in the callback
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
.catch((err) => {
|
|
109
|
+
try {
|
|
110
|
+
onError(err, entry);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// swallow
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=wrap.js.map
|
package/dist/wrap.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../src/wrap.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@genbounty/ailp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript client for the AILP (AI Log Protocol) LLM compliance risk assessment API.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts"
|
|
10
|
+
},
|
|
11
|
+
"./react": {
|
|
12
|
+
"import": "./dist/react.js",
|
|
13
|
+
"types": "./dist/react.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"dev": "tsc --watch",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"ai",
|
|
29
|
+
"llm",
|
|
30
|
+
"compliance",
|
|
31
|
+
"risk-assessment",
|
|
32
|
+
"logging",
|
|
33
|
+
"openai",
|
|
34
|
+
"eu-ai-act",
|
|
35
|
+
"owasp",
|
|
36
|
+
"nist"
|
|
37
|
+
],
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18.0.0"
|
|
41
|
+
},
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/genbounty/ailp"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/genbounty/ailp",
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"react": ">=18.0.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"react": {
|
|
52
|
+
"optional": true
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/react": "^18.0.0",
|
|
57
|
+
"typescript": "^5.0.0"
|
|
58
|
+
}
|
|
59
|
+
}
|