@opengeni/sdk 3.3.2-canary.1 → 3.4.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 +1007 -72
- package/dist/adapters/express.d.ts +31 -0
- package/dist/adapters/express.js +87 -0
- package/dist/adapters/express.js.map +1 -0
- package/dist/adapters/hono.d.ts +16 -0
- package/dist/adapters/hono.js +8 -0
- package/dist/adapters/hono.js.map +1 -0
- package/dist/adapters/next.d.ts +29 -0
- package/dist/adapters/next.js +22 -0
- package/dist/adapters/next.js.map +1 -0
- package/dist/allowance-refusal.d.ts +2 -0
- package/dist/allowance-refusal.js +50 -0
- package/dist/allowance-refusal.js.map +1 -0
- package/dist/app-links.d.ts +42 -0
- package/dist/app-links.js +66 -0
- package/dist/app-links.js.map +1 -0
- package/dist/artifact-catalog.d.ts +40 -0
- package/dist/artifact-client.d.ts +20 -8
- package/dist/artifacts.d.ts +1 -1
- package/dist/artifacts.js +8 -6
- package/dist/automations.js +8 -2
- package/dist/automations.js.map +1 -1
- package/dist/azure-live-transport.d.ts +32 -0
- package/dist/browser.d.ts +6 -2
- package/dist/browser.js +25 -5
- package/dist/chat/fold.d.ts +75 -0
- package/dist/chat/handler.d.ts +41 -0
- package/dist/chat/http.d.ts +67 -0
- package/dist/chat/ids.d.ts +34 -0
- package/dist/chat/index.d.ts +9 -0
- package/dist/chat/index.js +1369 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/openai.d.ts +30 -0
- package/dist/chat/opengeni.d.ts +129 -0
- package/dist/chat/types.d.ts +207 -0
- package/dist/chat/vercel.d.ts +49 -0
- package/dist/chats.d.ts +8 -0
- package/dist/chunk-4AHR4KGA.js +301 -0
- package/dist/chunk-4AHR4KGA.js.map +1 -0
- package/dist/chunk-6GYGMLX4.js +332 -0
- package/dist/chunk-6GYGMLX4.js.map +1 -0
- package/dist/chunk-7EWT3PV6.js +368 -0
- package/dist/chunk-7EWT3PV6.js.map +1 -0
- package/dist/chunk-FTWVVPR6.js +1665 -0
- package/dist/chunk-FTWVVPR6.js.map +1 -0
- package/dist/{chunk-VYCTL62C.js → chunk-GZQSWAKD.js} +1 -1
- package/dist/chunk-GZQSWAKD.js.map +1 -0
- package/dist/chunk-KGEABAID.js +71 -0
- package/dist/chunk-KGEABAID.js.map +1 -0
- package/dist/{chunk-YKZME56C.js → chunk-KWADQ227.js} +3 -3
- package/dist/{chunk-YKZME56C.js.map → chunk-KWADQ227.js.map} +1 -1
- package/dist/{chunk-E5BNEG2D.js → chunk-NCU5OAN7.js} +27 -2
- package/dist/chunk-NCU5OAN7.js.map +1 -0
- package/dist/{chunk-BESZFWMU.js → chunk-OI5YLASH.js} +73 -2
- package/dist/chunk-OI5YLASH.js.map +1 -0
- package/dist/chunk-OV3POE62.js +359 -0
- package/dist/chunk-OV3POE62.js.map +1 -0
- package/dist/chunk-P7UWKORG.js +561 -0
- package/dist/chunk-P7UWKORG.js.map +1 -0
- package/dist/chunk-QGEIL4TR.js +195 -0
- package/dist/chunk-QGEIL4TR.js.map +1 -0
- package/dist/{chunk-GY6RQPCG.js → chunk-S2NLS3ES.js} +3598 -1278
- package/dist/chunk-S2NLS3ES.js.map +1 -0
- package/dist/chunk-UM4ZXXJR.js +9 -0
- package/dist/chunk-UM4ZXXJR.js.map +1 -0
- package/dist/{chunk-TFCLHRZK.js → chunk-UME3X7CP.js} +28 -32
- package/dist/chunk-UME3X7CP.js.map +1 -0
- package/dist/chunk-VT4YM4XQ.js +210 -0
- package/dist/chunk-VT4YM4XQ.js.map +1 -0
- package/dist/chunk-WSYYXONG.js +1602 -0
- package/dist/chunk-WSYYXONG.js.map +1 -0
- package/dist/{chunk-6NEPJ7NC.js → chunk-WVCJRSGJ.js} +119 -14
- package/dist/chunk-WVCJRSGJ.js.map +1 -0
- package/dist/chunk-X5ITQVXE.js +15 -0
- package/dist/chunk-X5ITQVXE.js.map +1 -0
- package/dist/chunk-XA7HVIHI.js +126 -0
- package/dist/chunk-XA7HVIHI.js.map +1 -0
- package/dist/{chunk-QTBAMHEF.js → chunk-YJCHB7R3.js} +60 -12
- package/dist/chunk-YJCHB7R3.js.map +1 -0
- package/dist/chunk-YKIHNLWD.js +153 -0
- package/dist/chunk-YKIHNLWD.js.map +1 -0
- package/dist/chunk-ZDUBPV33.js +277 -0
- package/dist/chunk-ZDUBPV33.js.map +1 -0
- package/dist/client.d.ts +1056 -118
- package/dist/codex-realtime-controller.d.ts +13 -0
- package/dist/codex-realtime-controller.js +4 -2
- package/dist/codex-realtime-v3-wire.d.ts +3 -2
- package/dist/codex-realtime.d.ts +5 -1
- package/dist/company-brain.d.ts +1 -11
- package/dist/core.d.ts +6 -2
- package/dist/core.js +23 -6
- package/dist/deprecation.d.ts +47 -0
- package/dist/document-authority-client.d.ts +24 -2
- package/dist/document-authority.js +7 -5
- package/dist/editable-artifacts/index.d.ts +1 -1
- package/dist/editable-artifacts/types.d.ts +12 -2
- package/dist/editable-artifacts.js +19 -3
- package/dist/editable-artifacts.js.map +1 -1
- package/dist/embedding-client.d.ts +129 -0
- package/dist/errors.d.ts +64 -1
- package/dist/external-vault-receiver.d.ts +203 -0
- package/dist/external-vault-receiver.js +564 -0
- package/dist/external-vault-receiver.js.map +1 -0
- package/dist/feedback.d.ts +23 -0
- package/dist/gateway-realtime-transport.js +1 -1
- package/dist/github-repositories.d.ts +10 -0
- package/dist/github-repositories.js +36 -0
- package/dist/github-repositories.js.map +1 -0
- package/dist/index.d.ts +61 -11
- package/dist/index.js +555 -338
- package/dist/index.js.map +1 -1
- package/dist/insights-usage.d.ts +33 -0
- package/dist/insights-usage.js +7 -0
- package/dist/insights-usage.js.map +1 -0
- package/dist/interaction.d.ts +165 -71
- package/dist/interaction.js +2 -2
- package/dist/knowledge.d.ts +7 -0
- package/dist/knowledge.js +20 -0
- package/dist/knowledge.js.map +1 -0
- package/dist/known-tools.d.ts +4 -0
- package/dist/message-links.d.ts +68 -0
- package/dist/model-context.d.ts +68 -0
- package/dist/model-display.d.ts +2 -0
- package/dist/model-display.js +17 -0
- package/dist/model-display.js.map +1 -0
- package/dist/organization-integration-policy.d.ts +26 -0
- package/dist/organization-integration-policy.js +26 -0
- package/dist/organization-integration-policy.js.map +1 -0
- package/dist/pr-review-client.d.ts +1 -1
- package/dist/pr-review.d.ts +1 -1
- package/dist/pr-review.js.map +1 -1
- package/dist/preference-registry.d.ts +1 -1
- package/dist/prepared-mcp-setup.d.ts +5 -0
- package/dist/proxy.d.ts +13 -11
- package/dist/realtime.d.ts +1 -1
- package/dist/realtime.js +253 -7
- package/dist/realtime.js.map +1 -1
- package/dist/session-history-import.d.ts +22 -0
- package/dist/session-history-import.js +36 -0
- package/dist/session-history-import.js.map +1 -0
- package/dist/session-list-entries.d.ts +1 -0
- package/dist/session-list-entries.js +7 -0
- package/dist/session-list-entries.js.map +1 -0
- package/dist/session-message-search.d.ts +53 -0
- package/dist/session-proxy-client.d.ts +28 -0
- package/dist/session-proxy.d.ts +334 -0
- package/dist/session-proxy.js +24 -0
- package/dist/session-proxy.js.map +1 -0
- package/dist/session-titles.d.ts +2 -28
- package/dist/session-usage-limits.d.ts +10 -0
- package/dist/session-usage-limits.js +43 -0
- package/dist/session-usage-limits.js.map +1 -0
- package/dist/shared-catalog-loader.d.ts +34 -0
- package/dist/site-ai.d.ts +35 -0
- package/dist/site-bridge-host.d.ts +112 -0
- package/dist/site-bridge-host.js +286 -0
- package/dist/site-bridge-host.js.map +1 -0
- package/dist/site-browser-entry.d.ts +1 -0
- package/dist/site-browser-runtime.gen.d.ts +1 -0
- package/dist/site-data.d.ts +178 -0
- package/dist/site-document.d.ts +5 -0
- package/dist/site-document.js +20 -0
- package/dist/site-document.js.map +1 -0
- package/dist/site-document.test.d.ts +1 -0
- package/dist/site-http.d.ts +17 -0
- package/dist/site-sql.d.ts +31 -0
- package/dist/site-tool-bridge.d.ts +57 -0
- package/dist/site.d.ts +186 -0
- package/dist/site.js +63 -0
- package/dist/site.js.map +1 -0
- package/dist/skills.d.ts +75 -0
- package/dist/sse.d.ts +1 -1
- package/dist/stream.d.ts +2 -0
- package/dist/tenant-workspaces.d.ts +47 -0
- package/dist/tenant-workspaces.js +8 -0
- package/dist/tenant-workspaces.js.map +1 -0
- package/dist/tool-auth.d.ts +87 -0
- package/dist/tool-auth.js +23 -0
- package/dist/tool-auth.js.map +1 -0
- package/dist/tool-display-metadata.d.ts +3 -0
- package/dist/tools-37DCTCNZ.js +12 -0
- package/dist/tools-37DCTCNZ.js.map +1 -0
- package/dist/tools.d.ts +81 -0
- package/dist/transcription.d.ts +1 -1
- package/dist/types.d.ts +2785 -592
- package/dist/usage-allowances.d.ts +36 -0
- package/dist/usage-allowances.js +80 -0
- package/dist/usage-allowances.js.map +1 -0
- package/dist/vault-types.d.ts +324 -0
- package/dist/vaults-api.d.ts +65 -0
- package/dist/workspace-artifacts.d.ts +47 -5
- package/dist/workspace-instruction-policies.d.ts +2 -2
- package/dist/workspace-integrations.d.ts +74 -0
- package/dist/workspace-integrations.js +67 -0
- package/dist/workspace-integrations.js.map +1 -0
- package/dist/workspace-state.d.ts +8 -71
- package/package.json +99 -5
- package/src/adapters/express.ts +136 -0
- package/src/adapters/hono.ts +18 -0
- package/src/adapters/next.ts +42 -0
- package/src/allowance-refusal.ts +5 -0
- package/src/app-links.ts +117 -0
- package/src/artifact-catalog.ts +51 -0
- package/src/artifact-client.ts +40 -49
- package/src/artifacts.ts +1 -0
- package/src/automations-client.ts +8 -2
- package/src/azure-live-transport.ts +286 -0
- package/src/browser.ts +35 -0
- package/src/chat/fold.ts +431 -0
- package/src/chat/handler.ts +240 -0
- package/src/chat/http.ts +257 -0
- package/src/chat/ids.ts +85 -0
- package/src/chat/index.ts +88 -0
- package/src/chat/openai.ts +439 -0
- package/src/chat/opengeni.ts +737 -0
- package/src/chat/types.ts +219 -0
- package/src/chat/vercel.ts +204 -0
- package/src/chats.ts +16 -0
- package/src/client.ts +5595 -1847
- package/src/codex-realtime-controller.ts +163 -8
- package/src/codex-realtime-v3-wire.ts +4 -3
- package/src/codex-realtime-v3.ts +12 -3
- package/src/codex-realtime.ts +11 -3
- package/src/company-brain.ts +0 -40
- package/src/core.ts +18 -0
- package/src/deprecation.ts +149 -0
- package/src/document-authority-client.ts +104 -1
- package/src/editable-artifacts/controller.ts +36 -2
- package/src/editable-artifacts/index.ts +1 -0
- package/src/editable-artifacts/types.ts +29 -16
- package/src/embedding-client.ts +519 -0
- package/src/errors.ts +281 -5
- package/src/external-vault-receiver.ts +914 -0
- package/src/feedback.ts +20 -0
- package/src/gateway-realtime-transport.ts +3 -3
- package/src/github-repositories.ts +60 -0
- package/src/index.ts +592 -65
- package/src/insights-usage.ts +64 -0
- package/src/interaction.ts +315 -93
- package/src/knowledge.ts +72 -0
- package/src/known-tools.ts +279 -0
- package/src/message-links.ts +178 -0
- package/src/model-context.ts +113 -0
- package/src/model-display.ts +11 -0
- package/src/organization-integration-policy.ts +54 -0
- package/src/pr-review-client.ts +1 -1
- package/src/pr-review.ts +1 -1
- package/src/preference-registry.ts +2 -0
- package/src/prepared-mcp-setup.ts +123 -0
- package/src/proxy.ts +23 -12
- package/src/realtime.ts +15 -6
- package/src/session-history-import.ts +84 -0
- package/src/session-list-entries.ts +1 -0
- package/src/session-message-search.ts +47 -0
- package/src/session-proxy-client.ts +68 -0
- package/src/session-proxy.ts +2098 -0
- package/src/session-titles.ts +8 -82
- package/src/session-usage-limits.ts +71 -0
- package/src/shared-catalog-loader.ts +169 -0
- package/src/site-ai.ts +284 -0
- package/src/site-bridge-host.ts +422 -0
- package/src/site-browser-entry.ts +6 -0
- package/src/site-browser-runtime.gen.ts +2 -0
- package/src/site-data.ts +372 -0
- package/src/site-document.test.ts +64 -0
- package/src/site-document.ts +18 -0
- package/src/site-http.ts +171 -0
- package/src/site-sql.ts +153 -0
- package/src/site-tool-bridge.ts +401 -0
- package/src/site.ts +878 -0
- package/src/skills.ts +69 -0
- package/src/sse.ts +9 -3
- package/src/stream.ts +33 -10
- package/src/tenant-workspaces.ts +148 -0
- package/src/tool-auth.ts +301 -0
- package/src/tool-display-metadata.ts +27 -0
- package/src/tools.ts +452 -0
- package/src/transcription.ts +3 -0
- package/src/types.ts +3142 -594
- package/src/usage-allowances.ts +189 -0
- package/src/vault-types.ts +379 -0
- package/src/vaults-api.ts +339 -0
- package/src/workspace-artifacts.ts +55 -6
- package/src/workspace-instruction-policies.ts +2 -1
- package/src/workspace-integrations.ts +402 -0
- package/src/workspace-state.ts +8 -82
- package/dist/chunk-6NEPJ7NC.js.map +0 -1
- package/dist/chunk-BESZFWMU.js.map +0 -1
- package/dist/chunk-E5BNEG2D.js.map +0 -1
- package/dist/chunk-GY6RQPCG.js.map +0 -1
- package/dist/chunk-OO5LPTO7.js +0 -132
- package/dist/chunk-OO5LPTO7.js.map +0 -1
- package/dist/chunk-QTBAMHEF.js.map +0 -1
- package/dist/chunk-TFCLHRZK.js.map +0 -1
- package/dist/chunk-VYCTL62C.js.map +0 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// src/tool-auth.ts
|
|
2
|
+
var TOOL_TOKEN_ISSUER = "opengeni-session-proxy";
|
|
3
|
+
var TOOL_TOKEN_KEY_LABEL = "opengeni-tool-token:v1";
|
|
4
|
+
var TOOL_TOKEN_DEFAULT_TTL_SECONDS = 24 * 60 * 60;
|
|
5
|
+
var MAX_TTL_SECONDS = 7 * 24 * 60 * 60;
|
|
6
|
+
var MAX_HEADER_VALUE_LENGTH = 4096;
|
|
7
|
+
var TOOL_SERVER_URL_ENV = "OPENGENI_TOOL_SERVER_URL";
|
|
8
|
+
var CLOCK_SKEW_SECONDS = 60;
|
|
9
|
+
var ToolRequestError = class extends Error {
|
|
10
|
+
constructor(code) {
|
|
11
|
+
super("Tool request is not authorized.");
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.name = "ToolRequestError";
|
|
14
|
+
}
|
|
15
|
+
status = 401;
|
|
16
|
+
/** A ready 401 response with a `WWW-Authenticate: Bearer` challenge. */
|
|
17
|
+
toResponse() {
|
|
18
|
+
return new Response(JSON.stringify({ error: { code: this.code, message: this.message } }), {
|
|
19
|
+
status: 401,
|
|
20
|
+
headers: {
|
|
21
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
22
|
+
"WWW-Authenticate": 'Bearer error="invalid_token"'
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
async function verifyToolRequest(request, options = {}) {
|
|
28
|
+
const key = await signingKey(resolveToolTokenSecret(options.secret));
|
|
29
|
+
const audience = options.audience ?? environment(TOOL_SERVER_URL_ENV);
|
|
30
|
+
if (!audience) {
|
|
31
|
+
throw new TypeError(
|
|
32
|
+
`verifyToolRequest needs the tool server URL: pass { audience } or set ${TOOL_SERVER_URL_ENV}.`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
const authorization = requestAuthorization(request);
|
|
36
|
+
const match = /^Bearer[ ]+([A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)$/i.exec(
|
|
37
|
+
authorization?.trim() ?? ""
|
|
38
|
+
);
|
|
39
|
+
if (!match) throw new ToolRequestError("token_missing");
|
|
40
|
+
const [header, payload, signature] = match[1].split(".");
|
|
41
|
+
let protectedHeader;
|
|
42
|
+
let claims;
|
|
43
|
+
let signatureBytes;
|
|
44
|
+
try {
|
|
45
|
+
signatureBytes = base64UrlDecode(signature);
|
|
46
|
+
protectedHeader = JSON.parse(utf8(base64UrlDecode(header)));
|
|
47
|
+
claims = JSON.parse(utf8(base64UrlDecode(payload)));
|
|
48
|
+
} catch {
|
|
49
|
+
throw new ToolRequestError("token_malformed");
|
|
50
|
+
}
|
|
51
|
+
if (!protectedHeader || typeof protectedHeader !== "object" || protectedHeader.alg !== "HS256" || !claims || typeof claims !== "object" || Array.isArray(claims)) {
|
|
52
|
+
throw new ToolRequestError("token_malformed");
|
|
53
|
+
}
|
|
54
|
+
const valid = await crypto.subtle.verify(
|
|
55
|
+
"HMAC",
|
|
56
|
+
key,
|
|
57
|
+
signatureBytes,
|
|
58
|
+
new TextEncoder().encode(`${header}.${payload}`)
|
|
59
|
+
);
|
|
60
|
+
if (!valid) throw new ToolRequestError("token_invalid");
|
|
61
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
62
|
+
const { iss, aud, sub, exp, iat, workspace_id, source, tenant } = claims;
|
|
63
|
+
if (iss !== TOOL_TOKEN_ISSUER) throw new ToolRequestError("token_invalid");
|
|
64
|
+
if (typeof exp !== "number" || exp <= now) throw new ToolRequestError("token_expired");
|
|
65
|
+
if (typeof iat !== "number" || iat > now + CLOCK_SKEW_SECONDS) {
|
|
66
|
+
throw new ToolRequestError("token_invalid");
|
|
67
|
+
}
|
|
68
|
+
if (aud !== audience) {
|
|
69
|
+
throw new ToolRequestError("token_audience");
|
|
70
|
+
}
|
|
71
|
+
if (typeof sub !== "string" || !sub || typeof workspace_id !== "string" || !workspace_id || typeof source !== "string" || tenant !== void 0 && typeof tenant !== "string") {
|
|
72
|
+
throw new ToolRequestError("token_invalid");
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
user: sub,
|
|
76
|
+
...tenant !== void 0 ? { tenant } : {},
|
|
77
|
+
workspaceId: workspace_id,
|
|
78
|
+
source,
|
|
79
|
+
expiresAt: new Date(exp * 1e3)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function mintToolToken(input) {
|
|
83
|
+
const ttl = input.ttlSeconds ?? TOOL_TOKEN_DEFAULT_TTL_SECONDS;
|
|
84
|
+
if (!Number.isSafeInteger(ttl) || ttl < 1 || ttl > MAX_TTL_SECONDS) {
|
|
85
|
+
throw new TypeError(`ttlSeconds must be an integer from 1 to ${MAX_TTL_SECONDS}.`);
|
|
86
|
+
}
|
|
87
|
+
const key = await signingKey(resolveToolTokenSecret(input.secret));
|
|
88
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
89
|
+
const header = base64UrlJson({ alg: "HS256", typ: "JWT" });
|
|
90
|
+
const payload = base64UrlJson({
|
|
91
|
+
iss: TOOL_TOKEN_ISSUER,
|
|
92
|
+
aud: input.audience,
|
|
93
|
+
sub: input.user,
|
|
94
|
+
workspace_id: input.workspaceId,
|
|
95
|
+
source: input.source,
|
|
96
|
+
...input.tenant !== void 0 ? { tenant: input.tenant } : {},
|
|
97
|
+
iat: now,
|
|
98
|
+
exp: now + ttl
|
|
99
|
+
});
|
|
100
|
+
const signature = await crypto.subtle.sign(
|
|
101
|
+
"HMAC",
|
|
102
|
+
key,
|
|
103
|
+
new TextEncoder().encode(`${header}.${payload}`)
|
|
104
|
+
);
|
|
105
|
+
const token = `${header}.${payload}.${base64UrlEncode(new Uint8Array(signature))}`;
|
|
106
|
+
if (`Bearer ${token}`.length > MAX_HEADER_VALUE_LENGTH) {
|
|
107
|
+
throw new TypeError(
|
|
108
|
+
`Tool token exceeds Opengeni's ${MAX_HEADER_VALUE_LENGTH}-character header limit; shorten the user, tenant, or URL.`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
return token;
|
|
112
|
+
}
|
|
113
|
+
async function deriveToolTokenKey(secret) {
|
|
114
|
+
return [...await derivedKeyBytes(resolveToolTokenSecret(secret))].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
115
|
+
}
|
|
116
|
+
function resolveToolTokenSecret(secret) {
|
|
117
|
+
const resolved = secret ?? environment("OPENGENI_API_KEY");
|
|
118
|
+
if (!resolved) {
|
|
119
|
+
throw new TypeError(
|
|
120
|
+
"Tool tokens need a signing secret: set OPENGENI_API_KEY, or pass the same `secret` to the session proxy's toolServer and verifyToolRequest."
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return resolved;
|
|
124
|
+
}
|
|
125
|
+
function environment(name) {
|
|
126
|
+
return globalThis.process?.env?.[name] || void 0;
|
|
127
|
+
}
|
|
128
|
+
async function derivedKeyBytes(secret) {
|
|
129
|
+
const root = await crypto.subtle.importKey(
|
|
130
|
+
"raw",
|
|
131
|
+
new TextEncoder().encode(secret),
|
|
132
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
133
|
+
false,
|
|
134
|
+
["sign"]
|
|
135
|
+
);
|
|
136
|
+
return new Uint8Array(
|
|
137
|
+
await crypto.subtle.sign("HMAC", root, new TextEncoder().encode(TOOL_TOKEN_KEY_LABEL))
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
var keys = /* @__PURE__ */ new Map();
|
|
141
|
+
function signingKey(secret) {
|
|
142
|
+
let key = keys.get(secret);
|
|
143
|
+
if (!key) {
|
|
144
|
+
key = (async () => await crypto.subtle.importKey(
|
|
145
|
+
"raw",
|
|
146
|
+
await derivedKeyBytes(secret),
|
|
147
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
148
|
+
false,
|
|
149
|
+
["sign", "verify"]
|
|
150
|
+
))();
|
|
151
|
+
key.catch(() => keys.delete(secret));
|
|
152
|
+
if (keys.size >= 16) keys.delete(keys.keys().next().value);
|
|
153
|
+
keys.set(secret, key);
|
|
154
|
+
}
|
|
155
|
+
return key;
|
|
156
|
+
}
|
|
157
|
+
function requestAuthorization(request) {
|
|
158
|
+
if (typeof Request !== "undefined" && request instanceof Request) {
|
|
159
|
+
return request.headers.get("authorization") ?? void 0;
|
|
160
|
+
}
|
|
161
|
+
const headers = request.headers;
|
|
162
|
+
const raw = headers && typeof headers.get === "function" ? headers.get("authorization") ?? void 0 : headers?.authorization;
|
|
163
|
+
return Array.isArray(raw) ? void 0 : raw;
|
|
164
|
+
}
|
|
165
|
+
function base64UrlJson(value) {
|
|
166
|
+
return base64UrlEncode(new TextEncoder().encode(JSON.stringify(value)));
|
|
167
|
+
}
|
|
168
|
+
function base64UrlEncode(bytes) {
|
|
169
|
+
let binary = "";
|
|
170
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
171
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
172
|
+
}
|
|
173
|
+
function base64UrlDecode(value) {
|
|
174
|
+
const base64 = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
175
|
+
const binary = atob(base64 + "=".repeat((4 - base64.length % 4) % 4));
|
|
176
|
+
const bytes = new Uint8Array(binary.length);
|
|
177
|
+
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
178
|
+
return bytes;
|
|
179
|
+
}
|
|
180
|
+
function utf8(bytes) {
|
|
181
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export {
|
|
185
|
+
TOOL_TOKEN_ISSUER,
|
|
186
|
+
TOOL_TOKEN_KEY_LABEL,
|
|
187
|
+
TOOL_TOKEN_DEFAULT_TTL_SECONDS,
|
|
188
|
+
TOOL_SERVER_URL_ENV,
|
|
189
|
+
ToolRequestError,
|
|
190
|
+
verifyToolRequest,
|
|
191
|
+
mintToolToken,
|
|
192
|
+
deriveToolTokenKey,
|
|
193
|
+
resolveToolTokenSecret
|
|
194
|
+
};
|
|
195
|
+
//# sourceMappingURL=chunk-QGEIL4TR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tool-auth.ts"],"sourcesContent":["/**\n * Per-user credentials for a product's own MCP tool server.\n *\n * `createSessionProxyHandler({ toolServer })` mints a short-lived token for the\n * user its `resolve` hook authenticated, attaches it to each session it creates,\n * and refreshes it on every message, approval, and answer. The product's MCP\n * endpoint calls {@link verifyToolRequest} on every request and scopes all data\n * access to the returned identity, never to ids the model supplied.\n *\n * Wire format (for non-Node verifiers): an HS256 JWT in `Authorization: Bearer`,\n * signed with the hex key from {@link deriveToolTokenKey} (`HMAC-SHA256(key =\n * secret, message = \"opengeni-tool-token:v1\")`, where `secret` is\n * `OPENGENI_API_KEY` unless configured). Give a non-Node verifier that derived\n * key, never the organization key. Claims: `iss` = `\"opengeni-session-proxy\"`,\n * `aud` = the tool server URL, `sub` = the external user id, `workspace_id`,\n * `source`, optional `tenant`, `iat`, `exp`.\n */\n\n/** `iss` of every tool token. */\nexport const TOOL_TOKEN_ISSUER = \"opengeni-session-proxy\";\n/** HMAC message used to derive the signing key from the secret. */\nexport const TOOL_TOKEN_KEY_LABEL = \"opengeni-tool-token:v1\";\n/** Default token lifetime: 24 hours, refreshed on every message, approval, and answer. */\nexport const TOOL_TOKEN_DEFAULT_TTL_SECONDS = 24 * 60 * 60;\nconst MAX_TTL_SECONDS = 7 * 24 * 60 * 60;\n/** Opengeni's per-value limit for session MCP credential headers. */\nconst MAX_HEADER_VALUE_LENGTH = 4096;\n/** Default `toolServer.url` and `verifyToolRequest` audience. */\nexport const TOOL_SERVER_URL_ENV = \"OPENGENI_TOOL_SERVER_URL\";\nconst CLOCK_SKEW_SECONDS = 60;\n\n/** The user a verified tool request acts for. */\nexport type ToolRequestIdentity = {\n /** External user id the session proxy's `resolve` hook authenticated. */\n user: string;\n /** Tenant from `resolve`, when it returned one. */\n tenant?: string | undefined;\n workspaceId: string;\n /** External identity source (same as the proxy's `asUser` source). */\n source: string;\n expiresAt: Date;\n};\n\nexport type VerifyToolRequestOptions = {\n /** Signing secret. Defaults to `OPENGENI_API_KEY`; must match the proxy's. */\n secret?: string | undefined;\n /**\n * Exact tool server URL the token must be issued for (the proxy's\n * `toolServer.url`). Defaults to `OPENGENI_TOOL_SERVER_URL`.\n */\n audience?: string | undefined;\n};\n\n/** A Web `Request`, or a Node/Express request (`headers` plus `originalUrl`/`url`). */\nexport type ToolRequestLike =\n | Request\n | {\n headers: Record<string, string | string[] | undefined>;\n originalUrl?: string | undefined;\n url?: string | undefined;\n };\n\n/** Missing, expired, forged, or misdirected tool token. Respond with `status` (401). */\nexport class ToolRequestError extends Error {\n readonly status = 401;\n constructor(readonly code: string) {\n super(\"Tool request is not authorized.\");\n this.name = \"ToolRequestError\";\n }\n /** A ready 401 response with a `WWW-Authenticate: Bearer` challenge. */\n toResponse(): Response {\n return new Response(JSON.stringify({ error: { code: this.code, message: this.message } }), {\n status: 401,\n headers: {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"WWW-Authenticate\": 'Bearer error=\"invalid_token\"',\n },\n });\n }\n}\n\n/**\n * Verify the tool token on one MCP request and return who it acts for.\n * Throws {@link ToolRequestError} (401) for every invalid token. Call it on\n * every request, before any tool runs.\n *\n * ```ts\n * const user = await verifyToolRequest(request); // { user, tenant, workspaceId }\n * ```\n */\nexport async function verifyToolRequest(\n request: ToolRequestLike,\n options: VerifyToolRequestOptions = {},\n): Promise<ToolRequestIdentity> {\n const key = await signingKey(resolveToolTokenSecret(options.secret));\n const audience = options.audience ?? environment(TOOL_SERVER_URL_ENV);\n if (!audience) {\n throw new TypeError(\n `verifyToolRequest needs the tool server URL: pass { audience } or set ${TOOL_SERVER_URL_ENV}.`,\n );\n }\n const authorization = requestAuthorization(request);\n const match = /^Bearer[ ]+([A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+)$/i.exec(\n authorization?.trim() ?? \"\",\n );\n if (!match) throw new ToolRequestError(\"token_missing\");\n const [header, payload, signature] = match[1]!.split(\".\") as [string, string, string];\n let protectedHeader: unknown;\n let claims: Record<string, unknown>;\n let signatureBytes: Uint8Array<ArrayBuffer>;\n try {\n signatureBytes = base64UrlDecode(signature);\n protectedHeader = JSON.parse(utf8(base64UrlDecode(header)));\n claims = JSON.parse(utf8(base64UrlDecode(payload)));\n } catch {\n throw new ToolRequestError(\"token_malformed\");\n }\n if (\n !protectedHeader ||\n typeof protectedHeader !== \"object\" ||\n (protectedHeader as { alg?: unknown }).alg !== \"HS256\" ||\n !claims ||\n typeof claims !== \"object\" ||\n Array.isArray(claims)\n ) {\n throw new ToolRequestError(\"token_malformed\");\n }\n const valid = await crypto.subtle.verify(\n \"HMAC\",\n key,\n signatureBytes,\n new TextEncoder().encode(`${header}.${payload}`),\n );\n if (!valid) throw new ToolRequestError(\"token_invalid\");\n const now = Math.floor(Date.now() / 1000);\n const { iss, aud, sub, exp, iat, workspace_id, source, tenant } = claims;\n if (iss !== TOOL_TOKEN_ISSUER) throw new ToolRequestError(\"token_invalid\");\n if (typeof exp !== \"number\" || exp <= now) throw new ToolRequestError(\"token_expired\");\n if (typeof iat !== \"number\" || iat > now + CLOCK_SKEW_SECONDS) {\n throw new ToolRequestError(\"token_invalid\");\n }\n if (aud !== audience) {\n throw new ToolRequestError(\"token_audience\");\n }\n if (\n typeof sub !== \"string\" ||\n !sub ||\n typeof workspace_id !== \"string\" ||\n !workspace_id ||\n typeof source !== \"string\" ||\n (tenant !== undefined && typeof tenant !== \"string\")\n ) {\n throw new ToolRequestError(\"token_invalid\");\n }\n return {\n user: sub,\n ...(tenant !== undefined ? { tenant } : {}),\n workspaceId: workspace_id,\n source,\n expiresAt: new Date(exp * 1000),\n };\n}\n\n/** Mint one tool token. The session proxy calls this; products rarely need to. */\nexport async function mintToolToken(input: {\n /** Tool server URL; becomes `aud`. */\n audience: string;\n user: string;\n tenant?: string | undefined;\n workspaceId: string;\n source: string;\n secret?: string | undefined;\n ttlSeconds?: number | undefined;\n}): Promise<string> {\n const ttl = input.ttlSeconds ?? TOOL_TOKEN_DEFAULT_TTL_SECONDS;\n if (!Number.isSafeInteger(ttl) || ttl < 1 || ttl > MAX_TTL_SECONDS) {\n throw new TypeError(`ttlSeconds must be an integer from 1 to ${MAX_TTL_SECONDS}.`);\n }\n const key = await signingKey(resolveToolTokenSecret(input.secret));\n const now = Math.floor(Date.now() / 1000);\n const header = base64UrlJson({ alg: \"HS256\", typ: \"JWT\" });\n const payload = base64UrlJson({\n iss: TOOL_TOKEN_ISSUER,\n aud: input.audience,\n sub: input.user,\n workspace_id: input.workspaceId,\n source: input.source,\n ...(input.tenant !== undefined ? { tenant: input.tenant } : {}),\n iat: now,\n exp: now + ttl,\n });\n const signature = await crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(`${header}.${payload}`),\n );\n const token = `${header}.${payload}.${base64UrlEncode(new Uint8Array(signature))}`;\n if (`Bearer ${token}`.length > MAX_HEADER_VALUE_LENGTH) {\n throw new TypeError(\n `Tool token exceeds Opengeni's ${MAX_HEADER_VALUE_LENGTH}-character header limit; shorten the user, tenant, or URL.`,\n );\n }\n return token;\n}\n\n/**\n * The hex HS256 key tool tokens are signed with. Give this (not the\n * organization key) to a tool server written in Python, Ruby, Go, and so on.\n */\nexport async function deriveToolTokenKey(secret?: string): Promise<string> {\n return [...(await derivedKeyBytes(resolveToolTokenSecret(secret)))]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/** The configured secret, else `OPENGENI_API_KEY`. Throws when neither is set. */\nexport function resolveToolTokenSecret(secret: string | undefined): string {\n const resolved = secret ?? environment(\"OPENGENI_API_KEY\");\n if (!resolved) {\n throw new TypeError(\n \"Tool tokens need a signing secret: set OPENGENI_API_KEY, or pass the same `secret` to the session proxy's toolServer and verifyToolRequest.\",\n );\n }\n return resolved;\n}\n\nfunction environment(name: string): string | undefined {\n return (\n (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env?.[\n name\n ] || undefined\n );\n}\n\nasync function derivedKeyBytes(secret: string): Promise<Uint8Array<ArrayBuffer>> {\n const root = await crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n return new Uint8Array(\n await crypto.subtle.sign(\"HMAC\", root, new TextEncoder().encode(TOOL_TOKEN_KEY_LABEL)),\n );\n}\n\nconst keys = new Map<string, Promise<CryptoKey>>();\n\n/** HS256 key derived from the secret, so the raw secret never signs tokens itself. */\nfunction signingKey(secret: string): Promise<CryptoKey> {\n let key = keys.get(secret);\n if (!key) {\n key = (async () =>\n await crypto.subtle.importKey(\n \"raw\",\n await derivedKeyBytes(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\", \"verify\"],\n ))();\n key.catch(() => keys.delete(secret));\n if (keys.size >= 16) keys.delete(keys.keys().next().value!);\n keys.set(secret, key);\n }\n return key;\n}\n\nfunction requestAuthorization(request: ToolRequestLike): string | undefined {\n if (typeof Request !== \"undefined\" && request instanceof Request) {\n return request.headers.get(\"authorization\") ?? undefined;\n }\n const headers = (request as Exclude<ToolRequestLike, Request>).headers as unknown;\n const raw =\n headers && typeof (headers as Headers).get === \"function\"\n ? ((headers as Headers).get(\"authorization\") ?? undefined)\n : (headers as Record<string, string | string[] | undefined>)?.authorization;\n return Array.isArray(raw) ? undefined : raw;\n}\n\nfunction base64UrlJson(value: unknown): string {\n return base64UrlEncode(new TextEncoder().encode(JSON.stringify(value)));\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction base64UrlDecode(value: string): Uint8Array<ArrayBuffer> {\n const base64 = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const binary = atob(base64 + \"=\".repeat((4 - (base64.length % 4)) % 4));\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);\n return bytes;\n}\n\nfunction utf8(bytes: Uint8Array): string {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n}\n"],"mappings":"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","names":[]}
|