@buoy-gg/agent-core 7.0.33
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/LICENSE +58 -0
- package/README.md +42 -0
- package/lib/commonjs/blocks/receipts.js +702 -0
- package/lib/commonjs/blocks/receipts.js.map +1 -0
- package/lib/commonjs/blocks/types.js +119 -0
- package/lib/commonjs/blocks/types.js.map +1 -0
- package/lib/commonjs/blocks/uiTool.js +994 -0
- package/lib/commonjs/blocks/uiTool.js.map +1 -0
- package/lib/commonjs/catalog/catalog.g.js +4044 -0
- package/lib/commonjs/catalog/catalog.g.js.map +1 -0
- package/lib/commonjs/catalog/catalog.source.json +4956 -0
- package/lib/commonjs/catalog/snapshotReads.js +256 -0
- package/lib/commonjs/catalog/snapshotReads.js.map +1 -0
- package/lib/commonjs/catalog/toProviderTools.js +107 -0
- package/lib/commonjs/catalog/toProviderTools.js.map +1 -0
- package/lib/commonjs/catalog/validateParams.js +129 -0
- package/lib/commonjs/catalog/validateParams.js.map +1 -0
- package/lib/commonjs/context/buildContextPack.js +141 -0
- package/lib/commonjs/context/buildContextPack.js.map +1 -0
- package/lib/commonjs/effects/ledger.js +229 -0
- package/lib/commonjs/effects/ledger.js.map +1 -0
- package/lib/commonjs/engine/effectFor.js +95 -0
- package/lib/commonjs/engine/effectFor.js.map +1 -0
- package/lib/commonjs/engine/runAgentTurn.js +667 -0
- package/lib/commonjs/engine/runAgentTurn.js.map +1 -0
- package/lib/commonjs/engine/systemPrompt.js +86 -0
- package/lib/commonjs/engine/systemPrompt.js.map +1 -0
- package/lib/commonjs/index.js +288 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/policy/labels.js +303 -0
- package/lib/commonjs/policy/labels.js.map +1 -0
- package/lib/commonjs/policy/policy.js +143 -0
- package/lib/commonjs/policy/policy.js.map +1 -0
- package/lib/commonjs/policy/redact.js +135 -0
- package/lib/commonjs/policy/redact.js.map +1 -0
- package/lib/commonjs/providers/anthropic.js +272 -0
- package/lib/commonjs/providers/anthropic.js.map +1 -0
- package/lib/commonjs/providers/openai.js +193 -0
- package/lib/commonjs/providers/openai.js.map +1 -0
- package/lib/commonjs/providers/sse.js +104 -0
- package/lib/commonjs/providers/sse.js.map +1 -0
- package/lib/commonjs/providers/types.js +6 -0
- package/lib/commonjs/providers/types.js.map +1 -0
- package/lib/commonjs/session.js +173 -0
- package/lib/commonjs/session.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/blocks/receipts.js +696 -0
- package/lib/module/blocks/receipts.js.map +1 -0
- package/lib/module/blocks/types.js +113 -0
- package/lib/module/blocks/types.js.map +1 -0
- package/lib/module/blocks/uiTool.js +987 -0
- package/lib/module/blocks/uiTool.js.map +1 -0
- package/lib/module/catalog/catalog.g.js +4040 -0
- package/lib/module/catalog/catalog.g.js.map +1 -0
- package/lib/module/catalog/catalog.source.json +4956 -0
- package/lib/module/catalog/snapshotReads.js +252 -0
- package/lib/module/catalog/snapshotReads.js.map +1 -0
- package/lib/module/catalog/toProviderTools.js +101 -0
- package/lib/module/catalog/toProviderTools.js.map +1 -0
- package/lib/module/catalog/validateParams.js +124 -0
- package/lib/module/catalog/validateParams.js.map +1 -0
- package/lib/module/context/buildContextPack.js +138 -0
- package/lib/module/context/buildContextPack.js.map +1 -0
- package/lib/module/effects/ledger.js +223 -0
- package/lib/module/effects/ledger.js.map +1 -0
- package/lib/module/engine/effectFor.js +91 -0
- package/lib/module/engine/effectFor.js.map +1 -0
- package/lib/module/engine/runAgentTurn.js +663 -0
- package/lib/module/engine/runAgentTurn.js.map +1 -0
- package/lib/module/engine/systemPrompt.js +82 -0
- package/lib/module/engine/systemPrompt.js.map +1 -0
- package/lib/module/index.js +30 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/policy/labels.js +296 -0
- package/lib/module/policy/labels.js.map +1 -0
- package/lib/module/policy/policy.js +137 -0
- package/lib/module/policy/policy.js.map +1 -0
- package/lib/module/policy/redact.js +128 -0
- package/lib/module/policy/redact.js.map +1 -0
- package/lib/module/providers/anthropic.js +268 -0
- package/lib/module/providers/anthropic.js.map +1 -0
- package/lib/module/providers/openai.js +189 -0
- package/lib/module/providers/openai.js.map +1 -0
- package/lib/module/providers/sse.js +99 -0
- package/lib/module/providers/sse.js.map +1 -0
- package/lib/module/providers/types.js +4 -0
- package/lib/module/providers/types.js.map +1 -0
- package/lib/module/session.js +168 -0
- package/lib/module/session.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/blocks/receipts.d.ts +32 -0
- package/lib/typescript/blocks/receipts.d.ts.map +1 -0
- package/lib/typescript/blocks/types.d.ts +576 -0
- package/lib/typescript/blocks/types.d.ts.map +1 -0
- package/lib/typescript/blocks/uiTool.d.ts +15 -0
- package/lib/typescript/blocks/uiTool.d.ts.map +1 -0
- package/lib/typescript/catalog/catalog.g.d.ts +11 -0
- package/lib/typescript/catalog/catalog.g.d.ts.map +1 -0
- package/lib/typescript/catalog/snapshotReads.d.ts +37 -0
- package/lib/typescript/catalog/snapshotReads.d.ts.map +1 -0
- package/lib/typescript/catalog/toProviderTools.d.ts +52 -0
- package/lib/typescript/catalog/toProviderTools.d.ts.map +1 -0
- package/lib/typescript/catalog/validateParams.d.ts +33 -0
- package/lib/typescript/catalog/validateParams.d.ts.map +1 -0
- package/lib/typescript/context/buildContextPack.d.ts +32 -0
- package/lib/typescript/context/buildContextPack.d.ts.map +1 -0
- package/lib/typescript/effects/ledger.d.ts +119 -0
- package/lib/typescript/effects/ledger.d.ts.map +1 -0
- package/lib/typescript/engine/effectFor.d.ts +21 -0
- package/lib/typescript/engine/effectFor.d.ts.map +1 -0
- package/lib/typescript/engine/runAgentTurn.d.ts +140 -0
- package/lib/typescript/engine/runAgentTurn.d.ts.map +1 -0
- package/lib/typescript/engine/systemPrompt.d.ts +49 -0
- package/lib/typescript/engine/systemPrompt.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +29 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/policy/labels.d.ts +10 -0
- package/lib/typescript/policy/labels.d.ts.map +1 -0
- package/lib/typescript/policy/policy.d.ts +106 -0
- package/lib/typescript/policy/policy.d.ts.map +1 -0
- package/lib/typescript/policy/redact.d.ts +37 -0
- package/lib/typescript/policy/redact.d.ts.map +1 -0
- package/lib/typescript/providers/anthropic.d.ts +22 -0
- package/lib/typescript/providers/anthropic.d.ts.map +1 -0
- package/lib/typescript/providers/openai.d.ts +19 -0
- package/lib/typescript/providers/openai.d.ts.map +1 -0
- package/lib/typescript/providers/sse.d.ts +18 -0
- package/lib/typescript/providers/sse.d.ts.map +1 -0
- package/lib/typescript/providers/types.d.ts +129 -0
- package/lib/typescript/providers/types.d.ts.map +1 -0
- package/lib/typescript/session.d.ts +58 -0
- package/lib/typescript/session.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +119 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Scrub tool results before they leave the device.
|
|
5
|
+
*
|
|
6
|
+
* Two separate reasons, and the second is the one people forget:
|
|
7
|
+
*
|
|
8
|
+
* 1. EGRESS. Tool results go to the customer's own model endpoint. That is
|
|
9
|
+
* their data boundary, not ours — but a response body carrying an
|
|
10
|
+
* `Authorization` header or a Buoy `licenseKey` is a credential, and
|
|
11
|
+
* credentials do not belong in a chat transcript that may be retained for
|
|
12
|
+
* 30 days for abuse monitoring.
|
|
13
|
+
* 2. SELF-INJECTION. Buoy's own network interceptor captures the agent's
|
|
14
|
+
* requests to the model endpoint. Without exclusion, the model reads back
|
|
15
|
+
* its own request headers — including whatever the host app's `headers()`
|
|
16
|
+
* returned — out of `network.getRequests`. That is a credential leak and a
|
|
17
|
+
* prompt-injection channel in one call.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const SECRET_KEYS = ["authorization", "cookie", "set-cookie", "x-api-key", "api-key", "apikey", "proxy-authorization", "x-auth-token", "licensekey", "license_key", "refresh_token", "access_token", "id_token", "password", "secret", "client_secret"];
|
|
21
|
+
const REDACTED = "[redacted by Buoy]";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Credential SHAPES, for values whose key name gives nothing away — a JWT
|
|
25
|
+
* stored under `session`, a Bearer header quoted inside a response body. The
|
|
26
|
+
* key-name check alone let those through whole. Same shapes the broker wire
|
|
27
|
+
* scrubber uses; duplicated here because agent-core cannot depend on ask-buoy.
|
|
28
|
+
*/
|
|
29
|
+
const SECRET_VALUE_PATTERNS = [{
|
|
30
|
+
re: /\bBearer\s+[A-Za-z0-9._~+/-]{12,}=*/gi,
|
|
31
|
+
label: "[bearer token removed]"
|
|
32
|
+
}, {
|
|
33
|
+
re: /\beyJ[A-Za-z0-9._-]{20,}/g,
|
|
34
|
+
label: "[jwt removed]"
|
|
35
|
+
}, {
|
|
36
|
+
re: /\bsk-[A-Za-z0-9_-]{16,}/g,
|
|
37
|
+
label: "[api key removed]"
|
|
38
|
+
}, {
|
|
39
|
+
re: /\bBUOY-[A-Z0-9-]{8,}/g,
|
|
40
|
+
label: "[license key removed]"
|
|
41
|
+
}, {
|
|
42
|
+
re: /("|')?(authorization|x-api-key|api[_-]?key|password|secret|access_token|refresh_token)\1?\s*[:=]\s*("|')?[^\s"',}]{6,}/gi,
|
|
43
|
+
label: "[credential removed]"
|
|
44
|
+
}];
|
|
45
|
+
function scrubString(s) {
|
|
46
|
+
let out = s;
|
|
47
|
+
for (const {
|
|
48
|
+
re,
|
|
49
|
+
label
|
|
50
|
+
} of SECRET_VALUE_PATTERNS) {
|
|
51
|
+
out = out.replace(re, label);
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
function isSecretKey(key) {
|
|
56
|
+
const k = key.toLowerCase();
|
|
57
|
+
return SECRET_KEYS.some(s => k === s || k.endsWith(s) || k.includes(s));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Deep-redact by key name AND by value shape. Depth-limited because tool
|
|
62
|
+
* results can be deeply nested state trees and a runaway walk on a megabyte
|
|
63
|
+
* payload is a frame drop on the JS thread the app is also using.
|
|
64
|
+
*/
|
|
65
|
+
export function redact(value, depth = 0) {
|
|
66
|
+
if (typeof value === "string") return scrubString(value);
|
|
67
|
+
if (depth > 12 || value === null || typeof value !== "object") return value;
|
|
68
|
+
if (Array.isArray(value)) {
|
|
69
|
+
return value.map(v => redact(v, depth + 1));
|
|
70
|
+
}
|
|
71
|
+
const out = {};
|
|
72
|
+
for (const [key, v] of Object.entries(value)) {
|
|
73
|
+
out[key] = isSecretKey(key) ? REDACTED : redact(v, depth + 1);
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Hosts that must never appear in a tool result, because they are the agent's
|
|
80
|
+
* own traffic. Registered by the runtime from the configured endpoint.
|
|
81
|
+
*/
|
|
82
|
+
const selfHosts = new Set();
|
|
83
|
+
export function registerSelfEndpoint(endpoint) {
|
|
84
|
+
try {
|
|
85
|
+
// No URL polyfill assumptions — a plain parse is enough for a host match.
|
|
86
|
+
const match = /^[a-z]+:\/\/([^/?#]+)/i.exec(endpoint);
|
|
87
|
+
if (match?.[1]) selfHosts.add(match[1].toLowerCase());
|
|
88
|
+
} catch {
|
|
89
|
+
/* an unparseable endpoint just means no exclusion */
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export function isSelfTraffic(url) {
|
|
93
|
+
if (typeof url !== "string") return false;
|
|
94
|
+
const lower = url.toLowerCase();
|
|
95
|
+
for (const host of selfHosts) {
|
|
96
|
+
if (lower.includes(host)) return true;
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
function hasSelfUrl(item) {
|
|
101
|
+
if (!item || typeof item !== "object") return false;
|
|
102
|
+
const rec = item;
|
|
103
|
+
return isSelfTraffic(rec.url ?? rec.uri ?? rec.href);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Drop the agent's own requests out of a network-shaped result before the
|
|
108
|
+
* model sees them.
|
|
109
|
+
*
|
|
110
|
+
* WALKS INTO OBJECTS, not just top-level arrays. A network reader returns
|
|
111
|
+
* `{ totalCaptured, requests: [...] }`, not a bare array, and a version of
|
|
112
|
+
* this that only handled the bare array quietly did nothing — the agent's own
|
|
113
|
+
* POST to the model endpoint, headers and all, came straight back to it out
|
|
114
|
+
* of the network read. Depth-limited for the same reason `redact` is: this
|
|
115
|
+
* runs on the JS thread the app is drawing on.
|
|
116
|
+
*/
|
|
117
|
+
export function stripSelfTraffic(value, depth = 0) {
|
|
118
|
+
if (depth > 6 || value === null || typeof value !== "object") return value;
|
|
119
|
+
if (Array.isArray(value)) {
|
|
120
|
+
return value.filter(item => !hasSelfUrl(item)).map(item => stripSelfTraffic(item, depth + 1));
|
|
121
|
+
}
|
|
122
|
+
const out = {};
|
|
123
|
+
for (const [key, v] of Object.entries(value)) {
|
|
124
|
+
out[key] = stripSelfTraffic(v, depth + 1);
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["SECRET_KEYS","REDACTED","SECRET_VALUE_PATTERNS","re","label","scrubString","s","out","replace","isSecretKey","key","k","toLowerCase","some","endsWith","includes","redact","value","depth","Array","isArray","map","v","Object","entries","selfHosts","Set","registerSelfEndpoint","endpoint","match","exec","add","isSelfTraffic","url","lower","host","hasSelfUrl","item","rec","uri","href","stripSelfTraffic","filter"],"sourceRoot":"../../../src","sources":["policy/redact.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,MAAMA,WAAW,GAAG,CAClB,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,SAAS,EACT,QAAQ,EACR,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,UAAU,EACV,UAAU,EACV,QAAQ,EACR,eAAe,CAChB;AAED,MAAMC,QAAQ,GAAG,oBAAoB;;AAErC;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,qBAAsD,GAAG,CAC7D;EAAEC,EAAE,EAAE,uCAAuC;EAAEC,KAAK,EAAE;AAAyB,CAAC,EAChF;EAAED,EAAE,EAAE,2BAA2B;EAAEC,KAAK,EAAE;AAAgB,CAAC,EAC3D;EAAED,EAAE,EAAE,0BAA0B;EAAEC,KAAK,EAAE;AAAoB,CAAC,EAC9D;EAAED,EAAE,EAAE,uBAAuB;EAAEC,KAAK,EAAE;AAAwB,CAAC,EAC/D;EACED,EAAE,EAAE,0HAA0H;EAC9HC,KAAK,EAAE;AACT,CAAC,CACF;AAED,SAASC,WAAWA,CAACC,CAAS,EAAU;EACtC,IAAIC,GAAG,GAAGD,CAAC;EACX,KAAK,MAAM;IAAEH,EAAE;IAAEC;EAAM,CAAC,IAAIF,qBAAqB,EAAE;IACjDK,GAAG,GAAGA,GAAG,CAACC,OAAO,CAACL,EAAE,EAAEC,KAAK,CAAC;EAC9B;EACA,OAAOG,GAAG;AACZ;AAEA,SAASE,WAAWA,CAACC,GAAW,EAAW;EACzC,MAAMC,CAAC,GAAGD,GAAG,CAACE,WAAW,CAAC,CAAC;EAC3B,OAAOZ,WAAW,CAACa,IAAI,CAAEP,CAAC,IAAKK,CAAC,KAAKL,CAAC,IAAIK,CAAC,CAACG,QAAQ,CAACR,CAAC,CAAC,IAAIK,CAAC,CAACI,QAAQ,CAACT,CAAC,CAAC,CAAC;AAC3E;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASU,MAAMA,CAACC,KAAc,EAAEC,KAAK,GAAG,CAAC,EAAW;EACzD,IAAI,OAAOD,KAAK,KAAK,QAAQ,EAAE,OAAOZ,WAAW,CAACY,KAAK,CAAC;EACxD,IAAIC,KAAK,GAAG,EAAE,IAAID,KAAK,KAAK,IAAI,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAE3E,IAAIE,KAAK,CAACC,OAAO,CAACH,KAAK,CAAC,EAAE;IACxB,OAAOA,KAAK,CAACI,GAAG,CAAEC,CAAC,IAAKN,MAAM,CAACM,CAAC,EAAEJ,KAAK,GAAG,CAAC,CAAC,CAAC;EAC/C;EAEA,MAAMX,GAA4B,GAAG,CAAC,CAAC;EACvC,KAAK,MAAM,CAACG,GAAG,EAAEY,CAAC,CAAC,IAAIC,MAAM,CAACC,OAAO,CAACP,KAAgC,CAAC,EAAE;IACvEV,GAAG,CAACG,GAAG,CAAC,GAAGD,WAAW,CAACC,GAAG,CAAC,GAAGT,QAAQ,GAAGe,MAAM,CAACM,CAAC,EAAEJ,KAAK,GAAG,CAAC,CAAC;EAC/D;EACA,OAAOX,GAAG;AACZ;;AAEA;AACA;AACA;AACA;AACA,MAAMkB,SAAS,GAAG,IAAIC,GAAG,CAAS,CAAC;AAEnC,OAAO,SAASC,oBAAoBA,CAACC,QAAgB,EAAQ;EAC3D,IAAI;IACF;IACA,MAAMC,KAAK,GAAG,wBAAwB,CAACC,IAAI,CAACF,QAAQ,CAAC;IACrD,IAAIC,KAAK,GAAG,CAAC,CAAC,EAAEJ,SAAS,CAACM,GAAG,CAACF,KAAK,CAAC,CAAC,CAAC,CAACjB,WAAW,CAAC,CAAC,CAAC;EACvD,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ;AAEA,OAAO,SAASoB,aAAaA,CAACC,GAAY,EAAW;EACnD,IAAI,OAAOA,GAAG,KAAK,QAAQ,EAAE,OAAO,KAAK;EACzC,MAAMC,KAAK,GAAGD,GAAG,CAACrB,WAAW,CAAC,CAAC;EAC/B,KAAK,MAAMuB,IAAI,IAAIV,SAAS,EAAE;IAC5B,IAAIS,KAAK,CAACnB,QAAQ,CAACoB,IAAI,CAAC,EAAE,OAAO,IAAI;EACvC;EACA,OAAO,KAAK;AACd;AAEA,SAASC,UAAUA,CAACC,IAAa,EAAW;EAC1C,IAAI,CAACA,IAAI,IAAI,OAAOA,IAAI,KAAK,QAAQ,EAAE,OAAO,KAAK;EACnD,MAAMC,GAAG,GAAGD,IAA+B;EAC3C,OAAOL,aAAa,CAACM,GAAG,CAACL,GAAG,IAAIK,GAAG,CAACC,GAAG,IAAID,GAAG,CAACE,IAAI,CAAC;AACtD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAACxB,KAAc,EAAEC,KAAK,GAAG,CAAC,EAAW;EACnE,IAAIA,KAAK,GAAG,CAAC,IAAID,KAAK,KAAK,IAAI,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAE1E,IAAIE,KAAK,CAACC,OAAO,CAACH,KAAK,CAAC,EAAE;IACxB,OAAOA,KAAK,CAACyB,MAAM,CAAEL,IAAI,IAAK,CAACD,UAAU,CAACC,IAAI,CAAC,CAAC,CAAChB,GAAG,CAAEgB,IAAI,IAAKI,gBAAgB,CAACJ,IAAI,EAAEnB,KAAK,GAAG,CAAC,CAAC,CAAC;EACnG;EAEA,MAAMX,GAA4B,GAAG,CAAC,CAAC;EACvC,KAAK,MAAM,CAACG,GAAG,EAAEY,CAAC,CAAC,IAAIC,MAAM,CAACC,OAAO,CAACP,KAAgC,CAAC,EAAE;IACvEV,GAAG,CAACG,GAAG,CAAC,GAAG+B,gBAAgB,CAACnB,CAAC,EAAEJ,KAAK,GAAG,CAAC,CAAC;EAC3C;EACA,OAAOX,GAAG;AACZ","ignoreList":[]}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Anthropic Messages protocol.
|
|
5
|
+
*
|
|
6
|
+
* Four things here are not obvious and each one is a silent failure if missed:
|
|
7
|
+
*
|
|
8
|
+
* 1. `content_block_start` for a `tool_use` carries `"input": {}` — an EMPTY
|
|
9
|
+
* object, never the real arguments. The arguments only exist after
|
|
10
|
+
* concatenating every `input_json_delta.partial_json` and parsing at
|
|
11
|
+
* `content_block_stop`. Reading `.input` at start yields a tool call with no
|
|
12
|
+
* arguments and no error.
|
|
13
|
+
* 2. There is NO `data: [DONE]` sentinel (removed in the 2023-06-01 version).
|
|
14
|
+
* The stream ends at `message_stop`.
|
|
15
|
+
* 3. `error` events arrive MID-STREAM on an already-committed HTTP 200 —
|
|
16
|
+
* `overloaded_error` being the common one. A 200 is not success.
|
|
17
|
+
* 4. Ordering is 400-level strict: `tool_result` blocks must come FIRST in the
|
|
18
|
+
* user content array with any text after, and that user message must
|
|
19
|
+
* immediately follow the assistant turn. "Here are the results:" placed
|
|
20
|
+
* before the blocks is an instant 400.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { errorBody, readSse } from "./sse";
|
|
24
|
+
const DEFAULT_VERSION = "2023-06-01";
|
|
25
|
+
function toWireMessages(messages) {
|
|
26
|
+
const out = [];
|
|
27
|
+
for (const m of messages) {
|
|
28
|
+
if (m.role === "user") {
|
|
29
|
+
out.push({
|
|
30
|
+
role: "user",
|
|
31
|
+
content: [{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: m.text
|
|
34
|
+
}]
|
|
35
|
+
});
|
|
36
|
+
} else if (m.role === "assistant") {
|
|
37
|
+
const content = [];
|
|
38
|
+
if (m.text) content.push({
|
|
39
|
+
type: "text",
|
|
40
|
+
text: m.text
|
|
41
|
+
});
|
|
42
|
+
for (const c of m.toolCalls ?? []) {
|
|
43
|
+
content.push({
|
|
44
|
+
type: "tool_use",
|
|
45
|
+
id: c.id,
|
|
46
|
+
name: c.name,
|
|
47
|
+
input: c.input
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (content.length) out.push({
|
|
51
|
+
role: "assistant",
|
|
52
|
+
content
|
|
53
|
+
});
|
|
54
|
+
} else {
|
|
55
|
+
// tool_result blocks FIRST — see note 4. No preamble text, ever.
|
|
56
|
+
out.push({
|
|
57
|
+
role: "user",
|
|
58
|
+
content: m.results.map(r => ({
|
|
59
|
+
type: "tool_result",
|
|
60
|
+
tool_use_id: r.toolCallId,
|
|
61
|
+
content: r.content,
|
|
62
|
+
...(r.isError ? {
|
|
63
|
+
is_error: true
|
|
64
|
+
} : {})
|
|
65
|
+
}))
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
export function createAnthropicProvider(config) {
|
|
72
|
+
return {
|
|
73
|
+
protocol: "anthropic",
|
|
74
|
+
async *send(req) {
|
|
75
|
+
const headers = {
|
|
76
|
+
"content-type": "application/json",
|
|
77
|
+
"anthropic-version": config.anthropicVersion ?? DEFAULT_VERSION,
|
|
78
|
+
...(await (config.headers?.() ?? {}))
|
|
79
|
+
};
|
|
80
|
+
// Dev-only direct mode. A distributed build uses `headers` against the
|
|
81
|
+
// org's own gateway and never carries a provider key at all.
|
|
82
|
+
if (config.apiKey && !headers["x-api-key"] && !headers.Authorization) {
|
|
83
|
+
headers["x-api-key"] = config.apiKey;
|
|
84
|
+
// Without this the POST comes back with no access-control-allow-origin
|
|
85
|
+
// and a browser/Electron renderer silently discards an otherwise fine
|
|
86
|
+
// response — a 200 in the network log and "Failed to fetch" in JS.
|
|
87
|
+
headers["anthropic-dangerous-direct-browser-access"] = "true";
|
|
88
|
+
}
|
|
89
|
+
const response = await fetch(config.endpoint, {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers,
|
|
92
|
+
signal: req.signal,
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
model: req.model,
|
|
95
|
+
max_tokens: req.maxTokens,
|
|
96
|
+
stream: true,
|
|
97
|
+
// ONE cache breakpoint, at the end of `system`.
|
|
98
|
+
//
|
|
99
|
+
// Anthropic caches the prefix in a fixed order — tools, then system,
|
|
100
|
+
// then messages — up to and including the block carrying
|
|
101
|
+
// `cache_control`. So marking the end of the system prompt caches
|
|
102
|
+
// the tool definitions with it, which is the point: the tools are
|
|
103
|
+
// ~20k tokens and by far the larger half. A second breakpoint on the
|
|
104
|
+
// last tool would buy nothing and spend one of the four available.
|
|
105
|
+
//
|
|
106
|
+
// Messages stay uncached on purpose. They grow every turn, so they
|
|
107
|
+
// would invalidate on each request and pay the write multiplier for
|
|
108
|
+
// a prefix that is never read back.
|
|
109
|
+
system: config.cache === false ? req.system : [{
|
|
110
|
+
type: "text",
|
|
111
|
+
text: req.system,
|
|
112
|
+
cache_control: {
|
|
113
|
+
type: "ephemeral"
|
|
114
|
+
}
|
|
115
|
+
}],
|
|
116
|
+
tools: req.tools.map(t => ({
|
|
117
|
+
name: t.name,
|
|
118
|
+
description: t.description,
|
|
119
|
+
input_schema: t.inputSchema
|
|
120
|
+
})),
|
|
121
|
+
messages: toWireMessages(req.messages),
|
|
122
|
+
...config.requestOverrides
|
|
123
|
+
})
|
|
124
|
+
});
|
|
125
|
+
if (!response.ok) {
|
|
126
|
+
yield {
|
|
127
|
+
type: "error",
|
|
128
|
+
message: await errorBody(response)
|
|
129
|
+
};
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Partial tool_use args accumulate here, keyed by content-block index.
|
|
134
|
+
const pending = new Map();
|
|
135
|
+
let stopReason;
|
|
136
|
+
let usage;
|
|
137
|
+
for await (const ev of readSse(response)) {
|
|
138
|
+
let payload;
|
|
139
|
+
try {
|
|
140
|
+
payload = JSON.parse(ev.data);
|
|
141
|
+
} catch {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const kind = payload.type ?? ev.event;
|
|
145
|
+
switch (kind) {
|
|
146
|
+
case "content_block_start":
|
|
147
|
+
{
|
|
148
|
+
const block = payload.content_block;
|
|
149
|
+
if (block?.type === "tool_use") {
|
|
150
|
+
// NOT block.input — see note 1.
|
|
151
|
+
pending.set(payload.index, {
|
|
152
|
+
id: block.id,
|
|
153
|
+
name: block.name,
|
|
154
|
+
json: ""
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
case "content_block_delta":
|
|
160
|
+
{
|
|
161
|
+
const delta = payload.delta;
|
|
162
|
+
if (delta?.type === "text_delta") {
|
|
163
|
+
yield {
|
|
164
|
+
type: "text",
|
|
165
|
+
delta: delta.text
|
|
166
|
+
};
|
|
167
|
+
} else if (delta?.type === "input_json_delta") {
|
|
168
|
+
const slot = pending.get(payload.index);
|
|
169
|
+
if (slot) slot.json += delta.partial_json ?? "";
|
|
170
|
+
}
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case "content_block_stop":
|
|
174
|
+
{
|
|
175
|
+
const slot = pending.get(payload.index);
|
|
176
|
+
if (slot) {
|
|
177
|
+
pending.delete(payload.index);
|
|
178
|
+
let input = {};
|
|
179
|
+
try {
|
|
180
|
+
input = slot.json ? JSON.parse(slot.json) : {};
|
|
181
|
+
} catch {
|
|
182
|
+
yield {
|
|
183
|
+
type: "error",
|
|
184
|
+
message: `Model sent unparseable arguments for ${slot.name}`
|
|
185
|
+
};
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
const call = {
|
|
189
|
+
id: slot.id,
|
|
190
|
+
name: slot.name,
|
|
191
|
+
input
|
|
192
|
+
};
|
|
193
|
+
yield {
|
|
194
|
+
type: "tool-call",
|
|
195
|
+
call
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case "message_start":
|
|
201
|
+
{
|
|
202
|
+
// The cache counters arrive HERE, not on message_delta — the
|
|
203
|
+
// prefix is accounted for before a single token is generated. A
|
|
204
|
+
// reader that only watches message_delta sees cacheRead 0 on
|
|
205
|
+
// every request and concludes caching is not working.
|
|
206
|
+
const m = payload.message;
|
|
207
|
+
const u = m?.usage;
|
|
208
|
+
if (u) {
|
|
209
|
+
usage = {
|
|
210
|
+
input: u.input_tokens ?? 0,
|
|
211
|
+
output: u.output_tokens ?? 0,
|
|
212
|
+
...(u.cache_read_input_tokens !== undefined ? {
|
|
213
|
+
cacheRead: u.cache_read_input_tokens
|
|
214
|
+
} : {}),
|
|
215
|
+
...(u.cache_creation_input_tokens !== undefined ? {
|
|
216
|
+
cacheWrite: u.cache_creation_input_tokens
|
|
217
|
+
} : {})
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
case "message_delta":
|
|
223
|
+
{
|
|
224
|
+
const delta = payload.delta;
|
|
225
|
+
if (delta?.stop_reason) stopReason = delta.stop_reason;
|
|
226
|
+
// Cumulative, not incremental — assign, never add. Output tokens
|
|
227
|
+
// are only final here, so keep whatever message_start reported
|
|
228
|
+
// about the cache rather than replacing the whole record.
|
|
229
|
+
const u = payload.usage;
|
|
230
|
+
if (u) {
|
|
231
|
+
usage = {
|
|
232
|
+
...usage,
|
|
233
|
+
input: u.input_tokens ?? usage?.input ?? 0,
|
|
234
|
+
output: u.output_tokens ?? 0
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case "error":
|
|
240
|
+
{
|
|
241
|
+
const err = payload.error;
|
|
242
|
+
yield {
|
|
243
|
+
type: "error",
|
|
244
|
+
message: err?.message ?? "Provider error"
|
|
245
|
+
};
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
case "message_stop":
|
|
249
|
+
// The end. There is no [DONE] — see note 2.
|
|
250
|
+
yield {
|
|
251
|
+
type: "done",
|
|
252
|
+
stopReason,
|
|
253
|
+
usage
|
|
254
|
+
};
|
|
255
|
+
return;
|
|
256
|
+
default:
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
yield {
|
|
261
|
+
type: "done",
|
|
262
|
+
stopReason,
|
|
263
|
+
usage
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["errorBody","readSse","DEFAULT_VERSION","toWireMessages","messages","out","m","role","push","content","type","text","c","toolCalls","id","name","input","length","results","map","r","tool_use_id","toolCallId","isError","is_error","createAnthropicProvider","config","protocol","send","req","headers","anthropicVersion","apiKey","Authorization","response","fetch","endpoint","method","signal","body","JSON","stringify","model","max_tokens","maxTokens","stream","system","cache","cache_control","tools","t","description","input_schema","inputSchema","requestOverrides","ok","message","pending","Map","stopReason","usage","ev","payload","parse","data","kind","event","block","content_block","set","index","json","delta","slot","get","partial_json","delete","call","u","input_tokens","output","output_tokens","cache_read_input_tokens","undefined","cacheRead","cache_creation_input_tokens","cacheWrite","stop_reason","err","error"],"sourceRoot":"../../../src","sources":["providers/anthropic.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OpenAI chat-completions protocol.
|
|
5
|
+
*
|
|
6
|
+
* The differences from Anthropic that actually matter to the code:
|
|
7
|
+
* - Tool results are their own `{role:"tool", tool_call_id, content}` MESSAGE,
|
|
8
|
+
* not blocks inside a user message.
|
|
9
|
+
* - Tool arguments arrive as a JSON STRING, streamed in fragments, and are
|
|
10
|
+
* keyed by an `index` that is stable across deltas while `id`/`name` only
|
|
11
|
+
* appear on the first fragment.
|
|
12
|
+
* - The stream DOES have a `data: [DONE]` sentinel, unlike Anthropic's.
|
|
13
|
+
*
|
|
14
|
+
* This adapter also serves Azure and any OpenAI-compatible org gateway, which
|
|
15
|
+
* is the common shape for an internal LLM proxy. Note Anthropic's own
|
|
16
|
+
* OpenAI-compatibility endpoint is explicitly not production-ready and silently
|
|
17
|
+
* ignores several fields — use the native Anthropic adapter for Anthropic.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { errorBody, readSse } from "./sse";
|
|
21
|
+
function toWireMessages(system, messages) {
|
|
22
|
+
const out = [{
|
|
23
|
+
role: "system",
|
|
24
|
+
content: system
|
|
25
|
+
}];
|
|
26
|
+
for (const m of messages) {
|
|
27
|
+
if (m.role === "user") {
|
|
28
|
+
out.push({
|
|
29
|
+
role: "user",
|
|
30
|
+
content: m.text
|
|
31
|
+
});
|
|
32
|
+
} else if (m.role === "assistant") {
|
|
33
|
+
out.push({
|
|
34
|
+
role: "assistant",
|
|
35
|
+
content: m.text || null,
|
|
36
|
+
...(m.toolCalls?.length ? {
|
|
37
|
+
tool_calls: m.toolCalls.map(c => ({
|
|
38
|
+
id: c.id,
|
|
39
|
+
type: "function",
|
|
40
|
+
function: {
|
|
41
|
+
name: c.name,
|
|
42
|
+
arguments: JSON.stringify(c.input)
|
|
43
|
+
}
|
|
44
|
+
}))
|
|
45
|
+
} : {})
|
|
46
|
+
});
|
|
47
|
+
} else {
|
|
48
|
+
// One message per result, not one message with many.
|
|
49
|
+
for (const r of m.results) {
|
|
50
|
+
out.push({
|
|
51
|
+
role: "tool",
|
|
52
|
+
tool_call_id: r.toolCallId,
|
|
53
|
+
content: r.content
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
export function createOpenAIProvider(config) {
|
|
61
|
+
return {
|
|
62
|
+
protocol: "openai",
|
|
63
|
+
async *send(req) {
|
|
64
|
+
const headers = {
|
|
65
|
+
"content-type": "application/json",
|
|
66
|
+
...(await (config.headers?.() ?? {}))
|
|
67
|
+
};
|
|
68
|
+
if (config.apiKey && !headers.Authorization && !headers["api-key"]) {
|
|
69
|
+
headers.Authorization = `Bearer ${config.apiKey}`;
|
|
70
|
+
}
|
|
71
|
+
const response = await fetch(config.endpoint, {
|
|
72
|
+
method: "POST",
|
|
73
|
+
headers,
|
|
74
|
+
signal: req.signal,
|
|
75
|
+
body: JSON.stringify({
|
|
76
|
+
model: req.model,
|
|
77
|
+
max_tokens: req.maxTokens,
|
|
78
|
+
stream: true,
|
|
79
|
+
stream_options: {
|
|
80
|
+
include_usage: true
|
|
81
|
+
},
|
|
82
|
+
messages: toWireMessages(req.system, req.messages),
|
|
83
|
+
tools: req.tools.map(t => ({
|
|
84
|
+
type: "function",
|
|
85
|
+
function: {
|
|
86
|
+
name: t.name,
|
|
87
|
+
// Azure caps function descriptions at 1024 chars while Anthropic's
|
|
88
|
+
// guidance asks for several sentences. Trim rather than 400.
|
|
89
|
+
description: t.description.slice(0, 1024),
|
|
90
|
+
parameters: t.inputSchema
|
|
91
|
+
}
|
|
92
|
+
})),
|
|
93
|
+
...config.requestOverrides
|
|
94
|
+
})
|
|
95
|
+
});
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
yield {
|
|
98
|
+
type: "error",
|
|
99
|
+
message: await errorBody(response)
|
|
100
|
+
};
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Keyed by the stream's `index`; id and name arrive only on the first
|
|
105
|
+
// fragment, arguments accumulate across all of them.
|
|
106
|
+
const pending = new Map();
|
|
107
|
+
let stopReason;
|
|
108
|
+
let usage;
|
|
109
|
+
const flush = function* () {
|
|
110
|
+
for (const [, slot] of pending) {
|
|
111
|
+
let input = {};
|
|
112
|
+
try {
|
|
113
|
+
input = slot.args ? JSON.parse(slot.args) : {};
|
|
114
|
+
} catch {
|
|
115
|
+
yield {
|
|
116
|
+
type: "error",
|
|
117
|
+
message: `Model sent unparseable arguments for ${slot.name}`
|
|
118
|
+
};
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
yield {
|
|
122
|
+
type: "tool-call",
|
|
123
|
+
call: {
|
|
124
|
+
id: slot.id,
|
|
125
|
+
name: slot.name,
|
|
126
|
+
input
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
pending.clear();
|
|
131
|
+
};
|
|
132
|
+
for await (const ev of readSse(response)) {
|
|
133
|
+
if (ev.data === "[DONE]") break;
|
|
134
|
+
let payload;
|
|
135
|
+
try {
|
|
136
|
+
payload = JSON.parse(ev.data);
|
|
137
|
+
} catch {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (payload.error) {
|
|
141
|
+
const err = payload.error;
|
|
142
|
+
yield {
|
|
143
|
+
type: "error",
|
|
144
|
+
message: err.message ?? "Provider error"
|
|
145
|
+
};
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const u = payload.usage;
|
|
149
|
+
if (u) {
|
|
150
|
+
usage = {
|
|
151
|
+
input: u.prompt_tokens ?? 0,
|
|
152
|
+
output: u.completion_tokens ?? 0
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const choice = payload.choices?.[0];
|
|
156
|
+
if (!choice) continue;
|
|
157
|
+
if (choice.finish_reason) stopReason = choice.finish_reason;
|
|
158
|
+
const delta = choice.delta;
|
|
159
|
+
if (typeof delta?.content === "string" && delta.content) {
|
|
160
|
+
yield {
|
|
161
|
+
type: "text",
|
|
162
|
+
delta: delta.content
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const calls = delta?.tool_calls;
|
|
166
|
+
for (const c of calls ?? []) {
|
|
167
|
+
const index = c.index ?? 0;
|
|
168
|
+
const fn = c.function;
|
|
169
|
+
const slot = pending.get(index) ?? {
|
|
170
|
+
id: "",
|
|
171
|
+
name: "",
|
|
172
|
+
args: ""
|
|
173
|
+
};
|
|
174
|
+
if (c.id) slot.id = c.id;
|
|
175
|
+
if (fn?.name) slot.name = fn.name;
|
|
176
|
+
if (typeof fn?.arguments === "string") slot.args += fn.arguments;
|
|
177
|
+
pending.set(index, slot);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
yield* flush();
|
|
181
|
+
yield {
|
|
182
|
+
type: "done",
|
|
183
|
+
stopReason,
|
|
184
|
+
usage
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["errorBody","readSse","toWireMessages","system","messages","out","role","content","m","push","text","toolCalls","length","tool_calls","map","c","id","type","function","name","arguments","JSON","stringify","input","r","results","tool_call_id","toolCallId","createOpenAIProvider","config","protocol","send","req","headers","apiKey","Authorization","response","fetch","endpoint","method","signal","body","model","max_tokens","maxTokens","stream","stream_options","include_usage","tools","t","description","slice","parameters","inputSchema","requestOverrides","ok","message","pending","Map","stopReason","usage","flush","slot","args","parse","call","clear","ev","data","payload","error","err","u","prompt_tokens","output","completion_tokens","choice","choices","finish_reason","delta","calls","index","fn","get","set"],"sourceRoot":"../../../src","sources":["providers/openai.ts"],"mappings":"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","ignoreList":[]}
|