@opendatalabs/personal-server-ts-server 1.16.0 → 1.17.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.
Files changed (93) hide show
  1. package/dist/app.d.ts +12 -0
  2. package/dist/app.d.ts.map +1 -1
  3. package/dist/app.js +54 -2
  4. package/dist/app.js.map +1 -1
  5. package/dist/bootstrap.d.ts +6 -0
  6. package/dist/bootstrap.d.ts.map +1 -1
  7. package/dist/bootstrap.js +65 -21
  8. package/dist/bootstrap.js.map +1 -1
  9. package/dist/enclave-main.d.ts +11 -0
  10. package/dist/enclave-main.d.ts.map +1 -0
  11. package/dist/enclave-main.js +188 -0
  12. package/dist/enclave-main.js.map +1 -0
  13. package/dist/index.js +11 -23
  14. package/dist/index.js.map +1 -1
  15. package/dist/jobs/access-reporter.d.ts +36 -0
  16. package/dist/jobs/access-reporter.d.ts.map +1 -0
  17. package/dist/jobs/access-reporter.js +272 -0
  18. package/dist/jobs/access-reporter.js.map +1 -0
  19. package/dist/jobs/raw-envelope-stream.d.ts +3 -0
  20. package/dist/jobs/raw-envelope-stream.d.ts.map +1 -0
  21. package/dist/jobs/raw-envelope-stream.js +371 -0
  22. package/dist/jobs/raw-envelope-stream.js.map +1 -0
  23. package/dist/jobs/types.d.ts +17 -0
  24. package/dist/jobs/types.d.ts.map +1 -0
  25. package/dist/jobs/types.js +3 -0
  26. package/dist/jobs/types.js.map +1 -0
  27. package/dist/jobs/worker.d.ts +43 -0
  28. package/dist/jobs/worker.d.ts.map +1 -0
  29. package/dist/jobs/worker.js +491 -0
  30. package/dist/jobs/worker.js.map +1 -0
  31. package/dist/listen.d.ts +11 -0
  32. package/dist/listen.d.ts.map +1 -0
  33. package/dist/listen.js +23 -0
  34. package/dist/listen.js.map +1 -0
  35. package/dist/mcp/durable-state.d.ts +75 -0
  36. package/dist/mcp/durable-state.d.ts.map +1 -0
  37. package/dist/mcp/durable-state.js +418 -0
  38. package/dist/mcp/durable-state.js.map +1 -0
  39. package/dist/mcp/grants.d.ts +12 -0
  40. package/dist/mcp/grants.d.ts.map +1 -0
  41. package/dist/mcp/grants.js +33 -0
  42. package/dist/mcp/grants.js.map +1 -0
  43. package/dist/mcp/index.d.ts +4 -0
  44. package/dist/mcp/index.d.ts.map +1 -0
  45. package/dist/mcp/index.js +4 -0
  46. package/dist/mcp/index.js.map +1 -0
  47. package/dist/mcp/tee-ingress.d.ts +29 -0
  48. package/dist/mcp/tee-ingress.d.ts.map +1 -0
  49. package/dist/mcp/tee-ingress.js +203 -0
  50. package/dist/mcp/tee-ingress.js.map +1 -0
  51. package/dist/middleware/local-listener.d.ts +33 -0
  52. package/dist/middleware/local-listener.d.ts.map +1 -0
  53. package/dist/middleware/local-listener.js +103 -0
  54. package/dist/middleware/local-listener.js.map +1 -0
  55. package/dist/package.json +67 -0
  56. package/dist/routes/enclave-fleet.d.ts +14 -0
  57. package/dist/routes/enclave-fleet.d.ts.map +1 -0
  58. package/dist/routes/enclave-fleet.js +43 -0
  59. package/dist/routes/enclave-fleet.js.map +1 -0
  60. package/dist/routes/enclave-jobs.d.ts +9 -0
  61. package/dist/routes/enclave-jobs.d.ts.map +1 -0
  62. package/dist/routes/enclave-jobs.js +106 -0
  63. package/dist/routes/enclave-jobs.js.map +1 -0
  64. package/dist/routes/enclave-mcp.d.ts +9 -0
  65. package/dist/routes/enclave-mcp.d.ts.map +1 -0
  66. package/dist/routes/enclave-mcp.js +46 -0
  67. package/dist/routes/enclave-mcp.js.map +1 -0
  68. package/dist/routes/mcp.d.ts +5 -2
  69. package/dist/routes/mcp.d.ts.map +1 -1
  70. package/dist/routes/mcp.js +49 -17
  71. package/dist/routes/mcp.js.map +1 -1
  72. package/dist/routes/ui.d.ts +7 -0
  73. package/dist/routes/ui.d.ts.map +1 -1
  74. package/dist/routes/ui.js +32 -3
  75. package/dist/routes/ui.js.map +1 -1
  76. package/dist/scripts/bundle-verification.d.ts +2 -0
  77. package/dist/scripts/bundle-verification.d.ts.map +1 -0
  78. package/dist/scripts/bundle-verification.js +32 -0
  79. package/dist/scripts/bundle-verification.js.map +1 -0
  80. package/dist/scripts/verify-bundle.d.ts +2 -0
  81. package/dist/scripts/verify-bundle.d.ts.map +1 -0
  82. package/dist/scripts/verify-bundle.js +44 -0
  83. package/dist/scripts/verify-bundle.js.map +1 -0
  84. package/dist/storage/hierarchy.d.ts +4 -0
  85. package/dist/storage/hierarchy.d.ts.map +1 -1
  86. package/dist/storage/hierarchy.js +10 -0
  87. package/dist/storage/hierarchy.js.map +1 -1
  88. package/dist/storage/node-data-storage.d.ts.map +1 -1
  89. package/dist/storage/node-data-storage.js +7 -1
  90. package/dist/storage/node-data-storage.js.map +1 -1
  91. package/dist/ui/index.html +13 -0
  92. package/dist/ui/ps-lite-debug.js +3205 -5575
  93. package/package.json +15 -7
@@ -0,0 +1,203 @@
1
+ import { Hono } from "hono";
2
+ import { cors } from "hono/cors";
3
+ import { isAddress } from "viem";
4
+ import { approveMcpOAuthAuthorization, handleMcpHandshake, hashConnectionToken, isMcpHandshake, toMcpOAuthAuthorizationView, } from "@opendatalabs/personal-server-ts-core/mcp";
5
+ import { mcpOAuthRoutes } from "../routes/mcp.js";
6
+ import { createBodyLimit } from "../middleware/body-limit.js";
7
+ /** Stable, non-retryable code for a caller whose owner withdrew enclave access
8
+ * (server deregistered, identity epoch bumped, delegation revoked). Retrying
9
+ * cannot help; the owner has to approve this enclave again. */
10
+ export const OWNER_ACCESS_REVOKED_CODE = "OWNER_ACCESS_REVOKED";
11
+ const OWNER_ACCESS_REVOKED_MESSAGE = "Owner access to this enclave was revoked; ask the owner to approve it again";
12
+ /** Thrown by `dispatch`/`ownerReady` providers when the live protocol identity
13
+ * shows the owner no longer authorizes this enclave. */
14
+ export class McpOwnerAccessRevokedError extends Error {
15
+ constructor() {
16
+ super(OWNER_ACCESS_REVOKED_MESSAGE);
17
+ this.name = "McpOwnerAccessRevokedError";
18
+ }
19
+ }
20
+ /** Public ingress: HTTPS terminates in the same CVM as this process. */
21
+ export function createTeeMcpIngress(deps) {
22
+ const app = new Hono();
23
+ const { state } = deps;
24
+ const redirectUris = new Set(deps.allowedRedirectUris);
25
+ app.use("*", createBodyLimit(256 * 1024));
26
+ app.use("*", cors({
27
+ origin: new URL(deps.approvalUrl).origin,
28
+ allowMethods: ["GET", "POST", "OPTIONS"],
29
+ allowHeaders: ["Content-Type", "Authorization", "MCP-Protocol-Version"],
30
+ exposeHeaders: ["WWW-Authenticate"],
31
+ }));
32
+ app.use("*", async (c, next) => {
33
+ c.header("Cache-Control", "no-store");
34
+ c.header("X-Content-Type-Options", "nosniff");
35
+ await next();
36
+ });
37
+ // One ingress writer serializes the core engine's multi-step OAuth updates.
38
+ app.use("/mcp/oauth/*", (c, next) => state.exclusive(async () => {
39
+ if (c.req.path === "/mcp/oauth/authorize" &&
40
+ !redirectUris.has(c.req.query("redirect_uri") ?? "")) {
41
+ return c.json({
42
+ error: "invalid_request",
43
+ error_description: "Unregistered demo redirect URI",
44
+ }, 400);
45
+ }
46
+ if (c.req.path === "/mcp/oauth/register") {
47
+ let body;
48
+ try {
49
+ body = await c.req.raw.clone().json();
50
+ }
51
+ catch {
52
+ return c.json({ error: "invalid_client_metadata" }, 400);
53
+ }
54
+ if (!Array.isArray(body.redirect_uris) ||
55
+ body.redirect_uris.length === 0 ||
56
+ body.redirect_uris.some((uri) => typeof uri !== "string" || !redirectUris.has(uri))) {
57
+ return c.json({ error: "invalid_redirect_uri" }, 400);
58
+ }
59
+ }
60
+ await next();
61
+ }));
62
+ // The random pending authorization ID reveals only the new grantee's public
63
+ // consent metadata. It does not authorize approval or return a private key.
64
+ app.get("/v1/mcp/readiness", async (c) => {
65
+ const owner = c.req.query("owner");
66
+ const chainId = Number(c.req.query("chainId"));
67
+ if (!owner || !isAddress(owner) || !Number.isSafeInteger(chainId))
68
+ return c.json({ error: "Owner and chain required" }, 400);
69
+ return c.json({
70
+ ready: (await deps.ownerReady?.({ owner, chainId })) ?? false,
71
+ });
72
+ });
73
+ app.get("/v1/mcp/oauth/authorizations/:id", async (c) => {
74
+ const record = await state.authorizations.getById(c.req.param("id"));
75
+ if (!record ||
76
+ record.status !== "pending" ||
77
+ Date.parse(record.expiresAt) <= Date.now())
78
+ return c.json({ error: "Authorization not found" }, 404);
79
+ const connection = await state.connections.getById(record.connectionId);
80
+ if (!connection)
81
+ return c.json({ error: "Connection not found" }, 404);
82
+ await deps.registerGrantee(connection, record.redirectUri);
83
+ return c.json(toMcpOAuthAuthorizationView(record));
84
+ });
85
+ app.post("/v1/mcp/oauth/authorizations/:id/approve", (c) => state.exclusive(async () => {
86
+ let body;
87
+ try {
88
+ body = await c.req.json();
89
+ }
90
+ catch {
91
+ return c.json({ error: "Invalid JSON" }, 400);
92
+ }
93
+ if (!body.owner ||
94
+ !isAddress(body.owner) ||
95
+ !Number.isSafeInteger(body.chainId) ||
96
+ !Array.isArray(body.grants) ||
97
+ body.grants.length === 0 ||
98
+ body.grants.some((grant) => !grant ||
99
+ typeof grant.grantId !== "string" ||
100
+ !Array.isArray(grant.scopes) ||
101
+ grant.scopes.length === 0 ||
102
+ grant.scopes.some((scope) => typeof scope !== "string"))) {
103
+ return c.json({ error: "Owner, chain and grants required" }, 400);
104
+ }
105
+ const authorization = await state.authorizations.getById(c.req.param("id"));
106
+ if (!authorization ||
107
+ authorization.status !== "pending" ||
108
+ Date.parse(authorization.expiresAt) <= Date.now())
109
+ return c.json({ error: "Authorization unavailable" }, 409);
110
+ const connection = await state.connections.getById(authorization.connectionId);
111
+ if (!connection)
112
+ return c.json({ error: "Connection unavailable" }, 404);
113
+ const binding = {
114
+ owner: body.owner,
115
+ chainId: body.chainId,
116
+ };
117
+ try {
118
+ await deps.verifyGrants(connection, binding, body.grants);
119
+ }
120
+ catch {
121
+ return c.json({ error: "Owner grant verification failed" }, 403);
122
+ }
123
+ if (deps.ownerReady && !(await deps.ownerReady(binding)))
124
+ return c.json({
125
+ error: "OWNER_PREWARM_REQUIRED",
126
+ message: "Finish owner prewarm before approving MCP",
127
+ }, 503);
128
+ try {
129
+ await deps.beforeOwnerApproval?.(binding);
130
+ }
131
+ catch {
132
+ return c.json({ error: "Owner scheduling unavailable" }, 503);
133
+ }
134
+ await state.bindOwner(connection.id, binding);
135
+ const approved = await approveMcpOAuthAuthorization({ authorizationId: authorization.id, grants: body.grants }, {
136
+ connectionStore: state.connections,
137
+ authorizationStore: state.authorizations,
138
+ });
139
+ return c.json({ redirectTo: approved.redirectTo });
140
+ }));
141
+ app.all("/mcp", async (c) => {
142
+ const header = c.req.header("authorization");
143
+ const token = header?.startsWith("Bearer ") ? header.slice(7).trim() : "";
144
+ const connection = token
145
+ ? await state.connections.getByTokenHash(await hashConnectionToken(token))
146
+ : null;
147
+ const binding = connection ? await state.getOwner(connection.id) : null;
148
+ if (!connection || !binding) {
149
+ c.header("WWW-Authenticate", `Bearer resource_metadata="${deps.origin}/.well-known/oauth-protected-resource/mcp", scope="vana:read"`);
150
+ return c.json({ error: "MCP authorization required" }, 401);
151
+ }
152
+ if (c.req.method !== "POST")
153
+ return c.body(null, 405, { Allow: "POST" });
154
+ // The handshake reads the static tool table, nothing of the owner's, so it
155
+ // is answered here rather than through grant verification, placement and
156
+ // two attested peer hops per message — the three messages a fresh client
157
+ // sends cost ~18 s each on that path.
158
+ let body;
159
+ try {
160
+ body = await c.req.raw.clone().json();
161
+ }
162
+ catch {
163
+ body = undefined;
164
+ }
165
+ if (isMcpHandshake(body))
166
+ return handleMcpHandshake(c.req.raw.clone());
167
+ try {
168
+ await deps.verifyGrants(connection, binding, connection.grants);
169
+ }
170
+ catch {
171
+ return c.json({ error: "MCP grants are no longer valid" }, 403);
172
+ }
173
+ return deps.dispatch(c.req.raw, connection, binding);
174
+ });
175
+ app.route("/", mcpOAuthRoutes({
176
+ gateway: deps.gateway,
177
+ serverOrigin: deps.origin,
178
+ oauthApprovalUrl: deps.approvalUrl,
179
+ connectionStore: state.connections,
180
+ oauthAuthorizationStore: state.authorizations,
181
+ }));
182
+ app.onError((error) => {
183
+ // A revoked owner is a terminal answer, not the transient 503 every other
184
+ // ingress failure gets: the MCP client must stop retrying this connection.
185
+ if (error instanceof McpOwnerAccessRevokedError)
186
+ return jsonError(403, {
187
+ error: OWNER_ACCESS_REVOKED_CODE,
188
+ message: OWNER_ACCESS_REVOKED_MESSAGE,
189
+ });
190
+ return jsonError(503, { error: "MCP request unavailable" });
191
+ });
192
+ return app;
193
+ }
194
+ function jsonError(status, body) {
195
+ return new Response(JSON.stringify(body), {
196
+ status,
197
+ headers: {
198
+ "content-type": "application/json",
199
+ "cache-control": "no-store",
200
+ },
201
+ });
202
+ }
203
+ //# sourceMappingURL=tee-ingress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tee-ingress.js","sourceRoot":"","sources":["../../src/mcp/tee-ingress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { MiddlewareHandler } from "hono";
2
+ export interface LoopbackListenerDeps {
3
+ /**
4
+ * Port of the loopback-only auth listener (see `index.ts`). The dev UI is
5
+ * served ONLY to connections that arrived on this listener. `undefined`
6
+ * (cloud mode, or not yet bound) means the UI is never served.
7
+ */
8
+ localApprovalPort: number | undefined;
9
+ /**
10
+ * The main (tunneled) server port. If the loopback port collides with it
11
+ * the loopback bind fails but the port value survives, and every tunneled
12
+ * request would match — so a collision disables the UI outright.
13
+ */
14
+ serverPort?: number;
15
+ }
16
+ /**
17
+ * Restrict a route subtree to requests that physically arrived on the
18
+ * loopback auth listener, addressed it by a loopback name, and did not come
19
+ * from another browser origin.
20
+ *
21
+ * Why the listener port and not the peer address: the tunnel client (frpc)
22
+ * runs on the same host and connects to the MAIN server port from
23
+ * 127.0.0.1, so every tunneled request already looks local by
24
+ * `remoteAddress`. The one thing a remote caller can never influence is
25
+ * which listening socket accepted the connection — the tunnel forwards to
26
+ * `config.server.port` only, never to the loopback auth port.
27
+ *
28
+ * Fails closed: no socket information (tests, non-Node runtimes), no
29
+ * loopback listener configured, a port collision, or an unparseable URL →
30
+ * 404, so the subtree is invisible.
31
+ */
32
+ export declare function requireLoopbackListener(deps: LoopbackListenerDeps): MiddlewareHandler;
33
+ //# sourceMappingURL=local-listener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-listener.d.ts","sourceRoot":"","sources":["../../src/middleware/local-listener.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAEvD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAkED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,oBAAoB,GACzB,iBAAiB,CAgCnB"}
@@ -0,0 +1,103 @@
1
+ const LOOPBACK_V4 = /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
2
+ /** Socket-level check: is this IP address (not a hostname) loopback? */
3
+ function isLoopbackIp(address) {
4
+ if (!address)
5
+ return false;
6
+ return (address === "::1" ||
7
+ address === "::ffff:127.0.0.1" ||
8
+ LOOPBACK_V4.test(address));
9
+ }
10
+ /**
11
+ * Host-header check (DNS-rebinding defense). A hostile page can point a
12
+ * name it controls at 127.0.0.1 and then fetch
13
+ * `http://attacker.example:<port>/ui`; the browser sends that name as both
14
+ * `Host` and `Origin`, so origin equality alone would pass and the browser
15
+ * would treat the response as same-origin. Only loopback literals and the
16
+ * exact name `localhost` may address this listener. (`URL.hostname` keeps
17
+ * IPv6 brackets.)
18
+ */
19
+ function isLoopbackRequestHost(hostname) {
20
+ return (hostname === "localhost" ||
21
+ hostname === "127.0.0.1" ||
22
+ hostname === "[::1]" ||
23
+ hostname === "::1" ||
24
+ LOOPBACK_V4.test(hostname));
25
+ }
26
+ function getSocket(c) {
27
+ // Access the Node.js socket via Hono's env bindings when running on the
28
+ // real server (@hono/node-server sets `c.env.incoming`).
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ return c.env?.incoming?.socket;
31
+ }
32
+ /**
33
+ * Browser check. A cross-origin fetch always carries an `Origin` header
34
+ * naming the requesting site; same-origin navigations carry none, and the
35
+ * page's own fetches (if the browser adds one) carry the page's origin,
36
+ * which is this listener's origin. Anything else is another page in the
37
+ * user's browser probing the loopback listener — the app's global CORS is
38
+ * `*`, and not every browser enforces Private Network Access.
39
+ *
40
+ * Exact equality against the request's own origin, deliberately: hostname
41
+ * heuristics are bypassable (`127.attacker.example` is a public name), and
42
+ * another *local* origin such as `http://localhost:12345` must not read
43
+ * this page either. Combined with the Host allowlist above, the request
44
+ * origin itself is guaranteed to be a loopback origin.
45
+ */
46
+ function hasForeignOrigin(c, requestOrigin) {
47
+ const origin = c.req.header("origin");
48
+ if (!origin)
49
+ return false;
50
+ try {
51
+ return new URL(origin).origin !== requestOrigin;
52
+ }
53
+ catch {
54
+ return true;
55
+ }
56
+ }
57
+ /**
58
+ * Restrict a route subtree to requests that physically arrived on the
59
+ * loopback auth listener, addressed it by a loopback name, and did not come
60
+ * from another browser origin.
61
+ *
62
+ * Why the listener port and not the peer address: the tunnel client (frpc)
63
+ * runs on the same host and connects to the MAIN server port from
64
+ * 127.0.0.1, so every tunneled request already looks local by
65
+ * `remoteAddress`. The one thing a remote caller can never influence is
66
+ * which listening socket accepted the connection — the tunnel forwards to
67
+ * `config.server.port` only, never to the loopback auth port.
68
+ *
69
+ * Fails closed: no socket information (tests, non-Node runtimes), no
70
+ * loopback listener configured, a port collision, or an unparseable URL →
71
+ * 404, so the subtree is invisible.
72
+ */
73
+ export function requireLoopbackListener(deps) {
74
+ return async (c, next) => {
75
+ const port = deps.localApprovalPort;
76
+ if (port === undefined || port === deps.serverPort) {
77
+ return c.notFound();
78
+ }
79
+ const socket = getSocket(c);
80
+ if (!socket ||
81
+ socket.localPort !== port ||
82
+ !isLoopbackIp(typeof socket.localAddress === "string"
83
+ ? socket.localAddress
84
+ : undefined)) {
85
+ return c.notFound();
86
+ }
87
+ let requestUrl;
88
+ try {
89
+ requestUrl = new URL(c.req.url);
90
+ }
91
+ catch {
92
+ return c.notFound();
93
+ }
94
+ if (!isLoopbackRequestHost(requestUrl.hostname)) {
95
+ return c.notFound();
96
+ }
97
+ if (hasForeignOrigin(c, requestUrl.origin)) {
98
+ return c.notFound();
99
+ }
100
+ await next();
101
+ };
102
+ }
103
+ //# sourceMappingURL=local-listener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-listener.js","sourceRoot":"","sources":["../../src/middleware/local-listener.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,GAAG,kCAAkC,CAAC;AAEvD,wEAAwE;AACxE,SAAS,YAAY,CAAC,OAA2B;IAC/C,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,OAAO,CACL,OAAO,KAAK,KAAK;QACjB,OAAO,KAAK,kBAAkB;QAC9B,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAC1B,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,qBAAqB,CAAC,QAAgB;IAC7C,OAAO,CACL,QAAQ,KAAK,WAAW;QACxB,QAAQ,KAAK,WAAW;QACxB,QAAQ,KAAK,OAAO;QACpB,QAAQ,KAAK,KAAK;QAClB,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAC3B,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAChB,CAAU;IAEV,wEAAwE;IACxE,yDAAyD;IACzD,8DAA8D;IAC9D,OAAQ,CAAC,CAAC,GAAW,EAAE,QAAQ,EAAE,MAAM,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,gBAAgB,CAAC,CAAU,EAAE,aAAqB;IACzD,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAA0B;IAE1B,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC;QACpC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YACnD,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtB,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC5B,IACE,CAAC,MAAM;YACP,MAAM,CAAC,SAAS,KAAK,IAAI;YACzB,CAAC,YAAY,CACX,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ;gBACrC,CAAC,CAAC,MAAM,CAAC,YAAY;gBACrB,CAAC,CAAC,SAAS,CACd,EACD,CAAC;YACD,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtB,CAAC;QACD,IAAI,UAAe,CAAC;QACpB,IAAI,CAAC;YACH,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChD,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtB,CAAC;QACD,IAAI,gBAAgB,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtB,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@opendatalabs/personal-server-ts-server",
3
+ "version": "0.0.1",
4
+ "description": "Hono HTTP server for the Vana Personal Server — routes, middleware, composition root",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/vana-com/personal-server-ts.git",
9
+ "directory": "packages/server"
10
+ },
11
+ "homepage": "https://github.com/vana-com/personal-server-ts#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/vana-com/personal-server-ts/issues"
14
+ },
15
+ "type": "module",
16
+ "main": "./dist/api.js",
17
+ "types": "./dist/api.d.ts",
18
+ "exports": {
19
+ "./mcp/tee": {
20
+ "types": "./dist/mcp/index.d.ts",
21
+ "import": "./dist/mcp/index.js"
22
+ },
23
+ ".": {
24
+ "types": "./dist/api.d.ts",
25
+ "import": "./dist/api.js"
26
+ },
27
+ "./config": {
28
+ "types": "./dist/config/index.d.ts",
29
+ "import": "./dist/config/index.js"
30
+ },
31
+ "./runtime": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js"
34
+ }
35
+ },
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "!dist/bundle"
42
+ ],
43
+ "scripts": {
44
+ "copy-ui": "mkdir -p dist/ui && cp src/ui/index.html dist/ui/index.html && cp ../lite/src/browser-tls-rustls/browser_tls_rustls_bg.wasm dist/ui/browser_tls_rustls_bg.wasm",
45
+ "bundle-ui": "esbuild src/ui/ps-lite-debug.ts --bundle --format=esm --platform=browser --target=es2022 --outfile=dist/ui/ps-lite-debug.js",
46
+ "build:bundle": "mkdir -p dist/bundle && esbuild dist/index.js --bundle --platform=node --format=esm --target=node22 --outfile=dist/bundle/enclave-main.mjs --external:better-sqlite3 --external:pino --external:pino-pretty --external:secp256k1 --external:thread-stream --packages=bundle --banner:js=\"import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __filename = __bundleFileURLToPath(import.meta.url); const __dirname = __bundleDirname(__filename);\" && cp package.json dist/package.json && npm run verify:bundle",
47
+ "verify:bundle": "node dist/scripts/verify-bundle.js",
48
+ "build": "tsc --build && npm run copy-ui && npm run bundle-ui && npm run build:bundle",
49
+ "start": "node dist/index.js",
50
+ "dev": "node --watch dist/index.js"
51
+ },
52
+ "dependencies": {
53
+ "@hono/node-server": "^1.19.13",
54
+ "@opendatalabs/personal-server-ts-core": "*",
55
+ "@opendatalabs/personal-server-ts-lite": "*",
56
+ "@opendatalabs/vana-sdk": "3.23.0-pr.211.36da1d8",
57
+ "better-sqlite3": "^12.11.1",
58
+ "hono": "^4.12.27",
59
+ "pino": "^10.3.1",
60
+ "pino-pretty": "^13.0.0",
61
+ "viem": "^2.54.2"
62
+ },
63
+ "devDependencies": {
64
+ "@types/better-sqlite3": "^7.6.0",
65
+ "esbuild": "0.28.1"
66
+ }
67
+ }
@@ -0,0 +1,14 @@
1
+ import { Hono } from "hono";
2
+ /** Sandbox-local endpoint. Never mounted on a full PS or a public router. */
3
+ export declare function enclaveFleetRoutes(deps: {
4
+ accessToken: string;
5
+ hydrate(scopes: string[]): Promise<void>;
6
+ observe(scope: string): {
7
+ dataVersion: number | null;
8
+ ready: boolean;
9
+ } | Promise<{
10
+ dataVersion: number | null;
11
+ ready: boolean;
12
+ }>;
13
+ }): Hono;
14
+ //# sourceMappingURL=enclave-fleet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enclave-fleet.d.ts","sourceRoot":"","sources":["../../src/routes/enclave-fleet.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,CACL,KAAK,EAAE,MAAM,GAEX;QAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAC9C,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC7D,GAAG,IAAI,CAkDP"}
@@ -0,0 +1,43 @@
1
+ import { timingSafeEqual } from "node:crypto";
2
+ import { Hono } from "hono";
3
+ import { ScopeSchema } from "@opendatalabs/vana-sdk/protocol/scopes";
4
+ import { createBodyLimit } from "../middleware/body-limit.js";
5
+ /** Sandbox-local endpoint. Never mounted on a full PS or a public router. */
6
+ export function enclaveFleetRoutes(deps) {
7
+ const app = new Hono();
8
+ app.use("*", createBodyLimit(16 * 1024));
9
+ app.post("/readiness", async (c) => {
10
+ const received = Buffer.from(c.req.header("authorization") ?? "");
11
+ const expected = Buffer.from(`Bearer ${deps.accessToken}`);
12
+ if (received.length !== expected.length ||
13
+ !timingSafeEqual(received, expected))
14
+ return c.json({ error: "authorization required" }, 401);
15
+ const body = (await c.req.json().catch(() => null));
16
+ if (!body ||
17
+ !Array.isArray(body.scopes) ||
18
+ body.scopes.length > 32 ||
19
+ body.scopes.some((s) => !s ||
20
+ !ScopeSchema.safeParse(s.scope).success ||
21
+ (s.minimumVersion !== undefined &&
22
+ (!Number.isSafeInteger(s.minimumVersion) || s.minimumVersion < 1)))) {
23
+ return c.json({ error: "invalid scopes" }, 400);
24
+ }
25
+ if (body.hydrate)
26
+ await deps.hydrate(body.scopes.map((s) => s.scope));
27
+ return c.json(await Promise.all(body.scopes.map(async (s) => {
28
+ const observed = await deps.observe(s.scope);
29
+ return {
30
+ scope: s.scope,
31
+ dataVersion: observed.dataVersion,
32
+ state: observed.ready &&
33
+ observed.dataVersion !== null &&
34
+ observed.dataVersion >= (s.minimumVersion ?? 1)
35
+ ? "ready"
36
+ : "pending",
37
+ observedAt: new Date().toISOString(),
38
+ };
39
+ })));
40
+ });
41
+ return app;
42
+ }
43
+ //# sourceMappingURL=enclave-fleet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enclave-fleet.js","sourceRoot":"","sources":["../../src/routes/enclave-fleet.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { Hono } from "hono";
2
+ import { type JobRequestEnvelope } from "@opendatalabs/vana-sdk/protocol/jobs";
3
+ import type { JobExecuteResponse } from "../jobs/types.js";
4
+ export interface EnclaveJobRouteDeps {
5
+ accessToken: string;
6
+ executeJob(envelope: JobRequestEnvelope): Promise<JobExecuteResponse>;
7
+ }
8
+ export declare function enclaveJobRoutes(deps: EnclaveJobRouteDeps): Hono;
9
+ //# sourceMappingURL=enclave-jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enclave-jobs.d.ts","sourceRoot":"","sources":["../../src/routes/enclave-jobs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,KAAK,EAEV,kBAAkB,EAEnB,MAAM,kBAAkB,CAAC;AAM1B,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACvE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CA0ChE"}
@@ -0,0 +1,106 @@
1
+ import { timingSafeEqual } from "node:crypto";
2
+ import { Hono } from "hono";
3
+ import { isAddress, isHex } from "viem";
4
+ import { JOB_OPERATIONS, JOB_PROTOCOL_VERSION, } from "@opendatalabs/vana-sdk/protocol/jobs";
5
+ import { createBodyLimit } from "../middleware/body-limit.js";
6
+ import { JobFailure } from "../jobs/worker.js";
7
+ const MAX_JOB_BODY_BYTES = 256 * 1024;
8
+ const BEARER_PREFIX = "Bearer ";
9
+ export function enclaveJobRoutes(deps) {
10
+ const app = new Hono();
11
+ app.use("/execute", createBodyLimit(MAX_JOB_BODY_BYTES));
12
+ app.post("/execute", async (context) => {
13
+ if (!hasValidBearer(context.req.header("authorization"), deps.accessToken)) {
14
+ return context.json(jobError("AUTH_INVALID", "invalid bearer token"), 401);
15
+ }
16
+ let body;
17
+ try {
18
+ body = await context.req.json();
19
+ }
20
+ catch {
21
+ return context.json({ error: { message: "invalid request body" } }, 400);
22
+ }
23
+ if (!isJobEnvelope(body)) {
24
+ return context.json({ error: { message: "invalid request body" } }, 400);
25
+ }
26
+ try {
27
+ return context.json(await deps.executeJob(body), 200);
28
+ }
29
+ catch (error) {
30
+ if (error instanceof JobFailure) {
31
+ return context.json(jobError(error.code, error.message, error.retryable), statusFor(error.code));
32
+ }
33
+ return context.json(jobError("INTERNAL", "job execution failed", true), 500);
34
+ }
35
+ });
36
+ return app;
37
+ }
38
+ function hasValidBearer(header, expected) {
39
+ if (!header?.startsWith(BEARER_PREFIX)) {
40
+ return false;
41
+ }
42
+ const received = Buffer.from(header.slice(BEARER_PREFIX.length));
43
+ const target = Buffer.from(expected);
44
+ if (received.length !== target.length) {
45
+ return false;
46
+ }
47
+ return timingSafeEqual(received, target);
48
+ }
49
+ function isJobEnvelope(value) {
50
+ if (!isRecord(value) || !isRecord(value.request)) {
51
+ return false;
52
+ }
53
+ const request = value.request;
54
+ return (value.auth !== "" &&
55
+ typeof value.auth === "string" &&
56
+ request.v === JOB_PROTOCOL_VERSION &&
57
+ typeof request.jobId === "string" &&
58
+ isAddressValue(request.owner) &&
59
+ isAddressValue(request.builder) &&
60
+ isHexValue(request.builderPublicKey) &&
61
+ isHexValue(request.grantId) &&
62
+ typeof request.scope === "string" &&
63
+ JOB_OPERATIONS.some((operation) => operation === request.operation) &&
64
+ (request.pinnedVersion === null ||
65
+ typeof request.pinnedVersion === "string") &&
66
+ typeof request.deadline === "string");
67
+ }
68
+ function isAddressValue(value) {
69
+ return typeof value === "string" && isAddress(value);
70
+ }
71
+ function isHexValue(value) {
72
+ return typeof value === "string" && isHex(value);
73
+ }
74
+ function isRecord(value) {
75
+ return typeof value === "object" && value !== null;
76
+ }
77
+ function jobError(code, message, retryable = false) {
78
+ return { error: { code, message, retryable } };
79
+ }
80
+ function statusFor(code) {
81
+ switch (code) {
82
+ case "AUTH_INVALID":
83
+ return 401;
84
+ case "BUILDER_MISMATCH":
85
+ case "OWNER_MISMATCH":
86
+ case "GRANT_REVOKED":
87
+ case "GRANT_INVALID":
88
+ case "SIGNED_ARTIFACT_MISSING":
89
+ case "SIGNED_ARTIFACT_INVALID":
90
+ case "SERVER_NOT_REGISTERED":
91
+ case "RESULT_SIGNING_REFUSED":
92
+ return 403;
93
+ case "SCOPE_NOT_FOUND":
94
+ return 404;
95
+ case "VERSION_MISMATCH":
96
+ return 409;
97
+ case "DEADLINE_PASSED":
98
+ return 410;
99
+ case "RESULT_TOO_LARGE":
100
+ return 413;
101
+ case "RESULT_UPLOAD_FAILED":
102
+ case "INTERNAL":
103
+ return 500;
104
+ }
105
+ }
106
+ //# sourceMappingURL=enclave-jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enclave-jobs.js","sourceRoot":"","sources":["../../src/routes/enclave-jobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,KAAK,EAA0B,MAAM,MAAM,CAAC;AAChE,OAAO,EACL,cAAc,EACd,oBAAoB,GAErB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAM9D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,kBAAkB,GAAG,GAAG,GAAG,IAAI,CAAC;AACtC,MAAM,aAAa,GAAG,SAAS,CAAC;AAOhC,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACxD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACzD,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACrC,IACE,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,EACtE,CAAC;YACD,OAAO,OAAO,CAAC,IAAI,CACjB,QAAQ,CAAC,cAAc,EAAE,sBAAsB,CAAC,EAChD,GAAG,CACJ,CAAC;QACJ,CAAC;QAED,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,sBAAsB,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,sBAAsB,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3E,CAAC;QAED,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;gBAChC,OAAO,OAAO,CAAC,IAAI,CACjB,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,EACpD,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CACtB,CAAC;YACJ,CAAC;YAED,OAAO,OAAO,CAAC,IAAI,CACjB,QAAQ,CAAC,UAAU,EAAE,sBAAsB,EAAE,IAAI,CAAC,EAClD,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,cAAc,CAAC,MAA0B,EAAE,QAAgB;IAClE,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACvC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAE9B,OAAO,CACL,KAAK,CAAC,IAAI,KAAK,EAAE;QACjB,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,OAAO,CAAC,CAAC,KAAK,oBAAoB;QAClC,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ;QACjC,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC;QAC7B,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC;QAC/B,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC;QACpC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC;QAC3B,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ;QACjC,cAAc,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS,CAAC;QACnE,CAAC,OAAO,CAAC,aAAa,KAAK,IAAI;YAC7B,OAAO,OAAO,CAAC,aAAa,KAAK,QAAQ,CAAC;QAC5C,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CACrC,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,QAAQ,CACf,IAAoB,EACpB,OAAe,EACf,SAAS,GAAG,KAAK;IAEjB,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,SAAS,CAChB,IAAoB;IAEpB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,cAAc;YACjB,OAAO,GAAG,CAAC;QACb,KAAK,kBAAkB,CAAC;QACxB,KAAK,gBAAgB,CAAC;QACtB,KAAK,eAAe,CAAC;QACrB,KAAK,eAAe,CAAC;QACrB,KAAK,yBAAyB,CAAC;QAC/B,KAAK,yBAAyB,CAAC;QAC/B,KAAK,uBAAuB,CAAC;QAC7B,KAAK,wBAAwB;YAC3B,OAAO,GAAG,CAAC;QACb,KAAK,iBAAiB;YACpB,OAAO,GAAG,CAAC;QACb,KAAK,kBAAkB;YACrB,OAAO,GAAG,CAAC;QACb,KAAK,iBAAiB;YACpB,OAAO,GAAG,CAAC;QACb,KAAK,kBAAkB;YACrB,OAAO,GAAG,CAAC;QACb,KAAK,sBAAsB,CAAC;QAC5B,KAAK,UAAU;YACb,OAAO,GAAG,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Hono } from "hono";
2
+ import type { McpConnectionRecord } from "@opendatalabs/personal-server-ts-core/mcp";
3
+ import { type Address } from "viem";
4
+ export declare function enclaveMcpRoutes(deps: {
5
+ accessToken: string;
6
+ serverOwner: Address;
7
+ execute(request: Request, connection: McpConnectionRecord): Promise<Response>;
8
+ }): Hono;
9
+ //# sourceMappingURL=enclave-mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enclave-mcp.d.ts","sourceRoot":"","sources":["../../src/routes/enclave-mcp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAG/D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC/E,GAAG,IAAI,CAoDP"}