gemi 0.144.0 → 0.145.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/dist/ai/AgentController.d.ts +2 -2
- package/dist/ai/AgentController.d.ts.map +1 -1
- package/dist/ai/index.d.ts +2 -2
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +11 -11
- package/dist/ai/index.js.map +3 -3
- package/dist/ai/store/Nonces.d.ts +68 -0
- package/dist/ai/store/Nonces.d.ts.map +1 -1
- package/dist/ai/store/index.d.ts +1 -1
- package/dist/ai/store/index.d.ts.map +1 -1
- package/dist/app/index.js +1 -1
- package/dist/bun/plugin.js +1 -1
- package/dist/bun/preload.js +1 -1
- package/dist/{chunk-fg2k18d2.js → chunk-0k8fk96c.js} +2 -2
- package/dist/{chunk-fg2k18d2.js.map → chunk-0k8fk96c.js.map} +1 -1
- package/dist/{chunk-y5yac6n1.js → chunk-0mt7kqwx.js} +2 -2
- package/dist/{chunk-y5yac6n1.js.map → chunk-0mt7kqwx.js.map} +1 -1
- package/dist/{chunk-1ed75a7b.js → chunk-1fyn63ka.js} +3 -3
- package/dist/{chunk-1ed75a7b.js.map → chunk-1fyn63ka.js.map} +1 -1
- package/dist/{chunk-tkvamktq.js → chunk-1ttd4rn9.js} +2 -2
- package/dist/{chunk-tkvamktq.js.map → chunk-1ttd4rn9.js.map} +1 -1
- package/dist/{chunk-m70hn4eg.js → chunk-1wz6kwjc.js} +2 -2
- package/dist/{chunk-m70hn4eg.js.map → chunk-1wz6kwjc.js.map} +1 -1
- package/dist/{chunk-fsem81ec.js → chunk-29jmaj16.js} +1 -1
- package/dist/{chunk-fpz9e3xx.js → chunk-2b3hh9xw.js} +3 -3
- package/dist/{chunk-fpz9e3xx.js.map → chunk-2b3hh9xw.js.map} +1 -1
- package/dist/{chunk-n9zycjm1.js → chunk-2djjs8f1.js} +3 -3
- package/dist/{chunk-n9zycjm1.js.map → chunk-2djjs8f1.js.map} +1 -1
- package/dist/{chunk-p81qeav5.js → chunk-2ery6a75.js} +3 -3
- package/dist/{chunk-p81qeav5.js.map → chunk-2ery6a75.js.map} +1 -1
- package/dist/{chunk-hyhbk12v.js → chunk-2k3935ke.js} +2 -2
- package/dist/{chunk-hyhbk12v.js.map → chunk-2k3935ke.js.map} +1 -1
- package/dist/{chunk-qt6x2r6a.js → chunk-2x6cv37t.js} +2 -2
- package/dist/{chunk-qt6x2r6a.js.map → chunk-2x6cv37t.js.map} +1 -1
- package/dist/{chunk-68f0jpje.js → chunk-313593t3.js} +2 -2
- package/dist/{chunk-68f0jpje.js.map → chunk-313593t3.js.map} +1 -1
- package/dist/{chunk-5qfzvnyp.js → chunk-3csz8pfk.js} +3 -3
- package/dist/{chunk-5qfzvnyp.js.map → chunk-3csz8pfk.js.map} +1 -1
- package/dist/{chunk-rezmtdyt.js → chunk-3x8zrsby.js} +2 -2
- package/dist/{chunk-rezmtdyt.js.map → chunk-3x8zrsby.js.map} +1 -1
- package/dist/{chunk-6d3m2w2p.js → chunk-43ws58db.js} +2 -2
- package/dist/{chunk-6d3m2w2p.js.map → chunk-43ws58db.js.map} +1 -1
- package/dist/chunk-49s8wwp2.js +5 -0
- package/dist/{chunk-b6mgrrk6.js.map → chunk-49s8wwp2.js.map} +1 -1
- package/dist/{chunk-ncb1qtae.js → chunk-4d4td4k9.js} +2 -2
- package/dist/{chunk-ncb1qtae.js.map → chunk-4d4td4k9.js.map} +1 -1
- package/dist/{chunk-v57ndv0h.js → chunk-4jd25v6d.js} +2 -2
- package/dist/{chunk-v57ndv0h.js.map → chunk-4jd25v6d.js.map} +1 -1
- package/dist/{chunk-78bfmwp0.js → chunk-4m0eqq80.js} +2 -2
- package/dist/{chunk-78bfmwp0.js.map → chunk-4m0eqq80.js.map} +1 -1
- package/dist/{chunk-ktrm6y5j.js → chunk-563ksar3.js} +3 -3
- package/dist/{chunk-ktrm6y5j.js.map → chunk-563ksar3.js.map} +1 -1
- package/dist/{chunk-z80v4z8y.js → chunk-5q2pmve9.js} +2 -2
- package/dist/{chunk-z80v4z8y.js.map → chunk-5q2pmve9.js.map} +1 -1
- package/dist/{chunk-20d0n391.js → chunk-5yz684rw.js} +2 -2
- package/dist/{chunk-20d0n391.js.map → chunk-5yz684rw.js.map} +1 -1
- package/dist/{chunk-236be97q.js → chunk-63xwah5k.js} +1 -1
- package/dist/{chunk-b4jx4fzq.js → chunk-65wy1r1a.js} +1 -1
- package/dist/{chunk-9tgcmx4h.js → chunk-70yz9e7f.js} +2 -2
- package/dist/{chunk-9tgcmx4h.js.map → chunk-70yz9e7f.js.map} +1 -1
- package/dist/{chunk-t03nda3s.js → chunk-73rzf7ys.js} +2 -2
- package/dist/{chunk-t03nda3s.js.map → chunk-73rzf7ys.js.map} +1 -1
- package/dist/{chunk-1cn7ets3.js → chunk-7txqv2qq.js} +3 -3
- package/dist/{chunk-1cn7ets3.js.map → chunk-7txqv2qq.js.map} +1 -1
- package/dist/{chunk-1skdsmjx.js → chunk-86zhngpg.js} +2 -2
- package/dist/{chunk-1skdsmjx.js.map → chunk-86zhngpg.js.map} +1 -1
- package/dist/{chunk-ce9wm3r9.js → chunk-877yc341.js} +3 -3
- package/dist/{chunk-ce9wm3r9.js.map → chunk-877yc341.js.map} +1 -1
- package/dist/{chunk-wffc5k3m.js → chunk-87y2nrjy.js} +2 -2
- package/dist/{chunk-wffc5k3m.js.map → chunk-87y2nrjy.js.map} +1 -1
- package/dist/{chunk-9zd7c4wq.js → chunk-8k346pjw.js} +14 -14
- package/dist/{chunk-9zd7c4wq.js.map → chunk-8k346pjw.js.map} +3 -3
- package/dist/{chunk-27xsjq8a.js → chunk-8km4drvv.js} +3 -3
- package/dist/{chunk-27xsjq8a.js.map → chunk-8km4drvv.js.map} +1 -1
- package/dist/{chunk-sa6a0wy1.js → chunk-94hcjdbe.js} +2 -2
- package/dist/{chunk-sa6a0wy1.js.map → chunk-94hcjdbe.js.map} +1 -1
- package/dist/{chunk-kaphqnpp.js → chunk-9z8zq4rx.js} +3 -3
- package/dist/{chunk-kaphqnpp.js.map → chunk-9z8zq4rx.js.map} +1 -1
- package/dist/{chunk-8ex0y47w.js → chunk-apga49vp.js} +2 -2
- package/dist/{chunk-8ex0y47w.js.map → chunk-apga49vp.js.map} +1 -1
- package/dist/{chunk-yjszzjyj.js → chunk-attr793y.js} +2 -2
- package/dist/{chunk-yjszzjyj.js.map → chunk-attr793y.js.map} +1 -1
- package/dist/{chunk-1x9ghjpt.js → chunk-bsa6b82q.js} +1 -1
- package/dist/{chunk-ceb4jcrm.js → chunk-bstn00nx.js} +2 -2
- package/dist/{chunk-ceb4jcrm.js.map → chunk-bstn00nx.js.map} +1 -1
- package/dist/{chunk-azd6da5h.js → chunk-bykkqvd8.js} +2 -2
- package/dist/{chunk-azd6da5h.js.map → chunk-bykkqvd8.js.map} +1 -1
- package/dist/{chunk-9k46m1vf.js → chunk-cee5gq7t.js} +2 -2
- package/dist/{chunk-9k46m1vf.js.map → chunk-cee5gq7t.js.map} +1 -1
- package/dist/{chunk-9dkpv8ev.js → chunk-dxh8njb4.js} +2 -2
- package/dist/{chunk-9dkpv8ev.js.map → chunk-dxh8njb4.js.map} +1 -1
- package/dist/{chunk-maqkrbsb.js → chunk-e06t0625.js} +2 -2
- package/dist/{chunk-maqkrbsb.js.map → chunk-e06t0625.js.map} +1 -1
- package/dist/{chunk-0839f72f.js → chunk-e9z8p2fy.js} +2 -2
- package/dist/{chunk-0839f72f.js.map → chunk-e9z8p2fy.js.map} +1 -1
- package/dist/{chunk-6hs102jh.js → chunk-eqv7yxk7.js} +2 -2
- package/dist/{chunk-6hs102jh.js.map → chunk-eqv7yxk7.js.map} +1 -1
- package/dist/{chunk-m6t5a0me.js → chunk-fqqbnp0z.js} +2 -2
- package/dist/{chunk-m6t5a0me.js.map → chunk-fqqbnp0z.js.map} +1 -1
- package/dist/{chunk-1w5dnkd1.js → chunk-g22kph4n.js} +2 -2
- package/dist/{chunk-1w5dnkd1.js.map → chunk-g22kph4n.js.map} +1 -1
- package/dist/{chunk-rvm5mkwm.js → chunk-g8sh9btf.js} +2 -2
- package/dist/{chunk-rvm5mkwm.js.map → chunk-g8sh9btf.js.map} +1 -1
- package/dist/{chunk-a78b9v7h.js → chunk-gvdg52ew.js} +4 -4
- package/dist/{chunk-a78b9v7h.js.map → chunk-gvdg52ew.js.map} +1 -1
- package/dist/{chunk-8ky8cmde.js → chunk-h8eawyhx.js} +2 -2
- package/dist/{chunk-8ky8cmde.js.map → chunk-h8eawyhx.js.map} +1 -1
- package/dist/{chunk-r567t83k.js → chunk-hcw671mg.js} +4 -4
- package/dist/{chunk-r567t83k.js.map → chunk-hcw671mg.js.map} +1 -1
- package/dist/{chunk-ej4kf7m5.js → chunk-hh5bs656.js} +3 -3
- package/dist/{chunk-ej4kf7m5.js.map → chunk-hh5bs656.js.map} +1 -1
- package/dist/{chunk-3q7sc68p.js → chunk-j6ygdvj8.js} +2 -2
- package/dist/{chunk-3q7sc68p.js.map → chunk-j6ygdvj8.js.map} +1 -1
- package/dist/{chunk-t2nsn0r2.js → chunk-jzpbwvbt.js} +2 -2
- package/dist/{chunk-t2nsn0r2.js.map → chunk-jzpbwvbt.js.map} +1 -1
- package/dist/{chunk-en33hg1c.js → chunk-k79ajvtc.js} +2 -2
- package/dist/{chunk-en33hg1c.js.map → chunk-k79ajvtc.js.map} +1 -1
- package/dist/{chunk-t0wfj6hy.js → chunk-k8pn2qvf.js} +2 -2
- package/dist/{chunk-t0wfj6hy.js.map → chunk-k8pn2qvf.js.map} +1 -1
- package/dist/{chunk-83cvkhzn.js → chunk-kmh402m4.js} +2 -2
- package/dist/{chunk-83cvkhzn.js.map → chunk-kmh402m4.js.map} +1 -1
- package/dist/{chunk-b4mg6v4g.js → chunk-m9am5fqq.js} +5 -5
- package/dist/{chunk-b4mg6v4g.js.map → chunk-m9am5fqq.js.map} +3 -3
- package/dist/{chunk-m8yd59gg.js → chunk-mr3szvr3.js} +2 -2
- package/dist/{chunk-m8yd59gg.js.map → chunk-mr3szvr3.js.map} +1 -1
- package/dist/{chunk-mkw35cz7.js → chunk-mtamgvf4.js} +2 -2
- package/dist/{chunk-mkw35cz7.js.map → chunk-mtamgvf4.js.map} +1 -1
- package/dist/{chunk-5xfpqda5.js → chunk-mv1rs9he.js} +1 -1
- package/dist/{chunk-s29tgy4y.js → chunk-mzkzgp2j.js} +2 -2
- package/dist/{chunk-s29tgy4y.js.map → chunk-mzkzgp2j.js.map} +1 -1
- package/dist/{chunk-9xzg05xg.js → chunk-n9n4qt20.js} +3 -3
- package/dist/{chunk-9xzg05xg.js.map → chunk-n9n4qt20.js.map} +1 -1
- package/dist/{chunk-2ra5skyk.js → chunk-p27y4xrw.js} +2 -2
- package/dist/{chunk-2ra5skyk.js.map → chunk-p27y4xrw.js.map} +1 -1
- package/dist/{chunk-sgwgj2q0.js → chunk-pq657qcp.js} +1 -1
- package/dist/{chunk-63q7ycwt.js → chunk-pwbm3x1y.js} +2 -2
- package/dist/{chunk-63q7ycwt.js.map → chunk-pwbm3x1y.js.map} +1 -1
- package/dist/{chunk-w4ma7978.js → chunk-q4qw629n.js} +2 -2
- package/dist/{chunk-w4ma7978.js.map → chunk-q4qw629n.js.map} +1 -1
- package/dist/{chunk-f2e7n064.js → chunk-q9na1syb.js} +2 -2
- package/dist/{chunk-f2e7n064.js.map → chunk-q9na1syb.js.map} +1 -1
- package/dist/{chunk-x0t3t7g3.js → chunk-rkbwb3v5.js} +2 -2
- package/dist/{chunk-x0t3t7g3.js.map → chunk-rkbwb3v5.js.map} +1 -1
- package/dist/{chunk-0t2ym9ap.js → chunk-rma7afjd.js} +3 -3
- package/dist/{chunk-0t2ym9ap.js.map → chunk-rma7afjd.js.map} +1 -1
- package/dist/{chunk-f5qdyw45.js → chunk-tr9ynv3w.js} +2 -2
- package/dist/{chunk-f5qdyw45.js.map → chunk-tr9ynv3w.js.map} +1 -1
- package/dist/{chunk-kzc6bn8n.js → chunk-twrf6d08.js} +2 -2
- package/dist/{chunk-kzc6bn8n.js.map → chunk-twrf6d08.js.map} +1 -1
- package/dist/{chunk-6jd0e1dz.js → chunk-v9z4x5j2.js} +2 -2
- package/dist/{chunk-6jd0e1dz.js.map → chunk-v9z4x5j2.js.map} +1 -1
- package/dist/{chunk-jmhrpfqn.js → chunk-vm5t0j24.js} +2 -2
- package/dist/{chunk-jmhrpfqn.js.map → chunk-vm5t0j24.js.map} +1 -1
- package/dist/{chunk-a37shxb1.js → chunk-xv58jnpb.js} +2 -2
- package/dist/{chunk-a37shxb1.js.map → chunk-xv58jnpb.js.map} +1 -1
- package/dist/{chunk-p57nt0pm.js → chunk-ydkv9e8w.js} +3 -3
- package/dist/{chunk-p57nt0pm.js.map → chunk-ydkv9e8w.js.map} +1 -1
- package/dist/{chunk-aw8gj99f.js → chunk-ymdpt00k.js} +2 -2
- package/dist/{chunk-aw8gj99f.js.map → chunk-ymdpt00k.js.map} +1 -1
- package/dist/{chunk-5g7m7g4a.js → chunk-z7tsh9qr.js} +3 -3
- package/dist/{chunk-5g7m7g4a.js.map → chunk-z7tsh9qr.js.map} +1 -1
- package/dist/config/index.js +1 -1
- package/dist/console/run.js +2 -2
- package/dist/console/run.js.map +1 -1
- package/dist/container/index.js +2 -2
- package/dist/container/index.js.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/index.js +2 -2
- package/dist/email/index.js.map +1 -1
- package/dist/facades/index.js +2 -2
- package/dist/facades/index.js.map +1 -1
- package/dist/foundation/index.js +2 -2
- package/dist/foundation/index.js.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/i18n/dictionaryRuntime.js +2 -2
- package/dist/i18n/dictionaryRuntime.js.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/kernel/index.js +2 -2
- package/dist/kernel/index.js.map +1 -1
- package/dist/orm/index.js +2 -2
- package/dist/orm/index.js.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/services/index.d.ts +2 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +9 -9
- package/dist/services/index.js.map +4 -3
- package/dist/services/mcp/http/McpHttpServer.d.ts +81 -1
- package/dist/services/mcp/http/McpHttpServer.d.ts.map +1 -1
- package/dist/services/mcp/http/oauth/prismaStore.d.ts +112 -0
- package/dist/services/mcp/http/oauth/prismaStore.d.ts.map +1 -0
- package/dist/services/queue/work.js +2 -2
- package/dist/services/queue/work.js.map +1 -1
- package/dist/stats/route-table.js +1 -1
- package/dist/support/index.js +2 -2
- package/dist/support/index.js.map +1 -1
- package/dist/vitest/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-b6mgrrk6.js +0 -5
- /package/dist/{chunk-fsem81ec.js.map → chunk-29jmaj16.js.map} +0 -0
- /package/dist/{chunk-236be97q.js.map → chunk-63xwah5k.js.map} +0 -0
- /package/dist/{chunk-b4jx4fzq.js.map → chunk-65wy1r1a.js.map} +0 -0
- /package/dist/{chunk-1x9ghjpt.js.map → chunk-bsa6b82q.js.map} +0 -0
- /package/dist/{chunk-5xfpqda5.js.map → chunk-mv1rs9he.js.map} +0 -0
- /package/dist/{chunk-sgwgj2q0.js.map → chunk-pq657qcp.js.map} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type NonceStore } from "../../../ai/store/Nonces";
|
|
2
2
|
import type { FeatureKey } from "../../../client/rpc";
|
|
3
|
-
import {
|
|
3
|
+
import { HttpRequest } from "../../../http/HttpRequest";
|
|
4
|
+
import { type McpRegistry, type McpRemotePrincipal } from "../McpRegistry";
|
|
4
5
|
import { type McpCallerResolver } from "./callers";
|
|
5
6
|
/**
|
|
6
7
|
* `route.mcp.remote`: the MCP endpoint remote clients connect to (#762).
|
|
@@ -90,6 +91,81 @@ export type McpRemoteHttpConfig = {
|
|
|
90
91
|
nonces?: NonceStore;
|
|
91
92
|
/** How long a legacy client waits to answer an approval prompt, in ms. Default 10 minutes. */
|
|
92
93
|
approvalTimeoutMs?: number;
|
|
94
|
+
/**
|
|
95
|
+
* Called once after every remote `tools/call` has been answered: one that
|
|
96
|
+
* ran, one that failed, and one that was refused (a tool the credential
|
|
97
|
+
* cannot see, an approval that was declined, replayed or could not be
|
|
98
|
+
* asked, a route that answered 401 or 403). For an audit log.
|
|
99
|
+
*
|
|
100
|
+
* Awaited before the answer is sent, so a row written here is there when
|
|
101
|
+
* the client sees the result. It never changes the answer: a hook that
|
|
102
|
+
* throws is logged and the call is answered as it would have been.
|
|
103
|
+
*
|
|
104
|
+
* A modern client's first call to a `requiresApproval` tool, answered
|
|
105
|
+
* `input_required`, is not reported: the retry that carries the user's
|
|
106
|
+
* answer is the call, and it is reported once.
|
|
107
|
+
*
|
|
108
|
+
* `arguments` are the client's, as sent, file data included. Keep only what
|
|
109
|
+
* you need (often the keys, or nothing for a tool whose input is private).
|
|
110
|
+
*/
|
|
111
|
+
onCall?: (event: McpCallEvent) => void | Promise<void>;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* How a remote tool call ended, for `route.mcp.remote.onCall`.
|
|
115
|
+
*
|
|
116
|
+
* - `ok`: the tool ran and answered.
|
|
117
|
+
* - `error`: the tool's answer is an error: invalid arguments, a
|
|
118
|
+
* `McpToolError`, a route that answered 4xx (other than 401 and 403) or
|
|
119
|
+
* 5xx, a timeout, or an unexpected failure.
|
|
120
|
+
* - `denied`: the caller was refused: `reason` says why.
|
|
121
|
+
*/
|
|
122
|
+
export type McpCallOutcome = "ok" | "error" | "denied";
|
|
123
|
+
/**
|
|
124
|
+
* Why a call was `denied`:
|
|
125
|
+
*
|
|
126
|
+
* - `unknown-tool`: no tool by that name is available to this credential (out
|
|
127
|
+
* of its scopes, behind a feature that is off, or not there at all).
|
|
128
|
+
* - `approval-declined`: the user declined, cancelled or did not answer.
|
|
129
|
+
* - `approval-unavailable`: the client cannot ask for an approval.
|
|
130
|
+
* - `approval-invalid`: the approval sent back was not valid for this call
|
|
131
|
+
* (forged, expired, another call's or another credential's).
|
|
132
|
+
* - `approval-replayed`: the approval was already used, or its single use
|
|
133
|
+
* could not be recorded.
|
|
134
|
+
* - `approval-required`: the registry refused to run it unapproved.
|
|
135
|
+
* - `forbidden`: the route answered 401 or 403.
|
|
136
|
+
*/
|
|
137
|
+
export type McpCallDenial = "unknown-tool" | "approval-declined" | "approval-unavailable" | "approval-invalid" | "approval-replayed" | "approval-required" | "forbidden";
|
|
138
|
+
/** What `route.mcp.remote.onCall` is told about one remote tool call. */
|
|
139
|
+
export type McpCallEvent = {
|
|
140
|
+
/** The user the call ran (or would have run) as. */
|
|
141
|
+
user: McpRemotePrincipal["user"];
|
|
142
|
+
/** The resolver that vouched for the credential: `"oauth"`, `"api-key"`, or an app's own. */
|
|
143
|
+
via: string;
|
|
144
|
+
/** The credential's stable id: the OAuth grant (its family) or the API key's id. Never the secret. */
|
|
145
|
+
credentialId: string;
|
|
146
|
+
/** The OAuth client the token was issued to, or `null` (an API key). */
|
|
147
|
+
clientId: string | null;
|
|
148
|
+
/** The scopes the credential carries. */
|
|
149
|
+
scopes: readonly string[];
|
|
150
|
+
/** The tool's name, as the client called it. */
|
|
151
|
+
tool: string;
|
|
152
|
+
/** The arguments, as the client sent them. */
|
|
153
|
+
arguments: unknown;
|
|
154
|
+
outcome: McpCallOutcome;
|
|
155
|
+
/** For `denied`, why. */
|
|
156
|
+
reason?: McpCallDenial;
|
|
157
|
+
/** For `error` and `denied`: what the client was told. */
|
|
158
|
+
message?: string;
|
|
159
|
+
/** The HTTP status the tool's route answered, when it answered an error. */
|
|
160
|
+
status?: number;
|
|
161
|
+
/** For an unexpected failure: what was thrown. It was logged, and the client was told only that the tool failed. */
|
|
162
|
+
error?: unknown;
|
|
163
|
+
/** Whether the user approved this call (a `requiresApproval` tool). */
|
|
164
|
+
approved: boolean;
|
|
165
|
+
/** How long the call took to answer, in ms: for a legacy client, including the wait for its user's approval. */
|
|
166
|
+
durationMs: number;
|
|
167
|
+
/** The MCP endpoint's request: its headers and `clientIp(req)`. */
|
|
168
|
+
req: HttpRequest<any, any>;
|
|
93
169
|
};
|
|
94
170
|
/**
|
|
95
171
|
* The MCP endpoint: Streamable HTTP, for remote MCP clients (#762).
|
|
@@ -117,6 +193,7 @@ export declare class McpHttpServer {
|
|
|
117
193
|
private readonly instructions?;
|
|
118
194
|
private readonly nonces;
|
|
119
195
|
private readonly approvalTimeoutMs;
|
|
196
|
+
private readonly onCall?;
|
|
120
197
|
/** `feature`: the flag the endpoint is served behind, if any (#885). */
|
|
121
198
|
private readonly feature?;
|
|
122
199
|
private readonly featureOn;
|
|
@@ -157,6 +234,9 @@ export declare class McpHttpServer {
|
|
|
157
234
|
private session;
|
|
158
235
|
private checkModernHeaders;
|
|
159
236
|
private callTool;
|
|
237
|
+
/** Tells `onCall` how a call ended. Its failure is logged, never answered. */
|
|
238
|
+
private report;
|
|
239
|
+
private runTool;
|
|
160
240
|
private toolResult;
|
|
161
241
|
/**
|
|
162
242
|
* Asks the user whether a `requiresApproval` tool may run, and answers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpHttpServer.d.ts","sourceRoot":"","sources":["../../../../services/mcp/http/McpHttpServer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"McpHttpServer.d.ts","sourceRoot":"","sources":["../../../../services/mcp/http/McpHttpServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { PrismaNonceStore, type NonceModel } from "../../../../ai/store/Nonces";
|
|
2
|
+
import type { McpOAuthClient, McpOAuthCode, McpOAuthStore, McpOAuthToken } from "./store";
|
|
3
|
+
/**
|
|
4
|
+
* The slice of a model `PrismaMcpOAuthStore` uses: a Prisma client's delegate
|
|
5
|
+
* (`prisma.mcpOAuthCredential`) or a gemi ORM model class
|
|
6
|
+
* (`McpOAuthCredential`). Both answer these with Prisma's arguments.
|
|
7
|
+
*/
|
|
8
|
+
export interface McpOAuthModel {
|
|
9
|
+
create(args: any): PromiseLike<unknown>;
|
|
10
|
+
findUnique(args: any): PromiseLike<any>;
|
|
11
|
+
findFirst(args: any): PromiseLike<any>;
|
|
12
|
+
findMany(args: any): PromiseLike<any[]>;
|
|
13
|
+
count(args: any): PromiseLike<number>;
|
|
14
|
+
updateMany(args: any): PromiseLike<{
|
|
15
|
+
count: number;
|
|
16
|
+
}>;
|
|
17
|
+
deleteMany(args: any): PromiseLike<{
|
|
18
|
+
count: number;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
export type PrismaMcpOAuthStoreModels = {
|
|
22
|
+
/** `McpOAuthClient`: the clients that registered. */
|
|
23
|
+
clients: Pick<McpOAuthModel, "create" | "findUnique" | "findMany">;
|
|
24
|
+
/** `McpOAuthCredential`: codes, access and refresh tokens, by their SHA-256. */
|
|
25
|
+
credentials: McpOAuthModel;
|
|
26
|
+
/** `McpOAuthUse`: single-use keys spent (codes, refresh tokens, consent decisions). */
|
|
27
|
+
uses: NonceModel;
|
|
28
|
+
};
|
|
29
|
+
/** A grant to one connected app, as a "Connected apps" screen lists it. */
|
|
30
|
+
export type McpOAuthConnectedApp = {
|
|
31
|
+
/** The grant: what `disconnect` revokes, and `req.mcpGrant().id` on its calls. */
|
|
32
|
+
familyId: string;
|
|
33
|
+
clientId: string;
|
|
34
|
+
/** What the client called itself when it registered: unverified. */
|
|
35
|
+
clientName: string | null;
|
|
36
|
+
clientUri: string | null;
|
|
37
|
+
scopes: string[];
|
|
38
|
+
/** When the grant's oldest live refresh token was issued. */
|
|
39
|
+
connectedAt: Date;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* `McpOAuthStore` on three tables of the app's database, shared by every
|
|
43
|
+
* instance. Pass the models: gemi ORM model classes, or a Prisma client's
|
|
44
|
+
* delegates.
|
|
45
|
+
*
|
|
46
|
+
* ```ts
|
|
47
|
+
* new PrismaMcpOAuthStore({ clients: McpOAuthClient, credentials: McpOAuthCredential, uses: McpOAuthUse });
|
|
48
|
+
* new PrismaMcpOAuthStore({ clients: prisma.mcpOAuthClient, credentials: prisma.mcpOAuthCredential, uses: prisma.mcpOAuthUse });
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* The models are in `docs/mcp.md` ("The store"). Every code and token is a
|
|
52
|
+
* row of `McpOAuthCredential`, kept as its SHA-256. A family (one user's
|
|
53
|
+
* grant to one client) is revoked by stamping `revokedAt` on its rows, and a
|
|
54
|
+
* family with any revoked row is revoked: so a token saved after the
|
|
55
|
+
* revocation (a refresh racing it) is refused too, and `prune` keeps a
|
|
56
|
+
* revoked family's rows while any of its rows could still be used.
|
|
57
|
+
*
|
|
58
|
+
* Besides the store, it answers what an app's settings need: the user's
|
|
59
|
+
* `connectedApps`, `disconnect` one, `revokeUser` (all of a user's grants,
|
|
60
|
+
* when their role changes), `prune` (from a scheduled job), and `nonces()`,
|
|
61
|
+
* a `NonceStore` for `route.mcp.remote.nonces` on the same `McpOAuthUse`
|
|
62
|
+
* table.
|
|
63
|
+
*/
|
|
64
|
+
export declare class PrismaMcpOAuthStore implements McpOAuthStore {
|
|
65
|
+
private readonly clients;
|
|
66
|
+
private readonly credentials;
|
|
67
|
+
private readonly uses;
|
|
68
|
+
private readonly usesModel;
|
|
69
|
+
constructor(models: PrismaMcpOAuthStoreModels);
|
|
70
|
+
createClient(client: McpOAuthClient): Promise<void>;
|
|
71
|
+
findClient(clientId: string): Promise<McpOAuthClient | null>;
|
|
72
|
+
saveCode(code: McpOAuthCode): Promise<void>;
|
|
73
|
+
findCode(hash: string): Promise<McpOAuthCode | null>;
|
|
74
|
+
saveToken(token: McpOAuthToken): Promise<void>;
|
|
75
|
+
findToken(hash: string): Promise<McpOAuthToken | null>;
|
|
76
|
+
use(hash: string, expiresAt: number): Promise<boolean>;
|
|
77
|
+
revokeFamily(familyId: string): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* A `NonceStore` on the same `McpOAuthUse` table, for
|
|
80
|
+
* `route.mcp.remote.nonces`: approvals spent once across every instance.
|
|
81
|
+
* Its keys carry `prefix` (default `"nonce:"`), so they never collide with
|
|
82
|
+
* the hashes the OAuth server spends there.
|
|
83
|
+
*/
|
|
84
|
+
nonces(options?: {
|
|
85
|
+
prefix?: string;
|
|
86
|
+
}): PrismaNonceStore;
|
|
87
|
+
/**
|
|
88
|
+
* The user's grants that can still be used, newest first: one per family
|
|
89
|
+
* with a refresh token that has neither expired nor been revoked.
|
|
90
|
+
*/
|
|
91
|
+
connectedApps(userId: string | number, now?: Date): Promise<McpOAuthConnectedApp[]>;
|
|
92
|
+
/** Revokes one of the user's grants. `false` when the grant is not theirs. */
|
|
93
|
+
disconnect(userId: string | number, familyId: string): Promise<boolean>;
|
|
94
|
+
/**
|
|
95
|
+
* Revokes every grant the user has, for every client: when they are
|
|
96
|
+
* deleted, signed out everywhere, or lose the role the tools need. Their
|
|
97
|
+
* clients have to connect again.
|
|
98
|
+
*/
|
|
99
|
+
revokeUser(userId: string | number): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Deletes what can no longer be used: codes and tokens a day past their
|
|
102
|
+
* expiry, and spent keys past theirs. A revoked family's revoked rows are
|
|
103
|
+
* what keeps it revoked, so they stay while any row of that family has not
|
|
104
|
+
* expired: a token a refresh saved as the grant was revoked would otherwise
|
|
105
|
+
* come back to life once the older revoked rows were gone.
|
|
106
|
+
*/
|
|
107
|
+
prune(now?: number): Promise<void>;
|
|
108
|
+
/** A code or token, unless its family has a revoked row. */
|
|
109
|
+
private findLive;
|
|
110
|
+
private revokedFamilies;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=prismaStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prismaStore.d.ts","sourceRoot":"","sources":["../../../../../services/mcp/http/oauth/prismaStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{Td as H,Wd as _}from"../../chunk-877yc341.js";import{Pj as O}from"../../chunk-313593t3.js";import"../../chunk-86zhngpg.js";import"../../chunk-attr793y.js";import"../../chunk-2ery6a75.js";import"../../chunk-73rzf7ys.js";import"../../chunk-1fyn63ka.js";import"../../chunk-e9z8p2fy.js";import{gl as U,hl as V,ll as Z}from"../../chunk-mzkzgp2j.js";import{pl as Y}from"../../chunk-apga49vp.js";import"../../chunk-jzpbwvbt.js";import X from"path";function T(z){if(!z.config.get("route.channels"))return null;let C=z.config.get("broadcast",{}).driver;if(!(C===void 0||C==="memory"||C instanceof O))return null;return'[gemi] Broadcasts from this worker reach no one: the broadcast driver is "memory", which delivers to the sockets of the process that emits, and a worker has none. Set `driver: "redis"` in app/config/broadcast.ts.'}class J extends Error{name="QueueWorkerRefused"}class N{kernel;stopping;keepAlive;settings;constructor(z,C={}){this.kernel=z;this.settings={...V(),...C}}async start(){if(await this.kernel.waitForBoot(),this.stopping)return;let z=this.kernel.app;if(!z.bound(H))throw new J("[gemi] `gemi queue:work` has no queue to claim from: this application does not register QueueServiceProvider.");let C=z.make(H);if(!C.durable)throw new J('[gemi] `gemi queue:work` refuses to start: the queue uses the memory driver, which keeps each job in the process that dispatched it, so a worker never sees one. Set `driver: "database"` (or another driver every process can reach) in app/config/queue.ts, or run jobs in the server and drop the worker.');C.start(),this.keepAlive=setInterval(()=>{},1073741824),console.log(`[gemi] Queue worker started: claiming up to ${C.config.concurrency} job(s) at a time.`);let E=T(z);if(E)console.warn(E)}stop(z={}){return this.stopping??=this.drain({...this.settings,...z}),this.stopping}async drain(z){U();let C=this.kernel.app,E=C.resolved(H)?C.make(H):void 0;if(E)console.log(`[gemi] Shutting down: waiting for ${E.running} running job(s) (up to ${z.timeoutMs/1000}s).`),await E.drain(z.timeoutMs);let F=await this.kernel.shutdown({timeoutMs:z.providerTimeoutMs});clearInterval(this.keepAlive);let G=(E?.running??0)===0&&F.failed.length===0&&F.timedOut.length===0;return console.log(`[gemi] Shutdown ${G?"complete":"finished with errors"}.`),G?0:1}}async function $(){let z=Y();process.env.ROOT_DIR=z,process.env.APP_DIR=X.join(z,"app"),_();let C=X.join(z,"app/kernel/Kernel.ts"),{default:E}=await import(C);if(typeof E!=="function")return console.error(`[gemi] ${C} has no default export to boot the worker from.`),1;let F=new E;F.boot();let G=new N(F);Z(()=>G.stop());try{await G.start()}catch(L){if(!(L instanceof J))throw L;return console.error(L.message),1}return}$().then((z)=>{if(z!==void 0)process.exit(z)},(z)=>{console.error("[gemi] The queue worker failed to start:",z),process.exit(1)});
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=32579ACF9B7FA66364756E2164756E21
|
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
"import type { Application, ShutdownReport } from \"../../foundation/Application\";\nimport { markShuttingDown, shutdownSettings, type ShutdownSettings } from \"../../server/shutdown\";\nimport { memoryBroadcastInWorker } from \"../broadcast/workerWarning\";\nimport { QueueManager } from \"./QueueManager\";\n\n/** The part of a `Kernel` a worker drives. */\nexport type WorkerKernel = {\n readonly app: Application;\n waitForBoot(): Promise<void>;\n shutdown(options?: { timeoutMs?: number }): Promise<ShutdownReport>;\n};\n\n/**\n * A worker that was told to start in an application it cannot claim for. The\n * message is written for the operator reading the deploy's logs.\n */\nexport class QueueWorkerRefused extends Error {\n name = \"QueueWorkerRefused\";\n}\n\n/**\n * The process `gemi queue:work` runs: the application booted as a server boots\n * it, claiming from the queue, and no `Bun.serve`. It exists so job capacity\n * can be scaled apart from request traffic, which needs a driver both kinds of\n * process can reach; see `start` for why the memory driver is refused.\n *\n * The caller marks the process as a worker (`markQueueWorker`) before the\n * kernel registers, so every claim rule that asks `claimsInThisProcess` sees a\n * process that claims, whatever `GEMI_QUEUE_CLAIM` says.\n */\nexport class QueueWorker {\n private stopping: Promise<number> | undefined;\n private keepAlive: ReturnType<typeof setInterval> | undefined;\n private readonly settings: ShutdownSettings;\n\n /**\n * `settings` default to the `GEMI_SHUTDOWN_*` variables, read here rather\n * than at the signal so a bad value is warned about while the deploy is\n * being watched, as `Server.start` does.\n */\n constructor(\n private readonly kernel: WorkerKernel,\n settings: Partial<ShutdownSettings> = {},\n ) {\n this.settings = { ...shutdownSettings(), ...settings };\n }\n\n /**\n * Boots the application and starts claiming. Rejects with\n * `QueueWorkerRefused` when the application has no queue, or its queue uses\n * the memory driver.\n *\n * Refused rather than warned about, because a memory worker can never do\n * anything: its jobs live in a `Map` in the process that dispatched them,\n * so a worker's is always empty. Left running, it looks like a healthy\n * deploy — a process up, no errors — that runs nothing, and scaling it out\n * adds no capacity. An exit the platform reports as a crash loop is a form\n * of the mistake someone will see.\n */\n async start(): Promise<void> {\n await this.kernel.waitForBoot();\n // A signal during the boot has already drained and cleared the handle\n // below. Going on would start the loop again and arm a handle nothing\n // clears, holding open a worker that has finished shutting down.\n if (this.stopping) return;\n\n const application = this.kernel.app;\n // `bound`, not `make` in a try: an application built without the queue\n // provider is a configuration to name, not an unbound-token stack trace.\n if (!application.bound(QueueManager)) {\n throw new QueueWorkerRefused(\n \"[gemi] `gemi queue:work` has no queue to claim from: this application \" +\n \"does not register QueueServiceProvider.\",\n );\n }\n const queue = application.make(QueueManager);\n if (!queue.durable) {\n throw new QueueWorkerRefused(\n \"[gemi] `gemi queue:work` refuses to start: the queue uses the memory \" +\n \"driver, which keeps each job in the process that dispatched it, so \" +\n 'a worker never sees one. Set `driver: \"database\"` (or another driver ' +\n \"every process can reach) in app/config/queue.ts, or run jobs in the \" +\n \"server and drop the worker.\",\n );\n }\n\n // Idempotent: a production boot with a durable driver has already started\n // it (`startClaimingIfServing`). Development has not, and a worker claims\n // in either.\n queue.start();\n // The queue's poll timer is unref'd, so that a script's queue does not\n // hold it open; here the queue is the process, and without a handle of its\n // own an idle worker would exit 0 as soon as it booted.\n this.keepAlive = setInterval(() => {}, 1 << 30);\n console.log(\n `[gemi] Queue worker started: claiming up to ${queue.config.concurrency} job(s) at a time.`,\n );\n const broadcastWarning = memoryBroadcastInWorker(application);\n if (broadcastWarning) console.warn(broadcastWarning);\n }\n\n /**\n * Stops claiming, waits for the running jobs, runs every provider's\n * `shutdown()`, and resolves with the exit code: 0 when no job was left\n * running and every provider finished in time, 1 otherwise. Idempotent.\n *\n * `gemi start`'s drain, with the jobs where the requests were:\n * `isShuttingDown()` turns true, which stops a durable queue claiming;\n * running jobs get `timeoutMs` (`GEMI_SHUTDOWN_TIMEOUT`), which a server\n * spends on requests; then `Application.shutdown` gets `providerTimeoutMs`,\n * and in it the queue provider waits for whatever is still running and\n * names it. The two budgets add up as they do for a server, so a worker\n * fits the same grace period. `delayMs` is not waited: it is for a load\n * balancer, and nothing routes to a worker.\n */\n stop(settings: Partial<ShutdownSettings> = {}): Promise<number> {\n this.stopping ??= this.drain({ ...this.settings, ...settings });\n return this.stopping;\n }\n\n private async drain(settings: ShutdownSettings): Promise<number> {\n markShuttingDown();\n const application = this.kernel.app;\n // Resolving the manager now would build a driver only to stop it, which\n // is what a signal during the boot, before the provider resolved it, finds.\n const queue = application.resolved(QueueManager) ? application.make(QueueManager) : undefined;\n if (queue) {\n console.log(\n `[gemi] Shutting down: waiting for ${queue.running} running job(s) ` +\n `(up to ${settings.timeoutMs / 1000}s).`,\n );\n await queue.drain(settings.timeoutMs);\n }\n\n const report = await this.kernel.shutdown({ timeoutMs: settings.providerTimeoutMs });\n clearInterval(this.keepAlive);\n const clean =\n (queue?.running ?? 0) === 0 && report.failed.length === 0 && report.timedOut.length === 0;\n console.log(`[gemi] Shutdown ${clean ? \"complete\" : \"finished with errors\"}.`);\n return clean ? 0 : 1;\n }\n}\n"
|
|
8
8
|
],
|
|
9
9
|
"mappings": ";gcAYA,kBCDO,OAAS,DAAuB,DAAC,AAAyC,DAC/E,CAAI,DAAC,AAAY,KAAO,IAAI,gBAAgB,EAAG,OAAO,KACtD,IAAM,EAAS,EAAY,OAAO,IAAqB,YAAa,CAAC,CAAC,EAAE,OAGxE,GAAI,EADF,IAAW,QAAa,IAAW,UAAY,aAAkB,GACtD,OAAO,KACpB,MACE,uNCFG,MAAM,UAA2B,KAAM,CAC5C,KAAO,oBACT,CAYO,MAAM,CAAY,CAWJ,OAVX,SACA,UACS,SAOjB,WAAW,CACQ,EACjB,EAAsC,CAAC,EACvC,CAFiB,cAGjB,KAAK,SAAW,IAAK,EAAiB,KAAM,CAAS,OAejD,MAAK,EAAkB,CAK3B,GAJA,MAAM,KAAK,OAAO,YAAY,EAI1B,KAAK,SAAU,OAEnB,IAAM,EAAc,KAAK,OAAO,IAGhC,GAAI,CAAC,EAAY,MAAM,CAAY,EACjC,MAAM,IAAI,EACR,+GAEF,EAEF,IAAM,EAAQ,EAAY,KAAK,CAAY,EAC3C,GAAI,CAAC,EAAM,QACT,MAAM,IAAI,EACR,8SAKF,EAMF,EAAM,MAAM,EAIZ,KAAK,UAAY,YAAY,IAAM,GAAI,UAAO,EAC9C,QAAQ,IACN,+CAA+C,EAAM,OAAO,+BAC9D,EACA,IAAM,EAAmB,EAAwB,CAAW,EAC5D,GAAI,EAAkB,QAAQ,KAAK,CAAgB,EAiBrD,IAAI,CAAC,EAAsC,CAAC,EAAoB,CAE9D,OADA,KAAK,WAAa,KAAK,MAAM,IAAK,KAAK,YAAa,CAAS,CAAC,EACvD,KAAK,cAGA,MAAK,CAAC,EAA6C,CAC/D,EAAiB,EACjB,IAAM,EAAc,KAAK,OAAO,IAG1B,EAAQ,EAAY,SAAS,CAAY,EAAI,EAAY,KAAK,CAAY,EAAI,OACpF,GAAI,EACF,QAAQ,IACN,qCAAqC,EAAM,iCAC/B,EAAS,UAAY,SACnC,EACA,MAAM,EAAM,MAAM,EAAS,SAAS,EAGtC,IAAM,EAAS,MAAM,KAAK,OAAO,SAAS,CAAE,UAAW,EAAS,iBAAkB,CAAC,EACnF,cAAc,KAAK,SAAS,EAC5B,IAAM,GACH,GAAO,SAAW,KAAO,GAAK,EAAO,OAAO,SAAW,GAAK,EAAO,SAAS,SAAW,EAE1F,OADA,QAAQ,IAAI,mBAAmB,EAAQ,WAAa,yBAAyB,EACtE,EAAQ,EAAI,EAEvB,CF1HA,eAAe,CAAI,EAAgC,CACjD,IAAM,EAAU,EAAY,EAI5B,QAAQ,IAAI,SAAW,EACvB,QAAQ,IAAI,QAAU,EAAK,KAAK,EAAS,KAAK,EAE9C,EAAgB,EAEhB,IAAM,EAAa,EAAK,KAAK,EAAS,sBAAsB,GACpD,QAAS,GAAY,MAAa,UAG1C,GAAI,OAAO,IAAW,WAEpB,OADA,QAAQ,MAAM,UAAU,kDAA2D,EAC5E,EAET,IAAM,EAAS,IAAI,EACnB,EAAO,KAAK,EAEZ,IAAM,EAAS,IAAI,EAAY,CAAM,EAKrC,EAAuB,IAAM,EAAO,KAAK,CAAC,EAE1C,GAAI,CACF,MAAM,EAAO,MAAM,EACnB,MAAO,EAAO,CACd,GAAI,EAAE,aAAiB,GAAqB,MAAM,EAElD,OADA,QAAQ,MAAM,EAAM,OAAO,EACpB,EAGT,OAGF,EAAK,EAAE,KACL,CAAC,IAAS,CACR,GAAI,IAAS,OAAW,QAAQ,KAAK,CAAI,GAE3C,CAAC,IAAU,CACT,QAAQ,MAAM,2CAA4C,CAAK,EAC/D,QAAQ,KAAK,CAAC,EAElB",
|
|
10
|
-
"debugId": "
|
|
10
|
+
"debugId": "32579ACF9B7FA66364756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import"../chunk-
|
|
2
|
+
import"../chunk-jzpbwvbt.js";import M from"path";import{writeFileSync as Q}from"fs";var L=new Set(["FILE","REDIRECT"]);function H(j){return j.run(()=>{let x=[];for(let{group:z,view:D}of j.domains().viewGroups())for(let[G,B]of Object.entries(D.flatViewRoutes)){let C=D.routeManifest[G]??B.segments.map((K)=>K.viewPath);if(C.length===0||L.has(C.at(-1)))continue;x.push({path:G,group:z,views:C,...B.static?{static:{...B.static.layout?{layout:B.static.layout}:{},...B.static.navigation?{navigation:!0}:{}}}:{}})}return x})}var J=process.argv[2];async function U(){if(!J)throw Error("usage: route-table <out.json>");let j=M.resolve(process.cwd(),"app/kernel/Kernel.ts"),x=await import(j);if(typeof x.default!=="function")throw Error(`${j} has no default export (the Kernel subclass).`);let z=new x.default;z.boot();try{Q(J,JSON.stringify(H(z)))}finally{z.destroy()}}U().then(()=>process.exit(0),(j)=>{console.error(j?.stack??String(j)),process.exit(1)});
|
|
3
3
|
|
|
4
4
|
//# debugId=05EB0087C5A2060D64756E2164756E21
|
package/dist/support/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{$d as Y}from"../chunk-eqv7yxk7.js";import{Uj as M}from"../chunk-attr793y.js";import{Wk as P,Yk as R}from"../chunk-1fyn63ka.js";import"../chunk-e9z8p2fy.js";import{ml as Q,nl as U,ol as V,pl as W}from"../chunk-apga49vp.js";import"../chunk-jzpbwvbt.js";class S{static token;async boot(){}static inject(){if(!this.token)throw Error(`Service [${this.name}] does not declare a \`static token\`, so the container has no key to resolve it by.`);try{return R(this)}catch(x){throw Error(`Could not inject [${this.name}]. Services are constructed when the kernel boots, so `+"inject() only works from code that runs after that \u2014 a constructor default or a method "+`body, never module top level. Check that [${this.name}] is listed in \`services\` on your Kernel.`,{cause:x})}}static with(x){let f=new this;for(let[C,g]of Object.entries(x))if(g!==void 0)f[C]=g;return f}}import{readdir as z}from"fs/promises";import{join as B,parse as j}from"path";var H=[".ts",".tsx",".js",".mjs",".jsx"];function J(x={}){let f={};for(let[C,g]of Object.entries(x))f[C]=q(g);return new P(f)}async function L(x,f=new P){let C=[];try{C=await z(x)}catch(D){return f}let g=C.filter((D)=>{let{ext:v,name:F}=j(D);return H.includes(v)&&!F.startsWith(".")}).sort();for(let D of g){let{name:v}=j(D),F=await import(B(x,D));f.set(v,q(F))}return f}function q(x){if(x&&typeof x==="object"&&"default"in x)return x.default;return x}export{M as withDefaults,Q as sourceFiles,W as projectRoot,L as loadConfigFrom,V as discoverClasses,J as createConfigRepository,Y as ServiceProvider,S as Service,P as Repository,U as DiscoveryError};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=5B94BBEED2562D0364756E2164756E21
|
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
"import { readdir } from \"node:fs/promises\";\nimport { join, parse } from \"node:path\";\n\nimport { Repository } from \"./Repository\";\n\nconst CONFIG_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".mjs\", \".jsx\"];\n\n// Builds a Repository from an already-imported map of config modules. The map\n// key becomes the top-level config key, so `{ mail: mailModule }` is readable\n// as `config.get(\"mail.driver\")`. Each entry may be either the module namespace\n// (its `default` export is unwrapped) or the config object itself.\nexport function createConfigRepository(\n modules: Record<string, any> = {},\n): Repository {\n const items: Record<string, any> = {};\n\n for (const [key, mod] of Object.entries(modules)) {\n items[key] = unwrap(mod);\n }\n\n return new Repository(items);\n}\n\n// Reads every config module in an app's `app/config` directory into a\n// Repository. The file's basename is the top-level key: `app/config/mail.ts`\n// populates `mail.*`. A missing directory yields an empty Repository so apps\n// that declare no config still boot.\nexport async function loadConfigFrom(\n directory: string,\n repository = new Repository(),\n): Promise<Repository> {\n let entries: string[] = [];\n\n try {\n entries = await readdir(directory);\n } catch (err) {\n return repository;\n }\n\n const files = entries\n .filter((entry) => {\n const { ext, name } = parse(entry);\n return CONFIG_EXTENSIONS.includes(ext) && !name.startsWith(\".\");\n })\n .sort();\n\n for (const file of files) {\n const { name } = parse(file);\n const mod = await import(join(directory, file));\n repository.set(name, unwrap(mod));\n }\n\n return repository;\n}\n\nfunction unwrap(mod: any) {\n if (mod && typeof mod === \"object\" && \"default\" in mod) {\n return mod.default;\n }\n return mod;\n}\n"
|
|
7
7
|
],
|
|
8
8
|
"mappings": ";2RAgCO,CAAe,JAAQ,EAOrB,OAMD,AAAI,EAAkB,QAmBrB,OAAS,EAKX,CACH,GAAI,CAAC,KAAK,MACR,MAAU,MACR,YAAY,KAAK,0FACnB,EAGF,GAAI,CACF,OAAO,EAAI,IAAuB,EAClC,MAAO,EAAO,CACd,MAAU,MACR,qBAAqB,KAAK,6DACxB,+FACA,6CAA6C,KAAK,kDAEpD,CAAE,OAAM,CACV,SAoBG,KAAuB,CAAoB,EAA0B,CAC1E,IAAM,EAAW,IAAI,KACrB,QAAY,EAAK,KAAU,OAAO,QAAQ,CAAS,EACjD,GAAI,IAAU,OAAW,EAAS,GAAO,EAE3C,OAAO,EAEX,CChHA,kBAAS,oBACT,eAAS,WAAM,aAIf,IAAM,EAAoB,CAAC,MAAO,OAAQ,MAAO,OAAQ,MAAM,EAMxD,SAAS,CAAsB,CACpC,EAA+B,CAAC,EACpB,CACZ,IAAM,EAA6B,CAAC,EAEpC,QAAY,EAAK,KAAQ,OAAO,QAAQ,CAAO,EAC7C,EAAM,GAAO,EAAO,CAAG,EAGzB,OAAO,IAAI,EAAW,CAAK,EAO7B,eAAsB,CAAc,CAClC,EACA,EAAa,IAAI,EACI,CACrB,IAAI,EAAoB,CAAC,EAEzB,GAAI,CACF,EAAU,MAAM,EAAQ,CAAS,EACjC,MAAO,EAAK,CACZ,OAAO,EAGT,IAAM,EAAQ,EACX,OAAO,CAAC,IAAU,CACjB,IAAQ,MAAK,QAAS,EAAM,CAAK,EACjC,OAAO,EAAkB,SAAS,CAAG,GAAK,CAAC,EAAK,WAAW,GAAG,EAC/D,EACA,KAAK,EAER,QAAW,KAAQ,EAAO,CACxB,IAAQ,QAAS,EAAM,CAAI,EACrB,EAAM,MAAa,SAAK,EAAW,CAAI,GAC7C,EAAW,IAAI,EAAM,EAAO,CAAG,CAAC,EAGlC,OAAO,EAGT,SAAS,CAAM,CAAC,EAAU,CACxB,GAAI,GAAO,OAAO,IAAQ,UAAY,YAAa,EACjD,OAAO,EAAI,QAEb,OAAO",
|
|
9
|
-
"debugId": "
|
|
9
|
+
"debugId": "5B94BBEED2562D0364756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/vitest/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{fa as B,ga as D}from"../chunk-
|
|
2
|
+
import{fa as B,ga as D}from"../chunk-2djjs8f1.js";import"../chunk-4jd25v6d.js";import"../chunk-2k3935ke.js";import{Aa as J}from"../chunk-twrf6d08.js";import"../chunk-g8sh9btf.js";import"../chunk-jzpbwvbt.js";function N(){return{name:"gemi-custom-request",enforce:"pre",async transform(G,H){let j=H.split("?",1)[0];if(j.includes("/node_modules/")||!B.test(j))return null;return{code:await D(G),map:null}}}}export{N as gemiRequestPlugin,J as gemiIslandPlugin};
|
|
3
3
|
|
|
4
4
|
//# debugId=C11E8611E15123D864756E2164756E21
|
package/package.json
CHANGED
package/dist/chunk-b6mgrrk6.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{Zd as o}from"./chunk-p57nt0pm.js";import{_d as i}from"./chunk-6hs102jh.js";import{Tj as t}from"./chunk-yjszzjyj.js";import{Tk as r}from"./chunk-m8yd59gg.js";class n extends i{register(){this.app.singleton(r,()=>new r(t(o(),this.app.config.get("translation",{}))))}}
|
|
3
|
-
export{n as ab};
|
|
4
|
-
|
|
5
|
-
//# debugId=71047EDC0E4974C064756E2164756E21
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|