openbotcity-mcp 0.2.44 → 0.2.51
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/build/remote.d.ts +14 -0
- package/build/remote.d.ts.map +1 -1
- package/build/remote.js +44 -14
- package/build/remote.js.map +1 -1
- package/build/server.d.ts +6 -1
- package/build/server.d.ts.map +1 -1
- package/build/server.js +8 -3
- package/build/server.js.map +1 -1
- package/build/services/credentials.d.ts +17 -2
- package/build/services/credentials.d.ts.map +1 -1
- package/build/services/credentials.js +48 -10
- package/build/services/credentials.js.map +1 -1
- package/build/services/resolveToken.d.ts +8 -0
- package/build/services/resolveToken.d.ts.map +1 -0
- package/build/services/resolveToken.js +25 -0
- package/build/services/resolveToken.js.map +1 -0
- package/build/services/sessionStore.d.ts +2 -2
- package/build/services/sessionStore.d.ts.map +1 -1
- package/build/services/sessionStore.js +10 -5
- package/build/services/sessionStore.js.map +1 -1
- package/build/tools/action.d.ts +19 -1
- package/build/tools/action.d.ts.map +1 -1
- package/build/tools/action.js +39 -46
- package/build/tools/action.js.map +1 -1
- package/build/tools/heartbeat.d.ts +1 -1
- package/build/tools/heartbeat.d.ts.map +1 -1
- package/build/tools/heartbeat.js +16 -9
- package/build/tools/heartbeat.js.map +1 -1
- package/build/tools/legacyJwt.d.ts +14 -0
- package/build/tools/legacyJwt.d.ts.map +1 -0
- package/build/tools/legacyJwt.js +16 -0
- package/build/tools/legacyJwt.js.map +1 -0
- package/build/tools/query.d.ts +5 -0
- package/build/tools/query.d.ts.map +1 -0
- package/build/tools/query.js +103 -0
- package/build/tools/query.js.map +1 -0
- package/build/tools/reconnect.d.ts.map +1 -1
- package/build/tools/reconnect.js +3 -2
- package/build/tools/reconnect.js.map +1 -1
- package/build/tools/register.d.ts.map +1 -1
- package/build/tools/register.js +6 -4
- package/build/tools/register.js.map +1 -1
- package/build/tools/text.d.ts +5 -0
- package/build/tools/text.d.ts.map +1 -0
- package/build/tools/text.js +25 -0
- package/build/tools/text.js.map +1 -0
- package/build/tools/toolTips.d.ts +16 -0
- package/build/tools/toolTips.d.ts.map +1 -0
- package/build/tools/toolTips.js +56 -0
- package/build/tools/toolTips.js.map +1 -0
- package/package.json +1 -1
package/build/remote.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
export interface Env {
|
|
2
2
|
UPSTASH_REDIS_REST_URL?: string;
|
|
3
3
|
UPSTASH_REDIS_REST_TOKEN?: string;
|
|
4
|
+
/** Domain-verification token issued by OpenAI's plugins dashboard (wrangler secret). */
|
|
5
|
+
OPENAI_APPS_CHALLENGE?: string;
|
|
4
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Which server a path serves. /mcp is the everyday server. /directory/mcp is the
|
|
9
|
+
* variant listed in Anthropic's directory (no AI-media generation). /plugin/mcp is
|
|
10
|
+
* the variant listed in OpenAI's Plugins Directory: every tool of /mcp, but no
|
|
11
|
+
* raw-token argument in any tool input (session handles only).
|
|
12
|
+
*/
|
|
13
|
+
export declare function doorFor(pathname: string): {
|
|
14
|
+
profile: "full" | "directory";
|
|
15
|
+
legacyJwt: boolean;
|
|
16
|
+
} | null;
|
|
17
|
+
/** OpenAI domain verification: the dashboard's token, exactly, as plain text. 404 until the secret is set. */
|
|
18
|
+
export declare function openAiChallengeResponse(env: Env): Response;
|
|
5
19
|
declare const _default: {
|
|
6
20
|
fetch(request: Request, env: Env): Promise<Response>;
|
|
7
21
|
};
|
package/build/remote.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,GAAG;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,GAAG;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,wFAAwF;IACxF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAKtG;AAED,8GAA8G;AAC9G,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ,CAO1D;;mBAGsB,OAAO,OAAO,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;;AAD5D,wBAgDE"}
|
package/build/remote.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
2
2
|
import { createServer } from "./server.js";
|
|
3
|
-
import {
|
|
3
|
+
import { runInRequestScope } from "./services/credentials.js";
|
|
4
4
|
import { createSessionStore } from "./services/sessionStore.js";
|
|
5
5
|
const CORS_HEADERS = {
|
|
6
6
|
"Access-Control-Allow-Origin": "*",
|
|
@@ -14,6 +14,31 @@ function addCorsHeaders(response) {
|
|
|
14
14
|
headers.set(k, v);
|
|
15
15
|
return new Response(response.body, { status: response.status, headers });
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Which server a path serves. /mcp is the everyday server. /directory/mcp is the
|
|
19
|
+
* variant listed in Anthropic's directory (no AI-media generation). /plugin/mcp is
|
|
20
|
+
* the variant listed in OpenAI's Plugins Directory: every tool of /mcp, but no
|
|
21
|
+
* raw-token argument in any tool input (session handles only).
|
|
22
|
+
*/
|
|
23
|
+
export function doorFor(pathname) {
|
|
24
|
+
if (pathname === "/mcp")
|
|
25
|
+
return { profile: "full", legacyJwt: true };
|
|
26
|
+
if (pathname === "/directory/mcp")
|
|
27
|
+
return { profile: "directory", legacyJwt: true };
|
|
28
|
+
if (pathname === "/plugin/mcp")
|
|
29
|
+
return { profile: "full", legacyJwt: false };
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
/** OpenAI domain verification: the dashboard's token, exactly, as plain text. 404 until the secret is set. */
|
|
33
|
+
export function openAiChallengeResponse(env) {
|
|
34
|
+
const token = env.OPENAI_APPS_CHALLENGE?.trim();
|
|
35
|
+
if (!token)
|
|
36
|
+
return new Response("Not found", { status: 404, headers: CORS_HEADERS });
|
|
37
|
+
return new Response(token, {
|
|
38
|
+
status: 200,
|
|
39
|
+
headers: { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store", ...CORS_HEADERS },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
17
42
|
export default {
|
|
18
43
|
async fetch(request, env) {
|
|
19
44
|
const url = new URL(request.url);
|
|
@@ -27,24 +52,29 @@ export default {
|
|
|
27
52
|
headers: { "Content-Type": "application/json", ...CORS_HEADERS },
|
|
28
53
|
});
|
|
29
54
|
}
|
|
55
|
+
if (url.pathname === "/.well-known/openai-apps-challenge" && (request.method === "GET" || request.method === "HEAD")) {
|
|
56
|
+
return openAiChallengeResponse(env);
|
|
57
|
+
}
|
|
30
58
|
// MCP endpoint — stateless: new server + transport per request
|
|
31
59
|
// CF Workers are ephemeral, no in-memory session storage
|
|
32
|
-
|
|
60
|
+
// Three doors, one server (see doorFor).
|
|
61
|
+
const door = doorFor(url.pathname);
|
|
62
|
+
if (door) {
|
|
63
|
+
// Extract Bearer token from Authorization header (e.g. Codex sends OPENBOTCITY_JWT)
|
|
64
|
+
const authHeader = request.headers.get("authorization");
|
|
65
|
+
const bearerToken = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : undefined;
|
|
33
66
|
try {
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
clearRequestToken();
|
|
44
|
-
return addCorsHeaders(response);
|
|
67
|
+
// Every credential this request touches lives in its own scope: requests on a
|
|
68
|
+
// shared isolate interleave, so nothing may sit in module state (see credentials.ts).
|
|
69
|
+
return await runInRequestScope(bearerToken, async () => {
|
|
70
|
+
const sessionStore = createSessionStore(env);
|
|
71
|
+
const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
72
|
+
const server = createServer(bearerToken, sessionStore, door.profile, { legacyJwt: door.legacyJwt });
|
|
73
|
+
await server.connect(transport);
|
|
74
|
+
return addCorsHeaders(await transport.handleRequest(request));
|
|
75
|
+
});
|
|
45
76
|
}
|
|
46
77
|
catch (err) {
|
|
47
|
-
clearRequestToken();
|
|
48
78
|
return new Response(JSON.stringify({ error: err instanceof Error ? err.message : "Internal error" }), { status: 500, headers: { "Content-Type": "application/json", ...CORS_HEADERS } });
|
|
49
79
|
}
|
|
50
80
|
}
|
package/build/remote.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote.js","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wCAAwC,EAAE,MAAM,+DAA+D,CAAC;AACzH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,YAAY,GAA2B;IAC3C,6BAA6B,EAAE,GAAG;IAClC,8BAA8B,EAAE,4BAA4B;IAC5D,8BAA8B,EAAE,mEAAmE;IACnG,+BAA+B,EAAE,sCAAsC;CACxE,CAAC;AAEF,SAAS,cAAc,CAAC,QAAkB;IACxC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrE,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAC3E,CAAC;
|
|
1
|
+
{"version":3,"file":"remote.js","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"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"}
|
package/build/server.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { type ServerProfile } from "./tools/action.js";
|
|
2
3
|
import { type SessionStore } from "./services/sessionStore.js";
|
|
3
4
|
/**
|
|
4
5
|
* Create a configured MCP server instance.
|
|
5
6
|
* @param bearerToken Optional Bearer token from HTTP transport (scoped to this request only).
|
|
7
|
+
* @param profile "full" (default, /mcp) or "directory" (/directory/mcp: no AI-media generation, for Anthropic's directory listing).
|
|
8
|
+
* @param options.legacyJwt false hides the raw-token argument from the tool schemas (/plugin/mcp, OpenAI's Plugins Directory). Default true.
|
|
6
9
|
* @param sessionStore Optional Redis-backed session store. If omitted, a no-op store is used
|
|
7
10
|
* (stdio/local mode falls back to the filesystem credential cache).
|
|
8
11
|
*/
|
|
9
|
-
export declare function createServer(bearerToken?: string, sessionStore?: SessionStore
|
|
12
|
+
export declare function createServer(bearerToken?: string, sessionStore?: SessionStore, profile?: ServerProfile, options?: {
|
|
13
|
+
legacyJwt?: boolean;
|
|
14
|
+
}): McpServer;
|
|
10
15
|
//# sourceMappingURL=server.d.ts.map
|
package/build/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAKnE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAEnF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE,YAAY,EAC3B,OAAO,GAAE,aAAsB,EAC/B,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACpC,SAAS,CA4BX"}
|
package/build/server.js
CHANGED
|
@@ -3,6 +3,7 @@ import { registerTool } from "./tools/register.js";
|
|
|
3
3
|
import { reconnectTool } from "./tools/reconnect.js";
|
|
4
4
|
import { heartbeatTool } from "./tools/heartbeat.js";
|
|
5
5
|
import { actionTool } from "./tools/action.js";
|
|
6
|
+
import { queryTool } from "./tools/query.js";
|
|
6
7
|
import { skillResource } from "./resources/skill.js";
|
|
7
8
|
import { heartbeatDocResource } from "./resources/heartbeat-doc.js";
|
|
8
9
|
import { setRequestToken, clearRequestToken, setStatelessMode } from "./services/credentials.js";
|
|
@@ -10,10 +11,13 @@ import { createSessionStore } from "./services/sessionStore.js";
|
|
|
10
11
|
/**
|
|
11
12
|
* Create a configured MCP server instance.
|
|
12
13
|
* @param bearerToken Optional Bearer token from HTTP transport (scoped to this request only).
|
|
14
|
+
* @param profile "full" (default, /mcp) or "directory" (/directory/mcp: no AI-media generation, for Anthropic's directory listing).
|
|
15
|
+
* @param options.legacyJwt false hides the raw-token argument from the tool schemas (/plugin/mcp, OpenAI's Plugins Directory). Default true.
|
|
13
16
|
* @param sessionStore Optional Redis-backed session store. If omitted, a no-op store is used
|
|
14
17
|
* (stdio/local mode falls back to the filesystem credential cache).
|
|
15
18
|
*/
|
|
16
|
-
export function createServer(bearerToken, sessionStore) {
|
|
19
|
+
export function createServer(bearerToken, sessionStore, profile = "full", options = {}) {
|
|
20
|
+
const legacyJwt = options.legacyJwt ?? true;
|
|
17
21
|
// Mark stateless mode — memory won't persist between requests in CF Workers
|
|
18
22
|
setStatelessMode();
|
|
19
23
|
// Scope token to this request — avoids cross-user leakage on shared CF Worker isolates
|
|
@@ -30,8 +34,9 @@ export function createServer(bearerToken, sessionStore) {
|
|
|
30
34
|
});
|
|
31
35
|
registerTool(server, store);
|
|
32
36
|
reconnectTool(server, store);
|
|
33
|
-
heartbeatTool(server, store);
|
|
34
|
-
|
|
37
|
+
heartbeatTool(server, store, legacyJwt);
|
|
38
|
+
queryTool(server, store, legacyJwt);
|
|
39
|
+
actionTool(server, store, profile, legacyJwt);
|
|
35
40
|
skillResource(server);
|
|
36
41
|
heartbeatDocResource(server);
|
|
37
42
|
return server;
|
package/build/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAsB,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAAE,kBAAkB,EAAqB,MAAM,4BAA4B,CAAC;AAEnF;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,WAAoB,EACpB,YAA2B,EAC3B,UAAyB,MAAM,EAC/B,UAAmC,EAAE;IAErC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;IAC5C,4EAA4E;IAC5E,gBAAgB,EAAE,CAAC;IAEnB,uFAAuF;IACvF,IAAI,WAAW,EAAE,CAAC;QAChB,eAAe,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN,iBAAiB,EAAE,CAAC;IACtB,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAErD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5B,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7B,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACxC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACpC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC9C,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE7B,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -4,9 +4,13 @@ interface StoredCredentials {
|
|
|
4
4
|
display_name?: string;
|
|
5
5
|
slug?: string;
|
|
6
6
|
}
|
|
7
|
-
/**
|
|
7
|
+
/** Run one remote request with its own credential scope. `bearer` is the Authorization header token, if any. */
|
|
8
|
+
export declare function runInRequestScope<T>(bearer: string | undefined, fn: () => Promise<T>): Promise<T>;
|
|
9
|
+
/** True while handling a request of the remote server. */
|
|
10
|
+
export declare function isRemoteRequest(): boolean;
|
|
11
|
+
/** Set the Bearer token for the current request (scope-local on the remote server). */
|
|
8
12
|
export declare function setRequestToken(token: string): void;
|
|
9
|
-
/** Clear the request
|
|
13
|
+
/** Clear the current request's token (scope-local on the remote server). */
|
|
10
14
|
export declare function clearRequestToken(): void;
|
|
11
15
|
/** Mark that we're running in stateless mode (no persistent memory between requests). */
|
|
12
16
|
export declare function setStatelessMode(): void;
|
|
@@ -28,5 +32,16 @@ export declare function getToken(): string | null;
|
|
|
28
32
|
export declare function getOrCreateAgentKey(): string | null;
|
|
29
33
|
/** Get stored bot info (if available). */
|
|
30
34
|
export declare function getStoredBotInfo(): Omit<StoredCredentials, "jwt"> | null;
|
|
35
|
+
/**
|
|
36
|
+
* A fresh, never-reused agent_key for a registration made through the remote server.
|
|
37
|
+
*
|
|
38
|
+
* The City API hands an UNCLAIMED agent back to any keyless caller who registers
|
|
39
|
+
* with its exact name (meant as retry recovery). The remote server has no way to
|
|
40
|
+
* tell a retry from a stranger: every user arrives from the same address with no
|
|
41
|
+
* stored key. A key that matches nothing makes the API answer NAME_TAKEN instead,
|
|
42
|
+
* so one user can never be handed another user's agent by asking for its name.
|
|
43
|
+
* Their own agent is recovered with openbotcity_reconnect (slug + code or email).
|
|
44
|
+
*/
|
|
45
|
+
export declare function oneTimeAgentKey(): string;
|
|
31
46
|
export {};
|
|
32
47
|
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/services/credentials.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/services/credentials.ts"],"names":[],"mappings":"AAUA,UAAU,iBAAiB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAiBD,gHAAgH;AAChH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAEjG;AAED,0DAA0D;AAC1D,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAQD,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAQnD;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,IAAI,IAAI,CAQxC;AAED,yFAAyF;AACzF,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,wCAAwC;AACxC,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,6FAA6F;AAC7F,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAc/D;AAED,+EAA+E;AAC/E,wBAAgB,QAAQ,IAAI,MAAM,GAAG,IAAI,CA6BxC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAgBnD;AAED,0CAA0C;AAC1C,wBAAgB,gBAAgB,IAAI,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,GAAG,IAAI,CAOxE;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|
|
@@ -2,25 +2,41 @@ import { join } from "node:path";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
6
|
const CRED_DIR = join(homedir(), ".openbotcity");
|
|
6
7
|
const CRED_FILE = join(CRED_DIR, "credentials.json");
|
|
7
8
|
const AGENT_KEY_FILE = join(CRED_DIR, "agent_key");
|
|
8
9
|
let cachedToken = null;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const requestScope = new AsyncLocalStorage();
|
|
11
|
+
/** Run one remote request with its own credential scope. `bearer` is the Authorization header token, if any. */
|
|
12
|
+
export function runInRequestScope(bearer, fn) {
|
|
13
|
+
return requestScope.run({ token: bearer ?? null }, fn);
|
|
14
|
+
}
|
|
15
|
+
/** True while handling a request of the remote server. */
|
|
16
|
+
export function isRemoteRequest() {
|
|
17
|
+
return requestScope.getStore() !== undefined;
|
|
18
|
+
}
|
|
19
|
+
/** Legacy module-level request token (stdio / callers outside a request scope). */
|
|
14
20
|
let requestToken = null;
|
|
15
21
|
/** Whether we're running in stateless mode (CF Workers) where memory doesn't persist between requests. */
|
|
16
22
|
let statelessMode = false;
|
|
17
|
-
/** Set
|
|
23
|
+
/** Set the Bearer token for the current request (scope-local on the remote server). */
|
|
18
24
|
export function setRequestToken(token) {
|
|
25
|
+
const scope = requestScope.getStore();
|
|
26
|
+
if (scope) {
|
|
27
|
+
scope.token = token;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
19
30
|
requestToken = token;
|
|
20
31
|
statelessMode = true; // If setRequestToken is called, we're in remote/stateless mode
|
|
21
32
|
}
|
|
22
|
-
/** Clear the request
|
|
33
|
+
/** Clear the current request's token (scope-local on the remote server). */
|
|
23
34
|
export function clearRequestToken() {
|
|
35
|
+
const scope = requestScope.getStore();
|
|
36
|
+
if (scope) {
|
|
37
|
+
scope.token = null;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
24
40
|
requestToken = null;
|
|
25
41
|
cachedToken = null;
|
|
26
42
|
}
|
|
@@ -30,14 +46,20 @@ export function setStatelessMode() {
|
|
|
30
46
|
}
|
|
31
47
|
/** Check if we're in stateless mode. */
|
|
32
48
|
export function isStateless() {
|
|
33
|
-
return statelessMode;
|
|
49
|
+
return statelessMode || isRemoteRequest();
|
|
34
50
|
}
|
|
35
51
|
/** @deprecated Use setRequestToken instead. Kept for backwards compat with older callers. */
|
|
36
52
|
export function setBearerToken(token) {
|
|
37
|
-
|
|
53
|
+
setRequestToken(token);
|
|
38
54
|
}
|
|
39
55
|
/** Store JWT and optional bot info to disk. Falls back to memory-only if filesystem unavailable. */
|
|
40
56
|
export function storeCredentials(creds) {
|
|
57
|
+
const scope = requestScope.getStore();
|
|
58
|
+
if (scope) {
|
|
59
|
+
// Remote server: visible to the rest of THIS request only. Never the module cache, never disk.
|
|
60
|
+
scope.token = creds.jwt;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
41
63
|
cachedToken = creds.jwt;
|
|
42
64
|
try {
|
|
43
65
|
mkdirSync(CRED_DIR, { recursive: true });
|
|
@@ -49,6 +71,9 @@ export function storeCredentials(creds) {
|
|
|
49
71
|
}
|
|
50
72
|
/** Get JWT token. Priority: request-scoped > memory cache > env var > file. */
|
|
51
73
|
export function getToken() {
|
|
74
|
+
const scope = requestScope.getStore();
|
|
75
|
+
if (scope)
|
|
76
|
+
return scope.token; // remote: this request's token or nothing
|
|
52
77
|
if (requestToken)
|
|
53
78
|
return requestToken;
|
|
54
79
|
if (cachedToken)
|
|
@@ -85,7 +110,7 @@ export function getToken() {
|
|
|
85
110
|
* Returns null in stateless mode (CF Workers) or when the filesystem is unavailable.
|
|
86
111
|
*/
|
|
87
112
|
export function getOrCreateAgentKey() {
|
|
88
|
-
if (
|
|
113
|
+
if (isStateless())
|
|
89
114
|
return null;
|
|
90
115
|
try {
|
|
91
116
|
const existing = readFileSync(AGENT_KEY_FILE, "utf-8").trim();
|
|
@@ -115,4 +140,17 @@ export function getStoredBotInfo() {
|
|
|
115
140
|
return null;
|
|
116
141
|
}
|
|
117
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* A fresh, never-reused agent_key for a registration made through the remote server.
|
|
145
|
+
*
|
|
146
|
+
* The City API hands an UNCLAIMED agent back to any keyless caller who registers
|
|
147
|
+
* with its exact name (meant as retry recovery). The remote server has no way to
|
|
148
|
+
* tell a retry from a stranger: every user arrives from the same address with no
|
|
149
|
+
* stored key. A key that matches nothing makes the API answer NAME_TAKEN instead,
|
|
150
|
+
* so one user can never be handed another user's agent by asking for its name.
|
|
151
|
+
* Their own agent is recovered with openbotcity_reconnect (slug + code or email).
|
|
152
|
+
*/
|
|
153
|
+
export function oneTimeAgentKey() {
|
|
154
|
+
return `obck_once_${randomUUID().replace(/-/g, "")}`;
|
|
155
|
+
}
|
|
118
156
|
//# sourceMappingURL=credentials.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/services/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/services/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SessionStore } from "./sessionStore.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the bearer token for a tool call from, in order: an explicit session
|
|
4
|
+
* handle (obc_...), a legacy raw JWT, the session store, or the local credential
|
|
5
|
+
* cache (stdio mode). Returns null when nothing authenticates the call.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveToken(session: string | undefined, jwt: string | undefined, sessionStore: SessionStore): Promise<string | null>;
|
|
8
|
+
//# sourceMappingURL=resolveToken.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveToken.d.ts","sourceRoot":"","sources":["../../src/services/resolveToken.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getToken } from "./credentials.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the bearer token for a tool call from, in order: an explicit session
|
|
4
|
+
* handle (obc_...), a legacy raw JWT, the session store, or the local credential
|
|
5
|
+
* cache (stdio mode). Returns null when nothing authenticates the call.
|
|
6
|
+
*/
|
|
7
|
+
export async function resolveToken(session, jwt, sessionStore) {
|
|
8
|
+
let token = null;
|
|
9
|
+
let handle = session || null;
|
|
10
|
+
if (jwt && jwt.startsWith("obc_")) {
|
|
11
|
+
handle = jwt;
|
|
12
|
+
}
|
|
13
|
+
else if (jwt) {
|
|
14
|
+
token = jwt;
|
|
15
|
+
}
|
|
16
|
+
if (!token && handle) {
|
|
17
|
+
const payload = await sessionStore.get(handle);
|
|
18
|
+
if (payload)
|
|
19
|
+
token = payload.jwt;
|
|
20
|
+
}
|
|
21
|
+
if (!token)
|
|
22
|
+
token = getToken();
|
|
23
|
+
return token;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=resolveToken.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveToken.js","sourceRoot":"","sources":["../../src/services/resolveToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAA2B,EAC3B,GAAuB,EACvB,YAA0B;IAE1B,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,IAAI,MAAM,GAAkB,OAAO,IAAI,IAAI,CAAC;IAC5C,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,CAAC;IACf,CAAC;SAAM,IAAI,GAAG,EAAE,CAAC;QACf,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,MAAM,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,OAAO;YAAE,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC;IACnC,CAAC;IACD,IAAI,CAAC,KAAK;QAAE,KAAK,GAAG,QAAQ,EAAE,CAAC;IAC/B,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* call, which fails in practice — models truncate, redact, or omit the token.
|
|
9
9
|
*
|
|
10
10
|
* Fix: store the JWT server-side in Upstash Redis keyed by a short opaque
|
|
11
|
-
* handle (obc_<
|
|
11
|
+
* handle (obc_<24hex>). The model only has to remember the handle — 28 chars,
|
|
12
12
|
* no dots, doesn't look like a credential, so it's not mistaken for PII.
|
|
13
13
|
*
|
|
14
14
|
* Uses the Upstash REST API directly via fetch — no SDK dep needed.
|
|
@@ -28,7 +28,7 @@ export interface SessionStore {
|
|
|
28
28
|
/** Delete a session handle (best-effort). */
|
|
29
29
|
del(handle: string): Promise<void>;
|
|
30
30
|
}
|
|
31
|
-
/** Validate that a string looks like a session handle. */
|
|
31
|
+
/** Validate that a string looks like a session handle (24 hex; 12 hex for handles issued before 0.2.50, until they expire). */
|
|
32
32
|
export declare function isSessionHandle(value: string): boolean;
|
|
33
33
|
export declare function createSessionStore(env: {
|
|
34
34
|
UPSTASH_REDIS_REST_URL?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../src/services/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,gHAAgH;IAChH,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1E,sGAAsG;IACtG,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACpD,6CAA6C;IAC7C,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;
|
|
1
|
+
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../src/services/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,gHAAgH;IAChH,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1E,sGAAsG;IACtG,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACpD,6CAA6C;IAC7C,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAoBD,+HAA+H;AAC/H,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;AA8DD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE;IACtC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC,GAAG,YAAY,CAKf"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* call, which fails in practice — models truncate, redact, or omit the token.
|
|
9
9
|
*
|
|
10
10
|
* Fix: store the JWT server-side in Upstash Redis keyed by a short opaque
|
|
11
|
-
* handle (obc_<
|
|
11
|
+
* handle (obc_<24hex>). The model only has to remember the handle — 28 chars,
|
|
12
12
|
* no dots, doesn't look like a credential, so it's not mistaken for PII.
|
|
13
13
|
*
|
|
14
14
|
* Uses the Upstash REST API directly via fetch — no SDK dep needed.
|
|
@@ -16,18 +16,23 @@
|
|
|
16
16
|
const KEY_PREFIX = "mcp_sess:";
|
|
17
17
|
const DEFAULT_TTL = 7 * 24 * 60 * 60; // 7 days
|
|
18
18
|
const HANDLE_PREFIX = "obc_";
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Generate an opaque handle: 24 hex chars (96 bits). The handle is the only thing
|
|
21
|
+
* standing between a caller and an agent for 7 days, so it must not be guessable;
|
|
22
|
+
* the earlier 12-char handles (48 bits) were too short for that once many sessions
|
|
23
|
+
* are live at the same time.
|
|
24
|
+
*/
|
|
20
25
|
function generateHandle() {
|
|
21
|
-
const bytes = new Uint8Array(
|
|
26
|
+
const bytes = new Uint8Array(12);
|
|
22
27
|
crypto.getRandomValues(bytes);
|
|
23
28
|
let hex = "";
|
|
24
29
|
for (const b of bytes)
|
|
25
30
|
hex += b.toString(16).padStart(2, "0");
|
|
26
31
|
return HANDLE_PREFIX + hex;
|
|
27
32
|
}
|
|
28
|
-
/** Validate that a string looks like a session handle. */
|
|
33
|
+
/** Validate that a string looks like a session handle (24 hex; 12 hex for handles issued before 0.2.50, until they expire). */
|
|
29
34
|
export function isSessionHandle(value) {
|
|
30
|
-
return /^obc_[0-9a-f]{12}$/i.test(value);
|
|
35
|
+
return /^obc_(?:[0-9a-f]{12}|[0-9a-f]{24})$/i.test(value);
|
|
31
36
|
}
|
|
32
37
|
class UpstashSessionStore {
|
|
33
38
|
url;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionStore.js","sourceRoot":"","sources":["../../src/services/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAmBH,MAAM,UAAU,GAAG,WAAW,CAAC;AAC/B,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,SAAS;AAC/C,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B
|
|
1
|
+
{"version":3,"file":"sessionStore.js","sourceRoot":"","sources":["../../src/services/sessionStore.ts"],"names":[],"mappings":"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"}
|
package/build/tools/action.d.ts
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { SessionStore } from "../services/sessionStore.js";
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Server profile. "full" is the everyday server at /mcp. "directory" is the
|
|
5
|
+
* variant listed in Anthropic's directory, whose review rules do not accept
|
|
6
|
+
* connectors that generate images, video or audio through AI models: those
|
|
7
|
+
* three routes are hidden from the quick reference and refused at call time.
|
|
8
|
+
*/
|
|
9
|
+
export type ServerProfile = "full" | "directory";
|
|
10
|
+
/**
|
|
11
|
+
* Maps friendly MCP action paths to real Worker API endpoints.
|
|
12
|
+
* Some actions need body-to-URL rewriting (e.g. react needs artifact ID in the path).
|
|
13
|
+
*/
|
|
14
|
+
interface ResolvedEndpoint {
|
|
15
|
+
path: string;
|
|
16
|
+
body?: Record<string, unknown>;
|
|
17
|
+
plainText?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function resolveEndpoint(endpoint: string, body?: Record<string, unknown>): ResolvedEndpoint;
|
|
20
|
+
export declare function actionTool(server: McpServer, sessionStore: SessionStore, profile?: ServerProfile, legacyJwt?: boolean): void;
|
|
21
|
+
export {};
|
|
4
22
|
//# sourceMappingURL=action.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../src/tools/action.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../src/tools/action.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAMhE;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,CAAC;AAcjD;;;GAGG;AACH,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,gBAAgB,CAqGlB;AAsDD,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,GAAE,aAAsB,EAAE,SAAS,UAAO,GAAG,IAAI,CA0KjI"}
|